aboutsummaryrefslogtreecommitdiff
path: root/src/dns
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-01-03 20:30:07 +0000
committerChristian Grothoff <christian@grothoff.org>2012-01-03 20:30:07 +0000
commit5b9de1c328efb28856b9239301be1821ecf21bc0 (patch)
treeb4a69b3a0d2c06c8786858c94f405a5c76b0a58f /src/dns
parent3368e64ea2c577cc5e6d4274d00cf6ec1641e063 (diff)
downloadgnunet-5b9de1c328efb28856b9239301be1821ecf21bc0.tar.gz
gnunet-5b9de1c328efb28856b9239301be1821ecf21bc0.zip
-more DNS service hacking
Diffstat (limited to 'src/dns')
-rw-r--r--src/dns/dns_api_new.c21
-rw-r--r--src/dns/dns_new.h18
-rw-r--r--src/dns/gnunet-service-dns_new.c499
3 files changed, 371 insertions, 167 deletions
diff --git a/src/dns/dns_api_new.c b/src/dns/dns_api_new.c
index a61676a47..b578c3a9d 100644
--- a/src/dns/dns_api_new.c
+++ b/src/dns/dns_api_new.c
@@ -125,6 +125,11 @@ struct GNUNET_DNS_Handle
125 * Re-connect counter, to make sure we did not reconnect in the meantime. 125 * Re-connect counter, to make sure we did not reconnect in the meantime.
126 */ 126 */
127 uint32_t generation; 127 uint32_t generation;
128
129 /**
130 * Flags for events we care about.
131 */
132 enum GNUNET_DNS_Flags flags;
128 133
129 /** 134 /**
130 * Did we start the receive loop yet? 135 * Did we start the receive loop yet?
@@ -162,7 +167,7 @@ reconnect (void *cls,
162{ 167{
163 struct GNUNET_DNS_Handle *dh = cls; 168 struct GNUNET_DNS_Handle *dh = cls;
164 struct ReplyQueueEntry *qe; 169 struct ReplyQueueEntry *qe;
165 struct GNUNET_MessageHeader *msg; 170 struct GNUNET_DNS_Register *msg;
166 171
167 dh->reconnect_task = GNUNET_SCHEDULER_NO_TASK; 172 dh->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
168 dh->dns_connection = GNUNET_CLIENT_connect ("dns", dh->cfg); 173 dh->dns_connection = GNUNET_CLIENT_connect ("dns", dh->cfg);
@@ -170,11 +175,12 @@ reconnect (void *cls,
170 return; 175 return;
171 dh->generation++; 176 dh->generation++;
172 qe = GNUNET_malloc (sizeof (struct ReplyQueueEntry) + 177 qe = GNUNET_malloc (sizeof (struct ReplyQueueEntry) +
173 sizeof (struct GNUNET_MessageHeader)); 178 sizeof (struct GNUNET_DNS_Register));
174 msg = (struct GNUNET_MessageHeader*) &qe[1]; 179 msg = (struct GNUNET_DNS_Register*) &qe[1];
175 qe->msg = msg; 180 qe->msg = &msg->header;
176 msg->size = htons (sizeof (struct GNUNET_MessageHeader)); 181 msg->header.size = htons (sizeof (struct GNUNET_DNS_Register));
177 msg->type = htons (GNUNET_MESSAGE_TYPE_DNS_CLIENT_INIT); 182 msg->header.type = htons (GNUNET_MESSAGE_TYPE_DNS_CLIENT_INIT);
183 msg->flags = htonl (dh->flags);
178 queue_reply (dh, qe); 184 queue_reply (dh, qe);
179} 185}
180 186
@@ -471,12 +477,14 @@ GNUNET_DNS_request_answer (struct GNUNET_DNS_RequestHandle *rh,
471 * Connect to the service-dns 477 * Connect to the service-dns
472 * 478 *
473 * @param cfg configuration to use 479 * @param cfg configuration to use
480 * @param flags when to call rh
474 * @param rh function to call with DNS requests 481 * @param rh function to call with DNS requests
475 * @param rh_cls closure to pass to rh 482 * @param rh_cls closure to pass to rh
476 * @return DNS handle 483 * @return DNS handle
477 */ 484 */
478struct GNUNET_DNS_Handle * 485struct GNUNET_DNS_Handle *
479GNUNET_DNS_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, 486GNUNET_DNS_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
487 enum GNUNET_DNS_Flags flags,
480 GNUNET_DNS_RequestHandler rh, 488 GNUNET_DNS_RequestHandler rh,
481 void *rh_cls) 489 void *rh_cls)
482{ 490{
@@ -484,6 +492,7 @@ GNUNET_DNS_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
484 492
485 dh = GNUNET_malloc (sizeof (struct GNUNET_DNS_Handle)); 493 dh = GNUNET_malloc (sizeof (struct GNUNET_DNS_Handle));
486 dh->cfg = cfg; 494 dh->cfg = cfg;
495 dh->flags = flags;
487 dh->rh = rh; 496 dh->rh = rh;
488 dh->rh_cls = rh_cls; 497 dh->rh_cls = rh_cls;
489 dh->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect, dh); 498 dh->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect, dh);
diff --git a/src/dns/dns_new.h b/src/dns/dns_new.h
index 7cf3a316a..29a9f937b 100644
--- a/src/dns/dns_new.h
+++ b/src/dns/dns_new.h
@@ -28,6 +28,24 @@
28 28
29GNUNET_NETWORK_STRUCT_BEGIN 29GNUNET_NETWORK_STRUCT_BEGIN
30 30
31
32/**
33 * Message from client to DNS service to register itself.
34 */
35struct GNUNET_DNS_Register
36{
37 /**
38 * Header of type GNUNET_MESSAGE_TYPE_DNS_CLIENT_INIT
39 */
40 struct GNUNET_MessageHeader header;
41
42 /**
43 * NBO encoding of 'enum GNUNET_DNS_Flags' for the client.
44 */
45 uint32_t flags;
46};
47
48
31/** 49/**
32 * Message from DNS service to client: please handle a request. 50 * Message from DNS service to client: please handle a request.
33 */ 51 */
diff --git a/src/dns/gnunet-service-dns_new.c b/src/dns/gnunet-service-dns_new.c
index ae57d9088..041b2d12b 100644
--- a/src/dns/gnunet-service-dns_new.c
+++ b/src/dns/gnunet-service-dns_new.c
@@ -22,27 +22,13 @@
22 * @file dns/gnunet-service-dns_new.c 22 * @file dns/gnunet-service-dns_new.c
23 * @author Christian Grothoff 23 * @author Christian Grothoff
24 */ 24 */
25// current thoughts:
26// - for full compatibility to DNS and to avoid going insane here parsing/generating DNS packets,
27// how about literally attaching the "original" DNS packet (request/response) to the IPC traffic?
28// that way, clients can literally do arbitrary modifications and we are done with that issue here.
29// All we'd do in here is add the IP/UDP headers and be DONE with it.
30// => minor modifications to API and IPC protocol
31// => minor modifications to our data structures
32// => major gains in terms of simplicity here and what can (at least theoretically) be done with the service
33// => can test much more quickly
34// => but: need to really write a good libgnunetdnsparse to avoid making MANY clients really complicated
35// (not the worst of worlds either, other than deferring this mess some...)
36// -> also positive: can be tested independently of the rest of the mess
37
38
39#include "platform.h" 25#include "platform.h"
40#include "gnunet_util_lib.h" 26#include "gnunet_util_lib.h"
41#include "gnunet_constants.h" 27#include "gnunet_constants.h"
42#include "gnunet_protocols.h" 28#include "gnunet_protocols.h"
43//#include "gnunet_dnsparser_lib.h"
44#include "gnunet_signatures.h" 29#include "gnunet_signatures.h"
45#include "dns_new.h" 30#include "dns_new.h"
31#include "gnunet_dns_service-new.h"
46 32
47GNUNET_NETWORK_STRUCT_BEGIN 33GNUNET_NETWORK_STRUCT_BEGIN
48struct ip4_hdr 34struct ip4_hdr
@@ -86,45 +72,58 @@ struct udp_pkt
86 uint16_t crc GNUNET_PACKED; 72 uint16_t crc GNUNET_PACKED;
87}; 73};
88 74
89struct dns_pkt 75
76struct dns_hdr
90{ 77{
91 uint16_t id GNUNET_PACKED; 78 uint16_t id GNUNET_PACKED;
92 79 uint16_t flags GNUNET_PACKED;
93 unsigned rd:1 GNUNET_PACKED; // recursion desired (client -> server) 80 uint16_t qdcount GNUNET_PACKED;
94 unsigned tc:1 GNUNET_PACKED; // message is truncated 81 uint16_t ancount GNUNET_PACKED;
95 unsigned aa:1 GNUNET_PACKED; // authoritative answer 82 uint16_t nscount GNUNET_PACKED;
96 unsigned op:4 GNUNET_PACKED; // query:0, inverse q.:1, status: 2 83 uint16_t arcount GNUNET_PACKED;
97 unsigned qr:1 GNUNET_PACKED; // query:0, response:1
98
99 unsigned rcode:4 GNUNET_PACKED; // 0 No error
100 // 1 Format error
101 // 2 Server failure
102 // 3 Name Error
103 // 4 Not Implemented
104 // 5 Refused
105 unsigned z:3 GNUNET_PACKED; // reserved
106 unsigned ra:1 GNUNET_PACKED; // recursion available (server -> client)
107
108 uint16_t qdcount GNUNET_PACKED; // number of questions
109 uint16_t ancount GNUNET_PACKED; // number of answers
110 uint16_t nscount GNUNET_PACKED; // number of authority-records
111 uint16_t arcount GNUNET_PACKED; // number of additional records
112}; 84};
85GNUNET_NETWORK_STRUCT_END
113 86
114struct dns_query_line
115{
116 uint16_t type;
117 uint16_t class;
118};
119 87
120struct dns_record_line 88/**
89 * Phases each request goes through.
90 */
91enum RequestPhase
121{ 92{
122 uint16_t type; 93 /**
123 uint16_t class; 94 * Request has just been received.
124 uint32_t ttl; 95 */
125 uint16_t data_len; 96 RP_INIT,
97
98 /**
99 * Showing the request to all monitor clients. If
100 * client list is empty, will enter QUERY phase.
101 */
102 RP_MONITOR,
103
104 /**
105 * Showing the request to PRE-RESOLUTION clients to find an answer.
106 * If client list is empty, will trigger global DNS request.
107 */
108 RP_QUERY,
109
110 /**
111 * Global Internet query is now pending.
112 */
113 RP_INTERNET_DNS,
114
115 /**
116 * Client (or global DNS request) has resulted in a response.
117 * Forward to all POST-RESOLUTION clients. If client list is empty,
118 * give the result to the hijacker (and be done).
119 */
120 RP_MODIFY,
121
122 /**
123 * Some client has told us to drop the request.
124 */
125 RP_DROP
126}; 126};
127GNUNET_NETWORK_STRUCT_END
128 127
129 128
130/** 129/**
@@ -147,6 +146,11 @@ struct ClientRecord
147 */ 146 */
148 struct GNUNET_SERVER_Client *client; 147 struct GNUNET_SERVER_Client *client;
149 148
149 /**
150 * Flags for the client.
151 */
152 enum GNUNET_DNS_Flags flags;
153
150}; 154};
151 155
152 156
@@ -157,25 +161,16 @@ struct RequestRecord
157{ 161{
158 162
159 /** 163 /**
160 * Name for the request.
161 */
162 char *name;
163
164 /**
165 * Response data, or NULL if not known.
166 */
167 char *rdata;
168
169 /**
170 * List of clients that still need to see this request (each entry 164 * List of clients that still need to see this request (each entry
171 * is set to NULL when the client is done). 165 * is set to NULL when the client is done).
172 */ 166 */
173 struct ClientRecord **client_wait_list; 167 struct ClientRecord **client_wait_list;
174 168
175 /** 169 /**
176 * Length of the client wait list. 170 * Payload of the UDP packet (the UDP payload), can be either query
171 * or already the response.
177 */ 172 */
178 unsigned int client_wait_list_length; 173 char *payload;
179 174
180 /** 175 /**
181 * Source address of the original request (for sending response). 176 * Source address of the original request (for sending response).
@@ -195,34 +190,19 @@ struct RequestRecord
195 uint64_t request_id; 190 uint64_t request_id;
196 191
197 /** 192 /**
198 * TTL if we know it, or 0. 193 * Number of bytes in payload.
199 */
200 uint32_t dns_ttl;
201
202 /**
203 * Number of bytes in rdata.
204 */ 194 */
205 uint16_t rdata_length; 195 size_t payload_length;
206 196
207 /** 197 /**
208 * Length of the 'name' string, including 0-terminator. 198 * Length of the client wait list.
209 */
210 uint16_t name_length;
211
212 /**
213 * The DNS type (i.e. 1 == 'A').
214 */
215 uint16_t dns_type;
216
217 /**
218 * The DNS class (i.e. 1 == Internet)
219 */ 199 */
220 uint16_t dns_class; 200 unsigned int client_wait_list_length;
221 201
222 /** 202 /**
223 * Original DNS Id we got from the client. 203 * In which phase this this request?
224 */ 204 */
225 uint16_t original_dns_id; 205 enum RequestPhase phase;
226 206
227}; 207};
228 208
@@ -281,6 +261,11 @@ static struct ClientRecord *clients_head;
281static struct ClientRecord *clients_tail; 261static struct ClientRecord *clients_tail;
282 262
283/** 263/**
264 * Our notification context.
265 */
266static struct GNUNET_SERVER_NotificationContext *nc;
267
268/**
284 * Array of all open requests. 269 * Array of all open requests.
285 */ 270 */
286static struct RequestRecord requests[UINT16_MAX]; 271static struct RequestRecord requests[UINT16_MAX];
@@ -292,6 +277,23 @@ static uint64_t request_id_gen;
292 277
293 278
294/** 279/**
280 * We're done processing a DNS request, free associated memory.
281 *
282 * @param rr request to clean up
283 */
284static void
285cleanup_rr (struct RequestRecord *rr)
286{
287 GNUNET_free (rr->payload);
288 rr->payload = NULL;
289 rr->payload_length = 0;
290 GNUNET_array_grow (rr->client_wait_list,
291 rr->client_wait_list_length,
292 0);
293}
294
295
296/**
295 * Task run during shutdown. 297 * Task run during shutdown.
296 * 298 *
297 * @param cls unused 299 * @param cls unused
@@ -302,7 +304,6 @@ cleanup_task (void *cls GNUNET_UNUSED,
302 const struct GNUNET_SCHEDULER_TaskContext *tc) 304 const struct GNUNET_SCHEDULER_TaskContext *tc)
303{ 305{
304 unsigned int i; 306 unsigned int i;
305 struct RequestRecord *rr;
306 307
307 GNUNET_HELPER_stop (hijacker); 308 GNUNET_HELPER_stop (hijacker);
308 hijacker = NULL; 309 hijacker = NULL;
@@ -329,19 +330,16 @@ cleanup_task (void *cls GNUNET_UNUSED,
329 read6_task = GNUNET_SCHEDULER_NO_TASK; 330 read6_task = GNUNET_SCHEDULER_NO_TASK;
330 } 331 }
331 for (i=0;i<65536;i++) 332 for (i=0;i<65536;i++)
332 { 333 cleanup_rr (&requests[i]);
333 rr = &requests[i]; 334 GNUNET_SERVER_notification_context_destroy (nc);
334 GNUNET_free (rr->name); 335 nc = NULL;
335 GNUNET_free_non_null (rr->rdata);
336 GNUNET_array_grow (rr->client_wait_list,
337 rr->client_wait_list_length,
338 0);
339 }
340} 336}
341 337
342 338
343/** 339/**
344 * We're done with some request, finish processing. 340 * We're done with some request, finish processing.
341 *
342 * @param rr request send to the network or just clean up.
345 */ 343 */
346static void 344static void
347request_done (struct RequestRecord *rr) 345request_done (struct RequestRecord *rr)
@@ -354,11 +352,10 @@ request_done (struct RequestRecord *rr)
354 GNUNET_array_grow (rr->client_wait_list, 352 GNUNET_array_grow (rr->client_wait_list,
355 rr->client_wait_list_length, 353 rr->client_wait_list_length,
356 0); 354 0);
357 if (NULL == rr->rdata) 355 if (RP_MODIFY != rr->phase)
358 { 356 {
359 /* no response, drop */ 357 /* no response, drop */
360 GNUNET_free (rr->name); 358 cleanup_rr (rr);
361 rr->name = NULL;
362 return; 359 return;
363 } 360 }
364 361
@@ -374,21 +371,16 @@ request_done (struct RequestRecord *rr)
374 break; 371 break;
375 default: 372 default:
376 GNUNET_break (0); 373 GNUNET_break (0);
377 GNUNET_free (rr->name); 374 cleanup_rr (rr);
378 rr->name = NULL;
379 return; 375 return;
380 } 376 }
381 reply_len += sizeof (struct udp_pkt); 377 reply_len += sizeof (struct udp_pkt);
382 reply_len += sizeof (struct dns_pkt); 378 reply_len += rr->payload_length;
383 reply_len += rr->name_length;
384 reply_len += sizeof (struct dns_record_line);
385 reply_len += rr->rdata_length;
386 if (reply_len >= GNUNET_SERVER_MAX_MESSAGE_SIZE) 379 if (reply_len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
387 { 380 {
388 /* response too big, drop */ 381 /* response too big, drop */
389 GNUNET_break (0); /* how can this be? */ 382 GNUNET_break (0); /* how can this be? */
390 GNUNET_free (rr->name); 383 cleanup_rr(rr);
391 rr->name = NULL;
392 return; 384 return;
393 } 385 }
394 { 386 {
@@ -433,6 +425,7 @@ request_done (struct RequestRecord *rr)
433 default: 425 default:
434 GNUNET_assert (0); 426 GNUNET_assert (0);
435 } 427 }
428
436 /* now UDP header */ 429 /* now UDP header */
437 { 430 {
438 struct udp_pkt udp; 431 struct udp_pkt udp;
@@ -444,51 +437,10 @@ request_done (struct RequestRecord *rr)
444 memcpy (&buf[off], &udp, sizeof (udp)); 437 memcpy (&buf[off], &udp, sizeof (udp));
445 off += sizeof (udp); 438 off += sizeof (udp);
446 } 439 }
447 440 /* now DNS header */
448 /* now DNS header */
449 {
450 struct dns_pkt dns;
451
452 dns.id = rr->original_dns_id;
453 dns.rd = 1; /* recursion desired / supported */
454 dns.tc = 0; /* not truncated */
455 dns.aa = 1; /* are we authoritative!? I say yes. */
456 dns.op = 0; /* standard query */
457 dns.qr = 1; /* this is a response */
458 dns.rcode = 0; /* no error */
459 dns.z = 0; /* reserved */
460 dns.ra = 1; /* recursion available */
461 dns.qdcount = htons (0); /* no queries */
462 dns.ancount = htons (1); /* one answer */
463 dns.nscount = htons (0); /* no authorities yet (fixme) */
464 dns.arcount = htons (0); /* no additinal records yet (fixme) */
465 memcpy (&buf[off], &dns, sizeof (dns));
466 off += sizeof (dns);
467 }
468
469 /* now DNS name */
470 {
471 // FIXME: fill in DNS name!
472 off += rr->name_length;
473 }
474
475
476 /* now DNS record line */
477 {
478 struct dns_record_line drl;
479
480 drl.type = htons (rr->dns_type);
481 drl.class = htons (rr->dns_class);
482 drl.ttl = htonl (rr->dns_ttl);
483 drl.data_len = htons (rr->rdata_length);
484 memcpy (&buf[off], &drl, sizeof (drl));
485 off += sizeof (drl);
486 }
487
488 /* now DNS rdata */
489 { 441 {
490 memcpy (&buf[off], rr->rdata, rr->rdata_length); 442 memcpy (&buf[off], rr->payload, rr->payload_length);
491 off += rr->rdata_length; 443 off += rr->payload_length;
492 } 444 }
493 445
494 /* final checks & sending */ 446 /* final checks & sending */
@@ -499,8 +451,147 @@ request_done (struct RequestRecord *rr)
499 NULL, NULL); 451 NULL, NULL);
500 } 452 }
501 /* clean up, we're done */ 453 /* clean up, we're done */
502 GNUNET_free (rr->name); 454 cleanup_rr (rr);
503 rr->name = NULL; 455}
456
457
458/**
459 * Show the payload of the given request record to the client
460 * (and wait for a response).
461 *
462 * @param rr request to send to client
463 * @param client client to send the response to
464 */
465static void
466send_request_to_client (struct RequestRecord *rr,
467 struct GNUNET_SERVER_Client *client)
468{
469 char buf[sizeof (struct GNUNET_DNS_Request) + rr->payload_length];
470 struct GNUNET_DNS_Request *req;
471
472 if (sizeof (buf) >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
473 {
474 GNUNET_break (0);
475 cleanup_rr (rr);
476 return;
477 }
478 req = (struct GNUNET_DNS_Request*) buf;
479 req->header.type = htons (GNUNET_MESSAGE_TYPE_DNS_CLIENT_REQUEST);
480 req->header.size = htons (sizeof (buf));
481 req->reserved = htonl (0);
482 req->request_id = rr->request_id;
483 memcpy (&req[1], rr->payload, rr->payload_length);
484 GNUNET_SERVER_notification_context_unicast (nc,
485 client,
486 &req->header,
487 GNUNET_NO);
488}
489
490
491/**
492 * A client has completed its processing for this
493 * request. Move on.
494 *
495 * @param rr request to process further
496 */
497static void
498next_phase (struct RequestRecord *rr)
499{
500 struct ClientRecord *cr;
501 int nz;
502 unsigned int j;
503 struct GNUNET_NETWORK_Handle *dnsout;
504 socklen_t salen;
505
506 if (rr->phase == RP_DROP)
507 {
508 cleanup_rr (rr);
509 return;
510 }
511 nz = -1;
512 for (j=0;j<rr->client_wait_list_length;j++)
513 {
514 if (NULL != rr->client_wait_list[j])
515 {
516 nz = (int) j;
517 break;
518 }
519 }
520 if (-1 != nz)
521 {
522 send_request_to_client (rr, rr->client_wait_list[nz]->client);
523 return;
524 }
525 /* done with current phase, advance! */
526 switch (rr->phase)
527 {
528 case RP_INIT:
529 rr->phase = RP_MONITOR;
530 for (cr = clients_head; NULL != cr; cr = cr->next)
531 {
532 if (0 != (cr->flags & GNUNET_DNS_FLAG_REQUEST_MONITOR))
533 GNUNET_array_append (rr->client_wait_list,
534 rr->client_wait_list_length,
535 cr);
536 }
537 next_phase (rr);
538 return;
539 case RP_MONITOR:
540 rr->phase = RP_QUERY;
541 for (cr = clients_head; NULL != cr; cr = cr->next)
542 {
543 if (0 != (cr->flags & GNUNET_DNS_FLAG_PRE_RESOLUTION))
544 GNUNET_array_append (rr->client_wait_list,
545 rr->client_wait_list_length,
546 cr);
547 }
548 next_phase (rr);
549 return;
550 case RP_QUERY:
551 rr->phase = RP_INTERNET_DNS;
552 switch (rr->dst_addr.ss_family)
553 {
554 case AF_INET:
555 dnsout = dnsout4;
556 salen = sizeof (struct ip4_hdr);
557 break;
558 case AF_INET6:
559 dnsout = dnsout6;
560 salen = sizeof (struct ip6_hdr);
561 break;
562 default:
563 GNUNET_break (0);
564 cleanup_rr (rr);
565 return;
566 }
567 GNUNET_NETWORK_socket_sendto (dnsout,
568 rr->payload,
569 rr->payload_length,
570 (struct sockaddr*) &rr->dst_addr,
571 salen);
572 return;
573 case RP_INTERNET_DNS:
574 rr->phase = RP_MODIFY;
575 for (cr = clients_head; NULL != cr; cr = cr->next)
576 {
577 if (0 != (cr->flags & GNUNET_DNS_FLAG_POST_RESOLUTION))
578 GNUNET_array_append (rr->client_wait_list,
579 rr->client_wait_list_length,
580 cr);
581 }
582 next_phase (rr);
583 return;
584 case RP_MODIFY:
585 request_done (rr);
586 break;
587 case RP_DROP:
588 cleanup_rr (rr);
589 break;
590 default:
591 GNUNET_break (0);
592 cleanup_rr (rr);
593 break;
594 }
504} 595}
505 596
506 597
@@ -517,7 +608,6 @@ client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
517 struct RequestRecord *rr; 608 struct RequestRecord *rr;
518 unsigned int i; 609 unsigned int i;
519 unsigned int j; 610 unsigned int j;
520 int az;
521 611
522 for (cr = clients_head; NULL != cr; cr = cr->next) 612 for (cr = clients_head; NULL != cr; cr = cr->next)
523 { 613 {
@@ -532,16 +622,14 @@ client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
532 rr = &requests[i]; 622 rr = &requests[i];
533 if (0 == rr->client_wait_list_length) 623 if (0 == rr->client_wait_list_length)
534 continue; /* not in use */ 624 continue; /* not in use */
535 az = 1;
536 for (j=0;j<rr->client_wait_list_length;j++) 625 for (j=0;j<rr->client_wait_list_length;j++)
537 { 626 {
538 if (rr->client_wait_list[j] == cr) 627 if (rr->client_wait_list[j] == cr)
628 {
539 rr->client_wait_list[j] = NULL; 629 rr->client_wait_list[j] = NULL;
540 if (rr->client_wait_list[j] != NULL) 630 next_phase (rr);
541 az = 0; 631 }
542 } 632 }
543 if (1 == az)
544 request_done (rr); /* this was the last client... */
545 } 633 }
546 GNUNET_free (cr); 634 GNUNET_free (cr);
547 return; 635 return;
@@ -564,7 +652,9 @@ read_response (void *cls,
564 struct sockaddr_in addr4; 652 struct sockaddr_in addr4;
565 struct sockaddr_in6 addr6; 653 struct sockaddr_in6 addr6;
566 struct sockaddr *addr; 654 struct sockaddr *addr;
655 struct dns_hdr *dns;
567 socklen_t addrlen; 656 socklen_t addrlen;
657 struct RequestRecord *rr;
568 ssize_t r; 658 ssize_t r;
569 int len; 659 int len;
570 660
@@ -612,9 +702,26 @@ read_response (void *cls,
612 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "recvfrom"); 702 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "recvfrom");
613 return; 703 return;
614 } 704 }
615 // NOTE: struct dns_pkt *dns = (struct dns_pkt *) buf; 705 if (sizeof (struct dns_hdr) > r)
616 // FIXME: handle_response (buf, r, addr, addrlen); 706 {
617 } 707 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
708 _("Received DNS response that is too small (%u bytes)"),
709 r);
710 return;
711 }
712 dns = (struct dns_hdr *) buf;
713 rr = &requests[dns->id];
714 if (rr->phase != RP_INTERNET_DNS)
715 {
716 /* FIXME: case for statistics */
717 /* unexpected / bogus reply */
718 return;
719 }
720 GNUNET_free_non_null (rr->payload);
721 rr->payload = GNUNET_malloc (len);
722 memcpy (rr->payload, buf, len);
723 next_phase (rr);
724 }
618} 725}
619 726
620 727
@@ -744,16 +851,19 @@ open_port6 ()
744static void 851static void
745handle_client_init (void *cls GNUNET_UNUSED, 852handle_client_init (void *cls GNUNET_UNUSED,
746 struct GNUNET_SERVER_Client *client, 853 struct GNUNET_SERVER_Client *client,
747 const struct GNUNET_MessageHeader *message GNUNET_UNUSED) 854 const struct GNUNET_MessageHeader *message)
748{ 855{
749 struct ClientRecord *cr; 856 struct ClientRecord *cr;
857 const struct GNUNET_DNS_Register *reg = (const struct GNUNET_DNS_Register*) message;
750 858
751 cr = GNUNET_malloc (sizeof (struct ClientRecord)); 859 cr = GNUNET_malloc (sizeof (struct ClientRecord));
752 cr->client = client; 860 cr->client = client;
861 cr->flags = (enum GNUNET_DNS_Flags) ntohl (reg->flags);
753 GNUNET_SERVER_client_keep (client); 862 GNUNET_SERVER_client_keep (client);
754 GNUNET_CONTAINER_DLL_insert (clients_head, 863 GNUNET_CONTAINER_DLL_insert (clients_head,
755 clients_tail, 864 clients_tail,
756 cr); 865 cr);
866 GNUNET_SERVER_notification_context_add (nc, client);
757 GNUNET_SERVER_receive_done (client, GNUNET_OK); 867 GNUNET_SERVER_receive_done (client, GNUNET_OK);
758} 868}
759 869
@@ -768,10 +878,73 @@ handle_client_init (void *cls GNUNET_UNUSED,
768static void 878static void
769handle_client_response (void *cls GNUNET_UNUSED, 879handle_client_response (void *cls GNUNET_UNUSED,
770 struct GNUNET_SERVER_Client *client, 880 struct GNUNET_SERVER_Client *client,
771 const struct GNUNET_MessageHeader *message GNUNET_UNUSED) 881 const struct GNUNET_MessageHeader *message)
772{ 882{
773 // FIXME: validate and parse response, process response 883 const struct GNUNET_DNS_Response *resp;
774 GNUNET_SERVER_receive_done (client, GNUNET_OK); 884 struct RequestRecord *rr;
885 unsigned int i;
886 uint16_t msize;
887 uint16_t off;
888
889 msize = ntohs (message->size);
890 if (msize < sizeof (struct GNUNET_DNS_Response))
891 {
892 GNUNET_break (0);
893 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
894 return;
895 }
896 resp = (const struct GNUNET_DNS_Response*) message;
897 off = (uint16_t) resp->request_id;
898 rr = &requests[off];
899 if (rr->request_id != resp->request_id)
900 {
901 // FIXME: this is a case for calling statistics...
902 // (client is answering a request that we've lost
903 // track of -- more than 64k requests ago or so...)
904 GNUNET_SERVER_receive_done (client, GNUNET_OK);
905 return;
906 }
907 for (i=0;i<rr->client_wait_list_length;i++)
908 {
909 if (rr->client_wait_list[i]->client != client)
910 continue;
911 rr->client_wait_list[i] = NULL;
912 switch (ntohl (resp->drop_flag))
913 {
914 case 0: /* drop */
915 rr->phase = RP_DROP;
916 break;
917 case 1: /* no change */
918 break;
919 case 2: /* update */
920 msize -= sizeof (struct GNUNET_DNS_Response);
921 if ( (sizeof (struct dns_hdr) > msize) ||
922 (RP_MONITOR == rr->phase) )
923 {
924 GNUNET_break (0);
925 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
926 next_phase (rr);
927 return;
928 }
929 GNUNET_free_non_null (rr->payload);
930 rr->payload = GNUNET_malloc (msize);
931 memcpy (rr->payload, &resp[1], msize);
932 if (rr->phase == RP_QUERY)
933 {
934 /* clear wait list, we're moving to MODIFY phase next */
935 GNUNET_array_grow (rr->client_wait_list,
936 rr->client_wait_list_length,
937 0);
938 }
939 next_phase (rr);
940 GNUNET_SERVER_receive_done (client, GNUNET_OK);
941 return;
942 }
943 }
944 /* odd, client was not on our list for the request, that ought
945 to be an error */
946 GNUNET_break (0);
947 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
775} 948}
776 949
777 950
@@ -784,12 +957,14 @@ handle_client_response (void *cls GNUNET_UNUSED,
784 * @param message the actual message, a DNS request we should handle 957 * @param message the actual message, a DNS request we should handle
785 */ 958 */
786static void 959static void
787process_helper_messages (void *cls, void *client, 960process_helper_messages (void *cls GNUNET_UNUSED, void *client,
788 const struct GNUNET_MessageHeader *message) 961 const struct GNUNET_MessageHeader *message)
789{ 962{
963 struct RequestRecord *rr = NULL;
790 /* FIXME: parse message, create record, start processing! */ 964 /* FIXME: parse message, create record, start processing! */
791 /* FIXME: put request into queue for clients / system DNS */ 965 /* FIXME: put request into queue for clients / system DNS */
792 request_id_gen++; 966 request_id_gen++;
967 next_phase (rr);
793} 968}
794 969
795 970
@@ -804,7 +979,8 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
804{ 979{
805 static const struct GNUNET_SERVER_MessageHandler handlers[] = { 980 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
806 /* callback, cls, type, size */ 981 /* callback, cls, type, size */
807 {&handle_client_init, NULL, GNUNET_MESSAGE_TYPE_DNS_CLIENT_INIT, sizeof (struct GNUNET_MessageHeader)}, 982 {&handle_client_init, NULL, GNUNET_MESSAGE_TYPE_DNS_CLIENT_INIT,
983 sizeof (struct GNUNET_DNS_Register)},
808 {&handle_client_response, NULL, GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE, 0}, 984 {&handle_client_response, NULL, GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE, 0},
809 {NULL, NULL, 0, 0} 985 {NULL, NULL, 0, 0}
810 }; 986 };
@@ -816,6 +992,7 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
816 char *ipv6prefix; 992 char *ipv6prefix;
817 993
818 cfg = cfg_; 994 cfg = cfg_;
995 nc = GNUNET_SERVER_notification_context_create (server, 1);
819 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task, 996 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
820 cls); 997 cls);
821 if (GNUNET_YES == 998 if (GNUNET_YES ==