aboutsummaryrefslogtreecommitdiff
path: root/src/exit
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2017-02-23 14:08:07 +0100
committerChristian Grothoff <christian@grothoff.org>2017-02-23 14:08:07 +0100
commit450f962ef7349f2f08fbda705e92acb87884af71 (patch)
treee9e934560bc343df83149188d41c718497561d12 /src/exit
parent1108ec482bba414f016b35a45e5d43ff99994b7b (diff)
downloadgnunet-450f962ef7349f2f08fbda705e92acb87884af71.tar.gz
gnunet-450f962ef7349f2f08fbda705e92acb87884af71.zip
convert EXIT to new CADET MQ API
Diffstat (limited to 'src/exit')
-rw-r--r--src/exit/Makefile.am8
-rw-r--r--src/exit/gnunet-daemon-exit.c3013
2 files changed, 1482 insertions, 1539 deletions
diff --git a/src/exit/Makefile.am b/src/exit/Makefile.am
index 6c4cbf114..271b4ebd7 100644
--- a/src/exit/Makefile.am
+++ b/src/exit/Makefile.am
@@ -30,11 +30,11 @@ endif
30 30
31libexec_PROGRAMS = \ 31libexec_PROGRAMS = \
32 gnunet-daemon-exit \ 32 gnunet-daemon-exit \
33 $(EXITBIN) 33 $(EXITBIN)
34 34
35if MINGW 35if MINGW
36 gnunet_helper_exit_LDFLAGS = \ 36 gnunet_helper_exit_LDFLAGS = \
37 -no-undefined -Wl,--export-all-symbols 37 -no-undefined -Wl,--export-all-symbols
38 38
39 gnunet_helper_exit_LDADD = \ 39 gnunet_helper_exit_LDADD = \
40 -lsetupapi -lnewdev -lshell32 -liconv -lstdc++ \ 40 -lsetupapi -lnewdev -lshell32 -liconv -lstdc++ \
@@ -47,13 +47,13 @@ else
47 gnunet-helper-exit.c 47 gnunet-helper-exit.c
48endif 48endif
49gnunet_daemon_exit_SOURCES = \ 49gnunet_daemon_exit_SOURCES = \
50 gnunet-daemon-exit.c exit.h 50 gnunet-daemon-exit.c exit.h
51gnunet_daemon_exit_LDADD = \ 51gnunet_daemon_exit_LDADD = \
52 $(top_builddir)/src/dns/libgnunetdnsstub.la \ 52 $(top_builddir)/src/dns/libgnunetdnsstub.la \
53 $(top_builddir)/src/dht/libgnunetdht.la \ 53 $(top_builddir)/src/dht/libgnunetdht.la \
54 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 54 $(top_builddir)/src/statistics/libgnunetstatistics.la \
55 $(top_builddir)/src/tun/libgnunettun.la \ 55 $(top_builddir)/src/tun/libgnunettun.la \
56 $(top_builddir)/src/util/libgnunetutil.la \ 56 $(top_builddir)/src/util/libgnunetutil.la \
57 $(top_builddir)/src/cadet/libgnunetcadet.la \ 57 $(top_builddir)/src/cadet/libgnunetcadetnew.la \
58 $(top_builddir)/src/regex/libgnunetregex.la \ 58 $(top_builddir)/src/regex/libgnunetregex.la \
59 $(GN_LIBINTL) 59 $(GN_LIBINTL)
diff --git a/src/exit/gnunet-daemon-exit.c b/src/exit/gnunet-daemon-exit.c
index 92acc61cd..09576e393 100644
--- a/src/exit/gnunet-daemon-exit.c
+++ b/src/exit/gnunet-daemon-exit.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2010-2013 Christian Grothoff 3 Copyright (C) 2010-2013, 2017 Christian Grothoff
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -195,33 +195,6 @@ struct RedirectInformation
195 195
196 196
197/** 197/**
198 * Queue of messages to a channel.
199 */
200struct ChannelMessageQueue
201{
202 /**
203 * This is a doubly-linked list.
204 */
205 struct ChannelMessageQueue *next;
206
207 /**
208 * This is a doubly-linked list.
209 */
210 struct ChannelMessageQueue *prev;
211
212 /**
213 * Payload to send via the channel.
214 */
215 const void *payload;
216
217 /**
218 * Number of bytes in @e payload.
219 */
220 size_t len;
221};
222
223
224/**
225 * This struct is saved into #connections_map to allow finding the 198 * This struct is saved into #connections_map to allow finding the
226 * right channel given an IP packet from TUN. It is also associated 199 * right channel given an IP packet from TUN. It is also associated
227 * with the channel's closure so we can find it again for the next 200 * with the channel's closure so we can find it again for the next
@@ -241,11 +214,6 @@ struct ChannelState
241 struct GNUNET_PeerIdentity peer; 214 struct GNUNET_PeerIdentity peer;
242 215
243 /** 216 /**
244 * Active channel transmission request (or NULL).
245 */
246 struct GNUNET_CADET_TransmitHandle *th;
247
248 /**
249 * #GNUNET_NO if this is a channel for TCP/UDP, 217 * #GNUNET_NO if this is a channel for TCP/UDP,
250 * #GNUNET_YES if this is a channel for DNS, 218 * #GNUNET_YES if this is a channel for DNS,
251 * #GNUNET_SYSERR if the channel is not yet initialized. 219 * #GNUNET_SYSERR if the channel is not yet initialized.
@@ -273,16 +241,6 @@ struct ChannelState
273 struct LocalService *serv; 241 struct LocalService *serv;
274 242
275 /** 243 /**
276 * Head of DLL of messages for this channel.
277 */
278 struct ChannelMessageQueue *head;
279
280 /**
281 * Tail of DLL of messages for this channel.
282 */
283 struct ChannelMessageQueue *tail;
284
285 /**
286 * Primary redirection information for this connection. 244 * Primary redirection information for this connection.
287 */ 245 */
288 struct RedirectInformation ri; 246 struct RedirectInformation ri;
@@ -292,22 +250,12 @@ struct ChannelState
292 { 250 {
293 251
294 /** 252 /**
295 * DNS reply ready for transmission.
296 */
297 char *reply;
298
299 /**
300 * Socket we are using to transmit this request (must match if we receive 253 * Socket we are using to transmit this request (must match if we receive
301 * a response). 254 * a response).
302 */ 255 */
303 struct GNUNET_DNSSTUB_RequestSocket *rs; 256 struct GNUNET_DNSSTUB_RequestSocket *rs;
304 257
305 /** 258 /**
306 * Number of bytes in 'reply'.
307 */
308 size_t reply_length;
309
310 /**
311 * Original DNS request ID as used by the client. 259 * Original DNS request ID as used by the client.
312 */ 260 */
313 uint16_t original_id; 261 uint16_t original_id;
@@ -428,7 +376,7 @@ static struct GNUNET_DHT_Handle *dht;
428/** 376/**
429 * Task for doing DHT PUTs to advertise exit service. 377 * Task for doing DHT PUTs to advertise exit service.
430 */ 378 */
431static struct GNUNET_SCHEDULER_Task * dht_task; 379static struct GNUNET_SCHEDULER_Task *dht_task;
432 380
433/** 381/**
434 * Advertisement message we put into the DHT to advertise us 382 * Advertisement message we put into the DHT to advertise us
@@ -447,6 +395,21 @@ static struct GNUNET_HashCode dht_put_key;
447static struct GNUNET_CRYPTO_EddsaPrivateKey *peer_key; 395static struct GNUNET_CRYPTO_EddsaPrivateKey *peer_key;
448 396
449/** 397/**
398 * Port for DNS exit.
399 */
400static struct GNUNET_CADET_Port *dns_port;
401
402/**
403 * Port for IPv4 exit.
404 */
405static struct GNUNET_CADET_Port *cadet_port4;
406
407/**
408 * Port for IPv6 exit.
409 */
410static struct GNUNET_CADET_Port *cadet_port6;
411
412/**
450 * Are we an IPv4-exit? 413 * Are we an IPv4-exit?
451 */ 414 */
452static int ipv4_exit; 415static int ipv4_exit;
@@ -467,51 +430,27 @@ static int ipv4_enabled;
467static int ipv6_enabled; 430static int ipv6_enabled;
468 431
469 432
433GNUNET_NETWORK_STRUCT_BEGIN
434
470/** 435/**
471 * We got a reply from DNS for a request of a CADET channel. Send it 436 * Message with a DNS response.
472 * via the channel (after changing the request ID back). 437 */
473 * 438struct DnsResponseMessage
474 * @param cls the `struct ChannelState`
475 * @param size number of bytes available in @a buf
476 * @param buf where to copy the reply
477 * @return number of bytes written to @a buf
478 */
479static size_t
480transmit_reply_to_cadet (void *cls,
481 size_t size,
482 void *buf)
483{ 439{
484 struct ChannelState *ts = cls; 440 /**
485 size_t off; 441 * GNUnet header, of type #GNUNET_MESSAGE_TYPE_VPN_DNS_FROM_INTERNET
486 size_t ret; 442 */
487 char *cbuf = buf; 443 struct GNUNET_MessageHeader header;
488 struct GNUNET_MessageHeader hdr; 444
445 /**
446 * DNS header.
447 */
489 struct GNUNET_TUN_DnsHeader dns; 448 struct GNUNET_TUN_DnsHeader dns;
490 449
491 GNUNET_assert (GNUNET_YES == ts->is_dns); 450 /* Followed by more DNS payload */
492 ts->th = NULL; 451};
493 GNUNET_assert (ts->specifics.dns.reply != NULL); 452
494 if (size == 0) 453GNUNET_NETWORK_STRUCT_END
495 return 0;
496 ret = sizeof (struct GNUNET_MessageHeader) + ts->specifics.dns.reply_length;
497 GNUNET_assert (ret <= size);
498 hdr.size = htons (ret);
499 hdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_DNS_FROM_INTERNET);
500 GNUNET_memcpy (&dns, ts->specifics.dns.reply, sizeof (dns));
501 dns.id = ts->specifics.dns.original_id;
502 off = 0;
503 GNUNET_memcpy (&cbuf[off], &hdr, sizeof (hdr));
504 off += sizeof (hdr);
505 GNUNET_memcpy (&cbuf[off], &dns, sizeof (dns));
506 off += sizeof (dns);
507 GNUNET_memcpy (&cbuf[off], &ts->specifics.dns.reply[sizeof (dns)], ts->specifics.dns.reply_length - sizeof (dns));
508 off += ts->specifics.dns.reply_length - sizeof (dns);
509 GNUNET_free (ts->specifics.dns.reply);
510 ts->specifics.dns.reply = NULL;
511 ts->specifics.dns.reply_length = 0;
512 GNUNET_assert (ret == off);
513 return ret;
514}
515 454
516 455
517/** 456/**
@@ -521,7 +460,7 @@ transmit_reply_to_cadet (void *cls,
521 * @param cls NULL 460 * @param cls NULL
522 * @param rs the socket that received the response 461 * @param rs the socket that received the response
523 * @param dns the response itself 462 * @param dns the response itself
524 * @param r number of bytes in dns 463 * @param r number of bytes in @a dns
525 */ 464 */
526static void 465static void
527process_dns_result (void *cls, 466process_dns_result (void *cls,
@@ -530,6 +469,8 @@ process_dns_result (void *cls,
530 size_t r) 469 size_t r)
531{ 470{
532 struct ChannelState *ts; 471 struct ChannelState *ts;
472 struct GNUNET_MQ_Envelope *env;
473 struct DnsResponseMessage *resp;
533 474
534 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 475 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
535 "Processing DNS result from stub resolver\n"); 476 "Processing DNS result from stub resolver\n");
@@ -542,48 +483,35 @@ process_dns_result (void *cls,
542 LOG (GNUNET_ERROR_TYPE_DEBUG, 483 LOG (GNUNET_ERROR_TYPE_DEBUG,
543 "Got a response from the stub resolver for DNS request received via CADET!\n"); 484 "Got a response from the stub resolver for DNS request received via CADET!\n");
544 channels[dns->id] = NULL; 485 channels[dns->id] = NULL;
545 GNUNET_free_non_null (ts->specifics.dns.reply); 486 env = GNUNET_MQ_msg_extra (resp,
546 ts->specifics.dns.reply = GNUNET_malloc (r); 487 r - sizeof (struct GNUNET_TUN_DnsHeader),
547 ts->specifics.dns.reply_length = r; 488 GNUNET_MESSAGE_TYPE_VPN_DNS_FROM_INTERNET);
548 GNUNET_memcpy (ts->specifics.dns.reply, dns, r); 489 GNUNET_memcpy (&resp->dns,
549 if (NULL != ts->th) 490 dns,
550 GNUNET_CADET_notify_transmit_ready_cancel (ts->th); 491 r);
551 ts->th = GNUNET_CADET_notify_transmit_ready (ts->channel, 492 resp->dns.id = ts->specifics.dns.original_id;
552 GNUNET_NO, 493 GNUNET_MQ_send (GNUNET_CADET_get_mq (ts->channel),
553 GNUNET_TIME_UNIT_FOREVER_REL, 494 env);
554 sizeof (struct GNUNET_MessageHeader) + r,
555 &transmit_reply_to_cadet,
556 ts);
557} 495}
558 496
559 497
560/** 498/**
561 * Process a request via cadet to perform a DNS query. 499 * Check a request via cadet to perform a DNS query.
562 *
563 * @param cls closure, NULL
564 * @param channel connection to the other end
565 * @param channel_ctx pointer to our `struct ChannelState *`
566 * @param message the actual message
567 * 500 *
501 * @param cls our `struct ChannelState *`
502 * @param msg the actual message
568 * @return #GNUNET_OK to keep the connection open, 503 * @return #GNUNET_OK to keep the connection open,
569 * #GNUNET_SYSERR to close it (signal serious error) 504 * #GNUNET_SYSERR to close it (signal serious error)
570 */ 505 */
571static int 506static int
572receive_dns_request (void *cls GNUNET_UNUSED, 507check_dns_request (void *cls,
573 struct GNUNET_CADET_Channel *channel, 508 const struct DnsResponseMessage *msg)
574 void **channel_ctx,
575 const struct GNUNET_MessageHeader *message)
576{ 509{
577 struct ChannelState *ts = *channel_ctx; 510 struct ChannelState *ts = cls;
578 const struct GNUNET_TUN_DnsHeader *dns;
579 size_t mlen = ntohs (message->size);
580 size_t dlen = mlen - sizeof (struct GNUNET_MessageHeader);
581 char buf[dlen] GNUNET_ALIGN;
582 struct GNUNET_TUN_DnsHeader *dout;
583 511
584 if (NULL == dnsstub) 512 if (NULL == dnsstub)
585 { 513 {
586 GNUNET_break_op (0); 514 GNUNET_break (0);
587 return GNUNET_SYSERR; 515 return GNUNET_SYSERR;
588 } 516 }
589 if (GNUNET_NO == ts->is_dns) 517 if (GNUNET_NO == ts->is_dns)
@@ -591,34 +519,53 @@ receive_dns_request (void *cls GNUNET_UNUSED,
591 GNUNET_break_op (0); 519 GNUNET_break_op (0);
592 return GNUNET_SYSERR; 520 return GNUNET_SYSERR;
593 } 521 }
522 return GNUNET_OK;
523}
524
525
526/**
527 * Process a request via cadet to perform a DNS query.
528 *
529 * @param cls our `struct ChannelState *`
530 * @param msg the actual message
531 */
532static void
533handle_dns_request (void *cls,
534 const struct DnsResponseMessage *msg)
535{
536 struct ChannelState *ts = cls;
537 size_t mlen = ntohs (msg->header.size);
538 size_t dlen = mlen - sizeof (struct GNUNET_MessageHeader);
539 char buf[dlen] GNUNET_ALIGN;
540 struct GNUNET_TUN_DnsHeader *dout;
541
594 if (GNUNET_SYSERR == ts->is_dns) 542 if (GNUNET_SYSERR == ts->is_dns)
595 { 543 {
596 /* channel is DNS from now on */ 544 /* channel is DNS from now on */
597 ts->is_dns = GNUNET_YES; 545 ts->is_dns = GNUNET_YES;
598 } 546 }
599 if (dlen < sizeof (struct GNUNET_TUN_DnsHeader)) 547 ts->specifics.dns.original_id = msg->dns.id;
600 {
601 GNUNET_break_op (0);
602 return GNUNET_SYSERR;
603 }
604 dns = (const struct GNUNET_TUN_DnsHeader *) &message[1];
605 ts->specifics.dns.original_id = dns->id;
606 if (channels[ts->specifics.dns.my_id] == ts) 548 if (channels[ts->specifics.dns.my_id] == ts)
607 channels[ts->specifics.dns.my_id] = NULL; 549 channels[ts->specifics.dns.my_id] = NULL;
608 ts->specifics.dns.my_id = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 550 ts->specifics.dns.my_id = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
609 UINT16_MAX + 1); 551 UINT16_MAX + 1);
610 channels[ts->specifics.dns.my_id] = ts; 552 channels[ts->specifics.dns.my_id] = ts;
611 GNUNET_memcpy (buf, dns, dlen); 553 GNUNET_memcpy (buf,
554 &msg->dns,
555 dlen);
612 dout = (struct GNUNET_TUN_DnsHeader *) buf; 556 dout = (struct GNUNET_TUN_DnsHeader *) buf;
613 dout->id = ts->specifics.dns.my_id; 557 dout->id = ts->specifics.dns.my_id;
614 ts->specifics.dns.rs = GNUNET_DNSSTUB_resolve2 (dnsstub, 558 ts->specifics.dns.rs = GNUNET_DNSSTUB_resolve2 (dnsstub,
615 buf, dlen, 559 buf,
560 dlen,
616 &process_dns_result, 561 &process_dns_result,
617 NULL); 562 NULL);
618 if (NULL == ts->specifics.dns.rs) 563 if (NULL == ts->specifics.dns.rs)
619 return GNUNET_SYSERR; 564 {
620 GNUNET_CADET_receive_done (channel); 565 GNUNET_break_op (0);
621 return GNUNET_OK; 566 return;
567 }
568 GNUNET_CADET_receive_done (ts->channel);
622} 569}
623 570
624 571
@@ -753,706 +700,445 @@ get_redirect_state (int af,
753} 700}
754 701
755 702
756/**
757 * Free memory associated with a service record.
758 *
759 * @param cls unused
760 * @param key service descriptor
761 * @param value service record to free
762 * @return #GNUNET_OK
763 */
764static int
765free_service_record (void *cls,
766 const struct GNUNET_HashCode *key,
767 void *value)
768{
769 struct LocalService *service = value;
770
771 GNUNET_assert (GNUNET_YES ==
772 GNUNET_CONTAINER_multihashmap_remove (services,
773 key,
774 service));
775 GNUNET_CADET_close_port (service->port);
776 GNUNET_free_non_null (service->name);
777 GNUNET_free (service);
778 return GNUNET_OK;
779}
780
781
782/**
783 * Callback from CADET for new channels.
784 *
785 * @param cls closure
786 * @param channel new handle to the channel
787 * @param initiator peer that started the channel
788 * @param port destination port
789 * @param options channel options flags
790 * @return initial channel context for the channel
791 */
792static void *
793new_service_channel (void *cls,
794 struct GNUNET_CADET_Channel *channel,
795 const struct GNUNET_PeerIdentity *initiator,
796 const struct GNUNET_HashCode *port,
797 enum GNUNET_CADET_ChannelOption options)
798{
799 struct LocalService *ls = cls;
800 struct ChannelState *s = GNUNET_new (struct ChannelState);
801
802 s->peer = *initiator;
803 GNUNET_STATISTICS_update (stats,
804 gettext_noop ("# Inbound CADET channels created"),
805 1,
806 GNUNET_NO);
807 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
808 "Received inbound channel from `%s'\n",
809 GNUNET_i2s (initiator));
810 s->channel = channel;
811 s->specifics.tcp_udp.serv = ls;
812 s->specifics.tcp_udp.ri.remote_address = ls->address;
813 return s;
814}
815
816 703
817/** 704/**
818 * Given a service descriptor and a destination port, find the 705 * Check a request via cadet to send a request to a TCP service
819 * respective service entry. 706 * offered by this system.
820 * 707 *
821 * @param proto IPPROTO_TCP or IPPROTO_UDP 708 * @param cls our `struct ChannelState *`
822 * @param name name of the service 709 * @param start the actual message
823 * @param destination_port destination port 710 * @return #GNUNET_OK to keep the connection open,
824 * @param service service information record to store (service->name will be set). 711 * #GNUNET_SYSERR to close it (signal serious error)
825 */ 712 */
826static void 713static int
827store_service (int proto, 714check_tcp_service (void *cls,
828 const char *name, 715 const struct GNUNET_EXIT_TcpServiceStartMessage *start)
829 uint16_t destination_port,
830 struct LocalService *service)
831{ 716{
832 struct GNUNET_HashCode cadet_port; 717 struct ChannelState *state = cls;
833 718
834 service->name = GNUNET_strdup (name); 719 if (NULL == state)
835 GNUNET_TUN_service_name_to_hash (name,
836 &service->descriptor);
837 GNUNET_TUN_compute_service_cadet_port (&service->descriptor,
838 destination_port,
839 &cadet_port);
840 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
841 "Opening CADET port %s for SERVICE exit %s on port %u\n",
842 GNUNET_h2s (&cadet_port),
843 name,
844 (unsigned int) destination_port);
845 service->port = GNUNET_CADET_open_port (cadet_handle,
846 &cadet_port,
847 &new_service_channel,
848 service);
849 service->is_udp = (IPPROTO_UDP == proto);
850 if (GNUNET_OK !=
851 GNUNET_CONTAINER_multihashmap_put (services,
852 &cadet_port,
853 service,
854 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
855 { 720 {
856 GNUNET_CADET_close_port (service->port); 721 GNUNET_break_op (0);
857 GNUNET_free_non_null (service->name); 722 return GNUNET_SYSERR;
858 GNUNET_free (service);
859 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
860 _("Got duplicate service records for `%s:%u'\n"),
861 name,
862 (unsigned int) destination_port);
863 } 723 }
724 if (GNUNET_YES == state->is_dns)
725 {
726 GNUNET_break_op (0);
727 return GNUNET_SYSERR;
728 }
729 if (NULL == state->specifics.tcp_udp.serv)
730 {
731 GNUNET_break_op (0);
732 return GNUNET_SYSERR;
733 }
734 if (NULL != state->specifics.tcp_udp.heap_node)
735 {
736 GNUNET_break_op (0);
737 return GNUNET_SYSERR;
738 }
739 if (start->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
740 {
741 GNUNET_break_op (0);
742 return GNUNET_SYSERR;
743 }
744 return GNUNET_OK;
864} 745}
865 746
866 747
867/** 748/**
868 * CADET is ready to receive a message for the channel. Transmit it. 749 * Prepare an IPv4 packet for transmission via the TUN interface.
869 * 750 * Initializes the IP header and calculates checksums (IP+UDP/TCP).
870 * @param cls the `struct ChannelState`. 751 * For UDP, the UDP header will be fully created, whereas for TCP
871 * @param size number of bytes available in @a buf 752 * only the ports and checksum will be filled in. So for TCP,
872 * @param buf where to copy the message 753 * a skeleton TCP header must be part of the provided payload.
873 * @return number of bytes copied to @a buf
874 */
875static size_t
876send_to_peer_notify_callback (void *cls,
877 size_t size,
878 void *buf)
879{
880 struct ChannelState *s = cls;
881 struct GNUNET_CADET_Channel *channel = s->channel;
882 struct ChannelMessageQueue *tnq;
883
884 s->th = NULL;
885 tnq = s->specifics.tcp_udp.head;
886 if (NULL == tnq)
887 return 0;
888 if (0 == size)
889 {
890 s->th = GNUNET_CADET_notify_transmit_ready (channel,
891 GNUNET_NO /* corking */,
892 GNUNET_TIME_UNIT_FOREVER_REL,
893 tnq->len,
894 &send_to_peer_notify_callback,
895 s);
896 return 0;
897 }
898 GNUNET_assert (size >= tnq->len);
899 GNUNET_memcpy (buf, tnq->payload, tnq->len);
900 size = tnq->len;
901 GNUNET_CONTAINER_DLL_remove (s->specifics.tcp_udp.head,
902 s->specifics.tcp_udp.tail,
903 tnq);
904 GNUNET_free (tnq);
905 if (NULL != (tnq = s->specifics.tcp_udp.head))
906 s->th = GNUNET_CADET_notify_transmit_ready (channel,
907 GNUNET_NO /* corking */,
908 GNUNET_TIME_UNIT_FOREVER_REL,
909 tnq->len,
910 &send_to_peer_notify_callback,
911 s);
912 GNUNET_STATISTICS_update (stats,
913 gettext_noop ("# Bytes transmitted via cadet channels"),
914 size, GNUNET_NO);
915 return size;
916}
917
918
919/**
920 * Send the given packet via the cadet channel.
921 *
922 * @param s channel destination
923 * @param tnq message to queue
924 */
925static void
926send_packet_to_cadet_channel (struct ChannelState *s,
927 struct ChannelMessageQueue *tnq)
928{
929 struct GNUNET_CADET_Channel *cadet_channel;
930
931 cadet_channel = s->channel;
932 GNUNET_assert (NULL != s);
933 GNUNET_CONTAINER_DLL_insert_tail (s->specifics.tcp_udp.head,
934 s->specifics.tcp_udp.tail,
935 tnq);
936 if (NULL == s->th)
937 s->th = GNUNET_CADET_notify_transmit_ready (cadet_channel,
938 GNUNET_NO /* cork */,
939 GNUNET_TIME_UNIT_FOREVER_REL,
940 tnq->len,
941 &send_to_peer_notify_callback,
942 s);
943}
944
945
946/**
947 * @brief Handles an ICMP packet received from the helper.
948 * 754 *
949 * @param icmp A pointer to the Packet 755 * @param payload payload of the packet (starting with UDP payload or
950 * @param pktlen number of bytes in @a icmp 756 * TCP header, depending on protocol)
951 * @param af address family (AFINET or AF_INET6) 757 * @param payload_length number of bytes in @a payload
952 * @param destination_ip destination IP-address of the IP packet (should 758 * @param protocol IPPROTO_UDP or IPPROTO_TCP
953 * be our local address) 759 * @param tcp_header skeleton of the TCP header, NULL for UDP
954 * @param source_ip original source IP-address of the IP packet (should 760 * @param src_address source address to use (IP and port)
955 * be the original destination address) 761 * @param dst_address destination address to use (IP and port)
762 * @param pkt4 where to write the assembled packet; must
763 * contain enough space for the IP header, UDP/TCP header
764 * AND the payload
956 */ 765 */
957static void 766static void
958icmp_from_helper (const struct GNUNET_TUN_IcmpHeader *icmp, 767prepare_ipv4_packet (const void *payload,
959 size_t pktlen, 768 size_t payload_length,
960 int af, 769 int protocol,
961 const void *destination_ip, 770 const struct GNUNET_TUN_TcpHeader *tcp_header,
962 const void *source_ip) 771 const struct SocketAddress *src_address,
772 const struct SocketAddress *dst_address,
773 struct GNUNET_TUN_IPv4Header *pkt4)
963{ 774{
964 struct ChannelState *state; 775 size_t len;
965 struct ChannelMessageQueue *tnq;
966 struct GNUNET_EXIT_IcmpToVPNMessage *i2v;
967 const struct GNUNET_TUN_IPv4Header *ipv4;
968 const struct GNUNET_TUN_IPv6Header *ipv6;
969 const struct GNUNET_TUN_UdpHeader *udp;
970 size_t mlen;
971 uint16_t source_port;
972 uint16_t destination_port;
973 uint8_t protocol;
974 776
777 len = payload_length;
778 switch (protocol)
975 { 779 {
976 char sbuf[INET6_ADDRSTRLEN]; 780 case IPPROTO_UDP:
977 char dbuf[INET6_ADDRSTRLEN]; 781 len += sizeof (struct GNUNET_TUN_UdpHeader);
978 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 782 break;
979 "Received ICMP packet going from %s to %s\n", 783 case IPPROTO_TCP:
980 inet_ntop (af, 784 len += sizeof (struct GNUNET_TUN_TcpHeader);
981 source_ip, 785 GNUNET_assert (NULL != tcp_header);
982 sbuf, sizeof (sbuf)), 786 break;
983 inet_ntop (af, 787 default:
984 destination_ip, 788 GNUNET_break (0);
985 dbuf, sizeof (dbuf))); 789 return;
986 } 790 }
987 if (pktlen < sizeof (struct GNUNET_TUN_IcmpHeader)) 791 if (len + sizeof (struct GNUNET_TUN_IPv4Header) > UINT16_MAX)
988 { 792 {
989 /* blame kernel */
990 GNUNET_break (0); 793 GNUNET_break (0);
991 return; 794 return;
992 } 795 }
993 796
994 /* Find out if this is an ICMP packet in response to an existing 797 GNUNET_TUN_initialize_ipv4_header (pkt4,
995 TCP/UDP packet and if so, figure out ports / protocol of the 798 protocol,
996 existing session from the IP data in the ICMP payload */ 799 len,
997 source_port = 0; 800 &src_address->address.ipv4,
998 destination_port = 0; 801 &dst_address->address.ipv4);
999 switch (af)
1000 {
1001 case AF_INET:
1002 protocol = IPPROTO_ICMP;
1003 switch (icmp->type)
1004 {
1005 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1006 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1007 break;
1008 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1009 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1010 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1011 if (pktlen <
1012 sizeof (struct GNUNET_TUN_IcmpHeader) +
1013 sizeof (struct GNUNET_TUN_IPv4Header) + 8)
1014 {
1015 /* blame kernel */
1016 GNUNET_break (0);
1017 return;
1018 }
1019 ipv4 = (const struct GNUNET_TUN_IPv4Header *) &icmp[1];
1020 protocol = ipv4->protocol;
1021 /* could be TCP or UDP, but both have the ports in the right
1022 place, so that doesn't matter here */
1023 udp = (const struct GNUNET_TUN_UdpHeader *) &ipv4[1];
1024 /* swap ports, as they are from the original message */
1025 destination_port = ntohs (udp->source_port);
1026 source_port = ntohs (udp->destination_port);
1027 /* throw away ICMP payload, won't be useful for the other side anyway */
1028 pktlen = sizeof (struct GNUNET_TUN_IcmpHeader);
1029 break;
1030 default:
1031 GNUNET_STATISTICS_update (stats,
1032 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1033 1, GNUNET_NO);
1034 return;
1035 }
1036 break;
1037 case AF_INET6:
1038 protocol = IPPROTO_ICMPV6;
1039 switch (icmp->type)
1040 {
1041 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1042 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1043 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1044 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1045 if (pktlen <
1046 sizeof (struct GNUNET_TUN_IcmpHeader) +
1047 sizeof (struct GNUNET_TUN_IPv6Header) + 8)
1048 {
1049 /* blame kernel */
1050 GNUNET_break (0);
1051 return;
1052 }
1053 ipv6 = (const struct GNUNET_TUN_IPv6Header *) &icmp[1];
1054 protocol = ipv6->next_header;
1055 /* could be TCP or UDP, but both have the ports in the right
1056 place, so that doesn't matter here */
1057 udp = (const struct GNUNET_TUN_UdpHeader *) &ipv6[1];
1058 /* swap ports, as they are from the original message */
1059 destination_port = ntohs (udp->source_port);
1060 source_port = ntohs (udp->destination_port);
1061 /* throw away ICMP payload, won't be useful for the other side anyway */
1062 pktlen = sizeof (struct GNUNET_TUN_IcmpHeader);
1063 break;
1064 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1065 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1066 break;
1067 default:
1068 GNUNET_STATISTICS_update (stats,
1069 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1070 1, GNUNET_NO);
1071 return;
1072 }
1073 break;
1074 default:
1075 GNUNET_assert (0);
1076 }
1077 switch (protocol) 802 switch (protocol)
1078 { 803 {
1079 case IPPROTO_ICMP:
1080 state = get_redirect_state (af,
1081 IPPROTO_ICMP,
1082 source_ip,
1083 0,
1084 destination_ip,
1085 0,
1086 NULL);
1087 break;
1088 case IPPROTO_ICMPV6:
1089 state = get_redirect_state (af,
1090 IPPROTO_ICMPV6,
1091 source_ip,
1092 0,
1093 destination_ip,
1094 0,
1095 NULL);
1096 break;
1097 case IPPROTO_UDP: 804 case IPPROTO_UDP:
1098 state = get_redirect_state (af, 805 {
1099 IPPROTO_UDP, 806 struct GNUNET_TUN_UdpHeader *pkt4_udp = (struct GNUNET_TUN_UdpHeader *) &pkt4[1];
1100 source_ip, 807
1101 source_port, 808 pkt4_udp->source_port = htons (src_address->port);
1102 destination_ip, 809 pkt4_udp->destination_port = htons (dst_address->port);
1103 destination_port, 810 pkt4_udp->len = htons ((uint16_t) payload_length);
1104 NULL); 811 GNUNET_TUN_calculate_udp4_checksum (pkt4,
812 pkt4_udp,
813 payload,
814 payload_length);
815 GNUNET_memcpy (&pkt4_udp[1],
816 payload,
817 payload_length);
818 }
1105 break; 819 break;
1106 case IPPROTO_TCP: 820 case IPPROTO_TCP:
1107 state = get_redirect_state (af, 821 {
1108 IPPROTO_TCP, 822 struct GNUNET_TUN_TcpHeader *pkt4_tcp = (struct GNUNET_TUN_TcpHeader *) &pkt4[1];
1109 source_ip, 823
1110 source_port, 824 *pkt4_tcp = *tcp_header;
1111 destination_ip, 825 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1112 destination_port, 826 "Sending TCP packet from port %u to port %u\n",
1113 NULL); 827 src_address->port,
828 dst_address->port);
829 pkt4_tcp->source_port = htons (src_address->port);
830 pkt4_tcp->destination_port = htons (dst_address->port);
831 GNUNET_TUN_calculate_tcp4_checksum (pkt4,
832 pkt4_tcp,
833 payload,
834 payload_length);
835 GNUNET_memcpy (&pkt4_tcp[1],
836 payload,
837 payload_length);
838 }
1114 break; 839 break;
1115 default: 840 default:
1116 GNUNET_STATISTICS_update (stats, 841 GNUNET_assert (0);
1117 gettext_noop ("# ICMP packets dropped (not allowed)"),
1118 1,
1119 GNUNET_NO);
1120 return;
1121 }
1122 if (NULL == state)
1123 {
1124 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1125 _("ICMP Packet dropped, have no matching connection information\n"));
1126 return;
1127 } 842 }
1128 mlen = sizeof (struct GNUNET_EXIT_IcmpToVPNMessage) + pktlen - sizeof (struct GNUNET_TUN_IcmpHeader);
1129 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueue) + mlen);
1130 tnq->payload = &tnq[1];
1131 tnq->len = mlen;
1132 i2v = (struct GNUNET_EXIT_IcmpToVPNMessage *) &tnq[1];
1133 i2v->header.size = htons ((uint16_t) mlen);
1134 i2v->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN);
1135 i2v->af = htonl (af);
1136 GNUNET_memcpy (&i2v->icmp_header,
1137 icmp,
1138 pktlen);
1139 send_packet_to_cadet_channel (state, tnq);
1140} 843}
1141 844
1142 845
1143/** 846/**
1144 * @brief Handles an UDP packet received from the helper. 847 * Prepare an IPv6 packet for transmission via the TUN interface.
848 * Initializes the IP header and calculates checksums (IP+UDP/TCP).
849 * For UDP, the UDP header will be fully created, whereas for TCP
850 * only the ports and checksum will be filled in. So for TCP,
851 * a skeleton TCP header must be part of the provided payload.
1145 * 852 *
1146 * @param udp A pointer to the Packet 853 * @param payload payload of the packet (starting with UDP payload or
1147 * @param pktlen number of bytes in 'udp' 854 * TCP header, depending on protocol)
1148 * @param af address family (AFINET or AF_INET6) 855 * @param payload_length number of bytes in @a payload
1149 * @param destination_ip destination IP-address of the IP packet (should 856 * @param protocol IPPROTO_UDP or IPPROTO_TCP
1150 * be our local address) 857 * @param tcp_header skeleton TCP header data to send, NULL for UDP
1151 * @param source_ip original source IP-address of the IP packet (should 858 * @param src_address source address to use (IP and port)
1152 * be the original destination address) 859 * @param dst_address destination address to use (IP and port)
860 * @param pkt6 where to write the assembled packet; must
861 * contain enough space for the IP header, UDP/TCP header
862 * AND the payload
1153 */ 863 */
1154static void 864static void
1155udp_from_helper (const struct GNUNET_TUN_UdpHeader *udp, 865prepare_ipv6_packet (const void *payload,
1156 size_t pktlen, 866 size_t payload_length,
1157 int af, 867 int protocol,
1158 const void *destination_ip, 868 const struct GNUNET_TUN_TcpHeader *tcp_header,
1159 const void *source_ip) 869 const struct SocketAddress *src_address,
870 const struct SocketAddress *dst_address,
871 struct GNUNET_TUN_IPv6Header *pkt6)
1160{ 872{
1161 struct ChannelState *state; 873 size_t len;
1162 struct ChannelMessageQueue *tnq;
1163 struct GNUNET_EXIT_UdpReplyMessage *urm;
1164 size_t mlen;
1165 874
875 len = payload_length;
876 switch (protocol)
1166 { 877 {
1167 char sbuf[INET6_ADDRSTRLEN]; 878 case IPPROTO_UDP:
1168 char dbuf[INET6_ADDRSTRLEN]; 879 len += sizeof (struct GNUNET_TUN_UdpHeader);
1169 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 880 break;
1170 "Received UDP packet going from %s:%u to %s:%u\n", 881 case IPPROTO_TCP:
1171 inet_ntop (af, 882 len += sizeof (struct GNUNET_TUN_TcpHeader);
1172 source_ip, 883 break;
1173 sbuf, sizeof (sbuf)), 884 default:
1174 (unsigned int) ntohs (udp->source_port),
1175 inet_ntop (af,
1176 destination_ip,
1177 dbuf, sizeof (dbuf)),
1178 (unsigned int) ntohs (udp->destination_port));
1179 }
1180 if (pktlen < sizeof (struct GNUNET_TUN_UdpHeader))
1181 {
1182 /* blame kernel */
1183 GNUNET_break (0); 885 GNUNET_break (0);
1184 return; 886 return;
1185 } 887 }
1186 if (pktlen != ntohs (udp->len)) 888 if (len > UINT16_MAX)
1187 { 889 {
1188 /* blame kernel */
1189 GNUNET_break (0); 890 GNUNET_break (0);
1190 return; 891 return;
1191 } 892 }
1192 state = get_redirect_state (af, 893
1193 IPPROTO_UDP, 894 GNUNET_TUN_initialize_ipv6_header (pkt6,
1194 source_ip, 895 protocol,
1195 ntohs (udp->source_port), 896 len,
1196 destination_ip, 897 &src_address->address.ipv6,
1197 ntohs (udp->destination_port), 898 &dst_address->address.ipv6);
1198 NULL); 899
1199 if (NULL == state) 900 switch (protocol)
1200 { 901 {
1201 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 902 case IPPROTO_UDP:
1202 _("UDP Packet dropped, have no matching connection information\n")); 903 {
1203 return; 904 struct GNUNET_TUN_UdpHeader *pkt6_udp = (struct GNUNET_TUN_UdpHeader *) &pkt6[1];
905
906 pkt6_udp->source_port = htons (src_address->port);
907 pkt6_udp->destination_port = htons (dst_address->port);
908 pkt6_udp->len = htons ((uint16_t) payload_length);
909 GNUNET_TUN_calculate_udp6_checksum (pkt6,
910 pkt6_udp,
911 payload,
912 payload_length);
913 GNUNET_memcpy (&pkt6_udp[1],
914 payload,
915 payload_length);
916 }
917 break;
918 case IPPROTO_TCP:
919 {
920 struct GNUNET_TUN_TcpHeader *pkt6_tcp = (struct GNUNET_TUN_TcpHeader *) &pkt6[1];
921
922 /* GNUNET_memcpy first here as some TCP header fields are initialized this way! */
923 *pkt6_tcp = *tcp_header;
924 pkt6_tcp->source_port = htons (src_address->port);
925 pkt6_tcp->destination_port = htons (dst_address->port);
926 GNUNET_TUN_calculate_tcp6_checksum (pkt6,
927 pkt6_tcp,
928 payload,
929 payload_length);
930 GNUNET_memcpy (&pkt6_tcp[1],
931 payload,
932 payload_length);
933 }
934 break;
935 default:
936 GNUNET_assert (0);
937 break;
1204 } 938 }
1205 mlen = sizeof (struct GNUNET_EXIT_UdpReplyMessage) + pktlen - sizeof (struct GNUNET_TUN_UdpHeader);
1206 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueue) + mlen);
1207 tnq->payload = &tnq[1];
1208 tnq->len = mlen;
1209 urm = (struct GNUNET_EXIT_UdpReplyMessage *) &tnq[1];
1210 urm->header.size = htons ((uint16_t) mlen);
1211 urm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY);
1212 urm->source_port = htons (0);
1213 urm->destination_port = htons (0);
1214 GNUNET_memcpy (&urm[1],
1215 &udp[1],
1216 pktlen - sizeof (struct GNUNET_TUN_UdpHeader));
1217 send_packet_to_cadet_channel (state, tnq);
1218} 939}
1219 940
1220 941
1221/** 942/**
1222 * @brief Handles a TCP packet received from the helper. 943 * Send a TCP packet via the TUN interface.
1223 * 944 *
1224 * @param tcp A pointer to the Packet 945 * @param destination_address IP and port to use for the TCP packet's destination
1225 * @param pktlen the length of the packet, including its TCP header 946 * @param source_address IP and port to use for the TCP packet's source
1226 * @param af address family (AFINET or AF_INET6) 947 * @param tcp_header header template to use
1227 * @param destination_ip destination IP-address of the IP packet (should 948 * @param payload payload of the TCP packet
1228 * be our local address) 949 * @param payload_length number of bytes in @a payload
1229 * @param source_ip original source IP-address of the IP packet (should
1230 * be the original destination address)
1231 */ 950 */
1232static void 951static void
1233tcp_from_helper (const struct GNUNET_TUN_TcpHeader *tcp, 952send_tcp_packet_via_tun (const struct SocketAddress *destination_address,
1234 size_t pktlen, 953 const struct SocketAddress *source_address,
1235 int af, 954 const struct GNUNET_TUN_TcpHeader *tcp_header,
1236 const void *destination_ip, 955 const void *payload,
1237 const void *source_ip) 956 size_t payload_length)
1238{ 957{
1239 struct ChannelState *state; 958 size_t len;
1240 char buf[pktlen] GNUNET_ALIGN;
1241 struct GNUNET_TUN_TcpHeader *mtcp;
1242 struct GNUNET_EXIT_TcpDataMessage *tdm;
1243 struct ChannelMessageQueue *tnq;
1244 size_t mlen;
1245 959
960 GNUNET_STATISTICS_update (stats,
961 gettext_noop ("# TCP packets sent via TUN"),
962 1,
963 GNUNET_NO);
964 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
965 "Sending packet with %u bytes TCP payload via TUN\n",
966 (unsigned int) payload_length);
967 len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader);
968 switch (source_address->af)
1246 { 969 {
1247 char sbuf[INET6_ADDRSTRLEN]; 970 case AF_INET:
1248 char dbuf[INET6_ADDRSTRLEN]; 971 len += sizeof (struct GNUNET_TUN_IPv4Header);
1249 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 972 break;
1250 "Received TCP packet with %u bytes going from %s:%u to %s:%u\n", 973 case AF_INET6:
1251 (unsigned int) (pktlen - sizeof (struct GNUNET_TUN_TcpHeader)), 974 len += sizeof (struct GNUNET_TUN_IPv6Header);
1252 inet_ntop (af, 975 break;
1253 source_ip, 976 default:
1254 sbuf, sizeof (sbuf)), 977 GNUNET_break (0);
1255 (unsigned int) ntohs (tcp->source_port), 978 return;
1256 inet_ntop (af,
1257 destination_ip,
1258 dbuf, sizeof (dbuf)),
1259 (unsigned int) ntohs (tcp->destination_port));
1260 } 979 }
1261 if (pktlen < sizeof (struct GNUNET_TUN_TcpHeader)) 980 len += sizeof (struct GNUNET_TUN_TcpHeader);
981 len += payload_length;
982 if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1262 { 983 {
1263 /* blame kernel */
1264 GNUNET_break (0); 984 GNUNET_break (0);
1265 return; 985 return;
1266 } 986 }
1267 state = get_redirect_state (af,
1268 IPPROTO_TCP,
1269 source_ip,
1270 ntohs (tcp->source_port),
1271 destination_ip,
1272 ntohs (tcp->destination_port),
1273 NULL);
1274 if (NULL == state)
1275 { 987 {
1276 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 988 char buf[len] GNUNET_ALIGN;
1277 _("TCP Packet dropped, have no matching connection information\n")); 989 struct GNUNET_MessageHeader *hdr;
990 struct GNUNET_TUN_Layer2PacketHeader *tun;
1278 991
1279 return; 992 hdr = (struct GNUNET_MessageHeader *) buf;
1280 } 993 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1281 /* mug port numbers and crc to avoid information leakage; 994 hdr->size = htons (len);
1282 sender will need to lookup the correct values anyway */ 995 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
1283 GNUNET_memcpy (buf, tcp, pktlen); 996 tun->flags = htons (0);
1284 mtcp = (struct GNUNET_TUN_TcpHeader *) buf; 997 switch (source_address->af)
1285 mtcp->source_port = 0; 998 {
1286 mtcp->destination_port = 0; 999 case AF_INET:
1287 mtcp->crc = 0; 1000 {
1001 struct GNUNET_TUN_IPv4Header *ipv4
1002 = (struct GNUNET_TUN_IPv4Header*) &tun[1];
1288 1003
1289 mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) + (pktlen - sizeof (struct GNUNET_TUN_TcpHeader)); 1004 tun->proto = htons (ETH_P_IPV4);
1290 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE) 1005 prepare_ipv4_packet (payload,
1291 { 1006 payload_length,
1292 GNUNET_break (0); 1007 IPPROTO_TCP,
1293 return; 1008 tcp_header,
1294 } 1009 source_address,
1010 destination_address,
1011 ipv4);
1012 }
1013 break;
1014 case AF_INET6:
1015 {
1016 struct GNUNET_TUN_IPv6Header *ipv6
1017 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
1295 1018
1296 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueue) + mlen); 1019 tun->proto = htons (ETH_P_IPV6);
1297 tnq->payload = &tnq[1]; 1020 prepare_ipv6_packet (payload,
1298 tnq->len = mlen; 1021 payload_length,
1299 tdm = (struct GNUNET_EXIT_TcpDataMessage *) &tnq[1]; 1022 IPPROTO_TCP,
1300 tdm->header.size = htons ((uint16_t) mlen); 1023 tcp_header,
1301 tdm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN); 1024 source_address,
1302 tdm->reserved = htonl (0); 1025 destination_address,
1303 GNUNET_memcpy (&tdm->tcp_header, 1026 ipv6);
1304 buf, 1027 }
1305 pktlen); 1028 break;
1306 send_packet_to_cadet_channel (state, tnq); 1029 default:
1030 GNUNET_assert (0);
1031 break;
1032 }
1033 if (NULL != helper_handle)
1034 (void) GNUNET_HELPER_send (helper_handle,
1035 (const struct GNUNET_MessageHeader*) buf,
1036 GNUNET_YES,
1037 NULL,
1038 NULL);
1039 }
1307} 1040}
1308 1041
1309 1042
1310/** 1043/**
1311 * Receive packets from the helper-process 1044 * Send an ICMP packet via the TUN interface.
1312 * 1045 *
1313 * @param cls unused 1046 * @param destination_address IP to use for the ICMP packet's destination
1314 * @param client unsued 1047 * @param source_address IP to use for the ICMP packet's source
1315 * @param message message received from helper 1048 * @param icmp_header ICMP header to send
1049 * @param payload payload of the ICMP packet (does NOT include ICMP header)
1050 * @param payload_length number of bytes of data in @a payload
1316 */ 1051 */
1317static int 1052static void
1318message_token (void *cls GNUNET_UNUSED, 1053send_icmp_packet_via_tun (const struct SocketAddress *destination_address,
1319 void *client GNUNET_UNUSED, 1054 const struct SocketAddress *source_address,
1320 const struct GNUNET_MessageHeader *message) 1055 const struct GNUNET_TUN_IcmpHeader *icmp_header,
1056 const void *payload, size_t payload_length)
1321{ 1057{
1322 const struct GNUNET_TUN_Layer2PacketHeader *pkt_tun; 1058 size_t len;
1323 size_t size; 1059 struct GNUNET_TUN_IcmpHeader *icmp;
1324 1060
1325 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1326 "Got %u-byte message of type %u from gnunet-helper-exit\n",
1327 ntohs (message->size),
1328 ntohs (message->type));
1329 GNUNET_STATISTICS_update (stats, 1061 GNUNET_STATISTICS_update (stats,
1330 gettext_noop ("# Packets received from TUN"), 1062 gettext_noop ("# ICMP packets sent via TUN"),
1331 1, GNUNET_NO); 1063 1, GNUNET_NO);
1332 if (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) 1064 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1065 "Sending packet with %u bytes ICMP payload via TUN\n",
1066 (unsigned int) payload_length);
1067 len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader);
1068 switch (destination_address->af)
1333 { 1069 {
1070 case AF_INET:
1071 len += sizeof (struct GNUNET_TUN_IPv4Header);
1072 break;
1073 case AF_INET6:
1074 len += sizeof (struct GNUNET_TUN_IPv6Header);
1075 break;
1076 default:
1334 GNUNET_break (0); 1077 GNUNET_break (0);
1335 return GNUNET_OK; 1078 return;
1336 } 1079 }
1337 size = ntohs (message->size); 1080 len += sizeof (struct GNUNET_TUN_IcmpHeader);
1338 if (size < sizeof (struct GNUNET_TUN_Layer2PacketHeader) + sizeof (struct GNUNET_MessageHeader)) 1081 len += payload_length;
1082 if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1339 { 1083 {
1340 GNUNET_break (0); 1084 GNUNET_break (0);
1341 return GNUNET_OK; 1085 return;
1342 } 1086 }
1343 GNUNET_STATISTICS_update (stats,
1344 gettext_noop ("# Bytes received from TUN"),
1345 size, GNUNET_NO);
1346 pkt_tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
1347 size -= sizeof (struct GNUNET_TUN_Layer2PacketHeader) + sizeof (struct GNUNET_MessageHeader);
1348 switch (ntohs (pkt_tun->proto))
1349 { 1087 {
1350 case ETH_P_IPV4: 1088 char buf[len] GNUNET_ALIGN;
1351 { 1089 struct GNUNET_MessageHeader *hdr;
1352 const struct GNUNET_TUN_IPv4Header *pkt4; 1090 struct GNUNET_TUN_Layer2PacketHeader *tun;
1353
1354 if (size < sizeof (struct GNUNET_TUN_IPv4Header))
1355 {
1356 /* Kernel to blame? */
1357 GNUNET_break (0);
1358 return GNUNET_OK;
1359 }
1360 pkt4 = (const struct GNUNET_TUN_IPv4Header *) &pkt_tun[1];
1361 if (size != ntohs (pkt4->total_length))
1362 {
1363 /* Kernel to blame? */
1364 GNUNET_break (0);
1365 return GNUNET_OK;
1366 }
1367 if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
1368 {
1369 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1370 _("IPv4 packet options received. Ignored.\n"));
1371 return GNUNET_OK;
1372 }
1373 1091
1374 size -= sizeof (struct GNUNET_TUN_IPv4Header); 1092 hdr= (struct GNUNET_MessageHeader *) buf;
1375 switch (pkt4->protocol) 1093 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1376 { 1094 hdr->size = htons (len);
1377 case IPPROTO_UDP: 1095 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
1378 udp_from_helper ((const struct GNUNET_TUN_UdpHeader *) &pkt4[1], size, 1096 tun->flags = htons (0);
1379 AF_INET, 1097 switch (source_address->af)
1380 &pkt4->destination_address,
1381 &pkt4->source_address);
1382 break;
1383 case IPPROTO_TCP:
1384 tcp_from_helper ((const struct GNUNET_TUN_TcpHeader *) &pkt4[1], size,
1385 AF_INET,
1386 &pkt4->destination_address,
1387 &pkt4->source_address);
1388 break;
1389 case IPPROTO_ICMP:
1390 icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt4[1], size,
1391 AF_INET,
1392 &pkt4->destination_address,
1393 &pkt4->source_address);
1394 break;
1395 default:
1396 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1397 _("IPv4 packet with unsupported next header %u received. Ignored.\n"),
1398 (int) pkt4->protocol);
1399 return GNUNET_OK;
1400 }
1401 }
1402 break;
1403 case ETH_P_IPV6:
1404 { 1098 {
1405 const struct GNUNET_TUN_IPv6Header *pkt6; 1099 case AF_INET:
1406
1407 if (size < sizeof (struct GNUNET_TUN_IPv6Header))
1408 {
1409 /* Kernel to blame? */
1410 GNUNET_break (0);
1411 return GNUNET_OK;
1412 }
1413 pkt6 = (struct GNUNET_TUN_IPv6Header *) &pkt_tun[1];
1414 if (size != ntohs (pkt6->payload_length) + sizeof (struct GNUNET_TUN_IPv6Header))
1415 { 1100 {
1416 /* Kernel to blame? */ 1101 struct GNUNET_TUN_IPv4Header * ipv4 = (struct GNUNET_TUN_IPv4Header*) &tun[1];
1417 GNUNET_break (0); 1102
1418 return GNUNET_OK; 1103 tun->proto = htons (ETH_P_IPV4);
1104 GNUNET_TUN_initialize_ipv4_header (ipv4,
1105 IPPROTO_ICMP,
1106 sizeof (struct GNUNET_TUN_IcmpHeader) + payload_length,
1107 &source_address->address.ipv4,
1108 &destination_address->address.ipv4);
1109 icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv4[1];
1419 } 1110 }
1420 size -= sizeof (struct GNUNET_TUN_IPv6Header); 1111 break;
1421 switch (pkt6->next_header) 1112 case AF_INET6:
1422 { 1113 {
1423 case IPPROTO_UDP: 1114 struct GNUNET_TUN_IPv6Header * ipv6 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
1424 udp_from_helper ((const struct GNUNET_TUN_UdpHeader *) &pkt6[1], size, 1115
1425 AF_INET6, 1116 tun->proto = htons (ETH_P_IPV6);
1426 &pkt6->destination_address, 1117 GNUNET_TUN_initialize_ipv6_header (ipv6,
1427 &pkt6->source_address); 1118 IPPROTO_ICMPV6,
1428 break; 1119 sizeof (struct GNUNET_TUN_IcmpHeader) + payload_length,
1429 case IPPROTO_TCP: 1120 &source_address->address.ipv6,
1430 tcp_from_helper ((const struct GNUNET_TUN_TcpHeader *) &pkt6[1], size, 1121 &destination_address->address.ipv6);
1431 AF_INET6, 1122 icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv6[1];
1432 &pkt6->destination_address,
1433 &pkt6->source_address);
1434 break;
1435 case IPPROTO_ICMPV6:
1436 icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt6[1], size,
1437 AF_INET6,
1438 &pkt6->destination_address,
1439 &pkt6->source_address);
1440 break;
1441 default:
1442 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1443 _("IPv6 packet with unsupported next header %d received. Ignored.\n"),
1444 pkt6->next_header);
1445 return GNUNET_OK;
1446 } 1123 }
1124 break;
1125 default:
1126 GNUNET_assert (0);
1127 break;
1447 } 1128 }
1448 break; 1129 *icmp = *icmp_header;
1449 default: 1130 GNUNET_memcpy (&icmp[1],
1450 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1131 payload,
1451 _("Packet from unknown protocol %u received. Ignored.\n"), 1132 payload_length);
1452 ntohs (pkt_tun->proto)); 1133 GNUNET_TUN_calculate_icmp_checksum (icmp,
1453 break; 1134 payload,
1135 payload_length);
1136 if (NULL != helper_handle)
1137 (void) GNUNET_HELPER_send (helper_handle,
1138 (const struct GNUNET_MessageHeader*) buf,
1139 GNUNET_YES,
1140 NULL, NULL);
1454 } 1141 }
1455 return GNUNET_OK;
1456} 1142}
1457 1143
1458 1144
@@ -1637,223 +1323,25 @@ setup_state_record (struct ChannelState *state)
1637 1323
1638 1324
1639/** 1325/**
1640 * Prepare an IPv4 packet for transmission via the TUN interface. 1326 * Send a UDP packet via the TUN interface.
1641 * Initializes the IP header and calculates checksums (IP+UDP/TCP).
1642 * For UDP, the UDP header will be fully created, whereas for TCP
1643 * only the ports and checksum will be filled in. So for TCP,
1644 * a skeleton TCP header must be part of the provided payload.
1645 *
1646 * @param payload payload of the packet (starting with UDP payload or
1647 * TCP header, depending on protocol)
1648 * @param payload_length number of bytes in @a payload
1649 * @param protocol IPPROTO_UDP or IPPROTO_TCP
1650 * @param tcp_header skeleton of the TCP header, NULL for UDP
1651 * @param src_address source address to use (IP and port)
1652 * @param dst_address destination address to use (IP and port)
1653 * @param pkt4 where to write the assembled packet; must
1654 * contain enough space for the IP header, UDP/TCP header
1655 * AND the payload
1656 */
1657static void
1658prepare_ipv4_packet (const void *payload,
1659 size_t payload_length,
1660 int protocol,
1661 const struct GNUNET_TUN_TcpHeader *tcp_header,
1662 const struct SocketAddress *src_address,
1663 const struct SocketAddress *dst_address,
1664 struct GNUNET_TUN_IPv4Header *pkt4)
1665{
1666 size_t len;
1667
1668 len = payload_length;
1669 switch (protocol)
1670 {
1671 case IPPROTO_UDP:
1672 len += sizeof (struct GNUNET_TUN_UdpHeader);
1673 break;
1674 case IPPROTO_TCP:
1675 len += sizeof (struct GNUNET_TUN_TcpHeader);
1676 GNUNET_assert (NULL != tcp_header);
1677 break;
1678 default:
1679 GNUNET_break (0);
1680 return;
1681 }
1682 if (len + sizeof (struct GNUNET_TUN_IPv4Header) > UINT16_MAX)
1683 {
1684 GNUNET_break (0);
1685 return;
1686 }
1687
1688 GNUNET_TUN_initialize_ipv4_header (pkt4,
1689 protocol,
1690 len,
1691 &src_address->address.ipv4,
1692 &dst_address->address.ipv4);
1693 switch (protocol)
1694 {
1695 case IPPROTO_UDP:
1696 {
1697 struct GNUNET_TUN_UdpHeader *pkt4_udp = (struct GNUNET_TUN_UdpHeader *) &pkt4[1];
1698
1699 pkt4_udp->source_port = htons (src_address->port);
1700 pkt4_udp->destination_port = htons (dst_address->port);
1701 pkt4_udp->len = htons ((uint16_t) payload_length);
1702 GNUNET_TUN_calculate_udp4_checksum (pkt4,
1703 pkt4_udp,
1704 payload,
1705 payload_length);
1706 GNUNET_memcpy (&pkt4_udp[1],
1707 payload,
1708 payload_length);
1709 }
1710 break;
1711 case IPPROTO_TCP:
1712 {
1713 struct GNUNET_TUN_TcpHeader *pkt4_tcp = (struct GNUNET_TUN_TcpHeader *) &pkt4[1];
1714
1715 *pkt4_tcp = *tcp_header;
1716 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1717 "Sending TCP packet from port %u to port %u\n",
1718 src_address->port,
1719 dst_address->port);
1720 pkt4_tcp->source_port = htons (src_address->port);
1721 pkt4_tcp->destination_port = htons (dst_address->port);
1722 GNUNET_TUN_calculate_tcp4_checksum (pkt4,
1723 pkt4_tcp,
1724 payload,
1725 payload_length);
1726 GNUNET_memcpy (&pkt4_tcp[1],
1727 payload,
1728 payload_length);
1729 }
1730 break;
1731 default:
1732 GNUNET_assert (0);
1733 }
1734}
1735
1736
1737/**
1738 * Prepare an IPv6 packet for transmission via the TUN interface.
1739 * Initializes the IP header and calculates checksums (IP+UDP/TCP).
1740 * For UDP, the UDP header will be fully created, whereas for TCP
1741 * only the ports and checksum will be filled in. So for TCP,
1742 * a skeleton TCP header must be part of the provided payload.
1743 *
1744 * @param payload payload of the packet (starting with UDP payload or
1745 * TCP header, depending on protocol)
1746 * @param payload_length number of bytes in @a payload
1747 * @param protocol IPPROTO_UDP or IPPROTO_TCP
1748 * @param tcp_header skeleton TCP header data to send, NULL for UDP
1749 * @param src_address source address to use (IP and port)
1750 * @param dst_address destination address to use (IP and port)
1751 * @param pkt6 where to write the assembled packet; must
1752 * contain enough space for the IP header, UDP/TCP header
1753 * AND the payload
1754 */
1755static void
1756prepare_ipv6_packet (const void *payload,
1757 size_t payload_length,
1758 int protocol,
1759 const struct GNUNET_TUN_TcpHeader *tcp_header,
1760 const struct SocketAddress *src_address,
1761 const struct SocketAddress *dst_address,
1762 struct GNUNET_TUN_IPv6Header *pkt6)
1763{
1764 size_t len;
1765
1766 len = payload_length;
1767 switch (protocol)
1768 {
1769 case IPPROTO_UDP:
1770 len += sizeof (struct GNUNET_TUN_UdpHeader);
1771 break;
1772 case IPPROTO_TCP:
1773 len += sizeof (struct GNUNET_TUN_TcpHeader);
1774 break;
1775 default:
1776 GNUNET_break (0);
1777 return;
1778 }
1779 if (len > UINT16_MAX)
1780 {
1781 GNUNET_break (0);
1782 return;
1783 }
1784
1785 GNUNET_TUN_initialize_ipv6_header (pkt6,
1786 protocol,
1787 len,
1788 &src_address->address.ipv6,
1789 &dst_address->address.ipv6);
1790
1791 switch (protocol)
1792 {
1793 case IPPROTO_UDP:
1794 {
1795 struct GNUNET_TUN_UdpHeader *pkt6_udp = (struct GNUNET_TUN_UdpHeader *) &pkt6[1];
1796
1797 pkt6_udp->source_port = htons (src_address->port);
1798 pkt6_udp->destination_port = htons (dst_address->port);
1799 pkt6_udp->len = htons ((uint16_t) payload_length);
1800 GNUNET_TUN_calculate_udp6_checksum (pkt6,
1801 pkt6_udp,
1802 payload,
1803 payload_length);
1804 GNUNET_memcpy (&pkt6_udp[1],
1805 payload,
1806 payload_length);
1807 }
1808 break;
1809 case IPPROTO_TCP:
1810 {
1811 struct GNUNET_TUN_TcpHeader *pkt6_tcp = (struct GNUNET_TUN_TcpHeader *) &pkt6[1];
1812
1813 /* GNUNET_memcpy first here as some TCP header fields are initialized this way! */
1814 *pkt6_tcp = *tcp_header;
1815 pkt6_tcp->source_port = htons (src_address->port);
1816 pkt6_tcp->destination_port = htons (dst_address->port);
1817 GNUNET_TUN_calculate_tcp6_checksum (pkt6,
1818 pkt6_tcp,
1819 payload,
1820 payload_length);
1821 GNUNET_memcpy (&pkt6_tcp[1],
1822 payload,
1823 payload_length);
1824 }
1825 break;
1826 default:
1827 GNUNET_assert (0);
1828 break;
1829 }
1830}
1831
1832
1833/**
1834 * Send a TCP packet via the TUN interface.
1835 * 1327 *
1836 * @param destination_address IP and port to use for the TCP packet's destination 1328 * @param destination_address IP and port to use for the UDP packet's destination
1837 * @param source_address IP and port to use for the TCP packet's source 1329 * @param source_address IP and port to use for the UDP packet's source
1838 * @param tcp_header header template to use 1330 * @param payload payload of the UDP packet (does NOT include UDP header)
1839 * @param payload payload of the TCP packet 1331 * @param payload_length number of bytes of data in @a payload
1840 * @param payload_length number of bytes in @a payload
1841 */ 1332 */
1842static void 1333static void
1843send_tcp_packet_via_tun (const struct SocketAddress *destination_address, 1334send_udp_packet_via_tun (const struct SocketAddress *destination_address,
1844 const struct SocketAddress *source_address, 1335 const struct SocketAddress *source_address,
1845 const struct GNUNET_TUN_TcpHeader *tcp_header, 1336 const void *payload, size_t payload_length)
1846 const void *payload,
1847 size_t payload_length)
1848{ 1337{
1849 size_t len; 1338 size_t len;
1850 1339
1851 GNUNET_STATISTICS_update (stats, 1340 GNUNET_STATISTICS_update (stats,
1852 gettext_noop ("# TCP packets sent via TUN"), 1341 gettext_noop ("# UDP packets sent via TUN"),
1853 1, 1342 1, GNUNET_NO);
1854 GNUNET_NO);
1855 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1343 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1856 "Sending packet with %u bytes TCP payload via TUN\n", 1344 "Sending packet with %u bytes UDP payload via TUN\n",
1857 (unsigned int) payload_length); 1345 (unsigned int) payload_length);
1858 len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader); 1346 len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader);
1859 switch (source_address->af) 1347 switch (source_address->af)
@@ -1868,7 +1356,7 @@ send_tcp_packet_via_tun (const struct SocketAddress *destination_address,
1868 GNUNET_break (0); 1356 GNUNET_break (0);
1869 return; 1357 return;
1870 } 1358 }
1871 len += sizeof (struct GNUNET_TUN_TcpHeader); 1359 len += sizeof (struct GNUNET_TUN_UdpHeader);
1872 len += payload_length; 1360 len += payload_length;
1873 if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE) 1361 if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1874 { 1362 {
@@ -1880,7 +1368,7 @@ send_tcp_packet_via_tun (const struct SocketAddress *destination_address,
1880 struct GNUNET_MessageHeader *hdr; 1368 struct GNUNET_MessageHeader *hdr;
1881 struct GNUNET_TUN_Layer2PacketHeader *tun; 1369 struct GNUNET_TUN_Layer2PacketHeader *tun;
1882 1370
1883 hdr = (struct GNUNET_MessageHeader *) buf; 1371 hdr= (struct GNUNET_MessageHeader *) buf;
1884 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); 1372 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1885 hdr->size = htons (len); 1373 hdr->size = htons (len);
1886 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1]; 1374 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
@@ -1889,14 +1377,13 @@ send_tcp_packet_via_tun (const struct SocketAddress *destination_address,
1889 { 1377 {
1890 case AF_INET: 1378 case AF_INET:
1891 { 1379 {
1892 struct GNUNET_TUN_IPv4Header *ipv4 1380 struct GNUNET_TUN_IPv4Header * ipv4 = (struct GNUNET_TUN_IPv4Header*) &tun[1];
1893 = (struct GNUNET_TUN_IPv4Header*) &tun[1];
1894 1381
1895 tun->proto = htons (ETH_P_IPV4); 1382 tun->proto = htons (ETH_P_IPV4);
1896 prepare_ipv4_packet (payload, 1383 prepare_ipv4_packet (payload,
1897 payload_length, 1384 payload_length,
1898 IPPROTO_TCP, 1385 IPPROTO_UDP,
1899 tcp_header, 1386 NULL,
1900 source_address, 1387 source_address,
1901 destination_address, 1388 destination_address,
1902 ipv4); 1389 ipv4);
@@ -1904,14 +1391,13 @@ send_tcp_packet_via_tun (const struct SocketAddress *destination_address,
1904 break; 1391 break;
1905 case AF_INET6: 1392 case AF_INET6:
1906 { 1393 {
1907 struct GNUNET_TUN_IPv6Header *ipv6 1394 struct GNUNET_TUN_IPv6Header * ipv6 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
1908 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
1909 1395
1910 tun->proto = htons (ETH_P_IPV6); 1396 tun->proto = htons (ETH_P_IPV6);
1911 prepare_ipv6_packet (payload, 1397 prepare_ipv6_packet (payload,
1912 payload_length, 1398 payload_length,
1913 IPPROTO_TCP, 1399 IPPROTO_UDP,
1914 tcp_header, 1400 NULL,
1915 source_address, 1401 source_address,
1916 destination_address, 1402 destination_address,
1917 ipv6); 1403 ipv6);
@@ -1925,48 +1411,202 @@ send_tcp_packet_via_tun (const struct SocketAddress *destination_address,
1925 (void) GNUNET_HELPER_send (helper_handle, 1411 (void) GNUNET_HELPER_send (helper_handle,
1926 (const struct GNUNET_MessageHeader*) buf, 1412 (const struct GNUNET_MessageHeader*) buf,
1927 GNUNET_YES, 1413 GNUNET_YES,
1928 NULL, 1414 NULL, NULL);
1929 NULL);
1930 } 1415 }
1931} 1416}
1932 1417
1933 1418
1934/** 1419/**
1935 * Process a request via cadet to send a request to a TCP service 1420 * Check a request to forward UDP data to the Internet via this peer.
1936 * offered by this system.
1937 * 1421 *
1938 * @param cls closure, NULL 1422 * @param cls our `struct ChannelState *`
1939 * @param channel connection to the other end 1423 * @param msg the actual message
1940 * @param channel_ctx pointer to our `struct ChannelState *`
1941 * @param message the actual message
1942 * @return #GNUNET_OK to keep the connection open, 1424 * @return #GNUNET_OK to keep the connection open,
1943 * #GNUNET_SYSERR to close it (signal serious error) 1425 * #GNUNET_SYSERR to close it (signal serious error)
1944 */ 1426 */
1945static int 1427static int
1946receive_tcp_service (void *cls, 1428check_udp_remote (void *cls,
1947 struct GNUNET_CADET_Channel *channel, 1429 const struct GNUNET_EXIT_UdpInternetMessage *msg)
1948 void **channel_ctx,
1949 const struct GNUNET_MessageHeader *message)
1950{ 1430{
1951 struct ChannelState *state = *channel_ctx; 1431 struct ChannelState *state = cls;
1952 const struct GNUNET_EXIT_TcpServiceStartMessage *start;
1953 uint16_t pkt_len = ntohs (message->size);
1954 1432
1955 if (NULL == state) 1433 if (GNUNET_YES == state->is_dns)
1956 { 1434 {
1957 GNUNET_break_op (0); 1435 GNUNET_break_op (0);
1958 return GNUNET_SYSERR; 1436 return GNUNET_SYSERR;
1959 } 1437 }
1960 if (GNUNET_YES == state->is_dns) 1438 return GNUNET_OK;
1439}
1440
1441
1442/**
1443 * Process a request to forward UDP data to the Internet via this peer.
1444 *
1445 * @param cls our `struct ChannelState *`
1446 * @param msg the actual message
1447 */
1448static void
1449handle_udp_remote (void *cls,
1450 const struct GNUNET_EXIT_UdpInternetMessage *msg)
1451{
1452 struct ChannelState *state = cls;
1453 uint16_t pkt_len = ntohs (msg->header.size) - sizeof (struct GNUNET_EXIT_UdpInternetMessage);
1454 const struct in_addr *v4;
1455 const struct in6_addr *v6;
1456 const void *payload;
1457 int af;
1458
1459 if (GNUNET_SYSERR == state->is_dns)
1460 {
1461 /* channel is UDP/TCP from now on */
1462 state->is_dns = GNUNET_NO;
1463 }
1464 GNUNET_STATISTICS_update (stats,
1465 gettext_noop ("# Bytes received from CADET"),
1466 pkt_len, GNUNET_NO);
1467 GNUNET_STATISTICS_update (stats,
1468 gettext_noop ("# UDP IP-exit requests received via cadet"),
1469 1, GNUNET_NO);
1470 af = (int) ntohl (msg->af);
1471 state->specifics.tcp_udp.ri.remote_address.af = af;
1472 switch (af)
1961 { 1473 {
1474 case AF_INET:
1475 if (pkt_len < sizeof (struct in_addr))
1476 {
1477 GNUNET_break_op (0);
1478 return;
1479 }
1480 if (! ipv4_exit)
1481 {
1482 GNUNET_break_op (0);
1483 return;
1484 }
1485 v4 = (const struct in_addr*) &msg[1];
1486 payload = &v4[1];
1487 pkt_len -= sizeof (struct in_addr);
1488 state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4;
1489 break;
1490 case AF_INET6:
1491 if (pkt_len < sizeof (struct in6_addr))
1492 {
1493 GNUNET_break_op (0);
1494 return;
1495 }
1496 if (! ipv6_exit)
1497 {
1498 GNUNET_break_op (0);
1499 return;
1500 }
1501 v6 = (const struct in6_addr*) &msg[1];
1502 payload = &v6[1];
1503 pkt_len -= sizeof (struct in6_addr);
1504 state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6;
1505 break;
1506 default:
1962 GNUNET_break_op (0); 1507 GNUNET_break_op (0);
1963 return GNUNET_SYSERR; 1508 return;
1964 } 1509 }
1510 {
1511 char buf[INET6_ADDRSTRLEN];
1512 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1513 "Received data from %s for forwarding to UDP %s:%u\n",
1514 GNUNET_i2s (&state->peer),
1515 inet_ntop (af,
1516 &state->specifics.tcp_udp.ri.remote_address.address,
1517 buf, sizeof (buf)),
1518 (unsigned int) ntohs (msg->destination_port));
1519 }
1520 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_UDP;
1521 state->specifics.tcp_udp.ri.remote_address.port = msg->destination_port;
1522 if (NULL == state->specifics.tcp_udp.heap_node)
1523 setup_state_record (state);
1524 if (0 != ntohs (msg->source_port))
1525 state->specifics.tcp_udp.ri.local_address.port = msg->source_port;
1526 send_udp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1527 &state->specifics.tcp_udp.ri.local_address,
1528 payload,
1529 pkt_len);
1530 GNUNET_CADET_receive_done (state->channel);
1531}
1532
1533
1534/**
1535 * Check a request via cadet to send a request to a UDP service
1536 * offered by this system.
1537 *
1538 * @param cls our `struct ChannelState *`
1539 * @param msg the actual message
1540 * @return #GNUNET_OK to keep the connection open,
1541 * #GNUNET_SYSERR to close it (signal serious error)
1542 */
1543static int
1544check_udp_service (void *cls,
1545 const struct GNUNET_EXIT_UdpServiceMessage *msg)
1546{
1547 struct ChannelState *state = cls;
1548
1965 if (NULL == state->specifics.tcp_udp.serv) 1549 if (NULL == state->specifics.tcp_udp.serv)
1966 { 1550 {
1967 GNUNET_break_op (0); 1551 GNUNET_break_op (0);
1968 return GNUNET_SYSERR; 1552 return GNUNET_SYSERR;
1969 } 1553 }
1554 return GNUNET_OK;
1555}
1556
1557
1558/**
1559 * Process a request via cadet to send a request to a UDP service
1560 * offered by this system.
1561 *
1562 * @param cls our `struct ChannelState *`
1563 * @param msg the actual message
1564 */
1565static void
1566handle_udp_service (void *cls,
1567 const struct GNUNET_EXIT_UdpServiceMessage *msg)
1568{
1569 struct ChannelState *state = cls;
1570 uint16_t pkt_len = ntohs (msg->header.size) - sizeof (struct GNUNET_EXIT_UdpServiceMessage);
1571
1572 GNUNET_STATISTICS_update (stats,
1573 gettext_noop ("# Bytes received from CADET"),
1574 pkt_len, GNUNET_NO);
1575 GNUNET_STATISTICS_update (stats,
1576 gettext_noop ("# UDP service requests received via cadet"),
1577 1, GNUNET_NO);
1578 LOG (GNUNET_ERROR_TYPE_DEBUG,
1579 "Received data from %s for forwarding to UDP service %s on port %u\n",
1580 GNUNET_i2s (&state->peer),
1581 GNUNET_h2s (&state->specifics.tcp_udp.serv->descriptor),
1582 (unsigned int) ntohs (msg->destination_port));
1583 setup_state_record (state);
1584 if (0 != ntohs (msg->source_port))
1585 state->specifics.tcp_udp.ri.local_address.port = msg->source_port;
1586 send_udp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1587 &state->specifics.tcp_udp.ri.local_address,
1588 &msg[1],
1589 pkt_len);
1590 GNUNET_CADET_receive_done (state->channel);
1591}
1592
1593
1594/**
1595 * Process a request via cadet to send a request to a TCP service
1596 * offered by this system.
1597 *
1598 * @param cls our `struct ChannelState *`
1599 * @param start the actual message
1600 * @return #GNUNET_OK to keep the connection open,
1601 * #GNUNET_SYSERR to close it (signal serious error)
1602 */
1603static void
1604handle_tcp_service (void *cls,
1605 const struct GNUNET_EXIT_TcpServiceStartMessage *start)
1606{
1607 struct ChannelState *state = cls;
1608 uint16_t pkt_len = ntohs (start->header.size) - sizeof (struct GNUNET_EXIT_TcpServiceStartMessage);
1609
1970 if (GNUNET_SYSERR == state->is_dns) 1610 if (GNUNET_SYSERR == state->is_dns)
1971 { 1611 {
1972 /* channel is UDP/TCP from now on */ 1612 /* channel is UDP/TCP from now on */
@@ -1980,24 +1620,6 @@ receive_tcp_service (void *cls,
1980 gettext_noop ("# Bytes received from CADET"), 1620 gettext_noop ("# Bytes received from CADET"),
1981 pkt_len, 1621 pkt_len,
1982 GNUNET_NO); 1622 GNUNET_NO);
1983 /* check that we got at least a valid header */
1984 if (pkt_len < sizeof (struct GNUNET_EXIT_TcpServiceStartMessage))
1985 {
1986 GNUNET_break_op (0);
1987 return GNUNET_SYSERR;
1988 }
1989 start = (const struct GNUNET_EXIT_TcpServiceStartMessage*) message;
1990 pkt_len -= sizeof (struct GNUNET_EXIT_TcpServiceStartMessage);
1991 if (NULL != state->specifics.tcp_udp.heap_node)
1992 {
1993 GNUNET_break_op (0);
1994 return GNUNET_SYSERR;
1995 }
1996 if (start->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
1997 {
1998 GNUNET_break_op (0);
1999 return GNUNET_SYSERR;
2000 }
2001 GNUNET_break_op (ntohl (start->reserved) == 0); 1623 GNUNET_break_op (ntohl (start->reserved) == 0);
2002 /* setup fresh connection */ 1624 /* setup fresh connection */
2003 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1625 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -2011,34 +1633,23 @@ receive_tcp_service (void *cls,
2011 &start->tcp_header, 1633 &start->tcp_header,
2012 &start[1], 1634 &start[1],
2013 pkt_len); 1635 pkt_len);
2014 GNUNET_CADET_receive_done (channel); 1636 GNUNET_CADET_receive_done (state->channel);
2015 return GNUNET_YES;
2016} 1637}
2017 1638
2018 1639
2019/** 1640/**
2020 * Process a request to forward TCP data to the Internet via this peer. 1641 * Check a request to forward TCP data to the Internet via this peer.
2021 * 1642 *
2022 * @param cls closure, NULL 1643 * @param cls our `struct ChannelState *`
2023 * @param channel connection to the other end 1644 * @param start the actual message
2024 * @param channel_ctx pointer to our `struct ChannelState *`
2025 * @param message the actual message
2026 * @return #GNUNET_OK to keep the connection open, 1645 * @return #GNUNET_OK to keep the connection open,
2027 * #GNUNET_SYSERR to close it (signal serious error) 1646 * #GNUNET_SYSERR to close it (signal serious error)
2028 */ 1647 */
2029static int 1648static int
2030receive_tcp_remote (void *cls GNUNET_UNUSED, 1649check_tcp_remote (void *cls,
2031 struct GNUNET_CADET_Channel *channel, 1650 const struct GNUNET_EXIT_TcpInternetStartMessage *start)
2032 void **channel_ctx GNUNET_UNUSED,
2033 const struct GNUNET_MessageHeader *message)
2034{ 1651{
2035 struct ChannelState *state = *channel_ctx; 1652 struct ChannelState *state = cls;
2036 const struct GNUNET_EXIT_TcpInternetStartMessage *start;
2037 uint16_t pkt_len = ntohs (message->size);
2038 const struct in_addr *v4;
2039 const struct in6_addr *v6;
2040 const void *payload;
2041 int af;
2042 1653
2043 if (NULL == state) 1654 if (NULL == state)
2044 { 1655 {
@@ -2050,24 +1661,6 @@ receive_tcp_remote (void *cls GNUNET_UNUSED,
2050 GNUNET_break_op (0); 1661 GNUNET_break_op (0);
2051 return GNUNET_SYSERR; 1662 return GNUNET_SYSERR;
2052 } 1663 }
2053 if (GNUNET_SYSERR == state->is_dns)
2054 {
2055 /* channel is UDP/TCP from now on */
2056 state->is_dns = GNUNET_NO;
2057 }
2058 GNUNET_STATISTICS_update (stats,
2059 gettext_noop ("# Bytes received from CADET"),
2060 pkt_len, GNUNET_NO);
2061 GNUNET_STATISTICS_update (stats,
2062 gettext_noop ("# TCP IP-exit creation requests received via cadet"),
2063 1, GNUNET_NO);
2064 if (pkt_len < sizeof (struct GNUNET_EXIT_TcpInternetStartMessage))
2065 {
2066 GNUNET_break_op (0);
2067 return GNUNET_SYSERR;
2068 }
2069 start = (const struct GNUNET_EXIT_TcpInternetStartMessage*) message;
2070 pkt_len -= sizeof (struct GNUNET_EXIT_TcpInternetStartMessage);
2071 if ( (NULL != state->specifics.tcp_udp.serv) || 1664 if ( (NULL != state->specifics.tcp_udp.serv) ||
2072 (NULL != state->specifics.tcp_udp.heap_node) ) 1665 (NULL != state->specifics.tcp_udp.heap_node) )
2073 { 1666 {
@@ -2079,6 +1672,38 @@ receive_tcp_remote (void *cls GNUNET_UNUSED,
2079 GNUNET_break_op (0); 1672 GNUNET_break_op (0);
2080 return GNUNET_SYSERR; 1673 return GNUNET_SYSERR;
2081 } 1674 }
1675 return GNUNET_OK;
1676}
1677
1678
1679/**
1680 * Process a request to forward TCP data to the Internet via this peer.
1681 *
1682 * @param cls our `struct ChannelState *`
1683 * @param start the actual message
1684 */
1685static void
1686handle_tcp_remote (void *cls,
1687 const struct GNUNET_EXIT_TcpInternetStartMessage *start)
1688{
1689 struct ChannelState *state = cls;
1690 uint16_t pkt_len = ntohs (start->header.size) - sizeof (struct GNUNET_EXIT_TcpInternetStartMessage);
1691 const struct in_addr *v4;
1692 const struct in6_addr *v6;
1693 const void *payload;
1694 int af;
1695
1696 if (GNUNET_SYSERR == state->is_dns)
1697 {
1698 /* channel is UDP/TCP from now on */
1699 state->is_dns = GNUNET_NO;
1700 }
1701 GNUNET_STATISTICS_update (stats,
1702 gettext_noop ("# Bytes received from CADET"),
1703 pkt_len, GNUNET_NO);
1704 GNUNET_STATISTICS_update (stats,
1705 gettext_noop ("# TCP IP-exit creation requests received via cadet"),
1706 1, GNUNET_NO);
2082 af = (int) ntohl (start->af); 1707 af = (int) ntohl (start->af);
2083 state->specifics.tcp_udp.ri.remote_address.af = af; 1708 state->specifics.tcp_udp.ri.remote_address.af = af;
2084 switch (af) 1709 switch (af)
@@ -2087,12 +1712,12 @@ receive_tcp_remote (void *cls GNUNET_UNUSED,
2087 if (pkt_len < sizeof (struct in_addr)) 1712 if (pkt_len < sizeof (struct in_addr))
2088 { 1713 {
2089 GNUNET_break_op (0); 1714 GNUNET_break_op (0);
2090 return GNUNET_SYSERR; 1715 return;
2091 } 1716 }
2092 if (! ipv4_exit) 1717 if (! ipv4_exit)
2093 { 1718 {
2094 GNUNET_break_op (0); 1719 GNUNET_break_op (0);
2095 return GNUNET_SYSERR; 1720 return;
2096 } 1721 }
2097 v4 = (const struct in_addr*) &start[1]; 1722 v4 = (const struct in_addr*) &start[1];
2098 payload = &v4[1]; 1723 payload = &v4[1];
@@ -2103,12 +1728,12 @@ receive_tcp_remote (void *cls GNUNET_UNUSED,
2103 if (pkt_len < sizeof (struct in6_addr)) 1728 if (pkt_len < sizeof (struct in6_addr))
2104 { 1729 {
2105 GNUNET_break_op (0); 1730 GNUNET_break_op (0);
2106 return GNUNET_SYSERR; 1731 return;
2107 } 1732 }
2108 if (! ipv6_exit) 1733 if (! ipv6_exit)
2109 { 1734 {
2110 GNUNET_break_op (0); 1735 GNUNET_break_op (0);
2111 return GNUNET_SYSERR; 1736 return;
2112 } 1737 }
2113 v6 = (const struct in6_addr*) &start[1]; 1738 v6 = (const struct in6_addr*) &start[1];
2114 payload = &v6[1]; 1739 payload = &v6[1];
@@ -2117,7 +1742,7 @@ receive_tcp_remote (void *cls GNUNET_UNUSED,
2117 break; 1742 break;
2118 default: 1743 default:
2119 GNUNET_break_op (0); 1744 GNUNET_break_op (0);
2120 return GNUNET_SYSERR; 1745 return;
2121 } 1746 }
2122 { 1747 {
2123 char buf[INET6_ADDRSTRLEN]; 1748 char buf[INET6_ADDRSTRLEN];
@@ -2135,46 +1760,27 @@ receive_tcp_remote (void *cls GNUNET_UNUSED,
2135 send_tcp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address, 1760 send_tcp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
2136 &state->specifics.tcp_udp.ri.local_address, 1761 &state->specifics.tcp_udp.ri.local_address,
2137 &start->tcp_header, 1762 &start->tcp_header,
2138 payload, pkt_len); 1763 payload,
2139 GNUNET_CADET_receive_done (channel); 1764 pkt_len);
2140 return GNUNET_YES; 1765 GNUNET_CADET_receive_done (state->channel);
2141} 1766}
2142 1767
2143 1768
2144/** 1769/**
2145 * Process a request to forward TCP data on an established 1770 * Check a request to forward TCP data on an established
2146 * connection via this peer. 1771 * connection via this peer.
2147 * 1772 *
2148 * @param cls closure, NULL 1773 * @param cls our `struct ChannelState *`
2149 * @param channel connection to the other end
2150 * @param channel_ctx pointer to our `struct ChannelState *`
2151 * @param message the actual message 1774 * @param message the actual message
2152 * @return #GNUNET_OK to keep the connection open, 1775 * @return #GNUNET_OK to keep the connection open,
2153 * #GNUNET_SYSERR to close it (signal serious error) 1776 * #GNUNET_SYSERR to close it (signal serious error)
2154 */ 1777 */
2155static int 1778static int
2156receive_tcp_data (void *cls GNUNET_UNUSED, 1779check_tcp_data (void *cls,
2157 struct GNUNET_CADET_Channel *channel, 1780 const struct GNUNET_EXIT_TcpDataMessage *data)
2158 void **channel_ctx GNUNET_UNUSED,
2159 const struct GNUNET_MessageHeader *message)
2160{ 1781{
2161 struct ChannelState *state = *channel_ctx; 1782 struct ChannelState *state = cls;
2162 const struct GNUNET_EXIT_TcpDataMessage *data;
2163 uint16_t pkt_len = ntohs (message->size);
2164 1783
2165 GNUNET_STATISTICS_update (stats,
2166 gettext_noop ("# Bytes received from CADET"),
2167 pkt_len, GNUNET_NO);
2168 GNUNET_STATISTICS_update (stats,
2169 gettext_noop ("# TCP data requests received via cadet"),
2170 1, GNUNET_NO);
2171 if (pkt_len < sizeof (struct GNUNET_EXIT_TcpDataMessage))
2172 {
2173 GNUNET_break_op (0);
2174 return GNUNET_SYSERR;
2175 }
2176 data = (const struct GNUNET_EXIT_TcpDataMessage*) message;
2177 pkt_len -= sizeof (struct GNUNET_EXIT_TcpDataMessage);
2178 if ( (NULL == state) || 1784 if ( (NULL == state) ||
2179 (NULL == state->specifics.tcp_udp.heap_node) ) 1785 (NULL == state->specifics.tcp_udp.heap_node) )
2180 { 1786 {
@@ -2195,6 +1801,30 @@ receive_tcp_data (void *cls GNUNET_UNUSED,
2195 GNUNET_break_op (0); 1801 GNUNET_break_op (0);
2196 return GNUNET_SYSERR; 1802 return GNUNET_SYSERR;
2197 } 1803 }
1804 return GNUNET_OK;
1805}
1806
1807
1808/**
1809 * Process a request to forward TCP data on an established
1810 * connection via this peer.
1811 *
1812 * @param cls our `struct ChannelState *`
1813 * @param message the actual message
1814 */
1815static void
1816handle_tcp_data (void *cls,
1817 const struct GNUNET_EXIT_TcpDataMessage *data)
1818{
1819 struct ChannelState *state = cls;
1820 uint16_t pkt_len = ntohs (data->header.size) - sizeof (struct GNUNET_EXIT_TcpDataMessage);
1821
1822 GNUNET_STATISTICS_update (stats,
1823 gettext_noop ("# Bytes received from CADET"),
1824 pkt_len, GNUNET_NO);
1825 GNUNET_STATISTICS_update (stats,
1826 gettext_noop ("# TCP data requests received via cadet"),
1827 1, GNUNET_NO);
2198 if (GNUNET_SYSERR == state->is_dns) 1828 if (GNUNET_SYSERR == state->is_dns)
2199 { 1829 {
2200 /* channel is UDP/TCP from now on */ 1830 /* channel is UDP/TCP from now on */
@@ -2218,110 +1848,7 @@ receive_tcp_data (void *cls GNUNET_UNUSED,
2218 &state->specifics.tcp_udp.ri.local_address, 1848 &state->specifics.tcp_udp.ri.local_address,
2219 &data->tcp_header, 1849 &data->tcp_header,
2220 &data[1], pkt_len); 1850 &data[1], pkt_len);
2221 GNUNET_CADET_receive_done (channel); 1851 GNUNET_CADET_receive_done (state->channel);
2222 return GNUNET_YES;
2223}
2224
2225
2226/**
2227 * Send an ICMP packet via the TUN interface.
2228 *
2229 * @param destination_address IP to use for the ICMP packet's destination
2230 * @param source_address IP to use for the ICMP packet's source
2231 * @param icmp_header ICMP header to send
2232 * @param payload payload of the ICMP packet (does NOT include ICMP header)
2233 * @param payload_length number of bytes of data in @a payload
2234 */
2235static void
2236send_icmp_packet_via_tun (const struct SocketAddress *destination_address,
2237 const struct SocketAddress *source_address,
2238 const struct GNUNET_TUN_IcmpHeader *icmp_header,
2239 const void *payload, size_t payload_length)
2240{
2241 size_t len;
2242 struct GNUNET_TUN_IcmpHeader *icmp;
2243
2244 GNUNET_STATISTICS_update (stats,
2245 gettext_noop ("# ICMP packets sent via TUN"),
2246 1, GNUNET_NO);
2247 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2248 "Sending packet with %u bytes ICMP payload via TUN\n",
2249 (unsigned int) payload_length);
2250 len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader);
2251 switch (destination_address->af)
2252 {
2253 case AF_INET:
2254 len += sizeof (struct GNUNET_TUN_IPv4Header);
2255 break;
2256 case AF_INET6:
2257 len += sizeof (struct GNUNET_TUN_IPv6Header);
2258 break;
2259 default:
2260 GNUNET_break (0);
2261 return;
2262 }
2263 len += sizeof (struct GNUNET_TUN_IcmpHeader);
2264 len += payload_length;
2265 if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2266 {
2267 GNUNET_break (0);
2268 return;
2269 }
2270 {
2271 char buf[len] GNUNET_ALIGN;
2272 struct GNUNET_MessageHeader *hdr;
2273 struct GNUNET_TUN_Layer2PacketHeader *tun;
2274
2275 hdr= (struct GNUNET_MessageHeader *) buf;
2276 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2277 hdr->size = htons (len);
2278 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
2279 tun->flags = htons (0);
2280 switch (source_address->af)
2281 {
2282 case AF_INET:
2283 {
2284 struct GNUNET_TUN_IPv4Header * ipv4 = (struct GNUNET_TUN_IPv4Header*) &tun[1];
2285
2286 tun->proto = htons (ETH_P_IPV4);
2287 GNUNET_TUN_initialize_ipv4_header (ipv4,
2288 IPPROTO_ICMP,
2289 sizeof (struct GNUNET_TUN_IcmpHeader) + payload_length,
2290 &source_address->address.ipv4,
2291 &destination_address->address.ipv4);
2292 icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv4[1];
2293 }
2294 break;
2295 case AF_INET6:
2296 {
2297 struct GNUNET_TUN_IPv6Header * ipv6 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
2298
2299 tun->proto = htons (ETH_P_IPV6);
2300 GNUNET_TUN_initialize_ipv6_header (ipv6,
2301 IPPROTO_ICMPV6,
2302 sizeof (struct GNUNET_TUN_IcmpHeader) + payload_length,
2303 &source_address->address.ipv6,
2304 &destination_address->address.ipv6);
2305 icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv6[1];
2306 }
2307 break;
2308 default:
2309 GNUNET_assert (0);
2310 break;
2311 }
2312 *icmp = *icmp_header;
2313 GNUNET_memcpy (&icmp[1],
2314 payload,
2315 payload_length);
2316 GNUNET_TUN_calculate_icmp_checksum (icmp,
2317 payload,
2318 payload_length);
2319 if (NULL != helper_handle)
2320 (void) GNUNET_HELPER_send (helper_handle,
2321 (const struct GNUNET_MessageHeader*) buf,
2322 GNUNET_YES,
2323 NULL, NULL);
2324 }
2325} 1852}
2326 1853
2327 1854
@@ -2378,35 +1905,46 @@ make_up_icmpv6_payload (struct ChannelState *state,
2378 1905
2379 1906
2380/** 1907/**
2381 * Process a request to forward ICMP data to the Internet via this peer. 1908 * Check a request to forward ICMP data to the Internet via this peer.
2382 * 1909 *
2383 * @param cls closure, NULL 1910 * @param cls our `struct ChannelState *`
2384 * @param channel connection to the other end 1911 * @param msg the actual message
2385 * @param channel_ctx pointer to our 'struct ChannelState *'
2386 * @param message the actual message
2387 * @return #GNUNET_OK to keep the connection open, 1912 * @return #GNUNET_OK to keep the connection open,
2388 * #GNUNET_SYSERR to close it (signal serious error) 1913 * #GNUNET_SYSERR to close it (signal serious error)
2389 */ 1914 */
2390static int 1915static int
2391receive_icmp_remote (void *cls, 1916check_icmp_remote (void *cls,
2392 struct GNUNET_CADET_Channel *channel, 1917 const struct GNUNET_EXIT_IcmpInternetMessage *msg)
2393 void **channel_ctx,
2394 const struct GNUNET_MessageHeader *message)
2395{ 1918{
2396 struct ChannelState *state = *channel_ctx; 1919 struct ChannelState *state = cls;
2397 const struct GNUNET_EXIT_IcmpInternetMessage *msg;
2398 uint16_t pkt_len = ntohs (message->size);
2399 const struct in_addr *v4;
2400 const struct in6_addr *v6;
2401 const void *payload;
2402 char buf[sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
2403 int af;
2404 1920
2405 if (GNUNET_YES == state->is_dns) 1921 if (GNUNET_YES == state->is_dns)
2406 { 1922 {
2407 GNUNET_break_op (0); 1923 GNUNET_break_op (0);
2408 return GNUNET_SYSERR; 1924 return GNUNET_SYSERR;
2409 } 1925 }
1926 return GNUNET_OK;
1927}
1928
1929
1930/**
1931 * Process a request to forward ICMP data to the Internet via this peer.
1932 *
1933 * @param cls our `struct ChannelState *`
1934 * @param msg the actual message
1935 */
1936static void
1937handle_icmp_remote (void *cls,
1938 const struct GNUNET_EXIT_IcmpInternetMessage *msg)
1939{
1940 struct ChannelState *state = cls;
1941 uint16_t pkt_len = ntohs (msg->header.size) - sizeof (struct GNUNET_EXIT_IcmpInternetMessage);
1942 const struct in_addr *v4;
1943 const struct in6_addr *v6;
1944 const void *payload;
1945 char buf[sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
1946 int af;
1947
2410 if (GNUNET_SYSERR == state->is_dns) 1948 if (GNUNET_SYSERR == state->is_dns)
2411 { 1949 {
2412 /* channel is UDP/TCP from now on */ 1950 /* channel is UDP/TCP from now on */
@@ -2418,13 +1956,6 @@ receive_icmp_remote (void *cls,
2418 GNUNET_STATISTICS_update (stats, 1956 GNUNET_STATISTICS_update (stats,
2419 gettext_noop ("# ICMP IP-exit requests received via cadet"), 1957 gettext_noop ("# ICMP IP-exit requests received via cadet"),
2420 1, GNUNET_NO); 1958 1, GNUNET_NO);
2421 if (pkt_len < sizeof (struct GNUNET_EXIT_IcmpInternetMessage))
2422 {
2423 GNUNET_break_op (0);
2424 return GNUNET_SYSERR;
2425 }
2426 msg = (const struct GNUNET_EXIT_IcmpInternetMessage*) message;
2427 pkt_len -= sizeof (struct GNUNET_EXIT_IcmpInternetMessage);
2428 1959
2429 af = (int) ntohl (msg->af); 1960 af = (int) ntohl (msg->af);
2430 if ( (NULL != state->specifics.tcp_udp.heap_node) && 1961 if ( (NULL != state->specifics.tcp_udp.heap_node) &&
@@ -2432,7 +1963,7 @@ receive_icmp_remote (void *cls,
2432 { 1963 {
2433 /* other peer switched AF on this channel; not allowed */ 1964 /* other peer switched AF on this channel; not allowed */
2434 GNUNET_break_op (0); 1965 GNUNET_break_op (0);
2435 return GNUNET_SYSERR; 1966 return;
2436 } 1967 }
2437 1968
2438 switch (af) 1969 switch (af)
@@ -2441,12 +1972,12 @@ receive_icmp_remote (void *cls,
2441 if (pkt_len < sizeof (struct in_addr)) 1972 if (pkt_len < sizeof (struct in_addr))
2442 { 1973 {
2443 GNUNET_break_op (0); 1974 GNUNET_break_op (0);
2444 return GNUNET_SYSERR; 1975 return;
2445 } 1976 }
2446 if (! ipv4_exit) 1977 if (! ipv4_exit)
2447 { 1978 {
2448 GNUNET_break_op (0); 1979 GNUNET_break_op (0);
2449 return GNUNET_SYSERR; 1980 return;
2450 } 1981 }
2451 v4 = (const struct in_addr*) &msg[1]; 1982 v4 = (const struct in_addr*) &msg[1];
2452 payload = &v4[1]; 1983 payload = &v4[1];
@@ -2471,7 +2002,7 @@ receive_icmp_remote (void *cls,
2471 if (0 != pkt_len) 2002 if (0 != pkt_len)
2472 { 2003 {
2473 GNUNET_break_op (0); 2004 GNUNET_break_op (0);
2474 return GNUNET_SYSERR; 2005 return;
2475 } 2006 }
2476 /* make up payload */ 2007 /* make up payload */
2477 { 2008 {
@@ -2491,7 +2022,7 @@ receive_icmp_remote (void *cls,
2491 GNUNET_STATISTICS_update (stats, 2022 GNUNET_STATISTICS_update (stats,
2492 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"), 2023 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
2493 1, GNUNET_NO); 2024 1, GNUNET_NO);
2494 return GNUNET_SYSERR; 2025 return;
2495 } 2026 }
2496 /* end AF_INET */ 2027 /* end AF_INET */
2497 break; 2028 break;
@@ -2499,12 +2030,12 @@ receive_icmp_remote (void *cls,
2499 if (pkt_len < sizeof (struct in6_addr)) 2030 if (pkt_len < sizeof (struct in6_addr))
2500 { 2031 {
2501 GNUNET_break_op (0); 2032 GNUNET_break_op (0);
2502 return GNUNET_SYSERR; 2033 return;
2503 } 2034 }
2504 if (! ipv6_exit) 2035 if (! ipv6_exit)
2505 { 2036 {
2506 GNUNET_break_op (0); 2037 GNUNET_break_op (0);
2507 return GNUNET_SYSERR; 2038 return;
2508 } 2039 }
2509 v6 = (const struct in6_addr*) &msg[1]; 2040 v6 = (const struct in6_addr*) &msg[1];
2510 payload = &v6[1]; 2041 payload = &v6[1];
@@ -2530,7 +2061,7 @@ receive_icmp_remote (void *cls,
2530 if (0 != pkt_len) 2061 if (0 != pkt_len)
2531 { 2062 {
2532 GNUNET_break_op (0); 2063 GNUNET_break_op (0);
2533 return GNUNET_SYSERR; 2064 return;
2534 } 2065 }
2535 /* make up payload */ 2066 /* make up payload */
2536 { 2067 {
@@ -2550,14 +2081,14 @@ receive_icmp_remote (void *cls,
2550 GNUNET_STATISTICS_update (stats, 2081 GNUNET_STATISTICS_update (stats,
2551 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"), 2082 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2552 1, GNUNET_NO); 2083 1, GNUNET_NO);
2553 return GNUNET_SYSERR; 2084 return;
2554 } 2085 }
2555 /* end AF_INET6 */ 2086 /* end AF_INET6 */
2556 break; 2087 break;
2557 default: 2088 default:
2558 /* bad AF */ 2089 /* bad AF */
2559 GNUNET_break_op (0); 2090 GNUNET_break_op (0);
2560 return GNUNET_SYSERR; 2091 return;
2561 } 2092 }
2562 2093
2563 { 2094 {
@@ -2573,8 +2104,7 @@ receive_icmp_remote (void *cls,
2573 &state->specifics.tcp_udp.ri.local_address, 2104 &state->specifics.tcp_udp.ri.local_address,
2574 &msg->icmp_header, 2105 &msg->icmp_header,
2575 payload, pkt_len); 2106 payload, pkt_len);
2576 GNUNET_CADET_receive_done (channel); 2107 GNUNET_CADET_receive_done (state->channel);
2577 return GNUNET_YES;
2578} 2108}
2579 2109
2580 2110
@@ -2629,28 +2159,19 @@ make_up_icmp_service_payload (struct ChannelState *state,
2629 2159
2630 2160
2631/** 2161/**
2632 * Process a request via cadet to send ICMP data to a service 2162 * Check a request via cadet to send ICMP data to a service
2633 * offered by this system. 2163 * offered by this system.
2634 * 2164 *
2635 * @param cls closure, NULL 2165 * @param cls our `struct ChannelState *`
2636 * @param channel connection to the other end 2166 * @param msg the actual message
2637 * @param channel_ctx pointer to our 'struct ChannelState *'
2638 * @param message the actual message
2639 * @return #GNUNET_OK to keep the connection open, 2167 * @return #GNUNET_OK to keep the connection open,
2640 * #GNUNET_SYSERR to close it (signal serious error) 2168 * #GNUNET_SYSERR to close it (signal serious error)
2641 */ 2169 */
2642static int 2170static int
2643receive_icmp_service (void *cls, 2171check_icmp_service (void *cls,
2644 struct GNUNET_CADET_Channel *channel, 2172 const struct GNUNET_EXIT_IcmpServiceMessage *msg)
2645 void **channel_ctx,
2646 const struct GNUNET_MessageHeader *message)
2647{ 2173{
2648 struct ChannelState *state = *channel_ctx; 2174 struct ChannelState *state = cls;
2649 const struct GNUNET_EXIT_IcmpServiceMessage *msg;
2650 uint16_t pkt_len = ntohs (message->size);
2651 struct GNUNET_TUN_IcmpHeader icmp;
2652 char buf[sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
2653 const void *payload;
2654 2175
2655 if (GNUNET_YES == state->is_dns) 2176 if (GNUNET_YES == state->is_dns)
2656 { 2177 {
@@ -2662,6 +2183,27 @@ receive_icmp_service (void *cls,
2662 GNUNET_break_op (0); 2183 GNUNET_break_op (0);
2663 return GNUNET_SYSERR; 2184 return GNUNET_SYSERR;
2664 } 2185 }
2186 return GNUNET_OK;
2187}
2188
2189
2190/**
2191 * Process a request via cadet to send ICMP data to a service
2192 * offered by this system.
2193 *
2194 * @param cls our `struct ChannelState *`
2195 * @param msg the actual message
2196 */
2197static void
2198handle_icmp_service (void *cls,
2199 const struct GNUNET_EXIT_IcmpServiceMessage *msg)
2200{
2201 struct ChannelState *state = cls;
2202 uint16_t pkt_len = ntohs (msg->header.size) - sizeof (struct GNUNET_EXIT_IcmpServiceMessage);
2203 struct GNUNET_TUN_IcmpHeader icmp;
2204 char buf[sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
2205 const void *payload;
2206
2665 GNUNET_STATISTICS_update (stats, 2207 GNUNET_STATISTICS_update (stats,
2666 gettext_noop ("# Bytes received from CADET"), 2208 gettext_noop ("# Bytes received from CADET"),
2667 pkt_len, GNUNET_NO); 2209 pkt_len, GNUNET_NO);
@@ -2669,13 +2211,6 @@ receive_icmp_service (void *cls,
2669 gettext_noop ("# ICMP service requests received via cadet"), 2211 gettext_noop ("# ICMP service requests received via cadet"),
2670 1, GNUNET_NO); 2212 1, GNUNET_NO);
2671 /* check that we got at least a valid header */ 2213 /* check that we got at least a valid header */
2672 if (pkt_len < sizeof (struct GNUNET_EXIT_IcmpServiceMessage))
2673 {
2674 GNUNET_break_op (0);
2675 return GNUNET_SYSERR;
2676 }
2677 msg = (const struct GNUNET_EXIT_IcmpServiceMessage*) message;
2678 pkt_len -= sizeof (struct GNUNET_EXIT_IcmpServiceMessage);
2679 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2214 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2680 "Received data from %s for forwarding to ICMP service %s\n", 2215 "Received data from %s for forwarding to ICMP service %s\n",
2681 GNUNET_i2s (&state->peer), 2216 GNUNET_i2s (&state->peer),
@@ -2707,7 +2242,7 @@ receive_icmp_service (void *cls,
2707 if (0 != pkt_len) 2242 if (0 != pkt_len)
2708 { 2243 {
2709 GNUNET_break_op (0); 2244 GNUNET_break_op (0);
2710 return GNUNET_SYSERR; 2245 return;
2711 } 2246 }
2712 payload = buf; 2247 payload = buf;
2713 pkt_len = make_up_icmp_service_payload (state, buf); 2248 pkt_len = make_up_icmp_service_payload (state, buf);
@@ -2718,7 +2253,7 @@ receive_icmp_service (void *cls,
2718 if (0 != pkt_len) 2253 if (0 != pkt_len)
2719 { 2254 {
2720 GNUNET_break_op (0); 2255 GNUNET_break_op (0);
2721 return GNUNET_SYSERR; 2256 return;
2722 } 2257 }
2723 payload = buf; 2258 payload = buf;
2724 pkt_len = make_up_icmp_service_payload (state, buf); 2259 pkt_len = make_up_icmp_service_payload (state, buf);
@@ -2729,12 +2264,12 @@ receive_icmp_service (void *cls,
2729 GNUNET_STATISTICS_update (stats, 2264 GNUNET_STATISTICS_update (stats,
2730 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"), 2265 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
2731 1, GNUNET_NO); 2266 1, GNUNET_NO);
2732 return GNUNET_OK; 2267 return;
2733 } 2268 }
2734 if (0 != pkt_len) 2269 if (0 != pkt_len)
2735 { 2270 {
2736 GNUNET_break_op (0); 2271 GNUNET_break_op (0);
2737 return GNUNET_SYSERR; 2272 return;
2738 } 2273 }
2739 payload = buf; 2274 payload = buf;
2740 pkt_len = make_up_icmp_service_payload (state, buf); 2275 pkt_len = make_up_icmp_service_payload (state, buf);
@@ -2744,7 +2279,7 @@ receive_icmp_service (void *cls,
2744 GNUNET_STATISTICS_update (stats, 2279 GNUNET_STATISTICS_update (stats,
2745 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"), 2280 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
2746 1, GNUNET_NO); 2281 1, GNUNET_NO);
2747 return GNUNET_SYSERR; 2282 return;
2748 } 2283 }
2749 /* end of AF_INET */ 2284 /* end of AF_INET */
2750 break; 2285 break;
@@ -2765,7 +2300,7 @@ receive_icmp_service (void *cls,
2765 if (0 != pkt_len) 2300 if (0 != pkt_len)
2766 { 2301 {
2767 GNUNET_break_op (0); 2302 GNUNET_break_op (0);
2768 return GNUNET_SYSERR; 2303 return;
2769 } 2304 }
2770 payload = buf; 2305 payload = buf;
2771 pkt_len = make_up_icmp_service_payload (state, buf); 2306 pkt_len = make_up_icmp_service_payload (state, buf);
@@ -2776,7 +2311,7 @@ receive_icmp_service (void *cls,
2776 if (0 != pkt_len) 2311 if (0 != pkt_len)
2777 { 2312 {
2778 GNUNET_break_op (0); 2313 GNUNET_break_op (0);
2779 return GNUNET_SYSERR; 2314 return;
2780 } 2315 }
2781 payload = buf; 2316 payload = buf;
2782 pkt_len = make_up_icmp_service_payload (state, buf); 2317 pkt_len = make_up_icmp_service_payload (state, buf);
@@ -2788,12 +2323,12 @@ receive_icmp_service (void *cls,
2788 GNUNET_STATISTICS_update (stats, 2323 GNUNET_STATISTICS_update (stats,
2789 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"), 2324 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
2790 1, GNUNET_NO); 2325 1, GNUNET_NO);
2791 return GNUNET_OK; 2326 return;
2792 } 2327 }
2793 if (0 != pkt_len) 2328 if (0 != pkt_len)
2794 { 2329 {
2795 GNUNET_break_op (0); 2330 GNUNET_break_op (0);
2796 return GNUNET_SYSERR; 2331 return;
2797 } 2332 }
2798 payload = buf; 2333 payload = buf;
2799 pkt_len = make_up_icmp_service_payload (state, buf); 2334 pkt_len = make_up_icmp_service_payload (state, buf);
@@ -2803,283 +2338,715 @@ receive_icmp_service (void *cls,
2803 GNUNET_STATISTICS_update (stats, 2338 GNUNET_STATISTICS_update (stats,
2804 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"), 2339 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2805 1, GNUNET_NO); 2340 1, GNUNET_NO);
2806 return GNUNET_SYSERR; 2341 return;
2807 } 2342 }
2808 /* end of AF_INET6 */ 2343 /* end of AF_INET6 */
2809 break; 2344 break;
2810 default: 2345 default:
2811 GNUNET_break_op (0); 2346 GNUNET_break_op (0);
2812 return GNUNET_SYSERR; 2347 return;
2813 } 2348 }
2814 2349
2815 send_icmp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address, 2350 send_icmp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
2816 &state->specifics.tcp_udp.ri.local_address, 2351 &state->specifics.tcp_udp.ri.local_address,
2817 &icmp, 2352 &icmp,
2818 payload, pkt_len); 2353 payload,
2819 GNUNET_CADET_receive_done (channel); 2354 pkt_len);
2820 return GNUNET_YES; 2355 GNUNET_CADET_receive_done (state->channel);
2821} 2356}
2822 2357
2823 2358
2824/** 2359/**
2825 * Send a UDP packet via the TUN interface. 2360 * Free memory associated with a service record.
2826 * 2361 *
2827 * @param destination_address IP and port to use for the UDP packet's destination 2362 * @param cls unused
2828 * @param source_address IP and port to use for the UDP packet's source 2363 * @param key service descriptor
2829 * @param payload payload of the UDP packet (does NOT include UDP header) 2364 * @param value service record to free
2830 * @param payload_length number of bytes of data in @a payload 2365 * @return #GNUNET_OK
2831 */ 2366 */
2832static void 2367static int
2833send_udp_packet_via_tun (const struct SocketAddress *destination_address, 2368free_service_record (void *cls,
2834 const struct SocketAddress *source_address, 2369 const struct GNUNET_HashCode *key,
2835 const void *payload, size_t payload_length) 2370 void *value)
2836{ 2371{
2837 size_t len; 2372 struct LocalService *service = value;
2373
2374 GNUNET_assert (GNUNET_YES ==
2375 GNUNET_CONTAINER_multihashmap_remove (services,
2376 key,
2377 service));
2378 GNUNET_CADET_close_port (service->port);
2379 GNUNET_free_non_null (service->name);
2380 GNUNET_free (service);
2381 return GNUNET_OK;
2382}
2838 2383
2384
2385/**
2386 * Callback from CADET for new channels.
2387 *
2388 * @param cls closure
2389 * @param channel new handle to the channel
2390 * @param initiator peer that started the channel
2391 * @return initial channel context for the channel
2392 */
2393static void *
2394new_service_channel (void *cls,
2395 struct GNUNET_CADET_Channel *channel,
2396 const struct GNUNET_PeerIdentity *initiator)
2397{
2398 struct LocalService *ls = cls;
2399 struct ChannelState *s = GNUNET_new (struct ChannelState);
2400
2401 s->peer = *initiator;
2839 GNUNET_STATISTICS_update (stats, 2402 GNUNET_STATISTICS_update (stats,
2840 gettext_noop ("# UDP packets sent via TUN"), 2403 gettext_noop ("# Inbound CADET channels created"),
2841 1, GNUNET_NO); 2404 1,
2405 GNUNET_NO);
2842 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2406 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2843 "Sending packet with %u bytes UDP payload via TUN\n", 2407 "Received inbound channel from `%s'\n",
2844 (unsigned int) payload_length); 2408 GNUNET_i2s (initiator));
2845 len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader); 2409 s->channel = channel;
2846 switch (source_address->af) 2410 s->specifics.tcp_udp.serv = ls;
2411 s->specifics.tcp_udp.ri.remote_address = ls->address;
2412 return s;
2413}
2414
2415
2416/**
2417 * Function called by cadet whenever an inbound channel is destroyed.
2418 * Should clean up any associated state.
2419 *
2420 * @param cls our `struct ChannelState *`
2421 * @param channel connection to the other end (henceforth invalid)
2422 */
2423static void
2424clean_channel (void *cls,
2425 const struct GNUNET_CADET_Channel *channel)
2426{
2427 struct ChannelState *s = cls;
2428
2429 LOG (GNUNET_ERROR_TYPE_DEBUG,
2430 "Channel destroyed\n");
2431 if (GNUNET_SYSERR == s->is_dns)
2847 { 2432 {
2848 case AF_INET: 2433 GNUNET_free (s);
2849 len += sizeof (struct GNUNET_TUN_IPv4Header);
2850 break;
2851 case AF_INET6:
2852 len += sizeof (struct GNUNET_TUN_IPv6Header);
2853 break;
2854 default:
2855 GNUNET_break (0);
2856 return; 2434 return;
2857 } 2435 }
2858 len += sizeof (struct GNUNET_TUN_UdpHeader); 2436 if (GNUNET_YES == s->is_dns)
2859 len += payload_length;
2860 if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2861 { 2437 {
2862 GNUNET_break (0); 2438 if (channels[s->specifics.dns.my_id] == s)
2863 return; 2439 channels[s->specifics.dns.my_id] = NULL;
2864 } 2440 }
2441 else
2865 { 2442 {
2866 char buf[len] GNUNET_ALIGN; 2443 if (NULL != s->specifics.tcp_udp.heap_node)
2867 struct GNUNET_MessageHeader *hdr;
2868 struct GNUNET_TUN_Layer2PacketHeader *tun;
2869
2870 hdr= (struct GNUNET_MessageHeader *) buf;
2871 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2872 hdr->size = htons (len);
2873 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
2874 tun->flags = htons (0);
2875 switch (source_address->af)
2876 { 2444 {
2877 case AF_INET: 2445 GNUNET_assert (GNUNET_YES ==
2878 { 2446 GNUNET_CONTAINER_multihashmap_remove (connections_map,
2879 struct GNUNET_TUN_IPv4Header * ipv4 = (struct GNUNET_TUN_IPv4Header*) &tun[1]; 2447 &s->specifics.tcp_udp.state_key,
2880 2448 s));
2881 tun->proto = htons (ETH_P_IPV4); 2449 GNUNET_CONTAINER_heap_remove_node (s->specifics.tcp_udp.heap_node);
2882 prepare_ipv4_packet (payload, 2450 s->specifics.tcp_udp.heap_node = NULL;
2883 payload_length,
2884 IPPROTO_UDP,
2885 NULL,
2886 source_address,
2887 destination_address,
2888 ipv4);
2889 }
2890 break;
2891 case AF_INET6:
2892 {
2893 struct GNUNET_TUN_IPv6Header * ipv6 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
2894
2895 tun->proto = htons (ETH_P_IPV6);
2896 prepare_ipv6_packet (payload,
2897 payload_length,
2898 IPPROTO_UDP,
2899 NULL,
2900 source_address,
2901 destination_address,
2902 ipv6);
2903 }
2904 break;
2905 default:
2906 GNUNET_assert (0);
2907 break;
2908 } 2451 }
2909 if (NULL != helper_handle)
2910 (void) GNUNET_HELPER_send (helper_handle,
2911 (const struct GNUNET_MessageHeader*) buf,
2912 GNUNET_YES,
2913 NULL, NULL);
2914 } 2452 }
2453 GNUNET_free (s);
2915} 2454}
2916 2455
2917 2456
2918/** 2457/**
2919 * Process a request to forward UDP data to the Internet via this peer. 2458 * Given a service descriptor and a destination port, find the
2459 * respective service entry.
2920 * 2460 *
2921 * @param cls closure, NULL 2461 * @param proto IPPROTO_TCP or IPPROTO_UDP
2922 * @param channel connection to the other end 2462 * @param name name of the service
2923 * @param channel_ctx pointer to our 'struct ChannelState *' 2463 * @param destination_port destination port
2924 * @param message the actual message 2464 * @param service service information record to store (service->name will be set).
2925 * @return #GNUNET_OK to keep the connection open,
2926 * #GNUNET_SYSERR to close it (signal serious error)
2927 */ 2465 */
2928static int 2466static void
2929receive_udp_remote (void *cls, 2467store_service (int proto,
2930 struct GNUNET_CADET_Channel *channel, 2468 const char *name,
2931 void **channel_ctx, 2469 uint16_t destination_port,
2932 const struct GNUNET_MessageHeader *message) 2470 struct LocalService *service)
2933{ 2471{
2934 struct ChannelState *state = *channel_ctx; 2472 struct GNUNET_MQ_MessageHandler handlers[] = {
2935 const struct GNUNET_EXIT_UdpInternetMessage *msg; 2473 GNUNET_MQ_hd_var_size (icmp_service,
2936 uint16_t pkt_len = ntohs (message->size); 2474 GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE,
2937 const struct in_addr *v4; 2475 struct GNUNET_EXIT_IcmpServiceMessage,
2938 const struct in6_addr *v6; 2476 service),
2939 const void *payload; 2477 GNUNET_MQ_hd_var_size (udp_service,
2940 int af; 2478 GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE,
2479 struct GNUNET_EXIT_UdpServiceMessage,
2480 service),
2481 GNUNET_MQ_hd_var_size (tcp_service,
2482 GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START,
2483 struct GNUNET_EXIT_TcpServiceStartMessage,
2484 service),
2485 GNUNET_MQ_hd_var_size (tcp_data,
2486 GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT,
2487 struct GNUNET_EXIT_TcpDataMessage,
2488 service),
2489 GNUNET_MQ_handler_end ()
2490 };
2941 2491
2942 if (GNUNET_YES == state->is_dns) 2492 struct GNUNET_HashCode cadet_port;
2493
2494 service->name = GNUNET_strdup (name);
2495 GNUNET_TUN_service_name_to_hash (name,
2496 &service->descriptor);
2497 GNUNET_TUN_compute_service_cadet_port (&service->descriptor,
2498 destination_port,
2499 &cadet_port);
2500 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2501 "Opening CADET port %s for SERVICE exit %s on port %u\n",
2502 GNUNET_h2s (&cadet_port),
2503 name,
2504 (unsigned int) destination_port);
2505 service->port = GNUNET_CADET_open_porT (cadet_handle,
2506 &cadet_port,
2507 &new_service_channel,
2508 service,
2509 NULL,
2510 &clean_channel,
2511 handlers);
2512 service->is_udp = (IPPROTO_UDP == proto);
2513 if (GNUNET_OK !=
2514 GNUNET_CONTAINER_multihashmap_put (services,
2515 &cadet_port,
2516 service,
2517 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
2943 { 2518 {
2944 GNUNET_break_op (0); 2519 GNUNET_CADET_close_port (service->port);
2945 return GNUNET_SYSERR; 2520 GNUNET_free_non_null (service->name);
2521 GNUNET_free (service);
2522 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2523 _("Got duplicate service records for `%s:%u'\n"),
2524 name,
2525 (unsigned int) destination_port);
2946 } 2526 }
2947 if (GNUNET_SYSERR == state->is_dns) 2527}
2528
2529
2530/**
2531 * Send the given packet via the cadet channel.
2532 *
2533 * @param s channel destination
2534 * @param env message to queue
2535 */
2536static void
2537send_packet_to_cadet_channel (struct ChannelState *s,
2538 struct GNUNET_MQ_Envelope *env)
2539{
2540 GNUNET_assert (NULL != s);
2541 GNUNET_STATISTICS_update (stats,
2542 gettext_noop ("# Messages transmitted via cadet channels"),
2543 1,
2544 GNUNET_NO);
2545 GNUNET_MQ_send (GNUNET_CADET_get_mq (s->channel),
2546 env);
2547}
2548
2549
2550/**
2551 * @brief Handles an ICMP packet received from the helper.
2552 *
2553 * @param icmp A pointer to the Packet
2554 * @param pktlen number of bytes in @a icmp
2555 * @param af address family (AFINET or AF_INET6)
2556 * @param destination_ip destination IP-address of the IP packet (should
2557 * be our local address)
2558 * @param source_ip original source IP-address of the IP packet (should
2559 * be the original destination address)
2560 */
2561static void
2562icmp_from_helper (const struct GNUNET_TUN_IcmpHeader *icmp,
2563 size_t pktlen,
2564 int af,
2565 const void *destination_ip,
2566 const void *source_ip)
2567{
2568 struct ChannelState *state;
2569 struct GNUNET_MQ_Envelope *env;
2570 struct GNUNET_EXIT_IcmpToVPNMessage *i2v;
2571 const struct GNUNET_TUN_IPv4Header *ipv4;
2572 const struct GNUNET_TUN_IPv6Header *ipv6;
2573 const struct GNUNET_TUN_UdpHeader *udp;
2574 uint16_t source_port;
2575 uint16_t destination_port;
2576 uint8_t protocol;
2577
2948 { 2578 {
2949 /* channel is UDP/TCP from now on */ 2579 char sbuf[INET6_ADDRSTRLEN];
2950 state->is_dns = GNUNET_NO; 2580 char dbuf[INET6_ADDRSTRLEN];
2581 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2582 "Received ICMP packet going from %s to %s\n",
2583 inet_ntop (af,
2584 source_ip,
2585 sbuf, sizeof (sbuf)),
2586 inet_ntop (af,
2587 destination_ip,
2588 dbuf, sizeof (dbuf)));
2951 } 2589 }
2952 GNUNET_STATISTICS_update (stats, 2590 if (pktlen < sizeof (struct GNUNET_TUN_IcmpHeader))
2953 gettext_noop ("# Bytes received from CADET"),
2954 pkt_len, GNUNET_NO);
2955 GNUNET_STATISTICS_update (stats,
2956 gettext_noop ("# UDP IP-exit requests received via cadet"),
2957 1, GNUNET_NO);
2958 if (pkt_len < sizeof (struct GNUNET_EXIT_UdpInternetMessage))
2959 { 2591 {
2960 GNUNET_break_op (0); 2592 /* blame kernel */
2961 return GNUNET_SYSERR; 2593 GNUNET_break (0);
2594 return;
2962 } 2595 }
2963 msg = (const struct GNUNET_EXIT_UdpInternetMessage*) message; 2596
2964 pkt_len -= sizeof (struct GNUNET_EXIT_UdpInternetMessage); 2597 /* Find out if this is an ICMP packet in response to an existing
2965 af = (int) ntohl (msg->af); 2598 TCP/UDP packet and if so, figure out ports / protocol of the
2966 state->specifics.tcp_udp.ri.remote_address.af = af; 2599 existing session from the IP data in the ICMP payload */
2600 source_port = 0;
2601 destination_port = 0;
2967 switch (af) 2602 switch (af)
2968 { 2603 {
2969 case AF_INET: 2604 case AF_INET:
2970 if (pkt_len < sizeof (struct in_addr)) 2605 protocol = IPPROTO_ICMP;
2971 { 2606 switch (icmp->type)
2972 GNUNET_break_op (0); 2607 {
2973 return GNUNET_SYSERR; 2608 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
2974 } 2609 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
2975 if (! ipv4_exit) 2610 break;
2976 { 2611 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
2977 GNUNET_break_op (0); 2612 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2978 return GNUNET_SYSERR; 2613 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2979 } 2614 if (pktlen <
2980 v4 = (const struct in_addr*) &msg[1]; 2615 sizeof (struct GNUNET_TUN_IcmpHeader) +
2981 payload = &v4[1]; 2616 sizeof (struct GNUNET_TUN_IPv4Header) + 8)
2982 pkt_len -= sizeof (struct in_addr); 2617 {
2983 state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4; 2618 /* blame kernel */
2619 GNUNET_break (0);
2620 return;
2621 }
2622 ipv4 = (const struct GNUNET_TUN_IPv4Header *) &icmp[1];
2623 protocol = ipv4->protocol;
2624 /* could be TCP or UDP, but both have the ports in the right
2625 place, so that doesn't matter here */
2626 udp = (const struct GNUNET_TUN_UdpHeader *) &ipv4[1];
2627 /* swap ports, as they are from the original message */
2628 destination_port = ntohs (udp->source_port);
2629 source_port = ntohs (udp->destination_port);
2630 /* throw away ICMP payload, won't be useful for the other side anyway */
2631 pktlen = sizeof (struct GNUNET_TUN_IcmpHeader);
2632 break;
2633 default:
2634 GNUNET_STATISTICS_update (stats,
2635 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
2636 1, GNUNET_NO);
2637 return;
2638 }
2984 break; 2639 break;
2985 case AF_INET6: 2640 case AF_INET6:
2986 if (pkt_len < sizeof (struct in6_addr)) 2641 protocol = IPPROTO_ICMPV6;
2987 { 2642 switch (icmp->type)
2988 GNUNET_break_op (0); 2643 {
2989 return GNUNET_SYSERR; 2644 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2990 } 2645 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2991 if (! ipv6_exit) 2646 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2992 { 2647 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2993 GNUNET_break_op (0); 2648 if (pktlen <
2994 return GNUNET_SYSERR; 2649 sizeof (struct GNUNET_TUN_IcmpHeader) +
2995 } 2650 sizeof (struct GNUNET_TUN_IPv6Header) + 8)
2996 v6 = (const struct in6_addr*) &msg[1]; 2651 {
2997 payload = &v6[1]; 2652 /* blame kernel */
2998 pkt_len -= sizeof (struct in6_addr); 2653 GNUNET_break (0);
2999 state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6; 2654 return;
2655 }
2656 ipv6 = (const struct GNUNET_TUN_IPv6Header *) &icmp[1];
2657 protocol = ipv6->next_header;
2658 /* could be TCP or UDP, but both have the ports in the right
2659 place, so that doesn't matter here */
2660 udp = (const struct GNUNET_TUN_UdpHeader *) &ipv6[1];
2661 /* swap ports, as they are from the original message */
2662 destination_port = ntohs (udp->source_port);
2663 source_port = ntohs (udp->destination_port);
2664 /* throw away ICMP payload, won't be useful for the other side anyway */
2665 pktlen = sizeof (struct GNUNET_TUN_IcmpHeader);
2666 break;
2667 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2668 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2669 break;
2670 default:
2671 GNUNET_STATISTICS_update (stats,
2672 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2673 1, GNUNET_NO);
2674 return;
2675 }
3000 break; 2676 break;
3001 default: 2677 default:
3002 GNUNET_break_op (0); 2678 GNUNET_assert (0);
3003 return GNUNET_SYSERR;
3004 } 2679 }
2680 switch (protocol)
3005 { 2681 {
3006 char buf[INET6_ADDRSTRLEN]; 2682 case IPPROTO_ICMP:
2683 state = get_redirect_state (af,
2684 IPPROTO_ICMP,
2685 source_ip,
2686 0,
2687 destination_ip,
2688 0,
2689 NULL);
2690 break;
2691 case IPPROTO_ICMPV6:
2692 state = get_redirect_state (af,
2693 IPPROTO_ICMPV6,
2694 source_ip,
2695 0,
2696 destination_ip,
2697 0,
2698 NULL);
2699 break;
2700 case IPPROTO_UDP:
2701 state = get_redirect_state (af,
2702 IPPROTO_UDP,
2703 source_ip,
2704 source_port,
2705 destination_ip,
2706 destination_port,
2707 NULL);
2708 break;
2709 case IPPROTO_TCP:
2710 state = get_redirect_state (af,
2711 IPPROTO_TCP,
2712 source_ip,
2713 source_port,
2714 destination_ip,
2715 destination_port,
2716 NULL);
2717 break;
2718 default:
2719 GNUNET_STATISTICS_update (stats,
2720 gettext_noop ("# ICMP packets dropped (not allowed)"),
2721 1,
2722 GNUNET_NO);
2723 return;
2724 }
2725 if (NULL == state)
2726 {
2727 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2728 _("ICMP Packet dropped, have no matching connection information\n"));
2729 return;
2730 }
2731 env = GNUNET_MQ_msg_extra (i2v,
2732 pktlen - sizeof (struct GNUNET_TUN_IcmpHeader),
2733 GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN);
2734 i2v->af = htonl (af);
2735 GNUNET_memcpy (&i2v->icmp_header,
2736 icmp,
2737 pktlen);
2738 send_packet_to_cadet_channel (state,
2739 env);
2740}
2741
2742
2743/**
2744 * @brief Handles an UDP packet received from the helper.
2745 *
2746 * @param udp A pointer to the Packet
2747 * @param pktlen number of bytes in 'udp'
2748 * @param af address family (AFINET or AF_INET6)
2749 * @param destination_ip destination IP-address of the IP packet (should
2750 * be our local address)
2751 * @param source_ip original source IP-address of the IP packet (should
2752 * be the original destination address)
2753 */
2754static void
2755udp_from_helper (const struct GNUNET_TUN_UdpHeader *udp,
2756 size_t pktlen,
2757 int af,
2758 const void *destination_ip,
2759 const void *source_ip)
2760{
2761 struct ChannelState *state;
2762 struct GNUNET_MQ_Envelope *env;
2763 struct GNUNET_EXIT_UdpReplyMessage *urm;
2764
2765 {
2766 char sbuf[INET6_ADDRSTRLEN];
2767 char dbuf[INET6_ADDRSTRLEN];
2768
3007 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2769 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3008 "Received data from %s for forwarding to UDP %s:%u\n", 2770 "Received UDP packet going from %s:%u to %s:%u\n",
3009 GNUNET_i2s (&state->peer),
3010 inet_ntop (af, 2771 inet_ntop (af,
3011 &state->specifics.tcp_udp.ri.remote_address.address, 2772 source_ip,
3012 buf, sizeof (buf)), 2773 sbuf, sizeof (sbuf)),
3013 (unsigned int) ntohs (msg->destination_port)); 2774 (unsigned int) ntohs (udp->source_port),
2775 inet_ntop (af,
2776 destination_ip,
2777 dbuf, sizeof (dbuf)),
2778 (unsigned int) ntohs (udp->destination_port));
3014 } 2779 }
3015 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_UDP; 2780 if (pktlen < sizeof (struct GNUNET_TUN_UdpHeader))
3016 state->specifics.tcp_udp.ri.remote_address.port = msg->destination_port; 2781 {
3017 if (NULL == state->specifics.tcp_udp.heap_node) 2782 /* blame kernel */
3018 setup_state_record (state); 2783 GNUNET_break (0);
3019 if (0 != ntohs (msg->source_port)) 2784 return;
3020 state->specifics.tcp_udp.ri.local_address.port = msg->source_port; 2785 }
3021 send_udp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address, 2786 if (pktlen != ntohs (udp->len))
3022 &state->specifics.tcp_udp.ri.local_address, 2787 {
3023 payload, pkt_len); 2788 /* blame kernel */
3024 GNUNET_CADET_receive_done (channel); 2789 GNUNET_break (0);
3025 return GNUNET_YES; 2790 return;
2791 }
2792 state = get_redirect_state (af,
2793 IPPROTO_UDP,
2794 source_ip,
2795 ntohs (udp->source_port),
2796 destination_ip,
2797 ntohs (udp->destination_port),
2798 NULL);
2799 if (NULL == state)
2800 {
2801 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2802 _("UDP Packet dropped, have no matching connection information\n"));
2803 return;
2804 }
2805 env = GNUNET_MQ_msg_extra (urm,
2806 pktlen - sizeof (struct GNUNET_TUN_UdpHeader),
2807 GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY);
2808 urm->source_port = htons (0);
2809 urm->destination_port = htons (0);
2810 GNUNET_memcpy (&urm[1],
2811 &udp[1],
2812 pktlen - sizeof (struct GNUNET_TUN_UdpHeader));
2813 send_packet_to_cadet_channel (state,
2814 env);
3026} 2815}
3027 2816
3028 2817
3029/** 2818/**
3030 * Process a request via cadet to send a request to a UDP service 2819 * @brief Handles a TCP packet received from the helper.
3031 * offered by this system.
3032 * 2820 *
3033 * @param cls closure, NULL 2821 * @param tcp A pointer to the Packet
3034 * @param channel connection to the other end 2822 * @param pktlen the length of the packet, including its TCP header
3035 * @param channel_ctx pointer to our 'struct ChannelState *' 2823 * @param af address family (AFINET or AF_INET6)
3036 * @param message the actual message 2824 * @param destination_ip destination IP-address of the IP packet (should
3037 * @return #GNUNET_OK to keep the connection open, 2825 * be our local address)
3038 * #GNUNET_SYSERR to close it (signal serious error) 2826 * @param source_ip original source IP-address of the IP packet (should
2827 * be the original destination address)
3039 */ 2828 */
3040static int 2829static void
3041receive_udp_service (void *cls, 2830tcp_from_helper (const struct GNUNET_TUN_TcpHeader *tcp,
3042 struct GNUNET_CADET_Channel *channel, 2831 size_t pktlen,
3043 void **channel_ctx, 2832 int af,
3044 const struct GNUNET_MessageHeader *message) 2833 const void *destination_ip,
2834 const void *source_ip)
3045{ 2835{
3046 struct ChannelState *state = *channel_ctx; 2836 struct ChannelState *state;
3047 const struct GNUNET_EXIT_UdpServiceMessage *msg; 2837 char buf[pktlen] GNUNET_ALIGN;
3048 uint16_t pkt_len = ntohs (message->size); 2838 struct GNUNET_TUN_TcpHeader *mtcp;
2839 struct GNUNET_EXIT_TcpDataMessage *tdm;
2840 struct GNUNET_MQ_Envelope *env;
2841 size_t mlen;
3049 2842
3050 if (NULL == state->specifics.tcp_udp.serv)
3051 { 2843 {
3052 GNUNET_break_op (0); 2844 char sbuf[INET6_ADDRSTRLEN];
3053 return GNUNET_SYSERR; 2845 char dbuf[INET6_ADDRSTRLEN];
2846 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2847 "Received TCP packet with %u bytes going from %s:%u to %s:%u\n",
2848 (unsigned int) (pktlen - sizeof (struct GNUNET_TUN_TcpHeader)),
2849 inet_ntop (af,
2850 source_ip,
2851 sbuf, sizeof (sbuf)),
2852 (unsigned int) ntohs (tcp->source_port),
2853 inet_ntop (af,
2854 destination_ip,
2855 dbuf, sizeof (dbuf)),
2856 (unsigned int) ntohs (tcp->destination_port));
3054 } 2857 }
2858 if (pktlen < sizeof (struct GNUNET_TUN_TcpHeader))
2859 {
2860 /* blame kernel */
2861 GNUNET_break (0);
2862 return;
2863 }
2864 state = get_redirect_state (af,
2865 IPPROTO_TCP,
2866 source_ip,
2867 ntohs (tcp->source_port),
2868 destination_ip,
2869 ntohs (tcp->destination_port),
2870 NULL);
2871 if (NULL == state)
2872 {
2873 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2874 _("TCP Packet dropped, have no matching connection information\n"));
2875
2876 return;
2877 }
2878 /* mug port numbers and crc to avoid information leakage;
2879 sender will need to lookup the correct values anyway */
2880 GNUNET_memcpy (buf, tcp, pktlen);
2881 mtcp = (struct GNUNET_TUN_TcpHeader *) buf;
2882 mtcp->source_port = 0;
2883 mtcp->destination_port = 0;
2884 mtcp->crc = 0;
2885
2886 mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) + (pktlen - sizeof (struct GNUNET_TUN_TcpHeader));
2887 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2888 {
2889 GNUNET_break (0);
2890 return;
2891 }
2892 env = GNUNET_MQ_msg_extra (tdm,
2893 pktlen - sizeof (struct GNUNET_TUN_TcpHeader),
2894 GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN);
2895 tdm->reserved = htonl (0);
2896 GNUNET_memcpy (&tdm->tcp_header,
2897 buf,
2898 pktlen);
2899 send_packet_to_cadet_channel (state,
2900 env);
2901}
2902
2903
2904/**
2905 * Receive packets from the helper-process
2906 *
2907 * @param cls unused
2908 * @param client unsued
2909 * @param message message received from helper
2910 */
2911static int
2912message_token (void *cls GNUNET_UNUSED,
2913 void *client GNUNET_UNUSED,
2914 const struct GNUNET_MessageHeader *message)
2915{
2916 const struct GNUNET_TUN_Layer2PacketHeader *pkt_tun;
2917 size_t size;
2918
2919 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2920 "Got %u-byte message of type %u from gnunet-helper-exit\n",
2921 ntohs (message->size),
2922 ntohs (message->type));
3055 GNUNET_STATISTICS_update (stats, 2923 GNUNET_STATISTICS_update (stats,
3056 gettext_noop ("# Bytes received from CADET"), 2924 gettext_noop ("# Packets received from TUN"),
3057 pkt_len, GNUNET_NO);
3058 GNUNET_STATISTICS_update (stats,
3059 gettext_noop ("# UDP service requests received via cadet"),
3060 1, GNUNET_NO); 2925 1, GNUNET_NO);
3061 /* check that we got at least a valid header */ 2926 if (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER)
3062 if (pkt_len < sizeof (struct GNUNET_EXIT_UdpServiceMessage))
3063 { 2927 {
3064 GNUNET_break_op (0); 2928 GNUNET_break (0);
3065 return GNUNET_SYSERR; 2929 return GNUNET_OK;
3066 } 2930 }
3067 msg = (const struct GNUNET_EXIT_UdpServiceMessage*) message; 2931 size = ntohs (message->size);
3068 pkt_len -= sizeof (struct GNUNET_EXIT_UdpServiceMessage); 2932 if (size < sizeof (struct GNUNET_TUN_Layer2PacketHeader) + sizeof (struct GNUNET_MessageHeader))
3069 LOG (GNUNET_ERROR_TYPE_DEBUG, 2933 {
3070 "Received data from %s for forwarding to UDP service %s on port %u\n", 2934 GNUNET_break (0);
3071 GNUNET_i2s (&state->peer), 2935 return GNUNET_OK;
3072 GNUNET_h2s (&state->specifics.tcp_udp.serv->descriptor), 2936 }
3073 (unsigned int) ntohs (msg->destination_port)); 2937 GNUNET_STATISTICS_update (stats,
3074 setup_state_record (state); 2938 gettext_noop ("# Bytes received from TUN"),
3075 if (0 != ntohs (msg->source_port)) 2939 size, GNUNET_NO);
3076 state->specifics.tcp_udp.ri.local_address.port = msg->source_port; 2940 pkt_tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
3077 send_udp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address, 2941 size -= sizeof (struct GNUNET_TUN_Layer2PacketHeader) + sizeof (struct GNUNET_MessageHeader);
3078 &state->specifics.tcp_udp.ri.local_address, 2942 switch (ntohs (pkt_tun->proto))
3079 &msg[1], 2943 {
3080 pkt_len); 2944 case ETH_P_IPV4:
3081 GNUNET_CADET_receive_done (channel); 2945 {
3082 return GNUNET_YES; 2946 const struct GNUNET_TUN_IPv4Header *pkt4;
2947
2948 if (size < sizeof (struct GNUNET_TUN_IPv4Header))
2949 {
2950 /* Kernel to blame? */
2951 GNUNET_break (0);
2952 return GNUNET_OK;
2953 }
2954 pkt4 = (const struct GNUNET_TUN_IPv4Header *) &pkt_tun[1];
2955 if (size != ntohs (pkt4->total_length))
2956 {
2957 /* Kernel to blame? */
2958 GNUNET_break (0);
2959 return GNUNET_OK;
2960 }
2961 if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
2962 {
2963 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2964 _("IPv4 packet options received. Ignored.\n"));
2965 return GNUNET_OK;
2966 }
2967
2968 size -= sizeof (struct GNUNET_TUN_IPv4Header);
2969 switch (pkt4->protocol)
2970 {
2971 case IPPROTO_UDP:
2972 udp_from_helper ((const struct GNUNET_TUN_UdpHeader *) &pkt4[1], size,
2973 AF_INET,
2974 &pkt4->destination_address,
2975 &pkt4->source_address);
2976 break;
2977 case IPPROTO_TCP:
2978 tcp_from_helper ((const struct GNUNET_TUN_TcpHeader *) &pkt4[1], size,
2979 AF_INET,
2980 &pkt4->destination_address,
2981 &pkt4->source_address);
2982 break;
2983 case IPPROTO_ICMP:
2984 icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt4[1], size,
2985 AF_INET,
2986 &pkt4->destination_address,
2987 &pkt4->source_address);
2988 break;
2989 default:
2990 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2991 _("IPv4 packet with unsupported next header %u received. Ignored.\n"),
2992 (int) pkt4->protocol);
2993 return GNUNET_OK;
2994 }
2995 }
2996 break;
2997 case ETH_P_IPV6:
2998 {
2999 const struct GNUNET_TUN_IPv6Header *pkt6;
3000
3001 if (size < sizeof (struct GNUNET_TUN_IPv6Header))
3002 {
3003 /* Kernel to blame? */
3004 GNUNET_break (0);
3005 return GNUNET_OK;
3006 }
3007 pkt6 = (struct GNUNET_TUN_IPv6Header *) &pkt_tun[1];
3008 if (size != ntohs (pkt6->payload_length) + sizeof (struct GNUNET_TUN_IPv6Header))
3009 {
3010 /* Kernel to blame? */
3011 GNUNET_break (0);
3012 return GNUNET_OK;
3013 }
3014 size -= sizeof (struct GNUNET_TUN_IPv6Header);
3015 switch (pkt6->next_header)
3016 {
3017 case IPPROTO_UDP:
3018 udp_from_helper ((const struct GNUNET_TUN_UdpHeader *) &pkt6[1], size,
3019 AF_INET6,
3020 &pkt6->destination_address,
3021 &pkt6->source_address);
3022 break;
3023 case IPPROTO_TCP:
3024 tcp_from_helper ((const struct GNUNET_TUN_TcpHeader *) &pkt6[1], size,
3025 AF_INET6,
3026 &pkt6->destination_address,
3027 &pkt6->source_address);
3028 break;
3029 case IPPROTO_ICMPV6:
3030 icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt6[1], size,
3031 AF_INET6,
3032 &pkt6->destination_address,
3033 &pkt6->source_address);
3034 break;
3035 default:
3036 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3037 _("IPv6 packet with unsupported next header %d received. Ignored.\n"),
3038 pkt6->next_header);
3039 return GNUNET_OK;
3040 }
3041 }
3042 break;
3043 default:
3044 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3045 _("Packet from unknown protocol %u received. Ignored.\n"),
3046 ntohs (pkt_tun->proto));
3047 break;
3048 }
3049 return GNUNET_OK;
3083} 3050}
3084 3051
3085 3052
@@ -3089,16 +3056,12 @@ receive_udp_service (void *cls,
3089 * @param cls closure 3056 * @param cls closure
3090 * @param channel new handle to the channel 3057 * @param channel new handle to the channel
3091 * @param initiator peer that started the channel 3058 * @param initiator peer that started the channel
3092 * @param port destination port
3093 * @param options channel options flags
3094 * @return initial channel context for the channel 3059 * @return initial channel context for the channel
3095 */ 3060 */
3096static void * 3061static void *
3097new_channel (void *cls, 3062new_channel (void *cls,
3098 struct GNUNET_CADET_Channel *channel, 3063 struct GNUNET_CADET_Channel *channel,
3099 const struct GNUNET_PeerIdentity *initiator, 3064 const struct GNUNET_PeerIdentity *initiator)
3100 const struct GNUNET_HashCode *port,
3101 enum GNUNET_CADET_ChannelOption options)
3102{ 3065{
3103 struct ChannelState *s = GNUNET_new (struct ChannelState); 3066 struct ChannelState *s = GNUNET_new (struct ChannelState);
3104 3067
@@ -3106,7 +3069,8 @@ new_channel (void *cls,
3106 s->peer = *initiator; 3069 s->peer = *initiator;
3107 GNUNET_STATISTICS_update (stats, 3070 GNUNET_STATISTICS_update (stats,
3108 gettext_noop ("# Inbound CADET channels created"), 3071 gettext_noop ("# Inbound CADET channels created"),
3109 1, GNUNET_NO); 3072 1,
3073 GNUNET_NO);
3110 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3074 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3111 "Received inbound channel from `%s'\n", 3075 "Received inbound channel from `%s'\n",
3112 GNUNET_i2s (initiator)); 3076 GNUNET_i2s (initiator));
@@ -3116,64 +3080,6 @@ new_channel (void *cls,
3116 3080
3117 3081
3118/** 3082/**
3119 * Function called by cadet whenever an inbound channel is destroyed.
3120 * Should clean up any associated state.
3121 *
3122 * @param cls closure (set from #GNUNET_CADET_connect)
3123 * @param channel connection to the other end (henceforth invalid)
3124 * @param channel_ctx place where local state associated
3125 * with the channel is stored
3126 */
3127static void
3128clean_channel (void *cls,
3129 const struct GNUNET_CADET_Channel *channel,
3130 void *channel_ctx)
3131{
3132 struct ChannelState *s = channel_ctx;
3133 struct ChannelMessageQueue *tnq;
3134
3135 LOG (GNUNET_ERROR_TYPE_DEBUG,
3136 "Channel destroyed\n");
3137 if (GNUNET_SYSERR == s->is_dns)
3138 {
3139 GNUNET_free (s);
3140 return;
3141 }
3142 if (GNUNET_YES == s->is_dns)
3143 {
3144 if (channels[s->specifics.dns.my_id] == s)
3145 channels[s->specifics.dns.my_id] = NULL;
3146 GNUNET_free_non_null (s->specifics.dns.reply);
3147 }
3148 else
3149 {
3150 while (NULL != (tnq = s->specifics.tcp_udp.head))
3151 {
3152 GNUNET_CONTAINER_DLL_remove (s->specifics.tcp_udp.head,
3153 s->specifics.tcp_udp.tail,
3154 tnq);
3155 GNUNET_free (tnq);
3156 }
3157 if (NULL != s->specifics.tcp_udp.heap_node)
3158 {
3159 GNUNET_assert (GNUNET_YES ==
3160 GNUNET_CONTAINER_multihashmap_remove (connections_map,
3161 &s->specifics.tcp_udp.state_key,
3162 s));
3163 GNUNET_CONTAINER_heap_remove_node (s->specifics.tcp_udp.heap_node);
3164 s->specifics.tcp_udp.heap_node = NULL;
3165 }
3166 }
3167 if (NULL != s->th)
3168 {
3169 GNUNET_CADET_notify_transmit_ready_cancel (s->th);
3170 s->th = NULL;
3171 }
3172 GNUNET_free (s);
3173}
3174
3175
3176/**
3177 * Function that frees everything from a hashmap 3083 * Function that frees everything from a hashmap
3178 * 3084 *
3179 * @param cls unused 3085 * @param cls unused
@@ -3241,6 +3147,21 @@ cleanup (void *cls)
3241 NULL); 3147 NULL);
3242 GNUNET_CONTAINER_multihashmap_destroy (services); 3148 GNUNET_CONTAINER_multihashmap_destroy (services);
3243 } 3149 }
3150 if (NULL != dns_port)
3151 {
3152 GNUNET_CADET_close_port (dns_port);
3153 dns_port = NULL;
3154 }
3155 if (NULL != cadet_port4)
3156 {
3157 GNUNET_CADET_close_port (cadet_port4);
3158 cadet_port4 = NULL;
3159 }
3160 if (NULL != cadet_port6)
3161 {
3162 GNUNET_CADET_close_port (cadet_port6);
3163 cadet_port6 = NULL;
3164 }
3244 if (NULL != cadet_handle) 3165 if (NULL != cadet_handle)
3245 { 3166 {
3246 GNUNET_CADET_disconnect (cadet_handle); 3167 GNUNET_CADET_disconnect (cadet_handle);
@@ -3286,7 +3207,8 @@ cleanup (void *cls)
3286 } 3207 }
3287 if (NULL != stats) 3208 if (NULL != stats)
3288 { 3209 {
3289 GNUNET_STATISTICS_destroy (stats, GNUNET_NO); 3210 GNUNET_STATISTICS_destroy (stats,
3211 GNUNET_NO);
3290 stats = NULL; 3212 stats = NULL;
3291 } 3213 }
3292 for (i=0;i<8;i++) 3214 for (i=0;i<8;i++)
@@ -3614,6 +3536,13 @@ parse_ip_options ()
3614static void 3536static void
3615advertise_dns_exit () 3537advertise_dns_exit ()
3616{ 3538{
3539 struct GNUNET_MQ_MessageHandler handlers[] = {
3540 GNUNET_MQ_hd_var_size (dns_request,
3541 GNUNET_MESSAGE_TYPE_VPN_DNS_TO_INTERNET,
3542 struct DnsResponseMessage,
3543 NULL),
3544 GNUNET_MQ_handler_end ()
3545 };
3617 char *dns_exit; 3546 char *dns_exit;
3618 struct GNUNET_HashCode port; 3547 struct GNUNET_HashCode port;
3619 struct in_addr dns_exit4; 3548 struct in_addr dns_exit4;
@@ -3650,10 +3579,13 @@ advertise_dns_exit ()
3650 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3579 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3651 "Opening CADET port %s for DNS exit service\n", 3580 "Opening CADET port %s for DNS exit service\n",
3652 GNUNET_h2s (&port)); 3581 GNUNET_h2s (&port));
3653 GNUNET_CADET_open_port (cadet_handle, 3582 dns_port = GNUNET_CADET_open_porT (cadet_handle,
3654 &port, 3583 &port,
3655 &new_channel, 3584 &new_channel,
3656 NULL); 3585 NULL,
3586 NULL,
3587 &clean_channel,
3588 handlers);
3657 /* advertise exit */ 3589 /* advertise exit */
3658 dht = GNUNET_DHT_connect (cfg, 3590 dht = GNUNET_DHT_connect (cfg,
3659 1); 3591 1);
@@ -3833,16 +3765,24 @@ run (void *cls,
3833 const char *cfgfile, 3765 const char *cfgfile,
3834 const struct GNUNET_CONFIGURATION_Handle *cfg_) 3766 const struct GNUNET_CONFIGURATION_Handle *cfg_)
3835{ 3767{
3836 static struct GNUNET_CADET_MessageHandler handlers[] = { 3768 struct GNUNET_MQ_MessageHandler handlers[] = {
3837 {&receive_icmp_service, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE, 0}, 3769 GNUNET_MQ_hd_var_size (icmp_remote,
3838 {&receive_icmp_remote, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET, 0}, 3770 GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET,
3839 {&receive_udp_service, GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE, 0}, 3771 struct GNUNET_EXIT_IcmpInternetMessage,
3840 {&receive_udp_remote, GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET, 0}, 3772 NULL),
3841 {&receive_tcp_service, GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START, 0}, 3773 GNUNET_MQ_hd_var_size (udp_remote,
3842 {&receive_tcp_remote, GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START, 0}, 3774 GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET,
3843 {&receive_tcp_data, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT, 0}, 3775 struct GNUNET_EXIT_UdpInternetMessage,
3844 {&receive_dns_request, GNUNET_MESSAGE_TYPE_VPN_DNS_TO_INTERNET, 0}, 3776 NULL),
3845 {NULL, 0, 0} 3777 GNUNET_MQ_hd_var_size (tcp_remote,
3778 GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START,
3779 struct GNUNET_EXIT_TcpInternetStartMessage,
3780 NULL),
3781 GNUNET_MQ_hd_var_size (tcp_data,
3782 GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT,
3783 struct GNUNET_EXIT_TcpDataMessage,
3784 NULL),
3785 GNUNET_MQ_handler_end ()
3846 }; 3786 };
3847 struct GNUNET_HashCode port; 3787 struct GNUNET_HashCode port;
3848 char *policy; 3788 char *policy;
@@ -3889,10 +3829,7 @@ run (void *cls,
3889 NULL); 3829 NULL);
3890 stats = GNUNET_STATISTICS_create ("exit", 3830 stats = GNUNET_STATISTICS_create ("exit",
3891 cfg); 3831 cfg);
3892 cadet_handle = GNUNET_CADET_connect (cfg, 3832 cadet_handle = GNUNET_CADET_connecT (cfg);
3893 NULL,
3894 &clean_channel,
3895 handlers);
3896 if (NULL == cadet_handle) 3833 if (NULL == cadet_handle)
3897 { 3834 {
3898 GNUNET_SCHEDULER_shutdown (); 3835 GNUNET_SCHEDULER_shutdown ();
@@ -3925,10 +3862,13 @@ run (void *cls,
3925 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3862 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3926 "Opening CADET port %s for IPv4 gateway service\n", 3863 "Opening CADET port %s for IPv4 gateway service\n",
3927 GNUNET_h2s (&port)); 3864 GNUNET_h2s (&port));
3928 GNUNET_CADET_open_port (cadet_handle, 3865 cadet_port4 = GNUNET_CADET_open_porT (cadet_handle,
3929 &port, 3866 &port,
3930 &new_channel, 3867 &new_channel,
3931 NULL); 3868 NULL,
3869 NULL,
3870 &clean_channel,
3871 handlers);
3932 policy = NULL; 3872 policy = NULL;
3933 if (GNUNET_OK != 3873 if (GNUNET_OK !=
3934 GNUNET_CONFIGURATION_get_value_string (cfg, 3874 GNUNET_CONFIGURATION_get_value_string (cfg,
@@ -3962,10 +3902,13 @@ run (void *cls,
3962 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3902 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3963 "Opening CADET port %s for IPv6 gateway service\n", 3903 "Opening CADET port %s for IPv6 gateway service\n",
3964 GNUNET_h2s (&port)); 3904 GNUNET_h2s (&port));
3965 GNUNET_CADET_open_port (cadet_handle, 3905 cadet_port6 = GNUNET_CADET_open_porT (cadet_handle,
3966 &port, 3906 &port,
3967 &new_channel, 3907 &new_channel,
3968 NULL); 3908 NULL,
3909 NULL,
3910 &clean_channel,
3911 handlers);
3969 policy = NULL; 3912 policy = NULL;
3970 if (GNUNET_OK != 3913 if (GNUNET_OK !=
3971 GNUNET_CONFIGURATION_get_value_string (cfg, 3914 GNUNET_CONFIGURATION_get_value_string (cfg,