#include "gnunet_statistics_service.h"
#include "gnunet_constants.h"
#include "gnunet_tun_lib.h"
+#include "gnunet_regex_lib.h"
#include "exit.h"
+/**
+ * Maximum path compression length for mesh regex announcing for IPv4 address
+ * based regex.
+ */
+#define REGEX_MAX_PATH_LEN_IPV4 4
+
+/**
+ * Maximum path compression length for mesh regex announcing for IPv6 address
+ * based regex.
+ */
+#define REGEX_MAX_PATH_LEN_IPV6 8
+
+
/**
* Information about an address.
*/
/**
* Key this state has in the connections_map.
*/
- GNUNET_HashCode state_key;
+ struct GNUNET_HashCode state_key;
/**
* Associated service record, or NULL for no service.
/**
* If there are at least this many connections, old ones will be removed
*/
-static long long unsigned int max_connections;
+static unsigned long long max_connections;
/**
* This hashmaps saves interesting things about the configured UDP services
* @param ri information about the connection
*/
static void
-hash_redirect_info (GNUNET_HashCode *hash,
+hash_redirect_info (struct GNUNET_HashCode *hash,
const struct RedirectInformation *ri)
{
char *off;
- memset (hash, 0, sizeof (GNUNET_HashCode));
+ memset (hash, 0, sizeof (struct GNUNET_HashCode));
/* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash,
so we put the IP address in there (and hope for few collisions) */
off = (char*) hash;
uint16_t destination_port,
const void *local_ip,
uint16_t local_port,
- GNUNET_HashCode *state_key)
+ struct GNUNET_HashCode *state_key)
{
struct RedirectInformation ri;
- GNUNET_HashCode key;
+ struct GNUNET_HashCode key;
struct TunnelState *state;
- if (protocol == IPPROTO_ICMP)
+ if ( ( (af == AF_INET) && (protocol == IPPROTO_ICMP) ) ||
+ ( (af == AF_INET6) && (protocol == IPPROTO_ICMPV6) ) )
{
/* ignore ports */
destination_port = 0;
*/
static struct LocalService *
find_service (struct GNUNET_CONTAINER_MultiHashMap *service_map,
- const GNUNET_HashCode *desc,
+ const struct GNUNET_HashCode *desc,
uint16_t destination_port)
{
- char key[sizeof (GNUNET_HashCode) + sizeof (uint16_t)];
+ char key[sizeof (struct GNUNET_HashCode) + sizeof (uint16_t)];
memcpy (&key[0], &destination_port, sizeof (uint16_t));
- memcpy (&key[sizeof(uint16_t)], desc, sizeof (GNUNET_HashCode));
+ memcpy (&key[sizeof(uint16_t)], desc, sizeof (struct GNUNET_HashCode));
return GNUNET_CONTAINER_multihashmap_get (service_map,
- (GNUNET_HashCode *) key);
+ (struct GNUNET_HashCode *) key);
}
*/
static int
free_service_record (void *cls,
- const GNUNET_HashCode *key,
+ const struct GNUNET_HashCode *key,
void *value)
{
struct LocalService *service = value;
uint16_t destination_port,
struct LocalService *service)
{
- char key[sizeof (GNUNET_HashCode) + sizeof (uint16_t)];
- GNUNET_HashCode desc;
+ char key[sizeof (struct GNUNET_HashCode) + sizeof (uint16_t)];
+ struct GNUNET_HashCode desc;
GNUNET_CRYPTO_hash (name, strlen (name) + 1, &desc);
service->name = GNUNET_strdup (name);
memcpy (&key[0], &destination_port, sizeof (uint16_t));
- memcpy (&key[sizeof(uint16_t)], &desc, sizeof (GNUNET_HashCode));
+ memcpy (&key[sizeof(uint16_t)], &desc, sizeof (struct GNUNET_HashCode));
if (GNUNET_OK !=
GNUNET_CONTAINER_multihashmap_put (service_map,
- (GNUNET_HashCode *) key,
+ (struct GNUNET_HashCode *) key,
service,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
{
- free_service_record (NULL, (GNUNET_HashCode *) key, service);
+ free_service_record (NULL, (struct GNUNET_HashCode *) key, service);
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
_("Got duplicate service records for `%s:%u'\n"),
name,
{
s->th = GNUNET_MESH_notify_transmit_ready (tunnel,
GNUNET_NO /* corking */,
- 0 /* priority */,
GNUNET_TIME_UNIT_FOREVER_REL,
NULL,
tnq->len,
if (NULL != (tnq = s->head))
s->th = GNUNET_MESH_notify_transmit_ready (tunnel,
GNUNET_NO /* corking */,
- 0 /* priority */,
GNUNET_TIME_UNIT_FOREVER_REL,
NULL,
tnq->len,
GNUNET_assert (NULL != s);
GNUNET_CONTAINER_DLL_insert_tail (s->head, s->tail, tnq);
if (NULL == s->th)
- s->th = GNUNET_MESH_notify_transmit_ready (mesh_tunnel, GNUNET_NO /* cork */, 0 /* priority */,
+ s->th = GNUNET_MESH_notify_transmit_ready (mesh_tunnel,
+ GNUNET_NO /* cork */,
GNUNET_TIME_UNIT_FOREVER_REL,
NULL, tnq->len,
&send_to_peer_notify_callback,
existing session from the IP data in the ICMP payload */
source_port = 0;
destination_port = 0;
- protocol = IPPROTO_ICMP;
switch (af)
{
case AF_INET:
+ protocol = IPPROTO_ICMP;
switch (icmp->type)
{
case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
/* could be TCP or UDP, but both have the ports in the right
place, so that doesn't matter here */
udp = (const struct GNUNET_TUN_UdpHeader *) &ipv4[1];
- source_port = ntohs (udp->source_port);
- destination_port = ntohs (udp->destination_port);
+ /* swap ports, as they are from the original message */
+ destination_port = ntohs (udp->source_port);
+ source_port = ntohs (udp->destination_port);
/* throw away ICMP payload, won't be useful for the other side anyway */
pktlen = sizeof (struct GNUNET_TUN_IcmpHeader);
break;
}
break;
case AF_INET6:
+ protocol = IPPROTO_ICMPV6;
switch (icmp->type)
{
case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
/* could be TCP or UDP, but both have the ports in the right
place, so that doesn't matter here */
udp = (const struct GNUNET_TUN_UdpHeader *) &ipv6[1];
- source_port = ntohs (udp->source_port);
- destination_port = ntohs (udp->destination_port);
+ /* swap ports, as they are from the original message */
+ destination_port = ntohs (udp->source_port);
+ source_port = ntohs (udp->destination_port);
/* throw away ICMP payload, won't be useful for the other side anyway */
pktlen = sizeof (struct GNUNET_TUN_IcmpHeader);
break;
destination_ip, 0,
NULL);
break;
+ case IPPROTO_ICMPV6:
+ state = get_redirect_state (af, IPPROTO_ICMPV6,
+ source_ip, 0,
+ destination_ip, 0,
+ NULL);
+ break;
case IPPROTO_UDP:
state = get_redirect_state (af, IPPROTO_UDP,
source_ip,
const void *source_ip)
{
struct TunnelState *state;
- char buf[pktlen];
+ char buf[pktlen] GNUNET_ALIGN;
struct GNUNET_TUN_TcpHeader *mtcp;
struct GNUNET_EXIT_TcpDataMessage *tdm;
struct TunnelMessageQueue *tnq;
* @param client unsued
* @param message message received from helper
*/
-static void
+static int
message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED,
const struct GNUNET_MessageHeader *message)
{
if (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER)
{
GNUNET_break (0);
- return;
+ return GNUNET_OK;
}
size = ntohs (message->size);
if (size < sizeof (struct GNUNET_TUN_Layer2PacketHeader) + sizeof (struct GNUNET_MessageHeader))
{
GNUNET_break (0);
- return;
+ return GNUNET_OK;
}
GNUNET_STATISTICS_update (stats,
gettext_noop ("# Bytes received from TUN"),
{
/* Kernel to blame? */
GNUNET_break (0);
- return;
+ return GNUNET_OK;
}
pkt4 = (const struct GNUNET_TUN_IPv4Header *) &pkt_tun[1];
if (size != ntohs (pkt4->total_length))
{
/* Kernel to blame? */
GNUNET_break (0);
- return;
+ return GNUNET_OK;
}
if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
_("IPv4 packet options received. Ignored.\n"));
- return;
+ return GNUNET_OK;
}
size -= sizeof (struct GNUNET_TUN_IPv4Header);
break;
default:
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("IPv4 packet with unsupported next header received. Ignored.\n"));
- return;
+ _("IPv4 packet with unsupported next header %u received. Ignored.\n"),
+ (int) pkt4->protocol);
+ return GNUNET_OK;
}
}
break;
{
/* Kernel to blame? */
GNUNET_break (0);
- return;
+ return GNUNET_OK;
}
pkt6 = (struct GNUNET_TUN_IPv6Header *) &pkt_tun[1];
if (size != ntohs (pkt6->payload_length) + sizeof (struct GNUNET_TUN_IPv6Header))
{
/* Kernel to blame? */
GNUNET_break (0);
- return;
+ return GNUNET_OK;
}
size -= sizeof (struct GNUNET_TUN_IPv6Header);
switch (pkt6->next_header)
&pkt6->destination_address,
&pkt6->source_address);
break;
- case IPPROTO_ICMP:
+ case IPPROTO_ICMPV6:
icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt6[1], size,
AF_INET6,
&pkt6->destination_address,
break;
default:
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("IPv6 packet with unsupported next header received. Ignored.\n"));
- return;
+ _("IPv6 packet with unsupported next header %d received. Ignored.\n"),
+ pkt6->next_header);
+ return GNUNET_OK;
}
}
break;
ntohs (pkt_tun->proto));
break;
}
+ return GNUNET_OK;
}
local_address->proto = (uint8_t) proto;
/* default "local" port range is often 32768--61000,
so we pick a random value in that range */
- if (proto == IPPROTO_ICMP)
+ if ( ( (af == AF_INET) && (proto == IPPROTO_ICMP) ) ||
+ ( (af == AF_INET6) && (proto == IPPROTO_ICMPV6) ) )
local_address->port = 0;
else
local_address->port
static void
setup_state_record (struct TunnelState *state)
{
- GNUNET_HashCode key;
+ struct GNUNET_HashCode key;
struct TunnelState *s;
/* generate fresh, unique address */
* @param tcp_header skeleton of the TCP header, NULL for UDP
* @param src_address source address to use (IP and port)
* @param dst_address destination address to use (IP and port)
- * @param pkt6 where to write the assembled packet; must
+ * @param pkt4 where to write the assembled packet; must
* contain enough space for the IP header, UDP/TCP header
* AND the payload
*/
* TCP header, depending on protocol)
* @param payload_length number of bytes in 'payload'
* @param protocol IPPROTO_UDP or IPPROTO_TCP
+ * @param tcp_header skeleton TCP header data to send, NULL for UDP
* @param src_address source address to use (IP and port)
* @param dst_address destination address to use (IP and port)
* @param pkt6 where to write the assembled packet; must
return;
}
{
- char buf[len];
+ char buf[len] GNUNET_ALIGN;
struct GNUNET_MessageHeader *hdr;
struct GNUNET_TUN_Layer2PacketHeader *tun;
return;
}
{
- char buf[len];
+ char buf[len] GNUNET_ALIGN;
struct GNUNET_MessageHeader *hdr;
struct GNUNET_TUN_Layer2PacketHeader *tun;
tun->proto = htons (ETH_P_IPV6);
GNUNET_TUN_initialize_ipv6_header (ipv6,
- IPPROTO_ICMP,
+ IPPROTO_ICMPV6,
sizeof (struct GNUNET_TUN_IcmpHeader) + payload_length,
&source_address->address.ipv6,
&destination_address->address.ipv6);
const struct in_addr *v4;
const struct in6_addr *v6;
const void *payload;
- char buf[sizeof (struct GNUNET_TUN_IPv6Header) + 8];
+ char buf[sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
int af;
GNUNET_STATISTICS_update (stats,
if (NULL == state->heap_node)
{
state->ri.remote_address.af = af;
- state->ri.remote_address.proto = IPPROTO_ICMP;
+ state->ri.remote_address.proto = IPPROTO_ICMPV6;
setup_state_record (state);
}
/* check that ICMP type is something we want to support
const struct GNUNET_EXIT_IcmpServiceMessage *msg;
uint16_t pkt_len = ntohs (message->size);
struct GNUNET_TUN_IcmpHeader icmp;
- char buf[sizeof (struct GNUNET_TUN_IPv6Header) + 8];
+ char buf[sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
const void *payload;
GNUNET_STATISTICS_update (stats,
return;
}
{
- char buf[len];
+ char buf[len] GNUNET_ALIGN;
struct GNUNET_MessageHeader *hdr;
struct GNUNET_TUN_Layer2PacketHeader *tun;
static void *
new_tunnel (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
const struct GNUNET_PeerIdentity *initiator GNUNET_UNUSED,
- const struct GNUNET_ATS_Information *ats GNUNET_UNUSED)
+ const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
{
struct TunnelState *s = GNUNET_malloc (sizeof (struct TunnelState));
*/
static int
free_iterate (void *cls GNUNET_UNUSED,
- const GNUNET_HashCode * hash GNUNET_UNUSED, void *value)
+ const struct GNUNET_HashCode * hash GNUNET_UNUSED, void *value)
{
GNUNET_free (value);
return GNUNET_YES;
}
serv = GNUNET_malloc (sizeof (struct LocalService));
+ serv->address.proto = proto;
serv->my_port = (uint16_t) local_port;
serv->address.port = remote_port;
if (0 == strcmp ("localhost4", hostname))
{
- const char *ip4addr = exit_argv[4];
+ const char *ip4addr = exit_argv[5];
serv->address.af = AF_INET;
- GNUNET_assert (1 != inet_pton (AF_INET, ip4addr, &serv->address.address.ipv4));
+ GNUNET_assert (1 == inet_pton (AF_INET, ip4addr, &serv->address.address.ipv4));
}
else if (0 == strcmp ("localhost6", hostname))
{
- const char *ip6addr = exit_argv[2];
+ const char *ip6addr = exit_argv[3];
serv->address.af = AF_INET6;
GNUNET_assert (1 == inet_pton (AF_INET6, ip6addr, &serv->address.address.ipv6));
}
-/**
- * Test if the given AF is supported by this system.
- *
- * @param af to test
- * @return GNUNET_OK if the AF is supported
- */
-static int
-test_af (int af)
-{
- int s;
-
- s = socket (af, SOCK_STREAM, 0);
- if (-1 == s)
- {
- if (EAFNOSUPPORT == errno)
- return GNUNET_NO;
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
- "socket");
- return GNUNET_SYSERR;
- }
- close (s);
- return GNUNET_OK;
-}
-
-
/**
* @brief Main function that will be run by the scheduler.
*
char *ipv6prefix_s;
char *ipv4addr;
char *ipv4mask;
+ char *binary;
+ char *regex;
+ binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-exit");
if (GNUNET_YES !=
- GNUNET_OS_check_helper_binary ("gnunet-helper-exit"))
+ GNUNET_OS_check_helper_binary (binary))
{
- fprintf (stderr,
- "`%s' is not SUID, refusing to run.\n",
- "gnunet-helper-exit");
+ GNUNET_free (binary);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("`%s' must be installed SUID, refusing to run\n"),
+ "gnunet-helper-exit");
global_ret = 1;
return;
}
+ GNUNET_free (binary);
cfg = cfg_;
stats = GNUNET_STATISTICS_create ("exit", cfg);
ipv4_exit = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "EXIT_IPV4");
ipv6_enabled = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "ENABLE_IPV6");
if ( (ipv4_exit || ipv4_enabled) &&
- GNUNET_OK != test_af (AF_INET))
+ GNUNET_OK != GNUNET_NETWORK_test_pf (PF_INET))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
_("This system does not support IPv4, will disable IPv4 functions despite them being enabled in the configuration\n"));
ipv4_enabled = GNUNET_NO;
}
if ( (ipv6_exit || ipv6_enabled) &&
- GNUNET_OK != test_af (AF_INET6))
+ GNUNET_OK != GNUNET_NETWORK_test_pf (PF_INET6))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
_("This system does not support IPv6, will disable IPv6 functions despite them being enabled in the configuration\n"));
}
exit_argv[7] = NULL;
- udp_services = GNUNET_CONTAINER_multihashmap_create (65536);
- tcp_services = GNUNET_CONTAINER_multihashmap_create (65536);
+ udp_services = GNUNET_CONTAINER_multihashmap_create (65536, GNUNET_NO);
+ tcp_services = GNUNET_CONTAINER_multihashmap_create (65536, GNUNET_NO);
GNUNET_CONFIGURATION_iterate_sections (cfg, &read_service_conf, NULL);
- connections_map = GNUNET_CONTAINER_multihashmap_create (65536);
+ connections_map = GNUNET_CONTAINER_multihashmap_create (65536, GNUNET_NO);
connections_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
mesh_handle
- = GNUNET_MESH_connect (cfg, 42 /* queue size */, NULL,
+ = GNUNET_MESH_connect (cfg, NULL,
&new_tunnel,
&clean_tunnel, handlers,
apptypes);
GNUNET_SCHEDULER_shutdown ();
return;
}
- helper_handle = GNUNET_HELPER_start ("gnunet-helper-exit",
+
+ /* Mesh handle acquired, now announce regular expressions matching our exit */
+ if ( (GNUNET_YES == ipv4_enabled) && (GNUNET_YES == ipv4_exit) )
+ {
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "EXIT_RANGE_IPV4_REGEX", ®ex))
+ regex = GNUNET_strdup ("(0|1)*");
+ GNUNET_MESH_announce_regex (mesh_handle, regex, REGEX_MAX_PATH_LEN_IPV4);
+ GNUNET_free (regex);
+ }
+
+ if (GNUNET_YES == ipv6_enabled && GNUNET_YES == ipv6_exit)
+ {
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "EXIT_RANGE_IPV6_REGEX", ®ex))
+ regex = GNUNET_strdup ("(0|1)*");
+ GNUNET_MESH_announce_regex (mesh_handle, regex, REGEX_MAX_PATH_LEN_IPV6);
+ GNUNET_free (regex);
+ }
+
+ helper_handle = GNUNET_HELPER_start (GNUNET_NO,
+ "gnunet-helper-exit",
exit_argv,
- &message_token, NULL);
+ &message_token,
+ NULL, NULL);
}
GNUNET_GETOPT_OPTION_END
};
+ if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
+ return 2;
+
return (GNUNET_OK ==
GNUNET_PROGRAM_run (argc, argv, "gnunet-daemon-exit",
gettext_noop