diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-01-18 22:10:08 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-01-18 22:10:08 +0000 |
commit | d8cda8039015fe11760ae256c43094d046e08cac (patch) | |
tree | 18644056a4e8e26eb537a683ae343adc066fe602 /src | |
parent | c37fba0bd9febb11297ebca62a58935276130244 (diff) | |
download | gnunet-d8cda8039015fe11760ae256c43094d046e08cac.tar.gz gnunet-d8cda8039015fe11760ae256c43094d046e08cac.zip |
-adding support for routing DNS requests via MESH to PT daemon
Diffstat (limited to 'src')
-rw-r--r-- | src/pt/Makefile.am | 1 | ||||
-rw-r--r-- | src/pt/gnunet-daemon-pt.c | 548 | ||||
-rw-r--r-- | src/pt/pt.conf | 3 |
3 files changed, 497 insertions, 55 deletions
diff --git a/src/pt/Makefile.am b/src/pt/Makefile.am index 8e33b45c2..385bff672 100644 --- a/src/pt/Makefile.am +++ b/src/pt/Makefile.am | |||
@@ -22,6 +22,7 @@ gnunet_daemon_pt_SOURCES = \ | |||
22 | gnunet-daemon-pt.c | 22 | gnunet-daemon-pt.c |
23 | gnunet_daemon_pt_LDADD = \ | 23 | gnunet_daemon_pt_LDADD = \ |
24 | $(top_builddir)/src/vpn/libgnunetvpn.la \ | 24 | $(top_builddir)/src/vpn/libgnunetvpn.la \ |
25 | $(top_builddir)/src/mesh/libgnunetmesh.la \ | ||
25 | $(top_builddir)/src/dns/libgnunetdns.la \ | 26 | $(top_builddir)/src/dns/libgnunetdns.la \ |
26 | $(top_builddir)/src/dns/libgnunetdnsparser.la \ | 27 | $(top_builddir)/src/dns/libgnunetdnsparser.la \ |
27 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | 28 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ |
diff --git a/src/pt/gnunet-daemon-pt.c b/src/pt/gnunet-daemon-pt.c index 3d9128379..17ed6712d 100644 --- a/src/pt/gnunet-daemon-pt.c +++ b/src/pt/gnunet-daemon-pt.c | |||
@@ -27,12 +27,15 @@ | |||
27 | #include "gnunet_util_lib.h" | 27 | #include "gnunet_util_lib.h" |
28 | #include "gnunet_dns_service.h" | 28 | #include "gnunet_dns_service.h" |
29 | #include "gnunet_dnsparser_lib.h" | 29 | #include "gnunet_dnsparser_lib.h" |
30 | #include "gnunet_mesh_service.h" | ||
31 | #include "gnunet_tun_lib.h" | ||
30 | #include "gnunet_vpn_service.h" | 32 | #include "gnunet_vpn_service.h" |
31 | #include "gnunet_statistics_service.h" | 33 | #include "gnunet_statistics_service.h" |
34 | #include "gnunet_applications.h" | ||
32 | 35 | ||
33 | 36 | ||
34 | /** | 37 | /** |
35 | * After how long do we time out if we could not get an IP from VPN? | 38 | * After how long do we time out if we could not get an IP from VPN or MESH? |
36 | */ | 39 | */ |
37 | #define TIMEOUT GNUNET_TIME_UNIT_MINUTES | 40 | #define TIMEOUT GNUNET_TIME_UNIT_MINUTES |
38 | 41 | ||
@@ -75,9 +78,9 @@ enum RequestGroup | |||
75 | 78 | ||
76 | 79 | ||
77 | /** | 80 | /** |
78 | * Information tracked per DNS request that we are processing. | 81 | * Information tracked per DNS reply that we are processing. |
79 | */ | 82 | */ |
80 | struct RequestContext | 83 | struct ReplyContext |
81 | { | 84 | { |
82 | /** | 85 | /** |
83 | * Handle to submit the final result. | 86 | * Handle to submit the final result. |
@@ -113,6 +116,51 @@ struct RequestContext | |||
113 | 116 | ||
114 | 117 | ||
115 | /** | 118 | /** |
119 | * State we keep for a request that is going out via MESH. | ||
120 | */ | ||
121 | struct RequestContext | ||
122 | { | ||
123 | /** | ||
124 | * We keep these in a DLL. | ||
125 | */ | ||
126 | struct RequestContext *next; | ||
127 | |||
128 | /** | ||
129 | * We keep these in a DLL. | ||
130 | */ | ||
131 | struct RequestContext *prev; | ||
132 | |||
133 | /** | ||
134 | * Handle for interaction with DNS service. | ||
135 | */ | ||
136 | struct GNUNET_DNS_RequestHandle *rh; | ||
137 | |||
138 | /** | ||
139 | * Message we're sending out via MESH, allocated at the | ||
140 | * end of this struct. | ||
141 | */ | ||
142 | const struct GNUNET_MessageHeader *mesh_message; | ||
143 | |||
144 | /** | ||
145 | * Task used to abort this operation with timeout. | ||
146 | */ | ||
147 | GNUNET_SCHEDULER_TaskIdentifier timeout_task; | ||
148 | |||
149 | /** | ||
150 | * ID of the original DNS request (used to match the reply). | ||
151 | */ | ||
152 | uint16_t dns_id; | ||
153 | |||
154 | /** | ||
155 | * GNUNET_NO if this request is still in the transmit_queue, | ||
156 | * GNUNET_YES if we are in the receive_queue. | ||
157 | */ | ||
158 | int16_t was_transmitted; | ||
159 | |||
160 | }; | ||
161 | |||
162 | |||
163 | /** | ||
116 | * The handle to the configuration used throughout the process | 164 | * The handle to the configuration used throughout the process |
117 | */ | 165 | */ |
118 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | 166 | static const struct GNUNET_CONFIGURATION_Handle *cfg; |
@@ -123,14 +171,54 @@ static const struct GNUNET_CONFIGURATION_Handle *cfg; | |||
123 | static struct GNUNET_VPN_Handle *vpn_handle; | 171 | static struct GNUNET_VPN_Handle *vpn_handle; |
124 | 172 | ||
125 | /** | 173 | /** |
174 | * The handle to the MESH service | ||
175 | */ | ||
176 | static struct GNUNET_MESH_Handle *mesh_handle; | ||
177 | |||
178 | /** | ||
179 | * Tunnel we use for DNS requests over MESH. | ||
180 | */ | ||
181 | static struct GNUNET_MESH_Tunnel *mesh_tunnel; | ||
182 | |||
183 | /** | ||
184 | * Active transmission request with MESH (or NULL). | ||
185 | */ | ||
186 | static struct GNUNET_MESH_TransmitHandle *mesh_th; | ||
187 | |||
188 | /** | ||
189 | * Head of DLL of requests to be transmitted to mesh_tunnel. | ||
190 | */ | ||
191 | static struct RequestContext *transmit_queue_head; | ||
192 | |||
193 | /** | ||
194 | * Tail of DLL of requests to be transmitted to mesh_tunnel. | ||
195 | */ | ||
196 | static struct RequestContext *transmit_queue_tail; | ||
197 | |||
198 | /** | ||
199 | * Head of DLL of requests waiting for a response. | ||
200 | */ | ||
201 | static struct RequestContext *receive_queue_head; | ||
202 | |||
203 | /** | ||
204 | * Tail of DLL of requests waiting for a response. | ||
205 | */ | ||
206 | static struct RequestContext *receive_queue_tail; | ||
207 | |||
208 | /** | ||
126 | * Statistics. | 209 | * Statistics. |
127 | */ | 210 | */ |
128 | static struct GNUNET_STATISTICS_Handle *stats; | 211 | static struct GNUNET_STATISTICS_Handle *stats; |
129 | 212 | ||
130 | /** | 213 | /** |
131 | * The handle to DNS | 214 | * The handle to DNS post-resolution modifications. |
132 | */ | 215 | */ |
133 | static struct GNUNET_DNS_Handle *dns_handle; | 216 | static struct GNUNET_DNS_Handle *dns_post_handle; |
217 | |||
218 | /** | ||
219 | * The handle to DNS pre-resolution modifications. | ||
220 | */ | ||
221 | static struct GNUNET_DNS_Handle *dns_pre_handle; | ||
134 | 222 | ||
135 | /** | 223 | /** |
136 | * Are we doing IPv4-pt? | 224 | * Are we doing IPv4-pt? |
@@ -142,6 +230,17 @@ static int ipv4_pt; | |||
142 | */ | 230 | */ |
143 | static int ipv6_pt; | 231 | static int ipv6_pt; |
144 | 232 | ||
233 | /** | ||
234 | * Are we tunneling DNS queries? | ||
235 | */ | ||
236 | static int dns_tunnel; | ||
237 | |||
238 | /** | ||
239 | * Number of DNS exit peers we currently have in the mesh tunnel. | ||
240 | * Used to see if using the mesh tunnel makes any sense right now. | ||
241 | */ | ||
242 | static unsigned int dns_exit_available; | ||
243 | |||
145 | 244 | ||
146 | /** | 245 | /** |
147 | * We're done modifying all records in the response. Submit the reply | 246 | * We're done modifying all records in the response. Submit the reply |
@@ -150,7 +249,7 @@ static int ipv6_pt; | |||
150 | * @param rc context to process | 249 | * @param rc context to process |
151 | */ | 250 | */ |
152 | static void | 251 | static void |
153 | finish_request (struct RequestContext *rc) | 252 | finish_request (struct ReplyContext *rc) |
154 | { | 253 | { |
155 | char *buf; | 254 | char *buf; |
156 | size_t buf_len; | 255 | size_t buf_len; |
@@ -187,7 +286,7 @@ finish_request (struct RequestContext *rc) | |||
187 | * @param rc context to process | 286 | * @param rc context to process |
188 | */ | 287 | */ |
189 | static void | 288 | static void |
190 | submit_request (struct RequestContext *rc); | 289 | submit_request (struct ReplyContext *rc); |
191 | 290 | ||
192 | 291 | ||
193 | /** | 292 | /** |
@@ -197,7 +296,7 @@ submit_request (struct RequestContext *rc); | |||
197 | * record and then continue with 'submit_request' to look at | 296 | * record and then continue with 'submit_request' to look at |
198 | * the other records. | 297 | * the other records. |
199 | * | 298 | * |
200 | * @param cls our 'struct RequestContext' | 299 | * @param cls our 'struct ReplyContext' |
201 | * @param af address family, AF_INET or AF_INET6; AF_UNSPEC on error; | 300 | * @param af address family, AF_INET or AF_INET6; AF_UNSPEC on error; |
202 | * will match 'result_af' from the request | 301 | * will match 'result_af' from the request |
203 | * @param address IP address (struct in_addr or struct in_addr6, depending on 'af') | 302 | * @param address IP address (struct in_addr or struct in_addr6, depending on 'af') |
@@ -210,7 +309,7 @@ vpn_allocation_callback (void *cls, | |||
210 | int af, | 309 | int af, |
211 | const void *address) | 310 | const void *address) |
212 | { | 311 | { |
213 | struct RequestContext *rc = cls; | 312 | struct ReplyContext *rc = cls; |
214 | 313 | ||
215 | rc->rr = NULL; | 314 | rc->rr = NULL; |
216 | if (af == AF_UNSPEC) | 315 | if (af == AF_UNSPEC) |
@@ -252,7 +351,7 @@ vpn_allocation_callback (void *cls, | |||
252 | * @param rec record to modify | 351 | * @param rec record to modify |
253 | */ | 352 | */ |
254 | static void | 353 | static void |
255 | modify_address (struct RequestContext *rc, | 354 | modify_address (struct ReplyContext *rc, |
256 | struct GNUNET_DNSPARSER_Record *rec) | 355 | struct GNUNET_DNSPARSER_Record *rec) |
257 | { | 356 | { |
258 | int af; | 357 | int af; |
@@ -290,7 +389,7 @@ modify_address (struct RequestContext *rc, | |||
290 | * @param rc context to process | 389 | * @param rc context to process |
291 | */ | 390 | */ |
292 | static void | 391 | static void |
293 | submit_request (struct RequestContext *rc) | 392 | submit_request (struct ReplyContext *rc) |
294 | { | 393 | { |
295 | struct GNUNET_DNSPARSER_Record *ra; | 394 | struct GNUNET_DNSPARSER_Record *ra; |
296 | unsigned int ra_len; | 395 | unsigned int ra_len; |
@@ -377,22 +476,10 @@ work_test (const struct GNUNET_DNSPARSER_Record *ra, | |||
377 | 476 | ||
378 | 477 | ||
379 | /** | 478 | /** |
380 | * Signature of a function that is called whenever the DNS service | 479 | * This function is called AFTER we got an IP address for a |
381 | * encounters a DNS request and needs to do something with it. The | 480 | * DNS request. Now, the PT daemon has the chance to substitute |
382 | * function has then the chance to generate or modify the response by | 481 | * the IP address with one from the VPN range to tunnel requests |
383 | * calling one of the three "GNUNET_DNS_request_*" continuations. | 482 | * destined for this IP address via VPN and MESH. |
384 | * | ||
385 | * When a request is intercepted, this function is called first to | ||
386 | * give the client a chance to do the complete address resolution; | ||
387 | * "rdata" will be NULL for this first call for a DNS request, unless | ||
388 | * some other client has already filled in a response. | ||
389 | * | ||
390 | * If multiple clients exist, all of them are called before the global | ||
391 | * DNS. The global DNS is only called if all of the clients' | ||
392 | * functions call GNUNET_DNS_request_forward. Functions that call | ||
393 | * GNUNET_DNS_request_forward will be called again before a final | ||
394 | * response is returned to the application. If any of the clients' | ||
395 | * functions call GNUNET_DNS_request_drop, the response is dropped. | ||
396 | * | 483 | * |
397 | * @param cls closure | 484 | * @param cls closure |
398 | * @param rh request handle to user for reply | 485 | * @param rh request handle to user for reply |
@@ -400,17 +487,17 @@ work_test (const struct GNUNET_DNSPARSER_Record *ra, | |||
400 | * @param request udp payload of the DNS request | 487 | * @param request udp payload of the DNS request |
401 | */ | 488 | */ |
402 | static void | 489 | static void |
403 | dns_request_handler (void *cls, | 490 | dns_post_request_handler (void *cls, |
404 | struct GNUNET_DNS_RequestHandle *rh, | 491 | struct GNUNET_DNS_RequestHandle *rh, |
405 | size_t request_length, | 492 | size_t request_length, |
406 | const char *request) | 493 | const char *request) |
407 | { | 494 | { |
408 | struct GNUNET_DNSPARSER_Packet *dns; | 495 | struct GNUNET_DNSPARSER_Packet *dns; |
409 | struct RequestContext *rc; | 496 | struct ReplyContext *rc; |
410 | int work; | 497 | int work; |
411 | 498 | ||
412 | GNUNET_STATISTICS_update (stats, | 499 | GNUNET_STATISTICS_update (stats, |
413 | gettext_noop ("# DNS requests intercepted"), | 500 | gettext_noop ("# DNS replies intercepted"), |
414 | 1, GNUNET_NO); | 501 | 1, GNUNET_NO); |
415 | dns = GNUNET_DNSPARSER_parse (request, request_length); | 502 | dns = GNUNET_DNSPARSER_parse (request, request_length); |
416 | if (NULL == dns) | 503 | if (NULL == dns) |
@@ -429,7 +516,7 @@ dns_request_handler (void *cls, | |||
429 | GNUNET_DNS_request_forward (rh); | 516 | GNUNET_DNS_request_forward (rh); |
430 | return; | 517 | return; |
431 | } | 518 | } |
432 | rc = GNUNET_malloc (sizeof (struct RequestContext)); | 519 | rc = GNUNET_malloc (sizeof (struct ReplyContext)); |
433 | rc->rh = rh; | 520 | rc->rh = rh; |
434 | rc->dns = dns; | 521 | rc->dns = dns; |
435 | rc->offset = 0; | 522 | rc->offset = 0; |
@@ -439,6 +526,292 @@ dns_request_handler (void *cls, | |||
439 | 526 | ||
440 | 527 | ||
441 | /** | 528 | /** |
529 | * Transmit a DNS request via MESH and move the request | ||
530 | * handle to the receive queue. | ||
531 | * | ||
532 | * @param cls NULL | ||
533 | * @param size number of bytes available in buf | ||
534 | * @param buf where to copy the message | ||
535 | * @return number of bytes written to buf | ||
536 | */ | ||
537 | static size_t | ||
538 | transmit_dns_request_to_mesh (void *cls, | ||
539 | size_t size, | ||
540 | void *buf) | ||
541 | { | ||
542 | struct RequestContext *rc; | ||
543 | size_t mlen; | ||
544 | |||
545 | mesh_th = NULL; | ||
546 | if (NULL == (rc = transmit_queue_head)) | ||
547 | return 0; | ||
548 | mlen = ntohs (rc->mesh_message->size); | ||
549 | if (mlen > size) | ||
550 | { | ||
551 | mesh_th = GNUNET_MESH_notify_transmit_ready (mesh_tunnel, | ||
552 | GNUNET_NO, 0, | ||
553 | TIMEOUT, | ||
554 | NULL, mlen, | ||
555 | &transmit_dns_request_to_mesh, | ||
556 | NULL); | ||
557 | return 0; | ||
558 | } | ||
559 | GNUNET_assert (GNUNET_NO == rc->was_transmitted); | ||
560 | memcpy (buf, rc->mesh_message, mlen); | ||
561 | GNUNET_CONTAINER_DLL_remove (transmit_queue_head, | ||
562 | transmit_queue_tail, | ||
563 | rc); | ||
564 | rc->was_transmitted = GNUNET_YES; | ||
565 | GNUNET_CONTAINER_DLL_insert (receive_queue_head, | ||
566 | receive_queue_tail, | ||
567 | rc); | ||
568 | rc = transmit_queue_head; | ||
569 | if (NULL != rc) | ||
570 | mesh_th = GNUNET_MESH_notify_transmit_ready (mesh_tunnel, | ||
571 | GNUNET_NO, 0, | ||
572 | TIMEOUT, | ||
573 | NULL, ntohs (rc->mesh_message->size), | ||
574 | &transmit_dns_request_to_mesh, | ||
575 | NULL); | ||
576 | return mlen; | ||
577 | } | ||
578 | |||
579 | |||
580 | /** | ||
581 | * Task run if the time to answer a DNS request via MESH is over. | ||
582 | * | ||
583 | * @param cls the 'struct RequestContext' to abort | ||
584 | * @param tc scheduler context | ||
585 | */ | ||
586 | static void | ||
587 | timeout_request (void *cls, | ||
588 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
589 | { | ||
590 | struct RequestContext *rc = cls; | ||
591 | |||
592 | if (rc->was_transmitted) | ||
593 | GNUNET_CONTAINER_DLL_remove (receive_queue_head, | ||
594 | receive_queue_tail, | ||
595 | rc); | ||
596 | else | ||
597 | GNUNET_CONTAINER_DLL_remove (transmit_queue_head, | ||
598 | transmit_queue_tail, | ||
599 | rc); | ||
600 | GNUNET_STATISTICS_update (stats, | ||
601 | gettext_noop ("# DNS requests dropped (timeout)"), | ||
602 | 1, GNUNET_NO); | ||
603 | GNUNET_DNS_request_drop (rc->rh); | ||
604 | GNUNET_free (rc); | ||
605 | } | ||
606 | |||
607 | |||
608 | /** | ||
609 | * This function is called *before* the DNS request has been | ||
610 | * given to a "local" DNS resolver. Tunneling for DNS requests | ||
611 | * was enabled, so we now need to send the request via some MESH | ||
612 | * tunnel to a DNS EXIT for resolution. | ||
613 | * | ||
614 | * @param cls closure | ||
615 | * @param rh request handle to user for reply | ||
616 | * @param request_length number of bytes in request | ||
617 | * @param request udp payload of the DNS request | ||
618 | */ | ||
619 | static void | ||
620 | dns_pre_request_handler (void *cls, | ||
621 | struct GNUNET_DNS_RequestHandle *rh, | ||
622 | size_t request_length, | ||
623 | const char *request) | ||
624 | { | ||
625 | struct RequestContext *rc; | ||
626 | size_t mlen; | ||
627 | struct GNUNET_MessageHeader hdr; | ||
628 | struct GNUNET_TUN_DnsHeader dns; | ||
629 | |||
630 | GNUNET_STATISTICS_update (stats, | ||
631 | gettext_noop ("# DNS requests intercepted"), | ||
632 | 1, GNUNET_NO); | ||
633 | if (0 == dns_exit_available) | ||
634 | { | ||
635 | GNUNET_STATISTICS_update (stats, | ||
636 | gettext_noop ("# DNS requests dropped (DNS mesh tunnel down)"), | ||
637 | 1, GNUNET_NO); | ||
638 | GNUNET_DNS_request_drop (rh); | ||
639 | return; | ||
640 | } | ||
641 | if (request_length < sizeof (dns)) | ||
642 | { | ||
643 | GNUNET_STATISTICS_update (stats, | ||
644 | gettext_noop ("# DNS requests dropped (malformed)"), | ||
645 | 1, GNUNET_NO); | ||
646 | GNUNET_DNS_request_drop (rh); | ||
647 | return; | ||
648 | } | ||
649 | memcpy (&dns, request, sizeof (dns)); | ||
650 | GNUNET_assert (NULL != mesh_tunnel); | ||
651 | mlen = sizeof (struct GNUNET_MessageHeader) + request_length; | ||
652 | rc = GNUNET_malloc (sizeof (struct RequestContext) + mlen); | ||
653 | rc->rh = rh; | ||
654 | rc->mesh_message = (const struct GNUNET_MessageHeader*) &rc[1]; | ||
655 | rc->timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
656 | &timeout_request, | ||
657 | rc); | ||
658 | rc->dns_id = dns.id; | ||
659 | hdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_DNS_TO_INTERNET); | ||
660 | hdr.size = htons (mlen); | ||
661 | memcpy (&rc[1], &hdr, sizeof (struct GNUNET_MessageHeader)); | ||
662 | memcpy (&(((char*)&rc[1])[sizeof (struct GNUNET_MessageHeader)]), | ||
663 | request, | ||
664 | request_length); | ||
665 | GNUNET_CONTAINER_DLL_insert_tail (transmit_queue_head, | ||
666 | transmit_queue_tail, | ||
667 | rc); | ||
668 | if (NULL == mesh_th) | ||
669 | mesh_th = GNUNET_MESH_notify_transmit_ready (mesh_tunnel, | ||
670 | GNUNET_NO, 0, | ||
671 | TIMEOUT, | ||
672 | NULL, mlen, | ||
673 | &transmit_dns_request_to_mesh, | ||
674 | NULL); | ||
675 | } | ||
676 | |||
677 | |||
678 | /** | ||
679 | * Process a request via mesh to perform a DNS query. | ||
680 | * | ||
681 | * @param cls closure, NULL | ||
682 | * @param tunnel connection to the other end | ||
683 | * @param tunnel_ctx pointer to our 'struct TunnelState *' | ||
684 | * @param sender who sent the message | ||
685 | * @param message the actual message | ||
686 | * @param atsi performance data for the connection | ||
687 | * @return GNUNET_OK to keep the connection open, | ||
688 | * GNUNET_SYSERR to close it (signal serious error) | ||
689 | */ | ||
690 | static int | ||
691 | receive_dns_response (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, | ||
692 | void **tunnel_ctx, | ||
693 | const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED, | ||
694 | const struct GNUNET_MessageHeader *message, | ||
695 | const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED) | ||
696 | { | ||
697 | struct GNUNET_TUN_DnsHeader dns; | ||
698 | size_t mlen; | ||
699 | struct RequestContext *rc; | ||
700 | |||
701 | mlen = ntohs (message->size); | ||
702 | mlen -= sizeof (struct GNUNET_MessageHeader); | ||
703 | if (mlen < sizeof (struct GNUNET_TUN_DnsHeader)) | ||
704 | { | ||
705 | GNUNET_break_op (0); | ||
706 | return GNUNET_SYSERR; | ||
707 | } | ||
708 | memcpy (&dns, &message[1], sizeof (dns)); | ||
709 | for (rc = receive_queue_head; NULL != rc; rc = rc->next) | ||
710 | { | ||
711 | GNUNET_assert (GNUNET_YES == rc->was_transmitted); | ||
712 | if (dns.id == rc->dns_id) | ||
713 | { | ||
714 | GNUNET_STATISTICS_update (stats, | ||
715 | gettext_noop ("# DNS replies received"), | ||
716 | 1, GNUNET_NO); | ||
717 | GNUNET_DNS_request_answer (rc->rh, | ||
718 | mlen, | ||
719 | (const void*) &message[1]); | ||
720 | GNUNET_CONTAINER_DLL_remove (receive_queue_head, | ||
721 | receive_queue_tail, | ||
722 | rc); | ||
723 | GNUNET_SCHEDULER_cancel (rc->timeout_task); | ||
724 | GNUNET_free (rc); | ||
725 | return GNUNET_OK; | ||
726 | } | ||
727 | } | ||
728 | GNUNET_STATISTICS_update (stats, | ||
729 | gettext_noop ("# DNS replies dropped (too late?)"), | ||
730 | 1, GNUNET_NO); | ||
731 | return GNUNET_OK; | ||
732 | } | ||
733 | |||
734 | |||
735 | /** | ||
736 | * The MESH DNS tunnel went down. Abort all pending DNS | ||
737 | * requests (we're unlikely to get an answer in time). | ||
738 | */ | ||
739 | static void | ||
740 | abort_all_requests () | ||
741 | { | ||
742 | struct RequestContext *rc; | ||
743 | |||
744 | while (NULL != (rc = receive_queue_head)) | ||
745 | { | ||
746 | GNUNET_STATISTICS_update (stats, | ||
747 | gettext_noop ("# DNS requests aborted (tunnel down)"), | ||
748 | 1, GNUNET_NO); | ||
749 | GNUNET_CONTAINER_DLL_remove (receive_queue_head, | ||
750 | receive_queue_tail, | ||
751 | rc); | ||
752 | GNUNET_DNS_request_drop (rc->rh); | ||
753 | GNUNET_SCHEDULER_cancel (rc->timeout_task); | ||
754 | GNUNET_free (rc); | ||
755 | } | ||
756 | while (NULL != (rc = transmit_queue_head)) | ||
757 | { | ||
758 | GNUNET_STATISTICS_update (stats, | ||
759 | gettext_noop ("# DNS requests aborted (tunnel down)"), | ||
760 | 1, GNUNET_NO); | ||
761 | GNUNET_CONTAINER_DLL_remove (transmit_queue_head, | ||
762 | transmit_queue_tail, | ||
763 | rc); | ||
764 | GNUNET_DNS_request_drop (rc->rh); | ||
765 | GNUNET_SCHEDULER_cancel (rc->timeout_task); | ||
766 | GNUNET_free (rc); | ||
767 | } | ||
768 | } | ||
769 | |||
770 | |||
771 | /** | ||
772 | * Method called whenever a peer has disconnected from the tunnel. | ||
773 | * | ||
774 | * @param cls closure | ||
775 | * @param peer peer identity the tunnel stopped working with | ||
776 | */ | ||
777 | static void | ||
778 | mesh_disconnect_handler (void *cls, | ||
779 | const struct | ||
780 | GNUNET_PeerIdentity * peer) | ||
781 | { | ||
782 | GNUNET_assert (dns_exit_available > 0); | ||
783 | dns_exit_available--; | ||
784 | if (0 == dns_exit_available) | ||
785 | { | ||
786 | if (NULL != mesh_th) | ||
787 | { | ||
788 | GNUNET_MESH_notify_transmit_ready_cancel (mesh_th); | ||
789 | mesh_th = NULL; | ||
790 | } | ||
791 | abort_all_requests (); | ||
792 | } | ||
793 | } | ||
794 | |||
795 | |||
796 | /** | ||
797 | * Method called whenever a peer has connected to the tunnel. | ||
798 | * | ||
799 | * @param cls closure | ||
800 | * @param peer peer identity the tunnel was created to, NULL on timeout | ||
801 | * @param atsi performance data for the connection | ||
802 | */ | ||
803 | static void | ||
804 | mesh_connect_handler (void *cls, | ||
805 | const struct GNUNET_PeerIdentity | ||
806 | * peer, | ||
807 | const struct | ||
808 | GNUNET_ATS_Information * atsi) | ||
809 | { | ||
810 | dns_exit_available++; | ||
811 | } | ||
812 | |||
813 | |||
814 | /** | ||
442 | * Function scheduled as very last function, cleans up after us | 815 | * Function scheduled as very last function, cleans up after us |
443 | */ | 816 | */ |
444 | static void | 817 | static void |
@@ -452,10 +825,31 @@ cleanup (void *cls GNUNET_UNUSED, | |||
452 | GNUNET_VPN_disconnect (vpn_handle); | 825 | GNUNET_VPN_disconnect (vpn_handle); |
453 | vpn_handle = NULL; | 826 | vpn_handle = NULL; |
454 | } | 827 | } |
455 | if (dns_handle != NULL) | 828 | if (NULL != mesh_th) |
829 | { | ||
830 | GNUNET_MESH_notify_transmit_ready_cancel (mesh_th); | ||
831 | mesh_th = NULL; | ||
832 | } | ||
833 | if (NULL != mesh_tunnel) | ||
834 | { | ||
835 | GNUNET_MESH_tunnel_destroy (mesh_tunnel); | ||
836 | mesh_tunnel = NULL; | ||
837 | } | ||
838 | if (mesh_handle != NULL) | ||
839 | { | ||
840 | GNUNET_MESH_disconnect (mesh_handle); | ||
841 | mesh_handle = NULL; | ||
842 | } | ||
843 | abort_all_requests (); | ||
844 | if (dns_post_handle != NULL) | ||
845 | { | ||
846 | GNUNET_DNS_disconnect (dns_post_handle); | ||
847 | dns_post_handle = NULL; | ||
848 | } | ||
849 | if (dns_pre_handle != NULL) | ||
456 | { | 850 | { |
457 | GNUNET_DNS_disconnect (dns_handle); | 851 | GNUNET_DNS_disconnect (dns_pre_handle); |
458 | dns_handle = NULL; | 852 | dns_pre_handle = NULL; |
459 | } | 853 | } |
460 | if (stats != NULL) | 854 | if (stats != NULL) |
461 | { | 855 | { |
@@ -482,7 +876,8 @@ run (void *cls, char *const *args GNUNET_UNUSED, | |||
482 | stats = GNUNET_STATISTICS_create ("pt", cfg); | 876 | stats = GNUNET_STATISTICS_create ("pt", cfg); |
483 | ipv4_pt = GNUNET_CONFIGURATION_get_value_yesno (cfg, "pt", "TUNNEL_IPV4"); | 877 | ipv4_pt = GNUNET_CONFIGURATION_get_value_yesno (cfg, "pt", "TUNNEL_IPV4"); |
484 | ipv6_pt = GNUNET_CONFIGURATION_get_value_yesno (cfg, "pt", "TUNNEL_IPV6"); | 878 | ipv6_pt = GNUNET_CONFIGURATION_get_value_yesno (cfg, "pt", "TUNNEL_IPV6"); |
485 | if (! (ipv4_pt || ipv6_pt)) | 879 | dns_tunnel = GNUNET_CONFIGURATION_get_value_yesno (cfg, "pt", "TUNNEL_DNS"); |
880 | if (! (ipv4_pt || ipv6_pt || dns_tunnel)) | ||
486 | { | 881 | { |
487 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 882 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
488 | _("No useful service enabled. Exiting.\n")); | 883 | _("No useful service enabled. Exiting.\n")); |
@@ -490,26 +885,69 @@ run (void *cls, char *const *args GNUNET_UNUSED, | |||
490 | return; | 885 | return; |
491 | } | 886 | } |
492 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls); | 887 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls); |
493 | dns_handle | 888 | if (ipv4_pt || ipv6_pt) |
494 | = GNUNET_DNS_connect (cfg, | ||
495 | GNUNET_DNS_FLAG_POST_RESOLUTION, | ||
496 | &dns_request_handler, NULL); | ||
497 | if (NULL == dns_handle) | ||
498 | { | 889 | { |
499 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 890 | dns_post_handle |
500 | _("Failed to connect to %s service. Exiting.\n"), | 891 | = GNUNET_DNS_connect (cfg, |
501 | "DNS"); | 892 | GNUNET_DNS_FLAG_POST_RESOLUTION, |
502 | GNUNET_SCHEDULER_shutdown (); | 893 | &dns_post_request_handler, NULL); |
503 | return; | 894 | if (NULL == dns_post_handle) |
895 | { | ||
896 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
897 | _("Failed to connect to %s service. Exiting.\n"), | ||
898 | "DNS"); | ||
899 | GNUNET_SCHEDULER_shutdown (); | ||
900 | return; | ||
901 | } | ||
902 | vpn_handle = GNUNET_VPN_connect (cfg); | ||
903 | if (NULL == vpn_handle) | ||
904 | { | ||
905 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
906 | _("Failed to connect to %s service. Exiting.\n"), | ||
907 | "VPN"); | ||
908 | GNUNET_SCHEDULER_shutdown (); | ||
909 | return; | ||
910 | } | ||
504 | } | 911 | } |
505 | vpn_handle = GNUNET_VPN_connect (cfg); | 912 | if (dns_tunnel) |
506 | if (NULL == vpn_handle) | ||
507 | { | 913 | { |
508 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 914 | static struct GNUNET_MESH_MessageHandler mesh_handlers[] = { |
509 | _("Failed to connect to %s service. Exiting.\n"), | 915 | {&receive_dns_response, GNUNET_MESSAGE_TYPE_VPN_DNS_FROM_INTERNET, 0}, |
510 | "VPN"); | 916 | {NULL, 0, 0} |
511 | GNUNET_SCHEDULER_shutdown (); | 917 | }; |
512 | return; | 918 | static GNUNET_MESH_ApplicationType mesh_types[] = { |
919 | GNUNET_APPLICATION_TYPE_END | ||
920 | }; | ||
921 | |||
922 | dns_pre_handle | ||
923 | = GNUNET_DNS_connect (cfg, | ||
924 | GNUNET_DNS_FLAG_PRE_RESOLUTION, | ||
925 | &dns_pre_request_handler, NULL); | ||
926 | if (NULL == dns_pre_handle) | ||
927 | { | ||
928 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
929 | _("Failed to connect to %s service. Exiting.\n"), | ||
930 | "DNS"); | ||
931 | GNUNET_SCHEDULER_shutdown (); | ||
932 | return; | ||
933 | } | ||
934 | mesh_handle = GNUNET_MESH_connect (cfg, 1, NULL, NULL, NULL, | ||
935 | mesh_handlers, mesh_types); | ||
936 | if (NULL == mesh_handle) | ||
937 | { | ||
938 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
939 | _("Failed to connect to %s service. Exiting.\n"), | ||
940 | "MESH"); | ||
941 | GNUNET_SCHEDULER_shutdown (); | ||
942 | return; | ||
943 | } | ||
944 | mesh_tunnel = GNUNET_MESH_tunnel_create (mesh_handle, | ||
945 | NULL, | ||
946 | &mesh_connect_handler, | ||
947 | &mesh_disconnect_handler, | ||
948 | NULL); | ||
949 | GNUNET_MESH_peer_request_connect_by_type (mesh_tunnel, | ||
950 | GNUNET_APPLICATION_TYPE_INTERNET_RESOLVER); | ||
513 | } | 951 | } |
514 | } | 952 | } |
515 | 953 | ||
diff --git a/src/pt/pt.conf b/src/pt/pt.conf index f5169f6ee..39c1fb60c 100644 --- a/src/pt/pt.conf +++ b/src/pt/pt.conf | |||
@@ -8,3 +8,6 @@ TUNNEL_IPV4 = NO | |||
8 | # Set this to YES to tunnel IPv6 traffic over GNUnet | 8 | # Set this to YES to tunnel IPv6 traffic over GNUnet |
9 | TUNNEL_IPV6 = NO | 9 | TUNNEL_IPV6 = NO |
10 | 10 | ||
11 | # Set this to YES to tunnel DNS traffic over GNUnet | ||
12 | TUNNEL_DNS = NO | ||
13 | |||