aboutsummaryrefslogtreecommitdiff
path: root/src/service/exit/gnunet-daemon-exit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/service/exit/gnunet-daemon-exit.c')
-rw-r--r--src/service/exit/gnunet-daemon-exit.c4121
1 files changed, 4121 insertions, 0 deletions
diff --git a/src/service/exit/gnunet-daemon-exit.c b/src/service/exit/gnunet-daemon-exit.c
new file mode 100644
index 000000000..eb2380439
--- /dev/null
+++ b/src/service/exit/gnunet-daemon-exit.c
@@ -0,0 +1,4121 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2010-2013, 2017 Christian Grothoff
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file exit/gnunet-daemon-exit.c
23 * @brief tool to allow IP traffic exit from the GNUnet cadet to the Internet
24 * @author Philipp Toelke
25 * @author Christian Grothoff
26 *
27 * TODO:
28 * - test
29 *
30 * Design:
31 * - which code should advertise services? the service model is right
32 * now a bit odd, especially as this code DOES the exit and knows
33 * the DNS "name", but OTOH this is clearly NOT the place to advertise
34 * the service's existence; maybe the daemon should turn into a
35 * service with an API to add local-exit services dynamically?
36 */
37#include "platform.h"
38#include "gnunet_util_lib.h"
39#include "gnunet_protocols.h"
40#include "gnunet_applications.h"
41#include "gnunet_dht_service.h"
42#include "gnunet_cadet_service.h"
43#include "gnunet_statistics_service.h"
44#include "gnunet_constants.h"
45#include "gnunet_signatures.h"
46#include "gnunet_regex_service.h"
47#include "exit.h"
48#include "block_dns.h"
49
50
51/**
52 * Maximum path compression length for cadet regex announcing for IPv4 address
53 * based regex.
54 */
55#define REGEX_MAX_PATH_LEN_IPV4 4
56
57/**
58 * Maximum path compression length for cadet regex announcing for IPv6 address
59 * based regex.
60 */
61#define REGEX_MAX_PATH_LEN_IPV6 8
62
63/**
64 * How frequently do we re-announce the regex for the exit?
65 */
66#define REGEX_REFRESH_FREQUENCY GNUNET_TIME_relative_multiply ( \
67 GNUNET_TIME_UNIT_MINUTES, 30)
68
69/**
70 * How frequently do we re-announce the DNS exit in the DHT?
71 */
72#define DHT_PUT_FREQUENCY GNUNET_TIME_relative_multiply ( \
73 GNUNET_TIME_UNIT_MINUTES, 15)
74
75/**
76 * How long do we typically sign the DNS exit advertisement for?
77 */
78#define DNS_ADVERTISEMENT_TIMEOUT GNUNET_TIME_relative_multiply ( \
79 GNUNET_TIME_UNIT_HOURS, 3)
80
81
82/**
83 * Generic logging shorthand
84 */
85#define LOG(kind, ...) \
86 GNUNET_log_from (kind, "exit", __VA_ARGS__);
87
88
89/**
90 * Information about an address.
91 */
92struct SocketAddress
93{
94 /**
95 * AF_INET or AF_INET6.
96 */
97 int af;
98
99 /**
100 * Remote address information.
101 */
102 union
103 {
104 /**
105 * Address, if af is AF_INET.
106 */
107 struct in_addr ipv4;
108
109 /**
110 * Address, if af is AF_INET6.
111 */
112 struct in6_addr ipv6;
113 } address;
114
115 /**
116 * IPPROTO_TCP or IPPROTO_UDP;
117 */
118 uint8_t proto;
119
120 /**
121 * Remote port, in host byte order!
122 */
123 uint16_t port;
124};
125
126
127/**
128 * This struct is saved into the services-hashmap to represent
129 * a service this peer is specifically offering an exit for
130 * (for a specific domain name).
131 */
132struct LocalService
133{
134 /**
135 * Remote address to use for the service.
136 */
137 struct SocketAddress address;
138
139 /**
140 * Descriptor for the service (CADET port).
141 */
142 struct GNUNET_HashCode descriptor;
143
144 /**
145 * DNS name of the service.
146 */
147 char *name;
148
149 /**
150 * Open port with CADET.
151 */
152 struct GNUNET_CADET_Port *port;
153
154 /**
155 * #GNUNET_YES if this is a UDP service, otherwise TCP.
156 */
157 int16_t is_udp;
158};
159
160
161/**
162 * Information we use to track a connection (the classical 6-tuple of
163 * IP-version, protocol, source-IP, destination-IP, source-port and
164 * destinatin-port.
165 */
166struct RedirectInformation
167{
168 /**
169 * Address information for the other party (equivalent of the
170 * arguments one would give to "connect").
171 */
172 struct SocketAddress remote_address;
173
174 /**
175 * Address information we used locally (AF and proto must match
176 * "remote_address"). Equivalent of the arguments one would give to
177 * "bind".
178 */
179 struct SocketAddress local_address;
180
181 /*
182 Note 1: additional information might be added here in the
183 future to support protocols that require special handling,
184 such as ftp/tftp
185
186 Note 2: we might also sometimes not match on all components
187 of the tuple, to support protocols where things do not always
188 fully map.
189 */
190};
191
192
193/**
194 * This struct is saved into #connections_map to allow finding the
195 * right channel given an IP packet from TUN. It is also associated
196 * with the channel's closure so we can find it again for the next
197 * message from the channel.
198 */
199struct ChannelState
200{
201 /**
202 * Cadet channel that is used for this connection.
203 */
204 struct GNUNET_CADET_Channel *channel;
205
206 /**
207 * Who is the other end of this channel.
208 * FIXME is this needed? Only used for debugging messages
209 */
210 struct GNUNET_PeerIdentity peer;
211
212 /**
213 * #GNUNET_NO if this is a channel for TCP/UDP,
214 * #GNUNET_YES if this is a channel for DNS,
215 * #GNUNET_SYSERR if the channel is not yet initialized.
216 */
217 int is_dns;
218
219 union
220 {
221 struct
222 {
223 /**
224 * Heap node for this state in the connections_heap.
225 */
226 struct GNUNET_CONTAINER_HeapNode *heap_node;
227
228 /**
229 * Key this state has in the #connections_map.
230 */
231 struct GNUNET_HashCode state_key;
232
233 /**
234 * Associated service record, or NULL for no service.
235 */
236 struct LocalService *serv;
237
238 /**
239 * Primary redirection information for this connection.
240 */
241 struct RedirectInformation ri;
242 } tcp_udp;
243
244 struct
245 {
246 /**
247 * Socket we are using to transmit this request (must match if we receive
248 * a response).
249 */
250 struct GNUNET_DNSSTUB_RequestSocket *rs;
251
252 /**
253 * Original DNS request ID as used by the client.
254 */
255 uint16_t original_id;
256
257 /**
258 * DNS request ID that we used for forwarding.
259 */
260 uint16_t my_id;
261 } dns;
262 } specifics;
263};
264
265
266/**
267 * Return value from 'main'.
268 */
269static int global_ret;
270
271/**
272 * Handle to our regex announcement for IPv4.
273 */
274static struct GNUNET_REGEX_Announcement *regex4;
275
276/**
277 * Handle to our regex announcement for IPv4.
278 */
279static struct GNUNET_REGEX_Announcement *regex6;
280
281/**
282 * The handle to the configuration used throughout the process
283 */
284static const struct GNUNET_CONFIGURATION_Handle *cfg;
285
286/**
287 * The handle to the helper
288 */
289static struct GNUNET_HELPER_Handle *helper_handle;
290
291/**
292 * Arguments to the exit helper.
293 */
294static char *exit_argv[8];
295
296/**
297 * IPv6 address of our TUN interface.
298 */
299static struct in6_addr exit_ipv6addr;
300
301/**
302 * IPv6 prefix (0..127) from configuration file.
303 */
304static unsigned long long ipv6prefix;
305
306/**
307 * IPv4 address of our TUN interface.
308 */
309static struct in_addr exit_ipv4addr;
310
311/**
312 * IPv4 netmask of our TUN interface.
313 */
314static struct in_addr exit_ipv4mask;
315
316/**
317 * Statistics.
318 */
319static struct GNUNET_STATISTICS_Handle *stats;
320
321/**
322 * The handle to cadet
323 */
324static struct GNUNET_CADET_Handle *cadet_handle;
325
326/**
327 * This hashmaps contains the mapping from peer, service-descriptor,
328 * source-port and destination-port to a struct ChannelState
329 */
330static struct GNUNET_CONTAINER_MultiHashMap *connections_map;
331
332/**
333 * Heap so we can quickly find "old" connections.
334 */
335static struct GNUNET_CONTAINER_Heap *connections_heap;
336
337/**
338 * If there are at least this many connections, old ones will be removed
339 */
340static unsigned long long max_connections;
341
342/**
343 * This hashmaps saves interesting things about the configured services
344 */
345static struct GNUNET_CONTAINER_MultiHashMap *services;
346
347/**
348 * Array of all open DNS requests from channels.
349 */
350static struct ChannelState *channels[UINT16_MAX + 1];
351
352/**
353 * Handle to the DNS Stub resolver.
354 */
355static struct GNUNET_DNSSTUB_Context *dnsstub;
356
357/**
358 * Handle for ongoing DHT PUT operations to advertise exit service.
359 */
360static struct GNUNET_DHT_PutHandle *dht_put;
361
362/**
363 * Handle to the DHT.
364 */
365static struct GNUNET_DHT_Handle *dht;
366
367/**
368 * Task for doing DHT PUTs to advertise exit service.
369 */
370static struct GNUNET_SCHEDULER_Task *dht_task;
371
372/**
373 * Advertisement message we put into the DHT to advertise us
374 * as a DNS exit.
375 */
376static struct GNUNET_DNS_Advertisement dns_advertisement;
377
378/**
379 * Key we store the DNS advertismenet under.
380 */
381static struct GNUNET_HashCode dht_put_key;
382
383/**
384 * Private key for this peer.
385 */
386static struct GNUNET_CRYPTO_EddsaPrivateKey *peer_key;
387
388/**
389 * Port for DNS exit.
390 */
391static struct GNUNET_CADET_Port *dns_port;
392
393/**
394 * Port for IPv4 exit.
395 */
396static struct GNUNET_CADET_Port *cadet_port4;
397
398/**
399 * Port for IPv6 exit.
400 */
401static struct GNUNET_CADET_Port *cadet_port6;
402
403/**
404 * Are we an IPv4-exit?
405 */
406static int ipv4_exit;
407
408/**
409 * Are we an IPv6-exit?
410 */
411static int ipv6_exit;
412
413/**
414 * Do we support IPv4 at all on the TUN interface?
415 */
416static int ipv4_enabled;
417
418/**
419 * Do we support IPv6 at all on the TUN interface?
420 */
421static int ipv6_enabled;
422
423
424GNUNET_NETWORK_STRUCT_BEGIN
425
426/**
427 * Message with a DNS response.
428 */
429struct DnsResponseMessage
430{
431 /**
432 * GNUnet header, of type #GNUNET_MESSAGE_TYPE_VPN_DNS_FROM_INTERNET
433 */
434 struct GNUNET_MessageHeader header;
435
436 /**
437 * DNS header.
438 */
439 struct GNUNET_TUN_DnsHeader dns;
440
441 /* Followed by more DNS payload */
442};
443
444GNUNET_NETWORK_STRUCT_END
445
446
447/**
448 * Callback called from DNSSTUB resolver when a resolution
449 * succeeded.
450 *
451 * @param cls NULL
452 * @param dns the response itself
453 * @param r number of bytes in @a dns
454 */
455static void
456process_dns_result (void *cls,
457 const struct GNUNET_TUN_DnsHeader *dns,
458 size_t r)
459{
460 struct ChannelState *ts;
461 struct GNUNET_MQ_Envelope *env;
462 struct DnsResponseMessage *resp;
463
464 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
465 "Processing DNS result from stub resolver\n");
466 GNUNET_assert (NULL == cls);
467 if (NULL == dns)
468 return;
469 /* Handle case that this is a reply to a request from a CADET DNS channel */
470 ts = channels[dns->id];
471 if (NULL == ts)
472 return;
473 LOG (GNUNET_ERROR_TYPE_DEBUG,
474 "Got a response from the stub resolver for DNS request received via CADET!\n");
475 channels[dns->id] = NULL;
476 env = GNUNET_MQ_msg_extra (resp,
477 r - sizeof(struct GNUNET_TUN_DnsHeader),
478 GNUNET_MESSAGE_TYPE_VPN_DNS_FROM_INTERNET);
479 GNUNET_memcpy (&resp->dns,
480 dns,
481 r);
482 resp->dns.id = ts->specifics.dns.original_id;
483 GNUNET_MQ_send (GNUNET_CADET_get_mq (ts->channel),
484 env);
485}
486
487
488/**
489 * Check a request via cadet to perform a DNS query.
490 *
491 * @param cls our `struct ChannelState *`
492 * @param msg the actual message
493 * @return #GNUNET_OK to keep the connection open,
494 * #GNUNET_SYSERR to close it (signal serious error)
495 */
496static int
497check_dns_request (void *cls,
498 const struct DnsResponseMessage *msg)
499{
500 struct ChannelState *ts = cls;
501
502 if (NULL == dnsstub)
503 {
504 GNUNET_break (0);
505 return GNUNET_SYSERR;
506 }
507 if (GNUNET_NO == ts->is_dns)
508 {
509 GNUNET_break_op (0);
510 return GNUNET_SYSERR;
511 }
512 return GNUNET_OK;
513}
514
515
516/**
517 * Process a request via cadet to perform a DNS query.
518 *
519 * @param cls our `struct ChannelState *`
520 * @param msg the actual message
521 */
522static void
523handle_dns_request (void *cls,
524 const struct DnsResponseMessage *msg)
525{
526 struct ChannelState *ts = cls;
527 size_t mlen = ntohs (msg->header.size);
528 size_t dlen = mlen - sizeof(struct GNUNET_MessageHeader);
529 char buf[dlen] GNUNET_ALIGN;
530 struct GNUNET_TUN_DnsHeader *dns_out;
531
532 if (GNUNET_SYSERR == ts->is_dns)
533 {
534 /* channel is DNS from now on */
535 ts->is_dns = GNUNET_YES;
536 }
537 ts->specifics.dns.original_id = msg->dns.id;
538 if (channels[ts->specifics.dns.my_id] == ts)
539 channels[ts->specifics.dns.my_id] = NULL;
540 ts->specifics.dns.my_id = (uint16_t) GNUNET_CRYPTO_random_u32 (
541 GNUNET_CRYPTO_QUALITY_WEAK,
542 UINT16_MAX
543 + 1);
544 channels[ts->specifics.dns.my_id] = ts;
545 GNUNET_memcpy (buf,
546 &msg->dns,
547 dlen);
548 dns_out = (struct GNUNET_TUN_DnsHeader *) buf;
549 dns_out->id = ts->specifics.dns.my_id;
550 ts->specifics.dns.rs = GNUNET_DNSSTUB_resolve (dnsstub,
551 buf,
552 dlen,
553 &process_dns_result,
554 NULL);
555 if (NULL == ts->specifics.dns.rs)
556 {
557 GNUNET_break_op (0);
558 return;
559 }
560 GNUNET_CADET_receive_done (ts->channel);
561}
562
563
564/**
565 * Given IP information about a connection, calculate the respective
566 * hash we would use for the #connections_map.
567 *
568 * @param hash resulting hash
569 * @param ri information about the connection
570 */
571static void
572hash_redirect_info (struct GNUNET_HashCode *hash,
573 const struct RedirectInformation *ri)
574{
575 char *off;
576
577 memset (hash,
578 0,
579 sizeof(struct GNUNET_HashCode));
580 /* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash,
581 so we put the IP address in there (and hope for few collisions) */
582 off = (char *) hash;
583 switch (ri->remote_address.af)
584 {
585 case AF_INET:
586 GNUNET_memcpy (off,
587 &ri->remote_address.address.ipv4,
588 sizeof(struct in_addr));
589 off += sizeof(struct in_addr);
590 break;
591
592 case AF_INET6:
593 GNUNET_memcpy (off,
594 &ri->remote_address.address.ipv6,
595 sizeof(struct in6_addr));
596 off += sizeof(struct in_addr);
597 break;
598
599 default:
600 GNUNET_assert (0);
601 }
602 GNUNET_memcpy (off,
603 &ri->remote_address.port,
604 sizeof(uint16_t));
605 off += sizeof(uint16_t);
606 switch (ri->local_address.af)
607 {
608 case AF_INET:
609 GNUNET_memcpy (off,
610 &ri->local_address.address.ipv4,
611 sizeof(struct in_addr));
612 off += sizeof(struct in_addr);
613 break;
614
615 case AF_INET6:
616 GNUNET_memcpy (off,
617 &ri->local_address.address.ipv6,
618 sizeof(struct in6_addr));
619 off += sizeof(struct in_addr);
620 break;
621
622 default:
623 GNUNET_assert (0);
624 }
625 GNUNET_memcpy (off,
626 &ri->local_address.port,
627 sizeof(uint16_t));
628 off += sizeof(uint16_t);
629 GNUNET_memcpy (off,
630 &ri->remote_address.proto,
631 sizeof(uint8_t));
632 /* off += sizeof (uint8_t); */
633}
634
635
636/**
637 * Get our connection tracking state. Warns if it does not exists,
638 * refreshes the timestamp if it does exist.
639 *
640 * @param af address family
641 * @param protocol IPPROTO_UDP or IPPROTO_TCP
642 * @param destination_ip target IP
643 * @param destination_port target port
644 * @param local_ip local IP
645 * @param local_port local port
646 * @param state_key set to hash's state if non-NULL
647 * @return NULL if we have no tracking information for this tuple
648 */
649static struct ChannelState *
650get_redirect_state (int af,
651 int protocol,
652 const void *destination_ip,
653 uint16_t destination_port,
654 const void *local_ip,
655 uint16_t local_port,
656 struct GNUNET_HashCode *state_key)
657{
658 struct RedirectInformation ri;
659 struct GNUNET_HashCode key;
660 struct ChannelState *state;
661
662 if (((af == AF_INET) && (protocol == IPPROTO_ICMP)) ||
663 ((af == AF_INET6) && (protocol == IPPROTO_ICMPV6)))
664 {
665 /* ignore ports */
666 destination_port = 0;
667 local_port = 0;
668 }
669 ri.remote_address.af = af;
670 if (af == AF_INET)
671 ri.remote_address.address.ipv4 = *((struct in_addr*) destination_ip);
672 else
673 ri.remote_address.address.ipv6 = *((struct in6_addr*) destination_ip);
674 ri.remote_address.port = destination_port;
675 ri.remote_address.proto = protocol;
676 ri.local_address.af = af;
677 if (af == AF_INET)
678 ri.local_address.address.ipv4 = *((struct in_addr*) local_ip);
679 else
680 ri.local_address.address.ipv6 = *((struct in6_addr*) local_ip);
681 ri.local_address.port = local_port;
682 ri.local_address.proto = protocol;
683 hash_redirect_info (&key,
684 &ri);
685 if (NULL != state_key)
686 *state_key = key;
687 state = GNUNET_CONTAINER_multihashmap_get (connections_map,
688 &key);
689 if (NULL == state)
690 return NULL;
691 /* Mark this connection as freshly used */
692 if (NULL == state_key)
693 GNUNET_CONTAINER_heap_update_cost (state->specifics.tcp_udp.heap_node,
694 GNUNET_TIME_absolute_get ().abs_value_us);
695 return state;
696}
697
698
699/**
700 * Check a request via cadet to send a request to a TCP service
701 * offered by this system.
702 *
703 * @param cls our `struct ChannelState *`
704 * @param start the actual message
705 * @return #GNUNET_OK to keep the connection open,
706 * #GNUNET_SYSERR to close it (signal serious error)
707 */
708static int
709check_tcp_service (void *cls,
710 const struct GNUNET_EXIT_TcpServiceStartMessage *start)
711{
712 struct ChannelState *state = cls;
713
714 if (NULL == state)
715 {
716 GNUNET_break_op (0);
717 return GNUNET_SYSERR;
718 }
719 if (GNUNET_YES == state->is_dns)
720 {
721 GNUNET_break_op (0);
722 return GNUNET_SYSERR;
723 }
724 if (NULL == state->specifics.tcp_udp.serv)
725 {
726 GNUNET_break_op (0);
727 return GNUNET_SYSERR;
728 }
729 if (NULL != state->specifics.tcp_udp.heap_node)
730 {
731 GNUNET_break_op (0);
732 return GNUNET_SYSERR;
733 }
734 if (start->tcp_header.off * 4 < sizeof(struct GNUNET_TUN_TcpHeader))
735 {
736 GNUNET_break_op (0);
737 return GNUNET_SYSERR;
738 }
739 return GNUNET_OK;
740}
741
742
743/**
744 * Prepare an IPv4 packet for transmission via the TUN interface.
745 * Initializes the IP header and calculates checksums (IP+UDP/TCP).
746 * For UDP, the UDP header will be fully created, whereas for TCP
747 * only the ports and checksum will be filled in. So for TCP,
748 * a skeleton TCP header must be part of the provided payload.
749 *
750 * @param payload payload of the packet (starting with UDP payload or
751 * TCP header, depending on protocol)
752 * @param payload_length number of bytes in @a payload
753 * @param protocol IPPROTO_UDP or IPPROTO_TCP
754 * @param tcp_header skeleton of the TCP header, NULL for UDP
755 * @param src_address source address to use (IP and port)
756 * @param dst_address destination address to use (IP and port)
757 * @param pkt4 where to write the assembled packet; must
758 * contain enough space for the IP header, UDP/TCP header
759 * AND the payload
760 */
761static void
762prepare_ipv4_packet (const void *payload,
763 size_t payload_length,
764 int protocol,
765 const struct GNUNET_TUN_TcpHeader *tcp_header,
766 const struct SocketAddress *src_address,
767 const struct SocketAddress *dst_address,
768 struct GNUNET_TUN_IPv4Header *pkt4)
769{
770 size_t len;
771
772 len = payload_length;
773 switch (protocol)
774 {
775 case IPPROTO_UDP:
776 len += sizeof(struct GNUNET_TUN_UdpHeader);
777 break;
778
779 case IPPROTO_TCP:
780 len += sizeof(struct GNUNET_TUN_TcpHeader);
781 GNUNET_assert (NULL != tcp_header);
782 break;
783
784 default:
785 GNUNET_break (0);
786 return;
787 }
788 if (len + sizeof(struct GNUNET_TUN_IPv4Header) > UINT16_MAX)
789 {
790 GNUNET_break (0);
791 return;
792 }
793
794 GNUNET_TUN_initialize_ipv4_header (pkt4,
795 protocol,
796 len,
797 &src_address->address.ipv4,
798 &dst_address->address.ipv4);
799 switch (protocol)
800 {
801 case IPPROTO_UDP:
802 {
803 struct GNUNET_TUN_UdpHeader *pkt4_udp = (struct
804 GNUNET_TUN_UdpHeader *) &pkt4[1];
805
806 pkt4_udp->source_port = htons (src_address->port);
807 pkt4_udp->destination_port = htons (dst_address->port);
808 pkt4_udp->len = htons ((uint16_t) payload_length);
809 GNUNET_TUN_calculate_udp4_checksum (pkt4,
810 pkt4_udp,
811 payload,
812 payload_length);
813 GNUNET_memcpy (&pkt4_udp[1],
814 payload,
815 payload_length);
816 }
817 break;
818
819 case IPPROTO_TCP:
820 {
821 struct GNUNET_TUN_TcpHeader *pkt4_tcp = (struct
822 GNUNET_TUN_TcpHeader *) &pkt4[1];
823
824 *pkt4_tcp = *tcp_header;
825 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
826 "Sending TCP packet from port %u to port %u\n",
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 }
839 break;
840
841 default:
842 GNUNET_assert (0);
843 }
844}
845
846
847/**
848 * Prepare an IPv6 packet for transmission via the TUN interface.
849 * Initializes the IP header and calculates checksums (IP+UDP/TCP).
850 * For UDP, the UDP header will be fully created, whereas for TCP
851 * only the ports and checksum will be filled in. So for TCP,
852 * a skeleton TCP header must be part of the provided payload.
853 *
854 * @param payload payload of the packet (starting with UDP payload or
855 * TCP header, depending on protocol)
856 * @param payload_length number of bytes in @a payload
857 * @param protocol IPPROTO_UDP or IPPROTO_TCP
858 * @param tcp_header skeleton TCP header data to send, NULL for UDP
859 * @param src_address source address to use (IP and port)
860 * @param dst_address destination address to use (IP and port)
861 * @param pkt6 where to write the assembled packet; must
862 * contain enough space for the IP header, UDP/TCP header
863 * AND the payload
864 */
865static void
866prepare_ipv6_packet (const void *payload,
867 size_t payload_length,
868 int protocol,
869 const struct GNUNET_TUN_TcpHeader *tcp_header,
870 const struct SocketAddress *src_address,
871 const struct SocketAddress *dst_address,
872 struct GNUNET_TUN_IPv6Header *pkt6)
873{
874 size_t len;
875
876 len = payload_length;
877 switch (protocol)
878 {
879 case IPPROTO_UDP:
880 len += sizeof(struct GNUNET_TUN_UdpHeader);
881 break;
882
883 case IPPROTO_TCP:
884 len += sizeof(struct GNUNET_TUN_TcpHeader);
885 break;
886
887 default:
888 GNUNET_break (0);
889 return;
890 }
891 if (len > UINT16_MAX)
892 {
893 GNUNET_break (0);
894 return;
895 }
896
897 GNUNET_TUN_initialize_ipv6_header (pkt6,
898 protocol,
899 len,
900 &src_address->address.ipv6,
901 &dst_address->address.ipv6);
902
903 switch (protocol)
904 {
905 case IPPROTO_UDP:
906 {
907 struct GNUNET_TUN_UdpHeader *pkt6_udp = (struct
908 GNUNET_TUN_UdpHeader *) &pkt6[1];
909
910 pkt6_udp->source_port = htons (src_address->port);
911 pkt6_udp->destination_port = htons (dst_address->port);
912 pkt6_udp->len = htons ((uint16_t) payload_length);
913 GNUNET_TUN_calculate_udp6_checksum (pkt6,
914 pkt6_udp,
915 payload,
916 payload_length);
917 GNUNET_memcpy (&pkt6_udp[1],
918 payload,
919 payload_length);
920 }
921 break;
922
923 case IPPROTO_TCP:
924 {
925 struct GNUNET_TUN_TcpHeader *pkt6_tcp = (struct
926 GNUNET_TUN_TcpHeader *) &pkt6[1];
927
928 /* GNUNET_memcpy first here as some TCP header fields are initialized this way! */
929 *pkt6_tcp = *tcp_header;
930 pkt6_tcp->source_port = htons (src_address->port);
931 pkt6_tcp->destination_port = htons (dst_address->port);
932 GNUNET_TUN_calculate_tcp6_checksum (pkt6,
933 pkt6_tcp,
934 payload,
935 payload_length);
936 GNUNET_memcpy (&pkt6_tcp[1],
937 payload,
938 payload_length);
939 }
940 break;
941
942 default:
943 GNUNET_assert (0);
944 break;
945 }
946}
947
948
949/**
950 * Send a TCP packet via the TUN interface.
951 *
952 * @param destination_address IP and port to use for the TCP packet's destination
953 * @param source_address IP and port to use for the TCP packet's source
954 * @param tcp_header header template to use
955 * @param payload payload of the TCP packet
956 * @param payload_length number of bytes in @a payload
957 */
958static void
959send_tcp_packet_via_tun (const struct SocketAddress *destination_address,
960 const struct SocketAddress *source_address,
961 const struct GNUNET_TUN_TcpHeader *tcp_header,
962 const void *payload,
963 size_t payload_length)
964{
965 size_t len;
966
967 GNUNET_STATISTICS_update (stats,
968 gettext_noop ("# TCP packets sent via TUN"),
969 1,
970 GNUNET_NO);
971 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
972 "Sending packet with %u bytes TCP payload via TUN\n",
973 (unsigned int) payload_length);
974 len = sizeof(struct GNUNET_MessageHeader) + sizeof(struct
975 GNUNET_TUN_Layer2PacketHeader);
976 switch (source_address->af)
977 {
978 case AF_INET:
979 len += sizeof(struct GNUNET_TUN_IPv4Header);
980 break;
981
982 case AF_INET6:
983 len += sizeof(struct GNUNET_TUN_IPv6Header);
984 break;
985
986 default:
987 GNUNET_break (0);
988 return;
989 }
990 len += sizeof(struct GNUNET_TUN_TcpHeader);
991 len += payload_length;
992 if (len >= GNUNET_MAX_MESSAGE_SIZE)
993 {
994 GNUNET_break (0);
995 return;
996 }
997 {
998 char buf[len] GNUNET_ALIGN;
999 struct GNUNET_MessageHeader *hdr;
1000 struct GNUNET_TUN_Layer2PacketHeader *tun;
1001
1002 hdr = (struct GNUNET_MessageHeader *) buf;
1003 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1004 hdr->size = htons (len);
1005 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
1006 tun->flags = htons (0);
1007 switch (source_address->af)
1008 {
1009 case AF_INET:
1010 {
1011 struct GNUNET_TUN_IPv4Header *ipv4
1012 = (struct GNUNET_TUN_IPv4Header*) &tun[1];
1013
1014 tun->proto = htons (ETH_P_IPV4);
1015 prepare_ipv4_packet (payload,
1016 payload_length,
1017 IPPROTO_TCP,
1018 tcp_header,
1019 source_address,
1020 destination_address,
1021 ipv4);
1022 }
1023 break;
1024
1025 case AF_INET6:
1026 {
1027 struct GNUNET_TUN_IPv6Header *ipv6
1028 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
1029
1030 tun->proto = htons (ETH_P_IPV6);
1031 prepare_ipv6_packet (payload,
1032 payload_length,
1033 IPPROTO_TCP,
1034 tcp_header,
1035 source_address,
1036 destination_address,
1037 ipv6);
1038 }
1039 break;
1040
1041 default:
1042 GNUNET_assert (0);
1043 break;
1044 }
1045 if (NULL != helper_handle)
1046 (void) GNUNET_HELPER_send (helper_handle,
1047 (const struct GNUNET_MessageHeader*) buf,
1048 GNUNET_YES,
1049 NULL,
1050 NULL);
1051 }
1052}
1053
1054
1055/**
1056 * Send an ICMP packet via the TUN interface.
1057 *
1058 * @param destination_address IP to use for the ICMP packet's destination
1059 * @param source_address IP to use for the ICMP packet's source
1060 * @param icmp_header ICMP header to send
1061 * @param payload payload of the ICMP packet (does NOT include ICMP header)
1062 * @param payload_length number of bytes of data in @a payload
1063 */
1064static void
1065send_icmp_packet_via_tun (const struct SocketAddress *destination_address,
1066 const struct SocketAddress *source_address,
1067 const struct GNUNET_TUN_IcmpHeader *icmp_header,
1068 const void *payload, size_t payload_length)
1069{
1070 size_t len;
1071 struct GNUNET_TUN_IcmpHeader *icmp;
1072
1073 GNUNET_STATISTICS_update (stats,
1074 gettext_noop ("# ICMP packets sent via TUN"),
1075 1, GNUNET_NO);
1076 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1077 "Sending packet with %u bytes ICMP payload via TUN\n",
1078 (unsigned int) payload_length);
1079 len = sizeof(struct GNUNET_MessageHeader) + sizeof(struct
1080 GNUNET_TUN_Layer2PacketHeader);
1081 switch (destination_address->af)
1082 {
1083 case AF_INET:
1084 len += sizeof(struct GNUNET_TUN_IPv4Header);
1085 break;
1086
1087 case AF_INET6:
1088 len += sizeof(struct GNUNET_TUN_IPv6Header);
1089 break;
1090
1091 default:
1092 GNUNET_break (0);
1093 return;
1094 }
1095 len += sizeof(struct GNUNET_TUN_IcmpHeader);
1096 len += payload_length;
1097 if (len >= GNUNET_MAX_MESSAGE_SIZE)
1098 {
1099 GNUNET_break (0);
1100 return;
1101 }
1102 {
1103 char buf[len] GNUNET_ALIGN;
1104 struct GNUNET_MessageHeader *hdr;
1105 struct GNUNET_TUN_Layer2PacketHeader *tun;
1106
1107 hdr = (struct GNUNET_MessageHeader *) buf;
1108 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1109 hdr->size = htons (len);
1110 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
1111 tun->flags = htons (0);
1112 switch (source_address->af)
1113 {
1114 case AF_INET:
1115 {
1116 struct GNUNET_TUN_IPv4Header *ipv4 = (struct
1117 GNUNET_TUN_IPv4Header*) &tun[1];
1118
1119 tun->proto = htons (ETH_P_IPV4);
1120 GNUNET_TUN_initialize_ipv4_header (ipv4,
1121 IPPROTO_ICMP,
1122 sizeof(struct
1123 GNUNET_TUN_IcmpHeader)
1124 + payload_length,
1125 &source_address->address.ipv4,
1126 &destination_address->address.ipv4);
1127 icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv4[1];
1128 }
1129 break;
1130
1131 case AF_INET6:
1132 {
1133 struct GNUNET_TUN_IPv6Header *ipv6 = (struct
1134 GNUNET_TUN_IPv6Header*) &tun[1];
1135
1136 tun->proto = htons (ETH_P_IPV6);
1137 GNUNET_TUN_initialize_ipv6_header (ipv6,
1138 IPPROTO_ICMPV6,
1139 sizeof(struct
1140 GNUNET_TUN_IcmpHeader)
1141 + payload_length,
1142 &source_address->address.ipv6,
1143 &destination_address->address.ipv6);
1144 icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv6[1];
1145 }
1146 break;
1147
1148 default:
1149 GNUNET_assert (0);
1150 break;
1151 }
1152 *icmp = *icmp_header;
1153 GNUNET_memcpy (&icmp[1],
1154 payload,
1155 payload_length);
1156 GNUNET_TUN_calculate_icmp_checksum (icmp,
1157 payload,
1158 payload_length);
1159 if (NULL != helper_handle)
1160 (void) GNUNET_HELPER_send (helper_handle,
1161 (const struct GNUNET_MessageHeader*) buf,
1162 GNUNET_YES,
1163 NULL, NULL);
1164 }
1165}
1166
1167
1168/**
1169 * We need to create a (unique) fresh local address (IP+port).
1170 * Fill one in.
1171 *
1172 * @param af desired address family
1173 * @param proto desired protocol (IPPROTO_UDP or IPPROTO_TCP)
1174 * @param local_address address to initialize
1175 */
1176static void
1177setup_fresh_address (int af,
1178 uint8_t proto,
1179 struct SocketAddress *local_address)
1180{
1181 local_address->af = af;
1182 local_address->proto = (uint8_t) proto;
1183 /* default "local" port range is often 32768--61000,
1184 so we pick a random value in that range */
1185 if (((af == AF_INET) && (proto == IPPROTO_ICMP)) ||
1186 ((af == AF_INET6) && (proto == IPPROTO_ICMPV6)))
1187 local_address->port = 0;
1188 else
1189 local_address->port
1190 = (uint16_t) 32768 + GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1191 28232);
1192 switch (af)
1193 {
1194 case AF_INET:
1195 {
1196 struct in_addr addr;
1197 struct in_addr mask;
1198 struct in_addr rnd;
1199
1200 addr = exit_ipv4addr;
1201 mask = exit_ipv4mask;
1202 if (0 == ~mask.s_addr)
1203 {
1204 /* only one valid IP anyway */
1205 local_address->address.ipv4 = addr;
1206 return;
1207 }
1208 /* Given 192.168.0.1/255.255.0.0, we want a mask
1209 of '192.168.255.255', thus: */
1210 mask.s_addr = addr.s_addr | ~mask.s_addr;
1211 /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
1212 do
1213 {
1214 rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1215 UINT32_MAX);
1216 local_address->address.ipv4.s_addr = (addr.s_addr | rnd.s_addr)
1217 & mask.s_addr;
1218 }
1219 while ((local_address->address.ipv4.s_addr == addr.s_addr) ||
1220 (local_address->address.ipv4.s_addr == mask.s_addr));
1221 }
1222 break;
1223
1224 case AF_INET6:
1225 {
1226 struct in6_addr addr;
1227 struct in6_addr mask;
1228 struct in6_addr rnd;
1229 int i;
1230
1231 addr = exit_ipv6addr;
1232 GNUNET_assert (ipv6prefix < 128);
1233 if (ipv6prefix == 127)
1234 {
1235 /* only one valid IP anyway */
1236 local_address->address.ipv6 = addr;
1237 return;
1238 }
1239 /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
1240 thus: */
1241 mask = addr;
1242 for (i = 127; i >= ipv6prefix; i--)
1243 mask.s6_addr[i / 8] |= (1 << (i % 8));
1244
1245 /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
1246 do
1247 {
1248 for (i = 0; i < 16; i++)
1249 {
1250 rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (
1251 GNUNET_CRYPTO_QUALITY_WEAK,
1252 256);
1253 local_address->address.ipv6.s6_addr[i]
1254 = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
1255 }
1256 }
1257 while ((0 == GNUNET_memcmp (&local_address->address.ipv6,
1258 &addr)) ||
1259 (0 == GNUNET_memcmp (&local_address->address.ipv6,
1260 &mask)));
1261 }
1262 break;
1263
1264 default:
1265 GNUNET_assert (0);
1266 }
1267}
1268
1269
1270/**
1271 * We are starting a fresh connection (TCP or UDP) and need
1272 * to pick a source port and IP address (within the correct
1273 * range and address family) to associate replies with the
1274 * connection / correct cadet channel. This function generates
1275 * a "fresh" source IP and source port number for a connection
1276 * After picking a good source address, this function sets up
1277 * the state in the 'connections_map' and 'connections_heap'
1278 * to allow finding the state when needed later. The function
1279 * also makes sure that we remain within memory limits by
1280 * cleaning up 'old' states.
1281 *
1282 * @param state skeleton state to setup a record for; should
1283 * 'state->specifics.tcp_udp.ri.remote_address' filled in so that
1284 * this code can determine which AF/protocol is
1285 * going to be used (the 'channel' should also
1286 * already be set); after calling this function,
1287 * heap_node and the local_address will be
1288 * also initialized (heap_node != NULL can be
1289 * used to test if a state has been fully setup).
1290 */
1291static void
1292setup_state_record (struct ChannelState *state)
1293{
1294 struct GNUNET_HashCode key;
1295 struct ChannelState *s;
1296
1297 /* generate fresh, unique address */
1298 do
1299 {
1300 if (NULL == state->specifics.tcp_udp.serv)
1301 setup_fresh_address (state->specifics.tcp_udp.ri.remote_address.af,
1302 state->specifics.tcp_udp.ri.remote_address.proto,
1303 &state->specifics.tcp_udp.ri.local_address);
1304 else
1305 setup_fresh_address (state->specifics.tcp_udp.serv->address.af,
1306 state->specifics.tcp_udp.serv->address.proto,
1307 &state->specifics.tcp_udp.ri.local_address);
1308 }
1309 while (NULL !=
1310 get_redirect_state (state->specifics.tcp_udp.ri.remote_address.af,
1311 state->specifics.tcp_udp.ri.remote_address.proto,
1312 &state->specifics.tcp_udp.ri.remote_address.address,
1313 state->specifics.tcp_udp.ri.remote_address.port,
1314 &state->specifics.tcp_udp.ri.local_address.address,
1315 state->specifics.tcp_udp.ri.local_address.port,
1316 &key));
1317 {
1318 char buf[INET6_ADDRSTRLEN];
1319 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1320 "Picked local address %s:%u for new connection\n",
1321 inet_ntop (state->specifics.tcp_udp.ri.local_address.af,
1322 &state->specifics.tcp_udp.ri.local_address.address,
1323 buf,
1324 sizeof(buf)),
1325 (unsigned int) state->specifics.tcp_udp.ri.local_address.port);
1326 }
1327 state->specifics.tcp_udp.state_key = key;
1328 GNUNET_assert (GNUNET_OK ==
1329 GNUNET_CONTAINER_multihashmap_put (connections_map,
1330 &key, state,
1331 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1332 state->specifics.tcp_udp.heap_node
1333 = GNUNET_CONTAINER_heap_insert (connections_heap,
1334 state,
1335 GNUNET_TIME_absolute_get ().abs_value_us);
1336 while (GNUNET_CONTAINER_heap_get_size (connections_heap) > max_connections)
1337 {
1338 s = GNUNET_CONTAINER_heap_remove_root (connections_heap);
1339 GNUNET_assert (state != s);
1340 s->specifics.tcp_udp.heap_node = NULL;
1341 GNUNET_CADET_channel_destroy (s->channel);
1342 GNUNET_assert (GNUNET_OK ==
1343 GNUNET_CONTAINER_multihashmap_remove (connections_map,
1344 &s->specifics.tcp_udp.
1345 state_key,
1346 s));
1347 GNUNET_free (s);
1348 }
1349}
1350
1351
1352/**
1353 * Send a UDP packet via the TUN interface.
1354 *
1355 * @param destination_address IP and port to use for the UDP packet's destination
1356 * @param source_address IP and port to use for the UDP packet's source
1357 * @param payload payload of the UDP packet (does NOT include UDP header)
1358 * @param payload_length number of bytes of data in @a payload
1359 */
1360static void
1361send_udp_packet_via_tun (const struct SocketAddress *destination_address,
1362 const struct SocketAddress *source_address,
1363 const void *payload, size_t payload_length)
1364{
1365 size_t len;
1366
1367 GNUNET_STATISTICS_update (stats,
1368 gettext_noop ("# UDP packets sent via TUN"),
1369 1, GNUNET_NO);
1370 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1371 "Sending packet with %u bytes UDP payload via TUN\n",
1372 (unsigned int) payload_length);
1373 len = sizeof(struct GNUNET_MessageHeader) + sizeof(struct
1374 GNUNET_TUN_Layer2PacketHeader);
1375 switch (source_address->af)
1376 {
1377 case AF_INET:
1378 len += sizeof(struct GNUNET_TUN_IPv4Header);
1379 break;
1380
1381 case AF_INET6:
1382 len += sizeof(struct GNUNET_TUN_IPv6Header);
1383 break;
1384
1385 default:
1386 GNUNET_break (0);
1387 return;
1388 }
1389 len += sizeof(struct GNUNET_TUN_UdpHeader);
1390 len += payload_length;
1391 if (len >= GNUNET_MAX_MESSAGE_SIZE)
1392 {
1393 GNUNET_break (0);
1394 return;
1395 }
1396 {
1397 char buf[len] GNUNET_ALIGN;
1398 struct GNUNET_MessageHeader *hdr;
1399 struct GNUNET_TUN_Layer2PacketHeader *tun;
1400
1401 hdr = (struct GNUNET_MessageHeader *) buf;
1402 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1403 hdr->size = htons (len);
1404 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
1405 tun->flags = htons (0);
1406 switch (source_address->af)
1407 {
1408 case AF_INET:
1409 {
1410 struct GNUNET_TUN_IPv4Header *ipv4 = (struct
1411 GNUNET_TUN_IPv4Header*) &tun[1];
1412
1413 tun->proto = htons (ETH_P_IPV4);
1414 prepare_ipv4_packet (payload,
1415 payload_length,
1416 IPPROTO_UDP,
1417 NULL,
1418 source_address,
1419 destination_address,
1420 ipv4);
1421 }
1422 break;
1423
1424 case AF_INET6:
1425 {
1426 struct GNUNET_TUN_IPv6Header *ipv6 = (struct
1427 GNUNET_TUN_IPv6Header*) &tun[1];
1428
1429 tun->proto = htons (ETH_P_IPV6);
1430 prepare_ipv6_packet (payload,
1431 payload_length,
1432 IPPROTO_UDP,
1433 NULL,
1434 source_address,
1435 destination_address,
1436 ipv6);
1437 }
1438 break;
1439
1440 default:
1441 GNUNET_assert (0);
1442 break;
1443 }
1444 if (NULL != helper_handle)
1445 (void) GNUNET_HELPER_send (helper_handle,
1446 (const struct GNUNET_MessageHeader*) buf,
1447 GNUNET_YES,
1448 NULL, NULL);
1449 }
1450}
1451
1452
1453/**
1454 * Check a request to forward UDP data to the Internet via this peer.
1455 *
1456 * @param cls our `struct ChannelState *`
1457 * @param msg the actual message
1458 * @return #GNUNET_OK to keep the connection open,
1459 * #GNUNET_SYSERR to close it (signal serious error)
1460 */
1461static int
1462check_udp_remote (void *cls,
1463 const struct GNUNET_EXIT_UdpInternetMessage *msg)
1464{
1465 struct ChannelState *state = cls;
1466
1467 if (GNUNET_YES == state->is_dns)
1468 {
1469 GNUNET_break_op (0);
1470 return GNUNET_SYSERR;
1471 }
1472 return GNUNET_OK;
1473}
1474
1475
1476/**
1477 * Process a request to forward UDP data to the Internet via this peer.
1478 *
1479 * @param cls our `struct ChannelState *`
1480 * @param msg the actual message
1481 */
1482static void
1483handle_udp_remote (void *cls,
1484 const struct GNUNET_EXIT_UdpInternetMessage *msg)
1485{
1486 struct ChannelState *state = cls;
1487 uint16_t pkt_len = ntohs (msg->header.size) - sizeof(struct
1488 GNUNET_EXIT_UdpInternetMessage);
1489 const struct in_addr *v4;
1490 const struct in6_addr *v6;
1491 const void *payload;
1492 int af;
1493
1494 if (GNUNET_SYSERR == state->is_dns)
1495 {
1496 /* channel is UDP/TCP from now on */
1497 state->is_dns = GNUNET_NO;
1498 }
1499 GNUNET_STATISTICS_update (stats,
1500 gettext_noop ("# Bytes received from CADET"),
1501 pkt_len, GNUNET_NO);
1502 GNUNET_STATISTICS_update (stats,
1503 gettext_noop (
1504 "# UDP IP-exit requests received via cadet"),
1505 1, GNUNET_NO);
1506 af = (int) ntohl (msg->af);
1507 state->specifics.tcp_udp.ri.remote_address.af = af;
1508 switch (af)
1509 {
1510 case AF_INET:
1511 if (pkt_len < sizeof(struct in_addr))
1512 {
1513 GNUNET_break_op (0);
1514 return;
1515 }
1516 if (! ipv4_exit)
1517 {
1518 GNUNET_break_op (0);
1519 return;
1520 }
1521 v4 = (const struct in_addr*) &msg[1];
1522 payload = &v4[1];
1523 pkt_len -= sizeof(struct in_addr);
1524 state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4;
1525 break;
1526
1527 case AF_INET6:
1528 if (pkt_len < sizeof(struct in6_addr))
1529 {
1530 GNUNET_break_op (0);
1531 return;
1532 }
1533 if (! ipv6_exit)
1534 {
1535 GNUNET_break_op (0);
1536 return;
1537 }
1538 v6 = (const struct in6_addr*) &msg[1];
1539 payload = &v6[1];
1540 pkt_len -= sizeof(struct in6_addr);
1541 state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6;
1542 break;
1543
1544 default:
1545 GNUNET_break_op (0);
1546 return;
1547 }
1548 {
1549 char buf[INET6_ADDRSTRLEN];
1550 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1551 "Received data from %s for forwarding to UDP %s:%u\n",
1552 GNUNET_i2s (&state->peer),
1553 inet_ntop (af,
1554 &state->specifics.tcp_udp.ri.remote_address.address,
1555 buf, sizeof(buf)),
1556 (unsigned int) ntohs (msg->destination_port));
1557 }
1558 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_UDP;
1559 state->specifics.tcp_udp.ri.remote_address.port = msg->destination_port;
1560 if (NULL == state->specifics.tcp_udp.heap_node)
1561 setup_state_record (state);
1562 if (0 != ntohs (msg->source_port))
1563 state->specifics.tcp_udp.ri.local_address.port = msg->source_port;
1564 send_udp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1565 &state->specifics.tcp_udp.ri.local_address,
1566 payload,
1567 pkt_len);
1568 GNUNET_CADET_receive_done (state->channel);
1569}
1570
1571
1572/**
1573 * Check a request via cadet to send a request to a UDP service
1574 * offered by this system.
1575 *
1576 * @param cls our `struct ChannelState *`
1577 * @param msg the actual message
1578 * @return #GNUNET_OK to keep the connection open,
1579 * #GNUNET_SYSERR to close it (signal serious error)
1580 */
1581static int
1582check_udp_service (void *cls,
1583 const struct GNUNET_EXIT_UdpServiceMessage *msg)
1584{
1585 struct ChannelState *state = cls;
1586
1587 if (NULL == state->specifics.tcp_udp.serv)
1588 {
1589 GNUNET_break_op (0);
1590 return GNUNET_SYSERR;
1591 }
1592 return GNUNET_OK;
1593}
1594
1595
1596/**
1597 * Process a request via cadet to send a request to a UDP service
1598 * offered by this system.
1599 *
1600 * @param cls our `struct ChannelState *`
1601 * @param msg the actual message
1602 */
1603static void
1604handle_udp_service (void *cls,
1605 const struct GNUNET_EXIT_UdpServiceMessage *msg)
1606{
1607 struct ChannelState *state = cls;
1608 uint16_t pkt_len = ntohs (msg->header.size) - sizeof(struct
1609 GNUNET_EXIT_UdpServiceMessage);
1610
1611 GNUNET_STATISTICS_update (stats,
1612 gettext_noop ("# Bytes received from CADET"),
1613 pkt_len, GNUNET_NO);
1614 GNUNET_STATISTICS_update (stats,
1615 gettext_noop (
1616 "# UDP service requests received via cadet"),
1617 1, GNUNET_NO);
1618 LOG (GNUNET_ERROR_TYPE_DEBUG,
1619 "Received data from %s for forwarding to UDP service %s on port %u\n",
1620 GNUNET_i2s (&state->peer),
1621 GNUNET_h2s (&state->specifics.tcp_udp.serv->descriptor),
1622 (unsigned int) ntohs (msg->destination_port));
1623 setup_state_record (state);
1624 if (0 != ntohs (msg->source_port))
1625 state->specifics.tcp_udp.ri.local_address.port = msg->source_port;
1626 send_udp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1627 &state->specifics.tcp_udp.ri.local_address,
1628 &msg[1],
1629 pkt_len);
1630 GNUNET_CADET_receive_done (state->channel);
1631}
1632
1633
1634/**
1635 * Process a request via cadet to send a request to a TCP service
1636 * offered by this system.
1637 *
1638 * @param cls our `struct ChannelState *`
1639 * @param start the actual message
1640 * @return #GNUNET_OK to keep the connection open,
1641 * #GNUNET_SYSERR to close it (signal serious error)
1642 */
1643static void
1644handle_tcp_service (void *cls,
1645 const struct GNUNET_EXIT_TcpServiceStartMessage *start)
1646{
1647 struct ChannelState *state = cls;
1648 uint16_t pkt_len = ntohs (start->header.size) - sizeof(struct
1649 GNUNET_EXIT_TcpServiceStartMessage);
1650
1651 if (GNUNET_SYSERR == state->is_dns)
1652 {
1653 /* channel is UDP/TCP from now on */
1654 state->is_dns = GNUNET_NO;
1655 }
1656 GNUNET_STATISTICS_update (stats,
1657 gettext_noop (
1658 "# TCP service creation requests received via cadet"),
1659 1,
1660 GNUNET_NO);
1661 GNUNET_STATISTICS_update (stats,
1662 gettext_noop ("# Bytes received from CADET"),
1663 pkt_len,
1664 GNUNET_NO);
1665 GNUNET_break_op (ntohl (start->reserved) == 0);
1666 /* setup fresh connection */
1667 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1668 "Received data from %s for forwarding to TCP service %s on port %u\n",
1669 GNUNET_i2s (&state->peer),
1670 GNUNET_h2s (&state->specifics.tcp_udp.serv->descriptor),
1671 (unsigned int) ntohs (start->tcp_header.destination_port));
1672 setup_state_record (state);
1673 send_tcp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1674 &state->specifics.tcp_udp.ri.local_address,
1675 &start->tcp_header,
1676 &start[1],
1677 pkt_len);
1678 GNUNET_CADET_receive_done (state->channel);
1679}
1680
1681
1682/**
1683 * Check a request to forward TCP data to the Internet via this peer.
1684 *
1685 * @param cls our `struct ChannelState *`
1686 * @param start the actual message
1687 * @return #GNUNET_OK to keep the connection open,
1688 * #GNUNET_SYSERR to close it (signal serious error)
1689 */
1690static int
1691check_tcp_remote (void *cls,
1692 const struct GNUNET_EXIT_TcpInternetStartMessage *start)
1693{
1694 struct ChannelState *state = cls;
1695
1696 if (NULL == state)
1697 {
1698 GNUNET_break_op (0);
1699 return GNUNET_SYSERR;
1700 }
1701 if (GNUNET_YES == state->is_dns)
1702 {
1703 GNUNET_break_op (0);
1704 return GNUNET_SYSERR;
1705 }
1706 if ((NULL != state->specifics.tcp_udp.serv) ||
1707 (NULL != state->specifics.tcp_udp.heap_node))
1708 {
1709 GNUNET_break_op (0);
1710 return GNUNET_SYSERR;
1711 }
1712 if (start->tcp_header.off * 4 < sizeof(struct GNUNET_TUN_TcpHeader))
1713 {
1714 GNUNET_break_op (0);
1715 return GNUNET_SYSERR;
1716 }
1717 return GNUNET_OK;
1718}
1719
1720
1721/**
1722 * Process a request to forward TCP data to the Internet via this peer.
1723 *
1724 * @param cls our `struct ChannelState *`
1725 * @param start the actual message
1726 */
1727static void
1728handle_tcp_remote (void *cls,
1729 const struct GNUNET_EXIT_TcpInternetStartMessage *start)
1730{
1731 struct ChannelState *state = cls;
1732 uint16_t pkt_len = ntohs (start->header.size) - sizeof(struct
1733 GNUNET_EXIT_TcpInternetStartMessage);
1734 const struct in_addr *v4;
1735 const struct in6_addr *v6;
1736 const void *payload;
1737 int af;
1738
1739 if (GNUNET_SYSERR == state->is_dns)
1740 {
1741 /* channel is UDP/TCP from now on */
1742 state->is_dns = GNUNET_NO;
1743 }
1744 GNUNET_STATISTICS_update (stats,
1745 gettext_noop ("# Bytes received from CADET"),
1746 pkt_len, GNUNET_NO);
1747 GNUNET_STATISTICS_update (stats,
1748 gettext_noop (
1749 "# TCP IP-exit creation requests received via cadet"),
1750 1, GNUNET_NO);
1751 af = (int) ntohl (start->af);
1752 state->specifics.tcp_udp.ri.remote_address.af = af;
1753 switch (af)
1754 {
1755 case AF_INET:
1756 if (pkt_len < sizeof(struct in_addr))
1757 {
1758 GNUNET_break_op (0);
1759 return;
1760 }
1761 if (! ipv4_exit)
1762 {
1763 GNUNET_break_op (0);
1764 return;
1765 }
1766 v4 = (const struct in_addr*) &start[1];
1767 payload = &v4[1];
1768 pkt_len -= sizeof(struct in_addr);
1769 state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4;
1770 break;
1771
1772 case AF_INET6:
1773 if (pkt_len < sizeof(struct in6_addr))
1774 {
1775 GNUNET_break_op (0);
1776 return;
1777 }
1778 if (! ipv6_exit)
1779 {
1780 GNUNET_break_op (0);
1781 return;
1782 }
1783 v6 = (const struct in6_addr*) &start[1];
1784 payload = &v6[1];
1785 pkt_len -= sizeof(struct in6_addr);
1786 state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6;
1787 break;
1788
1789 default:
1790 GNUNET_break_op (0);
1791 return;
1792 }
1793 {
1794 char buf[INET6_ADDRSTRLEN];
1795 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1796 "Received payload from %s for existing TCP stream to %s:%u\n",
1797 GNUNET_i2s (&state->peer),
1798 inet_ntop (af,
1799 &state->specifics.tcp_udp.ri.remote_address.address,
1800 buf, sizeof(buf)),
1801 (unsigned int) ntohs (start->tcp_header.destination_port));
1802 }
1803 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_TCP;
1804 state->specifics.tcp_udp.ri.remote_address.port = ntohs (
1805 start->tcp_header.destination_port);
1806 setup_state_record (state);
1807 send_tcp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1808 &state->specifics.tcp_udp.ri.local_address,
1809 &start->tcp_header,
1810 payload,
1811 pkt_len);
1812 GNUNET_CADET_receive_done (state->channel);
1813}
1814
1815
1816/**
1817 * Check a request to forward TCP data on an established
1818 * connection via this peer.
1819 *
1820 * @param cls our `struct ChannelState *`
1821 * @param data the actual message
1822 * @return #GNUNET_OK to keep the connection open,
1823 * #GNUNET_SYSERR to close it (signal serious error)
1824 */
1825static int
1826check_tcp_data (void *cls,
1827 const struct GNUNET_EXIT_TcpDataMessage *data)
1828{
1829 struct ChannelState *state = cls;
1830
1831 if ((NULL == state) ||
1832 (NULL == state->specifics.tcp_udp.heap_node))
1833 {
1834 /* connection should have been up! */
1835 GNUNET_STATISTICS_update (stats,
1836 gettext_noop (
1837 "# TCP DATA requests dropped (no session)"),
1838 1, GNUNET_NO);
1839 GNUNET_break_op (0);
1840 return GNUNET_SYSERR;
1841 }
1842 if (data->tcp_header.off * 4 < sizeof(struct GNUNET_TUN_TcpHeader))
1843 {
1844 GNUNET_break_op (0);
1845 return GNUNET_SYSERR;
1846 }
1847 if (GNUNET_YES == state->is_dns)
1848 {
1849 GNUNET_break_op (0);
1850 return GNUNET_SYSERR;
1851 }
1852 return GNUNET_OK;
1853}
1854
1855
1856/**
1857 * Process a request to forward TCP data on an established
1858 * connection via this peer.
1859 *
1860 * @param cls our `struct ChannelState *`
1861 * @param data the actual message
1862 */
1863static void
1864handle_tcp_data (void *cls,
1865 const struct GNUNET_EXIT_TcpDataMessage *data)
1866{
1867 struct ChannelState *state = cls;
1868 uint16_t pkt_len = ntohs (data->header.size) - sizeof(struct
1869 GNUNET_EXIT_TcpDataMessage);
1870
1871 GNUNET_STATISTICS_update (stats,
1872 gettext_noop ("# Bytes received from CADET"),
1873 pkt_len, GNUNET_NO);
1874 GNUNET_STATISTICS_update (stats,
1875 gettext_noop (
1876 "# TCP data requests received via cadet"),
1877 1, GNUNET_NO);
1878 if (GNUNET_SYSERR == state->is_dns)
1879 {
1880 /* channel is UDP/TCP from now on */
1881 state->is_dns = GNUNET_NO;
1882 }
1883
1884 GNUNET_break_op (ntohl (data->reserved) == 0);
1885 {
1886 char buf[INET6_ADDRSTRLEN];
1887 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1888 "Received additional %u bytes of data from %s for TCP stream to %s:%u\n",
1889 pkt_len,
1890 GNUNET_i2s (&state->peer),
1891 inet_ntop (state->specifics.tcp_udp.ri.remote_address.af,
1892 &state->specifics.tcp_udp.ri.remote_address.address,
1893 buf, sizeof(buf)),
1894 (unsigned int) state->specifics.tcp_udp.ri.remote_address.port);
1895 }
1896
1897 send_tcp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1898 &state->specifics.tcp_udp.ri.local_address,
1899 &data->tcp_header,
1900 &data[1], pkt_len);
1901 GNUNET_CADET_receive_done (state->channel);
1902}
1903
1904
1905/**
1906 * Synthesize a plausible ICMP payload for an ICMPv4 error
1907 * response on the given channel.
1908 *
1909 * @param state channel information
1910 * @param ipp IPv6 header to fill in (ICMP payload)
1911 * @param udp "UDP" header to fill in (ICMP payload); might actually
1912 * also be the first 8 bytes of the TCP header
1913 */
1914static void
1915make_up_icmpv4_payload (struct ChannelState *state,
1916 struct GNUNET_TUN_IPv4Header *ipp,
1917 struct GNUNET_TUN_UdpHeader *udp)
1918{
1919 GNUNET_TUN_initialize_ipv4_header (ipp,
1920 state->specifics.tcp_udp.ri.remote_address.
1921 proto,
1922 sizeof(struct GNUNET_TUN_TcpHeader),
1923 &state->specifics.tcp_udp.ri.remote_address
1924 .address.ipv4,
1925 &state->specifics.tcp_udp.ri.local_address.
1926 address.ipv4);
1927 udp->source_port = htons (state->specifics.tcp_udp.ri.remote_address.port);
1928 udp->destination_port = htons (
1929 state->specifics.tcp_udp.ri.local_address.port);
1930 udp->len = htons (0);
1931 udp->crc = htons (0);
1932}
1933
1934
1935/**
1936 * Synthesize a plausible ICMP payload for an ICMPv6 error
1937 * response on the given channel.
1938 *
1939 * @param state channel information
1940 * @param ipp IPv6 header to fill in (ICMP payload)
1941 * @param udp "UDP" header to fill in (ICMP payload); might actually
1942 * also be the first 8 bytes of the TCP header
1943 */
1944static void
1945make_up_icmpv6_payload (struct ChannelState *state,
1946 struct GNUNET_TUN_IPv6Header *ipp,
1947 struct GNUNET_TUN_UdpHeader *udp)
1948{
1949 GNUNET_TUN_initialize_ipv6_header (ipp,
1950 state->specifics.tcp_udp.ri.remote_address.
1951 proto,
1952 sizeof(struct GNUNET_TUN_TcpHeader),
1953 &state->specifics.tcp_udp.ri.remote_address
1954 .address.ipv6,
1955 &state->specifics.tcp_udp.ri.local_address.
1956 address.ipv6);
1957 udp->source_port = htons (state->specifics.tcp_udp.ri.remote_address.port);
1958 udp->destination_port = htons (
1959 state->specifics.tcp_udp.ri.local_address.port);
1960 udp->len = htons (0);
1961 udp->crc = htons (0);
1962}
1963
1964
1965/**
1966 * Check a request to forward ICMP data to the Internet via this peer.
1967 *
1968 * @param cls our `struct ChannelState *`
1969 * @param msg the actual message
1970 * @return #GNUNET_OK to keep the connection open,
1971 * #GNUNET_SYSERR to close it (signal serious error)
1972 */
1973static int
1974check_icmp_remote (void *cls,
1975 const struct GNUNET_EXIT_IcmpInternetMessage *msg)
1976{
1977 struct ChannelState *state = cls;
1978
1979 if (GNUNET_YES == state->is_dns)
1980 {
1981 GNUNET_break_op (0);
1982 return GNUNET_SYSERR;
1983 }
1984 return GNUNET_OK;
1985}
1986
1987
1988/**
1989 * Process a request to forward ICMP data to the Internet via this peer.
1990 *
1991 * @param cls our `struct ChannelState *`
1992 * @param msg the actual message
1993 */
1994static void
1995handle_icmp_remote (void *cls,
1996 const struct GNUNET_EXIT_IcmpInternetMessage *msg)
1997{
1998 struct ChannelState *state = cls;
1999 uint16_t pkt_len = ntohs (msg->header.size) - sizeof(struct
2000 GNUNET_EXIT_IcmpInternetMessage);
2001 const struct in_addr *v4;
2002 const struct in6_addr *v6;
2003 const void *payload;
2004 char buf[sizeof(struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
2005 int af;
2006
2007 if (GNUNET_SYSERR == state->is_dns)
2008 {
2009 /* channel is UDP/TCP from now on */
2010 state->is_dns = GNUNET_NO;
2011 }
2012 GNUNET_STATISTICS_update (stats,
2013 gettext_noop ("# Bytes received from CADET"),
2014 pkt_len, GNUNET_NO);
2015 GNUNET_STATISTICS_update (stats,
2016 gettext_noop (
2017 "# ICMP IP-exit requests received via cadet"),
2018 1, GNUNET_NO);
2019
2020 af = (int) ntohl (msg->af);
2021 if ((NULL != state->specifics.tcp_udp.heap_node) &&
2022 (af != state->specifics.tcp_udp.ri.remote_address.af))
2023 {
2024 /* other peer switched AF on this channel; not allowed */
2025 GNUNET_break_op (0);
2026 return;
2027 }
2028
2029 switch (af)
2030 {
2031 case AF_INET:
2032 if (pkt_len < sizeof(struct in_addr))
2033 {
2034 GNUNET_break_op (0);
2035 return;
2036 }
2037 if (! ipv4_exit)
2038 {
2039 GNUNET_break_op (0);
2040 return;
2041 }
2042 v4 = (const struct in_addr*) &msg[1];
2043 payload = &v4[1];
2044 pkt_len -= sizeof(struct in_addr);
2045 state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4;
2046 if (NULL == state->specifics.tcp_udp.heap_node)
2047 {
2048 state->specifics.tcp_udp.ri.remote_address.af = af;
2049 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_ICMP;
2050 setup_state_record (state);
2051 }
2052 /* check that ICMP type is something we want to support
2053 and possibly make up payload! */
2054 switch (msg->icmp_header.type)
2055 {
2056 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
2057 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
2058 break;
2059
2060 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
2061 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2062 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2063 if (0 != pkt_len)
2064 {
2065 GNUNET_break_op (0);
2066 return;
2067 }
2068 /* make up payload */
2069 {
2070 struct GNUNET_TUN_IPv4Header *ipp = (struct
2071 GNUNET_TUN_IPv4Header *) buf;
2072 struct GNUNET_TUN_UdpHeader *udp = (struct
2073 GNUNET_TUN_UdpHeader *) &ipp[1];
2074
2075 GNUNET_assert (8 == sizeof(struct GNUNET_TUN_UdpHeader));
2076 pkt_len = sizeof(struct GNUNET_TUN_IPv4Header) + 8;
2077 make_up_icmpv4_payload (state,
2078 ipp,
2079 udp);
2080 payload = ipp;
2081 }
2082 break;
2083
2084 default:
2085 GNUNET_break_op (0);
2086 GNUNET_STATISTICS_update (stats,
2087 gettext_noop (
2088 "# ICMPv4 packets dropped (type not allowed)"),
2089 1, GNUNET_NO);
2090 return;
2091 }
2092 /* end AF_INET */
2093 break;
2094
2095 case AF_INET6:
2096 if (pkt_len < sizeof(struct in6_addr))
2097 {
2098 GNUNET_break_op (0);
2099 return;
2100 }
2101 if (! ipv6_exit)
2102 {
2103 GNUNET_break_op (0);
2104 return;
2105 }
2106 v6 = (const struct in6_addr*) &msg[1];
2107 payload = &v6[1];
2108 pkt_len -= sizeof(struct in6_addr);
2109 state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6;
2110 if (NULL == state->specifics.tcp_udp.heap_node)
2111 {
2112 state->specifics.tcp_udp.ri.remote_address.af = af;
2113 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_ICMPV6;
2114 setup_state_record (state);
2115 }
2116 /* check that ICMP type is something we want to support
2117 and possibly make up payload! */
2118 switch (msg->icmp_header.type)
2119 {
2120 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2121 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2122 break;
2123
2124 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2125 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2126 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2127 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2128 if (0 != pkt_len)
2129 {
2130 GNUNET_break_op (0);
2131 return;
2132 }
2133 /* make up payload */
2134 {
2135 struct GNUNET_TUN_IPv6Header *ipp = (struct
2136 GNUNET_TUN_IPv6Header *) buf;
2137 struct GNUNET_TUN_UdpHeader *udp = (struct
2138 GNUNET_TUN_UdpHeader *) &ipp[1];
2139
2140 GNUNET_assert (8 == sizeof(struct GNUNET_TUN_UdpHeader));
2141 pkt_len = sizeof(struct GNUNET_TUN_IPv6Header) + 8;
2142 make_up_icmpv6_payload (state,
2143 ipp,
2144 udp);
2145 payload = ipp;
2146 }
2147 break;
2148
2149 default:
2150 GNUNET_break_op (0);
2151 GNUNET_STATISTICS_update (stats,
2152 gettext_noop (
2153 "# ICMPv6 packets dropped (type not allowed)"),
2154 1, GNUNET_NO);
2155 return;
2156 }
2157 /* end AF_INET6 */
2158 break;
2159
2160 default:
2161 /* bad AF */
2162 GNUNET_break_op (0);
2163 return;
2164 }
2165
2166 {
2167 char buf[INET6_ADDRSTRLEN];
2168 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2169 "Received ICMP data from %s for forwarding to %s\n",
2170 GNUNET_i2s (&state->peer),
2171 inet_ntop (af,
2172 &state->specifics.tcp_udp.ri.remote_address.address,
2173 buf, sizeof(buf)));
2174 }
2175 send_icmp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
2176 &state->specifics.tcp_udp.ri.local_address,
2177 &msg->icmp_header,
2178 payload, pkt_len);
2179 GNUNET_CADET_receive_done (state->channel);
2180}
2181
2182
2183/**
2184 * Setup ICMP payload for ICMP error messages. Called
2185 * for both IPv4 and IPv6 addresses.
2186 *
2187 * @param state context for creating the IP Packet
2188 * @param buf where to create the payload, has at least
2189 * sizeof (struct GNUNET_TUN_IPv6Header) + 8 bytes
2190 * @return number of bytes of payload we created in buf
2191 */
2192static uint16_t
2193make_up_icmp_service_payload (struct ChannelState *state,
2194 char *buf)
2195{
2196 switch (state->specifics.tcp_udp.serv->address.af)
2197 {
2198 case AF_INET:
2199 {
2200 struct GNUNET_TUN_IPv4Header *ipv4;
2201 struct GNUNET_TUN_UdpHeader *udp;
2202
2203 ipv4 = (struct GNUNET_TUN_IPv4Header *) buf;
2204 udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
2205 make_up_icmpv4_payload (state,
2206 ipv4,
2207 udp);
2208 GNUNET_assert (8 == sizeof(struct GNUNET_TUN_UdpHeader));
2209 return sizeof(struct GNUNET_TUN_IPv4Header) + 8;
2210 }
2211 break;
2212
2213 case AF_INET6:
2214 {
2215 struct GNUNET_TUN_IPv6Header *ipv6;
2216 struct GNUNET_TUN_UdpHeader *udp;
2217
2218 ipv6 = (struct GNUNET_TUN_IPv6Header *) buf;
2219 udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
2220 make_up_icmpv6_payload (state,
2221 ipv6,
2222 udp);
2223 GNUNET_assert (8 == sizeof(struct GNUNET_TUN_UdpHeader));
2224 return sizeof(struct GNUNET_TUN_IPv6Header) + 8;
2225 }
2226 break;
2227
2228 default:
2229 GNUNET_break (0);
2230 }
2231 return 0;
2232}
2233
2234
2235/**
2236 * Check a request via cadet to send ICMP data to a service
2237 * offered by this system.
2238 *
2239 * @param cls our `struct ChannelState *`
2240 * @param msg the actual message
2241 * @return #GNUNET_OK to keep the connection open,
2242 * #GNUNET_SYSERR to close it (signal serious error)
2243 */
2244static int
2245check_icmp_service (void *cls,
2246 const struct GNUNET_EXIT_IcmpServiceMessage *msg)
2247{
2248 struct ChannelState *state = cls;
2249
2250 if (GNUNET_YES == state->is_dns)
2251 {
2252 GNUNET_break_op (0);
2253 return GNUNET_SYSERR;
2254 }
2255 if (NULL == state->specifics.tcp_udp.serv)
2256 {
2257 GNUNET_break_op (0);
2258 return GNUNET_SYSERR;
2259 }
2260 return GNUNET_OK;
2261}
2262
2263
2264/**
2265 * Process a request via cadet to send ICMP data to a service
2266 * offered by this system.
2267 *
2268 * @param cls our `struct ChannelState *`
2269 * @param msg the actual message
2270 */
2271static void
2272handle_icmp_service (void *cls,
2273 const struct GNUNET_EXIT_IcmpServiceMessage *msg)
2274{
2275 struct ChannelState *state = cls;
2276 uint16_t pkt_len = ntohs (msg->header.size) - sizeof(struct
2277 GNUNET_EXIT_IcmpServiceMessage);
2278 struct GNUNET_TUN_IcmpHeader icmp;
2279 char buf[sizeof(struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
2280 const void *payload;
2281
2282 GNUNET_STATISTICS_update (stats,
2283 gettext_noop ("# Bytes received from CADET"),
2284 pkt_len, GNUNET_NO);
2285 GNUNET_STATISTICS_update (stats,
2286 gettext_noop (
2287 "# ICMP service requests received via cadet"),
2288 1, GNUNET_NO);
2289 /* check that we got at least a valid header */
2290 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2291 "Received data from %s for forwarding to ICMP service %s\n",
2292 GNUNET_i2s (&state->peer),
2293 GNUNET_h2s (&state->specifics.tcp_udp.serv->descriptor));
2294 icmp = msg->icmp_header;
2295 payload = &msg[1];
2296 state->specifics.tcp_udp.ri.remote_address
2297 = state->specifics.tcp_udp.serv->address;
2298 setup_state_record (state);
2299
2300 /* check that ICMP type is something we want to support,
2301 perform ICMP PT if needed and possibly make up payload */
2302 switch (msg->af)
2303 {
2304 case AF_INET:
2305 switch (msg->icmp_header.type)
2306 {
2307 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
2308 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2309 icmp.type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
2310 break;
2311
2312 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
2313 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2314 icmp.type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
2315 break;
2316
2317 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
2318 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2319 icmp.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
2320 if (0 != pkt_len)
2321 {
2322 GNUNET_break_op (0);
2323 return;
2324 }
2325 payload = buf;
2326 pkt_len = make_up_icmp_service_payload (state, buf);
2327 break;
2328
2329 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2330 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2331 icmp.type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
2332 if (0 != pkt_len)
2333 {
2334 GNUNET_break_op (0);
2335 return;
2336 }
2337 payload = buf;
2338 pkt_len = make_up_icmp_service_payload (state, buf);
2339 break;
2340
2341 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2342 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2343 {
2344 GNUNET_STATISTICS_update (stats,
2345 gettext_noop (
2346 "# ICMPv4 packets dropped (impossible PT to v6)"),
2347 1, GNUNET_NO);
2348 return;
2349 }
2350 if (0 != pkt_len)
2351 {
2352 GNUNET_break_op (0);
2353 return;
2354 }
2355 payload = buf;
2356 pkt_len = make_up_icmp_service_payload (state, buf);
2357 break;
2358
2359 default:
2360 GNUNET_break_op (0);
2361 GNUNET_STATISTICS_update (stats,
2362 gettext_noop (
2363 "# ICMPv4 packets dropped (type not allowed)"),
2364 1, GNUNET_NO);
2365 return;
2366 }
2367 /* end of AF_INET */
2368 break;
2369
2370 case AF_INET6:
2371 switch (msg->icmp_header.type)
2372 {
2373 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2374 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2375 icmp.type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
2376 break;
2377
2378 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2379 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2380 icmp.type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
2381 break;
2382
2383 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2384 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2385 icmp.type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
2386 if (0 != pkt_len)
2387 {
2388 GNUNET_break_op (0);
2389 return;
2390 }
2391 payload = buf;
2392 pkt_len = make_up_icmp_service_payload (state, buf);
2393 break;
2394
2395 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2396 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2397 icmp.type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
2398 if (0 != pkt_len)
2399 {
2400 GNUNET_break_op (0);
2401 return;
2402 }
2403 payload = buf;
2404 pkt_len = make_up_icmp_service_payload (state, buf);
2405 break;
2406
2407 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2408 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2409 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2410 {
2411 GNUNET_STATISTICS_update (stats,
2412 gettext_noop (
2413 "# ICMPv6 packets dropped (impossible PT to v4)"),
2414 1, GNUNET_NO);
2415 return;
2416 }
2417 if (0 != pkt_len)
2418 {
2419 GNUNET_break_op (0);
2420 return;
2421 }
2422 payload = buf;
2423 pkt_len = make_up_icmp_service_payload (state, buf);
2424 break;
2425
2426 default:
2427 GNUNET_break_op (0);
2428 GNUNET_STATISTICS_update (stats,
2429 gettext_noop (
2430 "# ICMPv6 packets dropped (type not allowed)"),
2431 1, GNUNET_NO);
2432 return;
2433 }
2434 /* end of AF_INET6 */
2435 break;
2436
2437 default:
2438 GNUNET_break_op (0);
2439 return;
2440 }
2441
2442 send_icmp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
2443 &state->specifics.tcp_udp.ri.local_address,
2444 &icmp,
2445 payload,
2446 pkt_len);
2447 GNUNET_CADET_receive_done (state->channel);
2448}
2449
2450
2451/**
2452 * Free memory associated with a service record.
2453 *
2454 * @param cls unused
2455 * @param key service descriptor
2456 * @param value service record to free
2457 * @return #GNUNET_OK
2458 */
2459static int
2460free_service_record (void *cls,
2461 const struct GNUNET_HashCode *key,
2462 void *value)
2463{
2464 struct LocalService *service = value;
2465
2466 GNUNET_assert (GNUNET_YES ==
2467 GNUNET_CONTAINER_multihashmap_remove (services,
2468 key,
2469 service));
2470 GNUNET_CADET_close_port (service->port);
2471 GNUNET_free (service->name);
2472 GNUNET_free (service);
2473 return GNUNET_OK;
2474}
2475
2476
2477/**
2478 * Callback from CADET for new channels.
2479 *
2480 * @param cls closure
2481 * @param channel new handle to the channel
2482 * @param initiator peer that started the channel
2483 * @return initial channel context for the channel
2484 */
2485static void *
2486new_service_channel (void *cls,
2487 struct GNUNET_CADET_Channel *channel,
2488 const struct GNUNET_PeerIdentity *initiator)
2489{
2490 struct LocalService *ls = cls;
2491 struct ChannelState *s = GNUNET_new (struct ChannelState);
2492
2493 s->peer = *initiator;
2494 GNUNET_STATISTICS_update (stats,
2495 gettext_noop ("# Inbound CADET channels created"),
2496 1,
2497 GNUNET_NO);
2498 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2499 "Received inbound channel from `%s'\n",
2500 GNUNET_i2s (initiator));
2501 s->channel = channel;
2502 s->specifics.tcp_udp.serv = ls;
2503 s->specifics.tcp_udp.ri.remote_address = ls->address;
2504 return s;
2505}
2506
2507
2508/**
2509 * Function called by cadet whenever an inbound channel is destroyed.
2510 * Should clean up any associated state.
2511 *
2512 * @param cls our `struct ChannelState *`
2513 * @param channel connection to the other end (henceforth invalid)
2514 */
2515static void
2516clean_channel (void *cls,
2517 const struct GNUNET_CADET_Channel *channel)
2518{
2519 struct ChannelState *s = cls;
2520
2521 LOG (GNUNET_ERROR_TYPE_DEBUG,
2522 "Channel destroyed\n");
2523 if (GNUNET_SYSERR == s->is_dns)
2524 {
2525 GNUNET_free (s);
2526 return;
2527 }
2528 if (GNUNET_YES == s->is_dns)
2529 {
2530 if (channels[s->specifics.dns.my_id] == s)
2531 channels[s->specifics.dns.my_id] = NULL;
2532 }
2533 else
2534 {
2535 if (NULL != s->specifics.tcp_udp.heap_node)
2536 {
2537 GNUNET_assert (GNUNET_YES ==
2538 GNUNET_CONTAINER_multihashmap_remove (connections_map,
2539 &s->specifics.tcp_udp
2540 .state_key,
2541 s));
2542 GNUNET_CONTAINER_heap_remove_node (s->specifics.tcp_udp.heap_node);
2543 s->specifics.tcp_udp.heap_node = NULL;
2544 }
2545 }
2546 GNUNET_free (s);
2547}
2548
2549
2550/**
2551 * Given a service descriptor and a destination port, find the
2552 * respective service entry.
2553 *
2554 * @param proto IPPROTO_TCP or IPPROTO_UDP
2555 * @param name name of the service
2556 * @param destination_port destination port
2557 * @param service service information record to store (service->name will be set).
2558 */
2559static void
2560store_service (int proto,
2561 const char *name,
2562 uint16_t destination_port,
2563 struct LocalService *service)
2564{
2565 struct GNUNET_MQ_MessageHandler handlers[] = {
2566 GNUNET_MQ_hd_var_size (icmp_service,
2567 GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE,
2568 struct GNUNET_EXIT_IcmpServiceMessage,
2569 service),
2570 GNUNET_MQ_hd_var_size (udp_service,
2571 GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE,
2572 struct GNUNET_EXIT_UdpServiceMessage,
2573 service),
2574 GNUNET_MQ_hd_var_size (tcp_service,
2575 GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START,
2576 struct GNUNET_EXIT_TcpServiceStartMessage,
2577 service),
2578 GNUNET_MQ_hd_var_size (tcp_data,
2579 GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT,
2580 struct GNUNET_EXIT_TcpDataMessage,
2581 service),
2582 GNUNET_MQ_handler_end ()
2583 };
2584
2585 struct GNUNET_HashCode cadet_port;
2586
2587 service->name = GNUNET_strdup (name);
2588 GNUNET_TUN_service_name_to_hash (name,
2589 &service->descriptor);
2590 GNUNET_TUN_compute_service_cadet_port (&service->descriptor,
2591 destination_port,
2592 &cadet_port);
2593 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2594 "Opening CADET port %s for SERVICE exit %s on port %u\n",
2595 GNUNET_h2s (&cadet_port),
2596 name,
2597 (unsigned int) destination_port);
2598 service->port = GNUNET_CADET_open_port (cadet_handle,
2599 &cadet_port,
2600 &new_service_channel,
2601 service,
2602 NULL,
2603 &clean_channel,
2604 handlers);
2605 service->is_udp = (IPPROTO_UDP == proto);
2606 if (GNUNET_OK !=
2607 GNUNET_CONTAINER_multihashmap_put (services,
2608 &cadet_port,
2609 service,
2610 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
2611 {
2612 GNUNET_CADET_close_port (service->port);
2613 GNUNET_free (service->name);
2614 GNUNET_free (service);
2615 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2616 _ ("Got duplicate service records for `%s:%u'\n"),
2617 name,
2618 (unsigned int) destination_port);
2619 }
2620}
2621
2622
2623/**
2624 * Send the given packet via the cadet channel.
2625 *
2626 * @param s channel destination
2627 * @param env message to queue
2628 */
2629static void
2630send_packet_to_cadet_channel (struct ChannelState *s,
2631 struct GNUNET_MQ_Envelope *env)
2632{
2633 GNUNET_assert (NULL != s);
2634 GNUNET_STATISTICS_update (stats,
2635 gettext_noop (
2636 "# Messages transmitted via cadet channels"),
2637 1,
2638 GNUNET_NO);
2639 GNUNET_MQ_send (GNUNET_CADET_get_mq (s->channel),
2640 env);
2641}
2642
2643
2644/**
2645 * @brief Handles an ICMP packet received from the helper.
2646 *
2647 * @param icmp A pointer to the Packet
2648 * @param pktlen number of bytes in @a icmp
2649 * @param af address family (AFINET or AF_INET6)
2650 * @param destination_ip destination IP-address of the IP packet (should
2651 * be our local address)
2652 * @param source_ip original source IP-address of the IP packet (should
2653 * be the original destination address)
2654 */
2655static void
2656icmp_from_helper (const struct GNUNET_TUN_IcmpHeader *icmp,
2657 size_t pktlen,
2658 int af,
2659 const void *destination_ip,
2660 const void *source_ip)
2661{
2662 struct ChannelState *state;
2663 struct GNUNET_MQ_Envelope *env;
2664 struct GNUNET_EXIT_IcmpToVPNMessage *i2v;
2665 const struct GNUNET_TUN_IPv4Header *ipv4;
2666 const struct GNUNET_TUN_IPv6Header *ipv6;
2667 const struct GNUNET_TUN_UdpHeader *udp;
2668 uint16_t source_port;
2669 uint16_t destination_port;
2670 uint8_t protocol;
2671
2672 {
2673 char sbuf[INET6_ADDRSTRLEN];
2674 char dbuf[INET6_ADDRSTRLEN];
2675 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2676 "Received ICMP packet going from %s to %s\n",
2677 inet_ntop (af,
2678 source_ip,
2679 sbuf, sizeof(sbuf)),
2680 inet_ntop (af,
2681 destination_ip,
2682 dbuf, sizeof(dbuf)));
2683 }
2684
2685 if (pktlen < sizeof(struct GNUNET_TUN_IcmpHeader))
2686 {
2687 /* blame kernel */
2688 GNUNET_break (0);
2689 return;
2690 }
2691
2692 /* Find out if this is an ICMP packet in response to an existing
2693 TCP/UDP packet and if so, figure out ports / protocol of the
2694 existing session from the IP data in the ICMP payload */
2695 source_port = 0;
2696 destination_port = 0;
2697 switch (af)
2698 {
2699 case AF_INET:
2700 protocol = IPPROTO_ICMP;
2701 switch (icmp->type)
2702 {
2703 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
2704 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
2705 break;
2706
2707 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
2708 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2709 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2710 if (pktlen <
2711 sizeof(struct GNUNET_TUN_IcmpHeader)
2712 + sizeof(struct GNUNET_TUN_IPv4Header) + 8)
2713 {
2714 /* blame kernel */
2715 GNUNET_break (0);
2716 return;
2717 }
2718 ipv4 = (const struct GNUNET_TUN_IPv4Header *) &icmp[1];
2719 protocol = ipv4->protocol;
2720 /* could be TCP or UDP, but both have the ports in the right
2721 place, so that doesn't matter here */
2722 udp = (const struct GNUNET_TUN_UdpHeader *) &ipv4[1];
2723 /* swap ports, as they are from the original message */
2724 destination_port = ntohs (udp->source_port);
2725 source_port = ntohs (udp->destination_port);
2726 /* throw away ICMP payload, won't be useful for the other side anyway */
2727 pktlen = sizeof(struct GNUNET_TUN_IcmpHeader);
2728 break;
2729
2730 default:
2731 GNUNET_STATISTICS_update (stats,
2732 gettext_noop (
2733 "# ICMPv4 packets dropped (type not allowed)"),
2734 1, GNUNET_NO);
2735 return;
2736 }
2737 break;
2738
2739 case AF_INET6:
2740 protocol = IPPROTO_ICMPV6;
2741 switch (icmp->type)
2742 {
2743 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2744 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2745 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2746 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2747 if (pktlen <
2748 sizeof(struct GNUNET_TUN_IcmpHeader)
2749 + sizeof(struct GNUNET_TUN_IPv6Header) + 8)
2750 {
2751 /* blame kernel */
2752 GNUNET_break (0);
2753 return;
2754 }
2755 ipv6 = (const struct GNUNET_TUN_IPv6Header *) &icmp[1];
2756 protocol = ipv6->next_header;
2757 /* could be TCP or UDP, but both have the ports in the right
2758 place, so that doesn't matter here */
2759 udp = (const struct GNUNET_TUN_UdpHeader *) &ipv6[1];
2760 /* swap ports, as they are from the original message */
2761 destination_port = ntohs (udp->source_port);
2762 source_port = ntohs (udp->destination_port);
2763 /* throw away ICMP payload, won't be useful for the other side anyway */
2764 pktlen = sizeof(struct GNUNET_TUN_IcmpHeader);
2765 break;
2766
2767 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2768 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2769 break;
2770
2771 default:
2772 GNUNET_STATISTICS_update (stats,
2773 gettext_noop (
2774 "# ICMPv6 packets dropped (type not allowed)"),
2775 1, GNUNET_NO);
2776 return;
2777 }
2778 break;
2779
2780 default:
2781 GNUNET_assert (0);
2782 }
2783 switch (protocol)
2784 {
2785 case IPPROTO_ICMP:
2786 state = get_redirect_state (af,
2787 IPPROTO_ICMP,
2788 source_ip,
2789 0,
2790 destination_ip,
2791 0,
2792 NULL);
2793 break;
2794
2795 case IPPROTO_ICMPV6:
2796 state = get_redirect_state (af,
2797 IPPROTO_ICMPV6,
2798 source_ip,
2799 0,
2800 destination_ip,
2801 0,
2802 NULL);
2803 break;
2804
2805 case IPPROTO_UDP:
2806 state = get_redirect_state (af,
2807 IPPROTO_UDP,
2808 source_ip,
2809 source_port,
2810 destination_ip,
2811 destination_port,
2812 NULL);
2813 break;
2814
2815 case IPPROTO_TCP:
2816 state = get_redirect_state (af,
2817 IPPROTO_TCP,
2818 source_ip,
2819 source_port,
2820 destination_ip,
2821 destination_port,
2822 NULL);
2823 break;
2824
2825 default:
2826 GNUNET_STATISTICS_update (stats,
2827 gettext_noop (
2828 "# ICMP packets dropped (not allowed)"),
2829 1,
2830 GNUNET_NO);
2831 return;
2832 }
2833 if (NULL == state)
2834 {
2835 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2836 _ (
2837 "ICMP Packet dropped, have no matching connection information\n"));
2838 return;
2839 }
2840 env = GNUNET_MQ_msg_extra (i2v,
2841 pktlen - sizeof(struct GNUNET_TUN_IcmpHeader),
2842 GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN);
2843 i2v->af = htonl (af);
2844 GNUNET_memcpy (&i2v->icmp_header,
2845 icmp,
2846 pktlen);
2847 send_packet_to_cadet_channel (state,
2848 env);
2849}
2850
2851
2852/**
2853 * @brief Handles an UDP packet received from the helper.
2854 *
2855 * @param udp A pointer to the Packet
2856 * @param pktlen number of bytes in 'udp'
2857 * @param af address family (AFINET or AF_INET6)
2858 * @param destination_ip destination IP-address of the IP packet (should
2859 * be our local address)
2860 * @param source_ip original source IP-address of the IP packet (should
2861 * be the original destination address)
2862 */
2863static void
2864udp_from_helper (const struct GNUNET_TUN_UdpHeader *udp,
2865 size_t pktlen,
2866 int af,
2867 const void *destination_ip,
2868 const void *source_ip)
2869{
2870 struct ChannelState *state;
2871 struct GNUNET_MQ_Envelope *env;
2872 struct GNUNET_EXIT_UdpReplyMessage *urm;
2873
2874 {
2875 char sbuf[INET6_ADDRSTRLEN];
2876 char dbuf[INET6_ADDRSTRLEN];
2877
2878 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2879 "Received UDP packet going from %s:%u to %s:%u\n",
2880 inet_ntop (af,
2881 source_ip,
2882 sbuf, sizeof(sbuf)),
2883 (unsigned int) ntohs (udp->source_port),
2884 inet_ntop (af,
2885 destination_ip,
2886 dbuf, sizeof(dbuf)),
2887 (unsigned int) ntohs (udp->destination_port));
2888 }
2889
2890 if (pktlen < sizeof(struct GNUNET_TUN_UdpHeader))
2891 {
2892 /* blame kernel */
2893 GNUNET_break (0);
2894 return;
2895 }
2896 if (pktlen != ntohs (udp->len))
2897 {
2898 /* blame kernel */
2899 GNUNET_break (0);
2900 return;
2901 }
2902 state = get_redirect_state (af,
2903 IPPROTO_UDP,
2904 source_ip,
2905 ntohs (udp->source_port),
2906 destination_ip,
2907 ntohs (udp->destination_port),
2908 NULL);
2909 if (NULL == state)
2910 {
2911 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2912 _ (
2913 "UDP Packet dropped, have no matching connection information\n"));
2914 return;
2915 }
2916 env = GNUNET_MQ_msg_extra (urm,
2917 pktlen - sizeof(struct GNUNET_TUN_UdpHeader),
2918 GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY);
2919 urm->source_port = htons (0);
2920 urm->destination_port = htons (0);
2921 GNUNET_memcpy (&urm[1],
2922 &udp[1],
2923 pktlen - sizeof(struct GNUNET_TUN_UdpHeader));
2924 send_packet_to_cadet_channel (state,
2925 env);
2926}
2927
2928
2929/**
2930 * @brief Handles a TCP packet received from the helper.
2931 *
2932 * @param tcp A pointer to the Packet
2933 * @param pktlen the length of the packet, including its TCP header
2934 * @param af address family (AFINET or AF_INET6)
2935 * @param destination_ip destination IP-address of the IP packet (should
2936 * be our local address)
2937 * @param source_ip original source IP-address of the IP packet (should
2938 * be the original destination address)
2939 */
2940static void
2941tcp_from_helper (const struct GNUNET_TUN_TcpHeader *tcp,
2942 size_t pktlen,
2943 int af,
2944 const void *destination_ip,
2945 const void *source_ip)
2946{
2947 struct ChannelState *state;
2948 char buf[pktlen] GNUNET_ALIGN;
2949 struct GNUNET_TUN_TcpHeader *mtcp;
2950 struct GNUNET_EXIT_TcpDataMessage *tdm;
2951 struct GNUNET_MQ_Envelope *env;
2952 size_t mlen;
2953
2954 {
2955 char sbuf[INET6_ADDRSTRLEN];
2956 char dbuf[INET6_ADDRSTRLEN];
2957 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2958 "Received TCP packet with %u bytes going from %s:%u to %s:%u\n",
2959 (unsigned int) (pktlen - sizeof(struct GNUNET_TUN_TcpHeader)),
2960 inet_ntop (af,
2961 source_ip,
2962 sbuf, sizeof(sbuf)),
2963 (unsigned int) ntohs (tcp->source_port),
2964 inet_ntop (af,
2965 destination_ip,
2966 dbuf, sizeof(dbuf)),
2967 (unsigned int) ntohs (tcp->destination_port));
2968 }
2969
2970 if (pktlen < sizeof(struct GNUNET_TUN_TcpHeader))
2971 {
2972 /* blame kernel */
2973 GNUNET_break (0);
2974 return;
2975 }
2976 state = get_redirect_state (af,
2977 IPPROTO_TCP,
2978 source_ip,
2979 ntohs (tcp->source_port),
2980 destination_ip,
2981 ntohs (tcp->destination_port),
2982 NULL);
2983 if (NULL == state)
2984 {
2985 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2986 _ (
2987 "TCP Packet dropped, have no matching connection information\n"));
2988
2989 return;
2990 }
2991 /* mug port numbers and crc to avoid information leakage;
2992 sender will need to lookup the correct values anyway */
2993 GNUNET_memcpy (buf, tcp, pktlen);
2994 mtcp = (struct GNUNET_TUN_TcpHeader *) buf;
2995 mtcp->source_port = 0;
2996 mtcp->destination_port = 0;
2997 mtcp->crc = 0;
2998
2999 mlen = sizeof(struct GNUNET_EXIT_TcpDataMessage) + (pktlen - sizeof(struct
3000 GNUNET_TUN_TcpHeader));
3001 if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
3002 {
3003 GNUNET_break (0);
3004 return;
3005 }
3006 env = GNUNET_MQ_msg_extra (tdm,
3007 pktlen - sizeof(struct GNUNET_TUN_TcpHeader),
3008 GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN);
3009 tdm->reserved = htonl (0);
3010 GNUNET_memcpy (&tdm->tcp_header,
3011 buf,
3012 pktlen);
3013 send_packet_to_cadet_channel (state,
3014 env);
3015}
3016
3017
3018/**
3019 * Receive packets from the helper-process
3020 *
3021 * @param cls unused
3022 * @param message message received from helper
3023 */
3024static int
3025message_token (void *cls GNUNET_UNUSED,
3026 const struct GNUNET_MessageHeader *message)
3027{
3028 const struct GNUNET_TUN_Layer2PacketHeader *pkt_tun;
3029 size_t size;
3030
3031 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3032 "Got %u-byte message of type %u from gnunet-helper-exit\n",
3033 ntohs (message->size),
3034 ntohs (message->type));
3035 GNUNET_STATISTICS_update (stats,
3036 gettext_noop ("# Packets received from TUN"),
3037 1, GNUNET_NO);
3038 if (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER)
3039 {
3040 GNUNET_break (0);
3041 return GNUNET_OK;
3042 }
3043 size = ntohs (message->size);
3044 if (size < sizeof(struct GNUNET_TUN_Layer2PacketHeader) + sizeof(struct
3045 GNUNET_MessageHeader))
3046 {
3047 GNUNET_break (0);
3048 return GNUNET_OK;
3049 }
3050 GNUNET_STATISTICS_update (stats,
3051 gettext_noop ("# Bytes received from TUN"),
3052 size, GNUNET_NO);
3053 pkt_tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
3054 size -= sizeof(struct GNUNET_TUN_Layer2PacketHeader) + sizeof(struct
3055 GNUNET_MessageHeader);
3056 switch (ntohs (pkt_tun->proto))
3057 {
3058 case ETH_P_IPV4:
3059 {
3060 const struct GNUNET_TUN_IPv4Header *pkt4;
3061
3062 if (size < sizeof(struct GNUNET_TUN_IPv4Header))
3063 {
3064 /* Kernel to blame? */
3065 GNUNET_break (0);
3066 return GNUNET_OK;
3067 }
3068 pkt4 = (const struct GNUNET_TUN_IPv4Header *) &pkt_tun[1];
3069 if (size != ntohs (pkt4->total_length))
3070 {
3071 /* Kernel to blame? */
3072 GNUNET_break (0);
3073 return GNUNET_OK;
3074 }
3075 if (pkt4->header_length * 4 != sizeof(struct GNUNET_TUN_IPv4Header))
3076 {
3077 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3078 _ ("IPv4 packet options received. Ignored.\n"));
3079 return GNUNET_OK;
3080 }
3081
3082 size -= sizeof(struct GNUNET_TUN_IPv4Header);
3083 switch (pkt4->protocol)
3084 {
3085 case IPPROTO_UDP:
3086 udp_from_helper ((const struct GNUNET_TUN_UdpHeader *) &pkt4[1], size,
3087 AF_INET,
3088 &pkt4->destination_address,
3089 &pkt4->source_address);
3090 break;
3091
3092 case IPPROTO_TCP:
3093 tcp_from_helper ((const struct GNUNET_TUN_TcpHeader *) &pkt4[1], size,
3094 AF_INET,
3095 &pkt4->destination_address,
3096 &pkt4->source_address);
3097 break;
3098
3099 case IPPROTO_ICMP:
3100 icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt4[1], size,
3101 AF_INET,
3102 &pkt4->destination_address,
3103 &pkt4->source_address);
3104 break;
3105
3106 default:
3107 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3108 _ (
3109 "IPv4 packet with unsupported next header %u received. Ignored.\n"),
3110 (int) pkt4->protocol);
3111 return GNUNET_OK;
3112 }
3113 }
3114 break;
3115
3116 case ETH_P_IPV6:
3117 {
3118 const struct GNUNET_TUN_IPv6Header *pkt6;
3119
3120 if (size < sizeof(struct GNUNET_TUN_IPv6Header))
3121 {
3122 /* Kernel to blame? */
3123 GNUNET_break (0);
3124 return GNUNET_OK;
3125 }
3126 pkt6 = (struct GNUNET_TUN_IPv6Header *) &pkt_tun[1];
3127 if (size != ntohs (pkt6->payload_length) + sizeof(struct
3128 GNUNET_TUN_IPv6Header))
3129 {
3130 /* Kernel to blame? */
3131 GNUNET_break (0);
3132 return GNUNET_OK;
3133 }
3134 size -= sizeof(struct GNUNET_TUN_IPv6Header);
3135 switch (pkt6->next_header)
3136 {
3137 case IPPROTO_UDP:
3138 udp_from_helper ((const struct GNUNET_TUN_UdpHeader *) &pkt6[1], size,
3139 AF_INET6,
3140 &pkt6->destination_address,
3141 &pkt6->source_address);
3142 break;
3143
3144 case IPPROTO_TCP:
3145 tcp_from_helper ((const struct GNUNET_TUN_TcpHeader *) &pkt6[1], size,
3146 AF_INET6,
3147 &pkt6->destination_address,
3148 &pkt6->source_address);
3149 break;
3150
3151 case IPPROTO_ICMPV6:
3152 icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt6[1], size,
3153 AF_INET6,
3154 &pkt6->destination_address,
3155 &pkt6->source_address);
3156 break;
3157
3158 default:
3159 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3160 _ (
3161 "IPv6 packet with unsupported next header %d received. Ignored.\n"),
3162 pkt6->next_header);
3163 return GNUNET_OK;
3164 }
3165 }
3166 break;
3167
3168 default:
3169 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3170 _ ("Packet from unknown protocol %u received. Ignored.\n"),
3171 ntohs (pkt_tun->proto));
3172 break;
3173 }
3174 return GNUNET_OK;
3175}
3176
3177
3178/**
3179 * Callback from CADET for new channels.
3180 *
3181 * @param cls closure
3182 * @param channel new handle to the channel
3183 * @param initiator peer that started the channel
3184 * @return initial channel context for the channel
3185 */
3186static void *
3187new_channel (void *cls,
3188 struct GNUNET_CADET_Channel *channel,
3189 const struct GNUNET_PeerIdentity *initiator)
3190{
3191 struct ChannelState *s = GNUNET_new (struct ChannelState);
3192
3193 s->is_dns = GNUNET_SYSERR;
3194 s->peer = *initiator;
3195 GNUNET_STATISTICS_update (stats,
3196 gettext_noop ("# Inbound CADET channels created"),
3197 1,
3198 GNUNET_NO);
3199 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3200 "Received inbound channel from `%s'\n",
3201 GNUNET_i2s (initiator));
3202 s->channel = channel;
3203 return s;
3204}
3205
3206
3207/**
3208 * Function that frees everything from a hashmap
3209 *
3210 * @param cls unused
3211 * @param hash key
3212 * @param value value to free
3213 */
3214static int
3215free_iterate (void *cls,
3216 const struct GNUNET_HashCode *hash,
3217 void *value)
3218{
3219 GNUNET_free (value);
3220 return GNUNET_YES;
3221}
3222
3223
3224/**
3225 * Function scheduled as very last function if the service
3226 * disabled itself because the helper is not installed
3227 * properly. Does nothing, except for keeping the
3228 * service process alive by virtue of being scheduled.
3229 *
3230 * @param cls NULL
3231 */
3232static void
3233dummy_task (void *cls)
3234{
3235 /* just terminate */
3236}
3237
3238
3239/**
3240 * Function scheduled as very last function, cleans up after us
3241 *
3242 * @param cls NULL
3243 */
3244static void
3245cleanup (void *cls)
3246{
3247 unsigned int i;
3248
3249 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3250 "Exit service is shutting down now\n");
3251
3252 if (NULL != helper_handle)
3253 {
3254 GNUNET_HELPER_stop (helper_handle, GNUNET_NO);
3255 helper_handle = NULL;
3256 }
3257 if (NULL != regex4)
3258 {
3259 GNUNET_REGEX_announce_cancel (regex4);
3260 regex4 = NULL;
3261 }
3262 if (NULL != regex6)
3263 {
3264 GNUNET_REGEX_announce_cancel (regex6);
3265 regex6 = NULL;
3266 }
3267 if (NULL != services)
3268 {
3269 GNUNET_CONTAINER_multihashmap_iterate (services,
3270 &free_service_record,
3271 NULL);
3272 GNUNET_CONTAINER_multihashmap_destroy (services);
3273 }
3274 if (NULL != dns_port)
3275 {
3276 GNUNET_CADET_close_port (dns_port);
3277 dns_port = NULL;
3278 }
3279 if (NULL != cadet_port4)
3280 {
3281 GNUNET_CADET_close_port (cadet_port4);
3282 cadet_port4 = NULL;
3283 }
3284 if (NULL != cadet_port6)
3285 {
3286 GNUNET_CADET_close_port (cadet_port6);
3287 cadet_port6 = NULL;
3288 }
3289 if (NULL != cadet_handle)
3290 {
3291 GNUNET_CADET_disconnect (cadet_handle);
3292 cadet_handle = NULL;
3293 }
3294 if (NULL != connections_map)
3295 {
3296 GNUNET_CONTAINER_multihashmap_iterate (connections_map,
3297 &free_iterate,
3298 NULL);
3299 GNUNET_CONTAINER_multihashmap_destroy (connections_map);
3300 connections_map = NULL;
3301 }
3302 if (NULL != connections_heap)
3303 {
3304 GNUNET_CONTAINER_heap_destroy (connections_heap);
3305 connections_heap = NULL;
3306 }
3307 if (NULL != dnsstub)
3308 {
3309 GNUNET_DNSSTUB_stop (dnsstub);
3310 dnsstub = NULL;
3311 }
3312 if (NULL != peer_key)
3313 {
3314 GNUNET_free (peer_key);
3315 peer_key = NULL;
3316 }
3317 if (NULL != dht_task)
3318 {
3319 GNUNET_SCHEDULER_cancel (dht_task);
3320 dht_task = NULL;
3321 }
3322 if (NULL != dht_put)
3323 {
3324 GNUNET_DHT_put_cancel (dht_put);
3325 dht_put = NULL;
3326 }
3327 if (NULL != dht)
3328 {
3329 GNUNET_DHT_disconnect (dht);
3330 dht = NULL;
3331 }
3332 if (NULL != stats)
3333 {
3334 GNUNET_STATISTICS_destroy (stats,
3335 GNUNET_NO);
3336 stats = NULL;
3337 }
3338 for (i = 0; i < 8; i++)
3339 GNUNET_free (exit_argv[i]);
3340}
3341
3342
3343/**
3344 * Add services to the service map.
3345 *
3346 * @param proto IPPROTO_TCP or IPPROTO_UDP
3347 * @param cpy copy of the service descriptor (can be mutilated)
3348 * @param name DNS name of the service
3349 */
3350static void
3351add_services (int proto,
3352 char *cpy,
3353 const char *name)
3354{
3355 char *redirect;
3356 char *hostname;
3357 char *hostport;
3358 struct LocalService *serv;
3359 char *n;
3360 size_t slen;
3361
3362 slen = strlen (name);
3363 GNUNET_assert (slen >= 8);
3364 n = GNUNET_strndup (name, slen - 8 /* remove .gnunet. */);
3365
3366 for (redirect = strtok (cpy, " ;"); redirect != NULL;
3367 redirect = strtok (NULL, " ;"))
3368 {
3369 if (NULL == (hostname = strstr (redirect, ":")))
3370 {
3371 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3372 _ (
3373 "Option `%s' for domain `%s' is not formatted correctly!\n"),
3374 redirect,
3375 name);
3376 continue;
3377 }
3378 hostname[0] = '\0';
3379 hostname++;
3380 if (NULL == (hostport = strstr (hostname, ":")))
3381 {
3382 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3383 _ (
3384 "Option `%s' for domain `%s' is not formatted correctly!\n"),
3385 redirect,
3386 name);
3387 continue;
3388 }
3389 hostport[0] = '\0';
3390 hostport++;
3391
3392 int local_port = atoi (redirect);
3393 int remote_port = atoi (hostport);
3394
3395 if (! ((local_port > 0) && (local_port < 65536)))
3396 {
3397 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3398 _ ("`%s' is not a valid port number (for domain `%s')!"),
3399 redirect,
3400 name);
3401 continue;
3402 }
3403 if (! ((remote_port > 0) && (remote_port < 65536)))
3404 {
3405 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3406 _ ("`%s' is not a valid port number (for domain `%s')!"),
3407 hostport,
3408 name);
3409 continue;
3410 }
3411
3412 serv = GNUNET_new (struct LocalService);
3413 serv->address.proto = proto;
3414 serv->address.port = remote_port;
3415 if (0 == strcmp ("localhost4",
3416 hostname))
3417 {
3418 const char *ip4addr = exit_argv[5];
3419
3420 serv->address.af = AF_INET;
3421 GNUNET_assert (1 == inet_pton (AF_INET,
3422 ip4addr,
3423 &serv->address.address.ipv4));
3424 }
3425 else if (0 == strcmp ("localhost6",
3426 hostname))
3427 {
3428 const char *ip6addr = exit_argv[3];
3429
3430 serv->address.af = AF_INET6;
3431 GNUNET_assert (1 == inet_pton (AF_INET6,
3432 ip6addr,
3433 &serv->address.address.ipv6));
3434 }
3435 else
3436 {
3437 struct addrinfo *res;
3438 int ret;
3439
3440 ret = getaddrinfo (hostname,
3441 NULL,
3442 NULL,
3443 &res);
3444 if ((0 != ret) || (NULL == res))
3445 {
3446 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3447 _ (
3448 "No addresses found for hostname `%s' of service `%s'!\n"),
3449 hostname,
3450 n);
3451 GNUNET_free (serv);
3452 continue;
3453 }
3454
3455 serv->address.af = res->ai_family;
3456 switch (res->ai_family)
3457 {
3458 case AF_INET:
3459 if (! ipv4_enabled)
3460 {
3461 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3462 _ (
3463 "Service `%s' configured for IPv4, but IPv4 is disabled!\n"),
3464 n);
3465 freeaddrinfo (res);
3466 GNUNET_free (serv);
3467 continue;
3468 }
3469 serv->address.address.ipv4
3470 = ((struct sockaddr_in *) res->ai_addr)->sin_addr;
3471 break;
3472
3473 case AF_INET6:
3474 if (! ipv6_enabled)
3475 {
3476 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3477 _ (
3478 "Service `%s' configured for IPv4, but IPv4 is disabled!\n"),
3479 n);
3480 freeaddrinfo (res);
3481 GNUNET_free (serv);
3482 continue;
3483 }
3484 serv->address.address.ipv6
3485 = ((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
3486 break;
3487
3488 default:
3489 freeaddrinfo (res);
3490 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3491 _ (
3492 "No IP addresses found for hostname `%s' of service `%s'!\n"),
3493 hostname,
3494 n);
3495 GNUNET_free (serv);
3496 continue;
3497 }
3498 freeaddrinfo (res);
3499 }
3500 store_service (proto,
3501 n,
3502 local_port,
3503 serv);
3504 }
3505 GNUNET_free (n);
3506}
3507
3508
3509/**
3510 * Reads the configuration and populates #udp_services and #tcp_services
3511 *
3512 * @param cls unused
3513 * @param section name of section in config
3514 */
3515static void
3516read_service_conf (void *cls,
3517 const char *section)
3518{
3519 char *cpy;
3520
3521 if ((strlen (section) < 8) ||
3522 (0 != strcmp (".gnunet.", section + (strlen (section) - 8))))
3523 return;
3524 if (GNUNET_OK ==
3525 GNUNET_CONFIGURATION_get_value_string (cfg,
3526 section,
3527 "UDP_REDIRECTS",
3528 &cpy))
3529 {
3530 add_services (IPPROTO_UDP,
3531 cpy,
3532 section);
3533 GNUNET_free (cpy);
3534 }
3535 if (GNUNET_OK ==
3536 GNUNET_CONFIGURATION_get_value_string (cfg,
3537 section,
3538 "TCP_REDIRECTS",
3539 &cpy))
3540 {
3541 add_services (IPPROTO_TCP,
3542 cpy,
3543 section);
3544 GNUNET_free (cpy);
3545 }
3546}
3547
3548
3549/**
3550 * We are running a DNS exit service, advertise it in the
3551 * DHT. This task is run periodically to do the DHT PUT.
3552 *
3553 * @param cls closure
3554 */
3555static void
3556do_dht_put (void *cls);
3557
3558
3559/**
3560 * Function called when the DHT PUT operation is complete.
3561 * Schedules the next PUT.
3562 *
3563 * @param cls closure, NULL
3564 */
3565static void
3566dht_put_cont (void *cls)
3567{
3568 dht_put = NULL;
3569}
3570
3571
3572/**
3573 * We are running a DNS exit service, advertise it in the
3574 * DHT. This task is run periodically to do the DHT PUT.
3575 *
3576 * @param cls closure
3577 */
3578static void
3579do_dht_put (void *cls)
3580{
3581 struct GNUNET_TIME_Absolute expiration;
3582
3583 dht_task = GNUNET_SCHEDULER_add_delayed (DHT_PUT_FREQUENCY,
3584 &do_dht_put,
3585 NULL);
3586 expiration = GNUNET_TIME_absolute_ntoh (dns_advertisement.expiration_time);
3587 if (GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us <
3588 GNUNET_TIME_UNIT_HOURS.rel_value_us)
3589 {
3590 /* refresh advertisement */
3591 expiration = GNUNET_TIME_relative_to_absolute (DNS_ADVERTISEMENT_TIMEOUT);
3592 dns_advertisement.expiration_time = GNUNET_TIME_absolute_hton (expiration);
3593 GNUNET_assert (GNUNET_OK ==
3594 GNUNET_CRYPTO_eddsa_sign_ (peer_key,
3595 &dns_advertisement.purpose,
3596 &dns_advertisement.signature));
3597 }
3598 if (NULL != dht_put)
3599 GNUNET_DHT_put_cancel (dht_put);
3600 dht_put = GNUNET_DHT_put (dht,
3601 &dht_put_key,
3602 1 /* replication */,
3603 GNUNET_DHT_RO_NONE,
3604 GNUNET_BLOCK_TYPE_DNS,
3605 sizeof(struct GNUNET_DNS_Advertisement),
3606 &dns_advertisement,
3607 expiration,
3608 &dht_put_cont,
3609 NULL);
3610}
3611
3612
3613/**
3614 * Figure out which IP versions we should support (and which
3615 * are supported by the OS) according to our configuration.
3616 */
3617static void
3618parse_ip_options ()
3619{
3620 ipv4_exit = GNUNET_CONFIGURATION_get_value_yesno (cfg,
3621 "exit",
3622 "EXIT_IPV4");
3623 ipv6_exit = GNUNET_CONFIGURATION_get_value_yesno (cfg,
3624 "exit",
3625 "EXIT_IPV6");
3626 ipv4_enabled = GNUNET_CONFIGURATION_get_value_yesno (cfg,
3627 "exit",
3628 "ENABLE_IPV4");
3629 ipv6_enabled = GNUNET_CONFIGURATION_get_value_yesno (cfg,
3630 "exit",
3631 "ENABLE_IPV6");
3632 if ((ipv4_exit || ipv4_enabled) &&
3633 (GNUNET_OK != GNUNET_NETWORK_test_pf (PF_INET)) )
3634 {
3635 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3636 _ (
3637 "This system does not support IPv4, will disable IPv4 functions despite them being enabled in the configuration\n"));
3638 ipv4_exit = GNUNET_NO;
3639 ipv4_enabled = GNUNET_NO;
3640 }
3641 if ((ipv6_exit || ipv6_enabled) &&
3642 (GNUNET_OK != GNUNET_NETWORK_test_pf (PF_INET6)) )
3643 {
3644 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3645 _ (
3646 "This system does not support IPv6, will disable IPv6 functions despite them being enabled in the configuration\n"));
3647 ipv6_exit = GNUNET_NO;
3648 ipv6_enabled = GNUNET_NO;
3649 }
3650 if (ipv4_exit && (! ipv4_enabled))
3651 {
3652 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3653 _ (
3654 "Cannot enable IPv4 exit but disable IPv4 on TUN interface, will use ENABLE_IPv4=YES\n"));
3655 ipv4_enabled = GNUNET_YES;
3656 }
3657 if (ipv6_exit && (! ipv6_enabled))
3658 {
3659 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3660 _ (
3661 "Cannot enable IPv6 exit but disable IPv6 on TUN interface, will use ENABLE_IPv6=YES\n"));
3662 ipv6_enabled = GNUNET_YES;
3663 }
3664}
3665
3666
3667/**
3668 * Helper function to open the CADET port for DNS exits and to
3669 * advertise the DNS exit (if applicable).
3670 */
3671static void
3672advertise_dns_exit ()
3673{
3674 struct GNUNET_MQ_MessageHandler handlers[] = {
3675 GNUNET_MQ_hd_var_size (dns_request,
3676 GNUNET_MESSAGE_TYPE_VPN_DNS_TO_INTERNET,
3677 struct DnsResponseMessage,
3678 NULL),
3679 GNUNET_MQ_handler_end ()
3680 };
3681 char *dns_exit;
3682 struct GNUNET_HashCode port;
3683
3684 if (GNUNET_YES !=
3685 GNUNET_CONFIGURATION_get_value_yesno (cfg,
3686 "exit",
3687 "EXIT_DNS"))
3688 return;
3689 GNUNET_assert (NULL != (dnsstub = GNUNET_DNSSTUB_start (128)));
3690 dns_exit = NULL;
3691 /* TODO: support using multiple DNS resolvers */
3692 if ((GNUNET_OK !=
3693 GNUNET_CONFIGURATION_get_value_string (cfg,
3694 "exit",
3695 "DNS_RESOLVER",
3696 &dns_exit)) ||
3697 (GNUNET_OK !=
3698 GNUNET_DNSSTUB_add_dns_ip (dnsstub,
3699 dns_exit)))
3700 {
3701 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
3702 "dns",
3703 "DNS_RESOLVER",
3704 _ ("need a valid IPv4 or IPv6 address\n"));
3705 GNUNET_free (dns_exit);
3706 return;
3707 }
3708 /* open port */
3709 GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_INTERNET_RESOLVER,
3710 strlen (GNUNET_APPLICATION_PORT_INTERNET_RESOLVER),
3711 &port);
3712 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3713 "Opening CADET port %s for DNS exit service\n",
3714 GNUNET_h2s (&port));
3715 dns_port = GNUNET_CADET_open_port (cadet_handle,
3716 &port,
3717 &new_channel,
3718 NULL,
3719 NULL,
3720 &clean_channel,
3721 handlers);
3722 /* advertise exit */
3723 dht = GNUNET_DHT_connect (cfg,
3724 1);
3725 peer_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg);
3726 GNUNET_CRYPTO_eddsa_key_get_public (peer_key,
3727 &dns_advertisement.peer.public_key);
3728 dns_advertisement.purpose.size = htonl (sizeof(struct
3729 GNUNET_DNS_Advertisement)
3730 - sizeof(struct
3731 GNUNET_CRYPTO_EddsaSignature));
3732 dns_advertisement.purpose.purpose = htonl (
3733 GNUNET_SIGNATURE_PURPOSE_DNS_RECORD);
3734 GNUNET_CRYPTO_hash ("dns",
3735 strlen ("dns"),
3736 &dht_put_key);
3737 dht_task = GNUNET_SCHEDULER_add_now (&do_dht_put,
3738 NULL);
3739 GNUNET_free (dns_exit);
3740}
3741
3742
3743/**
3744 * Initialize #exit_argv.
3745 *
3746 * @return #GNUNET_OK on success, #GNUNET_SYSERR if we should shutdown
3747 */
3748static int
3749setup_exit_helper_args ()
3750{
3751 char *exit_ifname;
3752 char *tun_ifname;
3753 char *ipv6addr;
3754 char *ipv6prefix_s;
3755 char *ipv4addr;
3756 char *ipv4mask;
3757
3758 exit_argv[0] = GNUNET_strdup ("exit-gnunet");
3759 if (GNUNET_SYSERR ==
3760 GNUNET_CONFIGURATION_get_value_string (cfg,
3761 "exit",
3762 "TUN_IFNAME",
3763 &tun_ifname))
3764 {
3765 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
3766 "EXIT",
3767 "TUN_IFNAME");
3768 return GNUNET_SYSERR;
3769 }
3770 exit_argv[1] = tun_ifname;
3771 if (ipv4_enabled)
3772 {
3773 if (GNUNET_SYSERR ==
3774 GNUNET_CONFIGURATION_get_value_string (cfg,
3775 "exit",
3776 "EXIT_IFNAME",
3777 &exit_ifname))
3778 {
3779 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
3780 "EXIT",
3781 "EXIT_IFNAME");
3782 return GNUNET_SYSERR;
3783 }
3784 exit_argv[2] = exit_ifname;
3785 }
3786 else
3787 {
3788 exit_argv[2] = GNUNET_strdup ("-");
3789 }
3790
3791 if (GNUNET_YES == ipv6_enabled)
3792 {
3793 ipv6addr = NULL;
3794 if (((GNUNET_SYSERR ==
3795 GNUNET_CONFIGURATION_get_value_string (cfg,
3796 "exit",
3797 "IPV6ADDR",
3798 &ipv6addr)) ||
3799 (1 != inet_pton (AF_INET6,
3800 ipv6addr,
3801 &exit_ipv6addr))))
3802 {
3803 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
3804 "EXIT",
3805 "IPV6ADDR");
3806 GNUNET_free (ipv6addr);
3807 return GNUNET_SYSERR;
3808 }
3809 exit_argv[3] = ipv6addr;
3810 if (GNUNET_SYSERR ==
3811 GNUNET_CONFIGURATION_get_value_string (cfg,
3812 "exit",
3813 "IPV6PREFIX",
3814 &ipv6prefix_s))
3815 {
3816 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
3817 "EXIT",
3818 "IPV6PREFIX");
3819 return GNUNET_SYSERR;
3820 }
3821 exit_argv[4] = ipv6prefix_s;
3822 if ((GNUNET_OK !=
3823 GNUNET_CONFIGURATION_get_value_number (cfg,
3824 "exit",
3825 "IPV6PREFIX",
3826 &ipv6prefix)) ||
3827 (ipv6prefix >= 127))
3828 {
3829 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
3830 "EXIT",
3831 "IPV6PREFIX",
3832 _ ("Must be a number"));
3833 return GNUNET_SYSERR;
3834 }
3835 }
3836 else
3837 {
3838 /* IPv6 explicitly disabled */
3839 exit_argv[3] = GNUNET_strdup ("-");
3840 exit_argv[4] = GNUNET_strdup ("-");
3841 }
3842 if (GNUNET_YES == ipv4_enabled)
3843 {
3844 ipv4addr = NULL;
3845 if (((GNUNET_SYSERR ==
3846 GNUNET_CONFIGURATION_get_value_string (cfg,
3847 "exit",
3848 "IPV4ADDR",
3849 &ipv4addr)) ||
3850 (1 != inet_pton (AF_INET,
3851 ipv4addr,
3852 &exit_ipv4addr))))
3853 {
3854 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
3855 "EXIT",
3856 "IPV4ADDR");
3857 GNUNET_free (ipv4addr);
3858 return GNUNET_SYSERR;
3859 }
3860 exit_argv[5] = ipv4addr;
3861 ipv4mask = NULL;
3862 if (((GNUNET_SYSERR ==
3863 GNUNET_CONFIGURATION_get_value_string (cfg,
3864 "exit",
3865 "IPV4MASK",
3866 &ipv4mask)) ||
3867 (1 != inet_pton (AF_INET,
3868 ipv4mask,
3869 &exit_ipv4mask))))
3870 {
3871 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
3872 "EXIT",
3873 "IPV4MASK");
3874 GNUNET_free (ipv4mask);
3875 return GNUNET_SYSERR;
3876 }
3877 exit_argv[6] = ipv4mask;
3878 }
3879 else
3880 {
3881 /* IPv4 explicitly disabled */
3882 exit_argv[5] = GNUNET_strdup ("-");
3883 exit_argv[6] = GNUNET_strdup ("-");
3884 }
3885 exit_argv[7] = NULL;
3886 return GNUNET_OK;
3887}
3888
3889
3890/**
3891 * @brief Main function that will be run by the scheduler.
3892 *
3893 * @param cls closure
3894 * @param args remaining command-line arguments
3895 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
3896 * @param cfg_ configuration
3897 */
3898static void
3899run (void *cls,
3900 char *const *args,
3901 const char *cfgfile,
3902 const struct GNUNET_CONFIGURATION_Handle *cfg_)
3903{
3904 struct GNUNET_MQ_MessageHandler handlers[] = {
3905 GNUNET_MQ_hd_var_size (icmp_remote,
3906 GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET,
3907 struct GNUNET_EXIT_IcmpInternetMessage,
3908 NULL),
3909 GNUNET_MQ_hd_var_size (udp_remote,
3910 GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET,
3911 struct GNUNET_EXIT_UdpInternetMessage,
3912 NULL),
3913 GNUNET_MQ_hd_var_size (tcp_remote,
3914 GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START,
3915 struct GNUNET_EXIT_TcpInternetStartMessage,
3916 NULL),
3917 GNUNET_MQ_hd_var_size (tcp_data,
3918 GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT,
3919 struct GNUNET_EXIT_TcpDataMessage,
3920 NULL),
3921 GNUNET_MQ_handler_end ()
3922 };
3923 struct GNUNET_HashCode port;
3924 char *policy;
3925 char *binary;
3926 char *regex;
3927 char *prefixed_regex;
3928
3929 cfg = cfg_;
3930 if (GNUNET_OK !=
3931 GNUNET_CONFIGURATION_get_value_number (cfg,
3932 "exit",
3933 "MAX_CONNECTIONS",
3934 &max_connections))
3935 max_connections = 1024;
3936 parse_ip_options ();
3937 binary = GNUNET_OS_get_suid_binary_path (cfg, "gnunet-helper-exit");
3938 if ((ipv4_exit) || (ipv6_exit))
3939 {
3940 if (GNUNET_YES !=
3941 GNUNET_OS_check_helper_binary (binary,
3942 GNUNET_YES,
3943 "gnunet-vpn - - - 169.1.3.7 255.255.255.0")) // no nat, ipv4 only
3944 {
3945 GNUNET_free (binary);
3946 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3947 _ (
3948 "`%s' is not SUID or the path is invalid, EXIT will not work\n"),
3949 "gnunet-helper-exit");
3950 GNUNET_SCHEDULER_add_shutdown (&dummy_task,
3951 NULL);
3952 global_ret = 1;
3953 return;
3954 }
3955 }
3956 if (! (ipv4_enabled || ipv6_enabled))
3957 {
3958 GNUNET_free (binary);
3959 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3960 _ ("No useful service enabled. Exiting.\n"));
3961 GNUNET_SCHEDULER_shutdown ();
3962 return;
3963 }
3964
3965 GNUNET_SCHEDULER_add_shutdown (&cleanup,
3966 NULL);
3967 stats = GNUNET_STATISTICS_create ("exit",
3968 cfg);
3969 cadet_handle = GNUNET_CADET_connect (cfg);
3970 if (NULL == cadet_handle)
3971 {
3972 GNUNET_free (binary);
3973 GNUNET_SCHEDULER_shutdown ();
3974 return;
3975 }
3976 advertise_dns_exit ();
3977 if (GNUNET_OK !=
3978 setup_exit_helper_args ())
3979 {
3980 GNUNET_free (binary);
3981 GNUNET_SCHEDULER_shutdown ();
3982 return;
3983 }
3984
3985 services = GNUNET_CONTAINER_multihashmap_create (65536,
3986 GNUNET_NO);
3987 connections_map = GNUNET_CONTAINER_multihashmap_create (65536,
3988 GNUNET_NO);
3989 connections_heap = GNUNET_CONTAINER_heap_create (
3990 GNUNET_CONTAINER_HEAP_ORDER_MIN);
3991 GNUNET_CONFIGURATION_iterate_sections (cfg,
3992 &read_service_conf,
3993 NULL);
3994
3995 /* Cadet handle acquired, now open ports and announce regular
3996 expressions matching our exit */
3997 if ((GNUNET_YES == ipv4_enabled) &&
3998 (GNUNET_YES == ipv4_exit))
3999 {
4000 GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_IPV4_GATEWAY,
4001 strlen (GNUNET_APPLICATION_PORT_IPV4_GATEWAY),
4002 &port);
4003 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4004 "Opening CADET port %s for IPv4 gateway service\n",
4005 GNUNET_h2s (&port));
4006 cadet_port4 = GNUNET_CADET_open_port (cadet_handle,
4007 &port,
4008 &new_channel,
4009 NULL,
4010 NULL,
4011 &clean_channel,
4012 handlers);
4013 policy = NULL;
4014 if (GNUNET_OK !=
4015 GNUNET_CONFIGURATION_get_value_string (cfg,
4016 "exit",
4017 "EXIT_RANGE_IPV4_POLICY",
4018 &policy))
4019 regex = NULL;
4020 else
4021 regex = GNUNET_TUN_ipv4policy2regex (policy);
4022 GNUNET_free (policy);
4023 if (NULL != regex)
4024 {
4025 (void) GNUNET_asprintf (&prefixed_regex,
4026 "%s%s",
4027 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
4028 regex);
4029 regex4 = GNUNET_REGEX_announce (cfg,
4030 prefixed_regex,
4031 REGEX_REFRESH_FREQUENCY,
4032 REGEX_MAX_PATH_LEN_IPV4);
4033 GNUNET_free (regex);
4034 GNUNET_free (prefixed_regex);
4035 }
4036 }
4037
4038 if ((GNUNET_YES == ipv6_enabled) && (GNUNET_YES == ipv6_exit))
4039 {
4040 GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_IPV6_GATEWAY,
4041 strlen (GNUNET_APPLICATION_PORT_IPV6_GATEWAY),
4042 &port);
4043 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4044 "Opening CADET port %s for IPv6 gateway service\n",
4045 GNUNET_h2s (&port));
4046 cadet_port6 = GNUNET_CADET_open_port (cadet_handle,
4047 &port,
4048 &new_channel,
4049 NULL,
4050 NULL,
4051 &clean_channel,
4052 handlers);
4053 policy = NULL;
4054 if (GNUNET_OK !=
4055 GNUNET_CONFIGURATION_get_value_string (cfg,
4056 "exit",
4057 "EXIT_RANGE_IPV6_POLICY",
4058 &policy))
4059 regex = NULL;
4060 else
4061 regex = GNUNET_TUN_ipv6policy2regex (policy);
4062 GNUNET_free (policy);
4063 if (NULL != regex)
4064 {
4065 (void) GNUNET_asprintf (&prefixed_regex,
4066 "%s%s",
4067 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
4068 regex);
4069 regex6 = GNUNET_REGEX_announce (cfg,
4070 prefixed_regex,
4071 REGEX_REFRESH_FREQUENCY,
4072 REGEX_MAX_PATH_LEN_IPV6);
4073 GNUNET_free (regex);
4074 GNUNET_free (prefixed_regex);
4075 }
4076 }
4077 helper_handle = GNUNET_HELPER_start (GNUNET_NO,
4078 binary,
4079 exit_argv,
4080 &message_token,
4081 NULL,
4082 NULL);
4083 GNUNET_free (binary);
4084}
4085
4086
4087/**
4088 * The main function
4089 *
4090 * @param argc number of arguments from the command line
4091 * @param argv command line arguments
4092 * @return 0 ok, 1 on error
4093 */
4094int
4095main (int argc,
4096 char *const *argv)
4097{
4098 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
4099 GNUNET_GETOPT_OPTION_END
4100 };
4101
4102 if (GNUNET_OK !=
4103 GNUNET_STRINGS_get_utf8_args (argc,
4104 argv,
4105 &argc,
4106 &argv))
4107 return 2;
4108
4109 return (GNUNET_OK ==
4110 GNUNET_PROGRAM_run (argc,
4111 argv,
4112 "gnunet-daemon-exit",
4113 gettext_noop (
4114 "Daemon to run to provide an IP exit node for the VPN"),
4115 options,
4116 &run,
4117 NULL)) ? global_ret : 1;
4118}
4119
4120
4121/* end of gnunet-daemon-exit.c */