[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r30418 - in gnunet/src: include tun util vpn
From: |
gnunet |
Subject: |
[GNUnet-SVN] r30418 - in gnunet/src: include tun util vpn |
Date: |
Sat, 26 Oct 2013 16:34:39 +0200 |
Author: grothoff
Date: 2013-10-26 16:34:39 +0200 (Sat, 26 Oct 2013)
New Revision: 30418
Modified:
gnunet/src/include/gnunet_strings_lib.h
gnunet/src/include/gnunet_tun_lib.h
gnunet/src/tun/regex.c
gnunet/src/tun/test_regex.c
gnunet/src/util/service.c
gnunet/src/util/strings.c
gnunet/src/vpn/gnunet-service-vpn.c
Log:
-converting regular expressions of vpn/pt to non-binary format and adding
proper policy parsing
Modified: gnunet/src/include/gnunet_strings_lib.h
===================================================================
--- gnunet/src/include/gnunet_strings_lib.h 2013-10-26 12:36:51 UTC (rev
30417)
+++ gnunet/src/include/gnunet_strings_lib.h 2013-10-26 14:34:39 UTC (rev
30418)
@@ -471,6 +471,28 @@
/* ***************** IPv4/IPv6 parsing ****************** */
+struct GNUNET_STRINGS_PortPolicy
+{
+
+ /**
+ * Starting port range (0 if none given).
+ */
+ uint16_t start_port;
+
+ /**
+ * End of port range (0 if none given).
+ */
+ uint16_t end_port;
+
+ /**
+ * #GNUNET_YES if the port range should be negated
+ * ("!" in policy).
+ */
+ int negate_portrange;
+
+};
+
+
/**
* @brief IPV4 network in CIDR notation.
*/
@@ -485,10 +507,16 @@
* IPv4 netmask.
*/
struct in_addr netmask;
+
+ /**
+ * Policy for port access.
+ */
+ struct GNUNET_STRINGS_PortPolicy pp;
+
};
+
/**
-
* @brief network in CIDR notation for IPV6.
*/
struct GNUNET_STRINGS_IPv6NetworkPolicy
@@ -502,30 +530,37 @@
* IPv6 netmask.
*/
struct in6_addr netmask;
+
+ /**
+ * Policy for port access.
+ */
+ struct GNUNET_STRINGS_PortPolicy pp;
+
};
/**
* Parse an IPv4 network policy. The argument specifies a list of
- * subnets. The format is <tt>[network/netmask;]*</tt> (no whitespace,
- * must be terminated with a semicolon). The network must be given in
- * dotted-decimal notation. The netmask can be given in CIDR notation
- * (/16) or in dotted-decimal (/255.255.0.0).
+ * subnets. The format is <tt>(network[/netmask][:[!]SPORT-DPORT];)*</tt>
+ * (no whitespace, must be terminated with a semicolon). The network
+ * must be given in dotted-decimal notation. The netmask can be given
+ * in CIDR notation (/16) or in dotted-decimal (/255.255.0.0).
*
- * @param routeList a string specifying the IPv4 subnets
+ * @param routeListX a string specifying the IPv4 subnets
* @return the converted list, terminated with all zeros;
* NULL if the synatx is flawed
*/
struct GNUNET_STRINGS_IPv4NetworkPolicy *
-GNUNET_STRINGS_parse_ipv4_policy (const char *routeList);
+GNUNET_STRINGS_parse_ipv4_policy (const char *routeListX);
/**
* Parse an IPv6 network policy. The argument specifies a list of
- * subnets. The format is <tt>[network/netmask;]*</tt> (no whitespace,
- * must be terminated with a semicolon). The network must be given in
- * colon-hex notation. The netmask must be given in CIDR notation
- * (/16) or can be omitted to specify a single host.
+ * subnets. The format is <tt>(network[/netmask[:[!]SPORT[-DPORT]]];)*</tt>
+ * (no whitespace, must be terminated with a semicolon). The network
+ * must be given in colon-hex notation. The netmask must be given in
+ * CIDR notation (/16) or can be omitted to specify a single host.
+ * Note that the netmask is mandatory if ports are specified.
*
* @param routeListX a string specifying the policy
* @return the converted list, 0-terminated, NULL if the synatx is flawed
Modified: gnunet/src/include/gnunet_tun_lib.h
===================================================================
--- gnunet/src/include/gnunet_tun_lib.h 2013-10-26 12:36:51 UTC (rev 30417)
+++ gnunet/src/include/gnunet_tun_lib.h 2013-10-26 14:34:39 UTC (rev 30418)
@@ -47,15 +47,21 @@
/**
- * Maximum regex string length for use with GNUNET_TUN_ipv4toregexsearch
+ * Maximum regex string length for use with #GNUNET_TUN_ipv4toregexsearch.
+ *
+ * 8 bytes for IPv4, 4 bytes for port, 1 byte for "4", 2 bytes for "-",
+ * one byte for 0-termination.
*/
-#define GNUNET_TUN_IPV4_REGEXLEN 32 + 6
+#define GNUNET_TUN_IPV4_REGEXLEN 16
/**
- * Maximum regex string length for use with GNUNET_TUN_ipv6toregexsearch
+ * Maximum regex string length for use with #GNUNET_TUN_ipv6toregexsearch
+ *
+ * 32 bytes for IPv4, 4 bytes for port, 1 byte for "4", 2 bytes for "-",
+ * one byte for 0-termination.
*/
-#define GNUNET_TUN_IPV6_REGEXLEN 128 + 6
+#define GNUNET_TUN_IPV6_REGEXLEN 40
GNUNET_NETWORK_STRUCT_BEGIN
@@ -653,8 +659,8 @@
* ICMP header.
*/
struct GNUNET_TUN_IcmpHeader {
- uint8_t type;
- uint8_t code;
+ uint8_t type;
+ uint8_t code;
uint16_t crc GNUNET_PACKED;
union {
@@ -677,8 +683,8 @@
/**
* ICMP Redirect
- */
- struct in_addr redirect_gateway_address GNUNET_PACKED;
+ */
+ struct in_addr redirect_gateway_address GNUNET_PACKED;
/**
* MTU for packets that are too big (IPv6).
@@ -775,7 +781,7 @@
* @param ip ipv6 header fully initialized
* @param udp UDP header (initialized except for CRC)
* @param payload the UDP payload
- * @param payload_length number of bytes of UDP payload
+ * @param payload_length number of bytes of @a payload
*/
void
GNUNET_TUN_calculate_udp6_checksum (const struct GNUNET_TUN_IPv6Header *ip,
@@ -789,7 +795,7 @@
*
* @param icmp IMCP header (initialized except for CRC)
* @param payload the ICMP payload
- * @param payload_length number of bytes of ICMP payload
+ * @param payload_length number of bytes of @a payload
*/
void
GNUNET_TUN_calculate_icmp_checksum (struct GNUNET_TUN_IcmpHeader *icmp,
@@ -798,29 +804,31 @@
/**
- * Create a regex in @a rxstr from the given @a ip and @a netmask.
+ * Create a regex in @a rxstr from the given @a ip and @a port.
*
* @param ip IPv4 representation.
- * @param netmask netmask for the ip.
+ * @param port destination port
* @param rxstr generated regex, must be at least #GNUNET_TUN_IPV4_REGEXLEN
* bytes long.
*/
void
-GNUNET_TUN_ipv4toregexsearch (const struct in_addr *ip, const char *netmask,
- char *rxstr);
+GNUNET_TUN_ipv4toregexsearch (const struct in_addr *ip,
+ uint16_t port,
+ char *rxstr);
/**
- * Create a regex in @a rxstr from the given @a ipv6 and @a prefixlen.
+ * Create a regex in @a rxstr from the given @a ipv6 and @a port.
*
* @param ipv6 IPv6 representation.
- * @param prefixlen length of the ipv6 prefix.
+ * @param port destination port
* @param rxstr generated regex, must be at least #GNUNET_TUN_IPV6_REGEXLEN
* bytes long.
*/
void
GNUNET_TUN_ipv6toregexsearch (const struct in6_addr *ipv6,
- unsigned int prefixlen, char *rxstr);
+ uint16_t port,
+ char *rxstr);
/**
Modified: gnunet/src/tun/regex.c
===================================================================
--- gnunet/src/tun/regex.c 2013-10-26 12:36:51 UTC (rev 30417)
+++ gnunet/src/tun/regex.c 2013-10-26 14:34:39 UTC (rev 30418)
@@ -21,6 +21,7 @@
* @file src/tun/regex.c
* @brief functions to convert IP networks to regexes
* @author Maximilian Szengel
+ * @author Christian Grothoff
*/
#include "platform.h"
#include "gnunet_util_lib.h"
@@ -28,114 +29,311 @@
/**
- * Create a string with binary IP notation for the given 'addr' in 'str'.
+ * Create a regex in @a rxstr from the given @a ip and @a netmask.
*
- * @param af address family of the given 'addr'.
- * @param addr address that should be converted to a string.
- * struct in_addr * for IPv4 and struct in6_addr * for IPv6.
- * @param str string that will contain binary notation of 'addr'. Expected
- * to be at least 33 bytes long for IPv4 and 129 bytes long for
IPv6.
+ * @param ip IPv4 representation.
+ * @param port destination port
+ * @param rxstr generated regex, must be at least #GNUNET_TUN_IPV4_REGEXLEN
+ * bytes long.
*/
-static void
-iptobinstr (const int af, const void *addr, char *str)
+void
+GNUNET_TUN_ipv4toregexsearch (const struct in_addr *ip,
+ uint16_t port,
+ char *rxstr)
{
- int i;
+ GNUNET_snprintf (rxstr,
+ GNUNET_TUN_IPV4_REGEXLEN,
+ "4-%04X-%08X",
+ (unsigned int) port,
+ ntohl (ip->s_addr));
+}
- switch (af)
+
+/**
+ * Create a regex in @a rxstr from the given @a ipv6 and @a prefixlen.
+ *
+ * @param ipv6 IPv6 representation.
+ * @param port destination port
+ * @param rxstr generated regex, must be at least #GNUNET_TUN_IPV6_REGEXLEN
+ * bytes long.
+ */
+void
+GNUNET_TUN_ipv6toregexsearch (const struct in6_addr *ipv6,
+ uint16_t port,
+ char *rxstr)
+{
+ const uint32_t *addr;
+
+ addr = (const uint32_t *) ipv6;
+ GNUNET_snprintf (rxstr,
+ GNUNET_TUN_IPV6_REGEXLEN,
+ "6-%04X-%08X%08X%08X%08X",
+ (unsigned int) port,
+ ntohl (addr[0]),
+ ntohl (addr[1]),
+ ntohl (addr[2]),
+ ntohl (addr[3]));
+}
+
+
+/**
+ * Convert the given 4-bit (!) number to a regex.
+ *
+ * @param value the value, only the lowest 4 bits will be looked at
+ * @param mask which bits in value are wildcards (any value)?
+ */
+static char *
+nibble_to_regex (uint8_t value,
+ uint8_t mask)
+{
+ char *ret;
+
+ value &= mask;
+ switch (mask)
{
- case AF_INET:
- {
- uint32_t b = htonl (((struct in_addr *) addr)->s_addr);
+ case 0:
+ return GNUNET_strdup ("."); /* wildcard */
+ case 8:
+ GNUNET_asprintf (&ret,
+ "(%X|%X|%X|%X|%X|%X|%X|%X)",
+ value,
+ value + 1,
+ value + 2,
+ value + 3,
+ value + 4,
+ value + 5,
+ value + 6,
+ value + 7);
+ return ret;
+ case 12:
+ GNUNET_asprintf (&ret,
+ "(%X|%X|%X|%X)",
+ value,
+ value + 1,
+ value + 2,
+ value + 3);
+ return ret;
+ case 14:
+ GNUNET_asprintf (&ret,
+ "(%X|%X)",
+ value,
+ value + 1);
+ return ret;
+ case 15:
+ GNUNET_asprintf (&ret,
+ "%X",
+ value);
+ return ret;
+ default:
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Bad mask: %d\n",
+ mask);
+ GNUNET_break (0);
+ return NULL;
+ }
+}
- str[32] = '\0';
- str += 31;
- for (i = 31; i >= 0; i--)
- {
- *str = (b & 1) + '0';
- str--;
- b >>= 1;
- }
- break;
- }
- case AF_INET6:
+
+/**
+ * Convert the given 16-bit number to a regex.
+ *
+ * @param value the value
+ * @param mask which bits in value are wildcards (any value)?
+ */
+static char *
+num_to_regex (uint16_t value,
+ uint16_t mask)
+{
+ const uint8_t *v = (const uint8_t *) &value;
+ const uint8_t *m = (const uint8_t *) &mask;
+ char *a;
+ char *b;
+ char *c;
+ char *d;
+ char *ret;
+
+ a = nibble_to_regex (v[0] >> 4, m[0] >> 4);
+ b = nibble_to_regex (v[0] & 15, m[0] & 15);
+ c = nibble_to_regex (v[1] >> 4, m[1] >> 4);
+ d = nibble_to_regex (v[1] & 15, m[1] & 15);
+ ret = NULL;
+ if ( (NULL != a) &&
+ (NULL != b) &&
+ (NULL != c) &&
+ (NULL != d) )
+ GNUNET_asprintf (&ret,
+ "%s%s%s%s",
+ a, b, c, d);
+ GNUNET_free_non_null (a);
+ GNUNET_free_non_null (b);
+ GNUNET_free_non_null (c);
+ GNUNET_free_non_null (d);
+ return ret;
+}
+
+
+/**
+ * Convert a port policy to a regular expression. Note: this is a
+ * very simplistic implementation, we might want to consider doing
+ * something more sophisiticated (resulting in smaller regular
+ * expressions) at a later time.
+ *
+ * @param pp port policy to convert
+ * @return NULL on error
+ */
+static char *
+port_to_regex (const struct GNUNET_STRINGS_PortPolicy *pp)
+{
+ char *reg;
+ char *ret;
+ char *tmp;
+ unsigned int i;
+
+ if ( (0 == pp->start_port) ||
+ ( (1 == pp->start_port) &&
+ (0xFFFF == pp->end_port) &&
+ (GNUNET_NO == pp->negate_portrange)) )
+ return GNUNET_strdup ("....");
+ if ( (pp->start_port == pp->end_port) &&
+ (GNUNET_NO == pp->negate_portrange))
+ {
+ GNUNET_asprintf (&ret,
+ "%04X",
+ pp->start_port);
+ return ret;
+ }
+ reg = NULL;
+ for (i=1;i<=0xFFFF;i++)
+ {
+ if ( ( (i >= pp->start_port) && (i <= pp->end_port) ) ^
+ (GNUNET_YES == pp->negate_portrange) )
{
- struct in6_addr b = *(const struct in6_addr *) addr;
-
- str[128] = '\0';
- str += 127;
- for (i = 127; i >= 0; i--)
- {
- *str = (b.s6_addr[i / 8] & 1) + '0';
- str--;
- b.s6_addr[i / 8] >>= 1;
- }
- break;
+ if (NULL == reg)
+ {
+ GNUNET_asprintf (&tmp,
+ "%04X",
+ i);
+ }
+ else
+ {
+ GNUNET_asprintf (&tmp,
+ "%s|%04X",
+ reg,
+ i);
+ GNUNET_free (reg);
+ }
+ reg = tmp;
}
}
+ GNUNET_asprintf (&ret,
+ "(%s)",
+ reg);
+ GNUNET_free (reg);
+ return ret;
}
/**
- * Get the ipv4 network prefix from the given 'netmask'.
+ * Convert an address (IPv4 or IPv6) to a regex.
*
- * @param netmask netmask for which to get the prefix len.
- *
- * @return length of ipv4 prefix for 'netmask'.
+ * @param addr address
+ * @param mask network mask
+ * @param len number of bytes in @a addr and @a mask
+ * @return NULL on error, otherwise regex for the address
*/
-static unsigned int
-ipv4netmasktoprefixlen (const char *netmask)
+static char *
+address_to_regex (const void *addr,
+ const void *mask,
+ size_t len)
{
- struct in_addr a;
- unsigned int len;
- uint32_t t;
+ const uint16_t *a = addr;
+ const uint16_t *m = mask;
+ char *ret;
+ char *tmp;
+ char *reg;
+ unsigned int i;
- if (1 != inet_pton (AF_INET, netmask, &a))
- return 0;
- len = 32;
- for (t = htonl (~a.s_addr); 0 != t; t >>= 1)
- len--;
- return len;
+ ret = NULL;
+ GNUNET_assert (1 != (len % 2));
+ for (i=0;i<len / 2;i++)
+ {
+ reg = num_to_regex (a[i], m[i]);
+ if (NULL == reg)
+ {
+ GNUNET_free_non_null (ret);
+ return NULL;
+ }
+ if (NULL == ret)
+ {
+ ret = reg;
+ }
+ else
+ {
+ GNUNET_asprintf (&tmp,
+ "%s%s",
+ ret, reg);
+ GNUNET_free (ret);
+ GNUNET_free (reg);
+ ret = tmp;
+ }
+ }
+ return ret;
}
/**
- * Create a regex in 'rxstr' from the given 'ip' and 'netmask'.
+ * Convert a single line of an IPv4 policy to a regular expression.
*
- * @param ip IPv4 representation.
- * @param netmask netmask for the ip.
- * @param rxstr generated regex, must be at least GNUNET_REGEX_IPV4_REGEXLEN
- * bytes long.
+ * @param v4 line to convert
+ * @return NULL on error
*/
-void
-GNUNET_TUN_ipv4toregexsearch (const struct in_addr *ip, const char *netmask,
- char *rxstr)
+static char *
+ipv4_to_regex (const struct GNUNET_STRINGS_IPv4NetworkPolicy *v4)
{
- unsigned int pfxlen;
+ char *reg;
+ char *pp;
+ char *ret;
- pfxlen = ipv4netmasktoprefixlen (netmask);
- iptobinstr (AF_INET, ip, rxstr);
- rxstr[pfxlen] = '\0';
- if (pfxlen < 32)
- strcat (rxstr, "(0|1)+");
+ reg = address_to_regex (&v4->network,
+ &v4->netmask,
+ sizeof (struct in_addr));
+ if (NULL == reg)
+ return NULL;
+ pp = port_to_regex (&v4->pp);
+ GNUNET_asprintf (&ret,
+ "4-%s-%s",
+ pp, reg);
+ GNUNET_free (pp);
+ GNUNET_free (reg);
+ return ret;
}
/**
- * Create a regex in 'rxstr' from the given 'ipv6' and 'prefixlen'.
+ * Convert a single line of an IPv4 policy to a regular expression.
*
- * @param ipv6 IPv6 representation.
- * @param prefixlen length of the ipv6 prefix.
- * @param rxstr generated regex, must be at least GNUNET_REGEX_IPV6_REGEXLEN
- * bytes long.
+ * @param v6 line to convert
+ * @return NULL on error
*/
-void
-GNUNET_TUN_ipv6toregexsearch (const struct in6_addr *ipv6, unsigned int
prefixlen,
- char *rxstr)
+static char *
+ipv6_to_regex (const struct GNUNET_STRINGS_IPv6NetworkPolicy *v6)
{
- iptobinstr (AF_INET6, ipv6, rxstr);
- rxstr[prefixlen] = '\0';
- if (prefixlen < 128)
- strcat (rxstr, "(0|1)+");
+ char *reg;
+ char *pp;
+ char *ret;
+
+ reg = address_to_regex (&v6->network,
+ &v6->netmask,
+ sizeof (struct in6_addr));
+ if (NULL == reg)
+ return NULL;
+ pp = port_to_regex (&v6->pp);
+ GNUNET_asprintf (&ret,
+ "6-%s-%s",
+ pp, reg);
+ GNUNET_free (pp);
+ GNUNET_free (reg);
+ return ret;
}
@@ -151,8 +349,39 @@
char *
GNUNET_TUN_ipv4policy2regex (const char *policy)
{
- // FIXME: do actual policy parsing here, see #2919
- return GNUNET_strdup (policy);
+ struct GNUNET_STRINGS_IPv4NetworkPolicy *np;
+ char *reg;
+ char *tmp;
+ char *line;
+ unsigned int i;
+
+ np = GNUNET_STRINGS_parse_ipv4_policy (policy);
+ if (NULL == np)
+ return NULL;
+ reg = NULL;
+ for (i=0; 0 != np[i].network.s_addr; i++)
+ {
+ line = ipv4_to_regex (&np[i]);
+ if (NULL == line)
+ {
+ GNUNET_free_non_null (reg);
+ return NULL;
+ }
+ if (NULL == reg)
+ {
+ reg = line;
+ }
+ else
+ {
+ GNUNET_asprintf (&tmp,
+ "%s|(%s)",
+ reg, line);
+ GNUNET_free (reg);
+ GNUNET_free (line);
+ reg = tmp;
+ }
+ }
+ return reg;
}
@@ -160,7 +389,7 @@
* Convert an exit policy to a regular expression. The exit policy
* specifies a set of subnets this peer is willing to serve as an
* exit for; the resulting regular expression will match the
- * IPv4 address strings as returned by 'GNUNET_TUN_ipv4toregexsearch'.
+ * IPv6 address strings as returned by 'GNUNET_TUN_ipv6toregexsearch'.
*
* @param policy exit policy specification
* @return regular expression, NULL on error
@@ -168,8 +397,41 @@
char *
GNUNET_TUN_ipv6policy2regex (const char *policy)
{
- // FIXME: do actual policy parsing here, see #2919
- return GNUNET_strdup (policy);
+ struct in6_addr zero;
+ struct GNUNET_STRINGS_IPv6NetworkPolicy *np;
+ char *reg;
+ char *tmp;
+ char *line;
+ unsigned int i;
+
+ np = GNUNET_STRINGS_parse_ipv6_policy (policy);
+ if (NULL == np)
+ return NULL;
+ reg = NULL;
+ memset (&zero, 0, sizeof (struct in6_addr));
+ for (i=0; 0 != memcmp (&zero, &np[i].network, sizeof (struct in6_addr)); i++)
+ {
+ line = ipv6_to_regex (&np[i]);
+ if (NULL == line)
+ {
+ GNUNET_free_non_null (reg);
+ return NULL;
+ }
+ if (NULL == reg)
+ {
+ reg = line;
+ }
+ else
+ {
+ GNUNET_asprintf (&tmp,
+ "%s|(%s)",
+ reg, line);
+ GNUNET_free (reg);
+ GNUNET_free (line);
+ reg = tmp;
+ }
+ }
+ return reg;
}
Modified: gnunet/src/tun/test_regex.c
===================================================================
--- gnunet/src/tun/test_regex.c 2013-10-26 12:36:51 UTC (rev 30417)
+++ gnunet/src/tun/test_regex.c 2013-10-26 14:34:39 UTC (rev 30418)
@@ -27,8 +27,11 @@
static int
-test_iptoregex (const char *ipv4, const char *netmask, const char *expectedv4,
- const char *ipv6, unsigned int prefixlen,
+test_iptoregex (const char *ipv4,
+ uint16_t port,
+ const char *expectedv4,
+ const char *ipv6,
+ uint16_t port6,
const char *expectedv6)
{
int error = 0;
@@ -39,29 +42,82 @@
char rxv6[GNUNET_TUN_IPV6_REGEXLEN];
GNUNET_assert (1 == inet_pton (AF_INET, ipv4, &a));
- GNUNET_TUN_ipv4toregexsearch (&a, netmask, rxv4);
+ GNUNET_TUN_ipv4toregexsearch (&a, port, rxv4);
-
if (0 != strcmp (rxv4, expectedv4))
{
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected: %s but got: %s\n",
- expectedv4, rxv4);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Expected: %s but got: %s\n",
+ expectedv4,
+ rxv4);
error++;
}
GNUNET_assert (1 == inet_pton (AF_INET6, ipv6, &b));
- GNUNET_TUN_ipv6toregexsearch (&b, prefixlen, rxv6);
-
+ GNUNET_TUN_ipv6toregexsearch (&b, port6, rxv6);
if (0 != strcmp (rxv6, expectedv6))
{
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected: %s but got: %s\n",
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Expected: %s but got: %s\n",
expectedv6, rxv6);
error++;
}
-
return error;
}
+
+static int
+test_policy4toregex (const char *policy,
+ const char *regex)
+{
+ char *r;
+ int ret;
+
+ ret = 0;
+ r = GNUNET_TUN_ipv4policy2regex (policy);
+ if (NULL == r)
+ {
+ GNUNET_break (0);
+ return 1;
+ }
+ if (0 != strcmp (regex, r))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Expected: `%s' but got: `%s'\n",
+ regex, r);
+ ret = 2;
+ }
+ GNUNET_free (r);
+ return ret;
+}
+
+
+static int
+test_policy6toregex (const char *policy,
+ const char *regex)
+{
+ char *r;
+ int ret;
+
+ ret = 0;
+ r = GNUNET_TUN_ipv6policy2regex (policy);
+ if (NULL == r)
+ {
+ GNUNET_break (0);
+ return 1;
+ }
+ if (0 != strcmp (regex, r))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Expected: `%s' but got: `%s'\n",
+ regex, r);
+ ret = 2;
+ }
+ GNUNET_free (r);
+ return ret;
+}
+
+
int
main (int argc, char *argv[])
{
@@ -72,32 +128,41 @@
error = 0;
error +=
- test_iptoregex ("192.0.0.0", "255.255.255.0",
- "110000000000000000000000(0|1)+", "FFFF::0", 16,
- "1111111111111111(0|1)+");
-
+ test_iptoregex ("192.1.2.3", 2086,
+ "4-0826-C0010203",
+ "FFFF::1", 8080,
+ "6-1F90-FFFF0000000000000000000000000001");
error +=
- test_iptoregex ("187.238.225.0", "255.255.255.128",
- "1011101111101110111000010(0|1)+", "E1E1:73F9:51BE::0",
- 49,
-
"1110000111100001011100111111100101010001101111100(0|1)+");
-
+ test_iptoregex ("187.238.255.0", 80,
+ "4-0050-BBEEFF00",
+ "E1E1:73F9:51BE::0", 49,
+ "6-0031-E1E173F951BE00000000000000000000");
error +=
- test_iptoregex ("255.255.255.255", "255.255.255.255",
- "11111111111111111111111111111111",
- "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF", 128,
- "11111111111111111111111111111111"
- "11111111111111111111111111111111"
- "11111111111111111111111111111111"
- "11111111111111111111111111111111");
-
+ test_policy4toregex ("192.1.2.0/24:80;",
+ "4-0050-C00102..");
error +=
- test_iptoregex ("0.0.0.0", "255.255.255.255",
- "00000000000000000000000000000000", "0::0", 128,
- "00000000000000000000000000000000"
- "00000000000000000000000000000000"
- "00000000000000000000000000000000"
- "00000000000000000000000000000000");
-
+ test_policy4toregex ("192.1.0.0/16;",
+ "4-....-C001....");
+ error +=
+ test_policy4toregex ("192.1.0.0/16:80-81;",
+ "4-(0050|0051)-C001....");
+ error +=
+ test_policy4toregex ("192.1.0.0/8:!3-65535;",
+ "4-(0001|0002)-C0......");
+ error +=
+ test_policy6toregex ("E1E1::1;",
+ "6-....-E1E10000000000000000000000000001");
+ error +=
+ test_policy6toregex ("E1E1:ABCD::1/120;",
+ "6-....-E1E1ABCD0000000000000000000000..");
+ error +=
+ test_policy6toregex ("E1E1:ABCD::ABCD/126;",
+ "6-....-E1E1ABCD00000000000000000000ABC(C|D|E|F)");
+ error +=
+ test_policy6toregex ("E1E1:ABCD::ABCD/127;",
+ "6-....-E1E1ABCD00000000000000000000ABC(C|D)");
+ error +=
+ test_policy6toregex ("E1E1:ABCD::ABCD/128:80;",
+ "6-0050-E1E1ABCD00000000000000000000ABCD");
return error;
}
Modified: gnunet/src/util/service.c
===================================================================
--- gnunet/src/util/service.c 2013-10-26 12:36:51 UTC (rev 30417)
+++ gnunet/src/util/service.c 2013-10-26 14:34:39 UTC (rev 30418)
@@ -65,10 +65,11 @@
*
* @param list a list of networks
* @param add the IP to check (in network byte order)
- * @return GNUNET_NO if the IP is not in the list, GNUNET_YES if it it is
+ * @return #GNUNET_NO if the IP is not in the list, #GNUNET_YES if it it is
*/
static int
-check_ipv4_listed (const struct GNUNET_STRINGS_IPv4NetworkPolicy *list, const
struct in_addr *add)
+check_ipv4_listed (const struct GNUNET_STRINGS_IPv4NetworkPolicy *list,
+ const struct in_addr *add)
{
unsigned int i;
@@ -91,10 +92,11 @@
*
* @param list a list of networks
* @param ip the IP to check (in network byte order)
- * @return GNUNET_NO if the IP is not in the list, GNUNET_YES if it it is
+ * @return #GNUNET_NO if the IP is not in the list, #GNUNET_YES if it it is
*/
static int
-check_ipv6_listed (const struct GNUNET_STRINGS_IPv6NetworkPolicy *list, const
struct in6_addr *ip)
+check_ipv6_listed (const struct GNUNET_STRINGS_IPv6NetworkPolicy *list,
+ const struct in6_addr *ip)
{
unsigned int i;
unsigned int j;
Modified: gnunet/src/util/strings.c
===================================================================
--- gnunet/src/util/strings.c 2013-10-26 12:36:51 UTC (rev 30417)
+++ gnunet/src/util/strings.c 2013-10-26 14:34:39 UTC (rev 30418)
@@ -993,22 +993,24 @@
/**
- * Check whether 'filename' is absolute or not, and if it's an URI
+ * Check whether @a filename is absolute or not, and if it's an URI
*
* @param filename filename to check
- * @param can_be_uri GNUNET_YES to check for being URI, GNUNET_NO - to
+ * @param can_be_uri #GNUNET_YES to check for being URI, #GNUNET_NO - to
* assume it's not URI
- * @param r_is_uri a pointer to an int that is set to GNUNET_YES if 'filename'
- * is URI and to GNUNET_NO otherwise. Can be NULL. If 'can_be_uri' is
- * not GNUNET_YES, *r_is_uri is set to GNUNET_NO.
+ * @param r_is_uri a pointer to an int that is set to #GNUNET_YES if @a
filename
+ * is URI and to #GNUNET_NO otherwise. Can be NULL. If @a can_be_uri is
+ * not #GNUNET_YES, `* r_is_uri` is set to #GNUNET_NO.
* @param r_uri_scheme a pointer to a char * that is set to a pointer to URI
scheme.
* The string is allocated by the function, and should be freed with
- * GNUNET_free (). Can be NULL.
- * @return GNUNET_YES if 'filename' is absolute, GNUNET_NO otherwise.
+ * GNUNET_free(). Can be NULL.
+ * @return #GNUNET_YES if @a filename is absolute, #GNUNET_NO otherwise.
*/
int
-GNUNET_STRINGS_path_is_absolute (const char *filename, int can_be_uri,
- int *r_is_uri, char **r_uri_scheme)
+GNUNET_STRINGS_path_is_absolute (const char *filename,
+ int can_be_uri,
+ int *r_is_uri,
+ char **r_uri_scheme)
{
#if WINDOWS
size_t len;
@@ -1067,12 +1069,12 @@
/**
- * Perform 'checks' on 'filename'
+ * Perform @a checks on @a filename.
*
* @param filename file to check
* @param checks checks to perform
- * @return GNUNET_YES if all checks pass, GNUNET_NO if at least one of them
- * fails, GNUNET_SYSERR when a check can't be performed
+ * @return #GNUNET_YES if all checks pass, #GNUNET_NO if at least one of them
+ * fails, #GNUNET_SYSERR when a check can't be performed
*/
int
GNUNET_STRINGS_check_filename (const char *filename,
@@ -1111,11 +1113,12 @@
* The string is expected to have the format "[ABCD::01]:80".
*
* @param zt_addr 0-terminated string. May be mangled by the function.
- * @param addrlen length of zt_addr (not counting 0-terminator).
+ * @param addrlen length of @a zt_addr (not counting 0-terminator).
* @param r_buf a buffer to fill. Initially gets filled with zeroes,
* then its sin6_port, sin6_family and sin6_addr are set appropriately.
- * @return GNUNET_OK if conversion succeded. GNUNET_SYSERR otherwise, in which
- * case the contents of r_buf are undefined.
+ * @return #GNUNET_OK if conversion succeded.
+ * #GNUNET_SYSERR otherwise, in which
+ * case the contents of @a r_buf are undefined.
*/
int
GNUNET_STRINGS_to_address_ipv6 (const char *zt_addr,
@@ -1182,10 +1185,11 @@
* The string is expected to have the format "1.2.3.4:80".
*
* @param zt_addr 0-terminated string. May be mangled by the function.
- * @param addrlen length of zt_addr (not counting 0-terminator).
+ * @param addrlen length of @a zt_addr (not counting 0-terminator).
* @param r_buf a buffer to fill.
- * @return GNUNET_OK if conversion succeded. GNUNET_SYSERR otherwise, in which
case
- * the contents of r_buf are undefined.
+ * @return #GNUNET_OK if conversion succeded.
+ * #GNUNET_SYSERR otherwise, in which case
+ * the contents of @a r_buf are undefined.
*/
int
GNUNET_STRINGS_to_address_ipv4 (const char *zt_addr, uint16_t addrlen,
@@ -1217,14 +1221,14 @@
/**
- * Tries to convert 'addr' string to an IP (v4 or v6) address.
+ * Tries to convert @a addr string to an IP (v4 or v6) address.
* Will automatically decide whether to treat 'addr' as v4 or v6 address.
*
* @param addr a string, may not be 0-terminated.
- * @param addrlen number of bytes in addr (if addr is 0-terminated,
+ * @param addrlen number of bytes in @a addr (if addr is 0-terminated,
* 0-terminator should not be counted towards addrlen).
* @param r_buf a buffer to fill.
- * @return GNUNET_OK if conversion succeded. GNUNET_SYSERR otherwise, in which
+ * @return #GNUNET_OK if conversion succeded. GNUNET_SYSERR otherwise, in which
* case the contents of r_buf are undefined.
*/
int
@@ -1233,8 +1237,12 @@
struct sockaddr_storage *r_buf)
{
if (addr[0] == '[')
- return GNUNET_STRINGS_to_address_ipv6 (addr, addrlen, (struct sockaddr_in6
*) r_buf);
- return GNUNET_STRINGS_to_address_ipv4 (addr, addrlen, (struct sockaddr_in *)
r_buf);
+ return GNUNET_STRINGS_to_address_ipv6 (addr,
+ addrlen,
+ (struct sockaddr_in6 *) r_buf);
+ return GNUNET_STRINGS_to_address_ipv4 (addr,
+ addrlen,
+ (struct sockaddr_in *) r_buf);
}
@@ -1243,7 +1251,8 @@
* freed with a single call to GNUNET_free ();
*/
static char *const *
-_make_continuous_arg_copy (int argc, char *const *argv)
+_make_continuous_arg_copy (int argc,
+ char *const *argv)
{
size_t argvsize = 0;
int i;
@@ -1276,7 +1285,7 @@
* @param argv argv (as given by main())
* @param u8argc a location to store new argc in (though it's th same as argc)
* @param u8argv a location to store new argv in
- * @return GNUNET_OK on success, GNUNET_SYSERR on failure
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
*/
int
GNUNET_STRINGS_get_utf8_args (int argc, char *const *argv, int *u8argc, char
*const **u8argv)
@@ -1330,18 +1339,65 @@
/**
+ * Parse the given port policy. The format is
+ * "[!]SPORT[-DPORT]".
+ *
+ * @param port_policy string to parse
+ * @param pp policy to fill in
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR if the
+ * @a port_policy is malformed
+ */
+static int
+parse_port_policy (const char *port_policy,
+ struct GNUNET_STRINGS_PortPolicy *pp)
+{
+ const char *pos;
+ int s;
+ int e;
+
+ pos = port_policy;
+ if ('!' == *pos)
+ {
+ pp->negate_portrange = GNUNET_YES;
+ pos++;
+ }
+ if (2 == sscanf (pos,
+ "%u-%u",
+ &s, &e))
+ {
+ pp->start_port = (uint16_t) s;
+ pp->end_port = (uint16_t) e;
+ return GNUNET_OK;
+ }
+ if (1 == sscanf (pos,
+ "%u",
+ &s))
+ {
+ pp->start_port = (uint16_t) s;
+ pp->end_port = (uint16_t) s;
+ return GNUNET_OK;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("Malformed port policy `%s'\n"),
+ port_policy);
+ return GNUNET_SYSERR;
+}
+
+
+/**
* Parse an IPv4 network policy. The argument specifies a list of
- * subnets. The format is <tt>[network/netmask;]*</tt> (no whitespace,
- * must be terminated with a semicolon). The network must be given in
+ * subnets. The format is
+ * <tt>(network[/netmask][:SPORT[-DPORT]];)*</tt> (no whitespace, must
+ * be terminated with a semicolon). The network must be given in
* dotted-decimal notation. The netmask can be given in CIDR notation
* (/16) or in dotted-decimal (/255.255.0.0).
*
- * @param routeList a string specifying the IPv4 subnets
+ * @param routeListX a string specifying the IPv4 subnets
* @return the converted list, terminated with all zeros;
* NULL if the synatx is flawed
*/
struct GNUNET_STRINGS_IPv4NetworkPolicy *
-GNUNET_STRINGS_parse_ipv4_policy (const char *routeList)
+GNUNET_STRINGS_parse_ipv4_policy (const char *routeListX)
{
unsigned int count;
unsigned int i;
@@ -1352,12 +1408,16 @@
unsigned int temps[8];
int slash;
struct GNUNET_STRINGS_IPv4NetworkPolicy *result;
+ int colon;
+ int end;
+ char *routeList;
- if (NULL == routeList)
+ if (NULL == routeListX)
return NULL;
- len = strlen (routeList);
+ len = strlen (routeListX);
if (0 == len)
return NULL;
+ routeList = GNUNET_strdup (routeListX);
count = 0;
for (i = 0; i < len; i++)
if (routeList[i] == ';')
@@ -1367,18 +1427,45 @@
pos = 0;
while (i < count)
{
+ for (colon = pos; ':' != routeList[colon]; colon++)
+ if ( (';' == routeList[colon]) ||
+ ('\0' == routeList[colon]) )
+ break;
+ end = colon;
+ for (end = colon; ';' != routeList[end]; end++)
+ if ('\0' == routeList[end])
+ break;
+ if ('\0' == routeList[end])
+ break;
+ routeList[end] = '\0';
+ if (':' == routeList[colon])
+ {
+ routeList[colon] = '\0';
+ if (GNUNET_OK != parse_port_policy (&routeList[colon + 1],
+ &result[i].pp))
+ break;
+ }
cnt =
- SSCANF (&routeList[pos], "%u.%u.%u.%u/%u.%u.%u.%u;", &temps[0],
- &temps[1], &temps[2], &temps[3], &temps[4], &temps[5],
- &temps[6], &temps[7]);
+ SSCANF (&routeList[pos],
+ "%u.%u.%u.%u/%u.%u.%u.%u",
+ &temps[0],
+ &temps[1],
+ &temps[2],
+ &temps[3],
+ &temps[4],
+ &temps[5],
+ &temps[6],
+ &temps[7]);
if (8 == cnt)
{
for (j = 0; j < 8; j++)
if (temps[j] > 0xFF)
{
- LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid format for IP: `%s'\n"),
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ _("Invalid format for IP: `%s'\n"),
&routeList[pos]);
GNUNET_free (result);
+ GNUNET_free (routeList);
return NULL;
}
result[i].network.s_addr =
@@ -1387,24 +1474,29 @@
result[i].netmask.s_addr =
htonl ((temps[4] << 24) + (temps[5] << 16) + (temps[6] << 8) +
temps[7]);
- while (routeList[pos] != ';')
- pos++;
- pos++;
+ pos = end + 1;
i++;
continue;
}
/* try second notation */
cnt =
- SSCANF (&routeList[pos], "%u.%u.%u.%u/%u;", &temps[0], &temps[1],
- &temps[2], &temps[3], &slash);
+ SSCANF (&routeList[pos],
+ "%u.%u.%u.%u/%u",
+ &temps[0],
+ &temps[1],
+ &temps[2],
+ &temps[3],
+ &slash);
if (5 == cnt)
{
for (j = 0; j < 4; j++)
if (temps[j] > 0xFF)
{
- LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid format for IP: `%s'\n"),
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ _("Invalid format for IP: `%s'\n"),
&routeList[pos]);
GNUNET_free (result);
+ GNUNET_free (routeList);
return NULL;
}
result[i].network.s_addr =
@@ -1420,9 +1512,7 @@
slash--;
}
result[i].netmask.s_addr = htonl (result[i].netmask.s_addr);
- while (';' != routeList[pos])
- pos++;
- pos++;
+ pos = end + 1;
i++;
continue;
}
@@ -1432,6 +1522,7 @@
_("Invalid network notation ('/%d' is not legal in IPv4 CIDR)."),
slash);
GNUNET_free (result);
+ GNUNET_free (routeList);
return NULL; /* error */
}
}
@@ -1439,7 +1530,7 @@
slash = 32;
cnt =
SSCANF (&routeList[pos],
- "%u.%u.%u.%u;",
+ "%u.%u.%u.%u",
&temps[0],
&temps[1],
&temps[2],
@@ -1453,6 +1544,7 @@
_("Invalid format for IP: `%s'\n"),
&routeList[pos]);
GNUNET_free (result);
+ GNUNET_free (routeList);
return NULL;
}
result[i].network.s_addr =
@@ -1465,9 +1557,7 @@
slash--;
}
result[i].netmask.s_addr = htonl (result[i].netmask.s_addr);
- while (routeList[pos] != ';')
- pos++;
- pos++;
+ pos = end + 1;
i++;
continue;
}
@@ -1475,6 +1565,7 @@
_("Invalid format for IP: `%s'\n"),
&routeList[pos]);
GNUNET_free (result);
+ GNUNET_free (routeList);
return NULL; /* error */
}
if (pos < strlen (routeList))
@@ -1483,18 +1574,21 @@
_("Invalid format for IP: `%s'\n"),
&routeList[pos]);
GNUNET_free (result);
+ GNUNET_free (routeList);
return NULL; /* oops */
}
+ GNUNET_free (routeList);
return result; /* ok */
}
/**
* Parse an IPv6 network policy. The argument specifies a list of
- * subnets. The format is <tt>[network/netmask;]*</tt> (no whitespace,
- * must be terminated with a semicolon). The network must be given in
- * colon-hex notation. The netmask must be given in CIDR notation
- * (/16) or can be omitted to specify a single host.
+ * subnets. The format is <tt>(network[/netmask[:SPORT[-DPORT]]];)*</tt>
+ * (no whitespace, must be terminated with a semicolon). The network
+ * must be given in colon-hex notation. The netmask must be given in
+ * CIDR notation (/16) or can be omitted to specify a single host.
+ * Note that the netmask is mandatory if ports are specified.
*
* @param routeListX a string specifying the policy
* @return the converted list, 0-terminated, NULL if the synatx is flawed
@@ -1514,6 +1608,7 @@
unsigned int bits;
unsigned int off;
int save;
+ int colon;
if (NULL == routeListX)
return NULL;
@@ -1545,19 +1640,36 @@
slash = pos;
while ((slash >= start) && (routeList[slash] != '/'))
slash--;
+
if (slash < start)
{
- memset (&result[i].netmask, 0xFF, sizeof (struct in6_addr));
+ memset (&result[i].netmask,
+ 0xFF,
+ sizeof (struct in6_addr));
slash = pos;
}
else
{
routeList[pos] = '\0';
+ for (colon = pos; ':' != routeList[colon]; colon--)
+ if ('/' == routeList[colon])
+ break;
+ if (':' == routeList[colon])
+ {
+ routeList[colon] = '\0';
+ if (GNUNET_OK != parse_port_policy (&routeList[colon + 1],
+ &result[i].pp))
+ {
+ GNUNET_free (result);
+ GNUNET_free (routeList);
+ return NULL;
+ }
+ }
ret = inet_pton (AF_INET6, &routeList[slash + 1], &result[i].netmask);
if (ret <= 0)
{
save = errno;
- if ((1 != SSCANF (&routeList[slash + 1], "%u", &bits)) || (bits >=
128))
+ if ((1 != SSCANF (&routeList[slash + 1], "%u", &bits)) || (bits > 128))
{
if (0 == ret)
LOG (GNUNET_ERROR_TYPE_ERROR,
Modified: gnunet/src/vpn/gnunet-service-vpn.c
===================================================================
--- gnunet/src/vpn/gnunet-service-vpn.c 2013-10-26 12:36:51 UTC (rev 30417)
+++ gnunet/src/vpn/gnunet-service-vpn.c 2013-10-26 14:34:39 UTC (rev 30418)
@@ -803,13 +803,11 @@
char address[GNUNET_TUN_IPV4_REGEXLEN];
GNUNET_TUN_ipv4toregexsearch
(&dt->destination->details.exit_destination.ip.v4,
- "255.255.255.255",
+ dt->destination_port,
address);
- GNUNET_asprintf (&policy, "%s%s%s:%u",
+ GNUNET_asprintf (&policy, "%s%s",
GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
- "4",
- address,
- (unsigned int) dt->destination_port);
+ address);
break;
}
case AF_INET6:
@@ -817,12 +815,11 @@
char address[GNUNET_TUN_IPV6_REGEXLEN];
GNUNET_TUN_ipv6toregexsearch
(&dt->destination->details.exit_destination.ip.v6,
- 128, address);
- GNUNET_asprintf (&policy, "%s%s%s:%u",
+ dt->destination_port,
+ address);
+ GNUNET_asprintf (&policy, "%s%s",
GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
- "6",
- address,
- (unsigned int) dt->destination_port);
+ address);
break;
}
default:
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r30418 - in gnunet/src: include tun util vpn,
gnunet <=