diff options
author | Philipp Tölke <toelke@in.tum.de> | 2010-11-02 21:40:03 +0000 |
---|---|---|
committer | Philipp Tölke <toelke@in.tum.de> | 2010-11-02 21:40:03 +0000 |
commit | 55278d42655a4175ea222275966f7df10654908a (patch) | |
tree | 35d9b9e0e369076614053337f6827986b2c6f839 | |
parent | b6ce573cb682686d40f7996247bd6efbd1e8f1d4 (diff) | |
download | gnunet-55278d42655a4175ea222275966f7df10654908a.tar.gz gnunet-55278d42655a4175ea222275966f7df10654908a.zip |
comment and indent gnunet-service-dns
-rw-r--r-- | src/vpn/gnunet-service-dns.c | 666 |
1 files changed, 389 insertions, 277 deletions
diff --git a/src/vpn/gnunet-service-dns.c b/src/vpn/gnunet-service-dns.c index c3d136406..ee2549d17 100644 --- a/src/vpn/gnunet-service-dns.c +++ b/src/vpn/gnunet-service-dns.c | |||
@@ -39,142 +39,243 @@ | |||
39 | #include "gnunet_crypto_lib.h" | 39 | #include "gnunet_crypto_lib.h" |
40 | #include "gnunet_signatures.h" | 40 | #include "gnunet_signatures.h" |
41 | 41 | ||
42 | /** | ||
43 | * The scheduler to use throughout the service | ||
44 | */ | ||
42 | static struct GNUNET_SCHEDULER_Handle *sched; | 45 | static struct GNUNET_SCHEDULER_Handle *sched; |
43 | 46 | ||
47 | /** | ||
48 | * The UDP-Socket through which DNS-Resolves will be sent if they are not to be | ||
49 | * sent through gnunet. The port of this socket will not be hijacked. | ||
50 | */ | ||
44 | static struct GNUNET_NETWORK_Handle *dnsout; | 51 | static struct GNUNET_NETWORK_Handle *dnsout; |
45 | 52 | ||
46 | static struct GNUNET_DHT_Handle *dht; | 53 | /** |
47 | 54 | * The port bound to the socket dnsout | |
55 | */ | ||
48 | static unsigned short dnsoutport; | 56 | static unsigned short dnsoutport; |
49 | 57 | ||
58 | /** | ||
59 | * A handle to the DHT-Service | ||
60 | */ | ||
61 | static struct GNUNET_DHT_Handle *dht; | ||
62 | |||
63 | /** | ||
64 | * The configuration to use | ||
65 | */ | ||
50 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | 66 | static const struct GNUNET_CONFIGURATION_Handle *cfg; |
51 | 67 | ||
68 | /** | ||
69 | * A list of DNS-Responses that have to be sent to the requesting client | ||
70 | */ | ||
52 | static struct answer_packet_list *head; | 71 | static struct answer_packet_list *head; |
53 | static struct answer_packet_list *tail; | ||
54 | |||
55 | struct dns_query_id_state { | ||
56 | unsigned valid:1; | ||
57 | struct GNUNET_SERVER_Client* client; | ||
58 | unsigned local_ip:32; | ||
59 | unsigned remote_ip:32; | ||
60 | unsigned local_port:16; | ||
61 | char* name; | ||
62 | unsigned namelen:8; | ||
63 | }; | ||
64 | static struct dns_query_id_state query_states[65536]; /* This is < 1.5MiB */ | ||
65 | |||
66 | void hijack(unsigned short port) { | ||
67 | char port_s[6]; | ||
68 | |||
69 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Hijacking, port is %d\n", port); | ||
70 | snprintf(port_s, 6, "%d", port); | ||
71 | GNUNET_OS_start_process(NULL, NULL, "gnunet-helper-hijack-dns", "gnunet-hijack-dns", port_s, NULL); | ||
72 | } | ||
73 | |||
74 | void unhijack(unsigned short port) { | ||
75 | char port_s[6]; | ||
76 | 72 | ||
77 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "unHijacking, port is %d\n", port); | 73 | /** |
78 | snprintf(port_s, 6, "%d", port); | 74 | * The tail of the list of DNS-responses |
79 | GNUNET_OS_start_process(NULL, NULL, "gnunet-helper-hijack-dns", "gnunet-hijack-dns", "-d", port_s, NULL); | 75 | */ |
80 | } | 76 | static struct answer_packet_list *tail; |
81 | 77 | ||
82 | size_t send_answer(void* cls, size_t size, void* buf); | 78 | /** |
79 | * A structure containing a mapping from network-byte-ordered DNS-id to | ||
80 | * some information needed to handle this query | ||
81 | * | ||
82 | * It currently allocates at least | ||
83 | * (1 + machine-width + 32 + 32 + 16 + machine-width + 8) * 65536 bit | ||
84 | * = 1.7 MiB on 64 bit. | ||
85 | * = 1.2 MiB on 32 bit. | ||
86 | */ | ||
87 | static struct { | ||
88 | unsigned valid:1; | ||
89 | struct GNUNET_SERVER_Client* client; | ||
90 | unsigned local_ip:32; | ||
91 | unsigned remote_ip:32; | ||
92 | unsigned local_port:16; | ||
93 | char* name; | ||
94 | unsigned namelen:8; | ||
95 | } query_states[65536]; | ||
83 | 96 | ||
97 | /** | ||
98 | * A struct used to give more than one value as | ||
99 | * closure to receive_dht | ||
100 | */ | ||
84 | struct receive_dht_cls { | 101 | struct receive_dht_cls { |
85 | unsigned short id; | 102 | unsigned short id; |
86 | struct GNUNET_DHT_GetHandle* handle; | 103 | struct GNUNET_DHT_GetHandle* handle; |
87 | }; | 104 | }; |
88 | 105 | ||
89 | void receive_dht(void *cls, | 106 | /** |
90 | struct GNUNET_TIME_Absolute exp, | 107 | * Hijack all outgoing DNS-Traffic but for traffic leaving "our" port. |
91 | const GNUNET_HashCode *key, | 108 | */ |
92 | const struct GNUNET_PeerIdentity *const *get_path, | 109 | static void |
93 | const struct GNUNET_PeerIdentity *const *put_path, | 110 | hijack(unsigned short port) { |
94 | enum GNUNET_BLOCK_Type type, | 111 | char port_s[6]; |
95 | size_t size, | 112 | |
96 | const void *data) | 113 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Hijacking, port is %d\n", port); |
97 | { | 114 | snprintf(port_s, 6, "%d", port); |
98 | unsigned short id = ((struct receive_dht_cls*)cls)->id; | 115 | GNUNET_OS_start_process(NULL, |
99 | struct GNUNET_DHT_GetHandle* handle = ((struct receive_dht_cls*)cls)->handle; | 116 | NULL, |
100 | GNUNET_free(cls); | 117 | "gnunet-helper-hijack-dns", |
101 | 118 | "gnunet-hijack-dns", | |
102 | GNUNET_assert(type == GNUNET_BLOCK_TYPE_DNS); | 119 | port_s, |
103 | 120 | NULL); | |
104 | if (query_states[id].valid != GNUNET_YES) return; | 121 | } |
105 | query_states[id].valid = GNUNET_NO; | ||
106 | |||
107 | const struct GNUNET_DNS_Record* rec = data; | ||
108 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got block of size %d, peer: %08x, desc: %08x\n", size, *((unsigned int*)&rec->peer), *((unsigned int*)&rec->service_descriptor)); | ||
109 | |||
110 | size_t len = sizeof(struct answer_packet) - 1 \ | ||
111 | + sizeof(struct dns_static) \ | ||
112 | + query_states[id].namelen \ | ||
113 | + sizeof(struct dns_query_line) \ | ||
114 | + 2 /* To hold the pointer to the name */ \ | ||
115 | + sizeof(struct dns_record_line) - 1 \ | ||
116 | + 16; | ||
117 | ; | ||
118 | struct answer_packet_list* answer = GNUNET_malloc(len + 2*sizeof(struct answer_packet_list*)); | ||
119 | memset(answer, 0, len + 2*sizeof(struct answer_packet_list*)); | ||
120 | |||
121 | answer->pkt.hdr.type = htons(GNUNET_MESSAGE_TYPE_LOCAL_RESPONSE_DNS); | ||
122 | answer->pkt.hdr.size = htons(len); | ||
123 | answer->pkt.subtype = GNUNET_DNS_ANSWER_TYPE_SERVICE; | ||
124 | |||
125 | GNUNET_CRYPTO_hash(&rec->peer, sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &answer->pkt.peer); | ||
126 | memcpy(&answer->pkt.service_descriptor, &rec->service_descriptor, sizeof(GNUNET_HashCode)); | ||
127 | memcpy(&answer->pkt.service_type, &rec->service_type, sizeof(answer->pkt.service_type)); | ||
128 | memcpy(&answer->pkt.ports, &rec->ports, sizeof(answer->pkt.ports)); | ||
129 | |||
130 | answer->pkt.from = query_states[id].remote_ip; | ||
131 | |||
132 | answer->pkt.to = query_states[id].local_ip; | ||
133 | answer->pkt.dst_port = query_states[id].local_port; | ||
134 | |||
135 | struct dns_pkt *dpkt = (struct dns_pkt*)answer->pkt.data; | ||
136 | |||
137 | dpkt->s.id = id; | ||
138 | dpkt->s.aa = 1; | ||
139 | dpkt->s.qr = 1; | ||
140 | dpkt->s.ra = 1; | ||
141 | dpkt->s.qdcount = htons(1); | ||
142 | dpkt->s.ancount = htons(1); | ||
143 | 122 | ||
144 | memcpy(dpkt->data, query_states[id].name, query_states[id].namelen); | 123 | /** |
145 | GNUNET_free(query_states[id].name); | 124 | * Delete the hijacking-routes |
125 | */ | ||
126 | static void | ||
127 | unhijack(unsigned short port) { | ||
128 | char port_s[6]; | ||
129 | |||
130 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "unHijacking, port is %d\n", port); | ||
131 | snprintf(port_s, 6, "%d", port); | ||
132 | GNUNET_OS_start_process(NULL, | ||
133 | NULL, | ||
134 | "gnunet-helper-hijack-dns", | ||
135 | "gnunet-hijack-dns", | ||
136 | "-d", | ||
137 | port_s, | ||
138 | NULL); | ||
139 | } | ||
146 | 140 | ||
141 | /** | ||
142 | * Send the DNS-Response to the client. Gets called via the notify_transmit_ready- | ||
143 | * system. | ||
144 | */ | ||
145 | static size_t | ||
146 | send_answer(void* cls, size_t size, void* buf) { | ||
147 | struct answer_packet_list* query = head; | ||
148 | size_t len = ntohs(query->pkt.hdr.size); | ||
147 | 149 | ||
148 | struct dns_query_line* dque = (struct dns_query_line*)(dpkt->data+(query_states[id].namelen)); | 150 | GNUNET_assert(len <= size); |
149 | dque->type = htons(28); | ||
150 | dque->class = htons(1); | ||
151 | 151 | ||
152 | char* anname = (char*)(dpkt->data+(query_states[id].namelen)+sizeof(struct dns_query_line)); | 152 | memcpy(buf, &query->pkt.hdr, len); |
153 | memcpy(anname, (char[]){0xc0, 0x0c}, 2); | ||
154 | 153 | ||
155 | struct dns_record_line *drec_data = (struct dns_record_line*)(dpkt->data+(query_states[id].namelen)+sizeof(struct dns_query_line)+2); | 154 | GNUNET_CONTAINER_DLL_remove (head, tail, query); |
156 | drec_data->type = htons(28); /* AAAA */ | ||
157 | drec_data->class = htons(1); /* IN */ | ||
158 | drec_data->ttl = htonl(3600); /* FIXME: read from block */ | ||
159 | drec_data->data_len = htons(16); | ||
160 | 155 | ||
161 | answer->pkt.addroffset = htons((unsigned short)((unsigned long)(&drec_data->data)-(unsigned long)(&answer->pkt))); | 156 | GNUNET_free(query); |
162 | 157 | ||
163 | GNUNET_CONTAINER_DLL_insert_after(head, tail, tail, answer); | 158 | /* When more data is to be sent, reschedule */ |
159 | if (head != NULL) | ||
160 | GNUNET_SERVER_notify_transmit_ready(cls, | ||
161 | ntohs(head->pkt.hdr.size), | ||
162 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
163 | &send_answer, | ||
164 | cls); | ||
164 | 165 | ||
165 | GNUNET_SERVER_notify_transmit_ready(query_states[id].client, | 166 | return len; |
166 | len, | 167 | } |
167 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
168 | &send_answer, | ||
169 | query_states[id].client); | ||
170 | 168 | ||
171 | GNUNET_DHT_get_stop(handle); | 169 | /** |
170 | * Receive a block from the dht. | ||
171 | */ | ||
172 | static void | ||
173 | receive_dht(void *cls, | ||
174 | struct GNUNET_TIME_Absolute exp, | ||
175 | const GNUNET_HashCode *key, | ||
176 | const struct GNUNET_PeerIdentity *const *get_path, | ||
177 | const struct GNUNET_PeerIdentity *const *put_path, | ||
178 | enum GNUNET_BLOCK_Type type, | ||
179 | size_t size, | ||
180 | const void *data) { | ||
181 | |||
182 | unsigned short id = ((struct receive_dht_cls*)cls)->id; | ||
183 | struct GNUNET_DHT_GetHandle* handle = ((struct receive_dht_cls*)cls)->handle; | ||
184 | GNUNET_free(cls); | ||
185 | |||
186 | GNUNET_assert(type == GNUNET_BLOCK_TYPE_DNS); | ||
187 | |||
188 | /* If no query with this id is pending, ignore the block */ | ||
189 | if (query_states[id].valid != GNUNET_YES) return; | ||
190 | query_states[id].valid = GNUNET_NO; | ||
191 | |||
192 | const struct GNUNET_DNS_Record* rec = data; | ||
193 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
194 | "Got block of size %d, peer: %08x, desc: %08x\n", | ||
195 | size, | ||
196 | *((unsigned int*)&rec->peer), | ||
197 | *((unsigned int*)&rec->service_descriptor)); | ||
198 | |||
199 | size_t len = sizeof(struct answer_packet) - 1 \ | ||
200 | + sizeof(struct dns_static) \ | ||
201 | + query_states[id].namelen \ | ||
202 | + sizeof(struct dns_query_line) \ | ||
203 | + 2 /* To hold the pointer (as defined in RFC1035) to the name */ \ | ||
204 | + sizeof(struct dns_record_line) - 1 \ | ||
205 | + 16; /* To hold the IPv6-Address */ | ||
206 | |||
207 | struct answer_packet_list* answer = GNUNET_malloc(len + 2*sizeof(struct answer_packet_list*)); | ||
208 | memset(answer, 0, len + 2*sizeof(struct answer_packet_list*)); | ||
209 | |||
210 | answer->pkt.hdr.type = htons(GNUNET_MESSAGE_TYPE_LOCAL_RESPONSE_DNS); | ||
211 | answer->pkt.hdr.size = htons(len); | ||
212 | answer->pkt.subtype = GNUNET_DNS_ANSWER_TYPE_SERVICE; | ||
213 | |||
214 | GNUNET_CRYPTO_hash(&rec->peer, | ||
215 | sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), | ||
216 | &answer->pkt.peer); | ||
217 | |||
218 | memcpy(&answer->pkt.service_descriptor, | ||
219 | &rec->service_descriptor, | ||
220 | sizeof(GNUNET_HashCode)); | ||
221 | memcpy(&answer->pkt.service_type, | ||
222 | &rec->service_type, | ||
223 | sizeof(answer->pkt.service_type)); | ||
224 | memcpy(&answer->pkt.ports, &rec->ports, sizeof(answer->pkt.ports)); | ||
225 | |||
226 | answer->pkt.from = query_states[id].remote_ip; | ||
227 | |||
228 | answer->pkt.to = query_states[id].local_ip; | ||
229 | answer->pkt.dst_port = query_states[id].local_port; | ||
230 | |||
231 | struct dns_pkt *dpkt = (struct dns_pkt*)answer->pkt.data; | ||
232 | |||
233 | dpkt->s.id = id; | ||
234 | dpkt->s.aa = 1; | ||
235 | dpkt->s.qr = 1; | ||
236 | dpkt->s.ra = 1; | ||
237 | dpkt->s.qdcount = htons(1); | ||
238 | dpkt->s.ancount = htons(1); | ||
239 | |||
240 | memcpy(dpkt->data, query_states[id].name, query_states[id].namelen); | ||
241 | GNUNET_free(query_states[id].name); | ||
242 | |||
243 | |||
244 | struct dns_query_line* dque = (struct dns_query_line*)(dpkt->data+(query_states[id].namelen)); | ||
245 | dque->type = htons(28); /* AAAA */ | ||
246 | dque->class = htons(1); /* IN */ | ||
247 | |||
248 | char* anname = (char*)(dpkt->data+(query_states[id].namelen)+sizeof(struct dns_query_line)); | ||
249 | memcpy(anname, (char[]){0xc0, 0x0c}, 2); | ||
250 | |||
251 | struct dns_record_line *drec_data = (struct dns_record_line*)(dpkt->data+(query_states[id].namelen)+sizeof(struct dns_query_line)+2); | ||
252 | drec_data->type = htons(28); /* AAAA */ | ||
253 | drec_data->class = htons(1); /* IN */ | ||
254 | drec_data->ttl = htonl(3600); /* FIXME: read from block */ | ||
255 | drec_data->data_len = htons(16); | ||
256 | |||
257 | /* Calculate at which offset in the packet the IPv6-Address belongs, it is | ||
258 | * filled in by the daemon-vpn */ | ||
259 | answer->pkt.addroffset = htons((unsigned short)((unsigned long)(&drec_data->data)-(unsigned long)(&answer->pkt))); | ||
260 | |||
261 | GNUNET_CONTAINER_DLL_insert_after(head, tail, tail, answer); | ||
262 | |||
263 | GNUNET_SERVER_notify_transmit_ready(query_states[id].client, | ||
264 | len, | ||
265 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
266 | &send_answer, | ||
267 | query_states[id].client); | ||
268 | |||
269 | GNUNET_DHT_get_stop(handle); | ||
172 | } | 270 | } |
173 | 271 | ||
174 | /** | 272 | /** |
175 | * This receives a GNUNET_MESSAGE_TYPE_REHIJACK and rehijacks the DNS | 273 | * This receives a GNUNET_MESSAGE_TYPE_REHIJACK and rehijacks the DNS |
176 | */ | 274 | */ |
177 | void rehijack(void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { | 275 | static void |
276 | rehijack(void *cls, | ||
277 | struct GNUNET_SERVER_Client *client, | ||
278 | const struct GNUNET_MessageHeader *message) { | ||
178 | unhijack(dnsoutport); | 279 | unhijack(dnsoutport); |
179 | hijack(dnsoutport); | 280 | hijack(dnsoutport); |
180 | } | 281 | } |
@@ -182,116 +283,122 @@ void rehijack(void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNE | |||
182 | /** | 283 | /** |
183 | * This receives the dns-payload from the daemon-vpn and sends it on over the udp-socket | 284 | * This receives the dns-payload from the daemon-vpn and sends it on over the udp-socket |
184 | */ | 285 | */ |
185 | void receive_query(void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) | 286 | static void |
186 | { | 287 | receive_query(void *cls, |
187 | struct query_packet* pkt = (struct query_packet*)message; | 288 | struct GNUNET_SERVER_Client *client, |
188 | struct dns_pkt* dns = (struct dns_pkt*)pkt->data; | 289 | const struct GNUNET_MessageHeader *message) { |
189 | struct dns_pkt_parsed* pdns = parse_dns_packet(dns); | 290 | struct query_packet* pkt = (struct query_packet*)message; |
190 | 291 | struct dns_pkt* dns = (struct dns_pkt*)pkt->data; | |
191 | query_states[dns->s.id].valid = GNUNET_YES; | 292 | struct dns_pkt_parsed* pdns = parse_dns_packet(dns); |
192 | query_states[dns->s.id].client = client; | 293 | |
193 | query_states[dns->s.id].local_ip = pkt->orig_from; | 294 | query_states[dns->s.id].valid = GNUNET_YES; |
194 | query_states[dns->s.id].local_port = pkt->src_port; | 295 | query_states[dns->s.id].client = client; |
195 | query_states[dns->s.id].remote_ip = pkt->orig_to; | 296 | query_states[dns->s.id].local_ip = pkt->orig_from; |
196 | query_states[dns->s.id].namelen = strlen((char*)dns->data) + 1; | 297 | query_states[dns->s.id].local_port = pkt->src_port; |
197 | query_states[dns->s.id].name = GNUNET_malloc(query_states[dns->s.id].namelen); | 298 | query_states[dns->s.id].remote_ip = pkt->orig_to; |
198 | memcpy(query_states[dns->s.id].name, dns->data, query_states[dns->s.id].namelen); | 299 | query_states[dns->s.id].namelen = strlen((char*)dns->data) + 1; |
199 | 300 | query_states[dns->s.id].name = GNUNET_malloc(query_states[dns->s.id].namelen); | |
200 | if (pdns->queries[0]->namelen > 9 && | 301 | memcpy(query_states[dns->s.id].name, dns->data, query_states[dns->s.id].namelen); |
201 | 0 == strncmp(pdns->queries[0]->name+(pdns->queries[0]->namelen - 9), ".gnunet.", 9)) { | 302 | |
202 | 303 | if (pdns->queries[0]->namelen > 9 && | |
203 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Query for .gnunet!\n"); | 304 | 0 == strncmp(pdns->queries[0]->name+(pdns->queries[0]->namelen - 9), ".gnunet.", 9)) |
204 | GNUNET_HashCode key; | 305 | { |
205 | GNUNET_CRYPTO_hash(pdns->queries[0]->name, pdns->queries[0]->namelen, &key); | 306 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Query for .gnunet!\n"); |
206 | 307 | GNUNET_HashCode key; | |
207 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Getting with key %08x, len is %d\n", *((unsigned int*)&key), pdns->queries[0]->namelen); | 308 | GNUNET_CRYPTO_hash(pdns->queries[0]->name, pdns->queries[0]->namelen, &key); |
208 | 309 | ||
209 | struct receive_dht_cls* cls = GNUNET_malloc(sizeof(struct receive_dht_cls)); | 310 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, |
210 | cls->id = dns->s.id; | 311 | "Getting with key %08x, len is %d\n", |
211 | 312 | *((unsigned int*)&key), | |
212 | cls->handle = GNUNET_DHT_get_start(dht, | 313 | pdns->queries[0]->namelen); |
213 | GNUNET_TIME_UNIT_MINUTES, | 314 | |
214 | GNUNET_BLOCK_TYPE_DNS, | 315 | struct receive_dht_cls* cls = GNUNET_malloc(sizeof(struct receive_dht_cls)); |
215 | &key, | 316 | cls->id = dns->s.id; |
216 | GNUNET_DHT_RO_NONE, | 317 | |
217 | NULL, | 318 | cls->handle = GNUNET_DHT_get_start(dht, |
218 | 0, | 319 | GNUNET_TIME_UNIT_MINUTES, |
219 | NULL, | 320 | GNUNET_BLOCK_TYPE_DNS, |
220 | 0, | 321 | &key, |
221 | receive_dht, | 322 | GNUNET_DHT_RO_NONE, |
222 | cls); | 323 | NULL, |
223 | 324 | 0, | |
224 | goto out; | 325 | NULL, |
225 | } | 326 | 0, |
226 | 327 | receive_dht, | |
227 | /* The query should be sent to the network */ | 328 | cls); |
228 | GNUNET_free(pdns); | 329 | |
229 | 330 | goto out; | |
230 | struct sockaddr_in dest; | 331 | } |
231 | memset(&dest, 0, sizeof dest); | 332 | |
232 | dest.sin_port = htons(53); | 333 | /* The query should be sent to the network */ |
233 | dest.sin_addr.s_addr = pkt->orig_to; | 334 | GNUNET_free(pdns); |
234 | 335 | ||
235 | /* int r = */ GNUNET_NETWORK_socket_sendto(dnsout, dns, ntohs(pkt->hdr.size) - sizeof(struct query_packet) + 1, (struct sockaddr*) &dest, sizeof dest); | 336 | struct sockaddr_in dest; |
337 | memset(&dest, 0, sizeof dest); | ||
338 | dest.sin_port = htons(53); | ||
339 | dest.sin_addr.s_addr = pkt->orig_to; | ||
340 | |||
341 | GNUNET_NETWORK_socket_sendto(dnsout, | ||
342 | dns, | ||
343 | ntohs(pkt->hdr.size) - sizeof(struct query_packet) + 1, | ||
344 | (struct sockaddr*) &dest, | ||
345 | sizeof dest); | ||
236 | 346 | ||
237 | out: | 347 | out: |
238 | GNUNET_SERVER_receive_done(client, GNUNET_OK); | 348 | GNUNET_SERVER_receive_done(client, GNUNET_OK); |
239 | } | 349 | } |
240 | 350 | ||
241 | size_t send_answer(void* cls, size_t size, void* buf) { | 351 | /** |
242 | struct answer_packet_list* query = head; | 352 | * Read a response-packet of the UDP-Socket |
243 | size_t len = ntohs(query->pkt.hdr.size); | 353 | */ |
244 | 354 | static void | |
245 | GNUNET_assert(len <= size); | 355 | read_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { |
246 | 356 | unsigned char buf[65536]; | |
247 | memcpy(buf, &query->pkt.hdr, len); | 357 | struct dns_pkt* dns = (struct dns_pkt*)buf; |
248 | |||
249 | GNUNET_CONTAINER_DLL_remove (head, tail, query); | ||
250 | |||
251 | GNUNET_free(query); | ||
252 | |||
253 | if (head != NULL) { | ||
254 | GNUNET_SERVER_notify_transmit_ready(cls, ntohs(head->pkt.hdr.size), GNUNET_TIME_UNIT_FOREVER_REL, &send_answer, cls); | ||
255 | } | ||
256 | |||
257 | return len; | ||
258 | } | ||
259 | |||
260 | static void read_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { | ||
261 | unsigned char buf[65536]; | ||
262 | struct dns_pkt* dns = (struct dns_pkt*)buf; | ||
263 | |||
264 | if (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) | ||
265 | return; | ||
266 | |||
267 | struct sockaddr_in addr; | ||
268 | memset(&addr, 0, sizeof addr); | ||
269 | unsigned int addrlen = sizeof addr; | ||
270 | |||
271 | int r; | ||
272 | r = GNUNET_NETWORK_socket_recvfrom(dnsout, buf, 65536, (struct sockaddr*)&addr, &addrlen); | ||
273 | |||
274 | /* if (r < 0) TODO */ | ||
275 | |||
276 | if (query_states[dns->s.id].valid == GNUNET_YES) { | ||
277 | query_states[dns->s.id].valid = GNUNET_NO; | ||
278 | |||
279 | size_t len = sizeof(struct answer_packet) + r - 1; /* 1 for the unsigned char data[1]; */ | ||
280 | struct answer_packet_list* answer = GNUNET_malloc(len + 2*sizeof(struct answer_packet_list*)); | ||
281 | answer->pkt.hdr.type = htons(GNUNET_MESSAGE_TYPE_LOCAL_RESPONSE_DNS); | ||
282 | answer->pkt.hdr.size = htons(len); | ||
283 | answer->pkt.subtype = GNUNET_DNS_ANSWER_TYPE_IP; | ||
284 | answer->pkt.from = addr.sin_addr.s_addr; | ||
285 | answer->pkt.to = query_states[dns->s.id].local_ip; | ||
286 | answer->pkt.dst_port = query_states[dns->s.id].local_port; | ||
287 | memcpy(answer->pkt.data, buf, r); | ||
288 | 358 | ||
289 | GNUNET_CONTAINER_DLL_insert_after(head, tail, tail, answer); | 359 | if (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) |
360 | return; | ||
290 | 361 | ||
291 | /* struct GNUNET_CONNECTION_TransmitHandle* th = */ GNUNET_SERVER_notify_transmit_ready(query_states[dns->s.id].client, len, GNUNET_TIME_UNIT_FOREVER_REL, &send_answer, query_states[dns->s.id].client); | 362 | struct sockaddr_in addr; |
292 | } | 363 | memset(&addr, 0, sizeof addr); |
364 | unsigned int addrlen = sizeof addr; | ||
365 | |||
366 | int r; | ||
367 | r = GNUNET_NETWORK_socket_recvfrom(dnsout, | ||
368 | buf, | ||
369 | 65536, | ||
370 | (struct sockaddr*)&addr, | ||
371 | &addrlen); | ||
372 | |||
373 | /* if (r < 0) FIXME */ | ||
374 | |||
375 | if (query_states[dns->s.id].valid == GNUNET_YES) { | ||
376 | query_states[dns->s.id].valid = GNUNET_NO; | ||
377 | |||
378 | size_t len = sizeof(struct answer_packet) + r - 1; /* 1 for the unsigned char data[1]; */ | ||
379 | struct answer_packet_list* answer = GNUNET_malloc(len + 2*sizeof(struct answer_packet_list*)); | ||
380 | answer->pkt.hdr.type = htons(GNUNET_MESSAGE_TYPE_LOCAL_RESPONSE_DNS); | ||
381 | answer->pkt.hdr.size = htons(len); | ||
382 | answer->pkt.subtype = GNUNET_DNS_ANSWER_TYPE_IP; | ||
383 | answer->pkt.from = addr.sin_addr.s_addr; | ||
384 | answer->pkt.to = query_states[dns->s.id].local_ip; | ||
385 | answer->pkt.dst_port = query_states[dns->s.id].local_port; | ||
386 | memcpy(answer->pkt.data, buf, r); | ||
387 | |||
388 | GNUNET_CONTAINER_DLL_insert_after(head, tail, tail, answer); | ||
389 | |||
390 | GNUNET_SERVER_notify_transmit_ready(query_states[dns->s.id].client, | ||
391 | len, | ||
392 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
393 | &send_answer, | ||
394 | query_states[dns->s.id].client); | ||
395 | } | ||
293 | 396 | ||
294 | GNUNET_SCHEDULER_add_read_net(sched, GNUNET_TIME_UNIT_FOREVER_REL, dnsout, &read_response, NULL); | 397 | GNUNET_SCHEDULER_add_read_net(sched, |
398 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
399 | dnsout, | ||
400 | &read_response, | ||
401 | NULL); | ||
295 | } | 402 | } |
296 | 403 | ||
297 | 404 | ||
@@ -305,69 +412,74 @@ static void | |||
305 | cleanup_task (void *cls, | 412 | cleanup_task (void *cls, |
306 | const struct GNUNET_SCHEDULER_TaskContext *tc) | 413 | const struct GNUNET_SCHEDULER_TaskContext *tc) |
307 | { | 414 | { |
308 | unhijack(dnsoutport); | 415 | unhijack(dnsoutport); |
309 | GNUNET_DHT_disconnect(dht); | 416 | GNUNET_DHT_disconnect(dht); |
310 | } | 417 | } |
311 | 418 | ||
419 | /** | ||
420 | * Publish a DNS-record in the DHT. This is up to now just for testing. | ||
421 | */ | ||
312 | static void | 422 | static void |
313 | publish_name (void *cls, | 423 | publish_name (void *cls, |
314 | const struct GNUNET_SCHEDULER_TaskContext *tc) | 424 | const struct GNUNET_SCHEDULER_TaskContext *tc) { |
315 | { | 425 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) |
316 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | 426 | return; |
317 | return; | ||
318 | |||
319 | char* name = "philipptoelke.gnunet."; | ||
320 | size_t size = sizeof(struct GNUNET_DNS_Record); | ||
321 | struct GNUNET_DNS_Record data; | ||
322 | memset(&data, 0, size); | ||
323 | 427 | ||
324 | data.purpose.size = htonl(size - sizeof(struct GNUNET_CRYPTO_RsaSignature)); | 428 | char* name = "philipptoelke.gnunet."; |
325 | data.purpose.purpose = GNUNET_SIGNATURE_PURPOSE_DNS_RECORD; | 429 | size_t size = sizeof(struct GNUNET_DNS_Record); |
430 | struct GNUNET_DNS_Record data; | ||
431 | memset(&data, 0, size); | ||
326 | 432 | ||
327 | GNUNET_CRYPTO_hash(name, strlen(name)+1, &data.service_descriptor); | 433 | data.purpose.size = htonl(size - sizeof(struct GNUNET_CRYPTO_RsaSignature)); |
434 | data.purpose.purpose = GNUNET_SIGNATURE_PURPOSE_DNS_RECORD; | ||
328 | 435 | ||
329 | char* keyfile; | 436 | GNUNET_CRYPTO_hash(name, strlen(name)+1, &data.service_descriptor); |
330 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename(cfg, "GNUNETD", | ||
331 | "HOSTKEY", &keyfile)) | ||
332 | { | ||
333 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "could not read keyfile-value\n"); | ||
334 | if (keyfile != NULL) GNUNET_free(keyfile); | ||
335 | return; | ||
336 | } | ||
337 | 437 | ||
338 | struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file(keyfile); | 438 | char* keyfile; |
339 | GNUNET_free(keyfile); | 439 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename(cfg, "GNUNETD", |
440 | "HOSTKEY", &keyfile)) | ||
441 | { | ||
442 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "could not read keyfile-value\n"); | ||
443 | if (keyfile != NULL) GNUNET_free(keyfile); | ||
444 | return; | ||
445 | } | ||
340 | 446 | ||
341 | GNUNET_CRYPTO_rsa_key_get_public(my_private_key, &data.peer); | 447 | struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file(keyfile); |
448 | GNUNET_free(keyfile); | ||
342 | 449 | ||
343 | data.expiration_time = GNUNET_TIME_relative_to_absolute(GNUNET_TIME_UNIT_HOURS); | 450 | GNUNET_CRYPTO_rsa_key_get_public(my_private_key, &data.peer); |
344 | 451 | ||
345 | /* Sign the block | 452 | data.expiration_time = GNUNET_TIME_relative_to_absolute(GNUNET_TIME_UNIT_HOURS); |
346 | */ | ||
347 | 453 | ||
348 | if (GNUNET_OK != GNUNET_CRYPTO_rsa_sign(my_private_key, | 454 | /* Sign the block */ |
349 | &data.purpose, | 455 | if (GNUNET_OK != GNUNET_CRYPTO_rsa_sign(my_private_key, |
350 | &data.signature)) | 456 | &data.purpose, |
351 | { | 457 | &data.signature)) |
352 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "could not sign DNS_Record\n"); | 458 | { |
353 | return; | 459 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "could not sign DNS_Record\n"); |
354 | } | 460 | return; |
355 | GNUNET_free(my_private_key); | 461 | } |
356 | 462 | GNUNET_free(my_private_key); | |
357 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Putting with key %08x\n", *((unsigned int*)&data.service_descriptor)); | 463 | |
358 | 464 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | |
359 | GNUNET_DHT_put(dht, | 465 | "Putting with key %08x\n", |
360 | &data.service_descriptor, | 466 | *((unsigned int*)&data.service_descriptor)); |
361 | GNUNET_DHT_RO_NONE, | 467 | |
362 | GNUNET_BLOCK_TYPE_DNS, | 468 | GNUNET_DHT_put(dht, |
363 | size, | 469 | &data.service_descriptor, |
364 | (char*)&data, | 470 | GNUNET_DHT_RO_NONE, |
365 | GNUNET_TIME_relative_to_absolute(GNUNET_TIME_UNIT_HOURS), | 471 | GNUNET_BLOCK_TYPE_DNS, |
366 | GNUNET_TIME_UNIT_MINUTES, | 472 | size, |
367 | NULL, | 473 | (char*)&data, |
368 | NULL); | 474 | GNUNET_TIME_relative_to_absolute(GNUNET_TIME_UNIT_HOURS), |
369 | 475 | GNUNET_TIME_UNIT_MINUTES, | |
370 | GNUNET_SCHEDULER_add_delayed (sched, GNUNET_TIME_UNIT_HOURS, publish_name, NULL); | 476 | NULL, |
477 | NULL); | ||
478 | |||
479 | GNUNET_SCHEDULER_add_delayed (sched, | ||
480 | GNUNET_TIME_UNIT_HOURS, | ||
481 | publish_name, | ||
482 | NULL); | ||
371 | } | 483 | } |
372 | 484 | ||
373 | /** | 485 | /** |
@@ -383,20 +495,18 @@ run (void *cls, | |||
383 | const struct GNUNET_CONFIGURATION_Handle *cfg_) | 495 | const struct GNUNET_CONFIGURATION_Handle *cfg_) |
384 | { | 496 | { |
385 | static const struct GNUNET_SERVER_MessageHandler handlers[] = { | 497 | static const struct GNUNET_SERVER_MessageHandler handlers[] = { |
386 | /* callback, cls, type, size */ | 498 | /* callback, cls, type, size */ |
387 | {&receive_query, NULL, GNUNET_MESSAGE_TYPE_LOCAL_QUERY_DNS, 0}, | 499 | {&receive_query, NULL, GNUNET_MESSAGE_TYPE_LOCAL_QUERY_DNS, 0}, |
388 | {&rehijack, NULL, GNUNET_MESSAGE_TYPE_REHIJACK, sizeof(struct GNUNET_MessageHeader)}, | 500 | {&rehijack, NULL, GNUNET_MESSAGE_TYPE_REHIJACK, sizeof(struct GNUNET_MessageHeader)}, |
389 | {NULL, NULL, 0, 0} | 501 | {NULL, NULL, 0, 0} |
390 | }; | 502 | }; |
391 | 503 | ||
392 | cfg = cfg_; | 504 | cfg = cfg_; |
393 | sched = sched_; | 505 | sched = sched_; |
394 | 506 | ||
395 | { | 507 | unsigned int i; |
396 | int i; | ||
397 | for (i = 0; i < 65536; i++) { | 508 | for (i = 0; i < 65536; i++) { |
398 | query_states[i].valid = GNUNET_NO; | 509 | query_states[i].valid = GNUNET_NO; |
399 | } | ||
400 | } | 510 | } |
401 | 511 | ||
402 | dht = GNUNET_DHT_connect(sched, cfg, 1024); | 512 | dht = GNUNET_DHT_connect(sched, cfg, 1024); |
@@ -413,9 +523,11 @@ run (void *cls, | |||
413 | sizeof(struct sockaddr_in)); | 523 | sizeof(struct sockaddr_in)); |
414 | 524 | ||
415 | if (err != GNUNET_YES) { | 525 | if (err != GNUNET_YES) { |
416 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Could not bind a port, exiting\n"); | 526 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Could not bind a port, exiting\n"); |
417 | return; | 527 | return; |
418 | } | 528 | } |
529 | |||
530 | /* Read the port we bound to */ | ||
419 | socklen_t addrlen = sizeof(struct sockaddr_in); | 531 | socklen_t addrlen = sizeof(struct sockaddr_in); |
420 | err = getsockname(GNUNET_NETWORK_get_fd(dnsout), | 532 | err = getsockname(GNUNET_NETWORK_get_fd(dnsout), |
421 | (struct sockaddr*) &addr, | 533 | (struct sockaddr*) &addr, |
@@ -431,9 +543,9 @@ run (void *cls, | |||
431 | 543 | ||
432 | GNUNET_SERVER_add_handlers (server, handlers); | 544 | GNUNET_SERVER_add_handlers (server, handlers); |
433 | GNUNET_SCHEDULER_add_delayed (sched, | 545 | GNUNET_SCHEDULER_add_delayed (sched, |
434 | GNUNET_TIME_UNIT_FOREVER_REL, | 546 | GNUNET_TIME_UNIT_FOREVER_REL, |
435 | &cleanup_task, | 547 | &cleanup_task, |
436 | cls); | 548 | cls); |
437 | } | 549 | } |
438 | 550 | ||
439 | /** | 551 | /** |
@@ -447,9 +559,9 @@ int | |||
447 | main (int argc, char *const *argv) | 559 | main (int argc, char *const *argv) |
448 | { | 560 | { |
449 | return (GNUNET_OK == | 561 | return (GNUNET_OK == |
450 | GNUNET_SERVICE_run (argc, | 562 | GNUNET_SERVICE_run (argc, |
451 | argv, | 563 | argv, |
452 | "dns", | 564 | "dns", |
453 | GNUNET_SERVICE_OPTION_NONE, | 565 | GNUNET_SERVICE_OPTION_NONE, |
454 | &run, NULL)) ? 0 : 1; | 566 | &run, NULL)) ? 0 : 1; |
455 | } | 567 | } |