GNUnet debian-0.24.3-29-g453fda2cf
 
Loading...
Searching...
No Matches
gnunet-daemon-exit.c File Reference

tool to allow IP traffic exit from the GNUnet cadet to the Internet More...

#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_protocols.h"
#include "gnunet_applications.h"
#include "gnunet_dht_service.h"
#include "gnunet_cadet_service.h"
#include "gnunet_statistics_service.h"
#include "gnunet_signatures.h"
#include "gnunet_regex_service.h"
#include "exit.h"
#include "block_dns.h"
Include dependency graph for gnunet-daemon-exit.c:

Go to the source code of this file.

Data Structures

struct  SocketAddress
 Information about an address. More...
 
struct  LocalService
 This struct is saved into the services-hashmap to represent a service this peer is specifically offering an exit for (for a specific domain name). More...
 
struct  RedirectInformation
 Information we use to track a connection (the classical 6-tuple of IP-version, protocol, source-IP, destination-IP, source-port and destinatin-port. More...
 
struct  ChannelState
 This struct is saved into connections_map to allow finding the right channel given an IP packet from TUN. More...
 
struct  DnsResponseMessage
 Message with a DNS response. More...
 

Macros

#define REGEX_MAX_PATH_LEN_IPV4   4
 Maximum path compression length for cadet regex announcing for IPv4 address based regex.
 
#define REGEX_MAX_PATH_LEN_IPV6   8
 Maximum path compression length for cadet regex announcing for IPv6 address based regex.
 
#define REGEX_REFRESH_FREQUENCY
 How frequently do we re-announce the regex for the exit?
 
#define DHT_PUT_FREQUENCY
 How frequently do we re-announce the DNS exit in the DHT?
 
#define DNS_ADVERTISEMENT_TIMEOUT
 How long do we typically sign the DNS exit advertisement for?
 
#define LOG(kind, ...)    GNUNET_log_from (kind, "exit", __VA_ARGS__);
 Generic logging shorthand.
 

Functions

static GNUNET_NETWORK_STRUCT_END void process_dns_result (void *cls, const struct GNUNET_TUN_DnsHeader *dns, size_t r)
 Callback called from DNSSTUB resolver when a resolution succeeded.
 
static int check_dns_request (void *cls, const struct DnsResponseMessage *msg)
 Check a request via cadet to perform a DNS query.
 
static void handle_dns_request (void *cls, const struct DnsResponseMessage *msg)
 Process a request via cadet to perform a DNS query.
 
static void hash_redirect_info (struct GNUNET_HashCode *hash, const struct RedirectInformation *ri)
 Given IP information about a connection, calculate the respective hash we would use for the connections_map.
 
static struct ChannelStateget_redirect_state (int af, int protocol, const void *destination_ip, uint16_t destination_port, const void *local_ip, uint16_t local_port, struct GNUNET_HashCode *state_key)
 Get our connection tracking state.
 
static int check_tcp_service (void *cls, const struct GNUNET_EXIT_TcpServiceStartMessage *start)
 Check a request via cadet to send a request to a TCP service offered by this system.
 
static void prepare_ipv4_packet (const void *payload, size_t payload_length, int protocol, const struct GNUNET_TUN_TcpHeader *tcp_header, const struct SocketAddress *src_address, const struct SocketAddress *dst_address, struct GNUNET_TUN_IPv4Header *pkt4)
 Prepare an IPv4 packet for transmission via the TUN interface.
 
static void prepare_ipv6_packet (const void *payload, size_t payload_length, int protocol, const struct GNUNET_TUN_TcpHeader *tcp_header, const struct SocketAddress *src_address, const struct SocketAddress *dst_address, struct GNUNET_TUN_IPv6Header *pkt6)
 Prepare an IPv6 packet for transmission via the TUN interface.
 
static void send_tcp_packet_via_tun (const struct SocketAddress *destination_address, const struct SocketAddress *source_address, const struct GNUNET_TUN_TcpHeader *tcp_header, const void *payload, size_t payload_length)
 Send a TCP packet via the TUN interface.
 
static void send_icmp_packet_via_tun (const struct SocketAddress *destination_address, const struct SocketAddress *source_address, const struct GNUNET_TUN_IcmpHeader *icmp_header, const void *payload, size_t payload_length)
 Send an ICMP packet via the TUN interface.
 
static void setup_fresh_address (int af, uint8_t proto, struct SocketAddress *local_address)
 We need to create a (unique) fresh local address (IP+port).
 
static void setup_state_record (struct ChannelState *state)
 We are starting a fresh connection (TCP or UDP) and need to pick a source port and IP address (within the correct range and address family) to associate replies with the connection / correct cadet channel.
 
static void send_udp_packet_via_tun (const struct SocketAddress *destination_address, const struct SocketAddress *source_address, const void *payload, size_t payload_length)
 Send a UDP packet via the TUN interface.
 
static int check_udp_remote (void *cls, const struct GNUNET_EXIT_UdpInternetMessage *msg)
 Check a request to forward UDP data to the Internet via this peer.
 
static void handle_udp_remote (void *cls, const struct GNUNET_EXIT_UdpInternetMessage *msg)
 Process a request to forward UDP data to the Internet via this peer.
 
static int check_udp_service (void *cls, const struct GNUNET_EXIT_UdpServiceMessage *msg)
 Check a request via cadet to send a request to a UDP service offered by this system.
 
static void handle_udp_service (void *cls, const struct GNUNET_EXIT_UdpServiceMessage *msg)
 Process a request via cadet to send a request to a UDP service offered by this system.
 
static void handle_tcp_service (void *cls, const struct GNUNET_EXIT_TcpServiceStartMessage *start)
 Process a request via cadet to send a request to a TCP service offered by this system.
 
static int check_tcp_remote (void *cls, const struct GNUNET_EXIT_TcpInternetStartMessage *start)
 Check a request to forward TCP data to the Internet via this peer.
 
static void handle_tcp_remote (void *cls, const struct GNUNET_EXIT_TcpInternetStartMessage *start)
 Process a request to forward TCP data to the Internet via this peer.
 
static int check_tcp_data (void *cls, const struct GNUNET_EXIT_TcpDataMessage *data)
 Check a request to forward TCP data on an established connection via this peer.
 
static void handle_tcp_data (void *cls, const struct GNUNET_EXIT_TcpDataMessage *data)
 Process a request to forward TCP data on an established connection via this peer.
 
static void make_up_icmpv4_payload (struct ChannelState *state, struct GNUNET_TUN_IPv4Header *ipp, struct GNUNET_TUN_UdpHeader *udp)
 Synthesize a plausible ICMP payload for an ICMPv4 error response on the given channel.
 
static void make_up_icmpv6_payload (struct ChannelState *state, struct GNUNET_TUN_IPv6Header *ipp, struct GNUNET_TUN_UdpHeader *udp)
 Synthesize a plausible ICMP payload for an ICMPv6 error response on the given channel.
 
static int check_icmp_remote (void *cls, const struct GNUNET_EXIT_IcmpInternetMessage *msg)
 Check a request to forward ICMP data to the Internet via this peer.
 
static void handle_icmp_remote (void *cls, const struct GNUNET_EXIT_IcmpInternetMessage *msg)
 Process a request to forward ICMP data to the Internet via this peer.
 
static uint16_t make_up_icmp_service_payload (struct ChannelState *state, char *buf)
 Setup ICMP payload for ICMP error messages.
 
static int check_icmp_service (void *cls, const struct GNUNET_EXIT_IcmpServiceMessage *msg)
 Check a request via cadet to send ICMP data to a service offered by this system.
 
static void handle_icmp_service (void *cls, const struct GNUNET_EXIT_IcmpServiceMessage *msg)
 Process a request via cadet to send ICMP data to a service offered by this system.
 
static int free_service_record (void *cls, const struct GNUNET_HashCode *key, void *value)
 Free memory associated with a service record.
 
static void * new_service_channel (void *cls, struct GNUNET_CADET_Channel *channel, const struct GNUNET_PeerIdentity *initiator)
 Callback from CADET for new channels.
 
static void clean_channel (void *cls, const struct GNUNET_CADET_Channel *channel)
 Function called by cadet whenever an inbound channel is destroyed.
 
static void store_service (int proto, const char *name, uint16_t destination_port, struct LocalService *service)
 Given a service descriptor and a destination port, find the respective service entry.
 
static void send_packet_to_cadet_channel (struct ChannelState *s, struct GNUNET_MQ_Envelope *env)
 Send the given packet via the cadet channel.
 
static void icmp_from_helper (const struct GNUNET_TUN_IcmpHeader *icmp, size_t pktlen, int af, const void *destination_ip, const void *source_ip)
 Handles an ICMP packet received from the helper.
 
static void udp_from_helper (const struct GNUNET_TUN_UdpHeader *udp, size_t pktlen, int af, const void *destination_ip, const void *source_ip)
 Handles an UDP packet received from the helper.
 
static void tcp_from_helper (const struct GNUNET_TUN_TcpHeader *tcp, size_t pktlen, int af, const void *destination_ip, const void *source_ip)
 Handles a TCP packet received from the helper.
 
static int message_token (void *cls, const struct GNUNET_MessageHeader *message)
 Receive packets from the helper-process.
 
static void * new_channel (void *cls, struct GNUNET_CADET_Channel *channel, const struct GNUNET_PeerIdentity *initiator)
 Callback from CADET for new channels.
 
static int free_iterate (void *cls, const struct GNUNET_HashCode *hash, void *value)
 Function that frees everything from a hashmap.
 
static void dummy_task (void *cls)
 Function scheduled as very last function if the service disabled itself because the helper is not installed properly.
 
static void cleanup (void *cls)
 Function scheduled as very last function, cleans up after us.
 
static void add_services (int proto, char *cpy, const char *name)
 Add services to the service map.
 
static void read_service_conf (void *cls, const char *section)
 Reads the configuration and populates #udp_services and #tcp_services.
 
static void do_dht_put (void *cls)
 We are running a DNS exit service, advertise it in the DHT.
 
static void dht_put_cont (void *cls)
 Function called when the DHT PUT operation is complete.
 
static void parse_ip_options ()
 Figure out which IP versions we should support (and which are supported by the OS) according to our configuration.
 
static void advertise_dns_exit ()
 Helper function to open the CADET port for DNS exits and to advertise the DNS exit (if applicable).
 
static int setup_exit_helper_args ()
 Initialize exit_argv.
 
static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg_)
 Main function that will be run by the scheduler.
 
int main (int argc, char *const *argv)
 The main function.
 

Variables

static int global_ret
 Return value from 'main'.
 
static struct GNUNET_REGEX_Announcementregex4
 Handle to our regex announcement for IPv4.
 
static struct GNUNET_REGEX_Announcementregex6
 Handle to our regex announcement for IPv4.
 
static const struct GNUNET_CONFIGURATION_Handlecfg
 The handle to the configuration used throughout the process.
 
static struct GNUNET_HELPER_Handlehelper_handle
 The handle to the helper.
 
static char * exit_argv [8]
 Arguments to the exit helper.
 
static struct in6_addr exit_ipv6addr
 IPv6 address of our TUN interface.
 
static unsigned long long ipv6prefix
 IPv6 prefix (0..127) from configuration file.
 
static struct in_addr exit_ipv4addr
 IPv4 address of our TUN interface.
 
static struct in_addr exit_ipv4mask
 IPv4 netmask of our TUN interface.
 
static struct GNUNET_STATISTICS_Handlestats
 Statistics.
 
static struct GNUNET_CADET_Handlecadet_handle
 The handle to cadet.
 
static struct GNUNET_CONTAINER_MultiHashMapconnections_map
 This hashmaps contains the mapping from peer, service-descriptor, source-port and destination-port to a struct ChannelState.
 
static struct GNUNET_CONTAINER_Heapconnections_heap
 Heap so we can quickly find "old" connections.
 
static unsigned long long max_connections
 If there are at least this many connections, old ones will be removed.
 
static struct GNUNET_CONTAINER_MultiHashMapservices
 This hashmaps saves interesting things about the configured services.
 
static struct ChannelStatechannels [UINT16_MAX+1]
 Array of all open DNS requests from channels.
 
static struct GNUNET_DNSSTUB_Contextdnsstub
 Handle to the DNS Stub resolver.
 
static struct GNUNET_DHT_PutHandledht_put
 Handle for ongoing DHT PUT operations to advertise exit service.
 
static struct GNUNET_DHT_Handledht
 Handle to the DHT.
 
static struct GNUNET_SCHEDULER_Taskdht_task
 Task for doing DHT PUTs to advertise exit service.
 
static struct GNUNET_DNS_Advertisement dns_advertisement
 Advertisement message we put into the DHT to advertise us as a DNS exit.
 
static struct GNUNET_HashCode dht_put_key
 Key we store the DNS advertismenet under.
 
static struct GNUNET_CRYPTO_EddsaPrivateKeypeer_key
 Private key for this peer.
 
static struct GNUNET_CADET_Portdns_port
 Port for DNS exit.
 
static struct GNUNET_CADET_Portcadet_port4
 Port for IPv4 exit.
 
static struct GNUNET_CADET_Portcadet_port6
 Port for IPv6 exit.
 
static int ipv4_exit
 Are we an IPv4-exit?
 
static int ipv6_exit
 Are we an IPv6-exit?
 
static int ipv4_enabled
 Do we support IPv4 at all on the TUN interface?
 
static int ipv6_enabled
 Do we support IPv6 at all on the TUN interface?
 

Detailed Description

tool to allow IP traffic exit from the GNUnet cadet to the Internet

Author
Philipp Toelke
Christian Grothoff

TODO:

  • test

Design:

  • which code should advertise services? the service model is right now a bit odd, especially as this code DOES the exit and knows the DNS "name", but OTOH this is clearly NOT the place to advertise the service's existence; maybe the daemon should turn into a service with an API to add local-exit services dynamically?

Definition in file gnunet-daemon-exit.c.

Macro Definition Documentation

◆ REGEX_MAX_PATH_LEN_IPV4

#define REGEX_MAX_PATH_LEN_IPV4   4

Maximum path compression length for cadet regex announcing for IPv4 address based regex.

Definition at line 54 of file gnunet-daemon-exit.c.

◆ REGEX_MAX_PATH_LEN_IPV6

#define REGEX_MAX_PATH_LEN_IPV6   8

Maximum path compression length for cadet regex announcing for IPv6 address based regex.

Definition at line 60 of file gnunet-daemon-exit.c.

◆ REGEX_REFRESH_FREQUENCY

#define REGEX_REFRESH_FREQUENCY
Value:
#define GNUNET_TIME_UNIT_MINUTES
One minute.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition time.c:486

How frequently do we re-announce the regex for the exit?

Definition at line 65 of file gnunet-daemon-exit.c.

91{
95 int af;
96
100 union
101 {
105 struct in_addr ipv4;
106
110 struct in6_addr ipv6;
111 } address;
112
116 uint8_t proto;
117
121 uint16_t port;
122};
123
124
130struct LocalService
131{
135 struct SocketAddress address;
136
141
145 char *name;
146
150 struct GNUNET_CADET_Port *port;
151
155 int16_t is_udp;
156};
157
158
165{
171
178
179 /*
180 Note 1: additional information might be added here in the
181 future to support protocols that require special handling,
182 such as ftp/tftp
183
184 Note 2: we might also sometimes not match on all components
185 of the tuple, to support protocols where things do not always
186 fully map.
187 */
188};
189
190
197struct ChannelState
198{
203
209
215 int is_dns;
216
217 union
218 {
219 struct
220 {
225
230
234 struct LocalService *serv;
235
239 struct RedirectInformation ri;
240 } tcp_udp;
241
242 struct
243 {
249
253 uint16_t original_id;
254
258 uint16_t my_id;
259 } dns;
260 } specifics;
261};
262
263
267static int global_ret;
268
272static struct GNUNET_REGEX_Announcement *regex4;
273
277static struct GNUNET_REGEX_Announcement *regex6;
278
282static const struct GNUNET_CONFIGURATION_Handle *cfg;
283
288
292static char *exit_argv[8];
293
297static struct in6_addr exit_ipv6addr;
298
302static unsigned long long ipv6prefix;
303
307static struct in_addr exit_ipv4addr;
308
312static struct in_addr exit_ipv4mask;
313
317static struct GNUNET_STATISTICS_Handle *stats;
318
322static struct GNUNET_CADET_Handle *cadet_handle;
323
329
334
338static unsigned long long max_connections;
339
344
348static struct ChannelState *channels[UINT16_MAX + 1];
349
353static struct GNUNET_DNSSTUB_Context *dnsstub;
354
358static struct GNUNET_DHT_PutHandle *dht_put;
359
363static struct GNUNET_DHT_Handle *dht;
364
368static struct GNUNET_SCHEDULER_Task *dht_task;
369
375
379static struct GNUNET_HashCode dht_put_key;
380
385
389static struct GNUNET_CADET_Port *dns_port;
390
394static struct GNUNET_CADET_Port *cadet_port4;
395
399static struct GNUNET_CADET_Port *cadet_port6;
400
404static int ipv4_exit;
405
409static int ipv6_exit;
410
414static int ipv4_enabled;
415
419static int ipv6_enabled;
420
421
423
428{
433
438
439 /* Followed by more DNS payload */
440};
441
443
444
453static void
454process_dns_result (void *cls,
455 const struct GNUNET_TUN_DnsHeader *dns,
456 size_t r)
457{
458 struct ChannelState *ts;
459 struct GNUNET_MQ_Envelope *env;
460 struct DnsResponseMessage *resp;
461
463 "Processing DNS result from stub resolver\n");
464 GNUNET_assert (NULL == cls);
465 if (NULL == dns)
466 return;
467 /* Handle case that this is a reply to a request from a CADET DNS channel */
468 ts = channels[dns->id];
469 if (NULL == ts)
470 return;
472 "Got a response from the stub resolver for DNS request received via CADET!\n");
473 channels[dns->id] = NULL;
474 env = GNUNET_MQ_msg_extra (resp,
475 r - sizeof(struct GNUNET_TUN_DnsHeader),
477 GNUNET_memcpy (&resp->dns,
478 dns,
479 r);
480 resp->dns.id = ts->specifics.dns.original_id;
482 env);
483}
484
485
494static int
495check_dns_request (void *cls,
496 const struct DnsResponseMessage *msg)
497{
498 struct ChannelState *ts = cls;
499
500 if (NULL == dnsstub)
501 {
502 GNUNET_break (0);
503 return GNUNET_SYSERR;
504 }
505 if (GNUNET_NO == ts->is_dns)
506 {
507 GNUNET_break_op (0);
508 return GNUNET_SYSERR;
509 }
510 return GNUNET_OK;
511}
512
513
520static void
521handle_dns_request (void *cls,
522 const struct DnsResponseMessage *msg)
523{
524 struct ChannelState *ts = cls;
525 size_t mlen = ntohs (msg->header.size);
526 size_t dlen = mlen - sizeof(struct GNUNET_MessageHeader);
527 char buf[dlen] GNUNET_ALIGN;
528 struct GNUNET_TUN_DnsHeader *dns_out;
529
530 if (GNUNET_SYSERR == ts->is_dns)
531 {
532 /* channel is DNS from now on */
533 ts->is_dns = GNUNET_YES;
534 }
535 ts->specifics.dns.original_id = msg->dns.id;
536 if (channels[ts->specifics.dns.my_id] == ts)
537 channels[ts->specifics.dns.my_id] = NULL;
540 UINT16_MAX
541 + 1);
542 channels[ts->specifics.dns.my_id] = ts;
543 GNUNET_memcpy (buf,
544 &msg->dns,
545 dlen);
546 dns_out = (struct GNUNET_TUN_DnsHeader *) buf;
547 dns_out->id = ts->specifics.dns.my_id;
549 buf,
550 dlen,
552 NULL);
553 if (NULL == ts->specifics.dns.rs)
554 {
555 GNUNET_break_op (0);
556 return;
557 }
559}
560
561
569static void
571 const struct RedirectInformation *ri)
572{
573 char *off;
574
575 memset (hash,
576 0,
577 sizeof(struct GNUNET_HashCode));
578 /* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash,
579 so we put the IP address in there (and hope for few collisions) */
580 off = (char *) hash;
581 switch (ri->remote_address.af)
582 {
583 case AF_INET:
584 GNUNET_memcpy (off,
586 sizeof(struct in_addr));
587 off += sizeof(struct in_addr);
588 break;
589
590 case AF_INET6:
591 GNUNET_memcpy (off,
593 sizeof(struct in6_addr));
594 off += sizeof(struct in_addr);
595 break;
596
597 default:
598 GNUNET_assert (0);
599 }
600 GNUNET_memcpy (off,
601 &ri->remote_address.port,
602 sizeof(uint16_t));
603 off += sizeof(uint16_t);
604 switch (ri->local_address.af)
605 {
606 case AF_INET:
607 GNUNET_memcpy (off,
609 sizeof(struct in_addr));
610 off += sizeof(struct in_addr);
611 break;
612
613 case AF_INET6:
614 GNUNET_memcpy (off,
616 sizeof(struct in6_addr));
617 off += sizeof(struct in_addr);
618 break;
619
620 default:
621 GNUNET_assert (0);
622 }
623 GNUNET_memcpy (off,
624 &ri->local_address.port,
625 sizeof(uint16_t));
626 off += sizeof(uint16_t);
627 GNUNET_memcpy (off,
629 sizeof(uint8_t));
630 /* off += sizeof (uint8_t); */
631}
632
633
647static struct ChannelState *
649 int protocol,
650 const void *destination_ip,
651 uint16_t destination_port,
652 const void *local_ip,
653 uint16_t local_port,
655{
656 struct RedirectInformation ri;
657 struct GNUNET_HashCode key;
658 struct ChannelState *state;
659
660 if (((af == AF_INET) && (protocol == IPPROTO_ICMP)) ||
661 ((af == AF_INET6) && (protocol == IPPROTO_ICMPV6)))
662 {
663 /* ignore ports */
665 local_port = 0;
666 }
668 if (af == AF_INET)
669 ri.remote_address.address.ipv4 = *((struct in_addr*) destination_ip);
670 else
671 ri.remote_address.address.ipv6 = *((struct in6_addr*) destination_ip);
672 ri.remote_address.port = destination_port;
673 ri.remote_address.proto = protocol;
674 ri.local_address.af = af;
675 if (af == AF_INET)
676 ri.local_address.address.ipv4 = *((struct in_addr*) local_ip);
677 else
678 ri.local_address.address.ipv6 = *((struct in6_addr*) local_ip);
679 ri.local_address.port = local_port;
680 ri.local_address.proto = protocol;
682 &ri);
683 if (NULL != state_key)
684 *state_key = key;
686 &key);
687 if (NULL == state)
688 return NULL;
689 /* Mark this connection as freshly used */
690 if (NULL == state_key)
691 GNUNET_CONTAINER_heap_update_cost (state->specifics.tcp_udp.heap_node,
692 GNUNET_TIME_absolute_get ().abs_value_us)
693 ;
694 return state;
695}
696
697
707static int
708check_tcp_service (void *cls,
710{
711 struct ChannelState *state = cls;
712
713 if (NULL == state)
714 {
715 GNUNET_break_op (0);
716 return GNUNET_SYSERR;
717 }
718 if (GNUNET_YES == state->is_dns)
719 {
720 GNUNET_break_op (0);
721 return GNUNET_SYSERR;
722 }
723 if (NULL == state->specifics.tcp_udp.serv)
724 {
725 GNUNET_break_op (0);
726 return GNUNET_SYSERR;
727 }
728 if (NULL != state->specifics.tcp_udp.heap_node)
729 {
730 GNUNET_break_op (0);
731 return GNUNET_SYSERR;
732 }
733 if (start->tcp_header.off * 4 < sizeof(struct GNUNET_TUN_TcpHeader))
734 {
735 GNUNET_break_op (0);
736 return GNUNET_SYSERR;
737 }
738 return GNUNET_OK;
739}
740
741
760static void
761prepare_ipv4_packet (const void *payload,
762 size_t payload_length,
763 int protocol,
764 const struct GNUNET_TUN_TcpHeader *tcp_header,
765 const struct SocketAddress *src_address,
766 const struct SocketAddress *dst_address,
767 struct GNUNET_TUN_IPv4Header *pkt4)
768{
769 size_t len;
770
771 len = payload_length;
772 switch (protocol)
773 {
774 case IPPROTO_UDP:
775 len += sizeof(struct GNUNET_TUN_UdpHeader);
776 break;
777
778 case IPPROTO_TCP:
779 len += sizeof(struct GNUNET_TUN_TcpHeader);
780 GNUNET_assert (NULL != tcp_header);
781 break;
782
783 default:
784 GNUNET_break (0);
785 return;
786 }
787 if (len + sizeof(struct GNUNET_TUN_IPv4Header) > UINT16_MAX)
788 {
789 GNUNET_break (0);
790 return;
791 }
792
794 protocol,
795 len,
796 &src_address->address.ipv4,
797 &dst_address->address.ipv4);
798 switch (protocol)
799 {
800 case IPPROTO_UDP:
801 {
802 struct GNUNET_TUN_UdpHeader *pkt4_udp = (struct
803 GNUNET_TUN_UdpHeader *) &pkt4[1];
804
805 pkt4_udp->source_port = htons (src_address->port);
806 pkt4_udp->destination_port = htons (dst_address->port);
807 pkt4_udp->len = htons ((uint16_t) payload_length);
809 pkt4_udp,
810 payload,
811 payload_length);
812 GNUNET_memcpy (&pkt4_udp[1],
813 payload,
814 payload_length);
815 }
816 break;
817
818 case IPPROTO_TCP:
819 {
820 struct GNUNET_TUN_TcpHeader *pkt4_tcp = (struct
822
823 *pkt4_tcp = *tcp_header;
825 "Sending TCP packet from port %u to port %u\n",
826 src_address->port,
827 dst_address->port);
828 pkt4_tcp->source_port = htons (src_address->port);
829 pkt4_tcp->destination_port = htons (dst_address->port);
831 pkt4_tcp,
832 payload,
833 payload_length);
835 payload,
836 payload_length);
837 }
838 break;
839
840 default:
841 GNUNET_assert (0);
842 }
843}
844
845
864static void
865prepare_ipv6_packet (const void *payload,
866 size_t payload_length,
867 int protocol,
868 const struct GNUNET_TUN_TcpHeader *tcp_header,
869 const struct SocketAddress *src_address,
870 const struct SocketAddress *dst_address,
872{
873 size_t len;
874
875 len = payload_length;
876 switch (protocol)
877 {
878 case IPPROTO_UDP:
879 len += sizeof(struct GNUNET_TUN_UdpHeader);
880 break;
881
882 case IPPROTO_TCP:
883 len += sizeof(struct GNUNET_TUN_TcpHeader);
884 break;
885
886 default:
887 GNUNET_break (0);
888 return;
889 }
890 if (len > UINT16_MAX)
891 {
892 GNUNET_break (0);
893 return;
894 }
895
897 protocol,
898 len,
899 &src_address->address.ipv6,
900 &dst_address->address.ipv6);
901
902 switch (protocol)
903 {
904 case IPPROTO_UDP:
905 {
906 struct GNUNET_TUN_UdpHeader *pkt6_udp = (struct
907 GNUNET_TUN_UdpHeader *) &pkt6[1];
908
909 pkt6_udp->source_port = htons (src_address->port);
910 pkt6_udp->destination_port = htons (dst_address->port);
911 pkt6_udp->len = htons ((uint16_t) payload_length);
913 pkt6_udp,
914 payload,
915 payload_length);
916 GNUNET_memcpy (&pkt6_udp[1],
917 payload,
918 payload_length);
919 }
920 break;
921
922 case IPPROTO_TCP:
923 {
924 struct GNUNET_TUN_TcpHeader *pkt6_tcp = (struct
926
927 /* GNUNET_memcpy first here as some TCP header fields are initialized this way! */
928 *pkt6_tcp = *tcp_header;
930 pkt6_tcp->destination_port = htons (dst_address->port);
932 pkt6_tcp,
933 payload,
934 payload_length);
936 payload,
937 payload_length);
938 }
939 break;
940
941 default:
942 GNUNET_assert (0);
943 break;
944 }
945}
946
947
957static void
958send_tcp_packet_via_tun (const struct SocketAddress *destination_address,
959 const struct SocketAddress *source_address,
960 const struct GNUNET_TUN_TcpHeader *tcp_header,
961 const void *payload,
962 size_t payload_length)
963{
964 size_t len;
965
967 gettext_noop ("# TCP packets sent via TUN"),
968 1,
969 GNUNET_NO);
971 "Sending packet with %u bytes TCP payload via TUN\n",
972 (unsigned int) payload_length);
973 len = sizeof(struct GNUNET_MessageHeader) + sizeof(struct
975 switch (source_address->af)
976 {
977 case AF_INET:
978 len += sizeof(struct GNUNET_TUN_IPv4Header);
979 break;
980
981 case AF_INET6:
982 len += sizeof(struct GNUNET_TUN_IPv6Header);
983 break;
984
985 default:
986 GNUNET_break (0);
987 return;
988 }
989 len += sizeof(struct GNUNET_TUN_TcpHeader);
990 len += payload_length;
991 if (len >= GNUNET_MAX_MESSAGE_SIZE)
992 {
993 GNUNET_break (0);
994 return;
995 }
996 {
997 char buf[len] GNUNET_ALIGN;
998 struct GNUNET_MessageHeader *hdr;
1000
1001 hdr = (struct GNUNET_MessageHeader *) buf;
1002 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1003 hdr->size = htons (len);
1004 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
1005 tun->flags = htons (0);
1006 switch (source_address->af)
1007 {
1008 case AF_INET:
1009 {
1011 = (struct GNUNET_TUN_IPv4Header*) &tun[1];
1012
1013 tun->proto = htons (ETH_P_IPV4);
1015 payload_length,
1016 IPPROTO_TCP,
1017 tcp_header,
1020 ipv4);
1021 }
1022 break;
1023
1024 case AF_INET6:
1025 {
1027 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
1028
1029 tun->proto = htons (ETH_P_IPV6);
1032 IPPROTO_TCP,
1033 tcp_header,
1036 ipv6);
1037 }
1038 break;
1039
1040 default:
1041 GNUNET_assert (0);
1042 break;
1043 }
1044 if (NULL != helper_handle)
1046 (const struct GNUNET_MessageHeader*) buf,
1047 GNUNET_YES,
1048 NULL,
1049 NULL);
1050 }
1051}
1052
1053
1063static void
1065 const struct SocketAddress *source_address,
1066 const struct GNUNET_TUN_IcmpHeader *icmp_header,
1067 const void *payload, size_t payload_length)
1068{
1069 size_t len;
1070 struct GNUNET_TUN_IcmpHeader *icmp;
1071
1073 gettext_noop ("# ICMP packets sent via TUN"),
1074 1, GNUNET_NO);
1076 "Sending packet with %u bytes ICMP payload via TUN\n",
1077 (unsigned int) payload_length);
1078 len = sizeof(struct GNUNET_MessageHeader) + sizeof(struct
1080 switch (destination_address->af)
1081 {
1082 case AF_INET:
1083 len += sizeof(struct GNUNET_TUN_IPv4Header);
1084 break;
1085
1086 case AF_INET6:
1087 len += sizeof(struct GNUNET_TUN_IPv6Header);
1088 break;
1089
1090 default:
1091 GNUNET_break (0);
1092 return;
1093 }
1094 len += sizeof(struct GNUNET_TUN_IcmpHeader);
1095 len += payload_length;
1096 if (len >= GNUNET_MAX_MESSAGE_SIZE)
1097 {
1098 GNUNET_break (0);
1099 return;
1100 }
1101 {
1102 char buf[len] GNUNET_ALIGN;
1103 struct GNUNET_MessageHeader *hdr;
1105
1106 hdr = (struct GNUNET_MessageHeader *) buf;
1107 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1108 hdr->size = htons (len);
1109 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
1110 tun->flags = htons (0);
1111 switch (source_address->af)
1112 {
1113 case AF_INET:
1114 {
1115 struct GNUNET_TUN_IPv4Header *ipv4 = (struct
1116 GNUNET_TUN_IPv4Header*) &tun[1];
1117
1118 tun->proto = htons (ETH_P_IPV4);
1120 IPPROTO_ICMP,
1121 sizeof(struct
1123 + payload_length,
1124 &source_address->address.ipv4,
1125 &destination_address->address.ipv4);
1126 icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv4[1];
1127 }
1128 break;
1129
1130 case AF_INET6:
1131 {
1132 struct GNUNET_TUN_IPv6Header *ipv6 = (struct
1133 GNUNET_TUN_IPv6Header*) &tun[1];
1134
1135 tun->proto = htons (ETH_P_IPV6);
1137 IPPROTO_ICMPV6,
1138 sizeof(struct
1141 &source_address->address.ipv6,
1142 &destination_address->address.ipv6);
1143 icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv6[1];
1144 }
1145 break;
1146
1147 default:
1148 GNUNET_assert (0);
1149 break;
1150 }
1151 *icmp = *icmp_header;
1152 GNUNET_memcpy (&icmp[1],
1153 payload,
1154 payload_length);
1156 payload,
1157 payload_length);
1158 if (NULL != helper_handle)
1160 (const struct GNUNET_MessageHeader*) buf,
1161 GNUNET_YES,
1162 NULL, NULL);
1163 }
1164}
1165
1166
1175static void
1176setup_fresh_address (int af,
1177 uint8_t proto,
1178 struct SocketAddress *local_address)
1179{
1180 local_address->af = af;
1181 local_address->proto = (uint8_t) proto;
1182 /* default "local" port range is often 32768--61000,
1183 so we pick a random value in that range */
1184 if (((af == AF_INET) && (proto == IPPROTO_ICMP)) ||
1185 ((af == AF_INET6) && (proto == IPPROTO_ICMPV6)))
1186 local_address->port = 0;
1187 else
1188 local_address->port
1190 28232);
1191 switch (af)
1192 {
1193 case AF_INET:
1194 {
1195 struct in_addr addr;
1196 struct in_addr mask;
1197 struct in_addr rnd;
1198
1199 addr = exit_ipv4addr;
1200 mask = exit_ipv4mask;
1201 if (0 == ~mask.s_addr)
1202 {
1203 /* only one valid IP anyway */
1204 local_address->address.ipv4 = addr;
1205 return;
1206 }
1207 /* Given 192.168.0.1/255.255.0.0, we want a mask
1208 of '192.168.255.255', thus: */
1209 mask.s_addr = addr.s_addr | ~mask.s_addr;
1210 /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
1211 do
1212 {
1214 UINT32_MAX);
1215 local_address->address.ipv4.s_addr = (addr.s_addr | rnd.s_addr)
1216 & mask.s_addr;
1217 }
1218 while ((local_address->address.ipv4.s_addr == addr.s_addr) ||
1219 (local_address->address.ipv4.s_addr == mask.s_addr));
1220 }
1221 break;
1222
1223 case AF_INET6:
1224 {
1225 struct in6_addr addr;
1226 struct in6_addr mask;
1227 struct in6_addr rnd;
1228 int i;
1229
1230 addr = exit_ipv6addr;
1231 GNUNET_assert (ipv6prefix < 128);
1232 if (ipv6prefix == 127)
1233 {
1234 /* only one valid IP anyway */
1235 local_address->address.ipv6 = addr;
1236 return;
1237 }
1238 /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
1239 thus: */
1240 mask = addr;
1241 for (i = 127; i >= ipv6prefix; i--)
1242 mask.s6_addr[i / 8] |= (1 << (i % 8));
1243
1244 /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
1245 do
1246 {
1247 for (i = 0; i < 16; i++)
1248 {
1249 rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (
1251 256);
1252 local_address->address.ipv6.s6_addr[i]
1253 = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
1254 }
1255 }
1256 while ((0 == GNUNET_memcmp (&local_address->address.ipv6,
1257 &addr)) ||
1258 (0 == GNUNET_memcmp (&local_address->address.ipv6,
1259 &mask)));
1260 }
1261 break;
1262
1263 default:
1264 GNUNET_assert (0);
1265 }
1266}
1267
1268
1290static void
1292{
1293 struct GNUNET_HashCode key;
1294 struct ChannelState *s;
1295
1296 /* generate fresh, unique address */
1297 do
1298 {
1299 if (NULL == state->specifics.tcp_udp.serv)
1300 setup_fresh_address (state->specifics.tcp_udp.ri.remote_address.af,
1301 state->specifics.tcp_udp.ri.remote_address.proto,
1302 &state->specifics.tcp_udp.ri.local_address);
1303 else
1304 setup_fresh_address (state->specifics.tcp_udp.serv->address.af,
1305 state->specifics.tcp_udp.serv->address.proto,
1306 &state->specifics.tcp_udp.ri.local_address);
1307 }
1308 while (NULL !=
1309 get_redirect_state (state->specifics.tcp_udp.ri.remote_address.af,
1310 state->specifics.tcp_udp.ri.remote_address.proto,
1311 &state->specifics.tcp_udp.ri.remote_address.address
1312 ,
1313 state->specifics.tcp_udp.ri.remote_address.port,
1314 &state->specifics.tcp_udp.ri.local_address.address,
1315 state->specifics.tcp_udp.ri.local_address.port,
1316 &key));
1317 {
1318 char buf[INET6_ADDRSTRLEN];
1320 "Picked local address %s:%u for new connection\n",
1321 inet_ntop (state->specifics.tcp_udp.ri.local_address.af,
1322 &state->specifics.tcp_udp.ri.local_address.address,
1323 buf,
1324 sizeof(buf)),
1325 (unsigned int) state->specifics.tcp_udp.ri.local_address.port);
1326 }
1327 state->specifics.tcp_udp.state_key = key;
1330 &key, state,
1332 state->specifics.tcp_udp.heap_node
1334 state,
1335 GNUNET_TIME_absolute_get ().abs_value_us);
1337 {
1339 GNUNET_assert (state != s);
1340 s->specifics.tcp_udp.heap_node = NULL;
1344 &s->specifics.tcp_udp.
1345 state_key,
1346 s));
1347 GNUNET_free (s);
1348 }
1349}
1350
1351
1360static void
1361send_udp_packet_via_tun (const struct SocketAddress *destination_address,
1362 const struct SocketAddress *source_address,
1363 const void *payload, size_t payload_length)
1364{
1365 size_t len;
1366
1368 gettext_noop ("# UDP packets sent via TUN"),
1369 1, GNUNET_NO);
1371 "Sending packet with %u bytes UDP payload via TUN\n",
1372 (unsigned int) payload_length);
1373 len = sizeof(struct GNUNET_MessageHeader) + sizeof(struct
1375 switch (source_address->af)
1376 {
1377 case AF_INET:
1378 len += sizeof(struct GNUNET_TUN_IPv4Header);
1379 break;
1380
1381 case AF_INET6:
1382 len += sizeof(struct GNUNET_TUN_IPv6Header);
1383 break;
1384
1385 default:
1386 GNUNET_break (0);
1387 return;
1388 }
1389 len += sizeof(struct GNUNET_TUN_UdpHeader);
1390 len += payload_length;
1392 {
1393 GNUNET_break (0);
1394 return;
1395 }
1396 {
1397 char buf[len] GNUNET_ALIGN;
1398 struct GNUNET_MessageHeader *hdr;
1400
1401 hdr = (struct GNUNET_MessageHeader *) buf;
1402 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1403 hdr->size = htons (len);
1404 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
1405 tun->flags = htons (0);
1406 switch (source_address->af)
1407 {
1408 case AF_INET:
1409 {
1410 struct GNUNET_TUN_IPv4Header *ipv4 = (struct
1411 GNUNET_TUN_IPv4Header*) &tun[1];
1412
1413 tun->proto = htons (ETH_P_IPV4);
1415 payload_length,
1416 IPPROTO_UDP,
1417 NULL,
1420 ipv4);
1421 }
1422 break;
1423
1424 case AF_INET6:
1425 {
1426 struct GNUNET_TUN_IPv6Header *ipv6 = (struct
1427 GNUNET_TUN_IPv6Header*) &tun[1];
1428
1429 tun->proto = htons (ETH_P_IPV6);
1432 IPPROTO_UDP,
1433 NULL,
1436 ipv6);
1437 }
1438 break;
1439
1440 default:
1441 GNUNET_assert (0);
1442 break;
1443 }
1444 if (NULL != helper_handle)
1446 (const struct GNUNET_MessageHeader*) buf,
1447 GNUNET_YES,
1448 NULL, NULL);
1449 }
1450}
1451
1452
1461static int
1462check_udp_remote (void *cls,
1463 const struct GNUNET_EXIT_UdpInternetMessage *msg)
1464{
1465 struct ChannelState *state = cls;
1466
1467 if (GNUNET_YES == state->is_dns)
1468 {
1469 GNUNET_break_op (0);
1470 return GNUNET_SYSERR;
1471 }
1472 return GNUNET_OK;
1473}
1474
1475
1482static void
1483handle_udp_remote (void *cls,
1484 const struct GNUNET_EXIT_UdpInternetMessage *msg)
1485{
1486 struct ChannelState *state = cls;
1487 uint16_t pkt_len = ntohs (msg->header.size) - sizeof(struct
1489 const struct in_addr *v4;
1490 const struct in6_addr *v6;
1491 const void *payload;
1492 int af;
1493
1494 if (GNUNET_SYSERR == state->is_dns)
1495 {
1496 /* channel is UDP/TCP from now on */
1498 }
1500 gettext_noop ("# Bytes received from CADET"),
1501 pkt_len, GNUNET_NO);
1503 gettext_noop (
1504 "# UDP IP-exit requests received via cadet"),
1505 1, GNUNET_NO);
1506 af = (int) ntohl (msg->af);
1507 state->specifics.tcp_udp.ri.remote_address.af = af;
1508 switch (af)
1509 {
1510 case AF_INET:
1511 if (pkt_len < sizeof(struct in_addr))
1512 {
1513 GNUNET_break_op (0);
1514 return;
1515 }
1516 if (! ipv4_exit)
1517 {
1518 GNUNET_break_op (0);
1519 return;
1520 }
1521 v4 = (const struct in_addr*) &msg[1];
1522 payload = &v4[1];
1523 pkt_len -= sizeof(struct in_addr);
1524 state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4;
1525 break;
1526
1527 case AF_INET6:
1528 if (pkt_len < sizeof(struct in6_addr))
1529 {
1530 GNUNET_break_op (0);
1531 return;
1532 }
1533 if (! ipv6_exit)
1534 {
1535 GNUNET_break_op (0);
1536 return;
1537 }
1538 v6 = (const struct in6_addr*) &msg[1];
1539 payload = &v6[1];
1540 pkt_len -= sizeof(struct in6_addr);
1541 state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6;
1542 break;
1543
1544 default:
1545 GNUNET_break_op (0);
1546 return;
1547 }
1548 {
1549 char buf[INET6_ADDRSTRLEN];
1551 "Received data from %s for forwarding to UDP %s:%u\n",
1552 GNUNET_i2s (&state->peer),
1553 inet_ntop (af,
1554 &state->specifics.tcp_udp.ri.remote_address.address,
1555 buf, sizeof(buf)),
1556 (unsigned int) ntohs (msg->destination_port));
1557 }
1558 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_UDP;
1559 state->specifics.tcp_udp.ri.remote_address.port = msg->destination_port;
1560 if (NULL == state->specifics.tcp_udp.heap_node)
1562 if (0 != ntohs (msg->source_port))
1563 state->specifics.tcp_udp.ri.local_address.port = msg->source_port;
1564 send_udp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1565 &state->specifics.tcp_udp.ri.local_address,
1566 payload,
1567 pkt_len);
1569}
1570
1571
1581static int
1582check_udp_service (void *cls,
1583 const struct GNUNET_EXIT_UdpServiceMessage *msg)
1584{
1585 struct ChannelState *state = cls;
1586
1587 if (NULL == state->specifics.tcp_udp.serv)
1588 {
1589 GNUNET_break_op (0);
1590 return GNUNET_SYSERR;
1591 }
1592 return GNUNET_OK;
1593}
1594
1595
1603static void
1604handle_udp_service (void *cls,
1605 const struct GNUNET_EXIT_UdpServiceMessage *msg)
1606{
1607 struct ChannelState *state = cls;
1608 uint16_t pkt_len = ntohs (msg->header.size) - sizeof(struct
1610
1612 gettext_noop ("# Bytes received from CADET"),
1613 pkt_len, GNUNET_NO);
1615 gettext_noop (
1616 "# UDP service requests received via cadet"),
1617 1, GNUNET_NO);
1619 "Received data from %s for forwarding to UDP service %s on port %u\n",
1620 GNUNET_i2s (&state->peer),
1621 GNUNET_h2s (&state->specifics.tcp_udp.serv->descriptor),
1622 (unsigned int) ntohs (msg->destination_port));
1624 if (0 != ntohs (msg->source_port))
1625 state->specifics.tcp_udp.ri.local_address.port = msg->source_port;
1626 send_udp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1627 &state->specifics.tcp_udp.ri.local_address,
1628 &msg[1],
1629 pkt_len);
1631}
1632
1633
1643static void
1644handle_tcp_service (void *cls,
1646{
1647 struct ChannelState *state = cls;
1648 uint16_t pkt_len = ntohs (start->header.size) - sizeof(struct
1650
1651 if (GNUNET_SYSERR == state->is_dns)
1652 {
1653 /* channel is UDP/TCP from now on */
1655 }
1657 gettext_noop (
1658 "# TCP service creation requests received via cadet"),
1659 1,
1660 GNUNET_NO);
1662 gettext_noop ("# Bytes received from CADET"),
1663 pkt_len,
1664 GNUNET_NO);
1665 GNUNET_break_op (ntohl (start->reserved) == 0);
1666 /* setup fresh connection */
1668 "Received data from %s for forwarding to TCP service %s on port %u\n",
1669 GNUNET_i2s (&state->peer),
1670 GNUNET_h2s (&state->specifics.tcp_udp.serv->descriptor),
1671 (unsigned int) ntohs (start->tcp_header.destination_port));
1673 send_tcp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1674 &state->specifics.tcp_udp.ri.local_address,
1675 &start->tcp_header,
1676 &start[1],
1677 pkt_len);
1679}
1680
1681
1690static int
1691check_tcp_remote (void *cls,
1693{
1694 struct ChannelState *state = cls;
1695
1696 if (NULL == state)
1697 {
1698 GNUNET_break_op (0);
1699 return GNUNET_SYSERR;
1700 }
1701 if (GNUNET_YES == state->is_dns)
1702 {
1703 GNUNET_break_op (0);
1704 return GNUNET_SYSERR;
1705 }
1706 if ((NULL != state->specifics.tcp_udp.serv) ||
1707 (NULL != state->specifics.tcp_udp.heap_node))
1708 {
1709 GNUNET_break_op (0);
1710 return GNUNET_SYSERR;
1711 }
1712 if (start->tcp_header.off * 4 < sizeof(struct GNUNET_TUN_TcpHeader))
1713 {
1714 GNUNET_break_op (0);
1715 return GNUNET_SYSERR;
1716 }
1717 return GNUNET_OK;
1718}
1719
1720
1727static void
1728handle_tcp_remote (void *cls,
1730{
1731 struct ChannelState *state = cls;
1732 uint16_t pkt_len = ntohs (start->header.size) - sizeof(struct
1734 const struct in_addr *v4;
1735 const struct in6_addr *v6;
1736 const void *payload;
1737 int af;
1738
1739 if (GNUNET_SYSERR == state->is_dns)
1740 {
1741 /* channel is UDP/TCP from now on */
1743 }
1745 gettext_noop ("# Bytes received from CADET"),
1746 pkt_len, GNUNET_NO);
1748 gettext_noop (
1749 "# TCP IP-exit creation requests received via cadet"),
1750 1, GNUNET_NO);
1751 af = (int) ntohl (start->af);
1752 state->specifics.tcp_udp.ri.remote_address.af = af;
1753 switch (af)
1754 {
1755 case AF_INET:
1756 if (pkt_len < sizeof(struct in_addr))
1757 {
1758 GNUNET_break_op (0);
1759 return;
1760 }
1761 if (! ipv4_exit)
1762 {
1763 GNUNET_break_op (0);
1764 return;
1765 }
1766 v4 = (const struct in_addr*) &start[1];
1767 payload = &v4[1];
1768 pkt_len -= sizeof(struct in_addr);
1769 state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4;
1770 break;
1771
1772 case AF_INET6:
1773 if (pkt_len < sizeof(struct in6_addr))
1774 {
1775 GNUNET_break_op (0);
1776 return;
1777 }
1778 if (! ipv6_exit)
1779 {
1780 GNUNET_break_op (0);
1781 return;
1782 }
1783 v6 = (const struct in6_addr*) &start[1];
1784 payload = &v6[1];
1785 pkt_len -= sizeof(struct in6_addr);
1786 state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6;
1787 break;
1788
1789 default:
1790 GNUNET_break_op (0);
1791 return;
1792 }
1793 {
1794 char buf[INET6_ADDRSTRLEN];
1796 "Received payload from %s for existing TCP stream to %s:%u\n",
1797 GNUNET_i2s (&state->peer),
1798 inet_ntop (af,
1799 &state->specifics.tcp_udp.ri.remote_address.address,
1800 buf, sizeof(buf)),
1801 (unsigned int) ntohs (start->tcp_header.destination_port));
1802 }
1803 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_TCP;
1804 state->specifics.tcp_udp.ri.remote_address.port = ntohs (
1805 start->tcp_header.destination_port);
1807 send_tcp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1808 &state->specifics.tcp_udp.ri.local_address,
1809 &start->tcp_header,
1810 payload,
1811 pkt_len);
1813}
1814
1815
1825static int
1826check_tcp_data (void *cls,
1827 const struct GNUNET_EXIT_TcpDataMessage *data)
1828{
1829 struct ChannelState *state = cls;
1830
1831 if ((NULL == state) ||
1832 (NULL == state->specifics.tcp_udp.heap_node))
1833 {
1834 /* connection should have been up! */
1836 gettext_noop (
1837 "# TCP DATA requests dropped (no session)"),
1838 1, GNUNET_NO);
1839 GNUNET_break_op (0);
1840 return GNUNET_SYSERR;
1841 }
1842 if (data->tcp_header.off * 4 < sizeof(struct GNUNET_TUN_TcpHeader))
1843 {
1844 GNUNET_break_op (0);
1845 return GNUNET_SYSERR;
1846 }
1847 if (GNUNET_YES == state->is_dns)
1848 {
1849 GNUNET_break_op (0);
1850 return GNUNET_SYSERR;
1851 }
1852 return GNUNET_OK;
1853}
1854
1855
1863static void
1864handle_tcp_data (void *cls,
1865 const struct GNUNET_EXIT_TcpDataMessage *data)
1866{
1867 struct ChannelState *state = cls;
1868 uint16_t pkt_len = ntohs (data->header.size) - sizeof(struct
1870
1872 gettext_noop ("# Bytes received from CADET"),
1873 pkt_len, GNUNET_NO);
1875 gettext_noop (
1876 "# TCP data requests received via cadet"),
1877 1, GNUNET_NO);
1878 if (GNUNET_SYSERR == state->is_dns)
1879 {
1880 /* channel is UDP/TCP from now on */
1881 state->is_dns = GNUNET_NO;
1882 }
1883
1884 GNUNET_break_op (ntohl (data->reserved) == 0);
1885 {
1886 char buf[INET6_ADDRSTRLEN];
1888 "Received additional %u bytes of data from %s for TCP stream to %s:%u\n",
1889 pkt_len,
1890 GNUNET_i2s (&state->peer),
1891 inet_ntop (state->specifics.tcp_udp.ri.remote_address.af,
1892 &state->specifics.tcp_udp.ri.remote_address.address,
1893 buf, sizeof(buf)),
1894 (unsigned int) state->specifics.tcp_udp.ri.remote_address.port);
1895 }
1896
1897 send_tcp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1898 &state->specifics.tcp_udp.ri.local_address,
1899 &data->tcp_header,
1900 &data[1], pkt_len);
1902}
1903
1904
1914static void
1916 struct GNUNET_TUN_IPv4Header *ipp,
1917 struct GNUNET_TUN_UdpHeader *udp)
1918{
1920 state->specifics.tcp_udp.ri.remote_address.
1921 proto,
1922 sizeof(struct GNUNET_TUN_TcpHeader),
1923 &state->specifics.tcp_udp.ri.remote_address
1924 .address.ipv4,
1925 &state->specifics.tcp_udp.ri.local_address.
1926 address.ipv4);
1927 udp->source_port = htons (state->specifics.tcp_udp.ri.remote_address.port);
1928 udp->destination_port = htons (
1929 state->specifics.tcp_udp.ri.local_address.port);
1930 udp->len = htons (0);
1931 udp->crc = htons (0);
1932}
1933
1934
1944static void
1946 struct GNUNET_TUN_IPv6Header *ipp,
1947 struct GNUNET_TUN_UdpHeader *udp)
1948{
1950 state->specifics.tcp_udp.ri.remote_address.
1951 proto,
1952 sizeof(struct GNUNET_TUN_TcpHeader),
1953 &state->specifics.tcp_udp.ri.remote_address
1954 .address.ipv6,
1955 &state->specifics.tcp_udp.ri.local_address.
1956 address.ipv6);
1957 udp->source_port = htons (state->specifics.tcp_udp.ri.remote_address.port);
1958 udp->destination_port = htons (
1959 state->specifics.tcp_udp.ri.local_address.port);
1960 udp->len = htons (0);
1961 udp->crc = htons (0);
1962}
1963
1964
1973static int
1974check_icmp_remote (void *cls,
1976{
1977 struct ChannelState *state = cls;
1978
1979 if (GNUNET_YES == state->is_dns)
1980 {
1981 GNUNET_break_op (0);
1982 return GNUNET_SYSERR;
1983 }
1984 return GNUNET_OK;
1985}
1986
1987
1994static void
1995handle_icmp_remote (void *cls,
1997{
1998 struct ChannelState *state = cls;
1999 uint16_t pkt_len = ntohs (msg->header.size) - sizeof(struct
2001 const struct in_addr *v4;
2002 const struct in6_addr *v6;
2003 const void *payload;
2004 char buf[sizeof(struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
2005 int af;
2006
2007 if (GNUNET_SYSERR == state->is_dns)
2008 {
2009 /* channel is UDP/TCP from now on */
2011 }
2013 gettext_noop ("# Bytes received from CADET"),
2014 pkt_len, GNUNET_NO);
2016 gettext_noop (
2017 "# ICMP IP-exit requests received via cadet"),
2018 1, GNUNET_NO);
2019
2020 af = (int) ntohl (msg->af);
2021 if ((NULL != state->specifics.tcp_udp.heap_node) &&
2022 (af != state->specifics.tcp_udp.ri.remote_address.af))
2023 {
2024 /* other peer switched AF on this channel; not allowed */
2025 GNUNET_break_op (0);
2026 return;
2027 }
2028
2029 switch (af)
2030 {
2031 case AF_INET:
2032 if (pkt_len < sizeof(struct in_addr))
2033 {
2034 GNUNET_break_op (0);
2035 return;
2036 }
2037 if (! ipv4_exit)
2038 {
2039 GNUNET_break_op (0);
2040 return;
2041 }
2042 v4 = (const struct in_addr*) &msg[1];
2043 payload = &v4[1];
2044 pkt_len -= sizeof(struct in_addr);
2045 state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4;
2046 if (NULL == state->specifics.tcp_udp.heap_node)
2047 {
2048 state->specifics.tcp_udp.ri.remote_address.af = af;
2049 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_ICMP;
2051 }
2052 /* check that ICMP type is something we want to support
2053 and possibly make up payload! */
2054 switch (msg->icmp_header.type)
2055 {
2058 break;
2059
2063 if (0 != pkt_len)
2064 {
2065 GNUNET_break_op (0);
2066 return;
2067 }
2068 /* make up payload */
2069 {
2070 struct GNUNET_TUN_IPv4Header *ipp = (struct
2071 GNUNET_TUN_IPv4Header *) buf;
2072 struct GNUNET_TUN_UdpHeader *udp = (struct
2073 GNUNET_TUN_UdpHeader *) &ipp[1];
2074
2075 GNUNET_assert (8 == sizeof(struct GNUNET_TUN_UdpHeader));
2076 pkt_len = sizeof(struct GNUNET_TUN_IPv4Header) + 8;
2078 ipp,
2079 udp);
2080 payload = ipp;
2081 }
2082 break;
2083
2084 default:
2085 GNUNET_break_op (0);
2087 gettext_noop (
2088 "# ICMPv4 packets dropped (type not allowed)")
2089 ,
2090 1, GNUNET_NO);
2091 return;
2092 }
2093 /* end AF_INET */
2094 break;
2095
2096 case AF_INET6:
2097 if (pkt_len < sizeof(struct in6_addr))
2098 {
2099 GNUNET_break_op (0);
2100 return;
2101 }
2102 if (! ipv6_exit)
2103 {
2104 GNUNET_break_op (0);
2105 return;
2106 }
2107 v6 = (const struct in6_addr*) &msg[1];
2108 payload = &v6[1];
2109 pkt_len -= sizeof(struct in6_addr);
2110 state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6;
2111 if (NULL == state->specifics.tcp_udp.heap_node)
2112 {
2113 state->specifics.tcp_udp.ri.remote_address.af = af;
2114 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_ICMPV6;
2116 }
2117 /* check that ICMP type is something we want to support
2118 and possibly make up payload! */
2119 switch (msg->icmp_header.type)
2120 {
2123 break;
2124
2129 if (0 != pkt_len)
2130 {
2131 GNUNET_break_op (0);
2132 return;
2133 }
2134 /* make up payload */
2135 {
2136 struct GNUNET_TUN_IPv6Header *ipp = (struct
2137 GNUNET_TUN_IPv6Header *) buf;
2138 struct GNUNET_TUN_UdpHeader *udp = (struct
2139 GNUNET_TUN_UdpHeader *) &ipp[1];
2140
2141 GNUNET_assert (8 == sizeof(struct GNUNET_TUN_UdpHeader));
2142 pkt_len = sizeof(struct GNUNET_TUN_IPv6Header) + 8;
2144 ipp,
2145 udp);
2146 payload = ipp;
2147 }
2148 break;
2149
2150 default:
2151 GNUNET_break_op (0);
2153 gettext_noop (
2154 "# ICMPv6 packets dropped (type not allowed)")
2155 ,
2156 1, GNUNET_NO);
2157 return;
2158 }
2159 /* end AF_INET6 */
2160 break;
2161
2162 default:
2163 /* bad AF */
2164 GNUNET_break_op (0);
2165 return;
2166 }
2167
2168 {
2169 char buf_tmp[INET6_ADDRSTRLEN];
2171 "Received ICMP data from %s for forwarding to %s\n",
2172 GNUNET_i2s (&state->peer),
2173 inet_ntop (af,
2174 &state->specifics.tcp_udp.ri.remote_address.address,
2175 buf_tmp, sizeof(buf_tmp)));
2176 }
2177 send_icmp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
2178 &state->specifics.tcp_udp.ri.local_address,
2179 &msg->icmp_header,
2180 payload, pkt_len);
2182}
2183
2184
2194static uint16_t
2196 char *buf)
2197{
2198 switch (state->specifics.tcp_udp.serv->address.af)
2199 {
2200 case AF_INET:
2201 {
2203 struct GNUNET_TUN_UdpHeader *udp;
2204
2205 ipv4 = (struct GNUNET_TUN_IPv4Header *) buf;
2206 udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
2208 ipv4,
2209 udp);
2210 GNUNET_assert (8 == sizeof(struct GNUNET_TUN_UdpHeader));
2211 return sizeof(struct GNUNET_TUN_IPv4Header) + 8;
2212 }
2213 break;
2214
2215 case AF_INET6:
2216 {
2218 struct GNUNET_TUN_UdpHeader *udp;
2219
2220 ipv6 = (struct GNUNET_TUN_IPv6Header *) buf;
2221 udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
2223 ipv6,
2224 udp);
2225 GNUNET_assert (8 == sizeof(struct GNUNET_TUN_UdpHeader));
2226 return sizeof(struct GNUNET_TUN_IPv6Header) + 8;
2227 }
2228 break;
2229
2230 default:
2231 GNUNET_break (0);
2232 }
2233 return 0;
2234}
2235
2236
2246static int
2247check_icmp_service (void *cls,
2248 const struct GNUNET_EXIT_IcmpServiceMessage *msg)
2249{
2250 struct ChannelState *state = cls;
2251
2252 if (GNUNET_YES == state->is_dns)
2253 {
2254 GNUNET_break_op (0);
2255 return GNUNET_SYSERR;
2256 }
2257 if (NULL == state->specifics.tcp_udp.serv)
2258 {
2259 GNUNET_break_op (0);
2260 return GNUNET_SYSERR;
2261 }
2262 return GNUNET_OK;
2263}
2264
2265
2273static void
2274handle_icmp_service (void *cls,
2275 const struct GNUNET_EXIT_IcmpServiceMessage *msg)
2276{
2277 struct ChannelState *state = cls;
2278 uint16_t pkt_len = ntohs (msg->header.size) - sizeof(struct
2280 struct GNUNET_TUN_IcmpHeader icmp;
2281 char buf[sizeof(struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
2282 const void *payload;
2283
2285 gettext_noop ("# Bytes received from CADET"),
2286 pkt_len, GNUNET_NO);
2288 gettext_noop (
2289 "# ICMP service requests received via cadet"),
2290 1, GNUNET_NO);
2291 /* check that we got at least a valid header */
2293 "Received data from %s for forwarding to ICMP service %s\n",
2294 GNUNET_i2s (&state->peer),
2295 GNUNET_h2s (&state->specifics.tcp_udp.serv->descriptor));
2296 icmp = msg->icmp_header;
2297 payload = &msg[1];
2298 state->specifics.tcp_udp.ri.remote_address
2299 = state->specifics.tcp_udp.serv->address;
2301
2302 /* check that ICMP type is something we want to support,
2303 perform ICMP PT if needed and possibly make up payload */
2304 switch (msg->af)
2305 {
2306 case AF_INET:
2307 switch (msg->icmp_header.type)
2308 {
2310 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2312 break;
2313
2315 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2317 break;
2318
2320 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2322 if (0 != pkt_len)
2323 {
2324 GNUNET_break_op (0);
2325 return;
2326 }
2327 payload = buf;
2328 pkt_len = make_up_icmp_service_payload (state, buf);
2329 break;
2330
2332 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2334 if (0 != pkt_len)
2335 {
2336 GNUNET_break_op (0);
2337 return;
2338 }
2339 payload = buf;
2340 pkt_len = make_up_icmp_service_payload (state, buf);
2341 break;
2342
2344 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2345 {
2347 gettext_noop (
2348 "# ICMPv4 packets dropped (impossible PT to v6)"),
2349 1, GNUNET_NO);
2350 return;
2351 }
2352 if (0 != pkt_len)
2353 {
2354 GNUNET_break_op (0);
2355 return;
2356 }
2357 payload = buf;
2358 pkt_len = make_up_icmp_service_payload (state, buf);
2359 break;
2360
2361 default:
2362 GNUNET_break_op (0);
2364 gettext_noop (
2365 "# ICMPv4 packets dropped (type not allowed)")
2366 ,
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 {
2377 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2379 break;
2380
2382 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2384 break;
2385
2387 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
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
2399 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
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
2412 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2413 {
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);
2432 gettext_noop (
2433 "# ICMPv6 packets dropped (type not allowed)")
2434 ,
2435 1, GNUNET_NO);
2436 return;
2437 }
2438 /* end of AF_INET6 */
2439 break;
2440
2441 default:
2442 GNUNET_break_op (0);
2443 return;
2444 }
2445
2446 send_icmp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
2447 &state->specifics.tcp_udp.ri.local_address,
2448 &icmp,
2449 payload,
2450 pkt_len);
2452}
2453
2454
2463static int
2464free_service_record (void *cls,
2465 const struct GNUNET_HashCode *key,
2466 void *value)
2467{
2468 struct LocalService *service = value;
2469
2472 key,
2473 service));
2475 GNUNET_free (service->name);
2477 return GNUNET_OK;
2478}
2479
2480
2489static void *
2490new_service_channel (void *cls,
2491 struct GNUNET_CADET_Channel *channel,
2492 const struct GNUNET_PeerIdentity *initiator)
2493{
2494 struct LocalService *ls = cls;
2495 struct ChannelState *s = GNUNET_new (struct ChannelState);
2496
2497 s->peer = *initiator;
2499 gettext_noop ("# Inbound CADET channels created"),
2500 1,
2501 GNUNET_NO);
2503 "Received inbound channel from `%s'\n",
2504 GNUNET_i2s (initiator));
2505 s->channel = channel;
2506 s->specifics.tcp_udp.serv = ls;
2507 s->specifics.tcp_udp.ri.remote_address = ls->address;
2508 return s;
2509}
2510
2511
2519static void
2520clean_channel (void *cls,
2521 const struct GNUNET_CADET_Channel *channel)
2522{
2523 struct ChannelState *s = cls;
2524
2526 "Channel destroyed\n");
2527 if (GNUNET_SYSERR == s->is_dns)
2528 {
2529 GNUNET_free (s);
2530 return;
2531 }
2532 if (GNUNET_YES == s->is_dns)
2533 {
2534 if (channels[s->specifics.dns.my_id] == s)
2535 channels[s->specifics.dns.my_id] = NULL;
2536 }
2537 else
2538 {
2539 if (NULL != s->specifics.tcp_udp.heap_node)
2540 {
2543 &s->specifics.tcp_udp
2544 .state_key,
2545 s));
2547 s->specifics.tcp_udp.heap_node = NULL;
2548 }
2549 }
2550 GNUNET_free (s);
2551}
2552
2553
2563static void
2564store_service (int proto,
2565 const char *name,
2566 uint16_t destination_port,
2567 struct LocalService *service)
2568{
2570 GNUNET_MQ_hd_var_size (icmp_service,
2573 service),
2574 GNUNET_MQ_hd_var_size (udp_service,
2577 service),
2578 GNUNET_MQ_hd_var_size (tcp_service,
2581 service),
2582 GNUNET_MQ_hd_var_size (tcp_data,
2585 service),
2587 };
2588
2590
2591 service->name = GNUNET_strdup (name);
2593 &service->descriptor);
2595 destination_port,
2596 &cadet_port);
2598 "Opening CADET port %s for SERVICE exit %s on port %u\n",
2600 name,
2601 (unsigned int) destination_port);
2603 &cadet_port,
2605 service,
2606 NULL,
2608 handlers);
2609 service->is_udp = (IPPROTO_UDP == proto);
2610 if (GNUNET_OK !=
2612 &cadet_port,
2613 service,
2615 {
2617 GNUNET_free (service->name);
2620 _ ("Got duplicate service records for `%s:%u'\n"),
2621 name,
2622 (unsigned int) destination_port);
2623 }
2624}
2625
2626
2633static void
2635 struct GNUNET_MQ_Envelope *env)
2636{
2637 GNUNET_assert (NULL != s);
2639 gettext_noop (
2640 "# Messages transmitted via cadet channels"),
2641 1,
2642 GNUNET_NO);
2644 env);
2645}
2646
2647
2659static void
2660icmp_from_helper (const struct GNUNET_TUN_IcmpHeader *icmp,
2661 size_t pktlen,
2662 int af,
2663 const void *destination_ip,
2664 const void *source_ip)
2665{
2666 struct ChannelState *state;
2667 struct GNUNET_MQ_Envelope *env;
2668 struct GNUNET_EXIT_IcmpToVPNMessage *i2v;
2669 const struct GNUNET_TUN_IPv4Header *ipv4;
2670 const struct GNUNET_TUN_IPv6Header *ipv6;
2671 const struct GNUNET_TUN_UdpHeader *udp;
2672 uint16_t source_port;
2673 uint16_t destination_port;
2674 uint8_t protocol;
2675
2676 {
2677 char sbuf[INET6_ADDRSTRLEN];
2678 char dbuf[INET6_ADDRSTRLEN];
2680 "Received ICMP packet going from %s to %s\n",
2681 inet_ntop (af,
2682 source_ip,
2683 sbuf, sizeof(sbuf)),
2684 inet_ntop (af,
2685 destination_ip,
2686 dbuf, sizeof(dbuf)));
2687 }
2688
2689 if (pktlen < sizeof(struct GNUNET_TUN_IcmpHeader))
2690 {
2691 /* blame kernel */
2692 GNUNET_break (0);
2693 return;
2694 }
2695
2696 /* Find out if this is an ICMP packet in response to an existing
2697 TCP/UDP packet and if so, figure out ports / protocol of the
2698 existing session from the IP data in the ICMP payload */
2699 source_port = 0;
2700 destination_port = 0;
2701 switch (af)
2702 {
2703 case AF_INET:
2704 protocol = IPPROTO_ICMP;
2705 switch (icmp->type)
2706 {
2709 break;
2710
2714 if (pktlen <
2715 sizeof(struct GNUNET_TUN_IcmpHeader)
2716 + sizeof(struct GNUNET_TUN_IPv4Header) + 8)
2717 {
2718 /* blame kernel */
2719 GNUNET_break (0);
2720 return;
2721 }
2722 ipv4 = (const struct GNUNET_TUN_IPv4Header *) &icmp[1];
2723 protocol = ipv4->protocol;
2724 /* could be TCP or UDP, but both have the ports in the right
2725 place, so that doesn't matter here */
2726 udp = (const struct GNUNET_TUN_UdpHeader *) &ipv4[1];
2727 /* swap ports, as they are from the original message */
2728 destination_port = ntohs (udp->source_port);
2729 source_port = ntohs (udp->destination_port);
2730 /* throw away ICMP payload, won't be useful for the other side anyway */
2731 pktlen = sizeof(struct GNUNET_TUN_IcmpHeader);
2732 break;
2733
2734 default:
2736 gettext_noop (
2737 "# ICMPv4 packets dropped (type not allowed)")
2738 ,
2739 1, GNUNET_NO);
2740 return;
2741 }
2742 break;
2743
2744 case AF_INET6:
2745 protocol = IPPROTO_ICMPV6;
2746 switch (icmp->type)
2747 {
2752 if (pktlen <
2753 sizeof(struct GNUNET_TUN_IcmpHeader)
2754 + sizeof(struct GNUNET_TUN_IPv6Header) + 8)
2755 {
2756 /* blame kernel */
2757 GNUNET_break (0);
2758 return;
2759 }
2760 ipv6 = (const struct GNUNET_TUN_IPv6Header *) &icmp[1];
2761 protocol = ipv6->next_header;
2762 /* could be TCP or UDP, but both have the ports in the right
2763 place, so that doesn't matter here */
2764 udp = (const struct GNUNET_TUN_UdpHeader *) &ipv6[1];
2765 /* swap ports, as they are from the original message */
2766 destination_port = ntohs (udp->source_port);
2767 source_port = ntohs (udp->destination_port);
2768 /* throw away ICMP payload, won't be useful for the other side anyway */
2769 pktlen = sizeof(struct GNUNET_TUN_IcmpHeader);
2770 break;
2771
2774 break;
2775
2776 default:
2778 gettext_noop (
2779 "# ICMPv6 packets dropped (type not allowed)")
2780 ,
2781 1, GNUNET_NO);
2782 return;
2783 }
2784 break;
2785
2786 default:
2787 GNUNET_assert (0);
2788 }
2789 switch (protocol)
2790 {
2791 case IPPROTO_ICMP:
2793 IPPROTO_ICMP,
2794 source_ip,
2795 0,
2796 destination_ip,
2797 0,
2798 NULL);
2799 break;
2800
2801 case IPPROTO_ICMPV6:
2803 IPPROTO_ICMPV6,
2804 source_ip,
2805 0,
2806 destination_ip,
2807 0,
2808 NULL);
2809 break;
2810
2811 case IPPROTO_UDP:
2813 IPPROTO_UDP,
2814 source_ip,
2815 source_port,
2816 destination_ip,
2817 destination_port,
2818 NULL);
2819 break;
2820
2821 case IPPROTO_TCP:
2823 IPPROTO_TCP,
2824 source_ip,
2825 source_port,
2826 destination_ip,
2827 destination_port,
2828 NULL);
2829 break;
2830
2831 default:
2833 gettext_noop (
2834 "# ICMP packets dropped (not allowed)"),
2835 1,
2836 GNUNET_NO);
2837 return;
2838 }
2839 if (NULL == state)
2840 {
2842 _ (
2843 "ICMP Packet dropped, have no matching connection information\n"));
2844 return;
2845 }
2846 env = GNUNET_MQ_msg_extra (i2v,
2847 pktlen - sizeof(struct GNUNET_TUN_IcmpHeader),
2849 i2v->af = htonl (af);
2851 icmp,
2852 pktlen);
2854 env);
2855}
2856
2857
2869static void
2871 size_t pktlen,
2872 int af,
2873 const void *destination_ip,
2874 const void *source_ip)
2875{
2876 struct ChannelState *state;
2877 struct GNUNET_MQ_Envelope *env;
2878 struct GNUNET_EXIT_UdpReplyMessage *urm;
2879
2880 {
2881 char sbuf[INET6_ADDRSTRLEN];
2882 char dbuf[INET6_ADDRSTRLEN];
2883
2885 "Received UDP packet going from %s:%u to %s:%u\n",
2886 inet_ntop (af,
2887 source_ip,
2888 sbuf, sizeof(sbuf)),
2889 (unsigned int) ntohs (udp->source_port),
2890 inet_ntop (af,
2891 destination_ip,
2892 dbuf, sizeof(dbuf)),
2893 (unsigned int) ntohs (udp->destination_port));
2894 }
2895
2896 if (pktlen < sizeof(struct GNUNET_TUN_UdpHeader))
2897 {
2898 /* blame kernel */
2899 GNUNET_break (0);
2900 return;
2901 }
2902 if (pktlen != ntohs (udp->len))
2903 {
2904 /* blame kernel */
2905 GNUNET_break (0);
2906 return;
2907 }
2909 IPPROTO_UDP,
2910 source_ip,
2911 ntohs (udp->source_port),
2912 destination_ip,
2913 ntohs (udp->destination_port),
2914 NULL);
2915 if (NULL == state)
2916 {
2918 _ (
2919 "UDP Packet dropped, have no matching connection information\n"));
2920 return;
2921 }
2922 env = GNUNET_MQ_msg_extra (urm,
2923 pktlen - sizeof(struct GNUNET_TUN_UdpHeader),
2925 urm->source_port = htons (0);
2926 urm->destination_port = htons (0);
2927 GNUNET_memcpy (&urm[1],
2928 &udp[1],
2929 pktlen - sizeof(struct GNUNET_TUN_UdpHeader));
2931 env);
2932}
2933
2934
2946static void
2948 size_t pktlen,
2949 int af,
2950 const void *destination_ip,
2951 const void *source_ip)
2952{
2953 struct ChannelState *state;
2954 char buf[pktlen] GNUNET_ALIGN;
2955 struct GNUNET_TUN_TcpHeader *mtcp;
2956 struct GNUNET_EXIT_TcpDataMessage *tdm;
2957 struct GNUNET_MQ_Envelope *env;
2958 size_t mlen;
2959
2960 {
2961 char sbuf[INET6_ADDRSTRLEN];
2962 char dbuf[INET6_ADDRSTRLEN];
2964 "Received TCP packet with %u bytes going from %s:%u to %s:%u\n",
2965 (unsigned int) (pktlen - sizeof(struct GNUNET_TUN_TcpHeader)),
2966 inet_ntop (af,
2967 source_ip,
2968 sbuf, sizeof(sbuf)),
2969 (unsigned int) ntohs (tcp->source_port),
2970 inet_ntop (af,
2971 destination_ip,
2972 dbuf, sizeof(dbuf)),
2973 (unsigned int) ntohs (tcp->destination_port));
2974 }
2975
2976 if (pktlen < sizeof(struct GNUNET_TUN_TcpHeader))
2977 {
2978 /* blame kernel */
2979 GNUNET_break (0);
2980 return;
2981 }
2983 IPPROTO_TCP,
2984 source_ip,
2985 ntohs (tcp->source_port),
2986 destination_ip,
2987 ntohs (tcp->destination_port),
2988 NULL);
2989 if (NULL == state)
2990 {
2992 _ (
2993 "TCP Packet dropped, have no matching connection information\n"));
2994
2995 return;
2996 }
2997 /* mug port numbers and crc to avoid information leakage;
2998 sender will need to lookup the correct values anyway */
2999 GNUNET_memcpy (buf, tcp, pktlen);
3000 mtcp = (struct GNUNET_TUN_TcpHeader *) buf;
3001 mtcp->source_port = 0;
3002 mtcp->destination_port = 0;
3003 mtcp->crc = 0;
3004
3005 mlen = sizeof(struct GNUNET_EXIT_TcpDataMessage) + (pktlen - sizeof(struct
3007 if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
3008 {
3009 GNUNET_break (0);
3010 return;
3011 }
3012 env = GNUNET_MQ_msg_extra (tdm,
3013 pktlen - sizeof(struct GNUNET_TUN_TcpHeader),
3015 tdm->reserved = htonl (0);
3017 buf,
3018 pktlen);
3020 env);
3021}
3022
3023
3030static int
3031message_token (void *cls GNUNET_UNUSED,
3032 const struct GNUNET_MessageHeader *message)
3033{
3034 const struct GNUNET_TUN_Layer2PacketHeader *pkt_tun;
3035 size_t size;
3036
3038 "Got %u-byte message of type %u from gnunet-helper-exit\n",
3039 ntohs (message->size),
3040 ntohs (message->type));
3042 gettext_noop ("# Packets received from TUN"),
3043 1, GNUNET_NO);
3044 if (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER)
3045 {
3046 GNUNET_break (0);
3047 return GNUNET_OK;
3048 }
3049 size = ntohs (message->size);
3050 if (size < sizeof(struct GNUNET_TUN_Layer2PacketHeader) + sizeof(struct
3052 {
3053 GNUNET_break (0);
3054 return GNUNET_OK;
3055 }
3057 gettext_noop ("# Bytes received from TUN"),
3058 size, GNUNET_NO);
3059 pkt_tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
3060 size -= sizeof(struct GNUNET_TUN_Layer2PacketHeader) + sizeof(struct
3062 switch (ntohs (pkt_tun->proto))
3063 {
3064 case ETH_P_IPV4:
3065 {
3066 const struct GNUNET_TUN_IPv4Header *pkt4;
3067
3068 if (size < sizeof(struct GNUNET_TUN_IPv4Header))
3069 {
3070 /* Kernel to blame? */
3071 GNUNET_break (0);
3072 return GNUNET_OK;
3073 }
3074 pkt4 = (const struct GNUNET_TUN_IPv4Header *) &pkt_tun[1];
3075 if (size != ntohs (pkt4->total_length))
3076 {
3077 /* Kernel to blame? */
3078 GNUNET_break (0);
3079 return GNUNET_OK;
3080 }
3081 if (pkt4->header_length * 4 != sizeof(struct GNUNET_TUN_IPv4Header))
3082 {
3084 _ ("IPv4 packet options received. Ignored.\n"));
3085 return GNUNET_OK;
3086 }
3087
3088 size -= sizeof(struct GNUNET_TUN_IPv4Header);
3089 switch (pkt4->protocol)
3090 {
3091 case IPPROTO_UDP:
3092 udp_from_helper ((const struct GNUNET_TUN_UdpHeader *) &pkt4[1], size,
3093 AF_INET,
3094 &pkt4->destination_address,
3095 &pkt4->source_address);
3096 break;
3097
3098 case IPPROTO_TCP:
3099 tcp_from_helper ((const struct GNUNET_TUN_TcpHeader *) &pkt4[1], size,
3100 AF_INET,
3101 &pkt4->destination_address,
3102 &pkt4->source_address);
3103 break;
3104
3105 case IPPROTO_ICMP:
3106 icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt4[1], size,
3107 AF_INET,
3108 &pkt4->destination_address,
3109 &pkt4->source_address);
3110 break;
3111
3112 default:
3114 _ (
3115 "IPv4 packet with unsupported next header %u received. Ignored.\n"),
3116 (int) pkt4->protocol);
3117 return GNUNET_OK;
3118 }
3119 }
3120 break;
3121
3122 case ETH_P_IPV6:
3123 {
3124 const struct GNUNET_TUN_IPv6Header *pkt6;
3125
3126 if (size < sizeof(struct GNUNET_TUN_IPv6Header))
3127 {
3128 /* Kernel to blame? */
3129 GNUNET_break (0);
3130 return GNUNET_OK;
3131 }
3132 pkt6 = (struct GNUNET_TUN_IPv6Header *) &pkt_tun[1];
3133 if (size != ntohs (pkt6->payload_length) + sizeof(struct
3135 {
3136 /* Kernel to blame? */
3137 GNUNET_break (0);
3138 return GNUNET_OK;
3139 }
3140 size -= sizeof(struct GNUNET_TUN_IPv6Header);
3141 switch (pkt6->next_header)
3142 {
3143 case IPPROTO_UDP:
3144 udp_from_helper ((const struct GNUNET_TUN_UdpHeader *) &pkt6[1], size,
3145 AF_INET6,
3146 &pkt6->destination_address,
3147 &pkt6->source_address);
3148 break;
3149
3150 case IPPROTO_TCP:
3151 tcp_from_helper ((const struct GNUNET_TUN_TcpHeader *) &pkt6[1], size,
3152 AF_INET6,
3153 &pkt6->destination_address,
3154 &pkt6->source_address);
3155 break;
3156
3157 case IPPROTO_ICMPV6:
3158 icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt6[1], size,
3159 AF_INET6,
3160 &pkt6->destination_address,
3161 &pkt6->source_address);
3162 break;
3163
3164 default:
3166 _ (
3167 "IPv6 packet with unsupported next header %d received. Ignored.\n"),
3168 pkt6->next_header);
3169 return GNUNET_OK;
3170 }
3171 }
3172 break;
3173
3174 default:
3176 _ ("Packet from unknown protocol %u received. Ignored.\n"),
3177 ntohs (pkt_tun->proto));
3178 break;
3179 }
3180 return GNUNET_OK;
3181}
3182
3183
3192static void *
3193new_channel (void *cls,
3194 struct GNUNET_CADET_Channel *channel,
3195 const struct GNUNET_PeerIdentity *initiator)
3196{
3197 struct ChannelState *s = GNUNET_new (struct ChannelState);
3198
3199 s->is_dns = GNUNET_SYSERR;
3200 s->peer = *initiator;
3202 gettext_noop ("# Inbound CADET channels created"),
3203 1,
3204 GNUNET_NO);
3206 "Received inbound channel from `%s'\n",
3207 GNUNET_i2s (initiator));
3208 s->channel = channel;
3209 return s;
3210}
3211
3212
3220static int
3221free_iterate (void *cls,
3222 const struct GNUNET_HashCode *hash,
3223 void *value)
3224{
3226 return GNUNET_YES;
3227}
3228
3229
3238static void
3239dummy_task (void *cls)
3240{
3241 /* just terminate */
3242}
3243
3244
3250static void
3251cleanup (void *cls)
3252{
3253 unsigned int i;
3254
3256 "Exit service is shutting down now\n");
3257
3258 if (NULL != helper_handle)
3259 {
3261 helper_handle = NULL;
3262 }
3263 if (NULL != regex4)
3264 {
3266 regex4 = NULL;
3267 }
3268 if (NULL != regex6)
3269 {
3271 regex6 = NULL;
3272 }
3273 if (NULL != services)
3274 {
3277 NULL);
3279 }
3280 if (NULL != dns_port)
3281 {
3283 dns_port = NULL;
3284 }
3285 if (NULL != cadet_port4)
3286 {
3288 cadet_port4 = NULL;
3289 }
3290 if (NULL != cadet_port6)
3291 {
3293 cadet_port6 = NULL;
3294 }
3295 if (NULL != cadet_handle)
3296 {
3298 cadet_handle = NULL;
3299 }
3300 if (NULL != connections_map)
3301 {
3303 &free_iterate,
3304 NULL);
3306 connections_map = NULL;
3307 }
3308 if (NULL != connections_heap)
3309 {
3311 connections_heap = NULL;
3312 }
3313 if (NULL != dnsstub)
3314 {
3316 dnsstub = NULL;
3317 }
3318 if (NULL != peer_key)
3319 {
3321 peer_key = NULL;
3322 }
3323 if (NULL != dht_task)
3324 {
3326 dht_task = NULL;
3327 }
3328 if (NULL != dht_put)
3329 {
3331 dht_put = NULL;
3332 }
3333 if (NULL != dht)
3334 {
3336 dht = NULL;
3337 }
3338 if (NULL != stats)
3339 {
3341 GNUNET_NO);
3342 stats = NULL;
3343 }
3344 for (i = 0; i < 8; i++)
3346}
3347
3348
3356static void
3357add_services (int proto,
3358 char *cpy,
3359 const char *name)
3360{
3361 char *redirect;
3362 char *hostname;
3363 char *hostport;
3364 struct LocalService *serv;
3365 char *n;
3366 size_t slen;
3367 int local_port;
3368 int remote_port;
3369
3370 slen = strlen (name);
3371 GNUNET_assert (slen >= 8);
3372 n = GNUNET_strndup (name, slen - 8 /* remove .gnunet. */);
3373
3374 for (redirect = strtok (cpy, " ;"); redirect != NULL;
3375 redirect = strtok (NULL, " ;"))
3376 {
3377 if (NULL == (hostname = strstr (redirect, ":")))
3378 {
3380 _ (
3381 "Option `%s' for domain `%s' is not formatted correctly!\n")
3382 ,
3383 redirect,
3384 name);
3385 continue;
3386 }
3387 hostname[0] = '\0';
3388 hostname++;
3389 if (NULL == (hostport = strstr (hostname, ":")))
3390 {
3392 _ (
3393 "Option `%s' for domain `%s' is not formatted correctly!\n")
3394 ,
3395 redirect,
3396 name);
3397 continue;
3398 }
3399 hostport[0] = '\0';
3400 hostport++;
3401
3402 local_port = atoi (redirect);
3403 remote_port = atoi (hostport);
3404
3405 if (! ((local_port > 0) && (local_port < 65536)))
3406 {
3408 _ ("`%s' is not a valid port number (for domain `%s')!"),
3409 redirect,
3410 name);
3411 continue;
3412 }
3413 if (! ((remote_port > 0) && (remote_port < 65536)))
3414 {
3416 _ ("`%s' is not a valid port number (for domain `%s')!"),
3417 hostport,
3418 name);
3419 continue;
3420 }
3421
3422 serv = GNUNET_new (struct LocalService);
3423 serv->address.proto = proto;
3424 serv->address.port = remote_port;
3425 if (0 == strcmp ("localhost4",
3426 hostname))
3427 {
3428 const char *ip4addr = exit_argv[5];
3429
3430 serv->address.af = AF_INET;
3431 GNUNET_assert (1 == inet_pton (AF_INET,
3432 ip4addr,
3433 &serv->address.address.ipv4));
3434 }
3435 else if (0 == strcmp ("localhost6",
3436 hostname))
3437 {
3438 const char *ip6addr = exit_argv[3];
3439
3440 serv->address.af = AF_INET6;
3441 GNUNET_assert (1 == inet_pton (AF_INET6,
3442 ip6addr,
3443 &serv->address.address.ipv6));
3444 }
3445 else
3446 {
3447 struct addrinfo *res;
3448 int ret;
3449
3450 ret = getaddrinfo (hostname,
3451 NULL,
3452 NULL,
3453 &res);
3454 if ((0 != ret) || (NULL == res))
3455 {
3457 _ (
3458 "No addresses found for hostname `%s' of service `%s'!\n")
3459 ,
3460 hostname,
3461 n);
3462 GNUNET_free (serv);
3463 continue;
3464 }
3465
3466 serv->address.af = res->ai_family;
3467 switch (res->ai_family)
3468 {
3469 case AF_INET:
3470 if (! ipv4_enabled)
3471 {
3473 _ (
3474 "Service `%s' configured for IPv4, but IPv4 is disabled!\n"),
3475 n);
3476 freeaddrinfo (res);
3477 GNUNET_free (serv);
3478 continue;
3479 }
3480 serv->address.address.ipv4
3481 = ((struct sockaddr_in *) res->ai_addr)->sin_addr;
3482 break;
3483
3484 case AF_INET6:
3485 if (! ipv6_enabled)
3486 {
3488 _ (
3489 "Service `%s' configured for IPv4, but IPv4 is disabled!\n"),
3490 n);
3491 freeaddrinfo (res);
3492 GNUNET_free (serv);
3493 continue;
3494 }
3495 serv->address.address.ipv6
3496 = ((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
3497 break;
3498
3499 default:
3500 freeaddrinfo (res);
3502 _ (
3503 "No IP addresses found for hostname `%s' of service `%s'!\n"),
3504 hostname,
3505 n);
3506 GNUNET_free (serv);
3507 continue;
3508 }
3509 freeaddrinfo (res);
3510 }
3512 n,
3513 local_port,
3514 serv);
3515 }
3516 GNUNET_free (n);
3517}
3518
3519
3526static void
3527read_service_conf (void *cls,
3528 const char *section)
3529{
3530 char *cpy;
3531
3532 if ((strlen (section) < 8) ||
3533 (0 != strcmp (".gnunet.", section + (strlen (section) - 8))))
3534 return;
3535 if (GNUNET_OK ==
3537 section,
3538 "UDP_REDIRECTS",
3539 &cpy))
3540 {
3541 add_services (IPPROTO_UDP,
3542 cpy,
3543 section);
3544 GNUNET_free (cpy);
3545 }
3546 if (GNUNET_OK ==
3548 section,
3549 "TCP_REDIRECTS",
3550 &cpy))
3551 {
3552 add_services (IPPROTO_TCP,
3553 cpy,
3554 section);
3555 GNUNET_free (cpy);
3556 }
3557}
3558
3559
3566static void
3567do_dht_put (void *cls);
3568
3569
3576static void
3577dht_put_cont (void *cls)
3578{
3579 dht_put = NULL;
3580}
3581
3582
3589static void
3590do_dht_put (void *cls)
3591{
3593
3595 &do_dht_put,
3596 NULL);
3600 {
3601 /* refresh advertisement */
3608 }
3609 if (NULL != dht_put)
3612 &dht_put_key,
3613 1 /* replication */,
3616 sizeof(struct GNUNET_DNS_Advertisement),
3618 expiration,
3619 &dht_put_cont,
3620 NULL);
3621}
3622
3623
3628static void
3630{
3632 "exit",
3633 "EXIT_IPV4");
3635 "exit",
3636 "EXIT_IPV6");
3638 "exit",
3639 "ENABLE_IPV4");
3641 "exit",
3642 "ENABLE_IPV6");
3643 if ((ipv4_exit || ipv4_enabled) &&
3644 (GNUNET_OK != GNUNET_NETWORK_test_pf (PF_INET)) )
3645 {
3647 _ (
3648 "This system does not support IPv4, will disable IPv4 functions despite them being enabled in the configuration\n"));
3651 }
3652 if ((ipv6_exit || ipv6_enabled) &&
3653 (GNUNET_OK != GNUNET_NETWORK_test_pf (PF_INET6)) )
3654 {
3656 _ (
3657 "This system does not support IPv6, will disable IPv6 functions despite them being enabled in the configuration\n"));
3660 }
3661 if (ipv4_exit && (! ipv4_enabled))
3662 {
3664 _ (
3665 "Cannot enable IPv4 exit but disable IPv4 on TUN interface, will use ENABLE_IPv4=YES\n"));
3667 }
3668 if (ipv6_exit && (! ipv6_enabled))
3669 {
3671 _ (
3672 "Cannot enable IPv6 exit but disable IPv6 on TUN interface, will use ENABLE_IPv6=YES\n"));
3674 }
3675}
3676
3677
3682static void
3684{
3686 GNUNET_MQ_hd_var_size (dns_request,
3688 struct DnsResponseMessage,
3689 NULL),
3691 };
3692 char *dns_exit;
3693 struct GNUNET_HashCode port;
3694
3695 if (GNUNET_YES !=
3697 "exit",
3698 "EXIT_DNS"))
3699 return;
3700 GNUNET_assert (NULL != (dnsstub = GNUNET_DNSSTUB_start (128)));
3701 dns_exit = NULL;
3702 /* TODO: support using multiple DNS resolvers */
3703 if ((GNUNET_OK !=
3705 "exit",
3706 "DNS_RESOLVER",
3707 &dns_exit)) ||
3708 (GNUNET_OK !=
3710 dns_exit)))
3711 {
3713 "dns",
3714 "DNS_RESOLVER",
3715 _ ("need a valid IPv4 or IPv6 address\n"));
3716 GNUNET_free (dns_exit);
3717 return;
3718 }
3719 /* open port */
3722 &port);
3724 "Opening CADET port %s for DNS exit service\n",
3725 GNUNET_h2s (&port));
3727 &port,
3728 &new_channel,
3729 NULL,
3730 NULL,
3732 handlers);
3733 /* advertise exit */
3735 1);
3739 dns_advertisement.purpose.size = htonl (sizeof(struct
3741 - sizeof(struct
3743 );
3746 GNUNET_CRYPTO_hash ("dns",
3747 strlen ("dns"),
3748 &dht_put_key);
3750 NULL);
3751 GNUNET_free (dns_exit);
3752}
3753
3754
3760static int
3762{
3763 char *exit_ifname;
3764 char *tun_ifname;
3765 char *ipv6addr;
3766 char *ipv6prefix_s;
3767 char *ipv4addr;
3768 char *ipv4mask;
3769
3770 exit_argv[0] = GNUNET_strdup ("exit-gnunet");
3771 if (GNUNET_SYSERR ==
3773 "exit",
3774 "TUN_IFNAME",
3775 &tun_ifname))
3776 {
3778 "EXIT",
3779 "TUN_IFNAME");
3780 return GNUNET_SYSERR;
3781 }
3782 exit_argv[1] = tun_ifname;
3783 if (ipv4_enabled)
3784 {
3785 if (GNUNET_SYSERR ==
3787 "exit",
3788 "EXIT_IFNAME",
3789 &exit_ifname))
3790 {
3792 "EXIT",
3793 "EXIT_IFNAME");
3794 return GNUNET_SYSERR;
3795 }
3796 exit_argv[2] = exit_ifname;
3797 }
3798 else
3799 {
3800 exit_argv[2] = GNUNET_strdup ("-");
3801 }
3802
3803 if (GNUNET_YES == ipv6_enabled)
3804 {
3805 ipv6addr = NULL;
3806 if (((GNUNET_SYSERR ==
3808 "exit",
3809 "IPV6ADDR",
3810 &ipv6addr)) ||
3811 (1 != inet_pton (AF_INET6,
3812 ipv6addr,
3813 &exit_ipv6addr))))
3814 {
3816 "EXIT",
3817 "IPV6ADDR");
3818 GNUNET_free (ipv6addr);
3819 return GNUNET_SYSERR;
3820 }
3821 exit_argv[3] = ipv6addr;
3822 if (GNUNET_SYSERR ==
3824 "exit",
3825 "IPV6PREFIX",
3826 &ipv6prefix_s))
3827 {
3829 "EXIT",
3830 "IPV6PREFIX");
3831 return GNUNET_SYSERR;
3832 }
3833 exit_argv[4] = ipv6prefix_s;
3834 if ((GNUNET_OK !=
3836 "exit",
3837 "IPV6PREFIX",
3838 &ipv6prefix)) ||
3839 (ipv6prefix >= 127))
3840 {
3842 "EXIT",
3843 "IPV6PREFIX",
3844 _ ("Must be a number"));
3845 return GNUNET_SYSERR;
3846 }
3847 }
3848 else
3849 {
3850 /* IPv6 explicitly disabled */
3851 exit_argv[3] = GNUNET_strdup ("-");
3852 exit_argv[4] = GNUNET_strdup ("-");
3853 }
3854 if (GNUNET_YES == ipv4_enabled)
3855 {
3856 ipv4addr = NULL;
3857 if (((GNUNET_SYSERR ==
3859 "exit",
3860 "IPV4ADDR",
3861 &ipv4addr)) ||
3862 (1 != inet_pton (AF_INET,
3863 ipv4addr,
3864 &exit_ipv4addr))))
3865 {
3867 "EXIT",
3868 "IPV4ADDR");
3869 GNUNET_free (ipv4addr);
3870 return GNUNET_SYSERR;
3871 }
3872 exit_argv[5] = ipv4addr;
3873 ipv4mask = NULL;
3874 if (((GNUNET_SYSERR ==
3876 "exit",
3877 "IPV4MASK",
3878 &ipv4mask)) ||
3879 (1 != inet_pton (AF_INET,
3880 ipv4mask,
3881 &exit_ipv4mask))))
3882 {
3884 "EXIT",
3885 "IPV4MASK");
3886 GNUNET_free (ipv4mask);
3887 return GNUNET_SYSERR;
3888 }
3889 exit_argv[6] = ipv4mask;
3890 }
3891 else
3892 {
3893 /* IPv4 explicitly disabled */
3894 exit_argv[5] = GNUNET_strdup ("-");
3895 exit_argv[6] = GNUNET_strdup ("-");
3896 }
3897 exit_argv[7] = NULL;
3898 return GNUNET_OK;
3899}
3900
3901
3910static void
3911run (void *cls,
3912 char *const *args,
3913 const char *cfgfile,
3914 const struct GNUNET_CONFIGURATION_Handle *cfg_)
3915{
3917 GNUNET_MQ_hd_var_size (icmp_remote,
3920 NULL),
3921 GNUNET_MQ_hd_var_size (udp_remote,
3924 NULL),
3925 GNUNET_MQ_hd_var_size (tcp_remote,
3928 NULL),
3929 GNUNET_MQ_hd_var_size (tcp_data,
3932 NULL),
3934 };
3935 struct GNUNET_HashCode port;
3936 char *policy;
3937 char *binary;
3938 char *regex;
3939 char *prefixed_regex;
3940
3941 cfg = cfg_;
3942 if (GNUNET_OK !=
3944 "exit",
3945 "MAX_CONNECTIONS",
3947 max_connections = 1024;
3950 cfg,
3951 "gnunet-helper-exit");
3952 if ((ipv4_exit) || (ipv6_exit))
3953 {
3954 if (GNUNET_YES !=
3956 GNUNET_YES,
3957 "gnunet-vpn - - - 169.1.3.7 255.255.255.0"))
3958 // no nat, ipv4 only
3959 {
3960 GNUNET_free (binary);
3962 _ (
3963 "`%s' is not SUID or the path is invalid, EXIT will not work\n"),
3964 "gnunet-helper-exit");
3966 NULL);
3967 global_ret = 1;
3968 return;
3969 }
3970 }
3971 if (! (ipv4_enabled || ipv6_enabled))
3972 {
3973 GNUNET_free (binary);
3975 _ ("No useful service enabled. Exiting.\n"));
3977 return;
3978 }
3979
3981 NULL);
3983 cfg);
3985 if (NULL == cadet_handle)
3986 {
3987 GNUNET_free (binary);
3989 return;
3990 }
3992 if (GNUNET_OK !=
3994 {
3995 GNUNET_free (binary);
3997 return;
3998 }
3999
4001 GNUNET_NO);
4003 GNUNET_NO);
4008 NULL);
4009
4010 /* Cadet handle acquired, now open ports and announce regular
4011 expressions matching our exit */
4012 if ((GNUNET_YES == ipv4_enabled) &&
4013 (GNUNET_YES == ipv4_exit))
4014 {
4017 &port);
4019 "Opening CADET port %s for IPv4 gateway service\n",
4020 GNUNET_h2s (&port));
4022 &port,
4023 &new_channel,
4024 NULL,
4025 NULL,
4027 handlers);
4028 policy = NULL;
4029 if (GNUNET_OK !=
4031 "exit",
4032 "EXIT_RANGE_IPV4_POLICY",
4033 &policy))
4034 regex = NULL;
4035 else
4036 regex = GNUNET_REGEX_ipv4policy2regex (policy);
4037 GNUNET_free (policy);
4038 if (NULL != regex)
4039 {
4040 (void) GNUNET_asprintf (&prefixed_regex,
4041 "%s%s",
4043 regex);
4045 prefixed_regex,
4048 GNUNET_free (regex);
4049 GNUNET_free (prefixed_regex);
4050 }
4051 }
4052
4054 {
4057 &port);
4059 "Opening CADET port %s for IPv6 gateway service\n",
4060 GNUNET_h2s (&port));
4062 &port,
4063 &new_channel,
4064 NULL,
4065 NULL,
4067 handlers);
4068 policy = NULL;
4069 if (GNUNET_OK !=
4071 "exit",
4072 "EXIT_RANGE_IPV6_POLICY",
4073 &policy))
4074 regex = NULL;
4075 else
4076 regex = GNUNET_REGEX_ipv6policy2regex (policy);
4077 GNUNET_free (policy);
4078 if (NULL != regex)
4079 {
4080 (void) GNUNET_asprintf (&prefixed_regex,
4081 "%s%s",
4083 regex);
4085 prefixed_regex,
4088 GNUNET_free (regex);
4089 GNUNET_free (prefixed_regex);
4090 }
4091 }
4093 GNUNET_NO,
4094 binary,
4095 exit_argv,
4097 NULL,
4098 NULL);
4099 GNUNET_free (binary);
4100}
4101
4102
4110int
4111main (int argc,
4112 char *const *argv)
4113{
4114 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
4116 };
4117
4118 return (GNUNET_OK ==
4120 argc,
4121 argv,
4122 "gnunet-daemon-exit",
4123 gettext_noop (
4124 "Daemon to run to provide an IP exit node for the VPN"),
4125 options,
4126 &run,
4127 NULL)) ? global_ret : 1;
4128}
4129
4130
4131/* end of gnunet-daemon-exit.c */
struct GNUNET_GETOPT_CommandLineOption options[]
Definition 002.c:5
struct GNUNET_MQ_MessageHandlers handlers[]
Definition 003.c:1
struct GNUNET_MessageHeader * msg
Definition 005.c:2
struct GNUNET_MQ_Envelope * env
Definition 005.c:1
int main()
Program to simulate results from GCP_get_desirability_of_path() for various plausible inputs.
#define gettext_noop(String)
Definition gettext.h:74
static int start
Set if we are to start default services (including ARM).
Definition gnunet-arm.c:38
static int ret
Final status code.
Definition gnunet-arm.c:93
static uint16_t port
Port number.
Definition gnunet-bcd.c:146
static char * address
GNS address for this phone.
static int check_udp_remote(void *cls, const struct GNUNET_EXIT_UdpInternetMessage *msg)
Check a request to forward UDP data to the Internet via this peer.
static int check_dns_request(void *cls, const struct DnsResponseMessage *msg)
Check a request via cadet to perform a DNS query.
static void udp_from_helper(const struct GNUNET_TUN_UdpHeader *udp, size_t pktlen, int af, const void *destination_ip, const void *source_ip)
Handles an UDP packet received from the helper.
static struct GNUNET_DHT_Handle * dht
Handle to the DHT.
static void send_udp_packet_via_tun(const struct SocketAddress *destination_address, const struct SocketAddress *source_address, const void *payload, size_t payload_length)
Send a UDP packet via the TUN interface.
static int ipv6_enabled
Do we support IPv6 at all on the TUN interface?
static int check_udp_service(void *cls, const struct GNUNET_EXIT_UdpServiceMessage *msg)
Check a request via cadet to send a request to a UDP service offered by this system.
static void make_up_icmpv4_payload(struct ChannelState *state, struct GNUNET_TUN_IPv4Header *ipp, struct GNUNET_TUN_UdpHeader *udp)
Synthesize a plausible ICMP payload for an ICMPv4 error response on the given channel.
static void clean_channel(void *cls, const struct GNUNET_CADET_Channel *channel)
Function called by cadet whenever an inbound channel is destroyed.
static struct GNUNET_REGEX_Announcement * regex4
Handle to our regex announcement for IPv4.
static void send_packet_to_cadet_channel(struct ChannelState *s, struct GNUNET_MQ_Envelope *env)
Send the given packet via the cadet channel.
static int ipv4_enabled
Do we support IPv4 at all on the TUN interface?
static int check_tcp_service(void *cls, const struct GNUNET_EXIT_TcpServiceStartMessage *start)
Check a request via cadet to send a request to a TCP service offered by this system.
static void send_tcp_packet_via_tun(const struct SocketAddress *destination_address, const struct SocketAddress *source_address, const struct GNUNET_TUN_TcpHeader *tcp_header, const void *payload, size_t payload_length)
Send a TCP packet via the TUN interface.
static struct GNUNET_CONTAINER_MultiHashMap * services
This hashmaps saves interesting things about the configured services.
#define REGEX_MAX_PATH_LEN_IPV4
Maximum path compression length for cadet regex announcing for IPv4 address based regex.
#define DNS_ADVERTISEMENT_TIMEOUT
How long do we typically sign the DNS exit advertisement for?
static struct ChannelState * channels[UINT16_MAX+1]
Array of all open DNS requests from channels.
static unsigned long long ipv6prefix
IPv6 prefix (0..127) from configuration file.
#define REGEX_REFRESH_FREQUENCY
How frequently do we re-announce the regex for the exit?
static struct in6_addr exit_ipv6addr
IPv6 address of our TUN interface.
static struct ChannelState * get_redirect_state(int af, int protocol, const void *destination_ip, uint16_t destination_port, const void *local_ip, uint16_t local_port, struct GNUNET_HashCode *state_key)
Get our connection tracking state.
static void handle_icmp_service(void *cls, const struct GNUNET_EXIT_IcmpServiceMessage *msg)
Process a request via cadet to send ICMP data to a service offered by this system.
static void setup_fresh_address(int af, uint8_t proto, struct SocketAddress *local_address)
We need to create a (unique) fresh local address (IP+port).
static unsigned long long max_connections
If there are at least this many connections, old ones will be removed.
static int global_ret
Return value from 'main'.
static void run(void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg_)
Main function that will be run by the scheduler.
static struct GNUNET_STATISTICS_Handle * stats
Statistics.
static int setup_exit_helper_args()
Initialize exit_argv.
static const struct GNUNET_CONFIGURATION_Handle * cfg
The handle to the configuration used throughout the process.
static struct GNUNET_DNS_Advertisement dns_advertisement
Advertisement message we put into the DHT to advertise us as a DNS exit.
static void * new_service_channel(void *cls, struct GNUNET_CADET_Channel *channel, const struct GNUNET_PeerIdentity *initiator)
Callback from CADET for new channels.
static void prepare_ipv6_packet(const void *payload, size_t payload_length, int protocol, const struct GNUNET_TUN_TcpHeader *tcp_header, const struct SocketAddress *src_address, const struct SocketAddress *dst_address, struct GNUNET_TUN_IPv6Header *pkt6)
Prepare an IPv6 packet for transmission via the TUN interface.
static struct GNUNET_DNSSTUB_Context * dnsstub
Handle to the DNS Stub resolver.
static void send_icmp_packet_via_tun(const struct SocketAddress *destination_address, const struct SocketAddress *source_address, const struct GNUNET_TUN_IcmpHeader *icmp_header, const void *payload, size_t payload_length)
Send an ICMP packet via the TUN interface.
static void dht_put_cont(void *cls)
Function called when the DHT PUT operation is complete.
static int check_icmp_service(void *cls, const struct GNUNET_EXIT_IcmpServiceMessage *msg)
Check a request via cadet to send ICMP data to a service offered by this system.
static void store_service(int proto, const char *name, uint16_t destination_port, struct LocalService *service)
Given a service descriptor and a destination port, find the respective service entry.
static struct GNUNET_CONTAINER_MultiHashMap * connections_map
This hashmaps contains the mapping from peer, service-descriptor, source-port and destination-port to...
static int ipv6_exit
Are we an IPv6-exit?
static void icmp_from_helper(const struct GNUNET_TUN_IcmpHeader *icmp, size_t pktlen, int af, const void *destination_ip, const void *source_ip)
Handles an ICMP packet received from the helper.
static void add_services(int proto, char *cpy, const char *name)
Add services to the service map.
static struct GNUNET_CONTAINER_Heap * connections_heap
Heap so we can quickly find "old" connections.
static void tcp_from_helper(const struct GNUNET_TUN_TcpHeader *tcp, size_t pktlen, int af, const void *destination_ip, const void *source_ip)
Handles a TCP packet received from the helper.
static void prepare_ipv4_packet(const void *payload, size_t payload_length, int protocol, const struct GNUNET_TUN_TcpHeader *tcp_header, const struct SocketAddress *src_address, const struct SocketAddress *dst_address, struct GNUNET_TUN_IPv4Header *pkt4)
Prepare an IPv4 packet for transmission via the TUN interface.
static struct GNUNET_DHT_PutHandle * dht_put
Handle for ongoing DHT PUT operations to advertise exit service.
#define REGEX_MAX_PATH_LEN_IPV6
Maximum path compression length for cadet regex announcing for IPv6 address based regex.
static void hash_redirect_info(struct GNUNET_HashCode *hash, const struct RedirectInformation *ri)
Given IP information about a connection, calculate the respective hash we would use for the connectio...
static void handle_tcp_service(void *cls, const struct GNUNET_EXIT_TcpServiceStartMessage *start)
Process a request via cadet to send a request to a TCP service offered by this system.
static uint16_t make_up_icmp_service_payload(struct ChannelState *state, char *buf)
Setup ICMP payload for ICMP error messages.
static struct GNUNET_REGEX_Announcement * regex6
Handle to our regex announcement for IPv4.
static void handle_tcp_remote(void *cls, const struct GNUNET_EXIT_TcpInternetStartMessage *start)
Process a request to forward TCP data to the Internet via this peer.
static struct GNUNET_CADET_Handle * cadet_handle
The handle to cadet.
static void dummy_task(void *cls)
Function scheduled as very last function if the service disabled itself because the helper is not ins...
static void do_dht_put(void *cls)
We are running a DNS exit service, advertise it in the DHT.
static int message_token(void *cls, const struct GNUNET_MessageHeader *message)
Receive packets from the helper-process.
static void handle_icmp_remote(void *cls, const struct GNUNET_EXIT_IcmpInternetMessage *msg)
Process a request to forward ICMP data to the Internet via this peer.
static void handle_udp_service(void *cls, const struct GNUNET_EXIT_UdpServiceMessage *msg)
Process a request via cadet to send a request to a UDP service offered by this system.
static void handle_tcp_data(void *cls, const struct GNUNET_EXIT_TcpDataMessage *data)
Process a request to forward TCP data on an established connection via this peer.
static char * exit_argv[8]
Arguments to the exit helper.
static void read_service_conf(void *cls, const char *section)
Reads the configuration and populates #udp_services and #tcp_services.
static struct GNUNET_CADET_Port * cadet_port4
Port for IPv4 exit.
static GNUNET_NETWORK_STRUCT_END void process_dns_result(void *cls, const struct GNUNET_TUN_DnsHeader *dns, size_t r)
Callback called from DNSSTUB resolver when a resolution succeeded.
static struct in_addr exit_ipv4mask
IPv4 netmask of our TUN interface.
static void parse_ip_options()
Figure out which IP versions we should support (and which are supported by the OS) according to our c...
static struct in_addr exit_ipv4addr
IPv4 address of our TUN interface.
static int free_service_record(void *cls, const struct GNUNET_HashCode *key, void *value)
Free memory associated with a service record.
static struct GNUNET_HashCode dht_put_key
Key we store the DNS advertismenet under.
static struct GNUNET_CRYPTO_EddsaPrivateKey * peer_key
Private key for this peer.
static void * new_channel(void *cls, struct GNUNET_CADET_Channel *channel, const struct GNUNET_PeerIdentity *initiator)
Callback from CADET for new channels.
#define LOG(kind,...)
Generic logging shorthand.
static int check_tcp_data(void *cls, const struct GNUNET_EXIT_TcpDataMessage *data)
Check a request to forward TCP data on an established connection via this peer.
#define DHT_PUT_FREQUENCY
How frequently do we re-announce the DNS exit in the DHT?
static int check_icmp_remote(void *cls, const struct GNUNET_EXIT_IcmpInternetMessage *msg)
Check a request to forward ICMP data to the Internet via this peer.
static void handle_udp_remote(void *cls, const struct GNUNET_EXIT_UdpInternetMessage *msg)
Process a request to forward UDP data to the Internet via this peer.
static void setup_state_record(struct ChannelState *state)
We are starting a fresh connection (TCP or UDP) and need to pick a source port and IP address (within...
static struct GNUNET_CADET_Port * dns_port
Port for DNS exit.
static struct GNUNET_HELPER_Handle * helper_handle
The handle to the helper.
static int ipv4_exit
Are we an IPv4-exit?
static int free_iterate(void *cls, const struct GNUNET_HashCode *hash, void *value)
Function that frees everything from a hashmap.
static void advertise_dns_exit()
Helper function to open the CADET port for DNS exits and to advertise the DNS exit (if applicable).
static struct GNUNET_CADET_Port * cadet_port6
Port for IPv6 exit.
static struct GNUNET_SCHEDULER_Task * dht_task
Task for doing DHT PUTs to advertise exit service.
static int check_tcp_remote(void *cls, const struct GNUNET_EXIT_TcpInternetStartMessage *start)
Check a request to forward TCP data to the Internet via this peer.
static void make_up_icmpv6_payload(struct ChannelState *state, struct GNUNET_TUN_IPv6Header *ipp, struct GNUNET_TUN_UdpHeader *udp)
Synthesize a plausible ICMP payload for an ICMPv6 error response on the given channel.
static void handle_dns_request(void *cls, const struct DnsResponseMessage *msg)
Process a request via cadet to perform a DNS query.
static char * data
The data to insert into the dht.
struct GNUNET_HashCode key
The key used in the DHT.
static struct GNUNET_TIME_Relative expiration
User supplied expiration value.
static char * name
Name (label) of the records to list.
static int state
The current state of the parser.
static char * res
Currently read line or NULL on EOF.
static char * value
Value of the record to add/remove.
static uint8_t proto
Protocol to use.
static struct GNUNET_NETWORK_Handle * ls
Listen socket for STUN processing.
Definition gnunet-nat.c:85
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
static unsigned long long payload
How much data are we currently storing in the database?
static struct GNUNET_CADET_Port * cadet_port
Listen port for incoming requests.
static void cleanup()
Cleanup task.
static unsigned long long remote_port
Remote host's port.
static int ipv4
Option -4: IPv4 requested.
Definition gnunet-vpn.c:60
static int udp
Option -u: UDP requested.
Definition gnunet-vpn.c:75
static int ipv6
Option -6: IPv6 requested.
Definition gnunet-vpn.c:65
static int tcp
Option -t: TCP requested.
Definition gnunet-vpn.c:70
@ GNUNET_BLOCK_TYPE_DNS
Block for storing DNS exit service advertisements.
#define GNUNET_SIGNATURE_PURPOSE_DNS_RECORD
Signature on a GNUNET_DNS_Advertisement.
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message,...
#define GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX
Internet exit regex prefix.
#define GNUNET_APPLICATION_PORT_INTERNET_RESOLVER
Internet DNS resolution (external DNS gateway).
#define GNUNET_APPLICATION_PORT_IPV4_GATEWAY
Internet IPv4 gateway (any TCP/UDP/ICMP).
#define GNUNET_APPLICATION_PORT_IPV6_GATEWAY
Internet IPv6 gateway (any TCP/UDP/ICMP).
struct GNUNET_CADET_Handle * GNUNET_CADET_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the MQ-based cadet service.
Definition cadet_api.c:897
void GNUNET_CADET_receive_done(struct GNUNET_CADET_Channel *channel)
Indicate readiness to receive the next message on a channel.
Definition cadet_api.c:875
void GNUNET_CADET_channel_destroy(struct GNUNET_CADET_Channel *channel)
Destroy an existing channel.
Definition cadet_api.c:833
struct GNUNET_MQ_Handle * GNUNET_CADET_get_mq(const struct GNUNET_CADET_Channel *channel)
Obtain the message queue for a connected channel.
Definition cadet_api.c:1081
struct GNUNET_CADET_Port * GNUNET_CADET_open_port(struct GNUNET_CADET_Handle *h, const struct GNUNET_HashCode *port, GNUNET_CADET_ConnectEventHandler connects, void *connects_cls, GNUNET_CADET_WindowSizeEventHandler window_changes, GNUNET_CADET_DisconnectEventHandler disconnects, const struct GNUNET_MQ_MessageHandler *handlers)
Open a port to receive incoming MQ-based channels.
Definition cadet_api.c:966
void GNUNET_CADET_disconnect(struct GNUNET_CADET_Handle *handle)
Disconnect from the cadet service.
Definition cadet_api.c:777
void GNUNET_CADET_close_port(struct GNUNET_CADET_Port *p)
Close a port opened with GNUNET_CADET_open_port.
Definition cadet_api.c:804
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
void GNUNET_CONFIGURATION_iterate_sections(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_CONFIGURATION_SectionIterator iter, void *iter_cls)
Iterate over all sections in the configuration.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
void GNUNET_CRYPTO_eddsa_key_get_public(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, struct GNUNET_CRYPTO_EddsaPublicKey *pub)
Extract the public key for the given private key.
Definition crypto_ecc.c:201
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_sign_(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, struct GNUNET_CRYPTO_EddsaSignature *sig)
EdDSA sign a given block.
Definition crypto_ecc.c:625
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
struct GNUNET_CRYPTO_EddsaPrivateKey * GNUNET_CRYPTO_eddsa_key_create_from_configuration(const struct GNUNET_CONFIGURATION_Handle *cfg)
Create a new private key by reading our peer's key from the file specified in the configuration.
@ GNUNET_CRYPTO_QUALITY_WEAK
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
void GNUNET_DHT_put_cancel(struct GNUNET_DHT_PutHandle *ph)
Cancels a DHT PUT operation.
Definition dht_api.c:1144
struct GNUNET_DHT_PutHandle * GNUNET_DHT_put(struct GNUNET_DHT_Handle *handle, const struct GNUNET_HashCode *key, uint32_t desired_replication_level, enum GNUNET_DHT_RouteOption options, enum GNUNET_BLOCK_Type type, size_t size, const void *data, struct GNUNET_TIME_Absolute exp, GNUNET_SCHEDULER_TaskCallback cont, void *cont_cls)
Perform a PUT operation storing data in the DHT.
Definition dht_api.c:1081
struct GNUNET_DHT_Handle * GNUNET_DHT_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, unsigned int ht_len)
Initialize the connection with the DHT service.
Definition dht_api.c:1030
void GNUNET_DHT_disconnect(struct GNUNET_DHT_Handle *handle)
Shutdown connection with the DHT service.
Definition dht_api.c:1053
@ GNUNET_DHT_RO_NONE
Default.
struct GNUNET_DNSSTUB_Context * GNUNET_DNSSTUB_start(unsigned int num_sockets)
Start a DNS stub resolver.
Definition dnsstub.c:586
int GNUNET_DNSSTUB_add_dns_ip(struct GNUNET_DNSSTUB_Context *ctx, const char *dns_ip)
Add nameserver for use by the DNSSTUB.
Definition dnsstub.c:613
void GNUNET_DNSSTUB_stop(struct GNUNET_DNSSTUB_Context *ctx)
Cleanup DNSSTUB resolver.
Definition dnsstub.c:705
struct GNUNET_DNSSTUB_RequestSocket * GNUNET_DNSSTUB_resolve(struct GNUNET_DNSSTUB_Context *ctx, const void *request, size_t request_len, GNUNET_DNSSTUB_ResultCallback rc, void *rc_cls)
Perform DNS resolution using our default IP from init.
Definition dnsstub.c:526
#define GNUNET_GETOPT_OPTION_END
Marker for the end of the list of options.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition crypto_hash.c:41
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MultiHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_remove(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value)
Remove the given key-value pair from the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY
There must only be one value per key; storing a value should fail if a value under the same key alrea...
void * GNUNET_CONTAINER_heap_remove_node(struct GNUNET_CONTAINER_HeapNode *node)
Removes a node from the heap.
void * GNUNET_CONTAINER_heap_remove_root(struct GNUNET_CONTAINER_Heap *heap)
Remove root of the heap.
void GNUNET_CONTAINER_heap_update_cost(struct GNUNET_CONTAINER_HeapNode *node, GNUNET_CONTAINER_HeapCostType new_cost)
Updates the cost of any node in the tree.
struct GNUNET_CONTAINER_HeapNode * GNUNET_CONTAINER_heap_insert(struct GNUNET_CONTAINER_Heap *heap, void *element, GNUNET_CONTAINER_HeapCostType cost)
Inserts a new element into the heap.
unsigned int GNUNET_CONTAINER_heap_get_size(const struct GNUNET_CONTAINER_Heap *heap)
Get the current size of the heap.
struct GNUNET_CONTAINER_Heap * GNUNET_CONTAINER_heap_create(enum GNUNET_CONTAINER_HeapOrder order)
Create a new heap.
void GNUNET_CONTAINER_heap_destroy(struct GNUNET_CONTAINER_Heap *heap)
Destroys the heap.
@ GNUNET_CONTAINER_HEAP_ORDER_MIN
Heap with the minimum cost at the root.
struct GNUNET_HELPER_SendHandle * GNUNET_HELPER_send(struct GNUNET_HELPER_Handle *h, const struct GNUNET_MessageHeader *msg, bool can_drop, GNUNET_HELPER_Continuation cont, void *cont_cls)
Send an message to the helper.
Definition helper.c:615
struct GNUNET_HELPER_Handle * GNUNET_HELPER_start(const struct GNUNET_OS_ProjectData *pd, int with_control_pipe, const char *binary_name, char *const binary_argv[], GNUNET_MessageTokenizerCallback cb, GNUNET_HELPER_ExceptionCallback exp_cb, void *cb_cls)
Starts a helper and begins reading from it.
Definition helper.c:460
void GNUNET_HELPER_stop(struct GNUNET_HELPER_Handle *h, int soft_kill)
Kills the helper, closes the pipe, frees the handle and calls wait() on the helper process.
Definition helper.c:538
#define GNUNET_NETWORK_STRUCT_BEGIN
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
#define GNUNET_log(kind,...)
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32;.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
#define GNUNET_ALIGN
gcc-ism to force alignment; we use this to align char-arrays that may then be cast to 'struct's.
#define GNUNET_UNUSED
gcc-ism to document unused arguments
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
void GNUNET_log_config_invalid(enum GNUNET_ErrorType kind, const char *section, const char *option, const char *required)
Log error message about invalid configuration option value.
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition mq.c:305
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
enum GNUNET_GenericReturnValue GNUNET_NETWORK_test_pf(int pf)
Test if the given protocol family is supported by this system.
Definition network.c:79
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_gnunet(void)
Return default project data used by 'libgnunetutil' for GNUnet.
enum GNUNET_GenericReturnValue GNUNET_OS_check_helper_binary(const char *binary, bool check_suid, const char *params)
Check whether an executable exists and possibly if the suid bit is set on the file.
char * GNUNET_OS_get_suid_binary_path(const struct GNUNET_OS_ProjectData *pd, const struct GNUNET_CONFIGURATION_Handle *cfg, const char *progname)
Given the name of a helper, service or daemon binary construct the full path to the binary using the ...
enum GNUNET_GenericReturnValue GNUNET_PROGRAM_run(const struct GNUNET_OS_ProjectData *pd, int argc, char *const *argv, const char *binaryName, const char *binaryHelp, const struct GNUNET_GETOPT_CommandLineOption *options, GNUNET_PROGRAM_Main task, void *task_cls)
Run a standard GNUnet command startup sequence (initialize loggers and configuration,...
Definition program.c:407
#define GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY
Type of messages containing an UDP packet from a remote host.
#define GNUNET_MESSAGE_TYPE_VPN_HELPER
Type of messages between the gnunet-vpn-helper and the daemon.
#define GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT
Type of messages containing an TCP packet of an established connection.
#define GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE
Type of messages containing an ICMP packet for a service.
#define GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START
Type of messages containing an TCP packet for the Internet.
#define GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START
Type of messages containing an TCP packet for a service.
#define GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE
Type of messages containing an UDP packet for a service.
#define GNUNET_MESSAGE_TYPE_VPN_DNS_TO_INTERNET
Type of messages containing an DNS request for a DNS exit service.
#define GNUNET_MESSAGE_TYPE_VPN_DNS_FROM_INTERNET
Type of messages containing an DNS reply from a DNS exit service.
#define GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET
Type of messages containing an ICMP packet for the Internet.
#define GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN
Type of messages containing an TCP packet of an established connection.
#define GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET
Type of messages containing an UDP packet for the Internet.
#define GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN
Type of messages containing an ICMP packet for the VPN.
char * GNUNET_REGEX_ipv6policy2regex(const char *policy)
Convert an exit policy to a regular expression.
Definition regex.c:725
void GNUNET_REGEX_announce_cancel(struct GNUNET_REGEX_Announcement *a)
Stop announcing the regex specified by the given handle.
struct GNUNET_REGEX_Announcement * GNUNET_REGEX_announce(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *regex, struct GNUNET_TIME_Relative refresh_delay, uint16_t compression)
Announce this peer under the given regular expression.
char * GNUNET_REGEX_ipv4policy2regex(const char *policy)
Convert an exit policy to a regular expression.
Definition regex.c:682
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition scheduler.c:567
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition scheduler.c:1339
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:980
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition scheduler.c:1304
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition scheduler.c:1277
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
#define GNUNET_TIME_UNIT_HOURS
One hour.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition time.c:406
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition time.c:111
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition time.c:741
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition time.c:316
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition time.c:640
void GNUNET_TUN_initialize_ipv6_header(struct GNUNET_TUN_IPv6Header *ip, uint8_t protocol, uint16_t payload_length, const struct in6_addr *src, const struct in6_addr *dst)
Initialize an IPv6 header.
Definition tun.c:115
void GNUNET_TUN_calculate_udp4_checksum(const struct GNUNET_TUN_IPv4Header *ip, struct GNUNET_TUN_UdpHeader *udp, const void *payload, uint16_t payload_length)
Calculate IPv4 UDP checksum.
Definition tun.c:193
GNUNET_NETWORK_STRUCT_END void GNUNET_TUN_initialize_ipv4_header(struct GNUNET_TUN_IPv4Header *ip, uint8_t protocol, uint16_t payload_length, const struct in_addr *src, const struct in_addr *dst)
Initialize an IPv4 header.
Definition tun.c:80
#define GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM
void GNUNET_TUN_calculate_icmp_checksum(struct GNUNET_TUN_IcmpHeader *icmp, const void *payload, uint16_t payload_length)
Calculate ICMP checksum.
Definition tun.c:255
#define GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST
#define GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED
#define GNUNET_TUN_ICMPTYPE6_ECHO_REPLY
#define ETH_P_IPV6
Number for IPv6.
void GNUNET_TUN_compute_service_cadet_port(const struct GNUNET_HashCode *desc, uint16_t ip_port, struct GNUNET_HashCode *cadet_port)
Compute the CADET port given a service descriptor (returned from GNUNET_TUN_service_name_to_hash) and...
Definition tun.c:57
#define ETH_P_IPV4
Number for IPv4.
#define GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED
void GNUNET_TUN_calculate_tcp6_checksum(const struct GNUNET_TUN_IPv6Header *ip, struct GNUNET_TUN_TcpHeader *tcp, const void *payload, uint16_t payload_length)
Calculate IPv6 TCP checksum.
Definition tun.c:165
void GNUNET_TUN_service_name_to_hash(const char *service_name, struct GNUNET_HashCode *hc)
Hash the service name of a hosted service to the hash code that is used to identify the service on th...
Definition tun.c:38
#define GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE
#define GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH
void GNUNET_TUN_calculate_tcp4_checksum(const struct GNUNET_TUN_IPv4Header *ip, struct GNUNET_TUN_TcpHeader *tcp, const void *payload, uint16_t payload_length)
Calculate IPv4 TCP checksum.
Definition tun.c:135
#define GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE
#define GNUNET_TUN_ICMPTYPE_ECHO_REQUEST
#define GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG
#define GNUNET_TUN_ICMPTYPE_ECHO_REPLY
void GNUNET_TUN_calculate_udp6_checksum(const struct GNUNET_TUN_IPv6Header *ip, struct GNUNET_TUN_UdpHeader *udp, const void *payload, uint16_t payload_length)
Calculate IPv6 UDP checksum.
Definition tun.c:224
static unsigned int size
Size of the "table".
Definition peer.c:68
#define _(String)
GNU gettext support macro.
Definition platform.h:179
This struct is saved into connections_map to allow finding the right channel given an IP packet from ...
struct LocalService * serv
Associated service record, or NULL for no service.
uint16_t my_id
DNS request ID that we used for forwarding.
struct GNUNET_HashCode state_key
Key this state has in the connections_map.
struct ChannelState::@46::@47 tcp_udp
union ChannelState::@71 destination_ip
Destination IP address used by the source on our end (this is the IP that we pick freely within the V...
struct GNUNET_DNSSTUB_RequestSocket * rs
Socket we are using to transmit this request (must match if we receive a response).
int af
Address family used for this channel on the local TUN interface.
struct GNUNET_CADET_Channel * channel
Cadet channel that is used for this connection.
struct GNUNET_PeerIdentity peer
Who is the other end of this channel.
int is_dns
GNUNET_NO if this is a channel for TCP/UDP, GNUNET_YES if this is a channel for DNS,...
struct ChannelState::@46::@48 dns
struct GNUNET_CONTAINER_HeapNode * heap_node
Heap node for this state in the connections_heap.
uint8_t protocol
IPPROTO_TCP or IPPROTO_UDP once bound.
uint16_t destination_port
Destination port used by the sender on our end; 0 for uninitialized.
uint16_t original_id
Original DNS request ID as used by the client.
struct RedirectInformation ri
Primary redirection information for this connection.
union ChannelState::@46 specifics
Message with a DNS response.
struct GNUNET_MessageHeader header
GNUnet header, of type GNUNET_MESSAGE_TYPE_VPN_DNS_FROM_INTERNET.
struct GNUNET_TUN_DnsHeader dns
DNS header.
Opaque handle to a channel.
Definition cadet.h:116
Opaque handle to the service.
Definition cadet_api.c:39
Opaque handle to a port.
Definition cadet_api.c:80
Handle to a node in a heap.
Internal representation of the hash map.
uint32_t size
How many bytes does this signature sign? (including this purpose header); in network byte order (!...
uint32_t purpose
What does this signature vouch for? This must contain a GNUNET_SIGNATURE_PURPOSE_XXX constant (from g...
Private ECC key encoded for transmission.
an ECC signature using EdDSA.
Connection to the DHT service.
Definition dht_api.c:235
Handle to a PUT request.
Definition dht_api.c:43
Handle to the stub resolver.
Definition dnsstub.c:125
UDP socket we are using for sending DNS requests to the Internet.
Definition dnsstub.c:46
This is the structure describing an DNS exit service.
Definition block_dns.h:45
struct GNUNET_PeerIdentity peer
The peer providing this service.
Definition block_dns.h:65
struct GNUNET_TIME_AbsoluteNBO expiration_time
When does this signature expire?
Definition block_dns.h:60
struct GNUNET_CRYPTO_EddsaSignature signature
Signature of the peer affirming that it is offering the service.
Definition block_dns.h:49
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
Beginning of signed portion of the record, signs everything until the end of the struct.
Definition block_dns.h:55
Message send via cadet to an exit daemon to forward ICMP data to the Internet.
Definition exit.h:237
Message send via cadet to an exit daemon to send ICMP data to a local service.
Definition exit.h:206
Message send via cadet to the vpn service to send ICMP data to the VPN's TUN interface.
Definition exit.h:272
struct GNUNET_TUN_IcmpHeader icmp_header
ICMP header to use.
Definition exit.h:287
int32_t af
Address family, AF_INET or AF_INET6, in network byte order.
Definition exit.h:282
Message send via cadet between VPN and entry and an exit daemon to transmit TCP data between the VPN ...
Definition exit.h:95
uint32_t reserved
Always 0.
Definition exit.h:104
struct GNUNET_TUN_TcpHeader tcp_header
Skeleton of the TCP header to send.
Definition exit.h:110
Message send via cadet to an exit daemon to initiate forwarding of TCP data to the Internet.
Definition exit.h:64
Message send via cadet to an exit daemon to initiate forwarding of TCP data to a local service.
Definition exit.h:38
Message send via cadet to an exit daemon to forward UDP data to the Internet.
Definition exit.h:146
Message send from exit daemon back to the UDP entry point (used for both Internet and Service exit re...
Definition exit.h:179
uint16_t source_port
Source port to use for the UDP reply (0 to use the same port as for the original request).
Definition exit.h:189
uint16_t destination_port
Destination port to use for the UDP reply (0 to use the same port as for the original request).
Definition exit.h:195
Message send via cadet to an exit daemon to send UDP data to a local service.
Definition exit.h:121
Definition of a command line option.
The handle to a helper process.
Definition helper.c:77
A 512-bit hashcode.
Message handler for a specific message type.
Header for all communications.
The identity of the host (wraps the signing key of the peer).
struct GNUNET_CRYPTO_EddsaPublicKey public_key
Handle to store cached data about a regex announce.
Entry in list of pending tasks.
Definition scheduler.c:136
Handle for the service.
Time for absolute times used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.
uint16_t id
Unique identifier for the request/response.
Standard IPv4 header.
uint16_t total_length
Length of the packet, including this header.
uint8_t protocol
L4-protocol, for example, IPPROTO_UDP or IPPROTO_TCP.
struct in_addr source_address
Origin of the packet.
struct in_addr destination_address
Destination of the packet.
Standard IPv6 header.
struct in6_addr source_address
Origin of the packet.
uint8_t next_header
For example, IPPROTO_UDP or IPPROTO_TCP.
struct in6_addr destination_address
Destination of the packet.
uint16_t payload_length
Length of the payload, excluding this header.
Header from Linux TUN interface.
uint16_t proto
Here we get an ETH_P_-number.
uint16_t flags
Some flags (unused).
TCP packet header.
uint16_t source_port
Source port (in NBO).
unsigned int off
Number of 32-bit words in TCP header.
UDP packet header.
uint16_t len
Number of bytes of payload.
uint16_t destination_port
Destination port (in NBO).
uint16_t source_port
Source port (in NBO).
This struct is saved into the services-hashmap to represent a service this peer is specifically offer...
int16_t is_udp
GNUNET_YES if this is a UDP service, otherwise TCP.
struct GNUNET_CADET_Port * port
Open port with CADET.
struct SocketAddress address
Remote address to use for the service.
struct GNUNET_HashCode descriptor
Descriptor for the service (CADET port).
char * name
DNS name of the service.
Information we use to track a connection (the classical 6-tuple of IP-version, protocol,...
struct SocketAddress local_address
Address information we used locally (AF and proto must match "remote_address").
struct SocketAddress remote_address
Address information for the other party (equivalent of the arguments one would give to "connect").
Information about an address.
int af
AF_INET or AF_INET6.
union SocketAddress::@45 address
Remote address information.
uint8_t proto
IPPROTO_TCP or IPPROTO_UDP;.
struct in_addr ipv4
Address, if af is AF_INET.
uint16_t port
Remote port, in host byte order!
struct in6_addr ipv6
Address, if af is AF_INET6.

◆ DHT_PUT_FREQUENCY

#define DHT_PUT_FREQUENCY
Value:

How frequently do we re-announce the DNS exit in the DHT?

Definition at line 71 of file gnunet-daemon-exit.c.

◆ DNS_ADVERTISEMENT_TIMEOUT

#define DNS_ADVERTISEMENT_TIMEOUT
Value:

How long do we typically sign the DNS exit advertisement for?

Definition at line 77 of file gnunet-daemon-exit.c.

◆ LOG

#define LOG (   kind,
  ... 
)     GNUNET_log_from (kind, "exit", __VA_ARGS__);

Generic logging shorthand.

Definition at line 84 of file gnunet-daemon-exit.c.

Function Documentation

◆ process_dns_result()

static GNUNET_NETWORK_STRUCT_END void process_dns_result ( void *  cls,
const struct GNUNET_TUN_DnsHeader dns,
size_t  r 
)
static

Callback called from DNSSTUB resolver when a resolution succeeded.

Parameters
clsNULL
dnsthe response itself
rnumber of bytes in dns

Definition at line 455 of file gnunet-daemon-exit.c.

458{
459 struct ChannelState *ts;
460 struct GNUNET_MQ_Envelope *env;
461 struct DnsResponseMessage *resp;
462
464 "Processing DNS result from stub resolver\n");
465 GNUNET_assert (NULL == cls);
466 if (NULL == dns)
467 return;
468 /* Handle case that this is a reply to a request from a CADET DNS channel */
469 ts = channels[dns->id];
470 if (NULL == ts)
471 return;
473 "Got a response from the stub resolver for DNS request received via CADET!\n");
474 channels[dns->id] = NULL;
475 env = GNUNET_MQ_msg_extra (resp,
476 r - sizeof(struct GNUNET_TUN_DnsHeader),
478 GNUNET_memcpy (&resp->dns,
479 dns,
480 r);
481 resp->dns.id = ts->specifics.dns.original_id;
483 env);
484}

References ChannelState::channel, channels, ChannelState::dns, DnsResponseMessage::dns, env, GNUNET_assert, GNUNET_CADET_get_mq(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_VPN_DNS_FROM_INTERNET, GNUNET_MQ_msg_extra, GNUNET_MQ_send(), GNUNET_TUN_DnsHeader::id, LOG, ChannelState::original_id, and ChannelState::specifics.

Referenced by handle_dns_request().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_dns_request()

static int check_dns_request ( void *  cls,
const struct DnsResponseMessage msg 
)
static

Check a request via cadet to perform a DNS query.

Parameters
clsour struct ChannelState *
msgthe actual message
Returns
GNUNET_OK to keep the connection open, GNUNET_SYSERR to close it (signal serious error)

Definition at line 496 of file gnunet-daemon-exit.c.

498{
499 struct ChannelState *ts = cls;
500
501 if (NULL == dnsstub)
502 {
503 GNUNET_break (0);
504 return GNUNET_SYSERR;
505 }
506 if (GNUNET_NO == ts->is_dns)
507 {
508 GNUNET_break_op (0);
509 return GNUNET_SYSERR;
510 }
511 return GNUNET_OK;
512}

References dnsstub, GNUNET_break, GNUNET_break_op, GNUNET_NO, GNUNET_OK, GNUNET_SYSERR, and ChannelState::is_dns.

◆ handle_dns_request()

static void handle_dns_request ( void *  cls,
const struct DnsResponseMessage msg 
)
static

Process a request via cadet to perform a DNS query.

Parameters
clsour struct ChannelState *
msgthe actual message

Definition at line 522 of file gnunet-daemon-exit.c.

524{
525 struct ChannelState *ts = cls;
526 size_t mlen = ntohs (msg->header.size);
527 size_t dlen = mlen - sizeof(struct GNUNET_MessageHeader);
528 char buf[dlen] GNUNET_ALIGN;
529 struct GNUNET_TUN_DnsHeader *dns_out;
530
531 if (GNUNET_SYSERR == ts->is_dns)
532 {
533 /* channel is DNS from now on */
534 ts->is_dns = GNUNET_YES;
535 }
536 ts->specifics.dns.original_id = msg->dns.id;
537 if (channels[ts->specifics.dns.my_id] == ts)
538 channels[ts->specifics.dns.my_id] = NULL;
541 UINT16_MAX
542 + 1);
543 channels[ts->specifics.dns.my_id] = ts;
544 GNUNET_memcpy (buf,
545 &msg->dns,
546 dlen);
547 dns_out = (struct GNUNET_TUN_DnsHeader *) buf;
548 dns_out->id = ts->specifics.dns.my_id;
550 buf,
551 dlen,
553 NULL);
554 if (NULL == ts->specifics.dns.rs)
555 {
556 GNUNET_break_op (0);
557 return;
558 }
560}

References ChannelState::channel, channels, ChannelState::dns, dnsstub, GNUNET_ALIGN, GNUNET_break_op, GNUNET_CADET_receive_done(), GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CRYPTO_random_u32(), GNUNET_DNSSTUB_resolve(), GNUNET_memcpy, GNUNET_SYSERR, GNUNET_YES, GNUNET_TUN_DnsHeader::id, ChannelState::is_dns, msg, ChannelState::my_id, ChannelState::original_id, process_dns_result(), ChannelState::rs, GNUNET_MessageHeader::size, and ChannelState::specifics.

Here is the call graph for this function:

◆ hash_redirect_info()

static void hash_redirect_info ( struct GNUNET_HashCode hash,
const struct RedirectInformation ri 
)
static

Given IP information about a connection, calculate the respective hash we would use for the connections_map.

Parameters
hashresulting hash
riinformation about the connection

Definition at line 571 of file gnunet-daemon-exit.c.

573{
574 char *off;
575
576 memset (hash,
577 0,
578 sizeof(struct GNUNET_HashCode));
579 /* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash,
580 so we put the IP address in there (and hope for few collisions) */
581 off = (char *) hash;
582 switch (ri->remote_address.af)
583 {
584 case AF_INET:
585 GNUNET_memcpy (off,
587 sizeof(struct in_addr));
588 off += sizeof(struct in_addr);
589 break;
590
591 case AF_INET6:
592 GNUNET_memcpy (off,
594 sizeof(struct in6_addr));
595 off += sizeof(struct in_addr);
596 break;
597
598 default:
599 GNUNET_assert (0);
600 }
601 GNUNET_memcpy (off,
602 &ri->remote_address.port,
603 sizeof(uint16_t));
604 off += sizeof(uint16_t);
605 switch (ri->local_address.af)
606 {
607 case AF_INET:
608 GNUNET_memcpy (off,
610 sizeof(struct in_addr));
611 off += sizeof(struct in_addr);
612 break;
613
614 case AF_INET6:
615 GNUNET_memcpy (off,
617 sizeof(struct in6_addr));
618 off += sizeof(struct in_addr);
619 break;
620
621 default:
622 GNUNET_assert (0);
623 }
624 GNUNET_memcpy (off,
625 &ri->local_address.port,
626 sizeof(uint16_t));
627 off += sizeof(uint16_t);
628 GNUNET_memcpy (off,
630 sizeof(uint8_t));
631 /* off += sizeof (uint8_t); */
632}

References SocketAddress::address, SocketAddress::af, GNUNET_assert, GNUNET_memcpy, SocketAddress::ipv4, SocketAddress::ipv6, RedirectInformation::local_address, SocketAddress::port, SocketAddress::proto, and RedirectInformation::remote_address.

Referenced by get_redirect_state().

Here is the caller graph for this function:

◆ get_redirect_state()

static struct ChannelState * get_redirect_state ( int  af,
int  protocol,
const void *  destination_ip,
uint16_t  destination_port,
const void *  local_ip,
uint16_t  local_port,
struct GNUNET_HashCode state_key 
)
static

Get our connection tracking state.

Warns if it does not exists, refreshes the timestamp if it does exist.

Parameters
afaddress family
protocolIPPROTO_UDP or IPPROTO_TCP
destination_iptarget IP
destination_porttarget port
local_iplocal IP
local_portlocal port
state_keyset to hash's state if non-NULL
Returns
NULL if we have no tracking information for this tuple

Definition at line 649 of file gnunet-daemon-exit.c.

656{
657 struct RedirectInformation ri;
658 struct GNUNET_HashCode key;
659 struct ChannelState *state;
660
661 if (((af == AF_INET) && (protocol == IPPROTO_ICMP)) ||
662 ((af == AF_INET6) && (protocol == IPPROTO_ICMPV6)))
663 {
664 /* ignore ports */
666 local_port = 0;
667 }
669 if (af == AF_INET)
670 ri.remote_address.address.ipv4 = *((struct in_addr*) destination_ip);
671 else
672 ri.remote_address.address.ipv6 = *((struct in6_addr*) destination_ip);
673 ri.remote_address.port = destination_port;
674 ri.remote_address.proto = protocol;
675 ri.local_address.af = af;
676 if (af == AF_INET)
677 ri.local_address.address.ipv4 = *((struct in_addr*) local_ip);
678 else
679 ri.local_address.address.ipv6 = *((struct in6_addr*) local_ip);
680 ri.local_address.port = local_port;
681 ri.local_address.proto = protocol;
683 &ri);
684 if (NULL != state_key)
685 *state_key = key;
687 &key);
688 if (NULL == state)
689 return NULL;
690 /* Mark this connection as freshly used */
691 if (NULL == state_key)
692 GNUNET_CONTAINER_heap_update_cost (state->specifics.tcp_udp.heap_node,
693 GNUNET_TIME_absolute_get ().abs_value_us)
694 ;
695 return state;
696}

References SocketAddress::address, SocketAddress::af, ChannelState::af, connections_map, ChannelState::destination_port, GNUNET_CONTAINER_heap_update_cost(), GNUNET_CONTAINER_multihashmap_get(), GNUNET_TIME_absolute_get(), hash_redirect_info(), SocketAddress::ipv4, SocketAddress::ipv6, key, RedirectInformation::local_address, SocketAddress::port, SocketAddress::proto, ChannelState::protocol, RedirectInformation::remote_address, ChannelState::ri, and state.

Referenced by icmp_from_helper(), setup_state_record(), tcp_from_helper(), and udp_from_helper().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_tcp_service()

static int check_tcp_service ( void *  cls,
const struct GNUNET_EXIT_TcpServiceStartMessage start 
)
static

Check a request via cadet to send a request to a TCP service offered by this system.

Parameters
clsour struct ChannelState *
startthe actual message
Returns
GNUNET_OK to keep the connection open, GNUNET_SYSERR to close it (signal serious error)

Definition at line 709 of file gnunet-daemon-exit.c.

711{
712 struct ChannelState *state = cls;
713
714 if (NULL == state)
715 {
716 GNUNET_break_op (0);
717 return GNUNET_SYSERR;
718 }
719 if (GNUNET_YES == state->is_dns)
720 {
721 GNUNET_break_op (0);
722 return GNUNET_SYSERR;
723 }
724 if (NULL == state->specifics.tcp_udp.serv)
725 {
726 GNUNET_break_op (0);
727 return GNUNET_SYSERR;
728 }
729 if (NULL != state->specifics.tcp_udp.heap_node)
730 {
731 GNUNET_break_op (0);
732 return GNUNET_SYSERR;
733 }
734 if (start->tcp_header.off * 4 < sizeof(struct GNUNET_TUN_TcpHeader))
735 {
736 GNUNET_break_op (0);
737 return GNUNET_SYSERR;
738 }
739 return GNUNET_OK;
740}

References GNUNET_break_op, GNUNET_OK, GNUNET_SYSERR, GNUNET_YES, start, and state.

◆ prepare_ipv4_packet()

static void prepare_ipv4_packet ( const void *  payload,
size_t  payload_length,
int  protocol,
const struct GNUNET_TUN_TcpHeader tcp_header,
const struct SocketAddress src_address,
const struct SocketAddress dst_address,
struct GNUNET_TUN_IPv4Header pkt4 
)
static

Prepare an IPv4 packet for transmission via the TUN interface.

Initializes the IP header and calculates checksums (IP+UDP/TCP). For UDP, the UDP header will be fully created, whereas for TCP only the ports and checksum will be filled in. So for TCP, a skeleton TCP header must be part of the provided payload.

Parameters
payloadpayload of the packet (starting with UDP payload or TCP header, depending on protocol)
payload_lengthnumber of bytes in payload
protocolIPPROTO_UDP or IPPROTO_TCP
tcp_headerskeleton of the TCP header, NULL for UDP
src_addresssource address to use (IP and port)
dst_addressdestination address to use (IP and port)
pkt4where to write the assembled packet; must contain enough space for the IP header, UDP/TCP header AND the payload

Definition at line 762 of file gnunet-daemon-exit.c.

769{
770 size_t len;
771
772 len = payload_length;
773 switch (protocol)
774 {
775 case IPPROTO_UDP:
776 len += sizeof(struct GNUNET_TUN_UdpHeader);
777 break;
778
779 case IPPROTO_TCP:
780 len += sizeof(struct GNUNET_TUN_TcpHeader);
781 GNUNET_assert (NULL != tcp_header);
782 break;
783
784 default:
785 GNUNET_break (0);
786 return;
787 }
788 if (len + sizeof(struct GNUNET_TUN_IPv4Header) > UINT16_MAX)
789 {
790 GNUNET_break (0);
791 return;
792 }
793
795 protocol,
796 len,
797 &src_address->address.ipv4,
798 &dst_address->address.ipv4);
799 switch (protocol)
800 {
801 case IPPROTO_UDP:
802 {
803 struct GNUNET_TUN_UdpHeader *pkt4_udp = (struct
804 GNUNET_TUN_UdpHeader *) &pkt4[1];
805
806 pkt4_udp->source_port = htons (src_address->port);
807 pkt4_udp->destination_port = htons (dst_address->port);
808 pkt4_udp->len = htons ((uint16_t) payload_length);
810 pkt4_udp,
811 payload,
812 payload_length);
813 GNUNET_memcpy (&pkt4_udp[1],
814 payload,
815 payload_length);
816 }
817 break;
818
819 case IPPROTO_TCP:
820 {
821 struct GNUNET_TUN_TcpHeader *pkt4_tcp = (struct
823
824 *pkt4_tcp = *tcp_header;
826 "Sending TCP packet from port %u to port %u\n",
827 src_address->port,
828 dst_address->port);
829 pkt4_tcp->source_port = htons (src_address->port);
830 pkt4_tcp->destination_port = htons (dst_address->port);
832 pkt4_tcp,
833 payload,
834 payload_length);
836 payload,
837 payload_length);
838 }
839 break;
840
841 default:
842 GNUNET_assert (0);
843 }
844}

References GNUNET_TUN_UdpHeader::destination_port, GNUNET_assert, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_memcpy, GNUNET_TUN_calculate_tcp4_checksum(), GNUNET_TUN_calculate_udp4_checksum(), GNUNET_TUN_initialize_ipv4_header(), GNUNET_TUN_UdpHeader::len, GNUNET_TUN_TcpHeader::off, payload, SocketAddress::port, ChannelState::protocol, and GNUNET_TUN_UdpHeader::source_port.

Referenced by send_tcp_packet_via_tun(), and send_udp_packet_via_tun().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ prepare_ipv6_packet()

static void prepare_ipv6_packet ( const void *  payload,
size_t  payload_length,
int  protocol,
const struct GNUNET_TUN_TcpHeader tcp_header,
const struct SocketAddress src_address,
const struct SocketAddress dst_address,
struct GNUNET_TUN_IPv6Header pkt6 
)
static

Prepare an IPv6 packet for transmission via the TUN interface.

Initializes the IP header and calculates checksums (IP+UDP/TCP). For UDP, the UDP header will be fully created, whereas for TCP only the ports and checksum will be filled in. So for TCP, a skeleton TCP header must be part of the provided payload.

Parameters
payloadpayload of the packet (starting with UDP payload or TCP header, depending on protocol)
payload_lengthnumber of bytes in payload
protocolIPPROTO_UDP or IPPROTO_TCP
tcp_headerskeleton TCP header data to send, NULL for UDP
src_addresssource address to use (IP and port)
dst_addressdestination address to use (IP and port)
pkt6where to write the assembled packet; must contain enough space for the IP header, UDP/TCP header AND the payload

Definition at line 866 of file gnunet-daemon-exit.c.

873{
874 size_t len;
875
876 len = payload_length;
877 switch (protocol)
878 {
879 case IPPROTO_UDP:
880 len += sizeof(struct GNUNET_TUN_UdpHeader);
881 break;
882
883 case IPPROTO_TCP:
884 len += sizeof(struct GNUNET_TUN_TcpHeader);
885 break;
886
887 default:
888 GNUNET_break (0);
889 return;
890 }
891 if (len > UINT16_MAX)
892 {
893 GNUNET_break (0);
894 return;
895 }
896
898 protocol,
899 len,
900 &src_address->address.ipv6,
901 &dst_address->address.ipv6);
902
903 switch (protocol)
904 {
905 case IPPROTO_UDP:
906 {
907 struct GNUNET_TUN_UdpHeader *pkt6_udp = (struct
908 GNUNET_TUN_UdpHeader *) &pkt6[1];
909
910 pkt6_udp->source_port = htons (src_address->port);
911 pkt6_udp->destination_port = htons (dst_address->port);
912 pkt6_udp->len = htons ((uint16_t) payload_length);
914 pkt6_udp,
915 payload,
916 payload_length);
917 GNUNET_memcpy (&pkt6_udp[1],
918 payload,
919 payload_length);
920 }
921 break;
922
923 case IPPROTO_TCP:
924 {
925 struct GNUNET_TUN_TcpHeader *pkt6_tcp = (struct
927
928 /* GNUNET_memcpy first here as some TCP header fields are initialized this way! */
929 *pkt6_tcp = *tcp_header;
931 pkt6_tcp->destination_port = htons (dst_address->port);
933 pkt6_tcp,
934 payload,
935 payload_length);
937 payload,
938 payload_length);
939 }
940 break;
941
942 default:
943 GNUNET_assert (0);
944 break;
945 }
946}

References GNUNET_TUN_UdpHeader::destination_port, GNUNET_assert, GNUNET_break, GNUNET_memcpy, GNUNET_TUN_calculate_tcp6_checksum(), GNUNET_TUN_calculate_udp6_checksum(), GNUNET_TUN_initialize_ipv6_header(), GNUNET_TUN_UdpHeader::len, GNUNET_TUN_TcpHeader::off, payload, SocketAddress::port, GNUNET_TUN_TcpHeader::source_port, and GNUNET_TUN_UdpHeader::source_port.

Referenced by send_tcp_packet_via_tun(), and send_udp_packet_via_tun().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ send_tcp_packet_via_tun()

static void send_tcp_packet_via_tun ( const struct SocketAddress destination_address,
const struct SocketAddress source_address,
const struct GNUNET_TUN_TcpHeader tcp_header,
const void *  payload,
size_t  payload_length 
)
static

Send a TCP packet via the TUN interface.

Parameters
destination_addressIP and port to use for the TCP packet's destination
source_addressIP and port to use for the TCP packet's source
tcp_headerheader template to use
payloadpayload of the TCP packet
payload_lengthnumber of bytes in payload

Definition at line 959 of file gnunet-daemon-exit.c.

964{
965 size_t len;
966
968 gettext_noop ("# TCP packets sent via TUN"),
969 1,
970 GNUNET_NO);
972 "Sending packet with %u bytes TCP payload via TUN\n",
973 (unsigned int) payload_length);
974 len = sizeof(struct GNUNET_MessageHeader) + sizeof(struct
976 switch (source_address->af)
977 {
978 case AF_INET:
979 len += sizeof(struct GNUNET_TUN_IPv4Header);
980 break;
981
982 case AF_INET6:
983 len += sizeof(struct GNUNET_TUN_IPv6Header);
984 break;
985
986 default:
987 GNUNET_break (0);
988 return;
989 }
990 len += sizeof(struct GNUNET_TUN_TcpHeader);
991 len += payload_length;
992 if (len >= GNUNET_MAX_MESSAGE_SIZE)
993 {
994 GNUNET_break (0);
995 return;
996 }
997 {
998 char buf[len] GNUNET_ALIGN;
999 struct GNUNET_MessageHeader *hdr;
1001
1002 hdr = (struct GNUNET_MessageHeader *) buf;
1003 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1004 hdr->size = htons (len);
1005 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
1006 tun->flags = htons (0);
1007 switch (source_address->af)
1008 {
1009 case AF_INET:
1010 {
1012 = (struct GNUNET_TUN_IPv4Header*) &tun[1];
1013
1014 tun->proto = htons (ETH_P_IPV4);
1016 payload_length,
1017 IPPROTO_TCP,
1018 tcp_header,
1021 ipv4);
1022 }
1023 break;
1024
1025 case AF_INET6:
1026 {
1028 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
1029
1030 tun->proto = htons (ETH_P_IPV6);
1033 IPPROTO_TCP,
1034 tcp_header,
1037 ipv6);
1038 }
1039 break;
1040
1041 default:
1042 GNUNET_assert (0);
1043 break;
1044 }
1045 if (NULL != helper_handle)
1047 (const struct GNUNET_MessageHeader*) buf,
1048 GNUNET_YES,
1049 NULL,
1050 NULL);
1051 }
1052}

References SocketAddress::af, GNUNET_TUN_IPv4Header::destination_address, GNUNET_TUN_IPv6Header::destination_address, ETH_P_IPV4, ETH_P_IPV6, GNUNET_TUN_Layer2PacketHeader::flags, gettext_noop, GNUNET_ALIGN, GNUNET_assert, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_HELPER_send(), GNUNET_log, GNUNET_MAX_MESSAGE_SIZE, GNUNET_MESSAGE_TYPE_VPN_HELPER, GNUNET_NO, GNUNET_STATISTICS_update(), GNUNET_YES, helper_handle, ipv4, ipv6, payload, GNUNET_TUN_IPv6Header::payload_length, prepare_ipv4_packet(), prepare_ipv6_packet(), GNUNET_TUN_Layer2PacketHeader::proto, GNUNET_MessageHeader::size, GNUNET_TUN_IPv4Header::source_address, GNUNET_TUN_IPv6Header::source_address, stats, and GNUNET_MessageHeader::type.

Referenced by handle_tcp_data(), handle_tcp_remote(), and handle_tcp_service().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ send_icmp_packet_via_tun()

static void send_icmp_packet_via_tun ( const struct SocketAddress destination_address,
const struct SocketAddress source_address,
const struct GNUNET_TUN_IcmpHeader icmp_header,
const void *  payload,
size_t  payload_length 
)
static

Send an ICMP packet via the TUN interface.

Parameters
destination_addressIP to use for the ICMP packet's destination
source_addressIP to use for the ICMP packet's source
icmp_headerICMP header to send
payloadpayload of the ICMP packet (does NOT include ICMP header)
payload_lengthnumber of bytes of data in payload

Definition at line 1065 of file gnunet-daemon-exit.c.

1069{
1070 size_t len;
1071 struct GNUNET_TUN_IcmpHeader *icmp;
1072
1074 gettext_noop ("# ICMP packets sent via TUN"),
1075 1, GNUNET_NO);
1077 "Sending packet with %u bytes ICMP payload via TUN\n",
1078 (unsigned int) payload_length);
1079 len = sizeof(struct GNUNET_MessageHeader) + sizeof(struct
1081 switch (destination_address->af)
1082 {
1083 case AF_INET:
1084 len += sizeof(struct GNUNET_TUN_IPv4Header);
1085 break;
1086
1087 case AF_INET6:
1088 len += sizeof(struct GNUNET_TUN_IPv6Header);
1089 break;
1090
1091 default:
1092 GNUNET_break (0);
1093 return;
1094 }
1095 len += sizeof(struct GNUNET_TUN_IcmpHeader);
1096 len += payload_length;
1097 if (len >= GNUNET_MAX_MESSAGE_SIZE)
1098 {
1099 GNUNET_break (0);
1100 return;
1101 }
1102 {
1103 char buf[len] GNUNET_ALIGN;
1104 struct GNUNET_MessageHeader *hdr;
1106
1107 hdr = (struct GNUNET_MessageHeader *) buf;
1108 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1109 hdr->size = htons (len);
1110 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
1111 tun->flags = htons (0);
1112 switch (source_address->af)
1113 {
1114 case AF_INET:
1115 {
1116 struct GNUNET_TUN_IPv4Header *ipv4 = (struct
1117 GNUNET_TUN_IPv4Header*) &tun[1];
1118
1119 tun->proto = htons (ETH_P_IPV4);
1121 IPPROTO_ICMP,
1122 sizeof(struct
1124 + payload_length,
1125 &source_address->address.ipv4,
1126 &destination_address->address.ipv4);
1127 icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv4[1];
1128 }
1129 break;
1130
1131 case AF_INET6:
1132 {
1133 struct GNUNET_TUN_IPv6Header *ipv6 = (struct
1134 GNUNET_TUN_IPv6Header*) &tun[1];
1135
1136 tun->proto = htons (ETH_P_IPV6);
1138 IPPROTO_ICMPV6,
1139 sizeof(struct
1142 &source_address->address.ipv6,
1143 &destination_address->address.ipv6);
1144 icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv6[1];
1145 }
1146 break;
1147
1148 default:
1149 GNUNET_assert (0);
1150 break;
1151 }
1152 *icmp = *icmp_header;
1153 GNUNET_memcpy (&icmp[1],
1154 payload,
1155 payload_length);
1157 payload,
1158 payload_length);
1159 if (NULL != helper_handle)
1161 (const struct GNUNET_MessageHeader*) buf,
1162 GNUNET_YES,
1163 NULL, NULL);
1164 }
1165}

References SocketAddress::af, GNUNET_TUN_IPv4Header::destination_address, GNUNET_TUN_IPv6Header::destination_address, ETH_P_IPV4, ETH_P_IPV6, GNUNET_TUN_Layer2PacketHeader::flags, gettext_noop, GNUNET_ALIGN, GNUNET_assert, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_HELPER_send(), GNUNET_log, GNUNET_MAX_MESSAGE_SIZE, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_VPN_HELPER, GNUNET_NO, GNUNET_STATISTICS_update(), GNUNET_TUN_calculate_icmp_checksum(), GNUNET_TUN_initialize_ipv4_header(), GNUNET_TUN_initialize_ipv6_header(), GNUNET_YES, helper_handle, ipv4, ipv6, payload, GNUNET_TUN_IPv6Header::payload_length, GNUNET_TUN_Layer2PacketHeader::proto, GNUNET_MessageHeader::size, GNUNET_TUN_IPv4Header::source_address, GNUNET_TUN_IPv6Header::source_address, stats, and GNUNET_MessageHeader::type.

Referenced by handle_icmp_remote(), and handle_icmp_service().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ setup_fresh_address()

static void setup_fresh_address ( int  af,
uint8_t  proto,
struct SocketAddress local_address 
)
static

We need to create a (unique) fresh local address (IP+port).

Fill one in.

Parameters
afdesired address family
protodesired protocol (IPPROTO_UDP or IPPROTO_TCP)
local_addressaddress to initialize

Definition at line 1177 of file gnunet-daemon-exit.c.

1180{
1181 local_address->af = af;
1182 local_address->proto = (uint8_t) proto;
1183 /* default "local" port range is often 32768--61000,
1184 so we pick a random value in that range */
1185 if (((af == AF_INET) && (proto == IPPROTO_ICMP)) ||
1186 ((af == AF_INET6) && (proto == IPPROTO_ICMPV6)))
1187 local_address->port = 0;
1188 else
1189 local_address->port
1191 28232);
1192 switch (af)
1193 {
1194 case AF_INET:
1195 {
1196 struct in_addr addr;
1197 struct in_addr mask;
1198 struct in_addr rnd;
1199
1200 addr = exit_ipv4addr;
1201 mask = exit_ipv4mask;
1202 if (0 == ~mask.s_addr)
1203 {
1204 /* only one valid IP anyway */
1205 local_address->address.ipv4 = addr;
1206 return;
1207 }
1208 /* Given 192.168.0.1/255.255.0.0, we want a mask
1209 of '192.168.255.255', thus: */
1210 mask.s_addr = addr.s_addr | ~mask.s_addr;
1211 /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
1212 do
1213 {
1215 UINT32_MAX);
1216 local_address->address.ipv4.s_addr = (addr.s_addr | rnd.s_addr)
1217 & mask.s_addr;
1218 }
1219 while ((local_address->address.ipv4.s_addr == addr.s_addr) ||
1220 (local_address->address.ipv4.s_addr == mask.s_addr));
1221 }
1222 break;
1223
1224 case AF_INET6:
1225 {
1226 struct in6_addr addr;
1227 struct in6_addr mask;
1228 struct in6_addr rnd;
1229 int i;
1230
1231 addr = exit_ipv6addr;
1232 GNUNET_assert (ipv6prefix < 128);
1233 if (ipv6prefix == 127)
1234 {
1235 /* only one valid IP anyway */
1236 local_address->address.ipv6 = addr;
1237 return;
1238 }
1239 /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
1240 thus: */
1241 mask = addr;
1242 for (i = 127; i >= ipv6prefix; i--)
1243 mask.s6_addr[i / 8] |= (1 << (i % 8));
1244
1245 /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
1246 do
1247 {
1248 for (i = 0; i < 16; i++)
1249 {
1250 rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (
1252 256);
1253 local_address->address.ipv6.s6_addr[i]
1254 = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
1255 }
1256 }
1257 while ((0 == GNUNET_memcmp (&local_address->address.ipv6,
1258 &addr)) ||
1259 (0 == GNUNET_memcmp (&local_address->address.ipv6,
1260 &mask)));
1261 }
1262 break;
1263
1264 default:
1265 GNUNET_assert (0);
1266 }
1267}

References SocketAddress::address, SocketAddress::af, exit_ipv4addr, exit_ipv4mask, exit_ipv6addr, GNUNET_assert, GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CRYPTO_random_u32(), GNUNET_memcmp, SocketAddress::ipv4, SocketAddress::ipv6, ipv6prefix, SocketAddress::port, proto, and SocketAddress::proto.

Referenced by setup_state_record().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ setup_state_record()

static void setup_state_record ( struct ChannelState state)
static

We are starting a fresh connection (TCP or UDP) and need to pick a source port and IP address (within the correct range and address family) to associate replies with the connection / correct cadet channel.

This function generates a "fresh" source IP and source port number for a connection After picking a good source address, this function sets up the state in the 'connections_map' and 'connections_heap' to allow finding the state when needed later. The function also makes sure that we remain within memory limits by cleaning up 'old' states.

Parameters
stateskeleton state to setup a record for; should 'state->specifics.tcp_udp.ri.remote_address' filled in so that this code can determine which AF/protocol is going to be used (the 'channel' should also already be set); after calling this function, heap_node and the local_address will be also initialized (heap_node != NULL can be used to test if a state has been fully setup).

Definition at line 1292 of file gnunet-daemon-exit.c.

1293{
1294 struct GNUNET_HashCode key;
1295 struct ChannelState *s;
1296
1297 /* generate fresh, unique address */
1298 do
1299 {
1300 if (NULL == state->specifics.tcp_udp.serv)
1301 setup_fresh_address (state->specifics.tcp_udp.ri.remote_address.af,
1302 state->specifics.tcp_udp.ri.remote_address.proto,
1303 &state->specifics.tcp_udp.ri.local_address);
1304 else
1305 setup_fresh_address (state->specifics.tcp_udp.serv->address.af,
1306 state->specifics.tcp_udp.serv->address.proto,
1307 &state->specifics.tcp_udp.ri.local_address);
1308 }
1309 while (NULL !=
1310 get_redirect_state (state->specifics.tcp_udp.ri.remote_address.af,
1311 state->specifics.tcp_udp.ri.remote_address.proto,
1312 &state->specifics.tcp_udp.ri.remote_address.address
1313 ,
1314 state->specifics.tcp_udp.ri.remote_address.port,
1315 &state->specifics.tcp_udp.ri.local_address.address,
1316 state->specifics.tcp_udp.ri.local_address.port,
1317 &key));
1318 {
1319 char buf[INET6_ADDRSTRLEN];
1321 "Picked local address %s:%u for new connection\n",
1322 inet_ntop (state->specifics.tcp_udp.ri.local_address.af,
1323 &state->specifics.tcp_udp.ri.local_address.address,
1324 buf,
1325 sizeof(buf)),
1326 (unsigned int) state->specifics.tcp_udp.ri.local_address.port);
1327 }
1328 state->specifics.tcp_udp.state_key = key;
1331 &key, state,
1333 state->specifics.tcp_udp.heap_node
1335 state,
1336 GNUNET_TIME_absolute_get ().abs_value_us);
1338 {
1340 GNUNET_assert (state != s);
1341 s->specifics.tcp_udp.heap_node = NULL;
1345 &s->specifics.tcp_udp.
1346 state_key,
1347 s));
1348 GNUNET_free (s);
1349 }
1350}

References ChannelState::channel, connections_heap, connections_map, get_redirect_state(), GNUNET_assert, GNUNET_CADET_channel_destroy(), GNUNET_CONTAINER_heap_get_size(), GNUNET_CONTAINER_heap_insert(), GNUNET_CONTAINER_heap_remove_root(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_multihashmap_remove(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_OK, GNUNET_TIME_absolute_get(), ChannelState::heap_node, key, max_connections, setup_fresh_address(), ChannelState::specifics, state, ChannelState::state_key, and ChannelState::tcp_udp.

Referenced by handle_icmp_remote(), handle_icmp_service(), handle_tcp_remote(), handle_tcp_service(), handle_udp_remote(), and handle_udp_service().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ send_udp_packet_via_tun()

static void send_udp_packet_via_tun ( const struct SocketAddress destination_address,
const struct SocketAddress source_address,
const void *  payload,
size_t  payload_length 
)
static

Send a UDP packet via the TUN interface.

Parameters
destination_addressIP and port to use for the UDP packet's destination
source_addressIP and port to use for the UDP packet's source
payloadpayload of the UDP packet (does NOT include UDP header)
payload_lengthnumber of bytes of data in payload

Definition at line 1362 of file gnunet-daemon-exit.c.

1365{
1366 size_t len;
1367
1369 gettext_noop ("# UDP packets sent via TUN"),
1370 1, GNUNET_NO);
1372 "Sending packet with %u bytes UDP payload via TUN\n",
1373 (unsigned int) payload_length);
1374 len = sizeof(struct GNUNET_MessageHeader) + sizeof(struct
1376 switch (source_address->af)
1377 {
1378 case AF_INET:
1379 len += sizeof(struct GNUNET_TUN_IPv4Header);
1380 break;
1381
1382 case AF_INET6:
1383 len += sizeof(struct GNUNET_TUN_IPv6Header);
1384 break;
1385
1386 default:
1387 GNUNET_break (0);
1388 return;
1389 }
1390 len += sizeof(struct GNUNET_TUN_UdpHeader);
1391 len += payload_length;
1393 {
1394 GNUNET_break (0);
1395 return;
1396 }
1397 {
1398 char buf[len] GNUNET_ALIGN;
1399 struct GNUNET_MessageHeader *hdr;
1401
1402 hdr = (struct GNUNET_MessageHeader *) buf;
1403 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1404 hdr->size = htons (len);
1405 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
1406 tun->flags = htons (0);
1407 switch (source_address->af)
1408 {
1409 case AF_INET:
1410 {
1411 struct GNUNET_TUN_IPv4Header *ipv4 = (struct
1412 GNUNET_TUN_IPv4Header*) &tun[1];
1413
1414 tun->proto = htons (ETH_P_IPV4);
1416 payload_length,
1417 IPPROTO_UDP,
1418 NULL,
1421 ipv4);
1422 }
1423 break;
1424
1425 case AF_INET6:
1426 {
1427 struct GNUNET_TUN_IPv6Header *ipv6 = (struct
1428 GNUNET_TUN_IPv6Header*) &tun[1];
1429
1430 tun->proto = htons (ETH_P_IPV6);
1433 IPPROTO_UDP,
1434 NULL,
1437 ipv6);
1438 }
1439 break;
1440
1441 default:
1442 GNUNET_assert (0);
1443 break;
1444 }
1445 if (NULL != helper_handle)
1447 (const struct GNUNET_MessageHeader*) buf,
1448 GNUNET_YES,
1449 NULL, NULL);
1450 }
1451}

References SocketAddress::af, GNUNET_TUN_IPv4Header::destination_address, GNUNET_TUN_IPv6Header::destination_address, ETH_P_IPV4, ETH_P_IPV6, GNUNET_TUN_Layer2PacketHeader::flags, gettext_noop, GNUNET_ALIGN, GNUNET_assert, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_HELPER_send(), GNUNET_log, GNUNET_MAX_MESSAGE_SIZE, GNUNET_MESSAGE_TYPE_VPN_HELPER, GNUNET_NO, GNUNET_STATISTICS_update(), GNUNET_YES, helper_handle, ipv4, ipv6, GNUNET_TUN_UdpHeader::len, payload, GNUNET_TUN_IPv6Header::payload_length, prepare_ipv4_packet(), prepare_ipv6_packet(), GNUNET_TUN_Layer2PacketHeader::proto, GNUNET_MessageHeader::size, GNUNET_TUN_IPv4Header::source_address, GNUNET_TUN_IPv6Header::source_address, stats, and GNUNET_MessageHeader::type.

Referenced by handle_udp_remote(), and handle_udp_service().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_udp_remote()

static int check_udp_remote ( void *  cls,
const struct GNUNET_EXIT_UdpInternetMessage msg 
)
static

Check a request to forward UDP data to the Internet via this peer.

Parameters
clsour struct ChannelState *
msgthe actual message
Returns
GNUNET_OK to keep the connection open, GNUNET_SYSERR to close it (signal serious error)

Definition at line 1463 of file gnunet-daemon-exit.c.

1465{
1466 struct ChannelState *state = cls;
1467
1468 if (GNUNET_YES == state->is_dns)
1469 {
1470 GNUNET_break_op (0);
1471 return GNUNET_SYSERR;
1472 }
1473 return GNUNET_OK;
1474}

References GNUNET_break_op, GNUNET_OK, GNUNET_SYSERR, GNUNET_YES, and state.

◆ handle_udp_remote()

static void handle_udp_remote ( void *  cls,
const struct GNUNET_EXIT_UdpInternetMessage msg 
)
static

Process a request to forward UDP data to the Internet via this peer.

Parameters
clsour struct ChannelState *
msgthe actual message

Definition at line 1484 of file gnunet-daemon-exit.c.

1486{
1487 struct ChannelState *state = cls;
1488 uint16_t pkt_len = ntohs (msg->header.size) - sizeof(struct
1490 const struct in_addr *v4;
1491 const struct in6_addr *v6;
1492 const void *payload;
1493 int af;
1494
1495 if (GNUNET_SYSERR == state->is_dns)
1496 {
1497 /* channel is UDP/TCP from now on */
1499 }
1501 gettext_noop ("# Bytes received from CADET"),
1502 pkt_len, GNUNET_NO);
1504 gettext_noop (
1505 "# UDP IP-exit requests received via cadet"),
1506 1, GNUNET_NO);
1507 af = (int) ntohl (msg->af);
1508 state->specifics.tcp_udp.ri.remote_address.af = af;
1509 switch (af)
1510 {
1511 case AF_INET:
1512 if (pkt_len < sizeof(struct in_addr))
1513 {
1514 GNUNET_break_op (0);
1515 return;
1516 }
1517 if (! ipv4_exit)
1518 {
1519 GNUNET_break_op (0);
1520 return;
1521 }
1522 v4 = (const struct in_addr*) &msg[1];
1523 payload = &v4[1];
1524 pkt_len -= sizeof(struct in_addr);
1525 state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4;
1526 break;
1527
1528 case AF_INET6:
1529 if (pkt_len < sizeof(struct in6_addr))
1530 {
1531 GNUNET_break_op (0);
1532 return;
1533 }
1534 if (! ipv6_exit)
1535 {
1536 GNUNET_break_op (0);
1537 return;
1538 }
1539 v6 = (const struct in6_addr*) &msg[1];
1540 payload = &v6[1];
1541 pkt_len -= sizeof(struct in6_addr);
1542 state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6;
1543 break;
1544
1545 default:
1546 GNUNET_break_op (0);
1547 return;
1548 }
1549 {
1550 char buf[INET6_ADDRSTRLEN];
1552 "Received data from %s for forwarding to UDP %s:%u\n",
1553 GNUNET_i2s (&state->peer),
1554 inet_ntop (af,
1555 &state->specifics.tcp_udp.ri.remote_address.address,
1556 buf, sizeof(buf)),
1557 (unsigned int) ntohs (msg->destination_port));
1558 }
1559 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_UDP;
1560 state->specifics.tcp_udp.ri.remote_address.port = msg->destination_port;
1561 if (NULL == state->specifics.tcp_udp.heap_node)
1563 if (0 != ntohs (msg->source_port))
1564 state->specifics.tcp_udp.ri.local_address.port = msg->source_port;
1565 send_udp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1566 &state->specifics.tcp_udp.ri.local_address,
1567 payload,
1568 pkt_len);
1570}

References gettext_noop, GNUNET_break_op, GNUNET_CADET_receive_done(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_NO, GNUNET_STATISTICS_update(), GNUNET_SYSERR, ipv4_exit, ipv6_exit, ChannelState::is_dns, msg, payload, send_udp_packet_via_tun(), setup_state_record(), GNUNET_MessageHeader::size, state, and stats.

Here is the call graph for this function:

◆ check_udp_service()

static int check_udp_service ( void *  cls,
const struct GNUNET_EXIT_UdpServiceMessage msg 
)
static

Check a request via cadet to send a request to a UDP service offered by this system.

Parameters
clsour struct ChannelState *
msgthe actual message
Returns
GNUNET_OK to keep the connection open, GNUNET_SYSERR to close it (signal serious error)

Definition at line 1583 of file gnunet-daemon-exit.c.

1585{
1586 struct ChannelState *state = cls;
1587
1588 if (NULL == state->specifics.tcp_udp.serv)
1589 {
1590 GNUNET_break_op (0);
1591 return GNUNET_SYSERR;
1592 }
1593 return GNUNET_OK;
1594}

References GNUNET_break_op, GNUNET_OK, GNUNET_SYSERR, and state.

◆ handle_udp_service()

static void handle_udp_service ( void *  cls,
const struct GNUNET_EXIT_UdpServiceMessage msg 
)
static

Process a request via cadet to send a request to a UDP service offered by this system.

Parameters
clsour struct ChannelState *
msgthe actual message

Definition at line 1605 of file gnunet-daemon-exit.c.

1607{
1608 struct ChannelState *state = cls;
1609 uint16_t pkt_len = ntohs (msg->header.size) - sizeof(struct
1611
1613 gettext_noop ("# Bytes received from CADET"),
1614 pkt_len, GNUNET_NO);
1616 gettext_noop (
1617 "# UDP service requests received via cadet"),
1618 1, GNUNET_NO);
1620 "Received data from %s for forwarding to UDP service %s on port %u\n",
1621 GNUNET_i2s (&state->peer),
1622 GNUNET_h2s (&state->specifics.tcp_udp.serv->descriptor),
1623 (unsigned int) ntohs (msg->destination_port));
1625 if (0 != ntohs (msg->source_port))
1626 state->specifics.tcp_udp.ri.local_address.port = msg->source_port;
1627 send_udp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1628 &state->specifics.tcp_udp.ri.local_address,
1629 &msg[1],
1630 pkt_len);
1632}

References gettext_noop, GNUNET_CADET_receive_done(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_i2s(), GNUNET_NO, GNUNET_STATISTICS_update(), LOG, msg, send_udp_packet_via_tun(), setup_state_record(), GNUNET_MessageHeader::size, state, and stats.

Here is the call graph for this function:

◆ handle_tcp_service()

static void handle_tcp_service ( void *  cls,
const struct GNUNET_EXIT_TcpServiceStartMessage start 
)
static

Process a request via cadet to send a request to a TCP service offered by this system.

Parameters
clsour struct ChannelState *
startthe actual message
Returns
GNUNET_OK to keep the connection open, GNUNET_SYSERR to close it (signal serious error)

Definition at line 1645 of file gnunet-daemon-exit.c.

1647{
1648 struct ChannelState *state = cls;
1649 uint16_t pkt_len = ntohs (start->header.size) - sizeof(struct
1651
1652 if (GNUNET_SYSERR == state->is_dns)
1653 {
1654 /* channel is UDP/TCP from now on */
1656 }
1658 gettext_noop (
1659 "# TCP service creation requests received via cadet"),
1660 1,
1661 GNUNET_NO);
1663 gettext_noop ("# Bytes received from CADET"),
1664 pkt_len,
1665 GNUNET_NO);
1666 GNUNET_break_op (ntohl (start->reserved) == 0);
1667 /* setup fresh connection */
1669 "Received data from %s for forwarding to TCP service %s on port %u\n",
1670 GNUNET_i2s (&state->peer),
1671 GNUNET_h2s (&state->specifics.tcp_udp.serv->descriptor),
1672 (unsigned int) ntohs (start->tcp_header.destination_port));
1674 send_tcp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1675 &state->specifics.tcp_udp.ri.local_address,
1676 &start->tcp_header,
1677 &start[1],
1678 pkt_len);
1680}

References gettext_noop, GNUNET_break_op, GNUNET_CADET_receive_done(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_i2s(), GNUNET_log, GNUNET_NO, GNUNET_STATISTICS_update(), GNUNET_SYSERR, ChannelState::is_dns, send_tcp_packet_via_tun(), setup_state_record(), start, state, and stats.

Here is the call graph for this function:

◆ check_tcp_remote()

static int check_tcp_remote ( void *  cls,
const struct GNUNET_EXIT_TcpInternetStartMessage start 
)
static

Check a request to forward TCP data to the Internet via this peer.

Parameters
clsour struct ChannelState *
startthe actual message
Returns
GNUNET_OK to keep the connection open, GNUNET_SYSERR to close it (signal serious error)

Definition at line 1692 of file gnunet-daemon-exit.c.

1694{
1695 struct ChannelState *state = cls;
1696
1697 if (NULL == state)
1698 {
1699 GNUNET_break_op (0);
1700 return GNUNET_SYSERR;
1701 }
1702 if (GNUNET_YES == state->is_dns)
1703 {
1704 GNUNET_break_op (0);
1705 return GNUNET_SYSERR;
1706 }
1707 if ((NULL != state->specifics.tcp_udp.serv) ||
1708 (NULL != state->specifics.tcp_udp.heap_node))
1709 {
1710 GNUNET_break_op (0);
1711 return GNUNET_SYSERR;
1712 }
1713 if (start->tcp_header.off * 4 < sizeof(struct GNUNET_TUN_TcpHeader))
1714 {
1715 GNUNET_break_op (0);
1716 return GNUNET_SYSERR;
1717 }
1718 return GNUNET_OK;
1719}

References GNUNET_break_op, GNUNET_OK, GNUNET_SYSERR, GNUNET_YES, start, and state.

◆ handle_tcp_remote()

static void handle_tcp_remote ( void *  cls,
const struct GNUNET_EXIT_TcpInternetStartMessage start 
)
static

Process a request to forward TCP data to the Internet via this peer.

Parameters
clsour struct ChannelState *
startthe actual message

Definition at line 1729 of file gnunet-daemon-exit.c.

1731{
1732 struct ChannelState *state = cls;
1733 uint16_t pkt_len = ntohs (start->header.size) - sizeof(struct
1735 const struct in_addr *v4;
1736 const struct in6_addr *v6;
1737 const void *payload;
1738 int af;
1739
1740 if (GNUNET_SYSERR == state->is_dns)
1741 {
1742 /* channel is UDP/TCP from now on */
1744 }
1746 gettext_noop ("# Bytes received from CADET"),
1747 pkt_len, GNUNET_NO);
1749 gettext_noop (
1750 "# TCP IP-exit creation requests received via cadet"),
1751 1, GNUNET_NO);
1752 af = (int) ntohl (start->af);
1753 state->specifics.tcp_udp.ri.remote_address.af = af;
1754 switch (af)
1755 {
1756 case AF_INET:
1757 if (pkt_len < sizeof(struct in_addr))
1758 {
1759 GNUNET_break_op (0);
1760 return;
1761 }
1762 if (! ipv4_exit)
1763 {
1764 GNUNET_break_op (0);
1765 return;
1766 }
1767 v4 = (const struct in_addr*) &start[1];
1768 payload = &v4[1];
1769 pkt_len -= sizeof(struct in_addr);
1770 state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4;
1771 break;
1772
1773 case AF_INET6:
1774 if (pkt_len < sizeof(struct in6_addr))
1775 {
1776 GNUNET_break_op (0);
1777 return;
1778 }
1779 if (! ipv6_exit)
1780 {
1781 GNUNET_break_op (0);
1782 return;
1783 }
1784 v6 = (const struct in6_addr*) &start[1];
1785 payload = &v6[1];
1786 pkt_len -= sizeof(struct in6_addr);
1787 state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6;
1788 break;
1789
1790 default:
1791 GNUNET_break_op (0);
1792 return;
1793 }
1794 {
1795 char buf[INET6_ADDRSTRLEN];
1797 "Received payload from %s for existing TCP stream to %s:%u\n",
1798 GNUNET_i2s (&state->peer),
1799 inet_ntop (af,
1800 &state->specifics.tcp_udp.ri.remote_address.address,
1801 buf, sizeof(buf)),
1802 (unsigned int) ntohs (start->tcp_header.destination_port));
1803 }
1804 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_TCP;
1805 state->specifics.tcp_udp.ri.remote_address.port = ntohs (
1806 start->tcp_header.destination_port);
1808 send_tcp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1809 &state->specifics.tcp_udp.ri.local_address,
1810 &start->tcp_header,
1811 payload,
1812 pkt_len);
1814}

References gettext_noop, GNUNET_break_op, GNUNET_CADET_receive_done(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_NO, GNUNET_STATISTICS_update(), GNUNET_SYSERR, ipv4_exit, ipv6_exit, ChannelState::is_dns, payload, send_tcp_packet_via_tun(), setup_state_record(), start, state, and stats.

Here is the call graph for this function:

◆ check_tcp_data()

static int check_tcp_data ( void *  cls,
const struct GNUNET_EXIT_TcpDataMessage data 
)
static

Check a request to forward TCP data on an established connection via this peer.

Parameters
clsour struct ChannelState *
datathe actual message
Returns
GNUNET_OK to keep the connection open, GNUNET_SYSERR to close it (signal serious error)

Definition at line 1827 of file gnunet-daemon-exit.c.

1829{
1830 struct ChannelState *state = cls;
1831
1832 if ((NULL == state) ||
1833 (NULL == state->specifics.tcp_udp.heap_node))
1834 {
1835 /* connection should have been up! */
1837 gettext_noop (
1838 "# TCP DATA requests dropped (no session)"),
1839 1, GNUNET_NO);
1840 GNUNET_break_op (0);
1841 return GNUNET_SYSERR;
1842 }
1843 if (data->tcp_header.off * 4 < sizeof(struct GNUNET_TUN_TcpHeader))
1844 {
1845 GNUNET_break_op (0);
1846 return GNUNET_SYSERR;
1847 }
1848 if (GNUNET_YES == state->is_dns)
1849 {
1850 GNUNET_break_op (0);
1851 return GNUNET_SYSERR;
1852 }
1853 return GNUNET_OK;
1854}

References data, gettext_noop, GNUNET_break_op, GNUNET_NO, GNUNET_OK, GNUNET_STATISTICS_update(), GNUNET_SYSERR, GNUNET_YES, state, and stats.

Here is the call graph for this function:

◆ handle_tcp_data()

static void handle_tcp_data ( void *  cls,
const struct GNUNET_EXIT_TcpDataMessage data 
)
static

Process a request to forward TCP data on an established connection via this peer.

Parameters
clsour struct ChannelState *
datathe actual message

Definition at line 1865 of file gnunet-daemon-exit.c.

1867{
1868 struct ChannelState *state = cls;
1869 uint16_t pkt_len = ntohs (data->header.size) - sizeof(struct
1871
1873 gettext_noop ("# Bytes received from CADET"),
1874 pkt_len, GNUNET_NO);
1876 gettext_noop (
1877 "# TCP data requests received via cadet"),
1878 1, GNUNET_NO);
1879 if (GNUNET_SYSERR == state->is_dns)
1880 {
1881 /* channel is UDP/TCP from now on */
1882 state->is_dns = GNUNET_NO;
1883 }
1884
1885 GNUNET_break_op (ntohl (data->reserved) == 0);
1886 {
1887 char buf[INET6_ADDRSTRLEN];
1889 "Received additional %u bytes of data from %s for TCP stream to %s:%u\n",
1890 pkt_len,
1891 GNUNET_i2s (&state->peer),
1892 inet_ntop (state->specifics.tcp_udp.ri.remote_address.af,
1893 &state->specifics.tcp_udp.ri.remote_address.address,
1894 buf, sizeof(buf)),
1895 (unsigned int) state->specifics.tcp_udp.ri.remote_address.port);
1896 }
1897
1898 send_tcp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1899 &state->specifics.tcp_udp.ri.local_address,
1900 &data->tcp_header,
1901 &data[1], pkt_len);
1903}

References data, gettext_noop, GNUNET_break_op, GNUNET_CADET_receive_done(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_NO, GNUNET_STATISTICS_update(), GNUNET_SYSERR, send_tcp_packet_via_tun(), state, and stats.

Here is the call graph for this function:

◆ make_up_icmpv4_payload()

static void make_up_icmpv4_payload ( struct ChannelState state,
struct GNUNET_TUN_IPv4Header ipp,
struct GNUNET_TUN_UdpHeader udp 
)
static

Synthesize a plausible ICMP payload for an ICMPv4 error response on the given channel.

Parameters
statechannel information
ippIPv6 header to fill in (ICMP payload)
udp"UDP" header to fill in (ICMP payload); might actually also be the first 8 bytes of the TCP header

Definition at line 1916 of file gnunet-daemon-exit.c.

1919{
1921 state->specifics.tcp_udp.ri.remote_address.
1922 proto,
1923 sizeof(struct GNUNET_TUN_TcpHeader),
1924 &state->specifics.tcp_udp.ri.remote_address
1925 .address.ipv4,
1926 &state->specifics.tcp_udp.ri.local_address.
1927 address.ipv4);
1928 udp->source_port = htons (state->specifics.tcp_udp.ri.remote_address.port);
1929 udp->destination_port = htons (
1930 state->specifics.tcp_udp.ri.local_address.port);
1931 udp->len = htons (0);
1932 udp->crc = htons (0);
1933}

References address, GNUNET_TUN_initialize_ipv4_header(), proto, state, and udp.

Referenced by handle_icmp_remote(), and make_up_icmp_service_payload().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ make_up_icmpv6_payload()

static void make_up_icmpv6_payload ( struct ChannelState state,
struct GNUNET_TUN_IPv6Header ipp,
struct GNUNET_TUN_UdpHeader udp 
)
static

Synthesize a plausible ICMP payload for an ICMPv6 error response on the given channel.

Parameters
statechannel information
ippIPv6 header to fill in (ICMP payload)
udp"UDP" header to fill in (ICMP payload); might actually also be the first 8 bytes of the TCP header

Definition at line 1946 of file gnunet-daemon-exit.c.

1949{
1951 state->specifics.tcp_udp.ri.remote_address.
1952 proto,
1953 sizeof(struct GNUNET_TUN_TcpHeader),
1954 &state->specifics.tcp_udp.ri.remote_address
1955 .address.ipv6,
1956 &state->specifics.tcp_udp.ri.local_address.
1957 address.ipv6);
1958 udp->source_port = htons (state->specifics.tcp_udp.ri.remote_address.port);
1959 udp->destination_port = htons (
1960 state->specifics.tcp_udp.ri.local_address.port);
1961 udp->len = htons (0);
1962 udp->crc = htons (0);
1963}

References address, GNUNET_TUN_initialize_ipv6_header(), proto, state, and udp.

Referenced by handle_icmp_remote(), and make_up_icmp_service_payload().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_icmp_remote()

static int check_icmp_remote ( void *  cls,
const struct GNUNET_EXIT_IcmpInternetMessage msg 
)
static

Check a request to forward ICMP data to the Internet via this peer.

Parameters
clsour struct ChannelState *
msgthe actual message
Returns
GNUNET_OK to keep the connection open, GNUNET_SYSERR to close it (signal serious error)

Definition at line 1975 of file gnunet-daemon-exit.c.

1977{
1978 struct ChannelState *state = cls;
1979
1980 if (GNUNET_YES == state->is_dns)
1981 {
1982 GNUNET_break_op (0);
1983 return GNUNET_SYSERR;
1984 }
1985 return GNUNET_OK;
1986}

References GNUNET_break_op, GNUNET_OK, GNUNET_SYSERR, GNUNET_YES, and state.

◆ handle_icmp_remote()

static void handle_icmp_remote ( void *  cls,
const struct GNUNET_EXIT_IcmpInternetMessage msg 
)
static

Process a request to forward ICMP data to the Internet via this peer.

Parameters
clsour struct ChannelState *
msgthe actual message

Definition at line 1996 of file gnunet-daemon-exit.c.

1998{
1999 struct ChannelState *state = cls;
2000 uint16_t pkt_len = ntohs (msg->header.size) - sizeof(struct
2002 const struct in_addr *v4;
2003 const struct in6_addr *v6;
2004 const void *payload;
2005 char buf[sizeof(struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
2006 int af;
2007
2008 if (GNUNET_SYSERR == state->is_dns)
2009 {
2010 /* channel is UDP/TCP from now on */
2012 }
2014 gettext_noop ("# Bytes received from CADET"),
2015 pkt_len, GNUNET_NO);
2017 gettext_noop (
2018 "# ICMP IP-exit requests received via cadet"),
2019 1, GNUNET_NO);
2020
2021 af = (int) ntohl (msg->af);
2022 if ((NULL != state->specifics.tcp_udp.heap_node) &&
2023 (af != state->specifics.tcp_udp.ri.remote_address.af))
2024 {
2025 /* other peer switched AF on this channel; not allowed */
2026 GNUNET_break_op (0);
2027 return;
2028 }
2029
2030 switch (af)
2031 {
2032 case AF_INET:
2033 if (pkt_len < sizeof(struct in_addr))
2034 {
2035 GNUNET_break_op (0);
2036 return;
2037 }
2038 if (! ipv4_exit)
2039 {
2040 GNUNET_break_op (0);
2041 return;
2042 }
2043 v4 = (const struct in_addr*) &msg[1];
2044 payload = &v4[1];
2045 pkt_len -= sizeof(struct in_addr);
2046 state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4;
2047 if (NULL == state->specifics.tcp_udp.heap_node)
2048 {
2049 state->specifics.tcp_udp.ri.remote_address.af = af;
2050 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_ICMP;
2052 }
2053 /* check that ICMP type is something we want to support
2054 and possibly make up payload! */
2055 switch (msg->icmp_header.type)
2056 {
2059 break;
2060
2064 if (0 != pkt_len)
2065 {
2066 GNUNET_break_op (0);
2067 return;
2068 }
2069 /* make up payload */
2070 {
2071 struct GNUNET_TUN_IPv4Header *ipp = (struct
2072 GNUNET_TUN_IPv4Header *) buf;
2073 struct GNUNET_TUN_UdpHeader *udp = (struct
2074 GNUNET_TUN_UdpHeader *) &ipp[1];
2075
2076 GNUNET_assert (8 == sizeof(struct GNUNET_TUN_UdpHeader));
2077 pkt_len = sizeof(struct GNUNET_TUN_IPv4Header) + 8;
2079 ipp,
2080 udp);
2081 payload = ipp;
2082 }
2083 break;
2084
2085 default:
2086 GNUNET_break_op (0);
2088 gettext_noop (
2089 "# ICMPv4 packets dropped (type not allowed)")
2090 ,
2091 1, GNUNET_NO);
2092 return;
2093 }
2094 /* end AF_INET */
2095 break;
2096
2097 case AF_INET6:
2098 if (pkt_len < sizeof(struct in6_addr))
2099 {
2100 GNUNET_break_op (0);
2101 return;
2102 }
2103 if (! ipv6_exit)
2104 {
2105 GNUNET_break_op (0);
2106 return;
2107 }
2108 v6 = (const struct in6_addr*) &msg[1];
2109 payload = &v6[1];
2110 pkt_len -= sizeof(struct in6_addr);
2111 state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6;
2112 if (NULL == state->specifics.tcp_udp.heap_node)
2113 {
2114 state->specifics.tcp_udp.ri.remote_address.af = af;
2115 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_ICMPV6;
2117 }
2118 /* check that ICMP type is something we want to support
2119 and possibly make up payload! */
2120 switch (msg->icmp_header.type)
2121 {
2124 break;
2125
2130 if (0 != pkt_len)
2131 {
2132 GNUNET_break_op (0);
2133 return;
2134 }
2135 /* make up payload */
2136 {
2137 struct GNUNET_TUN_IPv6Header *ipp = (struct
2138 GNUNET_TUN_IPv6Header *) buf;
2139 struct GNUNET_TUN_UdpHeader *udp = (struct
2140 GNUNET_TUN_UdpHeader *) &ipp[1];
2141
2142 GNUNET_assert (8 == sizeof(struct GNUNET_TUN_UdpHeader));
2143 pkt_len = sizeof(struct GNUNET_TUN_IPv6Header) + 8;
2145 ipp,
2146 udp);
2147 payload = ipp;
2148 }
2149 break;
2150
2151 default:
2152 GNUNET_break_op (0);
2154 gettext_noop (
2155 "# ICMPv6 packets dropped (type not allowed)")
2156 ,
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_tmp[INET6_ADDRSTRLEN];
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_tmp, sizeof(buf_tmp)));
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);
2183}

References gettext_noop, GNUNET_ALIGN, GNUNET_assert, GNUNET_break_op, GNUNET_CADET_receive_done(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_NO, GNUNET_STATISTICS_update(), GNUNET_SYSERR, GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE, GNUNET_TUN_ICMPTYPE6_ECHO_REPLY, GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST, GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG, GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM, GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED, GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE, GNUNET_TUN_ICMPTYPE_ECHO_REPLY, GNUNET_TUN_ICMPTYPE_ECHO_REQUEST, GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH, GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED, ipv4_exit, ipv6_exit, ChannelState::is_dns, make_up_icmpv4_payload(), make_up_icmpv6_payload(), msg, payload, send_icmp_packet_via_tun(), setup_state_record(), GNUNET_MessageHeader::size, state, stats, GNUNET_MessageHeader::type, and udp.

Here is the call graph for this function:

◆ make_up_icmp_service_payload()

static uint16_t make_up_icmp_service_payload ( struct ChannelState state,
char *  buf 
)
static

Setup ICMP payload for ICMP error messages.

Called for both IPv4 and IPv6 addresses.

Parameters
statecontext for creating the IP Packet
bufwhere to create the payload, has at least sizeof (struct GNUNET_TUN_IPv6Header) + 8 bytes
Returns
number of bytes of payload we created in buf

Definition at line 2196 of file gnunet-daemon-exit.c.

2198{
2199 switch (state->specifics.tcp_udp.serv->address.af)
2200 {
2201 case AF_INET:
2202 {
2204 struct GNUNET_TUN_UdpHeader *udp;
2205
2206 ipv4 = (struct GNUNET_TUN_IPv4Header *) buf;
2207 udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
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 {
2219 struct GNUNET_TUN_UdpHeader *udp;
2220
2221 ipv6 = (struct GNUNET_TUN_IPv6Header *) buf;
2222 udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
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}

References GNUNET_assert, GNUNET_break, ipv4, ipv6, make_up_icmpv4_payload(), make_up_icmpv6_payload(), state, and udp.

Referenced by handle_icmp_service().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_icmp_service()

static int check_icmp_service ( void *  cls,
const struct GNUNET_EXIT_IcmpServiceMessage msg 
)
static

Check a request via cadet to send ICMP data to a service offered by this system.

Parameters
clsour struct ChannelState *
msgthe actual message
Returns
GNUNET_OK to keep the connection open, GNUNET_SYSERR to close it (signal serious error)

Definition at line 2248 of file gnunet-daemon-exit.c.

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}

References GNUNET_break_op, GNUNET_OK, GNUNET_SYSERR, GNUNET_YES, and state.

◆ handle_icmp_service()

static void handle_icmp_service ( void *  cls,
const struct GNUNET_EXIT_IcmpServiceMessage msg 
)
static

Process a request via cadet to send ICMP data to a service offered by this system.

Parameters
clsour struct ChannelState *
msgthe actual message

Definition at line 2275 of file gnunet-daemon-exit.c.

2277{
2278 struct ChannelState *state = cls;
2279 uint16_t pkt_len = ntohs (msg->header.size) - sizeof(struct
2281 struct GNUNET_TUN_IcmpHeader icmp;
2282 char buf[sizeof(struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
2283 const void *payload;
2284
2286 gettext_noop ("# Bytes received from CADET"),
2287 pkt_len, GNUNET_NO);
2289 gettext_noop (
2290 "# ICMP service requests received via cadet"),
2291 1, GNUNET_NO);
2292 /* check that we got at least a valid header */
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;
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 {
2311 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2313 break;
2314
2316 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2318 break;
2319
2321 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
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
2333 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
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
2345 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2346 {
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);
2365 gettext_noop (
2366 "# ICMPv4 packets dropped (type not allowed)")
2367 ,
2368 1, GNUNET_NO);
2369 return;
2370 }
2371 /* end of AF_INET */
2372 break;
2373
2374 case AF_INET6:
2375 switch (msg->icmp_header.type)
2376 {
2378 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2380 break;
2381
2383 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2385 break;
2386
2388 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2390 if (0 != pkt_len)
2391 {
2392 GNUNET_break_op (0);
2393 return;
2394 }
2395 payload = buf;
2396 pkt_len = make_up_icmp_service_payload (state, buf);
2397 break;
2398
2400 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2402 if (0 != pkt_len)
2403 {
2404 GNUNET_break_op (0);
2405 return;
2406 }
2407 payload = buf;
2408 pkt_len = make_up_icmp_service_payload (state, buf);
2409 break;
2410
2413 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2414 {
2416 gettext_noop (
2417 "# ICMPv6 packets dropped (impossible PT to v4)"),
2418 1, GNUNET_NO);
2419 return;
2420 }
2421 if (0 != pkt_len)
2422 {
2423 GNUNET_break_op (0);
2424 return;
2425 }
2426 payload = buf;
2427 pkt_len = make_up_icmp_service_payload (state, buf);
2428 break;
2429
2430 default:
2431 GNUNET_break_op (0);
2433 gettext_noop (
2434 "# ICMPv6 packets dropped (type not allowed)")
2435 ,
2436 1, GNUNET_NO);
2437 return;
2438 }
2439 /* end of AF_INET6 */
2440 break;
2441
2442 default:
2443 GNUNET_break_op (0);
2444 return;
2445 }
2446
2447 send_icmp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
2448 &state->specifics.tcp_udp.ri.local_address,
2449 &icmp,
2450 payload,
2451 pkt_len);
2453}

References gettext_noop, GNUNET_ALIGN, GNUNET_break_op, GNUNET_CADET_receive_done(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_i2s(), GNUNET_log, GNUNET_NO, GNUNET_STATISTICS_update(), GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE, GNUNET_TUN_ICMPTYPE6_ECHO_REPLY, GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST, GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG, GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM, GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED, GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE, GNUNET_TUN_ICMPTYPE_ECHO_REPLY, GNUNET_TUN_ICMPTYPE_ECHO_REQUEST, GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH, GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED, make_up_icmp_service_payload(), msg, payload, send_icmp_packet_via_tun(), setup_state_record(), GNUNET_MessageHeader::size, state, stats, GNUNET_MessageHeader::type, and GNUNET_TUN_IcmpHeader::type.

Here is the call graph for this function:

◆ free_service_record()

static int free_service_record ( void *  cls,
const struct GNUNET_HashCode key,
void *  value 
)
static

Free memory associated with a service record.

Parameters
clsunused
keyservice descriptor
valueservice record to free
Returns
GNUNET_OK

Definition at line 2465 of file gnunet-daemon-exit.c.

2468{
2469 struct LocalService *service = value;
2470
2473 key,
2474 service));
2476 GNUNET_free (service->name);
2478 return GNUNET_OK;
2479}

References GNUNET_assert, GNUNET_CADET_close_port(), GNUNET_CONTAINER_multihashmap_remove(), GNUNET_free, GNUNET_OK, GNUNET_YES, key, service, services, and value.

Referenced by cleanup().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ new_service_channel()

static void * new_service_channel ( void *  cls,
struct GNUNET_CADET_Channel channel,
const struct GNUNET_PeerIdentity initiator 
)
static

Callback from CADET for new channels.

Parameters
clsclosure
channelnew handle to the channel
initiatorpeer that started the channel
Returns
initial channel context for the channel

Definition at line 2491 of file gnunet-daemon-exit.c.

2494{
2495 struct LocalService *ls = cls;
2496 struct ChannelState *s = GNUNET_new (struct ChannelState);
2497
2498 s->peer = *initiator;
2500 gettext_noop ("# Inbound CADET channels created"),
2501 1,
2502 GNUNET_NO);
2504 "Received inbound channel from `%s'\n",
2505 GNUNET_i2s (initiator));
2506 s->channel = channel;
2507 s->specifics.tcp_udp.serv = ls;
2508 s->specifics.tcp_udp.ri.remote_address = ls->address;
2509 return s;
2510}

References ChannelState::channel, gettext_noop, GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_new, GNUNET_NO, GNUNET_STATISTICS_update(), ls, ChannelState::peer, RedirectInformation::remote_address, ChannelState::ri, ChannelState::serv, ChannelState::specifics, stats, and ChannelState::tcp_udp.

Referenced by store_service().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ clean_channel()

static void clean_channel ( void *  cls,
const struct GNUNET_CADET_Channel channel 
)
static

Function called by cadet whenever an inbound channel is destroyed.

Should clean up any associated state.

Parameters
clsour struct ChannelState *
channelconnection to the other end (henceforth invalid)

Definition at line 2521 of file gnunet-daemon-exit.c.

2523{
2524 struct ChannelState *s = cls;
2525
2527 "Channel destroyed\n");
2528 if (GNUNET_SYSERR == s->is_dns)
2529 {
2530 GNUNET_free (s);
2531 return;
2532 }
2533 if (GNUNET_YES == s->is_dns)
2534 {
2535 if (channels[s->specifics.dns.my_id] == s)
2536 channels[s->specifics.dns.my_id] = NULL;
2537 }
2538 else
2539 {
2540 if (NULL != s->specifics.tcp_udp.heap_node)
2541 {
2544 &s->specifics.tcp_udp
2545 .state_key,
2546 s));
2548 s->specifics.tcp_udp.heap_node = NULL;
2549 }
2550 }
2551 GNUNET_free (s);
2552}

References channels, connections_map, ChannelState::dns, GNUNET_assert, GNUNET_CONTAINER_heap_remove_node(), GNUNET_CONTAINER_multihashmap_remove(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_SYSERR, GNUNET_YES, ChannelState::heap_node, ChannelState::is_dns, LOG, ChannelState::my_id, ChannelState::specifics, ChannelState::state_key, and ChannelState::tcp_udp.

Referenced by advertise_dns_exit(), run(), and store_service().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ store_service()

static void store_service ( int  proto,
const char *  name,
uint16_t  destination_port,
struct LocalService service 
)
static

Given a service descriptor and a destination port, find the respective service entry.

Parameters
protoIPPROTO_TCP or IPPROTO_UDP
namename of the service
destination_portdestination port
serviceservice information record to store (service->name will be set).

Definition at line 2565 of file gnunet-daemon-exit.c.

2569{
2571 GNUNET_MQ_hd_var_size (icmp_service,
2574 service),
2575 GNUNET_MQ_hd_var_size (udp_service,
2578 service),
2579 GNUNET_MQ_hd_var_size (tcp_service,
2582 service),
2583 GNUNET_MQ_hd_var_size (tcp_data,
2586 service),
2588 };
2589
2591
2592 service->name = GNUNET_strdup (name);
2594 &service->descriptor);
2596 destination_port,
2597 &cadet_port);
2599 "Opening CADET port %s for SERVICE exit %s on port %u\n",
2601 name,
2602 (unsigned int) destination_port);
2604 &cadet_port,
2606 service,
2607 NULL,
2609 handlers);
2610 service->is_udp = (IPPROTO_UDP == proto);
2611 if (GNUNET_OK !=
2613 &cadet_port,
2614 service,
2616 {
2618 GNUNET_free (service->name);
2621 _ ("Got duplicate service records for `%s:%u'\n"),
2622 name,
2623 (unsigned int) destination_port);
2624 }
2625}

References _, cadet_handle, cadet_port, clean_channel(), GNUNET_CADET_close_port(), GNUNET_CADET_open_port(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_h2s(), GNUNET_log, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT, GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START, GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE, GNUNET_MQ_handler_end, GNUNET_MQ_hd_var_size, GNUNET_OK, GNUNET_strdup, GNUNET_TUN_compute_service_cadet_port(), GNUNET_TUN_service_name_to_hash(), handlers, name, new_service_channel(), proto, service, and services.

Referenced by add_services().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ send_packet_to_cadet_channel()

static void send_packet_to_cadet_channel ( struct ChannelState s,
struct GNUNET_MQ_Envelope env 
)
static

Send the given packet via the cadet channel.

Parameters
schannel destination
envmessage to queue

Definition at line 2635 of file gnunet-daemon-exit.c.

2637{
2638 GNUNET_assert (NULL != s);
2640 gettext_noop (
2641 "# Messages transmitted via cadet channels"),
2642 1,
2643 GNUNET_NO);
2645 env);
2646}

References ChannelState::channel, env, gettext_noop, GNUNET_assert, GNUNET_CADET_get_mq(), GNUNET_MQ_send(), GNUNET_NO, GNUNET_STATISTICS_update(), and stats.

Referenced by icmp_from_helper(), tcp_from_helper(), and udp_from_helper().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ icmp_from_helper()

static void icmp_from_helper ( const struct GNUNET_TUN_IcmpHeader icmp,
size_t  pktlen,
int  af,
const void *  destination_ip,
const void *  source_ip 
)
static

Handles an ICMP packet received from the helper.

Parameters
icmpA pointer to the Packet
pktlennumber of bytes in icmp
afaddress family (AFINET or AF_INET6)
destination_ipdestination IP-address of the IP packet (should be our local address)
source_iporiginal source IP-address of the IP packet (should be the original destination address)

Definition at line 2661 of file gnunet-daemon-exit.c.

2666{
2667 struct ChannelState *state;
2668 struct GNUNET_MQ_Envelope *env;
2669 struct GNUNET_EXIT_IcmpToVPNMessage *i2v;
2670 const struct GNUNET_TUN_IPv4Header *ipv4;
2671 const struct GNUNET_TUN_IPv6Header *ipv6;
2672 const struct GNUNET_TUN_UdpHeader *udp;
2673 uint16_t source_port;
2674 uint16_t destination_port;
2675 uint8_t protocol;
2676
2677 {
2678 char sbuf[INET6_ADDRSTRLEN];
2679 char dbuf[INET6_ADDRSTRLEN];
2681 "Received ICMP packet going from %s to %s\n",
2682 inet_ntop (af,
2683 source_ip,
2684 sbuf, sizeof(sbuf)),
2685 inet_ntop (af,
2686 destination_ip,
2687 dbuf, sizeof(dbuf)));
2688 }
2689
2690 if (pktlen < sizeof(struct GNUNET_TUN_IcmpHeader))
2691 {
2692 /* blame kernel */
2693 GNUNET_break (0);
2694 return;
2695 }
2696
2697 /* Find out if this is an ICMP packet in response to an existing
2698 TCP/UDP packet and if so, figure out ports / protocol of the
2699 existing session from the IP data in the ICMP payload */
2700 source_port = 0;
2701 destination_port = 0;
2702 switch (af)
2703 {
2704 case AF_INET:
2705 protocol = IPPROTO_ICMP;
2706 switch (icmp->type)
2707 {
2710 break;
2711
2715 if (pktlen <
2716 sizeof(struct GNUNET_TUN_IcmpHeader)
2717 + sizeof(struct GNUNET_TUN_IPv4Header) + 8)
2718 {
2719 /* blame kernel */
2720 GNUNET_break (0);
2721 return;
2722 }
2723 ipv4 = (const struct GNUNET_TUN_IPv4Header *) &icmp[1];
2724 protocol = ipv4->protocol;
2725 /* could be TCP or UDP, but both have the ports in the right
2726 place, so that doesn't matter here */
2727 udp = (const struct GNUNET_TUN_UdpHeader *) &ipv4[1];
2728 /* swap ports, as they are from the original message */
2729 destination_port = ntohs (udp->source_port);
2730 source_port = ntohs (udp->destination_port);
2731 /* throw away ICMP payload, won't be useful for the other side anyway */
2732 pktlen = sizeof(struct GNUNET_TUN_IcmpHeader);
2733 break;
2734
2735 default:
2737 gettext_noop (
2738 "# ICMPv4 packets dropped (type not allowed)")
2739 ,
2740 1, GNUNET_NO);
2741 return;
2742 }
2743 break;
2744
2745 case AF_INET6:
2746 protocol = IPPROTO_ICMPV6;
2747 switch (icmp->type)
2748 {
2753 if (pktlen <
2754 sizeof(struct GNUNET_TUN_IcmpHeader)
2755 + sizeof(struct GNUNET_TUN_IPv6Header) + 8)
2756 {
2757 /* blame kernel */
2758 GNUNET_break (0);
2759 return;
2760 }
2761 ipv6 = (const struct GNUNET_TUN_IPv6Header *) &icmp[1];
2762 protocol = ipv6->next_header;
2763 /* could be TCP or UDP, but both have the ports in the right
2764 place, so that doesn't matter here */
2765 udp = (const struct GNUNET_TUN_UdpHeader *) &ipv6[1];
2766 /* swap ports, as they are from the original message */
2767 destination_port = ntohs (udp->source_port);
2768 source_port = ntohs (udp->destination_port);
2769 /* throw away ICMP payload, won't be useful for the other side anyway */
2770 pktlen = sizeof(struct GNUNET_TUN_IcmpHeader);
2771 break;
2772
2775 break;
2776
2777 default:
2779 gettext_noop (
2780 "# ICMPv6 packets dropped (type not allowed)")
2781 ,
2782 1, GNUNET_NO);
2783 return;
2784 }
2785 break;
2786
2787 default:
2788 GNUNET_assert (0);
2789 }
2790 switch (protocol)
2791 {
2792 case IPPROTO_ICMP:
2794 IPPROTO_ICMP,
2795 source_ip,
2796 0,
2797 destination_ip,
2798 0,
2799 NULL);
2800 break;
2801
2802 case IPPROTO_ICMPV6:
2804 IPPROTO_ICMPV6,
2805 source_ip,
2806 0,
2807 destination_ip,
2808 0,
2809 NULL);
2810 break;
2811
2812 case IPPROTO_UDP:
2814 IPPROTO_UDP,
2815 source_ip,
2816 source_port,
2817 destination_ip,
2818 destination_port,
2819 NULL);
2820 break;
2821
2822 case IPPROTO_TCP:
2824 IPPROTO_TCP,
2825 source_ip,
2826 source_port,
2827 destination_ip,
2828 destination_port,
2829 NULL);
2830 break;
2831
2832 default:
2834 gettext_noop (
2835 "# ICMP packets dropped (not allowed)"),
2836 1,
2837 GNUNET_NO);
2838 return;
2839 }
2840 if (NULL == state)
2841 {
2843 _ (
2844 "ICMP Packet dropped, have no matching connection information\n"));
2845 return;
2846 }
2847 env = GNUNET_MQ_msg_extra (i2v,
2848 pktlen - sizeof(struct GNUNET_TUN_IcmpHeader),
2850 i2v->af = htonl (af);
2852 icmp,
2853 pktlen);
2855 env);
2856}

References _, GNUNET_EXIT_IcmpToVPNMessage::af, GNUNET_TUN_UdpHeader::destination_port, env, get_redirect_state(), gettext_noop, GNUNET_assert, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_log, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN, GNUNET_MQ_msg_extra, GNUNET_NO, GNUNET_STATISTICS_update(), GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE, GNUNET_TUN_ICMPTYPE6_ECHO_REPLY, GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST, GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG, GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM, GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED, GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE, GNUNET_TUN_ICMPTYPE_ECHO_REPLY, GNUNET_TUN_ICMPTYPE_ECHO_REQUEST, GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH, GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED, GNUNET_EXIT_IcmpToVPNMessage::icmp_header, ipv4, ipv6, GNUNET_TUN_IPv4Header::protocol, send_packet_to_cadet_channel(), GNUNET_TUN_UdpHeader::source_port, state, stats, GNUNET_TUN_IcmpHeader::type, and udp.

Referenced by message_token().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ udp_from_helper()

static void udp_from_helper ( const struct GNUNET_TUN_UdpHeader udp,
size_t  pktlen,
int  af,
const void *  destination_ip,
const void *  source_ip 
)
static

Handles an UDP packet received from the helper.

Parameters
udpA pointer to the Packet
pktlennumber of bytes in 'udp'
afaddress family (AFINET or AF_INET6)
destination_ipdestination IP-address of the IP packet (should be our local address)
source_iporiginal source IP-address of the IP packet (should be the original destination address)

Definition at line 2871 of file gnunet-daemon-exit.c.

2876{
2877 struct ChannelState *state;
2878 struct GNUNET_MQ_Envelope *env;
2879 struct GNUNET_EXIT_UdpReplyMessage *urm;
2880
2881 {
2882 char sbuf[INET6_ADDRSTRLEN];
2883 char dbuf[INET6_ADDRSTRLEN];
2884
2886 "Received UDP packet going from %s:%u to %s:%u\n",
2887 inet_ntop (af,
2888 source_ip,
2889 sbuf, sizeof(sbuf)),
2890 (unsigned int) ntohs (udp->source_port),
2891 inet_ntop (af,
2892 destination_ip,
2893 dbuf, sizeof(dbuf)),
2894 (unsigned int) ntohs (udp->destination_port));
2895 }
2896
2897 if (pktlen < sizeof(struct GNUNET_TUN_UdpHeader))
2898 {
2899 /* blame kernel */
2900 GNUNET_break (0);
2901 return;
2902 }
2903 if (pktlen != ntohs (udp->len))
2904 {
2905 /* blame kernel */
2906 GNUNET_break (0);
2907 return;
2908 }
2910 IPPROTO_UDP,
2911 source_ip,
2912 ntohs (udp->source_port),
2913 destination_ip,
2914 ntohs (udp->destination_port),
2915 NULL);
2916 if (NULL == state)
2917 {
2919 _ (
2920 "UDP Packet dropped, have no matching connection information\n"));
2921 return;
2922 }
2923 env = GNUNET_MQ_msg_extra (urm,
2924 pktlen - sizeof(struct GNUNET_TUN_UdpHeader),
2926 urm->source_port = htons (0);
2927 urm->destination_port = htons (0);
2928 GNUNET_memcpy (&urm[1],
2929 &udp[1],
2930 pktlen - sizeof(struct GNUNET_TUN_UdpHeader));
2932 env);
2933}

References _, GNUNET_EXIT_UdpReplyMessage::destination_port, env, get_redirect_state(), GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_log, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY, GNUNET_MQ_msg_extra, send_packet_to_cadet_channel(), GNUNET_EXIT_UdpReplyMessage::source_port, state, and udp.

Referenced by message_token().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ tcp_from_helper()

static void tcp_from_helper ( const struct GNUNET_TUN_TcpHeader tcp,
size_t  pktlen,
int  af,
const void *  destination_ip,
const void *  source_ip 
)
static

Handles a TCP packet received from the helper.

Parameters
tcpA pointer to the Packet
pktlenthe length of the packet, including its TCP header
afaddress family (AFINET or AF_INET6)
destination_ipdestination IP-address of the IP packet (should be our local address)
source_iporiginal source IP-address of the IP packet (should be the original destination address)

Definition at line 2948 of file gnunet-daemon-exit.c.

2953{
2954 struct ChannelState *state;
2955 char buf[pktlen] GNUNET_ALIGN;
2956 struct GNUNET_TUN_TcpHeader *mtcp;
2957 struct GNUNET_EXIT_TcpDataMessage *tdm;
2958 struct GNUNET_MQ_Envelope *env;
2959 size_t mlen;
2960
2961 {
2962 char sbuf[INET6_ADDRSTRLEN];
2963 char dbuf[INET6_ADDRSTRLEN];
2965 "Received TCP packet with %u bytes going from %s:%u to %s:%u\n",
2966 (unsigned int) (pktlen - sizeof(struct GNUNET_TUN_TcpHeader)),
2967 inet_ntop (af,
2968 source_ip,
2969 sbuf, sizeof(sbuf)),
2970 (unsigned int) ntohs (tcp->source_port),
2971 inet_ntop (af,
2972 destination_ip,
2973 dbuf, sizeof(dbuf)),
2974 (unsigned int) ntohs (tcp->destination_port));
2975 }
2976
2977 if (pktlen < sizeof(struct GNUNET_TUN_TcpHeader))
2978 {
2979 /* blame kernel */
2980 GNUNET_break (0);
2981 return;
2982 }
2984 IPPROTO_TCP,
2985 source_ip,
2986 ntohs (tcp->source_port),
2987 destination_ip,
2988 ntohs (tcp->destination_port),
2989 NULL);
2990 if (NULL == state)
2991 {
2993 _ (
2994 "TCP Packet dropped, have no matching connection information\n"));
2995
2996 return;
2997 }
2998 /* mug port numbers and crc to avoid information leakage;
2999 sender will need to lookup the correct values anyway */
3000 GNUNET_memcpy (buf, tcp, pktlen);
3001 mtcp = (struct GNUNET_TUN_TcpHeader *) buf;
3002 mtcp->source_port = 0;
3003 mtcp->destination_port = 0;
3004 mtcp->crc = 0;
3005
3006 mlen = sizeof(struct GNUNET_EXIT_TcpDataMessage) + (pktlen - sizeof(struct
3008 if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
3009 {
3010 GNUNET_break (0);
3011 return;
3012 }
3013 env = GNUNET_MQ_msg_extra (tdm,
3014 pktlen - sizeof(struct GNUNET_TUN_TcpHeader),
3016 tdm->reserved = htonl (0);
3018 buf,
3019 pktlen);
3021 env);
3022}

References _, env, get_redirect_state(), GNUNET_ALIGN, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_log, GNUNET_MAX_MESSAGE_SIZE, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN, GNUNET_MQ_msg_extra, GNUNET_TUN_TcpHeader::off, GNUNET_EXIT_TcpDataMessage::reserved, send_packet_to_cadet_channel(), GNUNET_TUN_TcpHeader::source_port, state, tcp, and GNUNET_EXIT_TcpDataMessage::tcp_header.

Referenced by message_token().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ message_token()

static int message_token ( void *  cls,
const struct GNUNET_MessageHeader message 
)
static

Receive packets from the helper-process.

Parameters
clsunused
messagemessage received from helper

Definition at line 3032 of file gnunet-daemon-exit.c.

3034{
3035 const struct GNUNET_TUN_Layer2PacketHeader *pkt_tun;
3036 size_t size;
3037
3039 "Got %u-byte message of type %u from gnunet-helper-exit\n",
3040 ntohs (message->size),
3041 ntohs (message->type));
3043 gettext_noop ("# Packets received from TUN"),
3044 1, GNUNET_NO);
3045 if (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER)
3046 {
3047 GNUNET_break (0);
3048 return GNUNET_OK;
3049 }
3050 size = ntohs (message->size);
3051 if (size < sizeof(struct GNUNET_TUN_Layer2PacketHeader) + sizeof(struct
3053 {
3054 GNUNET_break (0);
3055 return GNUNET_OK;
3056 }
3058 gettext_noop ("# Bytes received from TUN"),
3059 size, GNUNET_NO);
3060 pkt_tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
3061 size -= sizeof(struct GNUNET_TUN_Layer2PacketHeader) + sizeof(struct
3063 switch (ntohs (pkt_tun->proto))
3064 {
3065 case ETH_P_IPV4:
3066 {
3067 const struct GNUNET_TUN_IPv4Header *pkt4;
3068
3069 if (size < sizeof(struct GNUNET_TUN_IPv4Header))
3070 {
3071 /* Kernel to blame? */
3072 GNUNET_break (0);
3073 return GNUNET_OK;
3074 }
3075 pkt4 = (const struct GNUNET_TUN_IPv4Header *) &pkt_tun[1];
3076 if (size != ntohs (pkt4->total_length))
3077 {
3078 /* Kernel to blame? */
3079 GNUNET_break (0);
3080 return GNUNET_OK;
3081 }
3082 if (pkt4->header_length * 4 != sizeof(struct GNUNET_TUN_IPv4Header))
3083 {
3085 _ ("IPv4 packet options received. Ignored.\n"));
3086 return GNUNET_OK;
3087 }
3088
3089 size -= sizeof(struct GNUNET_TUN_IPv4Header);
3090 switch (pkt4->protocol)
3091 {
3092 case IPPROTO_UDP:
3093 udp_from_helper ((const struct GNUNET_TUN_UdpHeader *) &pkt4[1], size,
3094 AF_INET,
3095 &pkt4->destination_address,
3096 &pkt4->source_address);
3097 break;
3098
3099 case IPPROTO_TCP:
3100 tcp_from_helper ((const struct GNUNET_TUN_TcpHeader *) &pkt4[1], size,
3101 AF_INET,
3102 &pkt4->destination_address,
3103 &pkt4->source_address);
3104 break;
3105
3106 case IPPROTO_ICMP:
3107 icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt4[1], size,
3108 AF_INET,
3109 &pkt4->destination_address,
3110 &pkt4->source_address);
3111 break;
3112
3113 default:
3115 _ (
3116 "IPv4 packet with unsupported next header %u received. Ignored.\n"),
3117 (int) pkt4->protocol);
3118 return GNUNET_OK;
3119 }
3120 }
3121 break;
3122
3123 case ETH_P_IPV6:
3124 {
3125 const struct GNUNET_TUN_IPv6Header *pkt6;
3126
3127 if (size < sizeof(struct GNUNET_TUN_IPv6Header))
3128 {
3129 /* Kernel to blame? */
3130 GNUNET_break (0);
3131 return GNUNET_OK;
3132 }
3133 pkt6 = (struct GNUNET_TUN_IPv6Header *) &pkt_tun[1];
3134 if (size != ntohs (pkt6->payload_length) + sizeof(struct
3136 {
3137 /* Kernel to blame? */
3138 GNUNET_break (0);
3139 return GNUNET_OK;
3140 }
3141 size -= sizeof(struct GNUNET_TUN_IPv6Header);
3142 switch (pkt6->next_header)
3143 {
3144 case IPPROTO_UDP:
3145 udp_from_helper ((const struct GNUNET_TUN_UdpHeader *) &pkt6[1], size,
3146 AF_INET6,
3147 &pkt6->destination_address,
3148 &pkt6->source_address);
3149 break;
3150
3151 case IPPROTO_TCP:
3152 tcp_from_helper ((const struct GNUNET_TUN_TcpHeader *) &pkt6[1], size,
3153 AF_INET6,
3154 &pkt6->destination_address,
3155 &pkt6->source_address);
3156 break;
3157
3158 case IPPROTO_ICMPV6:
3159 icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt6[1], size,
3160 AF_INET6,
3161 &pkt6->destination_address,
3162 &pkt6->source_address);
3163 break;
3164
3165 default:
3167 _ (
3168 "IPv6 packet with unsupported next header %d received. Ignored.\n"),
3169 pkt6->next_header);
3170 return GNUNET_OK;
3171 }
3172 }
3173 break;
3174
3175 default:
3177 _ ("Packet from unknown protocol %u received. Ignored.\n"),
3178 ntohs (pkt_tun->proto));
3179 break;
3180 }
3181 return GNUNET_OK;
3182}

References _, ETH_P_IPV4, ETH_P_IPV6, gettext_noop, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_MESSAGE_TYPE_VPN_HELPER, GNUNET_NO, GNUNET_OK, GNUNET_STATISTICS_update(), GNUNET_TUN_IPv4Header::header_length, icmp_from_helper(), GNUNET_TUN_IPv6Header::next_header, GNUNET_TUN_IPv6Header::payload_length, GNUNET_TUN_Layer2PacketHeader::proto, GNUNET_TUN_IPv4Header::protocol, GNUNET_MessageHeader::size, size, stats, tcp_from_helper(), GNUNET_TUN_IPv4Header::total_length, GNUNET_MessageHeader::type, and udp_from_helper().

Referenced by run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ new_channel()

static void * new_channel ( void *  cls,
struct GNUNET_CADET_Channel channel,
const struct GNUNET_PeerIdentity initiator 
)
static

Callback from CADET for new channels.

Parameters
clsclosure
channelnew handle to the channel
initiatorpeer that started the channel
Returns
initial channel context for the channel

Definition at line 3194 of file gnunet-daemon-exit.c.

3197{
3198 struct ChannelState *s = GNUNET_new (struct ChannelState);
3199
3200 s->is_dns = GNUNET_SYSERR;
3201 s->peer = *initiator;
3203 gettext_noop ("# Inbound CADET channels created"),
3204 1,
3205 GNUNET_NO);
3207 "Received inbound channel from `%s'\n",
3208 GNUNET_i2s (initiator));
3209 s->channel = channel;
3210 return s;
3211}

References ChannelState::channel, gettext_noop, GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_new, GNUNET_NO, GNUNET_STATISTICS_update(), GNUNET_SYSERR, ChannelState::is_dns, ChannelState::peer, and stats.

Referenced by advertise_dns_exit(), and run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ free_iterate()

static int free_iterate ( void *  cls,
const struct GNUNET_HashCode hash,
void *  value 
)
static

Function that frees everything from a hashmap.

Parameters
clsunused
hashkey
valuevalue to free

Definition at line 3222 of file gnunet-daemon-exit.c.

3225{
3227 return GNUNET_YES;
3228}

References GNUNET_free, GNUNET_YES, and value.

Referenced by cleanup().

Here is the caller graph for this function:

◆ dummy_task()

static void dummy_task ( void *  cls)
static

Function scheduled as very last function if the service disabled itself because the helper is not installed properly.

Does nothing, except for keeping the service process alive by virtue of being scheduled.

Parameters
clsNULL

Definition at line 3240 of file gnunet-daemon-exit.c.

3241{
3242 /* just terminate */
3243}

Referenced by run().

Here is the caller graph for this function:

◆ cleanup()

static void cleanup ( void *  cls)
static

Function scheduled as very last function, cleans up after us.

Parameters
clsNULL

Definition at line 3252 of file gnunet-daemon-exit.c.

3253{
3254 unsigned int i;
3255
3257 "Exit service is shutting down now\n");
3258
3259 if (NULL != helper_handle)
3260 {
3262 helper_handle = NULL;
3263 }
3264 if (NULL != regex4)
3265 {
3267 regex4 = NULL;
3268 }
3269 if (NULL != regex6)
3270 {
3272 regex6 = NULL;
3273 }
3274 if (NULL != services)
3275 {
3278 NULL);
3280 }
3281 if (NULL != dns_port)
3282 {
3284 dns_port = NULL;
3285 }
3286 if (NULL != cadet_port4)
3287 {
3289 cadet_port4 = NULL;
3290 }
3291 if (NULL != cadet_port6)
3292 {
3294 cadet_port6 = NULL;
3295 }
3296 if (NULL != cadet_handle)
3297 {
3299 cadet_handle = NULL;
3300 }
3301 if (NULL != connections_map)
3302 {
3304 &free_iterate,
3305 NULL);
3307 connections_map = NULL;
3308 }
3309 if (NULL != connections_heap)
3310 {
3312 connections_heap = NULL;
3313 }
3314 if (NULL != dnsstub)
3315 {
3317 dnsstub = NULL;
3318 }
3319 if (NULL != peer_key)
3320 {
3322 peer_key = NULL;
3323 }
3324 if (NULL != dht_task)
3325 {
3327 dht_task = NULL;
3328 }
3329 if (NULL != dht_put)
3330 {
3332 dht_put = NULL;
3333 }
3334 if (NULL != dht)
3335 {
3337 dht = NULL;
3338 }
3339 if (NULL != stats)
3340 {
3342 GNUNET_NO);
3343 stats = NULL;
3344 }
3345 for (i = 0; i < 8; i++)
3347}

References cadet_handle, cadet_port4, cadet_port6, connections_heap, connections_map, dht, dht_put, dht_task, dns_port, dnsstub, exit_argv, free_iterate(), free_service_record(), GNUNET_CADET_close_port(), GNUNET_CADET_disconnect(), GNUNET_CONTAINER_heap_destroy(), GNUNET_CONTAINER_multihashmap_destroy(), GNUNET_CONTAINER_multihashmap_iterate(), GNUNET_DHT_disconnect(), GNUNET_DHT_put_cancel(), GNUNET_DNSSTUB_stop(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_HELPER_stop(), GNUNET_log, GNUNET_NO, GNUNET_REGEX_announce_cancel(), GNUNET_SCHEDULER_cancel(), GNUNET_STATISTICS_destroy(), helper_handle, peer_key, regex4, regex6, services, and stats.

Here is the call graph for this function:

◆ add_services()

static void add_services ( int  proto,
char *  cpy,
const char *  name 
)
static

Add services to the service map.

Parameters
protoIPPROTO_TCP or IPPROTO_UDP
cpycopy of the service descriptor (can be mutilated)
nameDNS name of the service

Definition at line 3358 of file gnunet-daemon-exit.c.

3361{
3362 char *redirect;
3363 char *hostname;
3364 char *hostport;
3365 struct LocalService *serv;
3366 char *n;
3367 size_t slen;
3368 int local_port;
3369 int remote_port;
3370
3371 slen = strlen (name);
3372 GNUNET_assert (slen >= 8);
3373 n = GNUNET_strndup (name, slen - 8 /* remove .gnunet. */);
3374
3375 for (redirect = strtok (cpy, " ;"); redirect != NULL;
3376 redirect = strtok (NULL, " ;"))
3377 {
3378 if (NULL == (hostname = strstr (redirect, ":")))
3379 {
3381 _ (
3382 "Option `%s' for domain `%s' is not formatted correctly!\n")
3383 ,
3384 redirect,
3385 name);
3386 continue;
3387 }
3388 hostname[0] = '\0';
3389 hostname++;
3390 if (NULL == (hostport = strstr (hostname, ":")))
3391 {
3393 _ (
3394 "Option `%s' for domain `%s' is not formatted correctly!\n")
3395 ,
3396 redirect,
3397 name);
3398 continue;
3399 }
3400 hostport[0] = '\0';
3401 hostport++;
3402
3403 local_port = atoi (redirect);
3404 remote_port = atoi (hostport);
3405
3406 if (! ((local_port > 0) && (local_port < 65536)))
3407 {
3409 _ ("`%s' is not a valid port number (for domain `%s')!"),
3410 redirect,
3411 name);
3412 continue;
3413 }
3414 if (! ((remote_port > 0) && (remote_port < 65536)))
3415 {
3417 _ ("`%s' is not a valid port number (for domain `%s')!"),
3418 hostport,
3419 name);
3420 continue;
3421 }
3422
3423 serv = GNUNET_new (struct LocalService);
3424 serv->address.proto = proto;
3425 serv->address.port = remote_port;
3426 if (0 == strcmp ("localhost4",
3427 hostname))
3428 {
3429 const char *ip4addr = exit_argv[5];
3430
3431 serv->address.af = AF_INET;
3432 GNUNET_assert (1 == inet_pton (AF_INET,
3433 ip4addr,
3434 &serv->address.address.ipv4));
3435 }
3436 else if (0 == strcmp ("localhost6",
3437 hostname))
3438 {
3439 const char *ip6addr = exit_argv[3];
3440
3441 serv->address.af = AF_INET6;
3442 GNUNET_assert (1 == inet_pton (AF_INET6,
3443 ip6addr,
3444 &serv->address.address.ipv6));
3445 }
3446 else
3447 {
3448 struct addrinfo *res;
3449 int ret;
3450
3451 ret = getaddrinfo (hostname,
3452 NULL,
3453 NULL,
3454 &res);
3455 if ((0 != ret) || (NULL == res))
3456 {
3458 _ (
3459 "No addresses found for hostname `%s' of service `%s'!\n")
3460 ,
3461 hostname,
3462 n);
3463 GNUNET_free (serv);
3464 continue;
3465 }
3466
3467 serv->address.af = res->ai_family;
3468 switch (res->ai_family)
3469 {
3470 case AF_INET:
3471 if (! ipv4_enabled)
3472 {
3474 _ (
3475 "Service `%s' configured for IPv4, but IPv4 is disabled!\n"),
3476 n);
3477 freeaddrinfo (res);
3478 GNUNET_free (serv);
3479 continue;
3480 }
3481 serv->address.address.ipv4
3482 = ((struct sockaddr_in *) res->ai_addr)->sin_addr;
3483 break;
3484
3485 case AF_INET6:
3486 if (! ipv6_enabled)
3487 {
3489 _ (
3490 "Service `%s' configured for IPv4, but IPv4 is disabled!\n"),
3491 n);
3492 freeaddrinfo (res);
3493 GNUNET_free (serv);
3494 continue;
3495 }
3496 serv->address.address.ipv6
3497 = ((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
3498 break;
3499
3500 default:
3501 freeaddrinfo (res);
3503 _ (
3504 "No IP addresses found for hostname `%s' of service `%s'!\n"),
3505 hostname,
3506 n);
3507 GNUNET_free (serv);
3508 continue;
3509 }
3510 freeaddrinfo (res);
3511 }
3513 n,
3514 local_port,
3515 serv);
3516 }
3517 GNUNET_free (n);
3518}

References _, SocketAddress::address, LocalService::address, SocketAddress::af, exit_argv, GNUNET_assert, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log, GNUNET_new, GNUNET_strndup, SocketAddress::ipv4, ipv4_enabled, SocketAddress::ipv6, ipv6_enabled, name, SocketAddress::port, proto, SocketAddress::proto, remote_port, res, ret, and store_service().

Referenced by read_service_conf().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ read_service_conf()

static void read_service_conf ( void *  cls,
const char *  section 
)
static

Reads the configuration and populates #udp_services and #tcp_services.

Parameters
clsunused
sectionname of section in config

Definition at line 3528 of file gnunet-daemon-exit.c.

3530{
3531 char *cpy;
3532
3533 if ((strlen (section) < 8) ||
3534 (0 != strcmp (".gnunet.", section + (strlen (section) - 8))))
3535 return;
3536 if (GNUNET_OK ==
3538 section,
3539 "UDP_REDIRECTS",
3540 &cpy))
3541 {
3542 add_services (IPPROTO_UDP,
3543 cpy,
3544 section);
3545 GNUNET_free (cpy);
3546 }
3547 if (GNUNET_OK ==
3549 section,
3550 "TCP_REDIRECTS",
3551 &cpy))
3552 {
3553 add_services (IPPROTO_TCP,
3554 cpy,
3555 section);
3556 GNUNET_free (cpy);
3557 }
3558}

References add_services(), cfg, GNUNET_CONFIGURATION_get_value_string(), GNUNET_free, and GNUNET_OK.

Referenced by run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ do_dht_put()

static void do_dht_put ( void *  cls)
static

We are running a DNS exit service, advertise it in the DHT.

This task is run periodically to do the DHT PUT.

Parameters
clsclosure

Definition at line 3591 of file gnunet-daemon-exit.c.

References dht, dht_put, dht_put_cont(), DHT_PUT_FREQUENCY, dht_put_key, dht_task, dns_advertisement, DNS_ADVERTISEMENT_TIMEOUT, do_dht_put(), expiration, GNUNET_DNS_Advertisement::expiration_time, GNUNET_assert, GNUNET_BLOCK_TYPE_DNS, GNUNET_CRYPTO_eddsa_sign_(), GNUNET_DHT_put(), GNUNET_DHT_put_cancel(), GNUNET_DHT_RO_NONE, GNUNET_OK, GNUNET_SCHEDULER_add_delayed(), GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_absolute_hton(), GNUNET_TIME_absolute_ntoh(), GNUNET_TIME_relative_to_absolute(), GNUNET_TIME_UNIT_HOURS, peer_key, GNUNET_DNS_Advertisement::purpose, GNUNET_TIME_Relative::rel_value_us, and GNUNET_DNS_Advertisement::signature.

Referenced by advertise_dns_exit(), and do_dht_put().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ dht_put_cont()

static void dht_put_cont ( void *  cls)
static

Function called when the DHT PUT operation is complete.

Schedules the next PUT.

Parameters
clsclosure, NULL

Definition at line 3578 of file gnunet-daemon-exit.c.

3579{
3580 dht_put = NULL;
3581}

References dht_put.

Referenced by do_dht_put().

Here is the caller graph for this function:

◆ parse_ip_options()

static void parse_ip_options ( )
static

Figure out which IP versions we should support (and which are supported by the OS) according to our configuration.

Definition at line 3630 of file gnunet-daemon-exit.c.

3631{
3633 "exit",
3634 "EXIT_IPV4");
3636 "exit",
3637 "EXIT_IPV6");
3639 "exit",
3640 "ENABLE_IPV4");
3642 "exit",
3643 "ENABLE_IPV6");
3644 if ((ipv4_exit || ipv4_enabled) &&
3645 (GNUNET_OK != GNUNET_NETWORK_test_pf (PF_INET)) )
3646 {
3648 _ (
3649 "This system does not support IPv4, will disable IPv4 functions despite them being enabled in the configuration\n"));
3652 }
3653 if ((ipv6_exit || ipv6_enabled) &&
3654 (GNUNET_OK != GNUNET_NETWORK_test_pf (PF_INET6)) )
3655 {
3657 _ (
3658 "This system does not support IPv6, will disable IPv6 functions despite them being enabled in the configuration\n"));
3661 }
3662 if (ipv4_exit && (! ipv4_enabled))
3663 {
3665 _ (
3666 "Cannot enable IPv4 exit but disable IPv4 on TUN interface, will use ENABLE_IPv4=YES\n"));
3668 }
3669 if (ipv6_exit && (! ipv6_enabled))
3670 {
3672 _ (
3673 "Cannot enable IPv6 exit but disable IPv6 on TUN interface, will use ENABLE_IPv6=YES\n"));
3675 }
3676}

References _, cfg, GNUNET_CONFIGURATION_get_value_yesno(), GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_NETWORK_test_pf(), GNUNET_NO, GNUNET_OK, GNUNET_YES, ipv4_enabled, ipv4_exit, ipv6_enabled, and ipv6_exit.

Referenced by run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ advertise_dns_exit()

static void advertise_dns_exit ( )
static

Helper function to open the CADET port for DNS exits and to advertise the DNS exit (if applicable).

Definition at line 3684 of file gnunet-daemon-exit.c.

3685{
3687 GNUNET_MQ_hd_var_size (dns_request,
3689 struct DnsResponseMessage,
3690 NULL),
3692 };
3693 char *dns_exit;
3694 struct GNUNET_HashCode port;
3695
3696 if (GNUNET_YES !=
3698 "exit",
3699 "EXIT_DNS"))
3700 return;
3701 GNUNET_assert (NULL != (dnsstub = GNUNET_DNSSTUB_start (128)));
3702 dns_exit = NULL;
3703 /* TODO: support using multiple DNS resolvers */
3704 if ((GNUNET_OK !=
3706 "exit",
3707 "DNS_RESOLVER",
3708 &dns_exit)) ||
3709 (GNUNET_OK !=
3711 dns_exit)))
3712 {
3714 "dns",
3715 "DNS_RESOLVER",
3716 _ ("need a valid IPv4 or IPv6 address\n"));
3717 GNUNET_free (dns_exit);
3718 return;
3719 }
3720 /* open port */
3723 &port);
3725 "Opening CADET port %s for DNS exit service\n",
3726 GNUNET_h2s (&port));
3728 &port,
3729 &new_channel,
3730 NULL,
3731 NULL,
3733 handlers);
3734 /* advertise exit */
3736 1);
3740 dns_advertisement.purpose.size = htonl (sizeof(struct
3742 - sizeof(struct
3744 );
3747 GNUNET_CRYPTO_hash ("dns",
3748 strlen ("dns"),
3749 &dht_put_key);
3751 NULL);
3752 GNUNET_free (dns_exit);
3753}

References _, cadet_handle, cfg, clean_channel(), dht, dht_put_key, dht_task, dns_advertisement, dns_port, dnsstub, do_dht_put(), GNUNET_APPLICATION_PORT_INTERNET_RESOLVER, GNUNET_assert, GNUNET_CADET_open_port(), GNUNET_CONFIGURATION_get_value_string(), GNUNET_CONFIGURATION_get_value_yesno(), GNUNET_CRYPTO_eddsa_key_create_from_configuration(), GNUNET_CRYPTO_eddsa_key_get_public(), GNUNET_CRYPTO_hash(), GNUNET_DHT_connect(), GNUNET_DNSSTUB_add_dns_ip(), GNUNET_DNSSTUB_start(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_h2s(), GNUNET_log, GNUNET_log_config_invalid(), GNUNET_MESSAGE_TYPE_VPN_DNS_TO_INTERNET, GNUNET_MQ_handler_end, GNUNET_MQ_hd_var_size, GNUNET_OK, GNUNET_SCHEDULER_add_now(), GNUNET_SIGNATURE_PURPOSE_DNS_RECORD, GNUNET_YES, handlers, new_channel(), GNUNET_DNS_Advertisement::peer, peer_key, port, GNUNET_PeerIdentity::public_key, GNUNET_DNS_Advertisement::purpose, GNUNET_CRYPTO_EccSignaturePurpose::purpose, and GNUNET_CRYPTO_EccSignaturePurpose::size.

Referenced by run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ setup_exit_helper_args()

static int setup_exit_helper_args ( )
static

Initialize exit_argv.

Returns
GNUNET_OK on success, GNUNET_SYSERR if we should shutdown

Definition at line 3762 of file gnunet-daemon-exit.c.

3763{
3764 char *exit_ifname;
3765 char *tun_ifname;
3766 char *ipv6addr;
3767 char *ipv6prefix_s;
3768 char *ipv4addr;
3769 char *ipv4mask;
3770
3771 exit_argv[0] = GNUNET_strdup ("exit-gnunet");
3772 if (GNUNET_SYSERR ==
3774 "exit",
3775 "TUN_IFNAME",
3776 &tun_ifname))
3777 {
3779 "EXIT",
3780 "TUN_IFNAME");
3781 return GNUNET_SYSERR;
3782 }
3783 exit_argv[1] = tun_ifname;
3784 if (ipv4_enabled)
3785 {
3786 if (GNUNET_SYSERR ==
3788 "exit",
3789 "EXIT_IFNAME",
3790 &exit_ifname))
3791 {
3793 "EXIT",
3794 "EXIT_IFNAME");
3795 return GNUNET_SYSERR;
3796 }
3797 exit_argv[2] = exit_ifname;
3798 }
3799 else
3800 {
3801 exit_argv[2] = GNUNET_strdup ("-");
3802 }
3803
3804 if (GNUNET_YES == ipv6_enabled)
3805 {
3806 ipv6addr = NULL;
3807 if (((GNUNET_SYSERR ==
3809 "exit",
3810 "IPV6ADDR",
3811 &ipv6addr)) ||
3812 (1 != inet_pton (AF_INET6,
3813 ipv6addr,
3814 &exit_ipv6addr))))
3815 {
3817 "EXIT",
3818 "IPV6ADDR");
3819 GNUNET_free (ipv6addr);
3820 return GNUNET_SYSERR;
3821 }
3822 exit_argv[3] = ipv6addr;
3823 if (GNUNET_SYSERR ==
3825 "exit",
3826 "IPV6PREFIX",
3827 &ipv6prefix_s))
3828 {
3830 "EXIT",
3831 "IPV6PREFIX");
3832 return GNUNET_SYSERR;
3833 }
3834 exit_argv[4] = ipv6prefix_s;
3835 if ((GNUNET_OK !=
3837 "exit",
3838 "IPV6PREFIX",
3839 &ipv6prefix)) ||
3840 (ipv6prefix >= 127))
3841 {
3843 "EXIT",
3844 "IPV6PREFIX",
3845 _ ("Must be a number"));
3846 return GNUNET_SYSERR;
3847 }
3848 }
3849 else
3850 {
3851 /* IPv6 explicitly disabled */
3852 exit_argv[3] = GNUNET_strdup ("-");
3853 exit_argv[4] = GNUNET_strdup ("-");
3854 }
3855 if (GNUNET_YES == ipv4_enabled)
3856 {
3857 ipv4addr = NULL;
3858 if (((GNUNET_SYSERR ==
3860 "exit",
3861 "IPV4ADDR",
3862 &ipv4addr)) ||
3863 (1 != inet_pton (AF_INET,
3864 ipv4addr,
3865 &exit_ipv4addr))))
3866 {
3868 "EXIT",
3869 "IPV4ADDR");
3870 GNUNET_free (ipv4addr);
3871 return GNUNET_SYSERR;
3872 }
3873 exit_argv[5] = ipv4addr;
3874 ipv4mask = NULL;
3875 if (((GNUNET_SYSERR ==
3877 "exit",
3878 "IPV4MASK",
3879 &ipv4mask)) ||
3880 (1 != inet_pton (AF_INET,
3881 ipv4mask,
3882 &exit_ipv4mask))))
3883 {
3885 "EXIT",
3886 "IPV4MASK");
3887 GNUNET_free (ipv4mask);
3888 return GNUNET_SYSERR;
3889 }
3890 exit_argv[6] = ipv4mask;
3891 }
3892 else
3893 {
3894 /* IPv4 explicitly disabled */
3895 exit_argv[5] = GNUNET_strdup ("-");
3896 exit_argv[6] = GNUNET_strdup ("-");
3897 }
3898 exit_argv[7] = NULL;
3899 return GNUNET_OK;
3900}

References _, cfg, exit_argv, exit_ipv4addr, exit_ipv4mask, exit_ipv6addr, GNUNET_CONFIGURATION_get_value_number(), GNUNET_CONFIGURATION_get_value_string(), GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_log_config_invalid(), GNUNET_log_config_missing(), GNUNET_OK, GNUNET_strdup, GNUNET_SYSERR, GNUNET_YES, ipv4_enabled, ipv6_enabled, and ipv6prefix.

Referenced by run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ run()

static void run ( void *  cls,
char *const *  args,
const char *  cfgfile,
const struct GNUNET_CONFIGURATION_Handle cfg_ 
)
static

Main function that will be run by the scheduler.

Parameters
clsclosure
argsremaining command-line arguments
cfgfilename of the configuration file used (for saving, can be NULL!)
cfg_configuration

Definition at line 3912 of file gnunet-daemon-exit.c.

3916{
3918 GNUNET_MQ_hd_var_size (icmp_remote,
3921 NULL),
3922 GNUNET_MQ_hd_var_size (udp_remote,
3925 NULL),
3926 GNUNET_MQ_hd_var_size (tcp_remote,
3929 NULL),
3930 GNUNET_MQ_hd_var_size (tcp_data,
3933 NULL),
3935 };
3936 struct GNUNET_HashCode port;
3937 char *policy;
3938 char *binary;
3939 char *regex;
3940 char *prefixed_regex;
3941
3942 cfg = cfg_;
3943 if (GNUNET_OK !=
3945 "exit",
3946 "MAX_CONNECTIONS",
3948 max_connections = 1024;
3951 cfg,
3952 "gnunet-helper-exit");
3953 if ((ipv4_exit) || (ipv6_exit))
3954 {
3955 if (GNUNET_YES !=
3957 GNUNET_YES,
3958 "gnunet-vpn - - - 169.1.3.7 255.255.255.0"))
3959 // no nat, ipv4 only
3960 {
3961 GNUNET_free (binary);
3963 _ (
3964 "`%s' is not SUID or the path is invalid, EXIT will not work\n"),
3965 "gnunet-helper-exit");
3967 NULL);
3968 global_ret = 1;
3969 return;
3970 }
3971 }
3972 if (! (ipv4_enabled || ipv6_enabled))
3973 {
3974 GNUNET_free (binary);
3976 _ ("No useful service enabled. Exiting.\n"));
3978 return;
3979 }
3980
3982 NULL);
3984 cfg);
3986 if (NULL == cadet_handle)
3987 {
3988 GNUNET_free (binary);
3990 return;
3991 }
3993 if (GNUNET_OK !=
3995 {
3996 GNUNET_free (binary);
3998 return;
3999 }
4000
4002 GNUNET_NO);
4004 GNUNET_NO);
4009 NULL);
4010
4011 /* Cadet handle acquired, now open ports and announce regular
4012 expressions matching our exit */
4013 if ((GNUNET_YES == ipv4_enabled) &&
4014 (GNUNET_YES == ipv4_exit))
4015 {
4018 &port);
4020 "Opening CADET port %s for IPv4 gateway service\n",
4021 GNUNET_h2s (&port));
4023 &port,
4024 &new_channel,
4025 NULL,
4026 NULL,
4028 handlers);
4029 policy = NULL;
4030 if (GNUNET_OK !=
4032 "exit",
4033 "EXIT_RANGE_IPV4_POLICY",
4034 &policy))
4035 regex = NULL;
4036 else
4037 regex = GNUNET_REGEX_ipv4policy2regex (policy);
4038 GNUNET_free (policy);
4039 if (NULL != regex)
4040 {
4041 (void) GNUNET_asprintf (&prefixed_regex,
4042 "%s%s",
4044 regex);
4046 prefixed_regex,
4049 GNUNET_free (regex);
4050 GNUNET_free (prefixed_regex);
4051 }
4052 }
4053
4055 {
4058 &port);
4060 "Opening CADET port %s for IPv6 gateway service\n",
4061 GNUNET_h2s (&port));
4063 &port,
4064 &new_channel,
4065 NULL,
4066 NULL,
4068 handlers);
4069 policy = NULL;
4070 if (GNUNET_OK !=
4072 "exit",
4073 "EXIT_RANGE_IPV6_POLICY",
4074 &policy))
4075 regex = NULL;
4076 else
4077 regex = GNUNET_REGEX_ipv6policy2regex (policy);
4078 GNUNET_free (policy);
4079 if (NULL != regex)
4080 {
4081 (void) GNUNET_asprintf (&prefixed_regex,
4082 "%s%s",
4084 regex);
4086 prefixed_regex,
4089 GNUNET_free (regex);
4090 GNUNET_free (prefixed_regex);
4091 }
4092 }
4094 GNUNET_NO,
4095 binary,
4096 exit_argv,
4098 NULL,
4099 NULL);
4100 GNUNET_free (binary);
4101}

References _, advertise_dns_exit(), cadet_handle, cadet_port4, cadet_port6, cfg, clean_channel(), cleanup(), connections_heap, connections_map, dummy_task(), exit_argv, global_ret, GNUNET_APPLICATION_PORT_IPV4_GATEWAY, GNUNET_APPLICATION_PORT_IPV6_GATEWAY, GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX, GNUNET_asprintf(), GNUNET_CADET_connect(), GNUNET_CADET_open_port(), GNUNET_CONFIGURATION_get_value_number(), GNUNET_CONFIGURATION_get_value_string(), GNUNET_CONFIGURATION_iterate_sections(), GNUNET_CONTAINER_heap_create(), GNUNET_CONTAINER_HEAP_ORDER_MIN, GNUNET_CONTAINER_multihashmap_create(), GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_h2s(), GNUNET_HELPER_start(), GNUNET_log, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT, GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START, GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET, GNUNET_MQ_handler_end, GNUNET_MQ_hd_var_size, GNUNET_NO, GNUNET_OK, GNUNET_OS_check_helper_binary(), GNUNET_OS_get_suid_binary_path(), GNUNET_OS_project_data_gnunet(), GNUNET_REGEX_announce(), GNUNET_REGEX_ipv4policy2regex(), GNUNET_REGEX_ipv6policy2regex(), GNUNET_SCHEDULER_add_shutdown(), GNUNET_SCHEDULER_shutdown(), GNUNET_STATISTICS_create(), GNUNET_YES, handlers, helper_handle, ipv4_enabled, ipv4_exit, ipv6_enabled, ipv6_exit, max_connections, message_token(), new_channel(), parse_ip_options(), port, read_service_conf(), regex4, regex6, REGEX_MAX_PATH_LEN_IPV4, REGEX_MAX_PATH_LEN_IPV6, REGEX_REFRESH_FREQUENCY, services, setup_exit_helper_args(), and stats.

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ main()

int main ( int  argc,
char *const *  argv 
)

The main function.

Parameters
argcnumber of arguments from the command line
argvcommand line arguments
Returns
0 ok, 1 on error

Definition at line 4112 of file gnunet-daemon-exit.c.

4114{
4115 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
4117 };
4118
4119 return (GNUNET_OK ==
4121 argc,
4122 argv,
4123 "gnunet-daemon-exit",
4124 gettext_noop (
4125 "Daemon to run to provide an IP exit node for the VPN"),
4126 options,
4127 &run,
4128 NULL)) ? global_ret : 1;
4129}

References gettext_noop, global_ret, GNUNET_GETOPT_OPTION_END, GNUNET_OK, GNUNET_OS_project_data_gnunet(), GNUNET_PROGRAM_run(), options, and run().

Here is the call graph for this function:

Variable Documentation

◆ global_ret

int global_ret
static

Return value from 'main'.

Definition at line 268 of file gnunet-daemon-exit.c.

Referenced by main(), and run().

◆ regex4

struct GNUNET_REGEX_Announcement* regex4
static

Handle to our regex announcement for IPv4.

Definition at line 273 of file gnunet-daemon-exit.c.

Referenced by cleanup(), and run().

◆ regex6

struct GNUNET_REGEX_Announcement* regex6
static

Handle to our regex announcement for IPv4.

Definition at line 278 of file gnunet-daemon-exit.c.

Referenced by cleanup(), and run().

◆ cfg

const struct GNUNET_CONFIGURATION_Handle* cfg
static

The handle to the configuration used throughout the process.

Definition at line 283 of file gnunet-daemon-exit.c.

Referenced by advertise_dns_exit(), parse_ip_options(), read_service_conf(), run(), and setup_exit_helper_args().

◆ helper_handle

struct GNUNET_HELPER_Handle* helper_handle
static

The handle to the helper.

Definition at line 288 of file gnunet-daemon-exit.c.

Referenced by cleanup(), run(), send_icmp_packet_via_tun(), send_tcp_packet_via_tun(), and send_udp_packet_via_tun().

◆ exit_argv

char* exit_argv[8]
static

Arguments to the exit helper.

Definition at line 293 of file gnunet-daemon-exit.c.

Referenced by add_services(), cleanup(), run(), and setup_exit_helper_args().

◆ exit_ipv6addr

struct in6_addr exit_ipv6addr
static

IPv6 address of our TUN interface.

Definition at line 298 of file gnunet-daemon-exit.c.

Referenced by setup_exit_helper_args(), and setup_fresh_address().

◆ ipv6prefix

unsigned long long ipv6prefix
static

IPv6 prefix (0..127) from configuration file.

Definition at line 303 of file gnunet-daemon-exit.c.

Referenced by run(), setup_exit_helper_args(), and setup_fresh_address().

◆ exit_ipv4addr

struct in_addr exit_ipv4addr
static

IPv4 address of our TUN interface.

Definition at line 308 of file gnunet-daemon-exit.c.

Referenced by setup_exit_helper_args(), and setup_fresh_address().

◆ exit_ipv4mask

struct in_addr exit_ipv4mask
static

IPv4 netmask of our TUN interface.

Definition at line 313 of file gnunet-daemon-exit.c.

Referenced by setup_exit_helper_args(), and setup_fresh_address().

◆ stats

◆ cadet_handle

struct GNUNET_CADET_Handle* cadet_handle
static

The handle to cadet.

Definition at line 323 of file gnunet-daemon-exit.c.

Referenced by advertise_dns_exit(), cleanup(), run(), and store_service().

◆ connections_map

struct GNUNET_CONTAINER_MultiHashMap* connections_map
static

This hashmaps contains the mapping from peer, service-descriptor, source-port and destination-port to a struct ChannelState.

Definition at line 329 of file gnunet-daemon-exit.c.

Referenced by clean_channel(), cleanup(), get_redirect_state(), run(), and setup_state_record().

◆ connections_heap

struct GNUNET_CONTAINER_Heap* connections_heap
static

Heap so we can quickly find "old" connections.

Definition at line 334 of file gnunet-daemon-exit.c.

Referenced by cleanup(), run(), and setup_state_record().

◆ max_connections

unsigned long long max_connections
static

If there are at least this many connections, old ones will be removed.

Definition at line 339 of file gnunet-daemon-exit.c.

Referenced by run(), and setup_state_record().

◆ services

struct GNUNET_CONTAINER_MultiHashMap* services
static

This hashmaps saves interesting things about the configured services.

Definition at line 344 of file gnunet-daemon-exit.c.

Referenced by cleanup(), free_service_record(), GSC_SVCI_add(), GSC_SVCI_contains(), GSC_SVCI_remove(), GSC_SVCI_to_string(), run(), and store_service().

◆ channels

struct ChannelState* channels[UINT16_MAX+1]
static

Array of all open DNS requests from channels.

Definition at line 349 of file gnunet-daemon-exit.c.

Referenced by clean_channel(), handle_dns_request(), and process_dns_result().

◆ dnsstub

struct GNUNET_DNSSTUB_Context* dnsstub
static

Handle to the DNS Stub resolver.

Definition at line 354 of file gnunet-daemon-exit.c.

Referenced by advertise_dns_exit(), check_dns_request(), cleanup(), and handle_dns_request().

◆ dht_put

struct GNUNET_DHT_PutHandle* dht_put
static

Handle for ongoing DHT PUT operations to advertise exit service.

Definition at line 359 of file gnunet-daemon-exit.c.

Referenced by cleanup(), dht_put_cont(), and do_dht_put().

◆ dht

struct GNUNET_DHT_Handle* dht
static

◆ dht_task

struct GNUNET_SCHEDULER_Task* dht_task
static

Task for doing DHT PUTs to advertise exit service.

Definition at line 369 of file gnunet-daemon-exit.c.

Referenced by advertise_dns_exit(), cleanup(), and do_dht_put().

◆ dns_advertisement

struct GNUNET_DNS_Advertisement dns_advertisement
static

Advertisement message we put into the DHT to advertise us as a DNS exit.

Definition at line 375 of file gnunet-daemon-exit.c.

Referenced by advertise_dns_exit(), and do_dht_put().

◆ dht_put_key

struct GNUNET_HashCode dht_put_key
static

Key we store the DNS advertismenet under.

Definition at line 380 of file gnunet-daemon-exit.c.

Referenced by advertise_dns_exit(), and do_dht_put().

◆ peer_key

struct GNUNET_CRYPTO_EddsaPrivateKey* peer_key
static

Private key for this peer.

Definition at line 385 of file gnunet-daemon-exit.c.

Referenced by advertise_dns_exit(), cleanup(), and do_dht_put().

◆ dns_port

struct GNUNET_CADET_Port* dns_port
static

Port for DNS exit.

Definition at line 390 of file gnunet-daemon-exit.c.

Referenced by advertise_dns_exit(), and cleanup().

◆ cadet_port4

struct GNUNET_CADET_Port* cadet_port4
static

Port for IPv4 exit.

Definition at line 395 of file gnunet-daemon-exit.c.

Referenced by cleanup(), and run().

◆ cadet_port6

struct GNUNET_CADET_Port* cadet_port6
static

Port for IPv6 exit.

Definition at line 400 of file gnunet-daemon-exit.c.

Referenced by cleanup(), and run().

◆ ipv4_exit

int ipv4_exit
static

Are we an IPv4-exit?

Definition at line 405 of file gnunet-daemon-exit.c.

Referenced by handle_icmp_remote(), handle_tcp_remote(), handle_udp_remote(), parse_ip_options(), and run().

◆ ipv6_exit

int ipv6_exit
static

Are we an IPv6-exit?

Definition at line 410 of file gnunet-daemon-exit.c.

Referenced by handle_icmp_remote(), handle_tcp_remote(), handle_udp_remote(), parse_ip_options(), and run().

◆ ipv4_enabled

int ipv4_enabled
static

Do we support IPv4 at all on the TUN interface?

Definition at line 415 of file gnunet-daemon-exit.c.

Referenced by add_services(), parse_ip_options(), run(), and setup_exit_helper_args().

◆ ipv6_enabled

int ipv6_enabled
static

Do we support IPv6 at all on the TUN interface?

Definition at line 420 of file gnunet-daemon-exit.c.

Referenced by add_services(), parse_ip_options(), run(), and setup_exit_helper_args().