aboutsummaryrefslogtreecommitdiff
path: root/src/dns
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-01-02 17:03:12 +0000
committerChristian Grothoff <christian@grothoff.org>2012-01-02 17:03:12 +0000
commit7abe8a4171588af22d4e64dade3956a15fcec6fd (patch)
tree5233d99cee4617d124048fbce74023432bef1409 /src/dns
parentb63b061c6fc20d9ad1db85911a83321d2a55a6e1 (diff)
downloadgnunet-7abe8a4171588af22d4e64dade3956a15fcec6fd.tar.gz
gnunet-7abe8a4171588af22d4e64dade3956a15fcec6fd.zip
-towards dns service
Diffstat (limited to 'src/dns')
-rw-r--r--src/dns/gnunet-service-dns_new.c378
1 files changed, 346 insertions, 32 deletions
diff --git a/src/dns/gnunet-service-dns_new.c b/src/dns/gnunet-service-dns_new.c
index afaf13196..5ae56873c 100644
--- a/src/dns/gnunet-service-dns_new.c
+++ b/src/dns/gnunet-service-dns_new.c
@@ -26,29 +26,91 @@
26#include "gnunet_util_lib.h" 26#include "gnunet_util_lib.h"
27#include "gnunet_constants.h" 27#include "gnunet_constants.h"
28#include "gnunet_protocols.h" 28#include "gnunet_protocols.h"
29#include "gnunet_dnsparser_lib.h" 29//#include "gnunet_dnsparser_lib.h"
30#include "gnunet_signatures.h" 30#include "gnunet_signatures.h"
31#include "dns_new.h" 31#include "dns_new.h"
32 32
33GNUNET_NETWORK_STRUCT_BEGIN
34struct ip4_hdr
35{
36 unsigned hdr_lngth:4 GNUNET_PACKED;
37 unsigned version:4 GNUNET_PACKED;
33 38
34/** 39 uint8_t diff_serv;
35 * Entry we keep for each active request. 40 uint16_t tot_lngth GNUNET_PACKED;
36 */ 41
37struct RequestRecord 42 uint16_t ident GNUNET_PACKED;
43 unsigned flags:3 GNUNET_PACKED;
44 unsigned frag_off:13 GNUNET_PACKED;
45
46 uint8_t ttl;
47 uint8_t proto;
48 uint16_t chks GNUNET_PACKED;
49
50 struct in_addr sadr GNUNET_PACKED;
51 struct in_addr dadr GNUNET_PACKED;
52};
53
54struct ip6_hdr
38{ 55{
56 unsigned tclass_h:4 GNUNET_PACKED;
57 unsigned version:4 GNUNET_PACKED;
58 unsigned tclass_l:4 GNUNET_PACKED;
59 unsigned flowlbl:20 GNUNET_PACKED;
60 uint16_t paylgth GNUNET_PACKED;
61 uint8_t nxthdr;
62 uint8_t hoplmt;
63 struct in6_addr sadr GNUNET_PACKED;
64 struct in6_addr dadr GNUNET_PACKED;
65};
39 66
67struct udp_pkt
68{
69 uint16_t spt GNUNET_PACKED;
70 uint16_t dpt GNUNET_PACKED;
71 uint16_t len GNUNET_PACKED;
72 uint16_t crc GNUNET_PACKED;
73};
40 74
41 /** 75struct dns_pkt
42 * Entry of this request record in the heap (for fast removal). 76{
43 */ 77 uint16_t id GNUNET_PACKED;
44 struct GNUNET_CONTAINER_HeapNode *hentry; 78
79 unsigned rd:1 GNUNET_PACKED; // recursion desired (client -> server)
80 unsigned tc:1 GNUNET_PACKED; // message is truncated
81 unsigned aa:1 GNUNET_PACKED; // authoritative answer
82 unsigned op:4 GNUNET_PACKED; // query:0, inverse q.:1, status: 2
83 unsigned qr:1 GNUNET_PACKED; // query:0, response:1
84
85 unsigned rcode:4 GNUNET_PACKED; // 0 No error
86 // 1 Format error
87 // 2 Server failure
88 // 3 Name Error
89 // 4 Not Implemented
90 // 5 Refused
91 unsigned z:3 GNUNET_PACKED; // reserved
92 unsigned ra:1 GNUNET_PACKED; // recursion available (server -> client)
93
94 uint16_t qdcount GNUNET_PACKED; // number of questions
95 uint16_t ancount GNUNET_PACKED; // number of answers
96 uint16_t nscount GNUNET_PACKED; // number of authority-records
97 uint16_t arcount GNUNET_PACKED; // number of additional records
98};
45 99
46 /** 100struct dns_query_line
47 * Array of clients and their answers. 101{
48 */ 102 uint16_t type;
49 struct GNUNET_SERVER_Client *client; 103 uint16_t class;
104};
50 105
106struct dns_record_line
107{
108 uint16_t type;
109 uint16_t class;
110 uint32_t ttl;
111 uint16_t data_len;
51}; 112};
113GNUNET_NETWORK_STRUCT_END
52 114
53 115
54/** 116/**
@@ -75,6 +137,83 @@ struct ClientRecord
75 137
76 138
77/** 139/**
140 * Entry we keep for each active request.
141 */
142struct RequestRecord
143{
144
145 /**
146 * Name for the request.
147 */
148 char *name;
149
150 /**
151 * Response data, or NULL if not known.
152 */
153 char *rdata;
154
155 /**
156 * List of clients that still need to see this request (each entry
157 * is set to NULL when the client is done).
158 */
159 struct ClientRecord **client_wait_list;
160
161 /**
162 * Length of the client wait list.
163 */
164 unsigned int client_wait_list_length;
165
166 /**
167 * Source address of the original request (for sending response).
168 */
169 struct sockaddr_storage src_addr;
170
171 /**
172 * Destination address of the original request (for potential use as exit).
173 */
174 struct sockaddr_storage dst_addr;
175
176 /**
177 * ID of this request, also basis for hashing. Lowest 16 bit will
178 * be our message ID when doing a global DNS request and our index
179 * into the 'requests' array.
180 */
181 uint64_t request_id;
182
183 /**
184 * TTL if we know it, or 0.
185 */
186 uint32_t dns_ttl;
187
188 /**
189 * Number of bytes in rdata.
190 */
191 uint16_t rdata_length;
192
193 /**
194 * Length of the 'name' string, including 0-terminator.
195 */
196 uint16_t name_length;
197
198 /**
199 * The DNS type (i.e. 1 == 'A').
200 */
201 uint16_t dns_type;
202
203 /**
204 * The DNS class (i.e. 1 == Internet)
205 */
206 uint16_t dns_class;
207
208 /**
209 * Original DNS Id we got from the client.
210 */
211 uint16_t original_dns_id;
212
213};
214
215
216/**
78 * The IPv4 UDP-Socket through which DNS-Resolves will be sent if they are not to be 217 * The IPv4 UDP-Socket through which DNS-Resolves will be sent if they are not to be
79 * sent through gnunet. The port of this socket will not be hijacked. 218 * sent through gnunet. The port of this socket will not be hijacked.
80 */ 219 */
@@ -128,15 +267,14 @@ static struct ClientRecord *clients_head;
128static struct ClientRecord *clients_tail; 267static struct ClientRecord *clients_tail;
129 268
130/** 269/**
131 * Hash map of open requests. 270 * Array of all open requests.
132 */ 271 */
133static struct GNUNET_CONTAINER_MultiHashMap *request_map; 272static struct RequestRecord requests[UINT16_MAX];
134 273
135/** 274/**
136 * Heap with open requests (sorted by time received, oldest on top). 275 * Generator for unique request IDs.
137 */ 276 */
138static struct GNUNET_CONTAINER_Heap *request_heap; 277static uint64_t request_id_gen;
139
140 278
141 279
142/** 280/**
@@ -176,21 +314,179 @@ cleanup_task (void *cls GNUNET_UNUSED,
176 GNUNET_SCHEDULER_cancel (read6_task); 314 GNUNET_SCHEDULER_cancel (read6_task);
177 read6_task = GNUNET_SCHEDULER_NO_TASK; 315 read6_task = GNUNET_SCHEDULER_NO_TASK;
178 } 316 }
179 if (NULL != request_heap) 317 for (i=0;i<65536;i++)
180 { 318 {
181 while (NULL != (rr = GNUNET_CONTAINER_heap_remove_root (request_heap))) 319 rr = &requests[i];
182 { 320 GNUNET_free (rr->name);
183 // FIXME: free rest of 'rr' 321 GNUNET_free_non_null (rr->rdata);
184 GNUNET_free (rr); 322 GNUNET_array_grow (rr->client_wait_list,
185 } 323 rr->client_wait_list_length,
186 GNUNET_CONTAINER_heap_destroy (request_heap); 324 0);
187 request_heap = NULL; 325 }
326}
327
328
329/**
330 * We're done with some request, finish processing.
331 */
332static void
333request_done (struct RequestRecord *rr)
334{
335 struct GNUNET_MessageHeader *hdr;
336 size_t reply_len;
337 uint16_t spt;
338 uint16_t dpt;
339
340 GNUNET_array_grow (rr->client_wait_list,
341 rr->client_wait_list_length,
342 0);
343 if (NULL == rr->rdata)
344 {
345 /* no response, drop */
346 GNUNET_free (rr->name);
347 rr->name = NULL;
348 return;
349 }
350
351 /* send response via hijacker */
352 reply_len = sizeof (struct GNUNET_MessageHeader);
353 switch (rr->src_addr.ss_family)
354 {
355 case AF_INET:
356 reply_len += sizeof (struct ip4_hdr);
357 break;
358 case AF_INET6:
359 reply_len += sizeof (struct ip6_hdr);
360 break;
361 default:
362 GNUNET_break (0);
363 GNUNET_free (rr->name);
364 rr->name = NULL;
365 return;
188 } 366 }
189 if (NULL != request_map) 367 reply_len += sizeof (struct udp_pkt);
368 reply_len += sizeof (struct dns_pkt);
369 reply_len += rr->name_length;
370 reply_len += sizeof (struct dns_record_line);
371 reply_len += rr->rdata_length;
372 if (reply_len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
190 { 373 {
191 GNUNET_CONTAINER_multihashmap_destroy (request_map); 374 /* response too big, drop */
192 request_map = NULL; 375 GNUNET_break (0); /* how can this be? */
376 GNUNET_free (rr->name);
377 rr->name = NULL;
378 return;
193 } 379 }
380 {
381 char buf[reply_len];
382 size_t off;
383
384 /* first, GNUnet message header */
385 hdr = (struct GNUNET_MessageHeader*) buf;
386 hdr->type = htons (GNUNET_MESSAGE_TYPE_DNS_HELPER);
387 hdr->size = htons ((uint16_t) reply_len);
388 off = sizeof (struct GNUNET_MessageHeader);
389
390 /* now IP header */
391 switch (rr->src_addr.ss_family)
392 {
393 case AF_INET:
394 {
395 struct sockaddr_in *src = (struct sockaddr_in *) &rr->src_addr;
396 struct sockaddr_in *dst = (struct sockaddr_in *) &rr->dst_addr;
397 struct ip4_hdr ip;
398
399 spt = dst->sin_port;
400 dpt = src->sin_port;
401 // FIXME: fill in IP header!
402 memcpy (&buf[off], &ip, sizeof (ip));
403 off += sizeof (ip);
404 break;
405 }
406 case AF_INET6:
407 {
408 struct sockaddr_in6 *src = (struct sockaddr_in6 *) &rr->src_addr;
409 struct sockaddr_in6 *dst = (struct sockaddr_in6 *) &rr->dst_addr;
410 struct ip6_hdr ip;
411
412 spt = dst->sin6_port;
413 dpt = src->sin6_port;
414 // FIXME: fill in IP header!
415 memcpy (&buf[off], &ip, sizeof (ip));
416 off += sizeof (ip);
417 }
418 break;
419 default:
420 GNUNET_assert (0);
421 }
422 /* now UDP header */
423 {
424 struct udp_pkt udp;
425
426 udp.spt = spt;
427 udp.dpt = dpt;
428 udp.len = htons (reply_len - off);
429 udp.crc = 0; /* checksum is optional */
430 memcpy (&buf[off], &udp, sizeof (udp));
431 off += sizeof (udp);
432 }
433
434 /* now DNS header */
435 {
436 struct dns_pkt dns;
437
438 dns.id = rr->original_dns_id;
439 dns.rd = 1; /* recursion desired / supported */
440 dns.tc = 0; /* not truncated */
441 dns.aa = 1; /* are we authoritative!? I say yes. */
442 dns.op = 0; /* standard query */
443 dns.qr = 1; /* this is a response */
444 dns.rcode = 0; /* no error */
445 dns.z = 0; /* reserved */
446 dns.ra = 1; /* recursion available */
447 dns.qdcount = htons (0); /* no queries */
448 dns.ancount = htons (1); /* one answer */
449 dns.nscount = htons (0); /* no authorities yet (fixme) */
450 dns.arcount = htons (0); /* no additinal records yet (fixme) */
451 memcpy (&buf[off], &dns, sizeof (dns));
452 off += sizeof (dns);
453 }
454
455 /* now DNS name */
456 {
457 // FIXME: fill in DNS name!
458 off += rr->name_length;
459 }
460
461
462 /* now DNS record line */
463 {
464 struct dns_record_line drl;
465
466 drl.type = htons (rr->dns_type);
467 drl.class = htons (rr->dns_class);
468 drl.ttl = htonl (rr->dns_ttl);
469 drl.data_len = htons (rr->rdata_length);
470 memcpy (&buf[off], &drl, sizeof (drl));
471 off += sizeof (drl);
472 }
473
474 /* now DNS rdata */
475 {
476 memcpy (&buf[off], rr->rdata, rr->rdata_length);
477 off += rr->rdata_length;
478 }
479
480 /* final checks & sending */
481 GNUNET_assert (off == reply_len);
482 GNUNET_HELPER_send (hijacker,
483 hdr,
484 GNUNET_YES,
485 NULL, NULL);
486 }
487 /* clean up, we're done */
488 GNUNET_free (rr->name);
489 rr->name = NULL;
194} 490}
195 491
196 492
@@ -204,8 +500,11 @@ static void
204client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) 500client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
205{ 501{
206 struct ClientRecord *cr; 502 struct ClientRecord *cr;
503 struct RequestRecord *rr;
504 unsigned int i;
505 unsigned int j;
506 int az;
207 507
208 /* FIXME: clean up after client */
209 for (cr = clients_head; NULL != cr; cr = cr->next) 508 for (cr = clients_head; NULL != cr; cr = cr->next)
210 { 509 {
211 if (cr->client == client) 510 if (cr->client == client)
@@ -214,6 +513,22 @@ client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
214 GNUNET_CONTAINER_DLL_remove (clients_head, 513 GNUNET_CONTAINER_DLL_remove (clients_head,
215 clients_tail, 514 clients_tail,
216 cr); 515 cr);
516 for (i=0;i<UINT16_MAX;i++)
517 {
518 rr = &requests[i];
519 if (0 == rr->client_wait_list_length)
520 continue; /* not in use */
521 az = 1;
522 for (j=0;j<rr->client_wait_list_length;j++)
523 {
524 if (rr->client_wait_list[j] == cr)
525 rr->client_wait_list[j] = NULL;
526 if (rr->client_wait_list[j] != NULL)
527 az = 0;
528 }
529 if (1 == az)
530 request_done (rr); /* this was the last client... */
531 }
217 GNUNET_free (cr); 532 GNUNET_free (cr);
218 return; 533 return;
219 } 534 }
@@ -460,6 +775,7 @@ process_helper_messages (void *cls, void *client,
460{ 775{
461 /* FIXME: parse message, create record, start processing! */ 776 /* FIXME: parse message, create record, start processing! */
462 /* FIXME: put request into queue for clients / system DNS */ 777 /* FIXME: put request into queue for clients / system DNS */
778 request_id_gen++;
463} 779}
464 780
465 781
@@ -486,8 +802,6 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
486 char *ipv6prefix; 802 char *ipv6prefix;
487 803
488 cfg = cfg_; 804 cfg = cfg_;
489 request_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
490 request_map = GNUNET_CONTAINER_multihashmap_create (1024 * 16);
491 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task, 805 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
492 cls); 806 cls);
493 if (GNUNET_YES == 807 if (GNUNET_YES ==