gnunet-svn
[Top][All Lists]
Advanced

[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:




reply via email to

[Prev in Thread] Current Thread [Next in Thread]