diff options
author | Philipp Tölke <toelke@in.tum.de> | 2011-10-26 07:13:23 +0000 |
---|---|---|
committer | Philipp Tölke <toelke@in.tum.de> | 2011-10-26 07:13:23 +0000 |
commit | 913f88d980ef4fcc4153336042387a17ad8e428b (patch) | |
tree | f7bc0d3e34dc0b84810dd44a0025cfea69e9aa95 /src/vpn | |
parent | 9095e6a2fc69654f993c37c0e5e4159dbd88028d (diff) | |
download | gnunet-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.c | 179 | ||||
-rw-r--r-- | src/vpn/gnunet-service-dns-p.h | 12 | ||||
-rw-r--r-- | src/vpn/gnunet-service-dns.c | 386 | ||||
-rw-r--r-- | src/vpn/gnunet-vpn-packet.h | 4 |
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 | */ |
52 | static struct GNUNET_NETWORK_Handle *dnsout; | 52 | static struct GNUNET_NETWORK_Handle *dnsout; |
53 | static 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 | ||
973 | outfree: | 1020 | outfree: |
974 | free_parsed_dns_packet (pdns); | 1021 | free_parsed_dns_packet (pdns); |
@@ -980,6 +1027,39 @@ out: | |||
980 | static void | 1027 | static void |
981 | read_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | 1028 | read_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); |
982 | 1029 | ||
1030 | static void | ||
1031 | read_response6 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
1032 | |||
1033 | static int | ||
1034 | open_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 | |||
983 | static int | 1063 | static int |
984 | open_port () | 1064 | open_port () |
985 | { | 1065 | { |
@@ -1018,6 +1098,57 @@ open_port () | |||
1018 | return GNUNET_YES; | 1098 | return GNUNET_YES; |
1019 | } | 1099 | } |
1020 | 1100 | ||
1101 | void 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 | */ | ||
1106 | static void | ||
1107 | read_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 | |||
1209 | void | ||
1210 | handle_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 |