GNUnet 0.22.2
gnunet-service-dns.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
39#include "platform.h"
40#include "gnunet_util_lib.h"
41#include "gnunet_protocols.h"
42#include "dns.h"
43#include "gnunet_dns_service.h"
45
49#define DNS_PORT 53
50
51
55#define LOG(kind, ...) \
56 GNUNET_log_from (kind, "dns", __VA_ARGS__);
57
58
63{
68
74
80
85
92
98
102 RP_DROP
104
105
110{
115
120
125
130
135};
136
137
142{
148
153 char *payload;
154
160
164 struct sockaddr_storage src_addr;
165
169 struct sockaddr_storage dst_addr;
170
176 uint64_t request_id;
177
182
187
192};
193
194
198static int global_ret;
199
203static const struct GNUNET_CONFIGURATION_Handle *cfg;
204
209
214
218static char *helper_argv[8];
219
224
229
233static struct RequestRecord requests[UINT16_MAX + 1];
234
238static uint64_t request_id_gen;
239
244
245
251static void
253{
254 GNUNET_free (rr->payload);
255 rr->payload = NULL;
256 rr->payload_length = 0;
259 0);
260}
261
262
268static void
270{
271 if (NULL != hijacker)
272 {
274 hijacker = NULL;
275 }
276 for (unsigned int i = 0; i < 8; i++)
278 for (unsigned int i = 0; i <= UINT16_MAX; i++)
279 cleanup_rr (&requests[i]);
280 if (NULL != stats)
281 {
283 GNUNET_NO);
284 stats = NULL;
285 }
286 if (NULL != dnsstub)
287 {
289 dnsstub = NULL;
290 }
291}
292
293
299static void
301{
302 struct GNUNET_MessageHeader *hdr;
303 size_t reply_len;
304 uint16_t source_port;
305 uint16_t destination_port;
306
309 0);
310 if (RP_RESPONSE_MONITOR != rr->phase)
311 {
312 /* no response, drop */
314 "Got no response for request %llu, dropping\n",
315 (unsigned long long) rr->request_id);
316 cleanup_rr (rr);
317 return;
318 }
319
321 "Transmitting response for request %llu\n",
322 (unsigned long long) rr->request_id);
323 /* send response via hijacker */
324 reply_len = sizeof(struct GNUNET_MessageHeader);
325 reply_len += sizeof(struct GNUNET_TUN_Layer2PacketHeader);
326 switch (rr->src_addr.ss_family)
327 {
328 case AF_INET:
329 reply_len += sizeof(struct GNUNET_TUN_IPv4Header);
330 break;
331
332 case AF_INET6:
333 reply_len += sizeof(struct GNUNET_TUN_IPv6Header);
334 break;
335
336 default:
337 GNUNET_break (0);
338 cleanup_rr (rr);
339 return;
340 }
341 reply_len += sizeof(struct GNUNET_TUN_UdpHeader);
342 reply_len += rr->payload_length;
343 if (reply_len >= GNUNET_MAX_MESSAGE_SIZE)
344 {
345 /* response too big, drop */
346 GNUNET_break (0); /* how can this be? */
347 cleanup_rr (rr);
348 return;
349 }
350 {
351 char buf[reply_len] GNUNET_ALIGN;
352 size_t off;
353 struct GNUNET_TUN_IPv4Header ip4;
354 struct GNUNET_TUN_IPv6Header ip6;
355
356 /* first, GNUnet message header */
357 hdr = (struct GNUNET_MessageHeader*) buf;
359 hdr->size = htons ((uint16_t) reply_len);
360 off = sizeof(struct GNUNET_MessageHeader);
361
362 /* first, TUN header */
363 {
365
366 tun.flags = htons (0);
367 if (rr->src_addr.ss_family == AF_INET)
368 tun.proto = htons (ETH_P_IPV4);
369 else
370 tun.proto = htons (ETH_P_IPV6);
371 GNUNET_memcpy (&buf[off],
372 &tun,
373 sizeof(struct GNUNET_TUN_Layer2PacketHeader));
374 off += sizeof(struct GNUNET_TUN_Layer2PacketHeader);
375 }
376
377 /* now IP header */
378 switch (rr->src_addr.ss_family)
379 {
380 case AF_INET:
381 {
382 struct sockaddr_in *src = (struct sockaddr_in *) &rr->src_addr;
383 struct sockaddr_in *dst = (struct sockaddr_in *) &rr->dst_addr;
384
385 source_port = dst->sin_port;
386 destination_port = src->sin_port;
388 IPPROTO_UDP,
389 reply_len - off - sizeof(struct
391 &dst->sin_addr,
392 &src->sin_addr);
393 GNUNET_memcpy (&buf[off],
394 &ip4,
395 sizeof(ip4));
396 off += sizeof(ip4);
397 }
398 break;
399
400 case AF_INET6:
401 {
402 struct sockaddr_in6 *src = (struct sockaddr_in6 *) &rr->src_addr;
403 struct sockaddr_in6 *dst = (struct sockaddr_in6 *) &rr->dst_addr;
404
405 source_port = dst->sin6_port;
406 destination_port = src->sin6_port;
408 IPPROTO_UDP,
409 reply_len - off - sizeof(struct
411 &dst->sin6_addr,
412 &src->sin6_addr);
413 GNUNET_memcpy (&buf[off],
414 &ip6,
415 sizeof(ip6));
416 off += sizeof(ip6);
417 }
418 break;
419
420 default:
421 GNUNET_assert (0);
422 }
423
424 /* now UDP header */
425 {
427
428 udp.source_port = source_port;
429 udp.destination_port = destination_port;
430 udp.len = htons (reply_len - off);
431 if (AF_INET == rr->src_addr.ss_family)
433 &udp,
434 rr->payload,
435 rr->payload_length);
436 else
438 &udp,
439 rr->payload,
440 rr->payload_length);
441 GNUNET_memcpy (&buf[off],
442 &udp,
443 sizeof(udp));
444 off += sizeof(udp);
445 }
446
447 /* now DNS payload */
448 {
449 GNUNET_memcpy (&buf[off], rr->payload, rr->payload_length);
450 off += rr->payload_length;
451 }
452 /* final checks & sending */
453 GNUNET_assert (off == reply_len);
455 hdr,
457 NULL, NULL);
460 "# DNS requests answered via TUN interface"),
461 1, GNUNET_NO);
462 }
463 /* clean up, we're done */
464 cleanup_rr (rr);
465}
466
467
475static void
477 struct ClientRecord *cr)
478{
479 struct GNUNET_MQ_Envelope *env;
480 struct GNUNET_DNS_Request *req;
481
482 if (sizeof(struct GNUNET_DNS_Request) + rr->payload_length >=
484 {
485 GNUNET_break (0);
486 cleanup_rr (rr);
487 return;
488 }
490 "Sending information about request %llu to local client\n",
491 (unsigned long long) rr->request_id);
493 rr->payload_length,
495 req->reserved = htonl (0);
496 req->request_id = rr->request_id;
497 GNUNET_memcpy (&req[1],
498 rr->payload,
499 rr->payload_length);
500 GNUNET_MQ_send (cr->mq,
501 env);
502}
503
504
513static void
514process_dns_result (void *cls,
515 const struct GNUNET_TUN_DnsHeader *dns,
516 size_t r);
517
518
525static void
527{
528 struct ClientRecord *cr;
529 int nz;
530
531 if (rr->phase == RP_DROP)
532 {
533 cleanup_rr (rr);
534 return;
535 }
536 nz = -1;
537 for (unsigned int j = 0; j < rr->client_wait_list_length; j++)
538 {
539 if (NULL != rr->client_wait_list[j])
540 {
541 nz = (int) j;
542 break;
543 }
544 }
545 if (-1 != nz)
546 {
548 rr->client_wait_list[nz]);
549 return;
550 }
551 /* done with current phase, advance! */
553 "Request %llu now in phase %d\n",
554 (unsigned long long) rr->request_id,
555 rr->phase);
556 switch (rr->phase)
557 {
558 case RP_INIT:
560 for (cr = clients_head; NULL != cr; cr = cr->next)
561 {
562 if (0 != (cr->flags & GNUNET_DNS_FLAG_REQUEST_MONITOR))
565 cr);
566 }
567 next_phase (rr);
568 return;
569
571 rr->phase = RP_QUERY;
572 for (cr = clients_head; NULL != cr; cr = cr->next)
573 {
574 if (0 != (cr->flags & GNUNET_DNS_FLAG_PRE_RESOLUTION))
577 cr);
578 }
579 next_phase (rr);
580 return;
581
582 case RP_QUERY:
583#if 0
584 /* TODO: optionally, use this to forward DNS requests to the
585 * original* DNS server instead of the one we have configured...
586 (but then we need to create a fresh dnsstub for each request
587 * and* manage the timeout) */
588 switch (rr->dst_addr.ss_family)
589 {
590 case AF_INET:
591 salen = sizeof(struct sockaddr_in);
592 sa = (const struct sockaddr *) &rr->dst_addr;
593 break;
594
595 case AF_INET6:
596 salen = sizeof(struct sockaddr_in6);
597 sa = (const struct sockaddr *) &rr->dst_addr;
598 break;
599
600 default:
601 GNUNET_assert (0);
602 }
603#endif
606 rr->payload,
607 rr->payload_length,
609 NULL);
610 if (NULL == rr->rs)
611 {
614 "# DNS exit failed (failed to open socket)"),
615 1,
616 GNUNET_NO);
617 cleanup_rr (rr);
618 return;
619 }
620 return;
621
622 case RP_INTERNET_DNS:
623 rr->phase = RP_MODIFY;
624 for (cr = clients_head; NULL != cr; cr = cr->next)
625 {
626 if (0 != (cr->flags & GNUNET_DNS_FLAG_POST_RESOLUTION))
629 cr);
630 }
631 next_phase (rr);
632 return;
633
634 case RP_MODIFY:
636 for (cr = clients_head; NULL != cr; cr = cr->next)
637 {
641 cr);
642 }
643 next_phase (rr);
644 return;
645
647 request_done (rr);
648 break;
649
650 case RP_DROP:
651 cleanup_rr (rr);
652 break;
653
654 default:
655 GNUNET_break (0);
656 cleanup_rr (rr);
657 break;
658 }
659}
660
661
670static void *
672 struct GNUNET_SERVICE_Client *client,
673 struct GNUNET_MQ_Handle *mq)
674{
675 struct ClientRecord *cr = cls;
676
677 cr = GNUNET_new (struct ClientRecord);
678 cr->client = client;
679 cr->mq = mq;
682 cr);
683 return cr;
684}
685
686
694static void
697 void *app_ctx)
698{
699 struct ClientRecord *cr = app_ctx;
700 struct RequestRecord *rr;
701
704 cr);
705 for (unsigned int i = 0; i < UINT16_MAX; i++)
706 {
707 rr = &requests[i];
708 if (0 == rr->client_wait_list_length)
709 continue; /* not in use */
710 for (unsigned int j = 0; j < rr->client_wait_list_length; j++)
711 {
712 if (rr->client_wait_list[j] == cr)
713 {
714 rr->client_wait_list[j] = NULL;
715 next_phase (rr);
716 }
717 }
718 }
719 GNUNET_free (cr);
720}
721
722
731static void
733 const struct GNUNET_TUN_DnsHeader *dns,
734 size_t r)
735{
736 struct RequestRecord *rr;
737
739 "Processing DNS result from stub resolver\n");
740 GNUNET_assert (NULL == cls);
741 if (NULL == dns)
742 return; /* ignore */
743
744 rr = &requests[dns->id];
745 if (rr->phase != RP_INTERNET_DNS)
746 {
747 /* unexpected / bogus reply */
750 "# External DNS response discarded (no matching request)"),
751 1, GNUNET_NO);
753 "Received DNS reply that does not match any pending request. Dropping.\n");
754 return;
755 }
757 "Got a response from the stub resolver for DNS request %llu intercepted locally!\n",
758 (unsigned long long) rr->request_id);
759 GNUNET_free (rr->payload);
760 rr->payload = GNUNET_malloc (r);
762 dns,
763 r);
764 rr->payload_length = r;
765 next_phase (rr);
766}
767
768
775static void
777 const struct GNUNET_DNS_Register *reg)
778{
779 struct ClientRecord *cr = cls;
780
781 cr->flags = ntohl (reg->flags);
783}
784
785
793static int
795 const struct GNUNET_DNS_Response *resp)
796{
797 return GNUNET_OK; /* any payload is acceptable */
798}
799
800
807static void
809 const struct GNUNET_DNS_Response *resp)
810{
811 struct ClientRecord *cr = cls;
812 struct RequestRecord *rr;
813 uint16_t msize;
814 uint16_t off;
815
816 msize = ntohs (resp->header.size);
817 off = (uint16_t) resp->request_id;
818 rr = &requests[off];
820 "Received DNS response with ID %llu from local client!\n",
821 (unsigned long long) resp->request_id);
822 if (rr->request_id != resp->request_id)
823 {
826 "# Client response discarded (no matching request)"),
827 1,
828 GNUNET_NO);
830 return;
831 }
832 for (unsigned int i = 0; i < rr->client_wait_list_length; i++)
833 {
834 if (NULL == rr->client_wait_list[i])
835 continue;
836 if (rr->client_wait_list[i] != cr)
837 continue;
838 rr->client_wait_list[i] = NULL;
839 switch (ntohl (resp->drop_flag))
840 {
841 case 0: /* drop */
842 rr->phase = RP_DROP;
843 break;
844
845 case 1: /* no change */
846 break;
847
848 case 2: /* update */
849 msize -= sizeof(struct GNUNET_DNS_Response);
850 if ((sizeof(struct GNUNET_TUN_DnsHeader) > msize) ||
851 (RP_REQUEST_MONITOR == rr->phase) ||
852 (RP_RESPONSE_MONITOR == rr->phase))
853 {
854 GNUNET_break (0);
856 next_phase (rr);
857 return;
858 }
859 GNUNET_free (rr->payload);
861 "Changing DNS reply according to client specifications\n");
862 rr->payload = GNUNET_malloc (msize);
863 rr->payload_length = msize;
864 GNUNET_memcpy (rr->payload, &resp[1], msize);
865 if (rr->phase == RP_QUERY)
866 {
867 /* clear wait list, we're moving to MODIFY phase next */
870 0);
871 }
872 /* if query changed to answer, move past DNS resolution phase... */
873 if ((RP_QUERY == rr->phase) &&
874 (rr->payload_length > sizeof(struct GNUNET_TUN_DnsHeader)) &&
875 ( ((struct GNUNET_TUN_DnsFlags*) &(((struct
877 payload)->flags))->
878 query_or_response == 1) )
879 {
883 0);
884 }
885 break;
886 }
887 next_phase (rr);
889 return;
890 }
891 /* odd, client was not on our list for the request, that ought
892 to be an error */
893 GNUNET_break (0);
895}
896
897
905static int
907 const struct GNUNET_MessageHeader *message)
908{
909 uint16_t msize;
910 const struct GNUNET_TUN_Layer2PacketHeader *tun;
911 const struct GNUNET_TUN_IPv4Header *ip4;
912 const struct GNUNET_TUN_IPv6Header *ip6;
913 const struct GNUNET_TUN_UdpHeader *udp;
914 const struct GNUNET_TUN_DnsHeader *dns;
915 struct RequestRecord *rr;
916 struct sockaddr_in *srca4;
917 struct sockaddr_in6 *srca6;
918 struct sockaddr_in *dsta4;
919 struct sockaddr_in6 *dsta6;
920
922 "Intercepted message via DNS hijacker\n");
923 msize = ntohs (message->size);
924 if (msize < sizeof(struct GNUNET_MessageHeader) + sizeof(struct
926 + sizeof(struct GNUNET_TUN_IPv4Header))
927 {
928 /* non-IP packet received on TUN!? */
929 GNUNET_break (0);
930 return GNUNET_OK;
931 }
932 msize -= sizeof(struct GNUNET_MessageHeader);
933 tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
934 msize -= sizeof(struct GNUNET_TUN_Layer2PacketHeader);
935 switch (ntohs (tun->proto))
936 {
937 case ETH_P_IPV4:
938 ip4 = (const struct GNUNET_TUN_IPv4Header *) &tun[1];
939 ip6 = NULL; /* make compiler happy */
940 if ((msize < sizeof(struct GNUNET_TUN_IPv4Header)) ||
941 (ip4->version != 4) ||
942 (ip4->header_length != sizeof(struct GNUNET_TUN_IPv4Header) / 4) ||
943 (ntohs (ip4->total_length) != msize) ||
944 (ip4->protocol != IPPROTO_UDP))
945 {
946 /* non-IP/UDP packet received on TUN (or with options) */
948 _ ("Received malformed IPv4-UDP packet on TUN interface.\n"));
949 return GNUNET_OK;
950 }
951 udp = (const struct GNUNET_TUN_UdpHeader*) &ip4[1];
952 msize -= sizeof(struct GNUNET_TUN_IPv4Header);
953 break;
954
955 case ETH_P_IPV6:
956 ip4 = NULL; /* make compiler happy */
957 ip6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1];
958 if ((msize < sizeof(struct GNUNET_TUN_IPv6Header)) ||
959 (ip6->version != 6) ||
960 (ntohs (ip6->payload_length) != msize - sizeof(struct
962 ||
963 (ip6->next_header != IPPROTO_UDP))
964 {
965 /* non-IP/UDP packet received on TUN (or with extensions) */
967 _ ("Received malformed IPv6-UDP packet on TUN interface.\n"));
968 return GNUNET_OK;
969 }
970 udp = (const struct GNUNET_TUN_UdpHeader *) &ip6[1];
971 msize -= sizeof(struct GNUNET_TUN_IPv6Header);
972 break;
973
974 default:
975 /* non-IP packet received on TUN!? */
977 _ (
978 "Got non-IP packet with %u bytes and protocol %u from TUN\n"),
979 (unsigned int) msize,
980 ntohs (tun->proto));
981 return GNUNET_OK;
982 }
983 if ((msize <= sizeof(struct GNUNET_TUN_UdpHeader) + sizeof(struct
985 ||
986 (DNS_PORT != ntohs (udp->destination_port)))
987 {
988 /* non-DNS packet received on TUN, ignore */
990 _ ("DNS interceptor got non-DNS packet (dropped)\n"));
993 "# Non-DNS UDP packet received via TUN interface"),
994 1, GNUNET_NO);
995 return GNUNET_OK;
996 }
997 msize -= sizeof(struct GNUNET_TUN_UdpHeader);
998 dns = (const struct GNUNET_TUN_DnsHeader*) &udp[1];
999 rr = &requests[dns->id];
1000
1001 /* clean up from previous request */
1002 GNUNET_free (rr->payload);
1003 rr->payload = NULL;
1006 0);
1007
1008 /* setup new request */
1009 rr->phase = RP_INIT;
1010 switch (ntohs (tun->proto))
1011 {
1012 case ETH_P_IPV4:
1013 {
1014 srca4 = (struct sockaddr_in*) &rr->src_addr;
1015 dsta4 = (struct sockaddr_in*) &rr->dst_addr;
1016 memset (srca4, 0, sizeof(struct sockaddr_in));
1017 memset (dsta4, 0, sizeof(struct sockaddr_in));
1018 srca4->sin_family = AF_INET;
1019 dsta4->sin_family = AF_INET;
1020 srca4->sin_addr = ip4->source_address;
1021 dsta4->sin_addr = ip4->destination_address;
1022 srca4->sin_port = udp->source_port;
1023 dsta4->sin_port = udp->destination_port;
1024#if HAVE_SOCKADDR_IN_SIN_LEN
1025 srca4->sin_len = sizeof(struct sockaddr_in);
1026 dsta4->sin_len = sizeof(struct sockaddr_in);
1027#endif
1028 }
1029 break;
1030
1031 case ETH_P_IPV6:
1032 {
1033 srca6 = (struct sockaddr_in6*) &rr->src_addr;
1034 dsta6 = (struct sockaddr_in6*) &rr->dst_addr;
1035 memset (srca6, 0, sizeof(struct sockaddr_in6));
1036 memset (dsta6, 0, sizeof(struct sockaddr_in6));
1037 srca6->sin6_family = AF_INET6;
1038 dsta6->sin6_family = AF_INET6;
1039 srca6->sin6_addr = ip6->source_address;
1040 dsta6->sin6_addr = ip6->destination_address;
1041 srca6->sin6_port = udp->source_port;
1042 dsta6->sin6_port = udp->destination_port;
1043#if HAVE_SOCKADDR_IN_SIN_LEN
1044 srca6->sin6_len = sizeof(struct sockaddr_in6);
1045 dsta6->sin6_len = sizeof(struct sockaddr_in6);
1046#endif
1047 }
1048 break;
1049
1050 default:
1051 GNUNET_assert (0);
1052 }
1053 rr->payload = GNUNET_malloc (msize);
1054 rr->payload_length = msize;
1055 GNUNET_memcpy (rr->payload, dns, msize);
1056 rr->request_id = dns->id | (request_id_gen << 16);
1059 "Creating new DNS request %llu\n",
1060 (unsigned long long) rr->request_id);
1062 gettext_noop (
1063 "# DNS requests received via TUN interface"),
1064 1, GNUNET_NO);
1065 /* start request processing state machine */
1066 next_phase (rr);
1067 return GNUNET_OK;
1068}
1069
1070
1076static void
1077run (void *cls,
1078 const struct GNUNET_CONFIGURATION_Handle *cfg_,
1080{
1081 char *ifc_name;
1082 char *ipv4addr;
1083 char *ipv4mask;
1084 char *ipv6addr;
1085 char *ipv6prefix;
1086 char *dns_exit;
1087 char *binary;
1088 int nortsetup;
1089
1090 cfg = cfg_;
1093 cls);
1095 /* TODO: support multiple DNS_EXIT servers being configured */
1096 /* TODO: see above TODO on using DNS server from original packet.
1097 Not sure which is best... */
1098 dns_exit = NULL;
1099 if ((GNUNET_OK !=
1101 "dns",
1102 "DNS_EXIT",
1103 &dns_exit)) ||
1104 (GNUNET_OK !=
1106 dns_exit)))
1107 {
1109 "dns",
1110 "DNS_EXIT",
1111 _ ("need a valid IPv4 or IPv6 address\n"));
1112 GNUNET_free (dns_exit);
1113 }
1115 cfg,
1116 "gnunet-helper-dns");
1117
1118 if (GNUNET_YES !=
1120 GNUNET_YES,
1121 NULL)) // TODO: once we have a windows-testcase, add test parameters here
1122 {
1124 _ ("`%s' is not SUID or the path is invalid, "
1125 "will not run DNS interceptor\n"),
1126 binary);
1127 global_ret = 1;
1128 GNUNET_free (binary);
1129 return;
1130 }
1131 GNUNET_free (binary);
1132
1133 helper_argv[0] = GNUNET_strdup ("gnunet-dns");
1134 if (GNUNET_SYSERR ==
1136 "dns",
1137 "IFNAME",
1138 &ifc_name))
1139 {
1141 "No entry 'IFNAME' in configuration!\n");
1142 GNUNET_free (binary);
1144 return;
1145 }
1146 helper_argv[1] = ifc_name;
1147 if ((GNUNET_SYSERR ==
1149 "dns",
1150 "IPV6ADDR",
1151 &ipv6addr)))
1152 {
1154 "No entry 'IPV6ADDR' in configuration!\n");
1155 GNUNET_free (binary);
1157 return;
1158 }
1159 helper_argv[2] = ipv6addr;
1160 if (GNUNET_SYSERR ==
1162 "dns",
1163 "IPV6PREFIX",
1164 &ipv6prefix))
1165 {
1167 "No entry 'IPV6PREFIX' in configuration!\n");
1168 GNUNET_free (binary);
1170 return;
1171 }
1173
1174 if (GNUNET_SYSERR ==
1176 "dns",
1177 "IPV4ADDR",
1178 &ipv4addr))
1179 {
1181 "No entry 'IPV4ADDR' in configuration!\n");
1182 GNUNET_free (binary);
1184 return;
1185 }
1186 helper_argv[4] = ipv4addr;
1187 if (GNUNET_SYSERR ==
1188 GNUNET_CONFIGURATION_get_value_string (cfg, "dns", "IPV4MASK",
1189 &ipv4mask))
1190 {
1192 "No entry 'IPV4MASK' in configuration!\n");
1193 GNUNET_free (binary);
1195 return;
1196 }
1197 helper_argv[5] = ipv4mask;
1198
1199 nortsetup = GNUNET_CONFIGURATION_get_value_yesno (cfg, "dns",
1200 "SKIP_ROUTING_SETUP");
1201 if (GNUNET_YES == nortsetup)
1202 helper_argv[6] = GNUNET_strdup ("1");
1203 else
1204 helper_argv[6] = GNUNET_strdup ("0");
1205
1206 helper_argv[7] = NULL;
1208 GNUNET_NO,
1209 binary,
1212 NULL, NULL);
1213 GNUNET_free (binary);
1214}
1215
1216
1222 "dns",
1224 &run,
1227 NULL,
1228 GNUNET_MQ_hd_fixed_size (client_init,
1230 struct GNUNET_DNS_Register,
1231 NULL),
1232 GNUNET_MQ_hd_var_size (client_response,
1234 struct GNUNET_DNS_Response,
1235 NULL),
1237
1238
1239/* FIXME: this might need a port on systems without 'getresgid' */
1240#if HAVE_GETRESGID
1241void __attribute__((constructor)) GNUNET_DNS_init (void);
1242
1246void __attribute__ ((constructor))
1247GNUNET_DNS_init (void)
1248{
1249 gid_t rgid;
1250 gid_t egid;
1251 gid_t sgid;
1252
1253 if (-1 == getresgid (&rgid,
1254 &egid,
1255 &sgid))
1256 {
1257 fprintf (stderr,
1258 "getresgid failed: %s\n",
1259 strerror (errno));
1260 }
1261 else if (sgid != rgid)
1262 {
1263 if (-1 == setregid (sgid,
1264 sgid))
1265 fprintf (stderr,
1266 "setregid failed: %s\n",
1267 strerror (errno));
1268 }
1269}
1270
1271
1272#endif
1273
1274
1275/* end of gnunet-service-dns.c */
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
IPC messages between DNS API and DNS service.
#define gettext_noop(String)
Definition: gettext.h:74
static unsigned long long ipv6prefix
IPv6 prefix (0..127) from configuration file.
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
static unsigned long long payload
How much data are we currently storing in the database?
static void next_phase(struct RequestRecord *rr)
A client has completed its processing for this request.
static int process_helper_messages(void *cls, const struct GNUNET_MessageHeader *message)
Functions with this signature are called whenever a complete message is received by the tokenizer fro...
static void handle_client_response(void *cls, const struct GNUNET_DNS_Response *resp)
Handle a response from a client.
static int global_ret
Global return value from 'main'.
RequestPhase
Phases each request goes through.
@ RP_REQUEST_MONITOR
Showing the request to all monitor clients.
@ RP_QUERY
Showing the request to PRE-RESOLUTION clients to find an answer.
@ RP_MODIFY
Client (or global DNS request) has resulted in a response.
@ RP_DROP
Some client has told us to drop the request.
@ RP_INTERNET_DNS
Global Internet query is now pending.
@ RP_INIT
Request has just been received.
@ RP_RESPONSE_MONITOR
Showing the request to all monitor clients.
static void process_dns_result(void *cls, const struct GNUNET_TUN_DnsHeader *dns, size_t r)
Callback called from DNSSTUB resolver when a resolution succeeded.
static struct GNUNET_STATISTICS_Handle * stats
Statistics.
static const struct GNUNET_CONFIGURATION_Handle * cfg
The configuration to use.
static struct GNUNET_HELPER_Handle * hijacker
Handle to DNS hijacker helper process ("gnunet-helper-dns").
static struct GNUNET_DNSSTUB_Context * dnsstub
Handle to the DNS Stub resolver.
static void cleanup_task(void *cls)
Task run during shutdown.
static void request_done(struct RequestRecord *rr)
We're done with some request, finish processing.
static char * helper_argv[8]
Command-line arguments we are giving to the hijacker process.
static void * client_connect_cb(void *cls, struct GNUNET_SERVICE_Client *client, struct GNUNET_MQ_Handle *mq)
A client connected, setup our data structures.
static struct ClientRecord * clients_head
Head of DLL of clients we consult.
static uint64_t request_id_gen
Generator for unique request IDs.
#define DNS_PORT
Port number for DNS.
static void handle_client_init(void *cls, const struct GNUNET_DNS_Register *reg)
We got a new client.
static int check_client_response(void *cls, const struct GNUNET_DNS_Response *resp)
Check a response from a client.
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg_, struct GNUNET_SERVICE_Handle *service)
static struct RequestRecord requests[UINT16_MAX+1]
Array of all open requests.
#define LOG(kind,...)
Generic logging shorthand.
static void cleanup_rr(struct RequestRecord *rr)
We're done processing a DNS request, free associated memory.
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *client, void *app_ctx)
A client disconnected, clean up after it.
static void send_request_to_client(struct RequestRecord *rr, struct ClientRecord *cr)
Show the payload of the given request record to the client (and wait for a response).
GNUNET_SERVICE_MAIN(GNUNET_OS_project_data_gnunet(), "dns", GNUNET_SERVICE_OPTION_NONE, &run, &client_connect_cb, &client_disconnect_cb, NULL, GNUNET_MQ_hd_fixed_size(client_init, GNUNET_MESSAGE_TYPE_DNS_CLIENT_INIT, struct GNUNET_DNS_Register, NULL), GNUNET_MQ_hd_var_size(client_response, GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE, struct GNUNET_DNS_Response, NULL), GNUNET_MQ_handler_end())
Define "main" method using service macro.
static struct ClientRecord * clients_tail
Tail of DLL of clients we consult.
static int udp
Option -u: UDP requested.
Definition: gnunet-vpn.c:75
API to access the DNS service.
struct GNUNET_PQ_ResultSpec __attribute__
Constants for network protocols.
API to create, modify and access statistics.
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message,...
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
struct GNUNET_DNSSTUB_Context * GNUNET_DNSSTUB_start(unsigned int num_sockets)
Start a DNS stub resolver.
Definition: dnsstub.c:586
int GNUNET_DNSSTUB_add_dns_ip(struct GNUNET_DNSSTUB_Context *ctx, const char *dns_ip)
Add nameserver for use by the DNSSTUB.
Definition: dnsstub.c:613
void GNUNET_DNSSTUB_stop(struct GNUNET_DNSSTUB_Context *ctx)
Cleanup DNSSTUB resolver.
Definition: dnsstub.c:705
struct GNUNET_DNSSTUB_RequestSocket * GNUNET_DNSSTUB_resolve(struct GNUNET_DNSSTUB_Context *ctx, const void *request, size_t request_len, GNUNET_DNSSTUB_ResultCallback rc, void *rc_cls)
Perform DNS resolution using our default IP from init.
Definition: dnsstub.c:526
GNUNET_DNS_Flags
Flags that specify when to call the client's handler.
@ GNUNET_DNS_FLAG_RESPONSE_MONITOR
Set this flag to see all requests just before they are returned to the network.
@ GNUNET_DNS_FLAG_REQUEST_MONITOR
Set this flag to see all requests first prior to resolution (for monitoring).
@ GNUNET_DNS_FLAG_PRE_RESOLUTION
This client should be called on requests that have not yet been resolved as this client provides a re...
@ GNUNET_DNS_FLAG_POST_RESOLUTION
This client wants to be called on the results of a DNS resolution (either resolved by PRE-RESOLUTION ...
struct GNUNET_HELPER_SendHandle * GNUNET_HELPER_send(struct GNUNET_HELPER_Handle *h, const struct GNUNET_MessageHeader *msg, bool can_drop, GNUNET_HELPER_Continuation cont, void *cont_cls)
Send an message to the helper.
Definition: helper.c:615
struct GNUNET_HELPER_Handle * GNUNET_HELPER_start(const struct GNUNET_OS_ProjectData *pd, int with_control_pipe, const char *binary_name, char *const binary_argv[], GNUNET_MessageTokenizerCallback cb, GNUNET_HELPER_ExceptionCallback exp_cb, void *cb_cls)
Starts a helper and begins reading from it.
Definition: helper.c:460
void GNUNET_HELPER_stop(struct GNUNET_HELPER_Handle *h, int soft_kill)
Kills the helper, closes the pipe, frees the handle and calls wait() on the helper process.
Definition: helper.c:538
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
#define GNUNET_log(kind,...)
#define GNUNET_ALIGN
gcc-ism to force alignment; we use this to align char-arrays that may then be cast to 'struct's.
#define GNUNET_UNUSED
gcc-ism to document unused arguments
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
void GNUNET_log_config_invalid(enum GNUNET_ErrorType kind, const char *section, const char *option, const char *required)
Log error message about invalid configuration option value.
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_array_append(arr, len, element)
Append an element to an array (growing the array by one).
#define GNUNET_free(ptr)
Wrapper around free.
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:305
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
Definition: gnunet_mq_lib.h:61
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_gnunet(void)
Return default project data used by 'libgnunetutil' for GNUnet.
enum GNUNET_GenericReturnValue GNUNET_OS_check_helper_binary(const char *binary, bool check_suid, const char *params)
Check whether an executable exists and possibly if the suid bit is set on the file.
char * GNUNET_OS_get_suid_binary_path(const struct GNUNET_OS_ProjectData *pd, const struct GNUNET_CONFIGURATION_Handle *cfg, const char *progname)
Given the name of a helper, service or daemon binary construct the full path to the binary using the ...
#define GNUNET_MESSAGE_TYPE_DNS_CLIENT_REQUEST
Type of messages between the gnunet-helper-dns and the service.
#define GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE
Type of messages between the gnunet-helper-dns and the service.
#define GNUNET_MESSAGE_TYPE_DNS_HELPER
Type of messages between the gnunet-helper-dns and the service.
#define GNUNET_MESSAGE_TYPE_DNS_CLIENT_INIT
Initial message from client to DNS service for registration.
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:567
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition: scheduler.c:1339
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2418
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2389
@ GNUNET_SERVICE_OPTION_NONE
Use defaults.
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
void GNUNET_TUN_initialize_ipv6_header(struct GNUNET_TUN_IPv6Header *ip, uint8_t protocol, uint16_t payload_length, const struct in6_addr *src, const struct in6_addr *dst)
Initialize an IPv6 header.
Definition: tun.c:115
void GNUNET_TUN_calculate_udp4_checksum(const struct GNUNET_TUN_IPv4Header *ip, struct GNUNET_TUN_UdpHeader *udp, const void *payload, uint16_t payload_length)
Calculate IPv4 UDP checksum.
Definition: tun.c:193
GNUNET_NETWORK_STRUCT_END void GNUNET_TUN_initialize_ipv4_header(struct GNUNET_TUN_IPv4Header *ip, uint8_t protocol, uint16_t payload_length, const struct in_addr *src, const struct in_addr *dst)
Initialize an IPv4 header.
Definition: tun.c:80
#define ETH_P_IPV6
Number for IPv6.
#define ETH_P_IPV4
Number for IPv4.
void GNUNET_TUN_calculate_udp6_checksum(const struct GNUNET_TUN_IPv6Header *ip, struct GNUNET_TUN_UdpHeader *udp, const void *payload, uint16_t payload_length)
Calculate IPv6 UDP checksum.
Definition: tun.c:224
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
Entry we keep for each client.
struct ClientRecord * prev
Kept in doubly-linked list.
struct GNUNET_MQ_Handle * mq
Message queue to talk to client.
enum GNUNET_DNS_Flags flags
Flags for the client.
struct GNUNET_SERVICE_Client * client
Handle to the client.
struct ClientRecord * next
Kept in doubly-linked list.
Handle to the stub resolver.
Definition: dnsstub.c:125
UDP socket we are using for sending DNS requests to the Internet.
Definition: dnsstub.c:46
Message from client to DNS service to register itself.
Definition: dns.h:36
uint32_t flags
NBO encoding of enum GNUNET_DNS_Flags for the client.
Definition: dns.h:45
Message from DNS service to client: please handle a request.
Definition: dns.h:53
uint32_t reserved
Always zero.
Definition: dns.h:62
uint64_t request_id
Unique request ID.
Definition: dns.h:67
Message from client to DNS service: here is my reply.
Definition: dns.h:77
struct GNUNET_MessageHeader header
Header of type GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE.
Definition: dns.h:81
uint32_t drop_flag
Zero to drop, 1 for no change (no payload), 2 for update (message has payload).
Definition: dns.h:86
uint64_t request_id
Unique request ID.
Definition: dns.h:91
The handle to a helper process.
Definition: helper.c:77
Handle to a message queue.
Definition: mq.c:87
Header for all communications.
Handle to a client that is connected to a service.
Definition: service.c:249
Handle to a service.
Definition: service.c:116
Handle for the service.
DNS flags (largely RFC 1035 / RFC 2136).
uint16_t id
Unique identifier for the request/response.
Standard IPv4 header.
uint16_t total_length
Length of the packet, including this header.
uint8_t protocol
L4-protocol, for example, IPPROTO_UDP or IPPROTO_TCP.
struct in_addr source_address
Origin of the packet.
struct in_addr destination_address
Destination of the packet.
unsigned int header_length
Standard IPv6 header.
struct in6_addr source_address
Origin of the packet.
uint8_t next_header
For example, IPPROTO_UDP or IPPROTO_TCP.
struct in6_addr destination_address
Destination of the packet.
uint16_t payload_length
Length of the payload, excluding this header.
Header from Linux TUN interface.
uint16_t proto
Here we get an ETH_P_-number.
uint16_t flags
Some flags (unused).
UDP packet header.
uint16_t destination_port
Destination port (in NBO).
uint16_t source_port
Source port (in NBO).
Entry we keep for each active request.
struct sockaddr_storage src_addr
Source address of the original request (for sending response).
char * payload
Payload of the UDP packet (the UDP payload), can be either query or already the response.
uint64_t request_id
ID of this request, also basis for hashing.
unsigned int client_wait_list_length
Length of the client_wait_list.
struct sockaddr_storage dst_addr
Destination address of the original request (for potential use as exit).
size_t payload_length
Number of bytes in payload.
struct ClientRecord ** client_wait_list
List of clients that still need to see this request (each entry is set to NULL when the client is don...
struct GNUNET_DNSSTUB_RequestSocket * rs
Socket we are using to transmit this request (must match if we receive a response).
enum RequestPhase phase
In which phase this this request?