From 2b152f749e6274ab97baa09b9d1522803c76027f Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 2 Jan 2012 09:57:25 +0000 Subject: [PATCH] -using new GNUNET_HELPER_ API inside of VPN, also eliminating bugs with partial writes as part of this --- src/vpn/Makefile.am | 3 - src/vpn/gnunet-daemon-exit.c | 283 ++++++------ src/vpn/gnunet-daemon-vpn-helper.c | 691 ----------------------------- src/vpn/gnunet-daemon-vpn-helper.h | 76 ---- src/vpn/gnunet-daemon-vpn.c | 656 ++++++++++++++++++++++++++- src/vpn/gnunet-helper-vpn-api.c | 98 ---- src/vpn/gnunet-helper-vpn-api.h | 110 ----- 7 files changed, 780 insertions(+), 1137 deletions(-) delete mode 100644 src/vpn/gnunet-daemon-vpn-helper.c delete mode 100644 src/vpn/gnunet-daemon-vpn-helper.h delete mode 100644 src/vpn/gnunet-helper-vpn-api.h diff --git a/src/vpn/Makefile.am b/src/vpn/Makefile.am index ecb01969b..bdfca7f2f 100644 --- a/src/vpn/Makefile.am +++ b/src/vpn/Makefile.am @@ -34,8 +34,6 @@ gnunet_helper_vpn_SOURCES = \ gnunet_daemon_vpn_SOURCES = \ gnunet-daemon-vpn.c gnunet-daemon-vpn.h \ - gnunet-daemon-vpn-helper.c gnunet-daemon-vpn-helper.h \ - gnunet-helper-vpn-api.c gnunet-helper-vpn-api.h \ gnunet-vpn-checksum.c gnunet-vpn-checksum.h gnunet_daemon_vpn_LDADD = \ $(top_builddir)/src/core/libgnunetcore.la \ @@ -48,7 +46,6 @@ gnunet_daemon_vpn_LDADD = \ gnunet_daemon_exit_SOURCES = \ gnunet-daemon-exit.c \ - gnunet-helper-vpn-api.c gnunet-helper-vpn-api.h \ gnunet-vpn-checksum.c gnunet-vpn-checksum.h gnunet_daemon_exit_LDADD = \ $(top_builddir)/src/core/libgnunetcore.la \ diff --git a/src/vpn/gnunet-daemon-exit.c b/src/vpn/gnunet-daemon-exit.c index 5c450ecc6..ebe3ec61a 100644 --- a/src/vpn/gnunet-daemon-exit.c +++ b/src/vpn/gnunet-daemon-exit.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2010 Christian Grothoff + (C) 2010, 2012 Christian Grothoff GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -33,11 +33,8 @@ #include #include "gnunet-vpn-packet.h" -#include "gnunet-helper-vpn-api.h" #include "gnunet-vpn-checksum.h" -GNUNET_SCHEDULER_TaskIdentifier shs_task; - /** * The handle to the configuration used throughout the process */ @@ -46,7 +43,12 @@ static const struct GNUNET_CONFIGURATION_Handle *cfg; /** * The handle to the helper */ -struct GNUNET_VPN_HELPER_Handle *helper_handle; +static struct GNUNET_HELPER_Handle *helper_handle; + +/** + * Arguments to the exit helper. + */ +static char *exit_argv[7]; /** * Final status code. @@ -63,8 +65,11 @@ static struct GNUNET_MESH_Handle *mesh_handle; * source-port and destination-port to a struct redirect_state */ static struct GNUNET_CONTAINER_MultiHashMap *udp_connections; + static struct GNUNET_CONTAINER_Heap *udp_connections_heap; + static struct GNUNET_CONTAINER_MultiHashMap *tcp_connections; + static struct GNUNET_CONTAINER_Heap *tcp_connections_heap; /** @@ -136,8 +141,7 @@ struct redirect_state struct GNUNET_CONTAINER_MultiHashMap *hashmap; GNUNET_HashCode hash; - enum - { SERVICE, REMOTE } type; + enum { SERVICE, REMOTE } type; /** * The source-address and -port of this connection @@ -146,9 +150,14 @@ struct redirect_state }; /** - * This hashmaps saves interesting things about the configured services + * This hashmaps saves interesting things about the configured UDP services */ static struct GNUNET_CONTAINER_MultiHashMap *udp_services; + +/** + * This hashmaps saves interesting things about the configured TCP services + */ + static struct GNUNET_CONTAINER_MultiHashMap *tcp_services; struct tunnel_notify_queue @@ -166,6 +175,7 @@ struct tunnel_state struct GNUNET_MESH_TransmitHandle *th; }; + /** * Function that frees everything from a hashmap */ @@ -184,17 +194,23 @@ static void cleanup (void *cls GNUNET_UNUSED, const struct GNUNET_SCHEDULER_TaskContext *tskctx) { - GNUNET_assert (0 != (tskctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)); - - GNUNET_CONTAINER_multihashmap_iterate (udp_connections, free_iterate, NULL); - - GNUNET_CONTAINER_multihashmap_iterate (tcp_connections, free_iterate, NULL); + unsigned int i; + GNUNET_assert (0 != (tskctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)); if (mesh_handle != NULL) { GNUNET_MESH_disconnect (mesh_handle); mesh_handle = NULL; } + if (helper_handle != NULL) + { + GNUNET_HELPER_stop (helper_handle); + helper_handle = NULL; + } + GNUNET_CONTAINER_multihashmap_iterate (udp_connections, &free_iterate, NULL); + GNUNET_CONTAINER_multihashmap_iterate (tcp_connections, &free_iterate, NULL); + for (i=0;i<5;i++) + GNUNET_free_non_null (exit_argv[i]); } static void * @@ -750,89 +766,7 @@ next: while (proto != UDP); } -/** - * Start the helper-process - * - * If cls != NULL it is assumed that this function is called as a result of a dying - * helper. cls is then taken as handle to the old helper and is cleaned up. - */ -static void -start_helper_and_schedule (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) - return; - - if (cls != NULL) - cleanup_helper (cls); - cls = NULL; - - char *ifname; - char *ipv6addr; - char *ipv6prefix; - char *ipv4addr; - char *ipv4mask; - - if (GNUNET_SYSERR == - GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IFNAME", &ifname)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "No entry 'IFNAME' in configuration!\n"); - exit (1); - } - - if (GNUNET_SYSERR == - GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6ADDR", - &ipv6addr)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "No entry 'IPV6ADDR' in configuration!\n"); - exit (1); - } - - if (GNUNET_SYSERR == - GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6PREFIX", - &ipv6prefix)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "No entry 'IPV6PREFIX' in configuration!\n"); - exit (1); - } - - if (GNUNET_SYSERR == - GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4ADDR", - &ipv4addr)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "No entry 'IPV4ADDR' in configuration!\n"); - exit (1); - } - - if (GNUNET_SYSERR == - GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4MASK", - &ipv4mask)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "No entry 'IPV4MASK' in configuration!\n"); - exit (1); - } - - /* Start the helper - * Messages get passed to the function message_token - * When the helper dies, this function will be called again with the - * helper_handle as cls. - */ - helper_handle = - start_helper (ifname, ipv6addr, ipv6prefix, ipv4addr, ipv4mask, - "exit-gnunet", start_helper_and_schedule, message_token, - NULL); - GNUNET_free (ipv6addr); - GNUNET_free (ipv6prefix); - GNUNET_free (ipv4addr); - GNUNET_free (ipv4mask); - GNUNET_free (ifname); -} static void prepare_ipv4_packet (size_t len, uint16_t pktlen, void *payload, @@ -1068,7 +1002,6 @@ receive_tcp_service (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, * At this point it would be possible to check against some kind of ACL. */ - char *buf; size_t len; /* Prepare the state. @@ -1086,50 +1019,56 @@ receive_tcp_service (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct pkt_tun) + sizeof (struct ip6_hdr) + pkt_len; - buf = alloca (len); - - memset (buf, 0, len); - - switch (serv->version) { - case 4: - prepare_ipv4_packet (len, pkt_len, pkt, IPPROTO_TCP, &serv->v4.ip4address, - tunnel, state, (struct ip_pkt *) buf); - break; - case 6: - prepare_ipv6_packet (len, pkt_len, pkt, IPPROTO_TCP, &serv->v6.ip6address, - tunnel, state, (struct ip6_pkt *) buf); - - break; - default: - GNUNET_assert (0); - break; - } - - hash_redirect_info (&state->hash, &state->redirect_info, - serv->version == 4 ? 4 : 16); + char buf[len]; - if (GNUNET_NO == - GNUNET_CONTAINER_multihashmap_contains (tcp_connections, &state->hash)) - { - GNUNET_CONTAINER_multihashmap_put (tcp_connections, &state->hash, state, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); + memset (buf, 0, len); + switch (serv->version) + { + case 4: + prepare_ipv4_packet (len, pkt_len, pkt, IPPROTO_TCP, &serv->v4.ip4address, + tunnel, state, (struct ip_pkt *) buf); + break; + case 6: + prepare_ipv6_packet (len, pkt_len, pkt, IPPROTO_TCP, &serv->v6.ip6address, + tunnel, state, (struct ip6_pkt *) buf); + + break; + default: + GNUNET_assert (0); + break; + } - state->heap_node = - GNUNET_CONTAINER_heap_insert (tcp_connections_heap, state, - GNUNET_TIME_absolute_get ().abs_value); + hash_redirect_info (&state->hash, &state->redirect_info, + serv->version == 4 ? 4 : 16); + + if (GNUNET_NO == + GNUNET_CONTAINER_multihashmap_contains (tcp_connections, &state->hash)) + { + GNUNET_CONTAINER_multihashmap_put (tcp_connections, &state->hash, state, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); + + state->heap_node = + GNUNET_CONTAINER_heap_insert (tcp_connections_heap, state, + GNUNET_TIME_absolute_get ().abs_value); + + if (GNUNET_CONTAINER_heap_get_size (tcp_connections_heap) > + max_tcp_connections) + GNUNET_SCHEDULER_add_now (collect_connections, tcp_connections_heap); + } + else + GNUNET_free (state); - if (GNUNET_CONTAINER_heap_get_size (tcp_connections_heap) > - max_tcp_connections) - GNUNET_SCHEDULER_add_now (collect_connections, tcp_connections_heap); + /* FIXME: here, flow-control with mesh would be nice to have... */ + (void) GNUNET_HELPER_send (helper_handle, + (const struct GNUNET_MessageHeader*) buf, + GNUNET_YES, + NULL, NULL); } - else - GNUNET_free (state); - - (void) GNUNET_DISK_file_write (helper_handle->fh_to_helper, buf, len); return GNUNET_YES; } + static int receive_tcp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx GNUNET_UNUSED, @@ -1197,7 +1136,11 @@ receive_tcp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, else GNUNET_free (state); - (void) GNUNET_DISK_file_write (helper_handle->fh_to_helper, buf, len); + /* FIXME: here, flow-control with mesh would be nice to have... */ + (void) GNUNET_HELPER_send (helper_handle, + (const struct GNUNET_MessageHeader*) buf, + GNUNET_YES, + NULL, NULL); return GNUNET_YES; } @@ -1271,7 +1214,10 @@ receive_udp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, else GNUNET_free (state); - (void) GNUNET_DISK_file_write (helper_handle->fh_to_helper, buf, len); + (void) GNUNET_HELPER_send (helper_handle, + (const struct GNUNET_MessageHeader*) buf, + GNUNET_YES, + NULL, NULL); return GNUNET_YES; } @@ -1374,7 +1320,10 @@ receive_udp_service (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, else GNUNET_free (state); - (void) GNUNET_DISK_file_write (helper_handle->fh_to_helper, buf, len); + (void) GNUNET_HELPER_send (helper_handle, + (const struct GNUNET_MessageHeader*) buf, + GNUNET_YES, + NULL, NULL); return GNUNET_YES; } @@ -1430,6 +1379,7 @@ connect_to_mesh () } + /** * @brief Main function that will be run by the scheduler. * @@ -1443,10 +1393,14 @@ run (void *cls, char *const *args GNUNET_UNUSED, const char *cfgfile GNUNET_UNUSED, const struct GNUNET_CONFIGURATION_Handle *cfg_) { - cfg = cfg_; + char *ifname; + char *ipv6addr; + char *ipv6prefix; + char *ipv4addr; + char *ipv4mask; + cfg = cfg_; connect_to_mesh (); - udp_connections = GNUNET_CONTAINER_multihashmap_create (65536); udp_connections_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); @@ -1455,7 +1409,6 @@ run (void *cls, char *const *args GNUNET_UNUSED, GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); udp_services = GNUNET_CONTAINER_multihashmap_create (65536); tcp_services = GNUNET_CONTAINER_multihashmap_create (65536); - if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, "exit", "MAX_UDP_CONNECTIONS", &max_udp_connections)) @@ -1465,7 +1418,59 @@ run (void *cls, char *const *args GNUNET_UNUSED, &max_tcp_connections)) max_tcp_connections = 256; GNUNET_CONFIGURATION_iterate_sections (cfg, read_service_conf, NULL); - GNUNET_SCHEDULER_add_now (start_helper_and_schedule, NULL); + + if (GNUNET_SYSERR == + GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IFNAME", &ifname)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "No entry 'IFNAME' in configuration!\n"); + exit (1); + } + + if (GNUNET_SYSERR == + GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6ADDR", + &ipv6addr)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "No entry 'IPV6ADDR' in configuration!\n"); + exit (1); + } + + if (GNUNET_SYSERR == + GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6PREFIX", + &ipv6prefix)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "No entry 'IPV6PREFIX' in configuration!\n"); + exit (1); + } + + if (GNUNET_SYSERR == + GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4ADDR", + &ipv4addr)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "No entry 'IPV4ADDR' in configuration!\n"); + exit (1); + } + + if (GNUNET_SYSERR == + GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4MASK", + &ipv4mask)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "No entry 'IPV4MASK' in configuration!\n"); + exit (1); + } + exit_argv[0] = GNUNET_strdup ("exit-gnunet"); + exit_argv[1] = ifname; + exit_argv[2] = ipv6addr; + exit_argv[3] = ipv6prefix; + exit_argv[4] = ipv4addr; + exit_argv[5] = ipv4mask; + exit_argv[6] = NULL; + helper_handle = GNUNET_HELPER_start ("gnunet-helper-vpn", exit_argv, + &message_token, NULL); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls); } diff --git a/src/vpn/gnunet-daemon-vpn-helper.c b/src/vpn/gnunet-daemon-vpn-helper.c deleted file mode 100644 index 3bb3aa262..000000000 --- a/src/vpn/gnunet-daemon-vpn-helper.c +++ /dev/null @@ -1,691 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2010 Christian Grothoff - - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -/** - * @file vpn/gnunet-daemon-vpn-helper.c - * @brief - * @author Philipp Toelke - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "gnunet-daemon-vpn.h" -#include "gnunet-daemon-vpn-helper.h" -#include "gnunet-vpn-packet.h" -#include "gnunet-vpn-checksum.h" -#include "gnunet-helper-vpn-api.h" - -struct GNUNET_VPN_HELPER_Handle *helper_handle; - -extern struct GNUNET_CLIENT_TransmitHandle *dns_transmit_handle; - -/** - * The tunnels that will be used to send tcp- and udp-packets - */ -static struct GNUNET_MESH_Tunnel *tcp_tunnel; -static struct GNUNET_MESH_Tunnel *udp_tunnel; - -/** - * Start the helper-process - * - * If cls != NULL it is assumed that this function is called as a result of a dying - * helper. cls is then taken as handle to the old helper and is cleaned up. - * {{{ - */ -void -start_helper_and_schedule (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - shs_task = GNUNET_SCHEDULER_NO_TASK; - if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) - return; - - if (cls != NULL) - cleanup_helper (cls); - cls = NULL; - - char *ifname; - char *ipv6addr; - char *ipv6prefix; - char *ipv4addr; - char *ipv4mask; - - if (GNUNET_SYSERR == - GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IFNAME", &ifname)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "No entry 'IFNAME' in configuration!\n"); - exit (1); - } - - if (GNUNET_SYSERR == - GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6ADDR", &ipv6addr)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "No entry 'IPV6ADDR' in configuration!\n"); - exit (1); - } - - if (GNUNET_SYSERR == - GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6PREFIX", - &ipv6prefix)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "No entry 'IPV6PREFIX' in configuration!\n"); - exit (1); - } - - if (GNUNET_SYSERR == - GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR", &ipv4addr)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "No entry 'IPV4ADDR' in configuration!\n"); - exit (1); - } - - if (GNUNET_SYSERR == - GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK", &ipv4mask)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "No entry 'IPV4MASK' in configuration!\n"); - exit (1); - } - - /* Start the helper - * Messages get passed to the function message_token - * When the helper dies, this function will be called again with the - * helper_handle as cls. - */ - helper_handle = - start_helper (ifname, ipv6addr, ipv6prefix, ipv4addr, ipv4mask, - "vpn-gnunet", start_helper_and_schedule, message_token, - NULL); - - GNUNET_free (ipv6addr); - GNUNET_free (ipv6prefix); - GNUNET_free (ipv4addr); - GNUNET_free (ipv4mask); - GNUNET_free (ifname); - - /* Tell the dns-service to rehijack the dns-port - * The routing-table gets flushed if an interface disappears. - */ - GNUNET_DNS_restart_hijack (dns_handle); - GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, - helper_handle->fh_to_helper, &helper_write, - NULL); -} - -/*}}}*/ - -static void * -initialize_tunnel_state (int addrlen, struct GNUNET_MESH_TransmitHandle *th) -{ - struct tunnel_state *ts = GNUNET_malloc (sizeof *ts); - - ts->addrlen = addrlen; - ts->th = th; - return ts; -} - -/** - * Send an dns-answer-packet to the helper - */ -void -helper_write (void *cls GNUNET_UNUSED, - const struct GNUNET_SCHEDULER_TaskContext *tsdkctx) -{ - if (tsdkctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) - return; - - struct answer_packet_list *ans = answer_proc_head; - - if (NULL == ans) - return; - - size_t len = ntohs (ans->pkt.hdr.size); - - GNUNET_assert (ans->pkt.subtype == GNUNET_DNS_ANSWER_TYPE_IP); - - GNUNET_assert (20 == sizeof (struct ip_hdr)); - GNUNET_assert (8 == sizeof (struct udp_pkt)); - - size_t data_len = len - sizeof (struct answer_packet) + 1; - - void *buf; - size_t pkt_len; - - if (ans->pkt.addrlen == 16) - { - size_t net_len = - sizeof (struct ip6_hdr) + sizeof (struct udp_dns) + data_len; - pkt_len = - sizeof (struct GNUNET_MessageHeader) + sizeof (struct pkt_tun) + - net_len; - - struct ip6_udp_dns *pkt = alloca (pkt_len); - - GNUNET_assert (pkt != NULL); - memset (pkt, 0, pkt_len); - - /* set the gnunet-header */ - pkt->shdr.size = htons (pkt_len); - pkt->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); - - /* set the tun-header (no flags and ethertype of IPv4) */ - pkt->tun.flags = 0; - pkt->tun.type = htons (0x86dd); - - memcpy (&pkt->ip6_hdr.sadr, ans->pkt.from, 16); - memcpy (&pkt->ip6_hdr.dadr, ans->pkt.to, 16); - - /* set the udp-header */ - pkt->udp_dns.udp_hdr.spt = htons (53); - pkt->udp_dns.udp_hdr.dpt = ans->pkt.dst_port; - pkt->udp_dns.udp_hdr.len = htons (net_len - sizeof (struct ip6_hdr)); - pkt->udp_dns.udp_hdr.crc = 0; - uint32_t sum = 0; - - sum = calculate_checksum_update (sum, (uint16_t *) & pkt->ip6_hdr.sadr, 16); - sum = calculate_checksum_update (sum, (uint16_t *) & pkt->ip6_hdr.dadr, 16); - uint32_t tmp = (pkt->udp_dns.udp_hdr.len & 0xffff); - - sum = calculate_checksum_update (sum, (uint16_t *) & tmp, 4); - tmp = htons (((pkt->ip6_hdr.nxthdr & 0x00ff))); - sum = calculate_checksum_update (sum, (uint16_t *) & tmp, 4); - - sum = - calculate_checksum_update (sum, (uint16_t *) & pkt->udp_dns.udp_hdr, - ntohs (net_len - sizeof (struct ip6_hdr))); - pkt->udp_dns.udp_hdr.crc = calculate_checksum_end (sum); - - pkt->ip6_hdr.version = 6; - pkt->ip6_hdr.paylgth = net_len - sizeof (struct ip6_hdr); - pkt->ip6_hdr.nxthdr = IPPROTO_UDP; - pkt->ip6_hdr.hoplmt = 0xff; - - memcpy (&pkt->udp_dns.data, ans->pkt.data, data_len); - buf = pkt; - } - else if (ans->pkt.addrlen == 4) - { - size_t net_len = - sizeof (struct ip_hdr) + sizeof (struct udp_dns) + data_len; - pkt_len = - sizeof (struct GNUNET_MessageHeader) + sizeof (struct pkt_tun) + - net_len; - - struct ip_udp_dns *pkt = alloca (pkt_len); - - GNUNET_assert (pkt != NULL); - memset (pkt, 0, pkt_len); - - /* set the gnunet-header */ - pkt->shdr.size = htons (pkt_len); - pkt->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); - - /* set the tun-header (no flags and ethertype of IPv4) */ - pkt->tun.flags = 0; - pkt->tun.type = htons (0x0800); - - /* set the ip-header */ - pkt->ip_hdr.version = 4; - pkt->ip_hdr.hdr_lngth = 5; - pkt->ip_hdr.diff_serv = 0; - pkt->ip_hdr.tot_lngth = htons (net_len); - pkt->ip_hdr.ident = 0; - pkt->ip_hdr.flags = 0; - pkt->ip_hdr.frag_off = 0; - pkt->ip_hdr.ttl = 255; - pkt->ip_hdr.proto = IPPROTO_UDP; - pkt->ip_hdr.chks = 0; /* Will be calculated later */ - - memcpy (&pkt->ip_hdr.sadr, ans->pkt.from, 4); - memcpy (&pkt->ip_hdr.dadr, ans->pkt.to, 4); - - pkt->ip_hdr.chks = - calculate_ip_checksum ((uint16_t *) & pkt->ip_hdr, 5 * 4); - - /* set the udp-header */ - pkt->udp_dns.udp_hdr.spt = htons (53); - pkt->udp_dns.udp_hdr.dpt = ans->pkt.dst_port; - pkt->udp_dns.udp_hdr.len = htons (net_len - sizeof (struct ip_hdr)); - pkt->udp_dns.udp_hdr.crc = 0; /* Optional for IPv4 */ - - memcpy (&pkt->udp_dns.data, ans->pkt.data, data_len); - buf = pkt; - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Wrong addrlen = %d\n", - ans->pkt.addrlen); - GNUNET_assert (0); - return; /* convince compiler that we're done here */ - } - - GNUNET_CONTAINER_DLL_remove (answer_proc_head, answer_proc_tail, ans); - GNUNET_free (ans); - - if (GNUNET_DISK_file_write (helper_handle->fh_to_helper, buf, pkt_len) < 0) - { - cleanup_helper (helper_handle); - GNUNET_SCHEDULER_add_now (start_helper_and_schedule, NULL); - return; - } - - /* if more packets are available, reschedule */ - if (answer_proc_head != NULL) - GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, - helper_handle->fh_to_helper, &helper_write, - NULL); -} - -/** - * Receive packets from the helper-process - */ -void -message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED, - const struct GNUNET_MessageHeader *message) -{ - GNUNET_assert (ntohs (message->type) == GNUNET_MESSAGE_TYPE_VPN_HELPER); - - struct tun_pkt *pkt_tun = (struct tun_pkt *) message; - GNUNET_HashCode *key; - - /* ethertype is ipv6 */ - if (ntohs (pkt_tun->tun.type) == 0x86dd) - { - struct ip6_pkt *pkt6 = (struct ip6_pkt *) message; - - GNUNET_assert (pkt6->ip6_hdr.version == 6); - struct ip6_tcp *pkt6_tcp; - struct ip6_udp *pkt6_udp; - struct ip6_icmp *pkt6_icmp; - - pkt6_udp = NULL; /* make compiler happy */ - switch (pkt6->ip6_hdr.nxthdr) - { - case IPPROTO_UDP: - pkt6_udp = (struct ip6_udp *) pkt6; - /* Send dns-packets to the service-dns */ - if (ntohs (pkt6_udp->udp_hdr.dpt) == 53) - { - /* 9 = 8 for the udp-header + 1 for the unsigned char data[1]; */ - GNUNET_DNS_queue_request_v6 (dns_handle, - &pkt6->ip6_hdr.dadr, - &pkt6->ip6_hdr.sadr, - ntohs (pkt6_udp->udp_hdr.spt), - ntohs (pkt6_udp->udp_hdr.len) - 8, - (const void*) pkt6_udp->data); - - break; - } - /* fall through */ - case IPPROTO_TCP: - pkt6_tcp = (struct ip6_tcp *) pkt6; - - if ((key = address6_mapping_exists (&pkt6->ip6_hdr.dadr)) != NULL) - { - struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key); - - GNUNET_assert (me != NULL); - GNUNET_free (key); - - size_t size = - sizeof (struct GNUNET_MESH_Tunnel *) + - sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) + - ntohs (pkt6->ip6_hdr.paylgth); - - struct GNUNET_MESH_Tunnel **cls = GNUNET_malloc (size); - struct GNUNET_MessageHeader *hdr = - (struct GNUNET_MessageHeader *) (cls + 1); - GNUNET_HashCode *hc = (GNUNET_HashCode *) (hdr + 1); - - hdr->size = - htons (sizeof (struct GNUNET_MessageHeader) + - sizeof (GNUNET_HashCode) + ntohs (pkt6->ip6_hdr.paylgth)); - - GNUNET_MESH_ApplicationType app_type = 0; /* fix compiler uninitialized warning... */ - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "me->addrlen is %d\n", - me->addrlen); - if (me->addrlen == 0) - { - /* This is a mapping to a gnunet-service */ - memcpy (hc, &me->desc.service_descriptor, sizeof (GNUNET_HashCode)); - - if (IPPROTO_UDP == pkt6->ip6_hdr.nxthdr && - (me->desc.service_type & htonl (GNUNET_DNS_SERVICE_TYPE_UDP)) && - (port_in_ports (me->desc.ports, pkt6_udp->udp_hdr.dpt) || - testBit (me->additional_ports, ntohs (pkt6_udp->udp_hdr.dpt)))) - { - hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP); - - memcpy (hc + 1, &pkt6_udp->udp_hdr, ntohs (pkt6_udp->udp_hdr.len)); - - } - else if (IPPROTO_TCP == pkt6->ip6_hdr.nxthdr && - (me->desc.service_type & htonl (GNUNET_DNS_SERVICE_TYPE_TCP)) - && (port_in_ports (me->desc.ports, pkt6_tcp->tcp_hdr.dpt))) - { - hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP); - - memcpy (hc + 1, &pkt6_tcp->tcp_hdr, ntohs (pkt6->ip6_hdr.paylgth)); - - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pip: %d\n", - port_in_ports (me->desc.ports, pkt6_tcp->tcp_hdr.dpt)); - GNUNET_assert (0); - } - if (me->tunnel == NULL && NULL != cls) - { - *cls = - GNUNET_MESH_tunnel_create (mesh_handle, - initialize_tunnel_state (16, NULL), - &send_pkt_to_peer, NULL, cls); - - GNUNET_MESH_peer_request_connect_add (*cls, - (struct GNUNET_PeerIdentity *) - &me->desc.peer); - me->tunnel = *cls; - } - else if (NULL != cls) - { - *cls = me->tunnel; - send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Queued to send IPv6 to peer %x, type %d\n", - *((unsigned int *) &me->desc.peer), ntohs (hdr->type)); - } - } - else - { - /* This is a mapping to a "real" address */ - struct remote_addr *s = (struct remote_addr *) hc; - - s->addrlen = me->addrlen; - memcpy (s->addr, me->addr, me->addrlen); - s->proto = pkt6->ip6_hdr.nxthdr; - if (s->proto == IPPROTO_UDP) - { - hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP); - memcpy (hc + 1, &pkt6_udp->udp_hdr, ntohs (pkt6_udp->udp_hdr.len)); - app_type = GNUNET_APPLICATION_TYPE_INTERNET_UDP_GATEWAY; - if (NULL != udp_tunnel) - me->tunnel = udp_tunnel; - } - else if (s->proto == IPPROTO_TCP) - { - hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP); - memcpy (hc + 1, &pkt6_tcp->tcp_hdr, ntohs (pkt6->ip6_hdr.paylgth)); - app_type = GNUNET_APPLICATION_TYPE_INTERNET_TCP_GATEWAY; - if (NULL != tcp_tunnel) - me->tunnel = tcp_tunnel; - } - else - { - GNUNET_assert (0); - } - if (me->tunnel == NULL && NULL != cls) - { - *cls = - GNUNET_MESH_tunnel_create (mesh_handle, - initialize_tunnel_state (16, NULL), - &send_pkt_to_peer, NULL, cls); - - GNUNET_MESH_peer_request_connect_by_type (*cls, app_type); - me->tunnel = *cls; - if (GNUNET_APPLICATION_TYPE_INTERNET_UDP_GATEWAY == app_type) - udp_tunnel = *cls; - else if (GNUNET_APPLICATION_TYPE_INTERNET_TCP_GATEWAY == app_type) - tcp_tunnel = *cls; - } - else if (NULL != cls) - { - *cls = me->tunnel; - send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL); - } - } - } - else - { - char pbuf[INET6_ADDRSTRLEN]; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Packet to %s, which has no mapping\n", - inet_ntop (AF_INET6, - &pkt6->ip6_hdr.dadr, - pbuf, - sizeof (pbuf))); - } - break; - case 0x3a: - /* ICMPv6 */ - pkt6_icmp = (struct ip6_icmp *) pkt6; - /* If this packet is an icmp-echo-request and a mapping exists, answer */ - if (pkt6_icmp->icmp_hdr.type == 0x80 && - (key = address6_mapping_exists (&pkt6->ip6_hdr.dadr)) != NULL) - { - GNUNET_free (key); - pkt6_icmp = GNUNET_malloc (ntohs (pkt6->shdr.size)); - memcpy (pkt6_icmp, pkt6, ntohs (pkt6->shdr.size)); - GNUNET_SCHEDULER_add_now (&send_icmp6_response, pkt6_icmp); - } - break; - } - } - /* ethertype is ipv4 */ - else if (ntohs (pkt_tun->tun.type) == 0x0800) - { - struct ip_pkt *pkt = (struct ip_pkt *) message; - struct ip_udp *udp = (struct ip_udp *) message; - struct ip_tcp *pkt_tcp; - struct ip_udp *pkt_udp; - struct ip_icmp *pkt_icmp; - - GNUNET_assert (pkt->ip_hdr.version == 4); - - /* Send dns-packets to the service-dns */ - if (pkt->ip_hdr.proto == IPPROTO_UDP && ntohs (udp->udp_hdr.dpt) == 53) - { - GNUNET_DNS_queue_request_v4 (dns_handle, - &pkt->ip_hdr.dadr, - &pkt->ip_hdr.sadr, - ntohs (udp->udp_hdr.spt), - ntohs (udp->udp_hdr.len) - 8, - (const void*) udp->data); - } - else - { - uint32_t dadr = pkt->ip_hdr.dadr.s_addr; - unsigned char *c = (unsigned char *) &dadr; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Packet to %d.%d.%d.%d, proto %x\n", - c[0], c[1], c[2], c[3], pkt->ip_hdr.proto); - switch (pkt->ip_hdr.proto) - { - case IPPROTO_TCP: - case IPPROTO_UDP: - pkt_tcp = (struct ip_tcp *) pkt; - pkt_udp = (struct ip_udp *) pkt; - - if ((key = address4_mapping_exists (dadr)) != NULL) - { - struct map_entry *me = - GNUNET_CONTAINER_multihashmap_get (hashmap, key); - GNUNET_assert (me != NULL); - GNUNET_free (key); - - size_t size = - sizeof (struct GNUNET_MESH_Tunnel *) + - sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) + - ntohs (pkt->ip_hdr.tot_lngth) - 4 * pkt->ip_hdr.hdr_lngth; - - struct GNUNET_MESH_Tunnel **cls = GNUNET_malloc (size); - struct GNUNET_MessageHeader *hdr = - (struct GNUNET_MessageHeader *) (cls + 1); - GNUNET_HashCode *hc = (GNUNET_HashCode *) (hdr + 1); - - hdr->size = - htons (sizeof (struct GNUNET_MessageHeader) + - sizeof (GNUNET_HashCode) + ntohs (pkt->ip_hdr.tot_lngth) - - 4 * pkt->ip_hdr.hdr_lngth); - - GNUNET_MESH_ApplicationType app_type = 0; /* make compiler happy */ - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "me->addrlen is %d\n", - me->addrlen); - if (me->addrlen == 0) - { - /* This is a mapping to a gnunet-service */ - memcpy (hc, &me->desc.service_descriptor, sizeof (GNUNET_HashCode)); - - if ((IPPROTO_UDP == pkt->ip_hdr.proto) && - (me->desc.service_type & htonl (GNUNET_DNS_SERVICE_TYPE_UDP)) && - (port_in_ports (me->desc.ports, pkt_udp->udp_hdr.dpt) || - testBit (me->additional_ports, ntohs (pkt_udp->udp_hdr.dpt)))) - { - hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP); - - memcpy (hc + 1, &pkt_udp->udp_hdr, ntohs (pkt_udp->udp_hdr.len)); - - } - else if ((IPPROTO_TCP == pkt->ip_hdr.proto) && - (me-> - desc.service_type & htonl (GNUNET_DNS_SERVICE_TYPE_TCP)) - && (port_in_ports (me->desc.ports, pkt_tcp->tcp_hdr.dpt))) - { - hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP); - - memcpy (hc + 1, &pkt_tcp->tcp_hdr, - ntohs (pkt->ip_hdr.tot_lngth) - - 4 * pkt->ip_hdr.hdr_lngth); - - } - if (me->tunnel == NULL && NULL != cls) - { - *cls = - GNUNET_MESH_tunnel_create (mesh_handle, - initialize_tunnel_state (4, NULL), - send_pkt_to_peer, NULL, cls); - GNUNET_MESH_peer_request_connect_add (*cls, - (struct GNUNET_PeerIdentity - *) &me->desc.peer); - me->tunnel = *cls; - } - else if (NULL != cls) - { - *cls = me->tunnel; - send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Queued to send IPv4 to peer %x, type %d\n", - *((unsigned int *) &me->desc.peer), - ntohs (hdr->type)); - } - } - else - { - /* This is a mapping to a "real" address */ - struct remote_addr *s = (struct remote_addr *) hc; - - s->addrlen = me->addrlen; - memcpy (s->addr, me->addr, me->addrlen); - s->proto = pkt->ip_hdr.proto; - if (s->proto == IPPROTO_UDP) - { - hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP); - memcpy (hc + 1, &pkt_udp->udp_hdr, ntohs (pkt_udp->udp_hdr.len)); - app_type = GNUNET_APPLICATION_TYPE_INTERNET_UDP_GATEWAY; - } - else if (s->proto == IPPROTO_TCP) - { - hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP); - memcpy (hc + 1, &pkt_tcp->tcp_hdr, - ntohs (pkt->ip_hdr.tot_lngth) - - 4 * pkt->ip_hdr.hdr_lngth); - app_type = GNUNET_APPLICATION_TYPE_INTERNET_TCP_GATEWAY; - } - else - GNUNET_assert (0); - if (me->tunnel == NULL && NULL != cls) - { - *cls = - GNUNET_MESH_tunnel_create (mesh_handle, - initialize_tunnel_state (4, NULL), - send_pkt_to_peer, NULL, cls); - - GNUNET_MESH_peer_request_connect_by_type (*cls, app_type); - me->tunnel = *cls; - } - else if (NULL != cls) - { - *cls = me->tunnel; - send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL); - } - } - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Packet to %x which has no mapping\n", dadr); - } - break; - case 0x01: - /* ICMP */ - pkt_icmp = (struct ip_icmp *) pkt; - if (pkt_icmp->icmp_hdr.type == 0x8 && - (key = address4_mapping_exists (dadr)) != NULL) - { - GNUNET_free (key); - pkt_icmp = GNUNET_malloc (ntohs (pkt->shdr.size)); - memcpy (pkt_icmp, pkt, ntohs (pkt->shdr.size)); - GNUNET_SCHEDULER_add_now (&send_icmp4_response, pkt_icmp); - } - break; - } - } - } -} - -void -write_to_helper (void *buf, size_t len) -{ - (void) GNUNET_DISK_file_write (helper_handle->fh_to_helper, buf, len); -} - -void -schedule_helper_write (struct GNUNET_TIME_Relative time, void *cls) -{ - if (GNUNET_SCHEDULER_NO_TASK != shs_task) - return; - GNUNET_SCHEDULER_add_write_file (time, helper_handle->fh_to_helper, - &helper_write, cls); -} diff --git a/src/vpn/gnunet-daemon-vpn-helper.h b/src/vpn/gnunet-daemon-vpn-helper.h deleted file mode 100644 index 7329e45ff..000000000 --- a/src/vpn/gnunet-daemon-vpn-helper.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2010 Christian Grothoff - - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -/** - * @file vpn/gnunet-daemon-vpn-helper.h - * @brief - * @author Philipp Toelke - */ -#ifndef GNUNET_DAEMON_VPN_HELPER_H -#define GNUNET_DAEMON_VPN_HELPER_H - -#include "gnunet-helper-vpn-api.h" - -/** - * Handle to the helper. contains filedescriptors and such - */ -extern struct GNUNET_VPN_HELPER_Handle *helper_handle; - -extern GNUNET_SCHEDULER_TaskIdentifier shs_task; - -/** - * Start the helper-process - */ -void -start_helper_and_schedule (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc); - -/** - * Restart the helper-process - */ -void -restart_helper (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tskctx); - -/** - * Read from the helper-process - */ -void -helper_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tsdkctx); - -/** - * Send an dns-answer-packet to the helper - */ -void -helper_write (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tsdkctx); - -/** - * Receive packets from the helper-process - */ -void -message_token (void *cls, void *client, - const struct GNUNET_MessageHeader *message); - -void -write_to_helper (void *buf, size_t len); - -void -schedule_helper_write (struct GNUNET_TIME_Relative, void *cls); - -#endif /* end of include guard: GNUNET-DAEMON-VPN-HELPER_H */ diff --git a/src/vpn/gnunet-daemon-vpn.c b/src/vpn/gnunet-daemon-vpn.c index 7d303ecd5..35db8af7b 100644 --- a/src/vpn/gnunet-daemon-vpn.c +++ b/src/vpn/gnunet-daemon-vpn.c @@ -35,7 +35,6 @@ #include "gnunet_container_lib.h" #include "gnunet_constants.h" #include -#include "gnunet-daemon-vpn-helper.h" #include "gnunet_dns_service.h" #include "gnunet-daemon-vpn.h" #include "gnunet-vpn-checksum.h" @@ -45,6 +44,16 @@ struct GNUNET_MESH_Handle *mesh_handle; struct GNUNET_CONTAINER_MultiHashMap *hashmap; static struct GNUNET_CONTAINER_Heap *heap; +/** + * The handle to the helper + */ +static struct GNUNET_HELPER_Handle *helper_handle; + +/** + * Arguments to the exit helper. + */ +static char *vpn_argv[7]; + struct GNUNET_DNS_Handle *dns_handle; struct answer_packet_list *answer_proc_head; @@ -81,6 +90,14 @@ GNUNET_SCHEDULER_TaskIdentifier conn_task; GNUNET_SCHEDULER_TaskIdentifier shs_task; +/** + * The tunnels that will be used to send tcp- and udp-packets + */ +static struct GNUNET_MESH_Tunnel *tcp_tunnel; +static struct GNUNET_MESH_Tunnel *udp_tunnel; + + + /** * Sets a bit active in a bitArray. * @@ -129,11 +146,9 @@ static void cleanup (void *cls GNUNET_UNUSED, const struct GNUNET_SCHEDULER_TaskContext *tskctx) { - GNUNET_assert (0 != (tskctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)); - - /* stop the helper */ - cleanup_helper (helper_handle); + unsigned int i; + GNUNET_assert (0 != (tskctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)); /* close the connection to the service-dns */ GNUNET_DNS_disconnect (dns_handle); if (mesh_handle != NULL) @@ -141,6 +156,11 @@ cleanup (void *cls GNUNET_UNUSED, GNUNET_MESH_disconnect (mesh_handle); mesh_handle = NULL; } + if (helper_handle != NULL) + { + GNUNET_HELPER_stop (helper_handle); + helper_handle = NULL; + } if (GNUNET_SCHEDULER_NO_TASK != shs_task) { GNUNET_SCHEDULER_cancel (shs_task); @@ -151,6 +171,8 @@ cleanup (void *cls GNUNET_UNUSED, GNUNET_SCHEDULER_cancel (conn_task); conn_task = GNUNET_SCHEDULER_NO_TASK; } + for (i=0;i<5;i++) + GNUNET_free_non_null (vpn_argv[i]); } /*}}}*/ @@ -210,6 +232,532 @@ address4_mapping_exists (uint32_t addr) } } + +static void * +initialize_tunnel_state (int addrlen, struct GNUNET_MESH_TransmitHandle *th) +{ + struct tunnel_state *ts = GNUNET_malloc (sizeof *ts); + + ts->addrlen = addrlen; + ts->th = th; + return ts; +} + +/** + * Send an dns-answer-packet to the helper + */ +void +helper_write (void *cls GNUNET_UNUSED, + int status) +{ + struct answer_packet_list *ans = answer_proc_head; + + if (NULL == ans) + return; + if (GNUNET_SYSERR == status) + return; + + size_t len = ntohs (ans->pkt.hdr.size); + + GNUNET_assert (ans->pkt.subtype == GNUNET_DNS_ANSWER_TYPE_IP); + + GNUNET_assert (20 == sizeof (struct ip_hdr)); + GNUNET_assert (8 == sizeof (struct udp_pkt)); + + size_t data_len = len - sizeof (struct answer_packet) + 1; + + size_t pkt_len; + + if (ans->pkt.addrlen == 16) + { + size_t net_len = + sizeof (struct ip6_hdr) + sizeof (struct udp_dns) + data_len; + pkt_len = + sizeof (struct GNUNET_MessageHeader) + sizeof (struct pkt_tun) + + net_len; + + struct ip6_udp_dns *pkt = alloca (pkt_len); + + GNUNET_assert (pkt != NULL); + memset (pkt, 0, pkt_len); + + /* set the gnunet-header */ + pkt->shdr.size = htons (pkt_len); + pkt->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); + + /* set the tun-header (no flags and ethertype of IPv4) */ + pkt->tun.flags = 0; + pkt->tun.type = htons (0x86dd); + + memcpy (&pkt->ip6_hdr.sadr, ans->pkt.from, 16); + memcpy (&pkt->ip6_hdr.dadr, ans->pkt.to, 16); + + /* set the udp-header */ + pkt->udp_dns.udp_hdr.spt = htons (53); + pkt->udp_dns.udp_hdr.dpt = ans->pkt.dst_port; + pkt->udp_dns.udp_hdr.len = htons (net_len - sizeof (struct ip6_hdr)); + pkt->udp_dns.udp_hdr.crc = 0; + uint32_t sum = 0; + + sum = calculate_checksum_update (sum, (uint16_t *) & pkt->ip6_hdr.sadr, 16); + sum = calculate_checksum_update (sum, (uint16_t *) & pkt->ip6_hdr.dadr, 16); + uint32_t tmp = (pkt->udp_dns.udp_hdr.len & 0xffff); + + sum = calculate_checksum_update (sum, (uint16_t *) & tmp, 4); + tmp = htons (((pkt->ip6_hdr.nxthdr & 0x00ff))); + sum = calculate_checksum_update (sum, (uint16_t *) & tmp, 4); + + sum = + calculate_checksum_update (sum, (uint16_t *) & pkt->udp_dns.udp_hdr, + ntohs (net_len - sizeof (struct ip6_hdr))); + pkt->udp_dns.udp_hdr.crc = calculate_checksum_end (sum); + + pkt->ip6_hdr.version = 6; + pkt->ip6_hdr.paylgth = net_len - sizeof (struct ip6_hdr); + pkt->ip6_hdr.nxthdr = IPPROTO_UDP; + pkt->ip6_hdr.hoplmt = 0xff; + + memcpy (&pkt->udp_dns.data, ans->pkt.data, data_len); + (void) GNUNET_HELPER_send (helper_handle, + &pkt->shdr, + GNUNET_YES, + &helper_write, NULL); + } + else if (ans->pkt.addrlen == 4) + { + size_t net_len = + sizeof (struct ip_hdr) + sizeof (struct udp_dns) + data_len; + pkt_len = + sizeof (struct GNUNET_MessageHeader) + sizeof (struct pkt_tun) + + net_len; + + struct ip_udp_dns *pkt = alloca (pkt_len); + + GNUNET_assert (pkt != NULL); + memset (pkt, 0, pkt_len); + + /* set the gnunet-header */ + pkt->shdr.size = htons (pkt_len); + pkt->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); + + /* set the tun-header (no flags and ethertype of IPv4) */ + pkt->tun.flags = 0; + pkt->tun.type = htons (0x0800); + + /* set the ip-header */ + pkt->ip_hdr.version = 4; + pkt->ip_hdr.hdr_lngth = 5; + pkt->ip_hdr.diff_serv = 0; + pkt->ip_hdr.tot_lngth = htons (net_len); + pkt->ip_hdr.ident = 0; + pkt->ip_hdr.flags = 0; + pkt->ip_hdr.frag_off = 0; + pkt->ip_hdr.ttl = 255; + pkt->ip_hdr.proto = IPPROTO_UDP; + pkt->ip_hdr.chks = 0; /* Will be calculated later */ + + memcpy (&pkt->ip_hdr.sadr, ans->pkt.from, 4); + memcpy (&pkt->ip_hdr.dadr, ans->pkt.to, 4); + + pkt->ip_hdr.chks = + calculate_ip_checksum ((uint16_t *) & pkt->ip_hdr, 5 * 4); + + /* set the udp-header */ + pkt->udp_dns.udp_hdr.spt = htons (53); + pkt->udp_dns.udp_hdr.dpt = ans->pkt.dst_port; + pkt->udp_dns.udp_hdr.len = htons (net_len - sizeof (struct ip_hdr)); + pkt->udp_dns.udp_hdr.crc = 0; /* Optional for IPv4 */ + + memcpy (&pkt->udp_dns.data, ans->pkt.data, data_len); + (void) GNUNET_HELPER_send (helper_handle, + &pkt->shdr, + GNUNET_YES, + &helper_write, NULL); + + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Wrong addrlen = %d\n", + ans->pkt.addrlen); + GNUNET_assert (0); + return; /* convince compiler that we're done here */ + } + + GNUNET_CONTAINER_DLL_remove (answer_proc_head, answer_proc_tail, ans); + GNUNET_free (ans); + +} + +/** + * Receive packets from the helper-process + */ +void +message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED, + const struct GNUNET_MessageHeader *message) +{ + GNUNET_assert (ntohs (message->type) == GNUNET_MESSAGE_TYPE_VPN_HELPER); + + struct tun_pkt *pkt_tun = (struct tun_pkt *) message; + GNUNET_HashCode *key; + + /* ethertype is ipv6 */ + if (ntohs (pkt_tun->tun.type) == 0x86dd) + { + struct ip6_pkt *pkt6 = (struct ip6_pkt *) message; + + GNUNET_assert (pkt6->ip6_hdr.version == 6); + struct ip6_tcp *pkt6_tcp; + struct ip6_udp *pkt6_udp; + struct ip6_icmp *pkt6_icmp; + + pkt6_udp = NULL; /* make compiler happy */ + switch (pkt6->ip6_hdr.nxthdr) + { + case IPPROTO_UDP: + pkt6_udp = (struct ip6_udp *) pkt6; + /* Send dns-packets to the service-dns */ + if (ntohs (pkt6_udp->udp_hdr.dpt) == 53) + { + /* 9 = 8 for the udp-header + 1 for the unsigned char data[1]; */ + GNUNET_DNS_queue_request_v6 (dns_handle, + &pkt6->ip6_hdr.dadr, + &pkt6->ip6_hdr.sadr, + ntohs (pkt6_udp->udp_hdr.spt), + ntohs (pkt6_udp->udp_hdr.len) - 8, + (const void*) pkt6_udp->data); + + break; + } + /* fall through */ + case IPPROTO_TCP: + pkt6_tcp = (struct ip6_tcp *) pkt6; + + if ((key = address6_mapping_exists (&pkt6->ip6_hdr.dadr)) != NULL) + { + struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key); + + GNUNET_assert (me != NULL); + GNUNET_free (key); + + size_t size = + sizeof (struct GNUNET_MESH_Tunnel *) + + sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) + + ntohs (pkt6->ip6_hdr.paylgth); + + struct GNUNET_MESH_Tunnel **cls = GNUNET_malloc (size); + struct GNUNET_MessageHeader *hdr = + (struct GNUNET_MessageHeader *) (cls + 1); + GNUNET_HashCode *hc = (GNUNET_HashCode *) (hdr + 1); + + hdr->size = + htons (sizeof (struct GNUNET_MessageHeader) + + sizeof (GNUNET_HashCode) + ntohs (pkt6->ip6_hdr.paylgth)); + + GNUNET_MESH_ApplicationType app_type = 0; /* fix compiler uninitialized warning... */ + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "me->addrlen is %d\n", + me->addrlen); + if (me->addrlen == 0) + { + /* This is a mapping to a gnunet-service */ + memcpy (hc, &me->desc.service_descriptor, sizeof (GNUNET_HashCode)); + + if (IPPROTO_UDP == pkt6->ip6_hdr.nxthdr && + (me->desc.service_type & htonl (GNUNET_DNS_SERVICE_TYPE_UDP)) && + (port_in_ports (me->desc.ports, pkt6_udp->udp_hdr.dpt) || + testBit (me->additional_ports, ntohs (pkt6_udp->udp_hdr.dpt)))) + { + hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP); + + memcpy (hc + 1, &pkt6_udp->udp_hdr, ntohs (pkt6_udp->udp_hdr.len)); + + } + else if (IPPROTO_TCP == pkt6->ip6_hdr.nxthdr && + (me->desc.service_type & htonl (GNUNET_DNS_SERVICE_TYPE_TCP)) + && (port_in_ports (me->desc.ports, pkt6_tcp->tcp_hdr.dpt))) + { + hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP); + + memcpy (hc + 1, &pkt6_tcp->tcp_hdr, ntohs (pkt6->ip6_hdr.paylgth)); + + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pip: %d\n", + port_in_ports (me->desc.ports, pkt6_tcp->tcp_hdr.dpt)); + GNUNET_assert (0); + } + if (me->tunnel == NULL && NULL != cls) + { + *cls = + GNUNET_MESH_tunnel_create (mesh_handle, + initialize_tunnel_state (16, NULL), + &send_pkt_to_peer, NULL, cls); + + GNUNET_MESH_peer_request_connect_add (*cls, + (struct GNUNET_PeerIdentity *) + &me->desc.peer); + me->tunnel = *cls; + } + else if (NULL != cls) + { + *cls = me->tunnel; + send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Queued to send IPv6 to peer %x, type %d\n", + *((unsigned int *) &me->desc.peer), ntohs (hdr->type)); + } + } + else + { + /* This is a mapping to a "real" address */ + struct remote_addr *s = (struct remote_addr *) hc; + + s->addrlen = me->addrlen; + memcpy (s->addr, me->addr, me->addrlen); + s->proto = pkt6->ip6_hdr.nxthdr; + if (s->proto == IPPROTO_UDP) + { + hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP); + memcpy (hc + 1, &pkt6_udp->udp_hdr, ntohs (pkt6_udp->udp_hdr.len)); + app_type = GNUNET_APPLICATION_TYPE_INTERNET_UDP_GATEWAY; + if (NULL != udp_tunnel) + me->tunnel = udp_tunnel; + } + else if (s->proto == IPPROTO_TCP) + { + hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP); + memcpy (hc + 1, &pkt6_tcp->tcp_hdr, ntohs (pkt6->ip6_hdr.paylgth)); + app_type = GNUNET_APPLICATION_TYPE_INTERNET_TCP_GATEWAY; + if (NULL != tcp_tunnel) + me->tunnel = tcp_tunnel; + } + else + { + GNUNET_assert (0); + } + if (me->tunnel == NULL && NULL != cls) + { + *cls = + GNUNET_MESH_tunnel_create (mesh_handle, + initialize_tunnel_state (16, NULL), + &send_pkt_to_peer, NULL, cls); + + GNUNET_MESH_peer_request_connect_by_type (*cls, app_type); + me->tunnel = *cls; + if (GNUNET_APPLICATION_TYPE_INTERNET_UDP_GATEWAY == app_type) + udp_tunnel = *cls; + else if (GNUNET_APPLICATION_TYPE_INTERNET_TCP_GATEWAY == app_type) + tcp_tunnel = *cls; + } + else if (NULL != cls) + { + *cls = me->tunnel; + send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL); + } + } + } + else + { + char pbuf[INET6_ADDRSTRLEN]; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Packet to %s, which has no mapping\n", + inet_ntop (AF_INET6, + &pkt6->ip6_hdr.dadr, + pbuf, + sizeof (pbuf))); + } + break; + case 0x3a: + /* ICMPv6 */ + pkt6_icmp = (struct ip6_icmp *) pkt6; + /* If this packet is an icmp-echo-request and a mapping exists, answer */ + if (pkt6_icmp->icmp_hdr.type == 0x80 && + (key = address6_mapping_exists (&pkt6->ip6_hdr.dadr)) != NULL) + { + GNUNET_free (key); + pkt6_icmp = GNUNET_malloc (ntohs (pkt6->shdr.size)); + memcpy (pkt6_icmp, pkt6, ntohs (pkt6->shdr.size)); + GNUNET_SCHEDULER_add_now (&send_icmp6_response, pkt6_icmp); + } + break; + } + } + /* ethertype is ipv4 */ + else if (ntohs (pkt_tun->tun.type) == 0x0800) + { + struct ip_pkt *pkt = (struct ip_pkt *) message; + struct ip_udp *udp = (struct ip_udp *) message; + struct ip_tcp *pkt_tcp; + struct ip_udp *pkt_udp; + struct ip_icmp *pkt_icmp; + + GNUNET_assert (pkt->ip_hdr.version == 4); + + /* Send dns-packets to the service-dns */ + if (pkt->ip_hdr.proto == IPPROTO_UDP && ntohs (udp->udp_hdr.dpt) == 53) + { + GNUNET_DNS_queue_request_v4 (dns_handle, + &pkt->ip_hdr.dadr, + &pkt->ip_hdr.sadr, + ntohs (udp->udp_hdr.spt), + ntohs (udp->udp_hdr.len) - 8, + (const void*) udp->data); + } + else + { + uint32_t dadr = pkt->ip_hdr.dadr.s_addr; + unsigned char *c = (unsigned char *) &dadr; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Packet to %d.%d.%d.%d, proto %x\n", + c[0], c[1], c[2], c[3], pkt->ip_hdr.proto); + switch (pkt->ip_hdr.proto) + { + case IPPROTO_TCP: + case IPPROTO_UDP: + pkt_tcp = (struct ip_tcp *) pkt; + pkt_udp = (struct ip_udp *) pkt; + + if ((key = address4_mapping_exists (dadr)) != NULL) + { + struct map_entry *me = + GNUNET_CONTAINER_multihashmap_get (hashmap, key); + GNUNET_assert (me != NULL); + GNUNET_free (key); + + size_t size = + sizeof (struct GNUNET_MESH_Tunnel *) + + sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) + + ntohs (pkt->ip_hdr.tot_lngth) - 4 * pkt->ip_hdr.hdr_lngth; + + struct GNUNET_MESH_Tunnel **cls = GNUNET_malloc (size); + struct GNUNET_MessageHeader *hdr = + (struct GNUNET_MessageHeader *) (cls + 1); + GNUNET_HashCode *hc = (GNUNET_HashCode *) (hdr + 1); + + hdr->size = + htons (sizeof (struct GNUNET_MessageHeader) + + sizeof (GNUNET_HashCode) + ntohs (pkt->ip_hdr.tot_lngth) - + 4 * pkt->ip_hdr.hdr_lngth); + + GNUNET_MESH_ApplicationType app_type = 0; /* make compiler happy */ + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "me->addrlen is %d\n", + me->addrlen); + if (me->addrlen == 0) + { + /* This is a mapping to a gnunet-service */ + memcpy (hc, &me->desc.service_descriptor, sizeof (GNUNET_HashCode)); + + if ((IPPROTO_UDP == pkt->ip_hdr.proto) && + (me->desc.service_type & htonl (GNUNET_DNS_SERVICE_TYPE_UDP)) && + (port_in_ports (me->desc.ports, pkt_udp->udp_hdr.dpt) || + testBit (me->additional_ports, ntohs (pkt_udp->udp_hdr.dpt)))) + { + hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP); + + memcpy (hc + 1, &pkt_udp->udp_hdr, ntohs (pkt_udp->udp_hdr.len)); + + } + else if ((IPPROTO_TCP == pkt->ip_hdr.proto) && + (me-> + desc.service_type & htonl (GNUNET_DNS_SERVICE_TYPE_TCP)) + && (port_in_ports (me->desc.ports, pkt_tcp->tcp_hdr.dpt))) + { + hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP); + + memcpy (hc + 1, &pkt_tcp->tcp_hdr, + ntohs (pkt->ip_hdr.tot_lngth) - + 4 * pkt->ip_hdr.hdr_lngth); + + } + if (me->tunnel == NULL && NULL != cls) + { + *cls = + GNUNET_MESH_tunnel_create (mesh_handle, + initialize_tunnel_state (4, NULL), + send_pkt_to_peer, NULL, cls); + GNUNET_MESH_peer_request_connect_add (*cls, + (struct GNUNET_PeerIdentity + *) &me->desc.peer); + me->tunnel = *cls; + } + else if (NULL != cls) + { + *cls = me->tunnel; + send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Queued to send IPv4 to peer %x, type %d\n", + *((unsigned int *) &me->desc.peer), + ntohs (hdr->type)); + } + } + else + { + /* This is a mapping to a "real" address */ + struct remote_addr *s = (struct remote_addr *) hc; + + s->addrlen = me->addrlen; + memcpy (s->addr, me->addr, me->addrlen); + s->proto = pkt->ip_hdr.proto; + if (s->proto == IPPROTO_UDP) + { + hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP); + memcpy (hc + 1, &pkt_udp->udp_hdr, ntohs (pkt_udp->udp_hdr.len)); + app_type = GNUNET_APPLICATION_TYPE_INTERNET_UDP_GATEWAY; + } + else if (s->proto == IPPROTO_TCP) + { + hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP); + memcpy (hc + 1, &pkt_tcp->tcp_hdr, + ntohs (pkt->ip_hdr.tot_lngth) - + 4 * pkt->ip_hdr.hdr_lngth); + app_type = GNUNET_APPLICATION_TYPE_INTERNET_TCP_GATEWAY; + } + else + GNUNET_assert (0); + if (me->tunnel == NULL && NULL != cls) + { + *cls = + GNUNET_MESH_tunnel_create (mesh_handle, + initialize_tunnel_state (4, NULL), + send_pkt_to_peer, NULL, cls); + + GNUNET_MESH_peer_request_connect_by_type (*cls, app_type); + me->tunnel = *cls; + } + else if (NULL != cls) + { + *cls = me->tunnel; + send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL); + } + } + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Packet to %x which has no mapping\n", dadr); + } + break; + case 0x01: + /* ICMP */ + pkt_icmp = (struct ip_icmp *) pkt; + if (pkt_icmp->icmp_hdr.type == 0x8 && + (key = address4_mapping_exists (dadr)) != NULL) + { + GNUNET_free (key); + pkt_icmp = GNUNET_malloc (ntohs (pkt->shdr.size)); + memcpy (pkt_icmp, pkt, ntohs (pkt->shdr.size)); + GNUNET_SCHEDULER_add_now (&send_icmp4_response, pkt_icmp); + } + break; + } + } + } +} + + + static void collect_mappings (void *cls GNUNET_UNUSED, const struct GNUNET_SCHEDULER_TaskContext *tc) @@ -269,8 +817,10 @@ send_icmp4_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) memcpy (response + 1, request + 1, ntohs (request->shdr.size) - sizeof (struct ip_icmp)); - write_to_helper (response, ntohs (response->shdr.size)); - + (void) GNUNET_HELPER_send (helper_handle, + &response->shdr, + GNUNET_YES, + NULL, NULL); GNUNET_free (request); } @@ -310,8 +860,10 @@ send_icmp6_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) memcpy (response + 1, request + 1, ntohs (request->shdr.size) - sizeof (struct ip6_icmp)); - write_to_helper (response, ntohs (response->shdr.size)); - + (void) GNUNET_HELPER_send (helper_handle, + &response->shdr, + GNUNET_YES, + NULL, NULL); GNUNET_free (request); } @@ -824,9 +1376,6 @@ process_answer (void *cls, GNUNET_CONTAINER_DLL_insert_after (answer_proc_head, answer_proc_tail, answer_proc_tail, list); - schedule_helper_write (GNUNET_TIME_UNIT_FOREVER_REL, NULL); - - return; } @@ -939,8 +1488,11 @@ receive_udp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, calculate_checksum_update (sum, (uint16_t *) & pkt6->udp_hdr, ntohs (pkt->len)); pkt6->udp_hdr.crc = calculate_checksum_end (sum); - - write_to_helper (pkt6, size); + + (void) GNUNET_HELPER_send (helper_handle, + &pkt6->shdr, + GNUNET_YES, + NULL, NULL); } else { @@ -1011,7 +1563,10 @@ receive_udp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, pkt4->ip_hdr.chks = calculate_ip_checksum ((uint16_t *) & pkt4->ip_hdr, 5 * 4); - write_to_helper (pkt4, size); + (void) GNUNET_HELPER_send (helper_handle, + &pkt4->shdr, + GNUNET_YES, + NULL, NULL); } return GNUNET_OK; @@ -1113,7 +1668,10 @@ receive_tcp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, ntohs (pkt6->ip6_hdr.paylgth)); pkt6->tcp_hdr.crc = calculate_checksum_end (sum); - write_to_helper (pkt6, size); + (void) GNUNET_HELPER_send (helper_handle, + &pkt6->shdr, + GNUNET_YES, + NULL, NULL); } else { @@ -1194,7 +1752,11 @@ receive_tcp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, pkt4->ip_hdr.chks = calculate_ip_checksum ((uint16_t *) & pkt4->ip_hdr, 5 * 4); - write_to_helper (pkt4, size); + (void) GNUNET_HELPER_send (helper_handle, + &pkt4->shdr, + GNUNET_YES, + NULL, NULL); + } return GNUNET_OK; @@ -1237,10 +1799,14 @@ run (void *cls, char *const *args GNUNET_UNUSED, {receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP_BACK, 0}, {NULL, 0, 0} }; - static const GNUNET_MESH_ApplicationType types[] = { GNUNET_APPLICATION_TYPE_END }; + char *ifname; + char *ipv6addr; + char *ipv6prefix; + char *ipv4addr; + char *ipv4mask; mesh_handle = GNUNET_MESH_connect (cfg_, 42, NULL, new_tunnel, cleaner, handlers, @@ -1254,8 +1820,58 @@ run (void *cls, char *const *args GNUNET_UNUSED, dns_handle = GNUNET_DNS_connect (cfg, &process_answer, NULL); - shs_task = - GNUNET_SCHEDULER_add_after (conn_task, start_helper_and_schedule, NULL); + if (GNUNET_SYSERR == + GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IFNAME", &ifname)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "No entry 'IFNAME' in configuration!\n"); + exit (1); + } + + if (GNUNET_SYSERR == + GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6ADDR", &ipv6addr)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "No entry 'IPV6ADDR' in configuration!\n"); + exit (1); + } + + if (GNUNET_SYSERR == + GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6PREFIX", + &ipv6prefix)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "No entry 'IPV6PREFIX' in configuration!\n"); + exit (1); + } + + if (GNUNET_SYSERR == + GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR", &ipv4addr)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "No entry 'IPV4ADDR' in configuration!\n"); + exit (1); + } + + if (GNUNET_SYSERR == + GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK", &ipv4mask)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "No entry 'IPV4MASK' in configuration!\n"); + exit (1); + } + + vpn_argv[0] = GNUNET_strdup ("vpn-gnunet"); + vpn_argv[1] = ifname; + vpn_argv[2] = ipv6addr; + vpn_argv[3] = ipv6prefix; + vpn_argv[4] = ipv4addr; + vpn_argv[5] = ipv4mask; + vpn_argv[6] = NULL; + + helper_handle = GNUNET_HELPER_start ("gnunet-helper-vpn", vpn_argv, + &message_token, NULL); + GNUNET_DNS_restart_hijack (dns_handle); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls); } diff --git a/src/vpn/gnunet-helper-vpn-api.c b/src/vpn/gnunet-helper-vpn-api.c index 379e75765..d2b5673d0 100644 --- a/src/vpn/gnunet-helper-vpn-api.c +++ b/src/vpn/gnunet-helper-vpn-api.c @@ -32,71 +32,6 @@ #include "gnunet-helper-vpn-api.h" -static void -stop_helper (struct GNUNET_VPN_HELPER_Handle *handle) -{ - if (NULL == handle->helper_proc) - return; - GNUNET_OS_process_kill (handle->helper_proc, SIGKILL); - GNUNET_OS_process_wait (handle->helper_proc); - GNUNET_OS_process_close (handle->helper_proc); - handle->helper_proc = NULL; - - GNUNET_DISK_pipe_close (handle->helper_in); - GNUNET_DISK_pipe_close (handle->helper_out); - - GNUNET_SERVER_mst_destroy (handle->mst); -} - -extern GNUNET_SCHEDULER_TaskIdentifier shs_task; - -/** - * Read from the helper-process - */ -static void -helper_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tsdkctx) -{ - struct GNUNET_VPN_HELPER_Handle *handle = cls; - - /* no message can be bigger then 64k */ - char buf[65535]; - - if (tsdkctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) - return; - - int t = GNUNET_DISK_file_read (handle->fh_from_helper, &buf, 65535); - - /* On read-error, restart the helper */ - if (t <= 0) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Read error for header from vpn-helper: %m\n"); - stop_helper (handle); - - /* Restart the helper */ - shs_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, - handle->restart_task, handle); - return; - } - - if (GNUNET_SYSERR == - GNUNET_SERVER_mst_receive (handle->mst, handle->client, buf, t, 0, 0)) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "SYSERR from mst\n"); - stop_helper (handle); - - /* Restart the helper */ - shs_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, - handle->restart_task, handle); - return; - - } - - GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, - handle->fh_from_helper, &helper_read, handle); -} void cleanup_helper (struct GNUNET_VPN_HELPER_Handle *handle) @@ -111,37 +46,4 @@ start_helper (const char *ifname, const char *ipv6addr, const char *ipv6prefix, const char *process_name, GNUNET_SCHEDULER_Task restart_task, GNUNET_SERVER_MessageTokenizerCallback cb, void *cb_cls) { - struct GNUNET_VPN_HELPER_Handle *handle = - GNUNET_malloc (sizeof (struct GNUNET_VPN_HELPER_Handle)); - - handle->helper_in = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO); - handle->helper_out = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_NO, GNUNET_YES); - - handle->restart_task = restart_task; - if (handle->helper_in == NULL || handle->helper_out == NULL) - { - GNUNET_free (handle); - return NULL; - } - - handle->helper_proc = - GNUNET_OS_start_process (handle->helper_in, handle->helper_out, - "gnunet-helper-vpn", process_name, ifname, - ipv6addr, ipv6prefix, ipv4addr, ipv4mask, NULL); - - handle->fh_from_helper = - GNUNET_DISK_pipe_handle (handle->helper_out, GNUNET_DISK_PIPE_END_READ); - handle->fh_to_helper = - GNUNET_DISK_pipe_handle (handle->helper_in, GNUNET_DISK_PIPE_END_WRITE); - - GNUNET_DISK_pipe_close_end (handle->helper_out, GNUNET_DISK_PIPE_END_WRITE); - GNUNET_DISK_pipe_close_end (handle->helper_in, GNUNET_DISK_PIPE_END_READ); - - handle->mst = GNUNET_SERVER_mst_create (cb, cb_cls); - - GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, - handle->fh_from_helper, &helper_read, handle); - - return handle; -} diff --git a/src/vpn/gnunet-helper-vpn-api.h b/src/vpn/gnunet-helper-vpn-api.h deleted file mode 100644 index 964beb23c..000000000 --- a/src/vpn/gnunet-helper-vpn-api.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2010 Christian Grothoff - - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -/** - * @file vpn/gnunet-helper-vpn-api.h - * @brief exposes the API (the convenience-functions) of dealing with the - * helper-vpn - * @author Philipp Toelke - */ -#ifndef GNUNET_HELPER_VPN_API_H -#define GNUNET_HELPER_VPN_API_H - -/** - * The handle to a helper. - * sometimes a few entries may be made opaque. - */ -struct GNUNET_VPN_HELPER_Handle -{ -/** - * PipeHandle to receive data from the helper - */ - struct GNUNET_DISK_PipeHandle *helper_in; - -/** - * PipeHandle to send data to the helper - */ - struct GNUNET_DISK_PipeHandle *helper_out; - -/** - * FileHandle to receive data from the helper - */ - const struct GNUNET_DISK_FileHandle *fh_from_helper; - -/** - * FileHandle to send data to the helper - */ - const struct GNUNET_DISK_FileHandle *fh_to_helper; - - /** - * The process id of the helper - */ - struct GNUNET_OS_Process *helper_proc; - - /** - * The Message-Tokenizer that tokenizes the messages comming from the helper - */ - struct GNUNET_SERVER_MessageStreamTokenizer *mst; - - /** - * The client-identifier passed to the mst-callback - */ - void *client; - - /** - * The name of the interface - */ - char *ifname; - - /** - * The task called when the helper dies. - * Will be called with the handle as cls - */ - GNUNET_SCHEDULER_Task restart_task; -}; - -/** - * @brief Starts a helper and begins reading from it - * - * @param ifname The name of the new interface - * @param ipv6addr The IPv6 address of the new interface - * @param ipv6prefix The IPv6 prefix length of the new IP - * @param ipv4addr The IPv4 address of the new interface - * @param ipv4mask The associated netmask - * @param process_name How the helper should appear in process-listings - * @param restart_task The task called when the helper dies. Will be called with the handle as cls - * @param cb A callback for messages from the helper - * @param cb_cls Closure for the callback - * - * @return A pointer to the new Handle, NULL on error - */ -struct GNUNET_VPN_HELPER_Handle * -start_helper (const char *ifname, const char *ipv6addr, const char *ipv6prefix, - const char *ipv4addr, const char *ipv4mask, - const char *process_name, GNUNET_SCHEDULER_Task restart_task, - GNUNET_SERVER_MessageTokenizerCallback cb, void *cb_cls); - -/** - * @brief Kills the helper, closes the pipe and free()s the handle - */ -void -cleanup_helper (struct GNUNET_VPN_HELPER_Handle *); - -#endif /* end of include guard: GNUNET_HELPER_VPN_API_H */ -- 2.25.1