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