aboutsummaryrefslogtreecommitdiff
path: root/src/vpn
diff options
context:
space:
mode:
authorPhilipp Tölke <toelke@in.tum.de>2011-10-26 07:13:23 +0000
committerPhilipp Tölke <toelke@in.tum.de>2011-10-26 07:13:23 +0000
commit913f88d980ef4fcc4153336042387a17ad8e428b (patch)
treef7bc0d3e34dc0b84810dd44a0025cfea69e9aa95 /src/vpn
parent9095e6a2fc69654f993c37c0e5e4159dbd88028d (diff)
downloadgnunet-913f88d980ef4fcc4153336042387a17ad8e428b.tar.gz
gnunet-913f88d980ef4fcc4153336042387a17ad8e428b.zip
handle dns over ipv6 and 6-to-4 and 4-to-6
Diffstat (limited to 'src/vpn')
-rw-r--r--src/vpn/gnunet-daemon-vpn-helper.c179
-rw-r--r--src/vpn/gnunet-service-dns-p.h12
-rw-r--r--src/vpn/gnunet-service-dns.c386
-rw-r--r--src/vpn/gnunet-vpn-packet.h4
4 files changed, 417 insertions, 164 deletions
diff --git a/src/vpn/gnunet-daemon-vpn-helper.c b/src/vpn/gnunet-daemon-vpn-helper.c
index 4d2bbf819..1790c2b00 100644
--- a/src/vpn/gnunet-daemon-vpn-helper.c
+++ b/src/vpn/gnunet-daemon-vpn-helper.c
@@ -174,52 +174,114 @@ helper_write (void *cls
174 174
175 GNUNET_assert (20 == sizeof (struct ip_hdr)); 175 GNUNET_assert (20 == sizeof (struct ip_hdr));
176 GNUNET_assert (8 == sizeof (struct udp_pkt)); 176 GNUNET_assert (8 == sizeof (struct udp_pkt));
177
177 size_t data_len = len - sizeof (struct answer_packet) + 1; 178 size_t data_len = len - sizeof (struct answer_packet) + 1;
178 size_t net_len = sizeof (struct ip_hdr) + sizeof (struct udp_dns) + data_len; 179
179 size_t pkt_len = 180 void* buf;
180 sizeof (struct GNUNET_MessageHeader) + sizeof (struct pkt_tun) + net_len; 181 size_t pkt_len;
181 182
182 struct ip_udp_dns *pkt = alloca (pkt_len); 183 if (ans->pkt.addrlen == 16)
183 184 {
184 GNUNET_assert (pkt != NULL); 185 size_t net_len = sizeof (struct ip6_hdr) + sizeof (struct udp_dns) + data_len;
185 memset (pkt, 0, pkt_len); 186 pkt_len =
186 187 sizeof (struct GNUNET_MessageHeader) + sizeof (struct pkt_tun) + net_len;
187 /* set the gnunet-header */ 188
188 pkt->shdr.size = htons (pkt_len); 189 struct ip6_udp_dns *pkt = alloca (pkt_len);
189 pkt->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); 190
190 191 GNUNET_assert (pkt != NULL);
191 /* set the tun-header (no flags and ethertype of IPv4) */ 192 memset (pkt, 0, pkt_len);
192 pkt->tun.flags = 0; 193
193 pkt->tun.type = htons (0x0800); 194 /* set the gnunet-header */
194 195 pkt->shdr.size = htons (pkt_len);
195 /* set the ip-header */ 196 pkt->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
196 pkt->ip_hdr.version = 4; 197
197 pkt->ip_hdr.hdr_lngth = 5; 198 /* set the tun-header (no flags and ethertype of IPv4) */
198 pkt->ip_hdr.diff_serv = 0; 199 pkt->tun.flags = 0;
199 pkt->ip_hdr.tot_lngth = htons (net_len); 200 pkt->tun.type = htons (0x86dd);
200 pkt->ip_hdr.ident = 0; 201
201 pkt->ip_hdr.flags = 0; 202 memcpy(&pkt->ip6_hdr.sadr, ans->pkt.from, 16);
202 pkt->ip_hdr.frag_off = 0; 203 memcpy(&pkt->ip6_hdr.dadr, ans->pkt.to, 16);
203 pkt->ip_hdr.ttl = 255; 204
204 pkt->ip_hdr.proto = IPPROTO_UDP; 205 /* set the udp-header */
205 pkt->ip_hdr.chks = 0; /* Will be calculated later */ 206 pkt->udp_dns.udp_hdr.spt = htons (53);
206 pkt->ip_hdr.sadr = ans->pkt.from; 207 pkt->udp_dns.udp_hdr.dpt = ans->pkt.dst_port;
207 pkt->ip_hdr.dadr = ans->pkt.to; 208 pkt->udp_dns.udp_hdr.len = htons (net_len - sizeof (struct ip6_hdr));
208 209 pkt->udp_dns.udp_hdr.crc = 0;
209 pkt->ip_hdr.chks = calculate_ip_checksum ((uint16_t *) & pkt->ip_hdr, 5 * 4); 210 uint32_t sum = 0;
210 211
211 /* set the udp-header */ 212 sum =
212 pkt->udp_dns.udp_hdr.spt = htons (53); 213 calculate_checksum_update (sum, (uint16_t *) & pkt->ip6_hdr.sadr, 16);
213 pkt->udp_dns.udp_hdr.dpt = ans->pkt.dst_port; 214 sum =
214 pkt->udp_dns.udp_hdr.len = htons (net_len - sizeof (struct ip_hdr)); 215 calculate_checksum_update (sum, (uint16_t *) & pkt->ip6_hdr.dadr, 16);
215 pkt->udp_dns.udp_hdr.crc = 0; /* Optional for IPv4 */ 216 uint32_t tmp = (pkt->udp_dns.udp_hdr.len & 0xffff);
216 217
217 memcpy (&pkt->udp_dns.data, ans->pkt.data, data_len); 218 sum = calculate_checksum_update (sum, (uint16_t *) & tmp, 4);
219 tmp = htons (((pkt->ip6_hdr.nxthdr & 0x00ff)));
220 sum = calculate_checksum_update (sum, (uint16_t *) & tmp, 4);
221
222 sum =
223 calculate_checksum_update (sum, (uint16_t *) & pkt->udp_dns.udp_hdr,
224 ntohs (net_len - sizeof(struct ip6_hdr)));
225 pkt->udp_dns.udp_hdr.crc = calculate_checksum_end (sum);
226
227 pkt->ip6_hdr.version = 6;
228 pkt->ip6_hdr.paylgth = net_len - sizeof (struct ip6_hdr);
229 pkt->ip6_hdr.nxthdr = IPPROTO_UDP;
230 pkt->ip6_hdr.hoplmt = 0xff;
231
232 memcpy (&pkt->udp_dns.data, ans->pkt.data, data_len);
233 buf = pkt;
234 }
235 else if (ans->pkt.addrlen == 4)
236 {
237 size_t net_len = sizeof (struct ip_hdr) + sizeof (struct udp_dns) + data_len;
238 pkt_len =
239 sizeof (struct GNUNET_MessageHeader) + sizeof (struct pkt_tun) + net_len;
240
241 struct ip_udp_dns *pkt = alloca (pkt_len);
242
243 GNUNET_assert (pkt != NULL);
244 memset (pkt, 0, pkt_len);
245
246 /* set the gnunet-header */
247 pkt->shdr.size = htons (pkt_len);
248 pkt->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
249
250 /* set the tun-header (no flags and ethertype of IPv4) */
251 pkt->tun.flags = 0;
252 pkt->tun.type = htons (0x0800);
253
254 /* set the ip-header */
255 pkt->ip_hdr.version = 4;
256 pkt->ip_hdr.hdr_lngth = 5;
257 pkt->ip_hdr.diff_serv = 0;
258 pkt->ip_hdr.tot_lngth = htons (net_len);
259 pkt->ip_hdr.ident = 0;
260 pkt->ip_hdr.flags = 0;
261 pkt->ip_hdr.frag_off = 0;
262 pkt->ip_hdr.ttl = 255;
263 pkt->ip_hdr.proto = IPPROTO_UDP;
264 pkt->ip_hdr.chks = 0; /* Will be calculated later */
265
266 memcpy(&pkt->ip_hdr.sadr, ans->pkt.from, 4);
267 memcpy(&pkt->ip_hdr.dadr, ans->pkt.to, 4);
268
269 pkt->ip_hdr.chks = calculate_ip_checksum ((uint16_t *) & pkt->ip_hdr, 5 * 4);
270
271 /* set the udp-header */
272 pkt->udp_dns.udp_hdr.spt = htons (53);
273 pkt->udp_dns.udp_hdr.dpt = ans->pkt.dst_port;
274 pkt->udp_dns.udp_hdr.len = htons (net_len - sizeof (struct ip_hdr));
275 pkt->udp_dns.udp_hdr.crc = 0; /* Optional for IPv4 */
276
277 memcpy (&pkt->udp_dns.data, ans->pkt.data, data_len);
278 buf = pkt;
279 }
218 280
219 GNUNET_CONTAINER_DLL_remove (answer_proc_head, answer_proc_tail, ans); 281 GNUNET_CONTAINER_DLL_remove (answer_proc_head, answer_proc_tail, ans);
220 GNUNET_free (ans); 282 GNUNET_free (ans);
221 283
222 if (GNUNET_DISK_file_write (helper_handle->fh_to_helper, pkt, pkt_len) < 0) 284 if (GNUNET_DISK_file_write (helper_handle->fh_to_helper, buf, pkt_len) < 0)
223 { 285 {
224 cleanup_helper (helper_handle); 286 cleanup_helper (helper_handle);
225 GNUNET_SCHEDULER_add_now (start_helper_and_schedule, NULL); 287 GNUNET_SCHEDULER_add_now (start_helper_and_schedule, NULL);
@@ -258,10 +320,36 @@ message_token (void *cls __attribute__ ((unused)), void *client
258 320
259 switch (pkt6->ip6_hdr.nxthdr) 321 switch (pkt6->ip6_hdr.nxthdr)
260 { 322 {
261 case IPPROTO_TCP:
262 case IPPROTO_UDP: 323 case IPPROTO_UDP:
263 pkt6_tcp = (struct ip6_tcp *) pkt6;
264 pkt6_udp = (struct ip6_udp *) pkt6; 324 pkt6_udp = (struct ip6_udp *) pkt6;
325 /* Send dns-packets to the service-dns */
326 if (ntohs (pkt6_udp->udp_hdr.dpt) == 53)
327 {
328 /* 9 = 8 for the udp-header + 1 for the unsigned char data[1]; */
329 size_t len = sizeof (struct query_packet) + ntohs (pkt6_udp->udp_hdr.len) - 9;
330
331 struct query_packet_list *query =
332 GNUNET_malloc (len + 2 * sizeof (struct query_packet_list *));
333 query->pkt.hdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_DNS_LOCAL_QUERY_DNS);
334 query->pkt.hdr.size = htons (len);
335 memcpy(query->pkt.orig_to, &pkt6->ip6_hdr.dadr, 16);
336 memcpy(query->pkt.orig_from, &pkt6->ip6_hdr.sadr, 16);
337 query->pkt.addrlen = 16;
338 query->pkt.src_port = pkt6_udp->udp_hdr.spt;
339 memcpy (query->pkt.data, pkt6_udp->data, ntohs (pkt6_udp->udp_hdr.len) - 8);
340
341 GNUNET_CONTAINER_DLL_insert_after (head, tail, tail, query);
342
343 GNUNET_assert (head != NULL);
344
345 if (dns_connection != NULL && dns_transmit_handle == NULL)
346 dns_transmit_handle = GNUNET_CLIENT_notify_transmit_ready (dns_connection, len,
347 GNUNET_TIME_UNIT_FOREVER_REL,
348 GNUNET_YES, &send_query, NULL);
349 break;
350 }
351 case IPPROTO_TCP:
352 pkt6_tcp = (struct ip6_tcp *) pkt6;
265 353
266 if ((key = address6_mapping_exists (pkt6->ip6_hdr.dadr)) != NULL) 354 if ((key = address6_mapping_exists (pkt6->ip6_hdr.dadr)) != NULL)
267 { 355 {
@@ -438,8 +526,9 @@ message_token (void *cls __attribute__ ((unused)), void *client
438 GNUNET_malloc (len + 2 * sizeof (struct query_packet_list *)); 526 GNUNET_malloc (len + 2 * sizeof (struct query_packet_list *));
439 query->pkt.hdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_DNS_LOCAL_QUERY_DNS); 527 query->pkt.hdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_DNS_LOCAL_QUERY_DNS);
440 query->pkt.hdr.size = htons (len); 528 query->pkt.hdr.size = htons (len);
441 query->pkt.orig_to = pkt->ip_hdr.dadr; 529 memcpy(query->pkt.orig_to, &pkt->ip_hdr.dadr, 4);
442 query->pkt.orig_from = pkt->ip_hdr.sadr; 530 memcpy(query->pkt.orig_from, &pkt->ip_hdr.sadr, 4);
531 query->pkt.addrlen = 4;
443 query->pkt.src_port = udp->udp_hdr.spt; 532 query->pkt.src_port = udp->udp_hdr.spt;
444 memcpy (query->pkt.data, udp->data, ntohs (udp->udp_hdr.len) - 8); 533 memcpy (query->pkt.data, udp->data, ntohs (udp->udp_hdr.len) - 8);
445 534
diff --git a/src/vpn/gnunet-service-dns-p.h b/src/vpn/gnunet-service-dns-p.h
index c48786d66..020700385 100644
--- a/src/vpn/gnunet-service-dns-p.h
+++ b/src/vpn/gnunet-service-dns-p.h
@@ -10,15 +10,16 @@ struct query_packet
10 /** 10 /**
11 * The IP-Address this query was originally sent to 11 * The IP-Address this query was originally sent to
12 */ 12 */
13 unsigned orig_to:32 GNUNET_PACKED; 13 char orig_to[16];
14 /** 14 /**
15 * The IP-Address this query was originally sent from 15 * The IP-Address this query was originally sent from
16 */ 16 */
17 unsigned orig_from:32 GNUNET_PACKED; 17 char orig_from[16];
18 /** 18 /**
19 * The UDP-Portthis query was originally sent from 19 * The UDP-Portthis query was originally sent from
20 */ 20 */
21 unsigned src_port:16 GNUNET_PACKED; 21 char addrlen;
22 uint16_t src_port GNUNET_PACKED;
22 23
23 unsigned char data[1]; /* The DNS-Packet */ 24 unsigned char data[1]; /* The DNS-Packet */
24}; 25};
@@ -76,8 +77,9 @@ struct answer_packet
76 struct GNUNET_MessageHeader hdr; 77 struct GNUNET_MessageHeader hdr;
77 enum GNUNET_DNS_ANSWER_Subtype subtype GNUNET_PACKED; 78 enum GNUNET_DNS_ANSWER_Subtype subtype GNUNET_PACKED;
78 79
79 unsigned from:32 GNUNET_PACKED; 80 char from[16];
80 unsigned to:32 GNUNET_PACKED; 81 char to[16];
82 char addrlen;
81 unsigned dst_port:16 GNUNET_PACKED; 83 unsigned dst_port:16 GNUNET_PACKED;
82 /* -- */ 84 /* -- */
83 85
diff --git a/src/vpn/gnunet-service-dns.c b/src/vpn/gnunet-service-dns.c
index 81f5cad98..38ce3c147 100644
--- a/src/vpn/gnunet-service-dns.c
+++ b/src/vpn/gnunet-service-dns.c
@@ -50,6 +50,7 @@ struct GNUNET_CONNECTION_TransmitHandle *server_notify;
50 * sent through gnunet. The port of this socket will not be hijacked. 50 * sent through gnunet. The port of this socket will not be hijacked.
51 */ 51 */
52static struct GNUNET_NETWORK_Handle *dnsout; 52static struct GNUNET_NETWORK_Handle *dnsout;
53static struct GNUNET_NETWORK_Handle *dnsout6;
53 54
54/** 55/**
55 * The port bound to the socket dnsout 56 * The port bound to the socket dnsout
@@ -90,8 +91,9 @@ static struct
90 unsigned valid:1; 91 unsigned valid:1;
91 struct GNUNET_SERVER_Client *client; 92 struct GNUNET_SERVER_Client *client;
92 struct GNUNET_MESH_Tunnel *tunnel; 93 struct GNUNET_MESH_Tunnel *tunnel;
93 uint32_t local_ip; 94 char local_ip[16];
94 uint32_t remote_ip; 95 char remote_ip[16];
96 char addrlen;
95 uint16_t local_port; 97 uint16_t local_port;
96 char *name; 98 char *name;
97 uint8_t namelen; 99 uint8_t namelen;
@@ -485,9 +487,9 @@ receive_mesh_answer (void *cls
485 memcpy (answer->pkt.addr, pdns->answers[0]->data, 487 memcpy (answer->pkt.addr, pdns->answers[0]->data,
486 ntohs (pdns->answers[0]->data_len)); 488 ntohs (pdns->answers[0]->data_len));
487 489
488 answer->pkt.from = query_states[dns->s.id].remote_ip; 490 memcpy(answer->pkt.from, query_states[dns->s.id].remote_ip, query_states[dns->s.id].addrlen);
489 491 memcpy(answer->pkt.to, query_states[dns->s.id].local_ip, query_states[dns->s.id].addrlen);
490 answer->pkt.to = query_states[dns->s.id].local_ip; 492 answer->pkt.addrlen = query_states[dns->s.id].addrlen;
491 answer->pkt.dst_port = query_states[dns->s.id].local_port; 493 answer->pkt.dst_port = query_states[dns->s.id].local_port;
492 494
493 struct dns_pkt *dpkt = (struct dns_pkt *) answer->pkt.data; 495 struct dns_pkt *dpkt = (struct dns_pkt *) answer->pkt.data;
@@ -589,9 +591,9 @@ send_rev_query (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
589 answer->pkt.hdr.size = htons (len); 591 answer->pkt.hdr.size = htons (len);
590 answer->pkt.subtype = GNUNET_DNS_ANSWER_TYPE_REV; 592 answer->pkt.subtype = GNUNET_DNS_ANSWER_TYPE_REV;
591 593
592 answer->pkt.from = query_states[id].remote_ip; 594 memcpy(answer->pkt.from, query_states[id].remote_ip, query_states[id].addrlen);
595 memcpy(answer->pkt.to, query_states[id].local_ip, query_states[id].addrlen);
593 596
594 answer->pkt.to = query_states[id].local_ip;
595 answer->pkt.dst_port = query_states[id].local_port; 597 answer->pkt.dst_port = query_states[id].local_port;
596 598
597 struct dns_pkt *dpkt = (struct dns_pkt *) answer->pkt.data; 599 struct dns_pkt *dpkt = (struct dns_pkt *) answer->pkt.data;
@@ -700,9 +702,9 @@ receive_dht (void *cls, struct GNUNET_TIME_Absolute exp
700 memcpy (&answer->pkt.service_descr.ports, &rec->ports, 702 memcpy (&answer->pkt.service_descr.ports, &rec->ports,
701 sizeof (answer->pkt.service_descr.ports)); 703 sizeof (answer->pkt.service_descr.ports));
702 704
703 answer->pkt.from = query_states[id].remote_ip; 705 memcpy(answer->pkt.from, query_states[id].remote_ip, query_states[id].addrlen);
706 memcpy(answer->pkt.to, query_states[id].local_ip, query_states[id].addrlen);
704 707
705 answer->pkt.to = query_states[id].local_ip;
706 answer->pkt.dst_port = query_states[id].local_port; 708 answer->pkt.dst_port = query_states[id].local_port;
707 709
708 struct dns_pkt *dpkt = (struct dns_pkt *) answer->pkt.data; 710 struct dns_pkt *dpkt = (struct dns_pkt *) answer->pkt.data;
@@ -784,9 +786,10 @@ receive_query (void *cls
784 786
785 query_states[dns->s.id].valid = GNUNET_YES; 787 query_states[dns->s.id].valid = GNUNET_YES;
786 query_states[dns->s.id].client = client; 788 query_states[dns->s.id].client = client;
787 query_states[dns->s.id].local_ip = pkt->orig_from; 789 memcpy(query_states[dns->s.id].local_ip, pkt->orig_from, pkt->addrlen);
790 query_states[dns->s.id].addrlen = pkt->addrlen;
788 query_states[dns->s.id].local_port = pkt->src_port; 791 query_states[dns->s.id].local_port = pkt->src_port;
789 query_states[dns->s.id].remote_ip = pkt->orig_to; 792 memcpy(query_states[dns->s.id].remote_ip, pkt->orig_to, pkt->addrlen);
790 query_states[dns->s.id].namelen = strlen ((char *) dns->data) + 1; 793 query_states[dns->s.id].namelen = strlen ((char *) dns->data) + 1;
791 if (query_states[dns->s.id].name != NULL) 794 if (query_states[dns->s.id].name != NULL)
792 GNUNET_free (query_states[dns->s.id].name); 795 GNUNET_free (query_states[dns->s.id].name);
@@ -883,27 +886,56 @@ receive_query (void *cls
883 } 886 }
884 } 887 }
885 888
886 char *virt_dns; 889 unsigned char virt_dns_bytes[16];
887 unsigned int virt_dns_bytes;
888 890
889 if (GNUNET_SYSERR == 891 if (pkt->addrlen == 4)
890 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "VIRTDNS", &virt_dns)) 892 {
891 { 893 char *virt_dns;
892 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
893 "No entry 'VIRTDNS' in configuration!\n");
894 exit (1);
895 }
896 894
897 if (1 != inet_pton (AF_INET, virt_dns, &virt_dns_bytes)) 895 if (GNUNET_SYSERR ==
898 { 896 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "VIRTDNS", &virt_dns))
899 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error parsing 'VIRTDNS': %s; %m!\n", 897 {
900 virt_dns); 898 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
901 exit (1); 899 "No entry 'VIRTDNS' in configuration!\n");
902 } 900 exit (1);
901 }
903 902
904 GNUNET_free (virt_dns); 903 if (1 != inet_pton (AF_INET, virt_dns, &virt_dns_bytes))
904 {
905 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error parsing 'VIRTDNS': %s; %m!\n",
906 virt_dns);
907 exit (1);
908 }
909
910 GNUNET_free (virt_dns);
911 }
912 else if (pkt->addrlen == 16)
913 {
914 char *virt_dns;
915
916 if (GNUNET_SYSERR ==
917 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "VIRTDNS6", &virt_dns))
918 {
919 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
920 "No entry 'VIRTDNS6' in configuration!\n");
921 exit (1);
922 }
923
924 if (1 != inet_pton (AF_INET6, virt_dns, &virt_dns_bytes))
925 {
926 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error parsing 'VIRTDNS6': %s; %m!\n",
927 virt_dns);
928 exit (1);
929 }
930
931 GNUNET_free (virt_dns);
932 }
933 else
934 {
935 GNUNET_assert(0);
936 }
905 937
906 if (virt_dns_bytes == pkt->orig_to) 938 if (memcmp(virt_dns_bytes,pkt->orig_to, pkt->addrlen) == 0)
907 { 939 {
908 /* This is a packet that was sent directly to the virtual dns-server 940 /* This is a packet that was sent directly to the virtual dns-server
909 * 941 *
@@ -958,17 +990,32 @@ receive_query (void *cls
958 990
959 991
960 /* The query should be sent to the network */ 992 /* The query should be sent to the network */
993 if (pkt->addrlen == 4)
994 {
995 struct sockaddr_in dest;
961 996
962 struct sockaddr_in dest; 997 memset (&dest, 0, sizeof dest);
998 dest.sin_port = htons (53);
999 memcpy(&dest.sin_addr.s_addr, pkt->orig_to, pkt->addrlen);
963 1000
964 memset (&dest, 0, sizeof dest); 1001 GNUNET_NETWORK_socket_sendto (dnsout, dns,
965 dest.sin_port = htons (53); 1002 ntohs (pkt->hdr.size) -
966 dest.sin_addr.s_addr = pkt->orig_to; 1003 sizeof (struct query_packet) + 1,
1004 (struct sockaddr *) &dest, sizeof dest);
1005 }
1006 else if (pkt->addrlen == 16)
1007 {
1008 struct sockaddr_in6 dest;
967 1009
968 GNUNET_NETWORK_socket_sendto (dnsout, dns, 1010 memset (&dest, 0, sizeof dest);
969 ntohs (pkt->hdr.size) - 1011 dest.sin6_port = htons (53);
970 sizeof (struct query_packet) + 1, 1012 memcpy(&dest.sin6_addr, pkt->orig_to, pkt->addrlen);
971 (struct sockaddr *) &dest, sizeof dest); 1013
1014 GNUNET_NETWORK_socket_sendto (dnsout6, dns,
1015 ntohs (pkt->hdr.size) -
1016 sizeof (struct query_packet) + 1,
1017 (struct sockaddr *) &dest, sizeof dest);
1018 }
972 1019
973outfree: 1020outfree:
974 free_parsed_dns_packet (pdns); 1021 free_parsed_dns_packet (pdns);
@@ -980,6 +1027,39 @@ out:
980static void 1027static void
981read_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); 1028read_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
982 1029
1030static void
1031read_response6 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
1032
1033static int
1034open_port6 ()
1035{
1036 struct sockaddr_in6 addr;
1037
1038 dnsout6 = GNUNET_NETWORK_socket_create (AF_INET6, SOCK_DGRAM, 0);
1039 if (dnsout6 == NULL)
1040 {
1041 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not create socket: %m\n");
1042 return GNUNET_SYSERR;
1043 }
1044 memset (&addr, 0, sizeof (struct sockaddr_in6));
1045
1046 addr.sin6_family = AF_INET6;
1047 int err = GNUNET_NETWORK_socket_bind (dnsout6,
1048 (struct sockaddr *) &addr,
1049 sizeof (struct sockaddr_in6));
1050
1051 if (err != GNUNET_OK)
1052 {
1053 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not bind a port: %m\n");
1054 return GNUNET_SYSERR;
1055 }
1056
1057 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, dnsout6,
1058 &read_response6, NULL);
1059
1060 return GNUNET_YES;
1061}
1062
983static int 1063static int
984open_port () 1064open_port ()
985{ 1065{
@@ -1018,6 +1098,57 @@ open_port ()
1018 return GNUNET_YES; 1098 return GNUNET_YES;
1019} 1099}
1020 1100
1101void handle_response(struct dns_pkt* dns, struct sockaddr *addr, socklen_t addrlen, int r);
1102
1103/**
1104 * Read a response-packet of the UDP-Socket
1105 */
1106static void
1107read_response6 (void *cls
1108 __attribute__ ((unused)),
1109 const struct GNUNET_SCHEDULER_TaskContext *tc)
1110{
1111 struct sockaddr_in6 addr;
1112 socklen_t addrlen = sizeof (addr);
1113 int r;
1114 int len;
1115
1116 if (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)
1117 return;
1118
1119 memset (&addr, 0, sizeof addr);
1120
1121#ifndef MINGW
1122 if (0 != ioctl (GNUNET_NETWORK_get_fd (dnsout6), FIONREAD, &len))
1123 {
1124 (void)open_port6 ();
1125 return;
1126 }
1127#else
1128 /* port the code above? */
1129 len = 65536;
1130#endif
1131
1132 unsigned char buf[len];
1133 struct dns_pkt *dns = (struct dns_pkt *) buf;
1134
1135 r = GNUNET_NETWORK_socket_recvfrom (dnsout, buf, sizeof (buf),
1136 (struct sockaddr *) &addr, &addrlen);
1137
1138 if (r < 0)
1139 {
1140 (void)open_port6 ();
1141 return;
1142 }
1143
1144 struct sockaddr *addr_ = GNUNET_malloc(sizeof addr);
1145 memcpy (addr_, &addr, sizeof addr);
1146 handle_response(dns, addr_, 4, r);
1147
1148 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, dnsout6,
1149 &read_response6, NULL);
1150}
1151
1021/** 1152/**
1022 * Read a response-packet of the UDP-Socket 1153 * Read a response-packet of the UDP-Socket
1023 */ 1154 */
@@ -1050,14 +1181,14 @@ read_response (void *cls
1050 /* port the code above? */ 1181 /* port the code above? */
1051 len = 65536; 1182 len = 65536;
1052#endif 1183#endif
1053 {
1054 unsigned char buf[len];
1055 struct dns_pkt *dns = (struct dns_pkt *) buf;
1056 1184
1057 r = GNUNET_NETWORK_socket_recvfrom (dnsout, buf, sizeof (buf), 1185 unsigned char buf[len];
1058 (struct sockaddr *) &addr, &addrlen); 1186 struct dns_pkt *dns = (struct dns_pkt *) buf;
1059 1187
1060 if (r < 0) 1188 r = GNUNET_NETWORK_socket_recvfrom (dnsout, buf, sizeof (buf),
1189 (struct sockaddr *) &addr, &addrlen);
1190
1191 if (r < 0)
1061 { 1192 {
1062 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, 1193 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
1063 "recvfrom"); 1194 "recvfrom");
@@ -1067,86 +1198,112 @@ read_response (void *cls
1067 return; 1198 return;
1068 } 1199 }
1069 1200
1070 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Answer to query %d\n", 1201 struct sockaddr *addr_ = GNUNET_malloc(sizeof addr);
1071 ntohs (dns->s.id)); 1202 memcpy (addr_, &addr, sizeof addr);
1203 handle_response(dns, addr_, 4, r);
1204
1205 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, dnsout,
1206 &read_response, NULL);
1207}
1208
1209void
1210handle_response(struct dns_pkt* dns, struct sockaddr *addr, socklen_t addrlen, int r)
1211{
1212 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Answer to query %d\n",
1213 ntohs (dns->s.id));
1214
1072 1215
1073 if (query_states[dns->s.id].valid == GNUNET_YES) 1216 if (query_states[dns->s.id].valid == GNUNET_YES)
1074 { 1217 {
1075 if (query_states[dns->s.id].tunnel != NULL) 1218 if (query_states[dns->s.id].tunnel != NULL)
1076 {
1077 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1078 "Answer to query %d for a remote peer!\n",
1079 ntohs (dns->s.id));
1080 /* This response should go through a tunnel */
1081 uint32_t *c =
1082 GNUNET_malloc (4 + sizeof (struct GNUNET_MESH_Tunnel *) + r);
1083 *c = r;
1084 struct GNUNET_MESH_Tunnel **t = (struct GNUNET_MESH_Tunnel **) (c + 1);
1085
1086 *t = query_states[dns->s.id].tunnel;
1087 memcpy (t + 1, dns, r);
1088 if (NULL ==
1089 GNUNET_MESH_tunnel_get_data (query_states[dns->s.id].tunnel))
1090 { 1219 {
1091 struct GNUNET_MESH_TransmitHandle *th = 1220 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1092 GNUNET_MESH_notify_transmit_ready (query_states[dns->s.id].tunnel, 1221 "Answer to query %d for a remote peer!\n",
1093 GNUNET_YES, 1222 ntohs (dns->s.id));
1094 32, 1223 /* This response should go through a tunnel */
1095 GNUNET_TIME_UNIT_MINUTES, 1224 uint32_t *c =
1096 NULL, 1225 GNUNET_malloc (4 + sizeof (struct GNUNET_MESH_Tunnel *) + r);
1097 r + 1226 *c = r;
1098 sizeof (struct 1227 struct GNUNET_MESH_Tunnel **t = (struct GNUNET_MESH_Tunnel **) (c + 1);
1099 GNUNET_MessageHeader), 1228
1100 mesh_send_response, c); 1229 *t = query_states[dns->s.id].tunnel;
1101 1230 memcpy (t + 1, dns, r);
1102 GNUNET_MESH_tunnel_set_data (query_states[dns->s.id].tunnel, th); 1231 if (NULL ==
1103 } 1232 GNUNET_MESH_tunnel_get_data (query_states[dns->s.id].tunnel))
1104 else 1233 {
1105 { 1234 struct GNUNET_MESH_TransmitHandle *th =
1106 struct tunnel_notify_queue *head = 1235 GNUNET_MESH_notify_transmit_ready (query_states[dns->s.id].tunnel,
1107 GNUNET_MESH_tunnel_get_head (query_states[dns->s.id].tunnel); 1236 GNUNET_YES,
1108 struct tunnel_notify_queue *tail = 1237 32,
1109 GNUNET_MESH_tunnel_get_tail (query_states[dns->s.id].tunnel); 1238 GNUNET_TIME_UNIT_MINUTES,
1110 1239 NULL,
1111 struct tunnel_notify_queue *element = 1240 r +
1112 GNUNET_malloc (sizeof (struct tunnel_notify_queue)); 1241 sizeof (struct
1113 element->cls = c; 1242 GNUNET_MessageHeader),
1114 element->len = r + sizeof (struct GNUNET_MessageHeader); 1243 mesh_send_response, c);
1115 element->cb = mesh_send_response; 1244
1116 1245 GNUNET_MESH_tunnel_set_data (query_states[dns->s.id].tunnel, th);
1117 GNUNET_CONTAINER_DLL_insert_tail (head, tail, element); 1246 }
1118 GNUNET_MESH_tunnel_set_head (query_states[dns->s.id].tunnel, head); 1247 else
1119 GNUNET_MESH_tunnel_set_tail (query_states[dns->s.id].tunnel, tail); 1248 {
1249 struct tunnel_notify_queue *head =
1250 GNUNET_MESH_tunnel_get_head (query_states[dns->s.id].tunnel);
1251 struct tunnel_notify_queue *tail =
1252 GNUNET_MESH_tunnel_get_tail (query_states[dns->s.id].tunnel);
1253
1254 struct tunnel_notify_queue *element =
1255 GNUNET_malloc (sizeof (struct tunnel_notify_queue));
1256 element->cls = c;
1257 element->len = r + sizeof (struct GNUNET_MessageHeader);
1258 element->cb = mesh_send_response;
1259
1260 GNUNET_CONTAINER_DLL_insert_tail (head, tail, element);
1261 GNUNET_MESH_tunnel_set_head (query_states[dns->s.id].tunnel, head);
1262 GNUNET_MESH_tunnel_set_tail (query_states[dns->s.id].tunnel, tail);
1263 }
1120 } 1264 }
1121 }
1122 else 1265 else
1123 { 1266 {
1124 query_states[dns->s.id].valid = GNUNET_NO; 1267 query_states[dns->s.id].valid = GNUNET_NO;
1125 1268
1126 size_t len = sizeof (struct answer_packet) + r - 1; /* 1 for the unsigned char data[1]; */ 1269 size_t len = sizeof (struct answer_packet) + r - 1; /* 1 for the unsigned char data[1]; */
1127 struct answer_packet_list *answer = 1270 struct answer_packet_list *answer =
1128 GNUNET_malloc (len + 2 * sizeof (struct answer_packet_list *)); 1271 GNUNET_malloc (len + 2 * sizeof (struct answer_packet_list *));
1129 answer->pkt.hdr.type = 1272 answer->pkt.hdr.type =
1130 htons (GNUNET_MESSAGE_TYPE_VPN_DNS_LOCAL_RESPONSE_DNS); 1273 htons (GNUNET_MESSAGE_TYPE_VPN_DNS_LOCAL_RESPONSE_DNS);
1131 answer->pkt.hdr.size = htons (len); 1274 answer->pkt.hdr.size = htons (len);
1132 answer->pkt.subtype = GNUNET_DNS_ANSWER_TYPE_IP; 1275 answer->pkt.subtype = GNUNET_DNS_ANSWER_TYPE_IP;
1133 answer->pkt.from = addr.sin_addr.s_addr; 1276 answer->pkt.addrlen = addrlen;
1134 answer->pkt.to = query_states[dns->s.id].local_ip; 1277 if (addrlen == 16)
1135 answer->pkt.dst_port = query_states[dns->s.id].local_port; 1278 {
1136 memcpy (answer->pkt.data, buf, r); 1279 struct sockaddr_in6 *addr_ = (struct sockaddr_in6*)addr;
1137 1280 memcpy(answer->pkt.from, &addr_->sin6_addr, addrlen);
1138 GNUNET_CONTAINER_DLL_insert_after (head, tail, tail, answer); 1281 memcpy(answer->pkt.to, query_states[dns->s.id].local_ip, addrlen);
1139 1282 }
1140 if (server_notify == NULL) 1283 else if (addrlen == 4)
1141 server_notify = GNUNET_SERVER_notify_transmit_ready (query_states[dns->s.id].client, 1284 {
1142 len, GNUNET_TIME_UNIT_FOREVER_REL, 1285 struct sockaddr_in *addr_ = (struct sockaddr_in*)addr;
1143 &send_answer, 1286 memcpy(answer->pkt.from, &addr_->sin_addr.s_addr, addrlen);
1144 query_states[dns->s.id].client); 1287 memcpy(answer->pkt.to, query_states[dns->s.id].local_ip, addrlen);
1145 } 1288 }
1289 else
1290 {
1291 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "addrlen = %d\n", addrlen);
1292 GNUNET_assert(0);
1293 }
1294 answer->pkt.dst_port = query_states[dns->s.id].local_port;
1295 memcpy (answer->pkt.data, dns, r);
1296
1297 GNUNET_CONTAINER_DLL_insert_after (head, tail, tail, answer);
1298
1299 if (server_notify == NULL)
1300 server_notify = GNUNET_SERVER_notify_transmit_ready (query_states[dns->s.id].client,
1301 len, GNUNET_TIME_UNIT_FOREVER_REL,
1302 &send_answer,
1303 query_states[dns->s.id].client);
1304 }
1146 } 1305 }
1147 } 1306 GNUNET_free(addr);
1148 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, dnsout,
1149 &read_response, NULL);
1150} 1307}
1151 1308
1152 1309
@@ -1422,6 +1579,11 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
1422 GNUNET_APPLICATION_TYPE_END 1579 GNUNET_APPLICATION_TYPE_END
1423 }; 1580 };
1424 1581
1582 if (GNUNET_YES != open_port6 ())
1583 {
1584 GNUNET_SCHEDULER_shutdown ();
1585 return;
1586 }
1425 1587
1426 if (GNUNET_YES != open_port ()) 1588 if (GNUNET_YES != open_port ())
1427 { 1589 {
diff --git a/src/vpn/gnunet-vpn-packet.h b/src/vpn/gnunet-vpn-packet.h
index 47fa69847..e2082f9a1 100644
--- a/src/vpn/gnunet-vpn-packet.h
+++ b/src/vpn/gnunet-vpn-packet.h
@@ -40,8 +40,8 @@ struct ip_hdr
40 unsigned proto:8 GNUNET_PACKED; 40 unsigned proto:8 GNUNET_PACKED;
41 unsigned chks:16 GNUNET_PACKED; 41 unsigned chks:16 GNUNET_PACKED;
42 42
43 unsigned sadr:32 GNUNET_PACKED; 43 uint32_t sadr GNUNET_PACKED;
44 unsigned dadr:32 GNUNET_PACKED; 44 uint32_t dadr GNUNET_PACKED;
45}; 45};
46 46
47#define TCP_FLAG_SYN 2 47#define TCP_FLAG_SYN 2