diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-01-03 21:02:45 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-01-03 21:02:45 +0000 |
commit | 1ce43f352bed1f5d95db4f09773b7ecb574c41de (patch) | |
tree | 0c5c0affd18f59f03a505eee9d042dab6467e89f /src/dns | |
parent | 5b9de1c328efb28856b9239301be1821ecf21bc0 (diff) | |
download | gnunet-1ce43f352bed1f5d95db4f09773b7ecb574c41de.tar.gz gnunet-1ce43f352bed1f5d95db4f09773b7ecb574c41de.zip |
-more DNS service hacking
Diffstat (limited to 'src/dns')
-rw-r--r-- | src/dns/gnunet-service-dns_new.c | 188 |
1 files changed, 146 insertions, 42 deletions
diff --git a/src/dns/gnunet-service-dns_new.c b/src/dns/gnunet-service-dns_new.c index 041b2d12b..14bb19811 100644 --- a/src/dns/gnunet-service-dns_new.c +++ b/src/dns/gnunet-service-dns_new.c | |||
@@ -31,40 +31,36 @@ | |||
31 | #include "gnunet_dns_service-new.h" | 31 | #include "gnunet_dns_service-new.h" |
32 | 32 | ||
33 | GNUNET_NETWORK_STRUCT_BEGIN | 33 | GNUNET_NETWORK_STRUCT_BEGIN |
34 | struct ip4_hdr | 34 | struct ip4_header |
35 | { | 35 | { |
36 | unsigned hdr_lngth:4 GNUNET_PACKED; | 36 | unsigned header_length:4 GNUNET_PACKED; |
37 | unsigned version:4 GNUNET_PACKED; | 37 | unsigned version:4 GNUNET_PACKED; |
38 | |||
39 | uint8_t diff_serv; | 38 | uint8_t diff_serv; |
40 | uint16_t tot_lngth GNUNET_PACKED; | 39 | uint16_t total_length GNUNET_PACKED; |
41 | 40 | uint16_t identification GNUNET_PACKED; | |
42 | uint16_t ident GNUNET_PACKED; | ||
43 | unsigned flags:3 GNUNET_PACKED; | 41 | unsigned flags:3 GNUNET_PACKED; |
44 | unsigned frag_off:13 GNUNET_PACKED; | 42 | unsigned fragmentation_offset:13 GNUNET_PACKED; |
45 | |||
46 | uint8_t ttl; | 43 | uint8_t ttl; |
47 | uint8_t proto; | 44 | uint8_t protocol; |
48 | uint16_t chks GNUNET_PACKED; | 45 | uint16_t checksum GNUNET_PACKED; |
49 | 46 | struct in_addr source_address GNUNET_PACKED; | |
50 | struct in_addr sadr GNUNET_PACKED; | 47 | struct in_addr destination_address GNUNET_PACKED; |
51 | struct in_addr dadr GNUNET_PACKED; | ||
52 | }; | 48 | }; |
53 | 49 | ||
54 | struct ip6_hdr | 50 | struct ip6_header |
55 | { | 51 | { |
56 | unsigned tclass_h:4 GNUNET_PACKED; | 52 | unsigned traffic_class_h:4 GNUNET_PACKED; |
57 | unsigned version:4 GNUNET_PACKED; | 53 | unsigned version:4 GNUNET_PACKED; |
58 | unsigned tclass_l:4 GNUNET_PACKED; | 54 | unsigned traffic_class_l:4 GNUNET_PACKED; |
59 | unsigned flowlbl:20 GNUNET_PACKED; | 55 | unsigned flow_label:20 GNUNET_PACKED; |
60 | uint16_t paylgth GNUNET_PACKED; | 56 | uint16_t payload_length GNUNET_PACKED; |
61 | uint8_t nxthdr; | 57 | uint8_t next_header; |
62 | uint8_t hoplmt; | 58 | uint8_t hop_limit; |
63 | struct in6_addr sadr GNUNET_PACKED; | 59 | struct in6_addr source_address GNUNET_PACKED; |
64 | struct in6_addr dadr GNUNET_PACKED; | 60 | struct in6_addr destination_address GNUNET_PACKED; |
65 | }; | 61 | }; |
66 | 62 | ||
67 | struct udp_pkt | 63 | struct udp_packet |
68 | { | 64 | { |
69 | uint16_t spt GNUNET_PACKED; | 65 | uint16_t spt GNUNET_PACKED; |
70 | uint16_t dpt GNUNET_PACKED; | 66 | uint16_t dpt GNUNET_PACKED; |
@@ -72,8 +68,7 @@ struct udp_pkt | |||
72 | uint16_t crc GNUNET_PACKED; | 68 | uint16_t crc GNUNET_PACKED; |
73 | }; | 69 | }; |
74 | 70 | ||
75 | 71 | struct dns_header | |
76 | struct dns_hdr | ||
77 | { | 72 | { |
78 | uint16_t id GNUNET_PACKED; | 73 | uint16_t id GNUNET_PACKED; |
79 | uint16_t flags GNUNET_PACKED; | 74 | uint16_t flags GNUNET_PACKED; |
@@ -364,17 +359,17 @@ request_done (struct RequestRecord *rr) | |||
364 | switch (rr->src_addr.ss_family) | 359 | switch (rr->src_addr.ss_family) |
365 | { | 360 | { |
366 | case AF_INET: | 361 | case AF_INET: |
367 | reply_len += sizeof (struct ip4_hdr); | 362 | reply_len += sizeof (struct ip4_header); |
368 | break; | 363 | break; |
369 | case AF_INET6: | 364 | case AF_INET6: |
370 | reply_len += sizeof (struct ip6_hdr); | 365 | reply_len += sizeof (struct ip6_header); |
371 | break; | 366 | break; |
372 | default: | 367 | default: |
373 | GNUNET_break (0); | 368 | GNUNET_break (0); |
374 | cleanup_rr (rr); | 369 | cleanup_rr (rr); |
375 | return; | 370 | return; |
376 | } | 371 | } |
377 | reply_len += sizeof (struct udp_pkt); | 372 | reply_len += sizeof (struct udp_packet); |
378 | reply_len += rr->payload_length; | 373 | reply_len += rr->payload_length; |
379 | if (reply_len >= GNUNET_SERVER_MAX_MESSAGE_SIZE) | 374 | if (reply_len >= GNUNET_SERVER_MAX_MESSAGE_SIZE) |
380 | { | 375 | { |
@@ -400,11 +395,23 @@ request_done (struct RequestRecord *rr) | |||
400 | { | 395 | { |
401 | struct sockaddr_in *src = (struct sockaddr_in *) &rr->src_addr; | 396 | struct sockaddr_in *src = (struct sockaddr_in *) &rr->src_addr; |
402 | struct sockaddr_in *dst = (struct sockaddr_in *) &rr->dst_addr; | 397 | struct sockaddr_in *dst = (struct sockaddr_in *) &rr->dst_addr; |
403 | struct ip4_hdr ip; | 398 | struct ip4_header ip; |
404 | 399 | ||
405 | spt = dst->sin_port; | 400 | spt = dst->sin_port; |
406 | dpt = src->sin_port; | 401 | dpt = src->sin_port; |
407 | // FIXME: fill in IP header! | 402 | ip.header_length = sizeof (struct ip4_header) / 4; |
403 | ip.version = IPVERSION; /* aka 4 */ | ||
404 | ip.diff_serv = 0; | ||
405 | ip.total_length = htons ((uint16_t) reply_len); | ||
406 | ip.identification = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
407 | 65536); | ||
408 | ip.flags = 0; | ||
409 | ip.fragmentation_offset = 0; | ||
410 | ip.ttl = 255; /* or lower? */ | ||
411 | ip.protocol = IPPROTO_UDP; | ||
412 | ip.checksum = 0; /* checksum is optional */ | ||
413 | ip.source_address = dst->sin_addr; | ||
414 | ip.destination_address = src->sin_addr; | ||
408 | memcpy (&buf[off], &ip, sizeof (ip)); | 415 | memcpy (&buf[off], &ip, sizeof (ip)); |
409 | off += sizeof (ip); | 416 | off += sizeof (ip); |
410 | break; | 417 | break; |
@@ -413,11 +420,19 @@ request_done (struct RequestRecord *rr) | |||
413 | { | 420 | { |
414 | struct sockaddr_in6 *src = (struct sockaddr_in6 *) &rr->src_addr; | 421 | struct sockaddr_in6 *src = (struct sockaddr_in6 *) &rr->src_addr; |
415 | struct sockaddr_in6 *dst = (struct sockaddr_in6 *) &rr->dst_addr; | 422 | struct sockaddr_in6 *dst = (struct sockaddr_in6 *) &rr->dst_addr; |
416 | struct ip6_hdr ip; | 423 | struct ip6_header ip; |
417 | 424 | ||
418 | spt = dst->sin6_port; | 425 | spt = dst->sin6_port; |
419 | dpt = src->sin6_port; | 426 | dpt = src->sin6_port; |
420 | // FIXME: fill in IP header! | 427 | ip.traffic_class_h = 0; |
428 | ip.version = 6; /* is there a named constant? I couldn't find one */ | ||
429 | ip.traffic_class_l = 0; | ||
430 | ip.flow_label = 0; | ||
431 | ip.payload_length = htons ((uint16_t) reply_len); | ||
432 | ip.next_header = IPPROTO_UDP; | ||
433 | ip.hop_limit = 255; /* or lower? */ | ||
434 | ip.source_address = dst->sin6_addr; | ||
435 | ip.destination_address = src->sin6_addr; | ||
421 | memcpy (&buf[off], &ip, sizeof (ip)); | 436 | memcpy (&buf[off], &ip, sizeof (ip)); |
422 | off += sizeof (ip); | 437 | off += sizeof (ip); |
423 | } | 438 | } |
@@ -428,7 +443,7 @@ request_done (struct RequestRecord *rr) | |||
428 | 443 | ||
429 | /* now UDP header */ | 444 | /* now UDP header */ |
430 | { | 445 | { |
431 | struct udp_pkt udp; | 446 | struct udp_packet udp; |
432 | 447 | ||
433 | udp.spt = spt; | 448 | udp.spt = spt; |
434 | udp.dpt = dpt; | 449 | udp.dpt = dpt; |
@@ -553,11 +568,11 @@ next_phase (struct RequestRecord *rr) | |||
553 | { | 568 | { |
554 | case AF_INET: | 569 | case AF_INET: |
555 | dnsout = dnsout4; | 570 | dnsout = dnsout4; |
556 | salen = sizeof (struct ip4_hdr); | 571 | salen = sizeof (struct ip4_header); |
557 | break; | 572 | break; |
558 | case AF_INET6: | 573 | case AF_INET6: |
559 | dnsout = dnsout6; | 574 | dnsout = dnsout6; |
560 | salen = sizeof (struct ip6_hdr); | 575 | salen = sizeof (struct ip6_header); |
561 | break; | 576 | break; |
562 | default: | 577 | default: |
563 | GNUNET_break (0); | 578 | GNUNET_break (0); |
@@ -652,7 +667,7 @@ read_response (void *cls, | |||
652 | struct sockaddr_in addr4; | 667 | struct sockaddr_in addr4; |
653 | struct sockaddr_in6 addr6; | 668 | struct sockaddr_in6 addr6; |
654 | struct sockaddr *addr; | 669 | struct sockaddr *addr; |
655 | struct dns_hdr *dns; | 670 | struct dns_header *dns; |
656 | socklen_t addrlen; | 671 | socklen_t addrlen; |
657 | struct RequestRecord *rr; | 672 | struct RequestRecord *rr; |
658 | ssize_t r; | 673 | ssize_t r; |
@@ -702,14 +717,14 @@ read_response (void *cls, | |||
702 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "recvfrom"); | 717 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "recvfrom"); |
703 | return; | 718 | return; |
704 | } | 719 | } |
705 | if (sizeof (struct dns_hdr) > r) | 720 | if (sizeof (struct dns_header) > r) |
706 | { | 721 | { |
707 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 722 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
708 | _("Received DNS response that is too small (%u bytes)"), | 723 | _("Received DNS response that is too small (%u bytes)"), |
709 | r); | 724 | r); |
710 | return; | 725 | return; |
711 | } | 726 | } |
712 | dns = (struct dns_hdr *) buf; | 727 | dns = (struct dns_header *) buf; |
713 | rr = &requests[dns->id]; | 728 | rr = &requests[dns->id]; |
714 | if (rr->phase != RP_INTERNET_DNS) | 729 | if (rr->phase != RP_INTERNET_DNS) |
715 | { | 730 | { |
@@ -918,7 +933,7 @@ handle_client_response (void *cls GNUNET_UNUSED, | |||
918 | break; | 933 | break; |
919 | case 2: /* update */ | 934 | case 2: /* update */ |
920 | msize -= sizeof (struct GNUNET_DNS_Response); | 935 | msize -= sizeof (struct GNUNET_DNS_Response); |
921 | if ( (sizeof (struct dns_hdr) > msize) || | 936 | if ( (sizeof (struct dns_header) > msize) || |
922 | (RP_MONITOR == rr->phase) ) | 937 | (RP_MONITOR == rr->phase) ) |
923 | { | 938 | { |
924 | GNUNET_break (0); | 939 | GNUNET_break (0); |
@@ -960,10 +975,99 @@ static void | |||
960 | process_helper_messages (void *cls GNUNET_UNUSED, void *client, | 975 | process_helper_messages (void *cls GNUNET_UNUSED, void *client, |
961 | const struct GNUNET_MessageHeader *message) | 976 | const struct GNUNET_MessageHeader *message) |
962 | { | 977 | { |
963 | struct RequestRecord *rr = NULL; | 978 | uint16_t msize; |
964 | /* FIXME: parse message, create record, start processing! */ | 979 | const struct ip4_header *ip4; |
965 | /* FIXME: put request into queue for clients / system DNS */ | 980 | const struct ip6_header *ip6; |
981 | const struct udp_packet *udp; | ||
982 | const struct dns_header *dns; | ||
983 | struct RequestRecord *rr; | ||
984 | struct sockaddr_in *srca4; | ||
985 | struct sockaddr_in6 *srca6; | ||
986 | struct sockaddr_in *dsta4; | ||
987 | struct sockaddr_in6 *dsta6; | ||
988 | |||
989 | msize = ntohs (message->size); | ||
990 | if (msize < sizeof (struct GNUNET_MessageHeader) + sizeof (struct ip4_header)) | ||
991 | { | ||
992 | /* non-IP packet received on TUN!? */ | ||
993 | GNUNET_break (0); | ||
994 | return; | ||
995 | } | ||
996 | msize -= sizeof (struct GNUNET_MessageHeader); | ||
997 | ip4 = (const struct ip4_header *) &message[1]; | ||
998 | ip6 = (const struct ip6_header *) &message[1]; | ||
999 | if (ip4->version == IPVERSION) | ||
1000 | { | ||
1001 | udp = (const struct udp_packet*) &ip4[1]; | ||
1002 | msize -= sizeof (struct ip4_header); | ||
1003 | } | ||
1004 | else if ( (ip6->version == 6) && | ||
1005 | (msize >= sizeof (struct ip6_header)) ) | ||
1006 | { | ||
1007 | udp = (const struct udp_packet*) &ip6[1]; | ||
1008 | msize -= sizeof (struct ip6_header); | ||
1009 | } | ||
1010 | else | ||
1011 | { | ||
1012 | /* non-IP packet received on TUN!? */ | ||
1013 | GNUNET_break (0); | ||
1014 | return; | ||
1015 | } | ||
1016 | if (msize <= sizeof (struct udp_packet) + sizeof (struct dns_header)) | ||
1017 | { | ||
1018 | /* non-DNS packet received on TUN, ignore */ | ||
1019 | /* FIXME: case for statistics... */ | ||
1020 | return; | ||
1021 | } | ||
1022 | msize -= sizeof (struct udp_packet); | ||
1023 | dns = (const struct dns_header*) &udp[1]; | ||
1024 | rr = &requests[dns->id]; | ||
1025 | |||
1026 | /* clean up from previous request */ | ||
1027 | GNUNET_free_non_null (rr->payload); | ||
1028 | rr->payload = NULL; | ||
1029 | GNUNET_array_grow (rr->client_wait_list, | ||
1030 | rr->client_wait_list_length, | ||
1031 | 0); | ||
1032 | |||
1033 | /* setup new request */ | ||
1034 | rr->phase = RP_INIT; | ||
1035 | if (ip4->version == IPVERSION) | ||
1036 | { | ||
1037 | srca4 = (struct sockaddr_in*) &rr->src_addr; | ||
1038 | dsta4 = (struct sockaddr_in*) &rr->dst_addr; | ||
1039 | memset (srca4, 0, sizeof (struct sockaddr_in)); | ||
1040 | memset (dsta4, 0, sizeof (struct sockaddr_in)); | ||
1041 | srca4->sin_family = AF_INET; | ||
1042 | dsta4->sin_family = AF_INET; | ||
1043 | srca4->sin_addr = ip4->source_address; | ||
1044 | dsta4->sin_addr = ip4->destination_address; | ||
1045 | srca4->sin_port = udp->spt; | ||
1046 | dsta4->sin_port = udp->dpt; | ||
1047 | /* FIXME: bother with FreeBSD sin_len crap? */ | ||
1048 | } | ||
1049 | else /* ipv6 */ | ||
1050 | { | ||
1051 | srca6 = (struct sockaddr_in6*) &rr->src_addr; | ||
1052 | dsta6 = (struct sockaddr_in6*) &rr->dst_addr; | ||
1053 | memset (srca6, 0, sizeof (struct sockaddr_in6)); | ||
1054 | memset (dsta6, 0, sizeof (struct sockaddr_in6)); | ||
1055 | srca6->sin6_family = AF_INET6; | ||
1056 | dsta6->sin6_family = AF_INET6; | ||
1057 | srca6->sin6_addr = ip6->source_address; | ||
1058 | dsta6->sin6_addr = ip6->destination_address; | ||
1059 | srca6->sin6_port = udp->spt; | ||
1060 | dsta6->sin6_port = udp->dpt; | ||
1061 | /* FIXME: bother with FreeBSD sin_len crap? */ | ||
1062 | } | ||
1063 | rr->payload = GNUNET_malloc (msize); | ||
1064 | rr->payload_length = msize; | ||
1065 | memcpy (rr->payload, dns, msize); | ||
1066 | rr->request_id = dns->id | (request_id_gen << 16); | ||
966 | request_id_gen++; | 1067 | request_id_gen++; |
1068 | |||
1069 | /* FIXME: case for statistics... */ | ||
1070 | /* start request processing state machine */ | ||
967 | next_phase (rr); | 1071 | next_phase (rr); |
968 | } | 1072 | } |
969 | 1073 | ||