diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-01-02 09:57:25 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-01-02 09:57:25 +0000 |
commit | 2b152f749e6274ab97baa09b9d1522803c76027f (patch) | |
tree | ea5e4857b6de87cb3ad79da334c6d61e213cd54a /src/vpn/gnunet-daemon-vpn.c | |
parent | a0f00b8f5726eccb6eab9bcf974c3e45ab572220 (diff) | |
download | gnunet-2b152f749e6274ab97baa09b9d1522803c76027f.tar.gz gnunet-2b152f749e6274ab97baa09b9d1522803c76027f.zip |
-using new GNUNET_HELPER_ API inside of VPN, also eliminating bugs with partial writes as part of this
Diffstat (limited to 'src/vpn/gnunet-daemon-vpn.c')
-rw-r--r-- | src/vpn/gnunet-daemon-vpn.c | 656 |
1 files changed, 636 insertions, 20 deletions
diff --git a/src/vpn/gnunet-daemon-vpn.c b/src/vpn/gnunet-daemon-vpn.c index 7d303ecd5..35db8af7b 100644 --- a/src/vpn/gnunet-daemon-vpn.c +++ b/src/vpn/gnunet-daemon-vpn.c | |||
@@ -35,7 +35,6 @@ | |||
35 | #include "gnunet_container_lib.h" | 35 | #include "gnunet_container_lib.h" |
36 | #include "gnunet_constants.h" | 36 | #include "gnunet_constants.h" |
37 | #include <block_dns.h> | 37 | #include <block_dns.h> |
38 | #include "gnunet-daemon-vpn-helper.h" | ||
39 | #include "gnunet_dns_service.h" | 38 | #include "gnunet_dns_service.h" |
40 | #include "gnunet-daemon-vpn.h" | 39 | #include "gnunet-daemon-vpn.h" |
41 | #include "gnunet-vpn-checksum.h" | 40 | #include "gnunet-vpn-checksum.h" |
@@ -45,6 +44,16 @@ struct GNUNET_MESH_Handle *mesh_handle; | |||
45 | struct GNUNET_CONTAINER_MultiHashMap *hashmap; | 44 | struct GNUNET_CONTAINER_MultiHashMap *hashmap; |
46 | static struct GNUNET_CONTAINER_Heap *heap; | 45 | static struct GNUNET_CONTAINER_Heap *heap; |
47 | 46 | ||
47 | /** | ||
48 | * The handle to the helper | ||
49 | */ | ||
50 | static struct GNUNET_HELPER_Handle *helper_handle; | ||
51 | |||
52 | /** | ||
53 | * Arguments to the exit helper. | ||
54 | */ | ||
55 | static char *vpn_argv[7]; | ||
56 | |||
48 | struct GNUNET_DNS_Handle *dns_handle; | 57 | struct GNUNET_DNS_Handle *dns_handle; |
49 | 58 | ||
50 | struct answer_packet_list *answer_proc_head; | 59 | struct answer_packet_list *answer_proc_head; |
@@ -82,6 +91,14 @@ GNUNET_SCHEDULER_TaskIdentifier shs_task; | |||
82 | 91 | ||
83 | 92 | ||
84 | /** | 93 | /** |
94 | * The tunnels that will be used to send tcp- and udp-packets | ||
95 | */ | ||
96 | static struct GNUNET_MESH_Tunnel *tcp_tunnel; | ||
97 | static struct GNUNET_MESH_Tunnel *udp_tunnel; | ||
98 | |||
99 | |||
100 | |||
101 | /** | ||
85 | * Sets a bit active in a bitArray. | 102 | * Sets a bit active in a bitArray. |
86 | * | 103 | * |
87 | * @param bitArray memory area to set the bit in | 104 | * @param bitArray memory area to set the bit in |
@@ -129,11 +146,9 @@ static void | |||
129 | cleanup (void *cls GNUNET_UNUSED, | 146 | cleanup (void *cls GNUNET_UNUSED, |
130 | const struct GNUNET_SCHEDULER_TaskContext *tskctx) | 147 | const struct GNUNET_SCHEDULER_TaskContext *tskctx) |
131 | { | 148 | { |
132 | GNUNET_assert (0 != (tskctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)); | 149 | unsigned int i; |
133 | |||
134 | /* stop the helper */ | ||
135 | cleanup_helper (helper_handle); | ||
136 | 150 | ||
151 | GNUNET_assert (0 != (tskctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)); | ||
137 | /* close the connection to the service-dns */ | 152 | /* close the connection to the service-dns */ |
138 | GNUNET_DNS_disconnect (dns_handle); | 153 | GNUNET_DNS_disconnect (dns_handle); |
139 | if (mesh_handle != NULL) | 154 | if (mesh_handle != NULL) |
@@ -141,6 +156,11 @@ cleanup (void *cls GNUNET_UNUSED, | |||
141 | GNUNET_MESH_disconnect (mesh_handle); | 156 | GNUNET_MESH_disconnect (mesh_handle); |
142 | mesh_handle = NULL; | 157 | mesh_handle = NULL; |
143 | } | 158 | } |
159 | if (helper_handle != NULL) | ||
160 | { | ||
161 | GNUNET_HELPER_stop (helper_handle); | ||
162 | helper_handle = NULL; | ||
163 | } | ||
144 | if (GNUNET_SCHEDULER_NO_TASK != shs_task) | 164 | if (GNUNET_SCHEDULER_NO_TASK != shs_task) |
145 | { | 165 | { |
146 | GNUNET_SCHEDULER_cancel (shs_task); | 166 | GNUNET_SCHEDULER_cancel (shs_task); |
@@ -151,6 +171,8 @@ cleanup (void *cls GNUNET_UNUSED, | |||
151 | GNUNET_SCHEDULER_cancel (conn_task); | 171 | GNUNET_SCHEDULER_cancel (conn_task); |
152 | conn_task = GNUNET_SCHEDULER_NO_TASK; | 172 | conn_task = GNUNET_SCHEDULER_NO_TASK; |
153 | } | 173 | } |
174 | for (i=0;i<5;i++) | ||
175 | GNUNET_free_non_null (vpn_argv[i]); | ||
154 | } | 176 | } |
155 | 177 | ||
156 | /*}}}*/ | 178 | /*}}}*/ |
@@ -210,6 +232,532 @@ address4_mapping_exists (uint32_t addr) | |||
210 | } | 232 | } |
211 | } | 233 | } |
212 | 234 | ||
235 | |||
236 | static void * | ||
237 | initialize_tunnel_state (int addrlen, struct GNUNET_MESH_TransmitHandle *th) | ||
238 | { | ||
239 | struct tunnel_state *ts = GNUNET_malloc (sizeof *ts); | ||
240 | |||
241 | ts->addrlen = addrlen; | ||
242 | ts->th = th; | ||
243 | return ts; | ||
244 | } | ||
245 | |||
246 | /** | ||
247 | * Send an dns-answer-packet to the helper | ||
248 | */ | ||
249 | void | ||
250 | helper_write (void *cls GNUNET_UNUSED, | ||
251 | int status) | ||
252 | { | ||
253 | struct answer_packet_list *ans = answer_proc_head; | ||
254 | |||
255 | if (NULL == ans) | ||
256 | return; | ||
257 | if (GNUNET_SYSERR == status) | ||
258 | return; | ||
259 | |||
260 | size_t len = ntohs (ans->pkt.hdr.size); | ||
261 | |||
262 | GNUNET_assert (ans->pkt.subtype == GNUNET_DNS_ANSWER_TYPE_IP); | ||
263 | |||
264 | GNUNET_assert (20 == sizeof (struct ip_hdr)); | ||
265 | GNUNET_assert (8 == sizeof (struct udp_pkt)); | ||
266 | |||
267 | size_t data_len = len - sizeof (struct answer_packet) + 1; | ||
268 | |||
269 | size_t pkt_len; | ||
270 | |||
271 | if (ans->pkt.addrlen == 16) | ||
272 | { | ||
273 | size_t net_len = | ||
274 | sizeof (struct ip6_hdr) + sizeof (struct udp_dns) + data_len; | ||
275 | pkt_len = | ||
276 | sizeof (struct GNUNET_MessageHeader) + sizeof (struct pkt_tun) + | ||
277 | net_len; | ||
278 | |||
279 | struct ip6_udp_dns *pkt = alloca (pkt_len); | ||
280 | |||
281 | GNUNET_assert (pkt != NULL); | ||
282 | memset (pkt, 0, pkt_len); | ||
283 | |||
284 | /* set the gnunet-header */ | ||
285 | pkt->shdr.size = htons (pkt_len); | ||
286 | pkt->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); | ||
287 | |||
288 | /* set the tun-header (no flags and ethertype of IPv4) */ | ||
289 | pkt->tun.flags = 0; | ||
290 | pkt->tun.type = htons (0x86dd); | ||
291 | |||
292 | memcpy (&pkt->ip6_hdr.sadr, ans->pkt.from, 16); | ||
293 | memcpy (&pkt->ip6_hdr.dadr, ans->pkt.to, 16); | ||
294 | |||
295 | /* set the udp-header */ | ||
296 | pkt->udp_dns.udp_hdr.spt = htons (53); | ||
297 | pkt->udp_dns.udp_hdr.dpt = ans->pkt.dst_port; | ||
298 | pkt->udp_dns.udp_hdr.len = htons (net_len - sizeof (struct ip6_hdr)); | ||
299 | pkt->udp_dns.udp_hdr.crc = 0; | ||
300 | uint32_t sum = 0; | ||
301 | |||
302 | sum = calculate_checksum_update (sum, (uint16_t *) & pkt->ip6_hdr.sadr, 16); | ||
303 | sum = calculate_checksum_update (sum, (uint16_t *) & pkt->ip6_hdr.dadr, 16); | ||
304 | uint32_t tmp = (pkt->udp_dns.udp_hdr.len & 0xffff); | ||
305 | |||
306 | sum = calculate_checksum_update (sum, (uint16_t *) & tmp, 4); | ||
307 | tmp = htons (((pkt->ip6_hdr.nxthdr & 0x00ff))); | ||
308 | sum = calculate_checksum_update (sum, (uint16_t *) & tmp, 4); | ||
309 | |||
310 | sum = | ||
311 | calculate_checksum_update (sum, (uint16_t *) & pkt->udp_dns.udp_hdr, | ||
312 | ntohs (net_len - sizeof (struct ip6_hdr))); | ||
313 | pkt->udp_dns.udp_hdr.crc = calculate_checksum_end (sum); | ||
314 | |||
315 | pkt->ip6_hdr.version = 6; | ||
316 | pkt->ip6_hdr.paylgth = net_len - sizeof (struct ip6_hdr); | ||
317 | pkt->ip6_hdr.nxthdr = IPPROTO_UDP; | ||
318 | pkt->ip6_hdr.hoplmt = 0xff; | ||
319 | |||
320 | memcpy (&pkt->udp_dns.data, ans->pkt.data, data_len); | ||
321 | (void) GNUNET_HELPER_send (helper_handle, | ||
322 | &pkt->shdr, | ||
323 | GNUNET_YES, | ||
324 | &helper_write, NULL); | ||
325 | } | ||
326 | else if (ans->pkt.addrlen == 4) | ||
327 | { | ||
328 | size_t net_len = | ||
329 | sizeof (struct ip_hdr) + sizeof (struct udp_dns) + data_len; | ||
330 | pkt_len = | ||
331 | sizeof (struct GNUNET_MessageHeader) + sizeof (struct pkt_tun) + | ||
332 | net_len; | ||
333 | |||
334 | struct ip_udp_dns *pkt = alloca (pkt_len); | ||
335 | |||
336 | GNUNET_assert (pkt != NULL); | ||
337 | memset (pkt, 0, pkt_len); | ||
338 | |||
339 | /* set the gnunet-header */ | ||
340 | pkt->shdr.size = htons (pkt_len); | ||
341 | pkt->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); | ||
342 | |||
343 | /* set the tun-header (no flags and ethertype of IPv4) */ | ||
344 | pkt->tun.flags = 0; | ||
345 | pkt->tun.type = htons (0x0800); | ||
346 | |||
347 | /* set the ip-header */ | ||
348 | pkt->ip_hdr.version = 4; | ||
349 | pkt->ip_hdr.hdr_lngth = 5; | ||
350 | pkt->ip_hdr.diff_serv = 0; | ||
351 | pkt->ip_hdr.tot_lngth = htons (net_len); | ||
352 | pkt->ip_hdr.ident = 0; | ||
353 | pkt->ip_hdr.flags = 0; | ||
354 | pkt->ip_hdr.frag_off = 0; | ||
355 | pkt->ip_hdr.ttl = 255; | ||
356 | pkt->ip_hdr.proto = IPPROTO_UDP; | ||
357 | pkt->ip_hdr.chks = 0; /* Will be calculated later */ | ||
358 | |||
359 | memcpy (&pkt->ip_hdr.sadr, ans->pkt.from, 4); | ||
360 | memcpy (&pkt->ip_hdr.dadr, ans->pkt.to, 4); | ||
361 | |||
362 | pkt->ip_hdr.chks = | ||
363 | calculate_ip_checksum ((uint16_t *) & pkt->ip_hdr, 5 * 4); | ||
364 | |||
365 | /* set the udp-header */ | ||
366 | pkt->udp_dns.udp_hdr.spt = htons (53); | ||
367 | pkt->udp_dns.udp_hdr.dpt = ans->pkt.dst_port; | ||
368 | pkt->udp_dns.udp_hdr.len = htons (net_len - sizeof (struct ip_hdr)); | ||
369 | pkt->udp_dns.udp_hdr.crc = 0; /* Optional for IPv4 */ | ||
370 | |||
371 | memcpy (&pkt->udp_dns.data, ans->pkt.data, data_len); | ||
372 | (void) GNUNET_HELPER_send (helper_handle, | ||
373 | &pkt->shdr, | ||
374 | GNUNET_YES, | ||
375 | &helper_write, NULL); | ||
376 | |||
377 | } | ||
378 | else | ||
379 | { | ||
380 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Wrong addrlen = %d\n", | ||
381 | ans->pkt.addrlen); | ||
382 | GNUNET_assert (0); | ||
383 | return; /* convince compiler that we're done here */ | ||
384 | } | ||
385 | |||
386 | GNUNET_CONTAINER_DLL_remove (answer_proc_head, answer_proc_tail, ans); | ||
387 | GNUNET_free (ans); | ||
388 | |||
389 | } | ||
390 | |||
391 | /** | ||
392 | * Receive packets from the helper-process | ||
393 | */ | ||
394 | void | ||
395 | message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED, | ||
396 | const struct GNUNET_MessageHeader *message) | ||
397 | { | ||
398 | GNUNET_assert (ntohs (message->type) == GNUNET_MESSAGE_TYPE_VPN_HELPER); | ||
399 | |||
400 | struct tun_pkt *pkt_tun = (struct tun_pkt *) message; | ||
401 | GNUNET_HashCode *key; | ||
402 | |||
403 | /* ethertype is ipv6 */ | ||
404 | if (ntohs (pkt_tun->tun.type) == 0x86dd) | ||
405 | { | ||
406 | struct ip6_pkt *pkt6 = (struct ip6_pkt *) message; | ||
407 | |||
408 | GNUNET_assert (pkt6->ip6_hdr.version == 6); | ||
409 | struct ip6_tcp *pkt6_tcp; | ||
410 | struct ip6_udp *pkt6_udp; | ||
411 | struct ip6_icmp *pkt6_icmp; | ||
412 | |||
413 | pkt6_udp = NULL; /* make compiler happy */ | ||
414 | switch (pkt6->ip6_hdr.nxthdr) | ||
415 | { | ||
416 | case IPPROTO_UDP: | ||
417 | pkt6_udp = (struct ip6_udp *) pkt6; | ||
418 | /* Send dns-packets to the service-dns */ | ||
419 | if (ntohs (pkt6_udp->udp_hdr.dpt) == 53) | ||
420 | { | ||
421 | /* 9 = 8 for the udp-header + 1 for the unsigned char data[1]; */ | ||
422 | GNUNET_DNS_queue_request_v6 (dns_handle, | ||
423 | &pkt6->ip6_hdr.dadr, | ||
424 | &pkt6->ip6_hdr.sadr, | ||
425 | ntohs (pkt6_udp->udp_hdr.spt), | ||
426 | ntohs (pkt6_udp->udp_hdr.len) - 8, | ||
427 | (const void*) pkt6_udp->data); | ||
428 | |||
429 | break; | ||
430 | } | ||
431 | /* fall through */ | ||
432 | case IPPROTO_TCP: | ||
433 | pkt6_tcp = (struct ip6_tcp *) pkt6; | ||
434 | |||
435 | if ((key = address6_mapping_exists (&pkt6->ip6_hdr.dadr)) != NULL) | ||
436 | { | ||
437 | struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key); | ||
438 | |||
439 | GNUNET_assert (me != NULL); | ||
440 | GNUNET_free (key); | ||
441 | |||
442 | size_t size = | ||
443 | sizeof (struct GNUNET_MESH_Tunnel *) + | ||
444 | sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) + | ||
445 | ntohs (pkt6->ip6_hdr.paylgth); | ||
446 | |||
447 | struct GNUNET_MESH_Tunnel **cls = GNUNET_malloc (size); | ||
448 | struct GNUNET_MessageHeader *hdr = | ||
449 | (struct GNUNET_MessageHeader *) (cls + 1); | ||
450 | GNUNET_HashCode *hc = (GNUNET_HashCode *) (hdr + 1); | ||
451 | |||
452 | hdr->size = | ||
453 | htons (sizeof (struct GNUNET_MessageHeader) + | ||
454 | sizeof (GNUNET_HashCode) + ntohs (pkt6->ip6_hdr.paylgth)); | ||
455 | |||
456 | GNUNET_MESH_ApplicationType app_type = 0; /* fix compiler uninitialized warning... */ | ||
457 | |||
458 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "me->addrlen is %d\n", | ||
459 | me->addrlen); | ||
460 | if (me->addrlen == 0) | ||
461 | { | ||
462 | /* This is a mapping to a gnunet-service */ | ||
463 | memcpy (hc, &me->desc.service_descriptor, sizeof (GNUNET_HashCode)); | ||
464 | |||
465 | if (IPPROTO_UDP == pkt6->ip6_hdr.nxthdr && | ||
466 | (me->desc.service_type & htonl (GNUNET_DNS_SERVICE_TYPE_UDP)) && | ||
467 | (port_in_ports (me->desc.ports, pkt6_udp->udp_hdr.dpt) || | ||
468 | testBit (me->additional_ports, ntohs (pkt6_udp->udp_hdr.dpt)))) | ||
469 | { | ||
470 | hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP); | ||
471 | |||
472 | memcpy (hc + 1, &pkt6_udp->udp_hdr, ntohs (pkt6_udp->udp_hdr.len)); | ||
473 | |||
474 | } | ||
475 | else if (IPPROTO_TCP == pkt6->ip6_hdr.nxthdr && | ||
476 | (me->desc.service_type & htonl (GNUNET_DNS_SERVICE_TYPE_TCP)) | ||
477 | && (port_in_ports (me->desc.ports, pkt6_tcp->tcp_hdr.dpt))) | ||
478 | { | ||
479 | hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP); | ||
480 | |||
481 | memcpy (hc + 1, &pkt6_tcp->tcp_hdr, ntohs (pkt6->ip6_hdr.paylgth)); | ||
482 | |||
483 | } | ||
484 | else | ||
485 | { | ||
486 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pip: %d\n", | ||
487 | port_in_ports (me->desc.ports, pkt6_tcp->tcp_hdr.dpt)); | ||
488 | GNUNET_assert (0); | ||
489 | } | ||
490 | if (me->tunnel == NULL && NULL != cls) | ||
491 | { | ||
492 | *cls = | ||
493 | GNUNET_MESH_tunnel_create (mesh_handle, | ||
494 | initialize_tunnel_state (16, NULL), | ||
495 | &send_pkt_to_peer, NULL, cls); | ||
496 | |||
497 | GNUNET_MESH_peer_request_connect_add (*cls, | ||
498 | (struct GNUNET_PeerIdentity *) | ||
499 | &me->desc.peer); | ||
500 | me->tunnel = *cls; | ||
501 | } | ||
502 | else if (NULL != cls) | ||
503 | { | ||
504 | *cls = me->tunnel; | ||
505 | send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL); | ||
506 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
507 | "Queued to send IPv6 to peer %x, type %d\n", | ||
508 | *((unsigned int *) &me->desc.peer), ntohs (hdr->type)); | ||
509 | } | ||
510 | } | ||
511 | else | ||
512 | { | ||
513 | /* This is a mapping to a "real" address */ | ||
514 | struct remote_addr *s = (struct remote_addr *) hc; | ||
515 | |||
516 | s->addrlen = me->addrlen; | ||
517 | memcpy (s->addr, me->addr, me->addrlen); | ||
518 | s->proto = pkt6->ip6_hdr.nxthdr; | ||
519 | if (s->proto == IPPROTO_UDP) | ||
520 | { | ||
521 | hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP); | ||
522 | memcpy (hc + 1, &pkt6_udp->udp_hdr, ntohs (pkt6_udp->udp_hdr.len)); | ||
523 | app_type = GNUNET_APPLICATION_TYPE_INTERNET_UDP_GATEWAY; | ||
524 | if (NULL != udp_tunnel) | ||
525 | me->tunnel = udp_tunnel; | ||
526 | } | ||
527 | else if (s->proto == IPPROTO_TCP) | ||
528 | { | ||
529 | hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP); | ||
530 | memcpy (hc + 1, &pkt6_tcp->tcp_hdr, ntohs (pkt6->ip6_hdr.paylgth)); | ||
531 | app_type = GNUNET_APPLICATION_TYPE_INTERNET_TCP_GATEWAY; | ||
532 | if (NULL != tcp_tunnel) | ||
533 | me->tunnel = tcp_tunnel; | ||
534 | } | ||
535 | else | ||
536 | { | ||
537 | GNUNET_assert (0); | ||
538 | } | ||
539 | if (me->tunnel == NULL && NULL != cls) | ||
540 | { | ||
541 | *cls = | ||
542 | GNUNET_MESH_tunnel_create (mesh_handle, | ||
543 | initialize_tunnel_state (16, NULL), | ||
544 | &send_pkt_to_peer, NULL, cls); | ||
545 | |||
546 | GNUNET_MESH_peer_request_connect_by_type (*cls, app_type); | ||
547 | me->tunnel = *cls; | ||
548 | if (GNUNET_APPLICATION_TYPE_INTERNET_UDP_GATEWAY == app_type) | ||
549 | udp_tunnel = *cls; | ||
550 | else if (GNUNET_APPLICATION_TYPE_INTERNET_TCP_GATEWAY == app_type) | ||
551 | tcp_tunnel = *cls; | ||
552 | } | ||
553 | else if (NULL != cls) | ||
554 | { | ||
555 | *cls = me->tunnel; | ||
556 | send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL); | ||
557 | } | ||
558 | } | ||
559 | } | ||
560 | else | ||
561 | { | ||
562 | char pbuf[INET6_ADDRSTRLEN]; | ||
563 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
564 | "Packet to %s, which has no mapping\n", | ||
565 | inet_ntop (AF_INET6, | ||
566 | &pkt6->ip6_hdr.dadr, | ||
567 | pbuf, | ||
568 | sizeof (pbuf))); | ||
569 | } | ||
570 | break; | ||
571 | case 0x3a: | ||
572 | /* ICMPv6 */ | ||
573 | pkt6_icmp = (struct ip6_icmp *) pkt6; | ||
574 | /* If this packet is an icmp-echo-request and a mapping exists, answer */ | ||
575 | if (pkt6_icmp->icmp_hdr.type == 0x80 && | ||
576 | (key = address6_mapping_exists (&pkt6->ip6_hdr.dadr)) != NULL) | ||
577 | { | ||
578 | GNUNET_free (key); | ||
579 | pkt6_icmp = GNUNET_malloc (ntohs (pkt6->shdr.size)); | ||
580 | memcpy (pkt6_icmp, pkt6, ntohs (pkt6->shdr.size)); | ||
581 | GNUNET_SCHEDULER_add_now (&send_icmp6_response, pkt6_icmp); | ||
582 | } | ||
583 | break; | ||
584 | } | ||
585 | } | ||
586 | /* ethertype is ipv4 */ | ||
587 | else if (ntohs (pkt_tun->tun.type) == 0x0800) | ||
588 | { | ||
589 | struct ip_pkt *pkt = (struct ip_pkt *) message; | ||
590 | struct ip_udp *udp = (struct ip_udp *) message; | ||
591 | struct ip_tcp *pkt_tcp; | ||
592 | struct ip_udp *pkt_udp; | ||
593 | struct ip_icmp *pkt_icmp; | ||
594 | |||
595 | GNUNET_assert (pkt->ip_hdr.version == 4); | ||
596 | |||
597 | /* Send dns-packets to the service-dns */ | ||
598 | if (pkt->ip_hdr.proto == IPPROTO_UDP && ntohs (udp->udp_hdr.dpt) == 53) | ||
599 | { | ||
600 | GNUNET_DNS_queue_request_v4 (dns_handle, | ||
601 | &pkt->ip_hdr.dadr, | ||
602 | &pkt->ip_hdr.sadr, | ||
603 | ntohs (udp->udp_hdr.spt), | ||
604 | ntohs (udp->udp_hdr.len) - 8, | ||
605 | (const void*) udp->data); | ||
606 | } | ||
607 | else | ||
608 | { | ||
609 | uint32_t dadr = pkt->ip_hdr.dadr.s_addr; | ||
610 | unsigned char *c = (unsigned char *) &dadr; | ||
611 | |||
612 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Packet to %d.%d.%d.%d, proto %x\n", | ||
613 | c[0], c[1], c[2], c[3], pkt->ip_hdr.proto); | ||
614 | switch (pkt->ip_hdr.proto) | ||
615 | { | ||
616 | case IPPROTO_TCP: | ||
617 | case IPPROTO_UDP: | ||
618 | pkt_tcp = (struct ip_tcp *) pkt; | ||
619 | pkt_udp = (struct ip_udp *) pkt; | ||
620 | |||
621 | if ((key = address4_mapping_exists (dadr)) != NULL) | ||
622 | { | ||
623 | struct map_entry *me = | ||
624 | GNUNET_CONTAINER_multihashmap_get (hashmap, key); | ||
625 | GNUNET_assert (me != NULL); | ||
626 | GNUNET_free (key); | ||
627 | |||
628 | size_t size = | ||
629 | sizeof (struct GNUNET_MESH_Tunnel *) + | ||
630 | sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) + | ||
631 | ntohs (pkt->ip_hdr.tot_lngth) - 4 * pkt->ip_hdr.hdr_lngth; | ||
632 | |||
633 | struct GNUNET_MESH_Tunnel **cls = GNUNET_malloc (size); | ||
634 | struct GNUNET_MessageHeader *hdr = | ||
635 | (struct GNUNET_MessageHeader *) (cls + 1); | ||
636 | GNUNET_HashCode *hc = (GNUNET_HashCode *) (hdr + 1); | ||
637 | |||
638 | hdr->size = | ||
639 | htons (sizeof (struct GNUNET_MessageHeader) + | ||
640 | sizeof (GNUNET_HashCode) + ntohs (pkt->ip_hdr.tot_lngth) - | ||
641 | 4 * pkt->ip_hdr.hdr_lngth); | ||
642 | |||
643 | GNUNET_MESH_ApplicationType app_type = 0; /* make compiler happy */ | ||
644 | |||
645 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "me->addrlen is %d\n", | ||
646 | me->addrlen); | ||
647 | if (me->addrlen == 0) | ||
648 | { | ||
649 | /* This is a mapping to a gnunet-service */ | ||
650 | memcpy (hc, &me->desc.service_descriptor, sizeof (GNUNET_HashCode)); | ||
651 | |||
652 | if ((IPPROTO_UDP == pkt->ip_hdr.proto) && | ||
653 | (me->desc.service_type & htonl (GNUNET_DNS_SERVICE_TYPE_UDP)) && | ||
654 | (port_in_ports (me->desc.ports, pkt_udp->udp_hdr.dpt) || | ||
655 | testBit (me->additional_ports, ntohs (pkt_udp->udp_hdr.dpt)))) | ||
656 | { | ||
657 | hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP); | ||
658 | |||
659 | memcpy (hc + 1, &pkt_udp->udp_hdr, ntohs (pkt_udp->udp_hdr.len)); | ||
660 | |||
661 | } | ||
662 | else if ((IPPROTO_TCP == pkt->ip_hdr.proto) && | ||
663 | (me-> | ||
664 | desc.service_type & htonl (GNUNET_DNS_SERVICE_TYPE_TCP)) | ||
665 | && (port_in_ports (me->desc.ports, pkt_tcp->tcp_hdr.dpt))) | ||
666 | { | ||
667 | hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP); | ||
668 | |||
669 | memcpy (hc + 1, &pkt_tcp->tcp_hdr, | ||
670 | ntohs (pkt->ip_hdr.tot_lngth) - | ||
671 | 4 * pkt->ip_hdr.hdr_lngth); | ||
672 | |||
673 | } | ||
674 | if (me->tunnel == NULL && NULL != cls) | ||
675 | { | ||
676 | *cls = | ||
677 | GNUNET_MESH_tunnel_create (mesh_handle, | ||
678 | initialize_tunnel_state (4, NULL), | ||
679 | send_pkt_to_peer, NULL, cls); | ||
680 | GNUNET_MESH_peer_request_connect_add (*cls, | ||
681 | (struct GNUNET_PeerIdentity | ||
682 | *) &me->desc.peer); | ||
683 | me->tunnel = *cls; | ||
684 | } | ||
685 | else if (NULL != cls) | ||
686 | { | ||
687 | *cls = me->tunnel; | ||
688 | send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL); | ||
689 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
690 | "Queued to send IPv4 to peer %x, type %d\n", | ||
691 | *((unsigned int *) &me->desc.peer), | ||
692 | ntohs (hdr->type)); | ||
693 | } | ||
694 | } | ||
695 | else | ||
696 | { | ||
697 | /* This is a mapping to a "real" address */ | ||
698 | struct remote_addr *s = (struct remote_addr *) hc; | ||
699 | |||
700 | s->addrlen = me->addrlen; | ||
701 | memcpy (s->addr, me->addr, me->addrlen); | ||
702 | s->proto = pkt->ip_hdr.proto; | ||
703 | if (s->proto == IPPROTO_UDP) | ||
704 | { | ||
705 | hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP); | ||
706 | memcpy (hc + 1, &pkt_udp->udp_hdr, ntohs (pkt_udp->udp_hdr.len)); | ||
707 | app_type = GNUNET_APPLICATION_TYPE_INTERNET_UDP_GATEWAY; | ||
708 | } | ||
709 | else if (s->proto == IPPROTO_TCP) | ||
710 | { | ||
711 | hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP); | ||
712 | memcpy (hc + 1, &pkt_tcp->tcp_hdr, | ||
713 | ntohs (pkt->ip_hdr.tot_lngth) - | ||
714 | 4 * pkt->ip_hdr.hdr_lngth); | ||
715 | app_type = GNUNET_APPLICATION_TYPE_INTERNET_TCP_GATEWAY; | ||
716 | } | ||
717 | else | ||
718 | GNUNET_assert (0); | ||
719 | if (me->tunnel == NULL && NULL != cls) | ||
720 | { | ||
721 | *cls = | ||
722 | GNUNET_MESH_tunnel_create (mesh_handle, | ||
723 | initialize_tunnel_state (4, NULL), | ||
724 | send_pkt_to_peer, NULL, cls); | ||
725 | |||
726 | GNUNET_MESH_peer_request_connect_by_type (*cls, app_type); | ||
727 | me->tunnel = *cls; | ||
728 | } | ||
729 | else if (NULL != cls) | ||
730 | { | ||
731 | *cls = me->tunnel; | ||
732 | send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL); | ||
733 | } | ||
734 | } | ||
735 | } | ||
736 | else | ||
737 | { | ||
738 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
739 | "Packet to %x which has no mapping\n", dadr); | ||
740 | } | ||
741 | break; | ||
742 | case 0x01: | ||
743 | /* ICMP */ | ||
744 | pkt_icmp = (struct ip_icmp *) pkt; | ||
745 | if (pkt_icmp->icmp_hdr.type == 0x8 && | ||
746 | (key = address4_mapping_exists (dadr)) != NULL) | ||
747 | { | ||
748 | GNUNET_free (key); | ||
749 | pkt_icmp = GNUNET_malloc (ntohs (pkt->shdr.size)); | ||
750 | memcpy (pkt_icmp, pkt, ntohs (pkt->shdr.size)); | ||
751 | GNUNET_SCHEDULER_add_now (&send_icmp4_response, pkt_icmp); | ||
752 | } | ||
753 | break; | ||
754 | } | ||
755 | } | ||
756 | } | ||
757 | } | ||
758 | |||
759 | |||
760 | |||
213 | static void | 761 | static void |
214 | collect_mappings (void *cls GNUNET_UNUSED, | 762 | collect_mappings (void *cls GNUNET_UNUSED, |
215 | const struct GNUNET_SCHEDULER_TaskContext *tc) | 763 | const struct GNUNET_SCHEDULER_TaskContext *tc) |
@@ -269,8 +817,10 @@ send_icmp4_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
269 | memcpy (response + 1, request + 1, | 817 | memcpy (response + 1, request + 1, |
270 | ntohs (request->shdr.size) - sizeof (struct ip_icmp)); | 818 | ntohs (request->shdr.size) - sizeof (struct ip_icmp)); |
271 | 819 | ||
272 | write_to_helper (response, ntohs (response->shdr.size)); | 820 | (void) GNUNET_HELPER_send (helper_handle, |
273 | 821 | &response->shdr, | |
822 | GNUNET_YES, | ||
823 | NULL, NULL); | ||
274 | GNUNET_free (request); | 824 | GNUNET_free (request); |
275 | } | 825 | } |
276 | 826 | ||
@@ -310,8 +860,10 @@ send_icmp6_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
310 | memcpy (response + 1, request + 1, | 860 | memcpy (response + 1, request + 1, |
311 | ntohs (request->shdr.size) - sizeof (struct ip6_icmp)); | 861 | ntohs (request->shdr.size) - sizeof (struct ip6_icmp)); |
312 | 862 | ||
313 | write_to_helper (response, ntohs (response->shdr.size)); | 863 | (void) GNUNET_HELPER_send (helper_handle, |
314 | 864 | &response->shdr, | |
865 | GNUNET_YES, | ||
866 | NULL, NULL); | ||
315 | GNUNET_free (request); | 867 | GNUNET_free (request); |
316 | } | 868 | } |
317 | 869 | ||
@@ -824,9 +1376,6 @@ process_answer (void *cls, | |||
824 | GNUNET_CONTAINER_DLL_insert_after (answer_proc_head, answer_proc_tail, | 1376 | GNUNET_CONTAINER_DLL_insert_after (answer_proc_head, answer_proc_tail, |
825 | answer_proc_tail, list); | 1377 | answer_proc_tail, list); |
826 | 1378 | ||
827 | schedule_helper_write (GNUNET_TIME_UNIT_FOREVER_REL, NULL); | ||
828 | |||
829 | return; | ||
830 | } | 1379 | } |
831 | 1380 | ||
832 | 1381 | ||
@@ -939,8 +1488,11 @@ receive_udp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, | |||
939 | calculate_checksum_update (sum, (uint16_t *) & pkt6->udp_hdr, | 1488 | calculate_checksum_update (sum, (uint16_t *) & pkt6->udp_hdr, |
940 | ntohs (pkt->len)); | 1489 | ntohs (pkt->len)); |
941 | pkt6->udp_hdr.crc = calculate_checksum_end (sum); | 1490 | pkt6->udp_hdr.crc = calculate_checksum_end (sum); |
942 | 1491 | ||
943 | write_to_helper (pkt6, size); | 1492 | (void) GNUNET_HELPER_send (helper_handle, |
1493 | &pkt6->shdr, | ||
1494 | GNUNET_YES, | ||
1495 | NULL, NULL); | ||
944 | } | 1496 | } |
945 | else | 1497 | else |
946 | { | 1498 | { |
@@ -1011,7 +1563,10 @@ receive_udp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, | |||
1011 | pkt4->ip_hdr.chks = | 1563 | pkt4->ip_hdr.chks = |
1012 | calculate_ip_checksum ((uint16_t *) & pkt4->ip_hdr, 5 * 4); | 1564 | calculate_ip_checksum ((uint16_t *) & pkt4->ip_hdr, 5 * 4); |
1013 | 1565 | ||
1014 | write_to_helper (pkt4, size); | 1566 | (void) GNUNET_HELPER_send (helper_handle, |
1567 | &pkt4->shdr, | ||
1568 | GNUNET_YES, | ||
1569 | NULL, NULL); | ||
1015 | } | 1570 | } |
1016 | 1571 | ||
1017 | return GNUNET_OK; | 1572 | return GNUNET_OK; |
@@ -1113,7 +1668,10 @@ receive_tcp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, | |||
1113 | ntohs (pkt6->ip6_hdr.paylgth)); | 1668 | ntohs (pkt6->ip6_hdr.paylgth)); |
1114 | pkt6->tcp_hdr.crc = calculate_checksum_end (sum); | 1669 | pkt6->tcp_hdr.crc = calculate_checksum_end (sum); |
1115 | 1670 | ||
1116 | write_to_helper (pkt6, size); | 1671 | (void) GNUNET_HELPER_send (helper_handle, |
1672 | &pkt6->shdr, | ||
1673 | GNUNET_YES, | ||
1674 | NULL, NULL); | ||
1117 | } | 1675 | } |
1118 | else | 1676 | else |
1119 | { | 1677 | { |
@@ -1194,7 +1752,11 @@ receive_tcp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, | |||
1194 | pkt4->ip_hdr.chks = | 1752 | pkt4->ip_hdr.chks = |
1195 | calculate_ip_checksum ((uint16_t *) & pkt4->ip_hdr, 5 * 4); | 1753 | calculate_ip_checksum ((uint16_t *) & pkt4->ip_hdr, 5 * 4); |
1196 | 1754 | ||
1197 | write_to_helper (pkt4, size); | 1755 | (void) GNUNET_HELPER_send (helper_handle, |
1756 | &pkt4->shdr, | ||
1757 | GNUNET_YES, | ||
1758 | NULL, NULL); | ||
1759 | |||
1198 | } | 1760 | } |
1199 | 1761 | ||
1200 | return GNUNET_OK; | 1762 | return GNUNET_OK; |
@@ -1237,10 +1799,14 @@ run (void *cls, char *const *args GNUNET_UNUSED, | |||
1237 | {receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP_BACK, 0}, | 1799 | {receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP_BACK, 0}, |
1238 | {NULL, 0, 0} | 1800 | {NULL, 0, 0} |
1239 | }; | 1801 | }; |
1240 | |||
1241 | static const GNUNET_MESH_ApplicationType types[] = { | 1802 | static const GNUNET_MESH_ApplicationType types[] = { |
1242 | GNUNET_APPLICATION_TYPE_END | 1803 | GNUNET_APPLICATION_TYPE_END |
1243 | }; | 1804 | }; |
1805 | char *ifname; | ||
1806 | char *ipv6addr; | ||
1807 | char *ipv6prefix; | ||
1808 | char *ipv4addr; | ||
1809 | char *ipv4mask; | ||
1244 | 1810 | ||
1245 | mesh_handle = | 1811 | mesh_handle = |
1246 | GNUNET_MESH_connect (cfg_, 42, NULL, new_tunnel, cleaner, handlers, | 1812 | GNUNET_MESH_connect (cfg_, 42, NULL, new_tunnel, cleaner, handlers, |
@@ -1254,8 +1820,58 @@ run (void *cls, char *const *args GNUNET_UNUSED, | |||
1254 | dns_handle = GNUNET_DNS_connect (cfg, | 1820 | dns_handle = GNUNET_DNS_connect (cfg, |
1255 | &process_answer, | 1821 | &process_answer, |
1256 | NULL); | 1822 | NULL); |
1257 | shs_task = | 1823 | if (GNUNET_SYSERR == |
1258 | GNUNET_SCHEDULER_add_after (conn_task, start_helper_and_schedule, NULL); | 1824 | GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IFNAME", &ifname)) |
1825 | { | ||
1826 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1827 | "No entry 'IFNAME' in configuration!\n"); | ||
1828 | exit (1); | ||
1829 | } | ||
1830 | |||
1831 | if (GNUNET_SYSERR == | ||
1832 | GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6ADDR", &ipv6addr)) | ||
1833 | { | ||
1834 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1835 | "No entry 'IPV6ADDR' in configuration!\n"); | ||
1836 | exit (1); | ||
1837 | } | ||
1838 | |||
1839 | if (GNUNET_SYSERR == | ||
1840 | GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6PREFIX", | ||
1841 | &ipv6prefix)) | ||
1842 | { | ||
1843 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1844 | "No entry 'IPV6PREFIX' in configuration!\n"); | ||
1845 | exit (1); | ||
1846 | } | ||
1847 | |||
1848 | if (GNUNET_SYSERR == | ||
1849 | GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR", &ipv4addr)) | ||
1850 | { | ||
1851 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1852 | "No entry 'IPV4ADDR' in configuration!\n"); | ||
1853 | exit (1); | ||
1854 | } | ||
1855 | |||
1856 | if (GNUNET_SYSERR == | ||
1857 | GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK", &ipv4mask)) | ||
1858 | { | ||
1859 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1860 | "No entry 'IPV4MASK' in configuration!\n"); | ||
1861 | exit (1); | ||
1862 | } | ||
1863 | |||
1864 | vpn_argv[0] = GNUNET_strdup ("vpn-gnunet"); | ||
1865 | vpn_argv[1] = ifname; | ||
1866 | vpn_argv[2] = ipv6addr; | ||
1867 | vpn_argv[3] = ipv6prefix; | ||
1868 | vpn_argv[4] = ipv4addr; | ||
1869 | vpn_argv[5] = ipv4mask; | ||
1870 | vpn_argv[6] = NULL; | ||
1871 | |||
1872 | helper_handle = GNUNET_HELPER_start ("gnunet-helper-vpn", vpn_argv, | ||
1873 | &message_token, NULL); | ||
1874 | GNUNET_DNS_restart_hijack (dns_handle); | ||
1259 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls); | 1875 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls); |
1260 | } | 1876 | } |
1261 | 1877 | ||