aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/include/gnunet_strings_lib.h57
-rw-r--r--src/include/gnunet_tun_lib.h42
-rw-r--r--src/tun/regex.c428
-rw-r--r--src/tun/test_regex.c133
-rw-r--r--src/util/service.c10
-rw-r--r--src/util/strings.c220
-rw-r--r--src/vpn/gnunet-service-vpn.c17
7 files changed, 694 insertions, 213 deletions
diff --git a/src/include/gnunet_strings_lib.h b/src/include/gnunet_strings_lib.h
index e0a299ac3..8bb8cfb06 100644
--- a/src/include/gnunet_strings_lib.h
+++ b/src/include/gnunet_strings_lib.h
@@ -471,6 +471,28 @@ GNUNET_STRINGS_get_utf8_args (int argc,
471 471
472/* ***************** IPv4/IPv6 parsing ****************** */ 472/* ***************** IPv4/IPv6 parsing ****************** */
473 473
474struct GNUNET_STRINGS_PortPolicy
475{
476
477 /**
478 * Starting port range (0 if none given).
479 */
480 uint16_t start_port;
481
482 /**
483 * End of port range (0 if none given).
484 */
485 uint16_t end_port;
486
487 /**
488 * #GNUNET_YES if the port range should be negated
489 * ("!" in policy).
490 */
491 int negate_portrange;
492
493};
494
495
474/** 496/**
475 * @brief IPV4 network in CIDR notation. 497 * @brief IPV4 network in CIDR notation.
476 */ 498 */
@@ -485,10 +507,16 @@ struct GNUNET_STRINGS_IPv4NetworkPolicy
485 * IPv4 netmask. 507 * IPv4 netmask.
486 */ 508 */
487 struct in_addr netmask; 509 struct in_addr netmask;
510
511 /**
512 * Policy for port access.
513 */
514 struct GNUNET_STRINGS_PortPolicy pp;
515
488}; 516};
489 517
490/**
491 518
519/**
492 * @brief network in CIDR notation for IPV6. 520 * @brief network in CIDR notation for IPV6.
493 */ 521 */
494struct GNUNET_STRINGS_IPv6NetworkPolicy 522struct GNUNET_STRINGS_IPv6NetworkPolicy
@@ -502,30 +530,37 @@ struct GNUNET_STRINGS_IPv6NetworkPolicy
502 * IPv6 netmask. 530 * IPv6 netmask.
503 */ 531 */
504 struct in6_addr netmask; 532 struct in6_addr netmask;
533
534 /**
535 * Policy for port access.
536 */
537 struct GNUNET_STRINGS_PortPolicy pp;
538
505}; 539};
506 540
507 541
508/** 542/**
509 * Parse an IPv4 network policy. The argument specifies a list of 543 * Parse an IPv4 network policy. The argument specifies a list of
510 * subnets. The format is <tt>[network/netmask;]*</tt> (no whitespace, 544 * subnets. The format is <tt>(network[/netmask][:[!]SPORT-DPORT];)*</tt>
511 * must be terminated with a semicolon). The network must be given in 545 * (no whitespace, must be terminated with a semicolon). The network
512 * dotted-decimal notation. The netmask can be given in CIDR notation 546 * must be given in dotted-decimal notation. The netmask can be given
513 * (/16) or in dotted-decimal (/255.255.0.0). 547 * in CIDR notation (/16) or in dotted-decimal (/255.255.0.0).
514 * 548 *
515 * @param routeList a string specifying the IPv4 subnets 549 * @param routeListX a string specifying the IPv4 subnets
516 * @return the converted list, terminated with all zeros; 550 * @return the converted list, terminated with all zeros;
517 * NULL if the synatx is flawed 551 * NULL if the synatx is flawed
518 */ 552 */
519struct GNUNET_STRINGS_IPv4NetworkPolicy * 553struct GNUNET_STRINGS_IPv4NetworkPolicy *
520GNUNET_STRINGS_parse_ipv4_policy (const char *routeList); 554GNUNET_STRINGS_parse_ipv4_policy (const char *routeListX);
521 555
522 556
523/** 557/**
524 * Parse an IPv6 network policy. The argument specifies a list of 558 * Parse an IPv6 network policy. The argument specifies a list of
525 * subnets. The format is <tt>[network/netmask;]*</tt> (no whitespace, 559 * subnets. The format is <tt>(network[/netmask[:[!]SPORT[-DPORT]]];)*</tt>
526 * must be terminated with a semicolon). The network must be given in 560 * (no whitespace, must be terminated with a semicolon). The network
527 * colon-hex notation. The netmask must be given in CIDR notation 561 * must be given in colon-hex notation. The netmask must be given in
528 * (/16) or can be omitted to specify a single host. 562 * CIDR notation (/16) or can be omitted to specify a single host.
563 * Note that the netmask is mandatory if ports are specified.
529 * 564 *
530 * @param routeListX a string specifying the policy 565 * @param routeListX a string specifying the policy
531 * @return the converted list, 0-terminated, NULL if the synatx is flawed 566 * @return the converted list, 0-terminated, NULL if the synatx is flawed
diff --git a/src/include/gnunet_tun_lib.h b/src/include/gnunet_tun_lib.h
index 17cec8d12..efadc4d14 100644
--- a/src/include/gnunet_tun_lib.h
+++ b/src/include/gnunet_tun_lib.h
@@ -47,15 +47,21 @@
47 47
48 48
49/** 49/**
50 * Maximum regex string length for use with GNUNET_TUN_ipv4toregexsearch 50 * Maximum regex string length for use with #GNUNET_TUN_ipv4toregexsearch.
51 *
52 * 8 bytes for IPv4, 4 bytes for port, 1 byte for "4", 2 bytes for "-",
53 * one byte for 0-termination.
51 */ 54 */
52#define GNUNET_TUN_IPV4_REGEXLEN 32 + 6 55#define GNUNET_TUN_IPV4_REGEXLEN 16
53 56
54 57
55/** 58/**
56 * Maximum regex string length for use with GNUNET_TUN_ipv6toregexsearch 59 * Maximum regex string length for use with #GNUNET_TUN_ipv6toregexsearch
60 *
61 * 32 bytes for IPv4, 4 bytes for port, 1 byte for "4", 2 bytes for "-",
62 * one byte for 0-termination.
57 */ 63 */
58#define GNUNET_TUN_IPV6_REGEXLEN 128 + 6 64#define GNUNET_TUN_IPV6_REGEXLEN 40
59 65
60 66
61GNUNET_NETWORK_STRUCT_BEGIN 67GNUNET_NETWORK_STRUCT_BEGIN
@@ -653,8 +659,8 @@ struct GNUNET_TUN_DnsRecordLine
653 * ICMP header. 659 * ICMP header.
654 */ 660 */
655struct GNUNET_TUN_IcmpHeader { 661struct GNUNET_TUN_IcmpHeader {
656 uint8_t type; 662 uint8_t type;
657 uint8_t code; 663 uint8_t code;
658 uint16_t crc GNUNET_PACKED; 664 uint16_t crc GNUNET_PACKED;
659 665
660 union { 666 union {
@@ -677,8 +683,8 @@ struct GNUNET_TUN_IcmpHeader {
677 683
678 /** 684 /**
679 * ICMP Redirect 685 * ICMP Redirect
680 */ 686 */
681 struct in_addr redirect_gateway_address GNUNET_PACKED; 687 struct in_addr redirect_gateway_address GNUNET_PACKED;
682 688
683 /** 689 /**
684 * MTU for packets that are too big (IPv6). 690 * MTU for packets that are too big (IPv6).
@@ -775,7 +781,7 @@ GNUNET_TUN_calculate_udp4_checksum (const struct GNUNET_TUN_IPv4Header *ip,
775 * @param ip ipv6 header fully initialized 781 * @param ip ipv6 header fully initialized
776 * @param udp UDP header (initialized except for CRC) 782 * @param udp UDP header (initialized except for CRC)
777 * @param payload the UDP payload 783 * @param payload the UDP payload
778 * @param payload_length number of bytes of UDP payload 784 * @param payload_length number of bytes of @a payload
779 */ 785 */
780void 786void
781GNUNET_TUN_calculate_udp6_checksum (const struct GNUNET_TUN_IPv6Header *ip, 787GNUNET_TUN_calculate_udp6_checksum (const struct GNUNET_TUN_IPv6Header *ip,
@@ -789,7 +795,7 @@ GNUNET_TUN_calculate_udp6_checksum (const struct GNUNET_TUN_IPv6Header *ip,
789 * 795 *
790 * @param icmp IMCP header (initialized except for CRC) 796 * @param icmp IMCP header (initialized except for CRC)
791 * @param payload the ICMP payload 797 * @param payload the ICMP payload
792 * @param payload_length number of bytes of ICMP payload 798 * @param payload_length number of bytes of @a payload
793 */ 799 */
794void 800void
795GNUNET_TUN_calculate_icmp_checksum (struct GNUNET_TUN_IcmpHeader *icmp, 801GNUNET_TUN_calculate_icmp_checksum (struct GNUNET_TUN_IcmpHeader *icmp,
@@ -798,29 +804,31 @@ GNUNET_TUN_calculate_icmp_checksum (struct GNUNET_TUN_IcmpHeader *icmp,
798 804
799 805
800/** 806/**
801 * Create a regex in @a rxstr from the given @a ip and @a netmask. 807 * Create a regex in @a rxstr from the given @a ip and @a port.
802 * 808 *
803 * @param ip IPv4 representation. 809 * @param ip IPv4 representation.
804 * @param netmask netmask for the ip. 810 * @param port destination port
805 * @param rxstr generated regex, must be at least #GNUNET_TUN_IPV4_REGEXLEN 811 * @param rxstr generated regex, must be at least #GNUNET_TUN_IPV4_REGEXLEN
806 * bytes long. 812 * bytes long.
807 */ 813 */
808void 814void
809GNUNET_TUN_ipv4toregexsearch (const struct in_addr *ip, const char *netmask, 815GNUNET_TUN_ipv4toregexsearch (const struct in_addr *ip,
810 char *rxstr); 816 uint16_t port,
817 char *rxstr);
811 818
812 819
813/** 820/**
814 * Create a regex in @a rxstr from the given @a ipv6 and @a prefixlen. 821 * Create a regex in @a rxstr from the given @a ipv6 and @a port.
815 * 822 *
816 * @param ipv6 IPv6 representation. 823 * @param ipv6 IPv6 representation.
817 * @param prefixlen length of the ipv6 prefix. 824 * @param port destination port
818 * @param rxstr generated regex, must be at least #GNUNET_TUN_IPV6_REGEXLEN 825 * @param rxstr generated regex, must be at least #GNUNET_TUN_IPV6_REGEXLEN
819 * bytes long. 826 * bytes long.
820 */ 827 */
821void 828void
822GNUNET_TUN_ipv6toregexsearch (const struct in6_addr *ipv6, 829GNUNET_TUN_ipv6toregexsearch (const struct in6_addr *ipv6,
823 unsigned int prefixlen, char *rxstr); 830 uint16_t port,
831 char *rxstr);
824 832
825 833
826/** 834/**
diff --git a/src/tun/regex.c b/src/tun/regex.c
index 87e75b511..3d3ebd8ba 100644
--- a/src/tun/regex.c
+++ b/src/tun/regex.c
@@ -21,6 +21,7 @@
21 * @file src/tun/regex.c 21 * @file src/tun/regex.c
22 * @brief functions to convert IP networks to regexes 22 * @brief functions to convert IP networks to regexes
23 * @author Maximilian Szengel 23 * @author Maximilian Szengel
24 * @author Christian Grothoff
24 */ 25 */
25#include "platform.h" 26#include "platform.h"
26#include "gnunet_util_lib.h" 27#include "gnunet_util_lib.h"
@@ -28,114 +29,311 @@
28 29
29 30
30/** 31/**
31 * Create a string with binary IP notation for the given 'addr' in 'str'. 32 * Create a regex in @a rxstr from the given @a ip and @a netmask.
32 * 33 *
33 * @param af address family of the given 'addr'. 34 * @param ip IPv4 representation.
34 * @param addr address that should be converted to a string. 35 * @param port destination port
35 * struct in_addr * for IPv4 and struct in6_addr * for IPv6. 36 * @param rxstr generated regex, must be at least #GNUNET_TUN_IPV4_REGEXLEN
36 * @param str string that will contain binary notation of 'addr'. Expected 37 * bytes long.
37 * to be at least 33 bytes long for IPv4 and 129 bytes long for IPv6. 38 */
39void
40GNUNET_TUN_ipv4toregexsearch (const struct in_addr *ip,
41 uint16_t port,
42 char *rxstr)
43{
44 GNUNET_snprintf (rxstr,
45 GNUNET_TUN_IPV4_REGEXLEN,
46 "4-%04X-%08X",
47 (unsigned int) port,
48 ntohl (ip->s_addr));
49}
50
51
52/**
53 * Create a regex in @a rxstr from the given @a ipv6 and @a prefixlen.
54 *
55 * @param ipv6 IPv6 representation.
56 * @param port destination port
57 * @param rxstr generated regex, must be at least #GNUNET_TUN_IPV6_REGEXLEN
58 * bytes long.
59 */
60void
61GNUNET_TUN_ipv6toregexsearch (const struct in6_addr *ipv6,
62 uint16_t port,
63 char *rxstr)
64{
65 const uint32_t *addr;
66
67 addr = (const uint32_t *) ipv6;
68 GNUNET_snprintf (rxstr,
69 GNUNET_TUN_IPV6_REGEXLEN,
70 "6-%04X-%08X%08X%08X%08X",
71 (unsigned int) port,
72 ntohl (addr[0]),
73 ntohl (addr[1]),
74 ntohl (addr[2]),
75 ntohl (addr[3]));
76}
77
78
79/**
80 * Convert the given 4-bit (!) number to a regex.
81 *
82 * @param value the value, only the lowest 4 bits will be looked at
83 * @param mask which bits in value are wildcards (any value)?
38 */ 84 */
39static void 85static char *
40iptobinstr (const int af, const void *addr, char *str) 86nibble_to_regex (uint8_t value,
87 uint8_t mask)
41{ 88{
42 int i; 89 char *ret;
43 90
44 switch (af) 91 value &= mask;
92 switch (mask)
45 { 93 {
46 case AF_INET: 94 case 0:
47 { 95 return GNUNET_strdup ("."); /* wildcard */
48 uint32_t b = htonl (((struct in_addr *) addr)->s_addr); 96 case 8:
49 97 GNUNET_asprintf (&ret,
50 str[32] = '\0'; 98 "(%X|%X|%X|%X|%X|%X|%X|%X)",
51 str += 31; 99 value,
52 for (i = 31; i >= 0; i--) 100 value + 1,
53 { 101 value + 2,
54 *str = (b & 1) + '0'; 102 value + 3,
55 str--; 103 value + 4,
56 b >>= 1; 104 value + 5,
57 } 105 value + 6,
58 break; 106 value + 7);
59 } 107 return ret;
60 case AF_INET6: 108 case 12:
109 GNUNET_asprintf (&ret,
110 "(%X|%X|%X|%X)",
111 value,
112 value + 1,
113 value + 2,
114 value + 3);
115 return ret;
116 case 14:
117 GNUNET_asprintf (&ret,
118 "(%X|%X)",
119 value,
120 value + 1);
121 return ret;
122 case 15:
123 GNUNET_asprintf (&ret,
124 "%X",
125 value);
126 return ret;
127 default:
128 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
129 "Bad mask: %d\n",
130 mask);
131 GNUNET_break (0);
132 return NULL;
133 }
134}
135
136
137/**
138 * Convert the given 16-bit number to a regex.
139 *
140 * @param value the value
141 * @param mask which bits in value are wildcards (any value)?
142 */
143static char *
144num_to_regex (uint16_t value,
145 uint16_t mask)
146{
147 const uint8_t *v = (const uint8_t *) &value;
148 const uint8_t *m = (const uint8_t *) &mask;
149 char *a;
150 char *b;
151 char *c;
152 char *d;
153 char *ret;
154
155 a = nibble_to_regex (v[0] >> 4, m[0] >> 4);
156 b = nibble_to_regex (v[0] & 15, m[0] & 15);
157 c = nibble_to_regex (v[1] >> 4, m[1] >> 4);
158 d = nibble_to_regex (v[1] & 15, m[1] & 15);
159 ret = NULL;
160 if ( (NULL != a) &&
161 (NULL != b) &&
162 (NULL != c) &&
163 (NULL != d) )
164 GNUNET_asprintf (&ret,
165 "%s%s%s%s",
166 a, b, c, d);
167 GNUNET_free_non_null (a);
168 GNUNET_free_non_null (b);
169 GNUNET_free_non_null (c);
170 GNUNET_free_non_null (d);
171 return ret;
172}
173
174
175/**
176 * Convert a port policy to a regular expression. Note: this is a
177 * very simplistic implementation, we might want to consider doing
178 * something more sophisiticated (resulting in smaller regular
179 * expressions) at a later time.
180 *
181 * @param pp port policy to convert
182 * @return NULL on error
183 */
184static char *
185port_to_regex (const struct GNUNET_STRINGS_PortPolicy *pp)
186{
187 char *reg;
188 char *ret;
189 char *tmp;
190 unsigned int i;
191
192 if ( (0 == pp->start_port) ||
193 ( (1 == pp->start_port) &&
194 (0xFFFF == pp->end_port) &&
195 (GNUNET_NO == pp->negate_portrange)) )
196 return GNUNET_strdup ("....");
197 if ( (pp->start_port == pp->end_port) &&
198 (GNUNET_NO == pp->negate_portrange))
199 {
200 GNUNET_asprintf (&ret,
201 "%04X",
202 pp->start_port);
203 return ret;
204 }
205 reg = NULL;
206 for (i=1;i<=0xFFFF;i++)
207 {
208 if ( ( (i >= pp->start_port) && (i <= pp->end_port) ) ^
209 (GNUNET_YES == pp->negate_portrange) )
61 { 210 {
62 struct in6_addr b = *(const struct in6_addr *) addr; 211 if (NULL == reg)
63 212 {
64 str[128] = '\0'; 213 GNUNET_asprintf (&tmp,
65 str += 127; 214 "%04X",
66 for (i = 127; i >= 0; i--) 215 i);
67 { 216 }
68 *str = (b.s6_addr[i / 8] & 1) + '0'; 217 else
69 str--; 218 {
70 b.s6_addr[i / 8] >>= 1; 219 GNUNET_asprintf (&tmp,
71 } 220 "%s|%04X",
72 break; 221 reg,
222 i);
223 GNUNET_free (reg);
224 }
225 reg = tmp;
73 } 226 }
74 } 227 }
228 GNUNET_asprintf (&ret,
229 "(%s)",
230 reg);
231 GNUNET_free (reg);
232 return ret;
75} 233}
76 234
77 235
78/** 236/**
79 * Get the ipv4 network prefix from the given 'netmask'. 237 * Convert an address (IPv4 or IPv6) to a regex.
80 * 238 *
81 * @param netmask netmask for which to get the prefix len. 239 * @param addr address
82 * 240 * @param mask network mask
83 * @return length of ipv4 prefix for 'netmask'. 241 * @param len number of bytes in @a addr and @a mask
242 * @return NULL on error, otherwise regex for the address
84 */ 243 */
85static unsigned int 244static char *
86ipv4netmasktoprefixlen (const char *netmask) 245address_to_regex (const void *addr,
246 const void *mask,
247 size_t len)
87{ 248{
88 struct in_addr a; 249 const uint16_t *a = addr;
89 unsigned int len; 250 const uint16_t *m = mask;
90 uint32_t t; 251 char *ret;
91 252 char *tmp;
92 if (1 != inet_pton (AF_INET, netmask, &a)) 253 char *reg;
93 return 0; 254 unsigned int i;
94 len = 32; 255
95 for (t = htonl (~a.s_addr); 0 != t; t >>= 1) 256 ret = NULL;
96 len--; 257 GNUNET_assert (1 != (len % 2));
97 return len; 258 for (i=0;i<len / 2;i++)
259 {
260 reg = num_to_regex (a[i], m[i]);
261 if (NULL == reg)
262 {
263 GNUNET_free_non_null (ret);
264 return NULL;
265 }
266 if (NULL == ret)
267 {
268 ret = reg;
269 }
270 else
271 {
272 GNUNET_asprintf (&tmp,
273 "%s%s",
274 ret, reg);
275 GNUNET_free (ret);
276 GNUNET_free (reg);
277 ret = tmp;
278 }
279 }
280 return ret;
98} 281}
99 282
100 283
101/** 284/**
102 * Create a regex in 'rxstr' from the given 'ip' and 'netmask'. 285 * Convert a single line of an IPv4 policy to a regular expression.
103 * 286 *
104 * @param ip IPv4 representation. 287 * @param v4 line to convert
105 * @param netmask netmask for the ip. 288 * @return NULL on error
106 * @param rxstr generated regex, must be at least GNUNET_REGEX_IPV4_REGEXLEN
107 * bytes long.
108 */ 289 */
109void 290static char *
110GNUNET_TUN_ipv4toregexsearch (const struct in_addr *ip, const char *netmask, 291ipv4_to_regex (const struct GNUNET_STRINGS_IPv4NetworkPolicy *v4)
111 char *rxstr)
112{ 292{
113 unsigned int pfxlen; 293 char *reg;
294 char *pp;
295 char *ret;
114 296
115 pfxlen = ipv4netmasktoprefixlen (netmask); 297 reg = address_to_regex (&v4->network,
116 iptobinstr (AF_INET, ip, rxstr); 298 &v4->netmask,
117 rxstr[pfxlen] = '\0'; 299 sizeof (struct in_addr));
118 if (pfxlen < 32) 300 if (NULL == reg)
119 strcat (rxstr, "(0|1)+"); 301 return NULL;
302 pp = port_to_regex (&v4->pp);
303 GNUNET_asprintf (&ret,
304 "4-%s-%s",
305 pp, reg);
306 GNUNET_free (pp);
307 GNUNET_free (reg);
308 return ret;
120} 309}
121 310
122 311
123/** 312/**
124 * Create a regex in 'rxstr' from the given 'ipv6' and 'prefixlen'. 313 * Convert a single line of an IPv4 policy to a regular expression.
125 * 314 *
126 * @param ipv6 IPv6 representation. 315 * @param v6 line to convert
127 * @param prefixlen length of the ipv6 prefix. 316 * @return NULL on error
128 * @param rxstr generated regex, must be at least GNUNET_REGEX_IPV6_REGEXLEN
129 * bytes long.
130 */ 317 */
131void 318static char *
132GNUNET_TUN_ipv6toregexsearch (const struct in6_addr *ipv6, unsigned int prefixlen, 319ipv6_to_regex (const struct GNUNET_STRINGS_IPv6NetworkPolicy *v6)
133 char *rxstr)
134{ 320{
135 iptobinstr (AF_INET6, ipv6, rxstr); 321 char *reg;
136 rxstr[prefixlen] = '\0'; 322 char *pp;
137 if (prefixlen < 128) 323 char *ret;
138 strcat (rxstr, "(0|1)+"); 324
325 reg = address_to_regex (&v6->network,
326 &v6->netmask,
327 sizeof (struct in6_addr));
328 if (NULL == reg)
329 return NULL;
330 pp = port_to_regex (&v6->pp);
331 GNUNET_asprintf (&ret,
332 "6-%s-%s",
333 pp, reg);
334 GNUNET_free (pp);
335 GNUNET_free (reg);
336 return ret;
139} 337}
140 338
141 339
@@ -151,8 +349,39 @@ GNUNET_TUN_ipv6toregexsearch (const struct in6_addr *ipv6, unsigned int prefixle
151char * 349char *
152GNUNET_TUN_ipv4policy2regex (const char *policy) 350GNUNET_TUN_ipv4policy2regex (const char *policy)
153{ 351{
154 // FIXME: do actual policy parsing here, see #2919 352 struct GNUNET_STRINGS_IPv4NetworkPolicy *np;
155 return GNUNET_strdup (policy); 353 char *reg;
354 char *tmp;
355 char *line;
356 unsigned int i;
357
358 np = GNUNET_STRINGS_parse_ipv4_policy (policy);
359 if (NULL == np)
360 return NULL;
361 reg = NULL;
362 for (i=0; 0 != np[i].network.s_addr; i++)
363 {
364 line = ipv4_to_regex (&np[i]);
365 if (NULL == line)
366 {
367 GNUNET_free_non_null (reg);
368 return NULL;
369 }
370 if (NULL == reg)
371 {
372 reg = line;
373 }
374 else
375 {
376 GNUNET_asprintf (&tmp,
377 "%s|(%s)",
378 reg, line);
379 GNUNET_free (reg);
380 GNUNET_free (line);
381 reg = tmp;
382 }
383 }
384 return reg;
156} 385}
157 386
158 387
@@ -160,7 +389,7 @@ GNUNET_TUN_ipv4policy2regex (const char *policy)
160 * Convert an exit policy to a regular expression. The exit policy 389 * Convert an exit policy to a regular expression. The exit policy
161 * specifies a set of subnets this peer is willing to serve as an 390 * specifies a set of subnets this peer is willing to serve as an
162 * exit for; the resulting regular expression will match the 391 * exit for; the resulting regular expression will match the
163 * IPv4 address strings as returned by 'GNUNET_TUN_ipv4toregexsearch'. 392 * IPv6 address strings as returned by 'GNUNET_TUN_ipv6toregexsearch'.
164 * 393 *
165 * @param policy exit policy specification 394 * @param policy exit policy specification
166 * @return regular expression, NULL on error 395 * @return regular expression, NULL on error
@@ -168,8 +397,41 @@ GNUNET_TUN_ipv4policy2regex (const char *policy)
168char * 397char *
169GNUNET_TUN_ipv6policy2regex (const char *policy) 398GNUNET_TUN_ipv6policy2regex (const char *policy)
170{ 399{
171 // FIXME: do actual policy parsing here, see #2919 400 struct in6_addr zero;
172 return GNUNET_strdup (policy); 401 struct GNUNET_STRINGS_IPv6NetworkPolicy *np;
402 char *reg;
403 char *tmp;
404 char *line;
405 unsigned int i;
406
407 np = GNUNET_STRINGS_parse_ipv6_policy (policy);
408 if (NULL == np)
409 return NULL;
410 reg = NULL;
411 memset (&zero, 0, sizeof (struct in6_addr));
412 for (i=0; 0 != memcmp (&zero, &np[i].network, sizeof (struct in6_addr)); i++)
413 {
414 line = ipv6_to_regex (&np[i]);
415 if (NULL == line)
416 {
417 GNUNET_free_non_null (reg);
418 return NULL;
419 }
420 if (NULL == reg)
421 {
422 reg = line;
423 }
424 else
425 {
426 GNUNET_asprintf (&tmp,
427 "%s|(%s)",
428 reg, line);
429 GNUNET_free (reg);
430 GNUNET_free (line);
431 reg = tmp;
432 }
433 }
434 return reg;
173} 435}
174 436
175 437
diff --git a/src/tun/test_regex.c b/src/tun/test_regex.c
index a0c3e99fd..341d8b9a0 100644
--- a/src/tun/test_regex.c
+++ b/src/tun/test_regex.c
@@ -27,8 +27,11 @@
27 27
28 28
29static int 29static int
30test_iptoregex (const char *ipv4, const char *netmask, const char *expectedv4, 30test_iptoregex (const char *ipv4,
31 const char *ipv6, unsigned int prefixlen, 31 uint16_t port,
32 const char *expectedv4,
33 const char *ipv6,
34 uint16_t port6,
32 const char *expectedv6) 35 const char *expectedv6)
33{ 36{
34 int error = 0; 37 int error = 0;
@@ -39,29 +42,82 @@ test_iptoregex (const char *ipv4, const char *netmask, const char *expectedv4,
39 char rxv6[GNUNET_TUN_IPV6_REGEXLEN]; 42 char rxv6[GNUNET_TUN_IPV6_REGEXLEN];
40 43
41 GNUNET_assert (1 == inet_pton (AF_INET, ipv4, &a)); 44 GNUNET_assert (1 == inet_pton (AF_INET, ipv4, &a));
42 GNUNET_TUN_ipv4toregexsearch (&a, netmask, rxv4); 45 GNUNET_TUN_ipv4toregexsearch (&a, port, rxv4);
43
44 46
45 if (0 != strcmp (rxv4, expectedv4)) 47 if (0 != strcmp (rxv4, expectedv4))
46 { 48 {
47 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected: %s but got: %s\n", 49 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
48 expectedv4, rxv4); 50 "Expected: %s but got: %s\n",
51 expectedv4,
52 rxv4);
49 error++; 53 error++;
50 } 54 }
51 55
52 GNUNET_assert (1 == inet_pton (AF_INET6, ipv6, &b)); 56 GNUNET_assert (1 == inet_pton (AF_INET6, ipv6, &b));
53 GNUNET_TUN_ipv6toregexsearch (&b, prefixlen, rxv6); 57 GNUNET_TUN_ipv6toregexsearch (&b, port6, rxv6);
54
55 if (0 != strcmp (rxv6, expectedv6)) 58 if (0 != strcmp (rxv6, expectedv6))
56 { 59 {
57 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected: %s but got: %s\n", 60 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
61 "Expected: %s but got: %s\n",
58 expectedv6, rxv6); 62 expectedv6, rxv6);
59 error++; 63 error++;
60 } 64 }
61
62 return error; 65 return error;
63} 66}
64 67
68
69static int
70test_policy4toregex (const char *policy,
71 const char *regex)
72{
73 char *r;
74 int ret;
75
76 ret = 0;
77 r = GNUNET_TUN_ipv4policy2regex (policy);
78 if (NULL == r)
79 {
80 GNUNET_break (0);
81 return 1;
82 }
83 if (0 != strcmp (regex, r))
84 {
85 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
86 "Expected: `%s' but got: `%s'\n",
87 regex, r);
88 ret = 2;
89 }
90 GNUNET_free (r);
91 return ret;
92}
93
94
95static int
96test_policy6toregex (const char *policy,
97 const char *regex)
98{
99 char *r;
100 int ret;
101
102 ret = 0;
103 r = GNUNET_TUN_ipv6policy2regex (policy);
104 if (NULL == r)
105 {
106 GNUNET_break (0);
107 return 1;
108 }
109 if (0 != strcmp (regex, r))
110 {
111 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
112 "Expected: `%s' but got: `%s'\n",
113 regex, r);
114 ret = 2;
115 }
116 GNUNET_free (r);
117 return ret;
118}
119
120
65int 121int
66main (int argc, char *argv[]) 122main (int argc, char *argv[])
67{ 123{
@@ -72,32 +128,41 @@ main (int argc, char *argv[])
72 error = 0; 128 error = 0;
73 129
74 error += 130 error +=
75 test_iptoregex ("192.0.0.0", "255.255.255.0", 131 test_iptoregex ("192.1.2.3", 2086,
76 "110000000000000000000000(0|1)+", "FFFF::0", 16, 132 "4-0826-C0010203",
77 "1111111111111111(0|1)+"); 133 "FFFF::1", 8080,
78 134 "6-1F90-FFFF0000000000000000000000000001");
79 error += 135 error +=
80 test_iptoregex ("187.238.225.0", "255.255.255.128", 136 test_iptoregex ("187.238.255.0", 80,
81 "1011101111101110111000010(0|1)+", "E1E1:73F9:51BE::0", 137 "4-0050-BBEEFF00",
82 49, 138 "E1E1:73F9:51BE::0", 49,
83 "1110000111100001011100111111100101010001101111100(0|1)+"); 139 "6-0031-E1E173F951BE00000000000000000000");
84
85 error += 140 error +=
86 test_iptoregex ("255.255.255.255", "255.255.255.255", 141 test_policy4toregex ("192.1.2.0/24:80;",
87 "11111111111111111111111111111111", 142 "4-0050-C00102..");
88 "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF", 128,
89 "11111111111111111111111111111111"
90 "11111111111111111111111111111111"
91 "11111111111111111111111111111111"
92 "11111111111111111111111111111111");
93
94 error += 143 error +=
95 test_iptoregex ("0.0.0.0", "255.255.255.255", 144 test_policy4toregex ("192.1.0.0/16;",
96 "00000000000000000000000000000000", "0::0", 128, 145 "4-....-C001....");
97 "00000000000000000000000000000000" 146 error +=
98 "00000000000000000000000000000000" 147 test_policy4toregex ("192.1.0.0/16:80-81;",
99 "00000000000000000000000000000000" 148 "4-(0050|0051)-C001....");
100 "00000000000000000000000000000000"); 149 error +=
101 150 test_policy4toregex ("192.1.0.0/8:!3-65535;",
151 "4-(0001|0002)-C0......");
152 error +=
153 test_policy6toregex ("E1E1::1;",
154 "6-....-E1E10000000000000000000000000001");
155 error +=
156 test_policy6toregex ("E1E1:ABCD::1/120;",
157 "6-....-E1E1ABCD0000000000000000000000..");
158 error +=
159 test_policy6toregex ("E1E1:ABCD::ABCD/126;",
160 "6-....-E1E1ABCD00000000000000000000ABC(C|D|E|F)");
161 error +=
162 test_policy6toregex ("E1E1:ABCD::ABCD/127;",
163 "6-....-E1E1ABCD00000000000000000000ABC(C|D)");
164 error +=
165 test_policy6toregex ("E1E1:ABCD::ABCD/128:80;",
166 "6-0050-E1E1ABCD00000000000000000000ABCD");
102 return error; 167 return error;
103} 168}
diff --git a/src/util/service.c b/src/util/service.c
index e7d4c1c6f..8f8cca36d 100644
--- a/src/util/service.c
+++ b/src/util/service.c
@@ -65,10 +65,11 @@ GNUNET_SPEEDUP_stop_ (void);
65 * 65 *
66 * @param list a list of networks 66 * @param list a list of networks
67 * @param add the IP to check (in network byte order) 67 * @param add the IP to check (in network byte order)
68 * @return GNUNET_NO if the IP is not in the list, GNUNET_YES if it it is 68 * @return #GNUNET_NO if the IP is not in the list, #GNUNET_YES if it it is
69 */ 69 */
70static int 70static int
71check_ipv4_listed (const struct GNUNET_STRINGS_IPv4NetworkPolicy *list, const struct in_addr *add) 71check_ipv4_listed (const struct GNUNET_STRINGS_IPv4NetworkPolicy *list,
72 const struct in_addr *add)
72{ 73{
73 unsigned int i; 74 unsigned int i;
74 75
@@ -91,10 +92,11 @@ check_ipv4_listed (const struct GNUNET_STRINGS_IPv4NetworkPolicy *list, const st
91 * 92 *
92 * @param list a list of networks 93 * @param list a list of networks
93 * @param ip the IP to check (in network byte order) 94 * @param ip the IP to check (in network byte order)
94 * @return GNUNET_NO if the IP is not in the list, GNUNET_YES if it it is 95 * @return #GNUNET_NO if the IP is not in the list, #GNUNET_YES if it it is
95 */ 96 */
96static int 97static int
97check_ipv6_listed (const struct GNUNET_STRINGS_IPv6NetworkPolicy *list, const struct in6_addr *ip) 98check_ipv6_listed (const struct GNUNET_STRINGS_IPv6NetworkPolicy *list,
99 const struct in6_addr *ip)
98{ 100{
99 unsigned int i; 101 unsigned int i;
100 unsigned int j; 102 unsigned int j;
diff --git a/src/util/strings.c b/src/util/strings.c
index c50669e62..2fc647f7b 100644
--- a/src/util/strings.c
+++ b/src/util/strings.c
@@ -993,22 +993,24 @@ GNUNET_STRINGS_parse_uri (const char *path, char **scheme_part,
993 993
994 994
995/** 995/**
996 * Check whether 'filename' is absolute or not, and if it's an URI 996 * Check whether @a filename is absolute or not, and if it's an URI
997 * 997 *
998 * @param filename filename to check 998 * @param filename filename to check
999 * @param can_be_uri GNUNET_YES to check for being URI, GNUNET_NO - to 999 * @param can_be_uri #GNUNET_YES to check for being URI, #GNUNET_NO - to
1000 * assume it's not URI 1000 * assume it's not URI
1001 * @param r_is_uri a pointer to an int that is set to GNUNET_YES if 'filename' 1001 * @param r_is_uri a pointer to an int that is set to #GNUNET_YES if @a filename
1002 * is URI and to GNUNET_NO otherwise. Can be NULL. If 'can_be_uri' is 1002 * is URI and to #GNUNET_NO otherwise. Can be NULL. If @a can_be_uri is
1003 * not GNUNET_YES, *r_is_uri is set to GNUNET_NO. 1003 * not #GNUNET_YES, `* r_is_uri` is set to #GNUNET_NO.
1004 * @param r_uri_scheme a pointer to a char * that is set to a pointer to URI scheme. 1004 * @param r_uri_scheme a pointer to a char * that is set to a pointer to URI scheme.
1005 * The string is allocated by the function, and should be freed with 1005 * The string is allocated by the function, and should be freed with
1006 * GNUNET_free (). Can be NULL. 1006 * GNUNET_free(). Can be NULL.
1007 * @return GNUNET_YES if 'filename' is absolute, GNUNET_NO otherwise. 1007 * @return #GNUNET_YES if @a filename is absolute, #GNUNET_NO otherwise.
1008 */ 1008 */
1009int 1009int
1010GNUNET_STRINGS_path_is_absolute (const char *filename, int can_be_uri, 1010GNUNET_STRINGS_path_is_absolute (const char *filename,
1011 int *r_is_uri, char **r_uri_scheme) 1011 int can_be_uri,
1012 int *r_is_uri,
1013 char **r_uri_scheme)
1012{ 1014{
1013#if WINDOWS 1015#if WINDOWS
1014 size_t len; 1016 size_t len;
@@ -1067,12 +1069,12 @@ GNUNET_STRINGS_path_is_absolute (const char *filename, int can_be_uri,
1067 1069
1068 1070
1069/** 1071/**
1070 * Perform 'checks' on 'filename' 1072 * Perform @a checks on @a filename.
1071 * 1073 *
1072 * @param filename file to check 1074 * @param filename file to check
1073 * @param checks checks to perform 1075 * @param checks checks to perform
1074 * @return GNUNET_YES if all checks pass, GNUNET_NO if at least one of them 1076 * @return #GNUNET_YES if all checks pass, #GNUNET_NO if at least one of them
1075 * fails, GNUNET_SYSERR when a check can't be performed 1077 * fails, #GNUNET_SYSERR when a check can't be performed
1076 */ 1078 */
1077int 1079int
1078GNUNET_STRINGS_check_filename (const char *filename, 1080GNUNET_STRINGS_check_filename (const char *filename,
@@ -1111,11 +1113,12 @@ GNUNET_STRINGS_check_filename (const char *filename,
1111 * The string is expected to have the format "[ABCD::01]:80". 1113 * The string is expected to have the format "[ABCD::01]:80".
1112 * 1114 *
1113 * @param zt_addr 0-terminated string. May be mangled by the function. 1115 * @param zt_addr 0-terminated string. May be mangled by the function.
1114 * @param addrlen length of zt_addr (not counting 0-terminator). 1116 * @param addrlen length of @a zt_addr (not counting 0-terminator).
1115 * @param r_buf a buffer to fill. Initially gets filled with zeroes, 1117 * @param r_buf a buffer to fill. Initially gets filled with zeroes,
1116 * then its sin6_port, sin6_family and sin6_addr are set appropriately. 1118 * then its sin6_port, sin6_family and sin6_addr are set appropriately.
1117 * @return GNUNET_OK if conversion succeded. GNUNET_SYSERR otherwise, in which 1119 * @return #GNUNET_OK if conversion succeded.
1118 * case the contents of r_buf are undefined. 1120 * #GNUNET_SYSERR otherwise, in which
1121 * case the contents of @a r_buf are undefined.
1119 */ 1122 */
1120int 1123int
1121GNUNET_STRINGS_to_address_ipv6 (const char *zt_addr, 1124GNUNET_STRINGS_to_address_ipv6 (const char *zt_addr,
@@ -1182,10 +1185,11 @@ GNUNET_STRINGS_to_address_ipv6 (const char *zt_addr,
1182 * The string is expected to have the format "1.2.3.4:80". 1185 * The string is expected to have the format "1.2.3.4:80".
1183 * 1186 *
1184 * @param zt_addr 0-terminated string. May be mangled by the function. 1187 * @param zt_addr 0-terminated string. May be mangled by the function.
1185 * @param addrlen length of zt_addr (not counting 0-terminator). 1188 * @param addrlen length of @a zt_addr (not counting 0-terminator).
1186 * @param r_buf a buffer to fill. 1189 * @param r_buf a buffer to fill.
1187 * @return GNUNET_OK if conversion succeded. GNUNET_SYSERR otherwise, in which case 1190 * @return #GNUNET_OK if conversion succeded.
1188 * the contents of r_buf are undefined. 1191 * #GNUNET_SYSERR otherwise, in which case
1192 * the contents of @a r_buf are undefined.
1189 */ 1193 */
1190int 1194int
1191GNUNET_STRINGS_to_address_ipv4 (const char *zt_addr, uint16_t addrlen, 1195GNUNET_STRINGS_to_address_ipv4 (const char *zt_addr, uint16_t addrlen,
@@ -1217,14 +1221,14 @@ GNUNET_STRINGS_to_address_ipv4 (const char *zt_addr, uint16_t addrlen,
1217 1221
1218 1222
1219/** 1223/**
1220 * Tries to convert 'addr' string to an IP (v4 or v6) address. 1224 * Tries to convert @a addr string to an IP (v4 or v6) address.
1221 * Will automatically decide whether to treat 'addr' as v4 or v6 address. 1225 * Will automatically decide whether to treat 'addr' as v4 or v6 address.
1222 * 1226 *
1223 * @param addr a string, may not be 0-terminated. 1227 * @param addr a string, may not be 0-terminated.
1224 * @param addrlen number of bytes in addr (if addr is 0-terminated, 1228 * @param addrlen number of bytes in @a addr (if addr is 0-terminated,
1225 * 0-terminator should not be counted towards addrlen). 1229 * 0-terminator should not be counted towards addrlen).
1226 * @param r_buf a buffer to fill. 1230 * @param r_buf a buffer to fill.
1227 * @return GNUNET_OK if conversion succeded. GNUNET_SYSERR otherwise, in which 1231 * @return #GNUNET_OK if conversion succeded. GNUNET_SYSERR otherwise, in which
1228 * case the contents of r_buf are undefined. 1232 * case the contents of r_buf are undefined.
1229 */ 1233 */
1230int 1234int
@@ -1233,8 +1237,12 @@ GNUNET_STRINGS_to_address_ip (const char *addr,
1233 struct sockaddr_storage *r_buf) 1237 struct sockaddr_storage *r_buf)
1234{ 1238{
1235 if (addr[0] == '[') 1239 if (addr[0] == '[')
1236 return GNUNET_STRINGS_to_address_ipv6 (addr, addrlen, (struct sockaddr_in6 *) r_buf); 1240 return GNUNET_STRINGS_to_address_ipv6 (addr,
1237 return GNUNET_STRINGS_to_address_ipv4 (addr, addrlen, (struct sockaddr_in *) r_buf); 1241 addrlen,
1242 (struct sockaddr_in6 *) r_buf);
1243 return GNUNET_STRINGS_to_address_ipv4 (addr,
1244 addrlen,
1245 (struct sockaddr_in *) r_buf);
1238} 1246}
1239 1247
1240 1248
@@ -1243,7 +1251,8 @@ GNUNET_STRINGS_to_address_ip (const char *addr,
1243 * freed with a single call to GNUNET_free (); 1251 * freed with a single call to GNUNET_free ();
1244 */ 1252 */
1245static char *const * 1253static char *const *
1246_make_continuous_arg_copy (int argc, char *const *argv) 1254_make_continuous_arg_copy (int argc,
1255 char *const *argv)
1247{ 1256{
1248 size_t argvsize = 0; 1257 size_t argvsize = 0;
1249 int i; 1258 int i;
@@ -1276,7 +1285,7 @@ _make_continuous_arg_copy (int argc, char *const *argv)
1276 * @param argv argv (as given by main()) 1285 * @param argv argv (as given by main())
1277 * @param u8argc a location to store new argc in (though it's th same as argc) 1286 * @param u8argc a location to store new argc in (though it's th same as argc)
1278 * @param u8argv a location to store new argv in 1287 * @param u8argv a location to store new argv in
1279 * @return GNUNET_OK on success, GNUNET_SYSERR on failure 1288 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
1280 */ 1289 */
1281int 1290int
1282GNUNET_STRINGS_get_utf8_args (int argc, char *const *argv, int *u8argc, char *const **u8argv) 1291GNUNET_STRINGS_get_utf8_args (int argc, char *const *argv, int *u8argc, char *const **u8argv)
@@ -1330,18 +1339,65 @@ GNUNET_STRINGS_get_utf8_args (int argc, char *const *argv, int *u8argc, char *co
1330 1339
1331 1340
1332/** 1341/**
1342 * Parse the given port policy. The format is
1343 * "[!]SPORT[-DPORT]".
1344 *
1345 * @param port_policy string to parse
1346 * @param pp policy to fill in
1347 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the
1348 * @a port_policy is malformed
1349 */
1350static int
1351parse_port_policy (const char *port_policy,
1352 struct GNUNET_STRINGS_PortPolicy *pp)
1353{
1354 const char *pos;
1355 int s;
1356 int e;
1357
1358 pos = port_policy;
1359 if ('!' == *pos)
1360 {
1361 pp->negate_portrange = GNUNET_YES;
1362 pos++;
1363 }
1364 if (2 == sscanf (pos,
1365 "%u-%u",
1366 &s, &e))
1367 {
1368 pp->start_port = (uint16_t) s;
1369 pp->end_port = (uint16_t) e;
1370 return GNUNET_OK;
1371 }
1372 if (1 == sscanf (pos,
1373 "%u",
1374 &s))
1375 {
1376 pp->start_port = (uint16_t) s;
1377 pp->end_port = (uint16_t) s;
1378 return GNUNET_OK;
1379 }
1380 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1381 _("Malformed port policy `%s'\n"),
1382 port_policy);
1383 return GNUNET_SYSERR;
1384}
1385
1386
1387/**
1333 * Parse an IPv4 network policy. The argument specifies a list of 1388 * Parse an IPv4 network policy. The argument specifies a list of
1334 * subnets. The format is <tt>[network/netmask;]*</tt> (no whitespace, 1389 * subnets. The format is
1335 * must be terminated with a semicolon). The network must be given in 1390 * <tt>(network[/netmask][:SPORT[-DPORT]];)*</tt> (no whitespace, must
1391 * be terminated with a semicolon). The network must be given in
1336 * dotted-decimal notation. The netmask can be given in CIDR notation 1392 * dotted-decimal notation. The netmask can be given in CIDR notation
1337 * (/16) or in dotted-decimal (/255.255.0.0). 1393 * (/16) or in dotted-decimal (/255.255.0.0).
1338 * 1394 *
1339 * @param routeList a string specifying the IPv4 subnets 1395 * @param routeListX a string specifying the IPv4 subnets
1340 * @return the converted list, terminated with all zeros; 1396 * @return the converted list, terminated with all zeros;
1341 * NULL if the synatx is flawed 1397 * NULL if the synatx is flawed
1342 */ 1398 */
1343struct GNUNET_STRINGS_IPv4NetworkPolicy * 1399struct GNUNET_STRINGS_IPv4NetworkPolicy *
1344GNUNET_STRINGS_parse_ipv4_policy (const char *routeList) 1400GNUNET_STRINGS_parse_ipv4_policy (const char *routeListX)
1345{ 1401{
1346 unsigned int count; 1402 unsigned int count;
1347 unsigned int i; 1403 unsigned int i;
@@ -1352,12 +1408,16 @@ GNUNET_STRINGS_parse_ipv4_policy (const char *routeList)
1352 unsigned int temps[8]; 1408 unsigned int temps[8];
1353 int slash; 1409 int slash;
1354 struct GNUNET_STRINGS_IPv4NetworkPolicy *result; 1410 struct GNUNET_STRINGS_IPv4NetworkPolicy *result;
1411 int colon;
1412 int end;
1413 char *routeList;
1355 1414
1356 if (NULL == routeList) 1415 if (NULL == routeListX)
1357 return NULL; 1416 return NULL;
1358 len = strlen (routeList); 1417 len = strlen (routeListX);
1359 if (0 == len) 1418 if (0 == len)
1360 return NULL; 1419 return NULL;
1420 routeList = GNUNET_strdup (routeListX);
1361 count = 0; 1421 count = 0;
1362 for (i = 0; i < len; i++) 1422 for (i = 0; i < len; i++)
1363 if (routeList[i] == ';') 1423 if (routeList[i] == ';')
@@ -1367,18 +1427,45 @@ GNUNET_STRINGS_parse_ipv4_policy (const char *routeList)
1367 pos = 0; 1427 pos = 0;
1368 while (i < count) 1428 while (i < count)
1369 { 1429 {
1430 for (colon = pos; ':' != routeList[colon]; colon++)
1431 if ( (';' == routeList[colon]) ||
1432 ('\0' == routeList[colon]) )
1433 break;
1434 end = colon;
1435 for (end = colon; ';' != routeList[end]; end++)
1436 if ('\0' == routeList[end])
1437 break;
1438 if ('\0' == routeList[end])
1439 break;
1440 routeList[end] = '\0';
1441 if (':' == routeList[colon])
1442 {
1443 routeList[colon] = '\0';
1444 if (GNUNET_OK != parse_port_policy (&routeList[colon + 1],
1445 &result[i].pp))
1446 break;
1447 }
1370 cnt = 1448 cnt =
1371 SSCANF (&routeList[pos], "%u.%u.%u.%u/%u.%u.%u.%u;", &temps[0], 1449 SSCANF (&routeList[pos],
1372 &temps[1], &temps[2], &temps[3], &temps[4], &temps[5], 1450 "%u.%u.%u.%u/%u.%u.%u.%u",
1373 &temps[6], &temps[7]); 1451 &temps[0],
1452 &temps[1],
1453 &temps[2],
1454 &temps[3],
1455 &temps[4],
1456 &temps[5],
1457 &temps[6],
1458 &temps[7]);
1374 if (8 == cnt) 1459 if (8 == cnt)
1375 { 1460 {
1376 for (j = 0; j < 8; j++) 1461 for (j = 0; j < 8; j++)
1377 if (temps[j] > 0xFF) 1462 if (temps[j] > 0xFF)
1378 { 1463 {
1379 LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid format for IP: `%s'\n"), 1464 LOG (GNUNET_ERROR_TYPE_ERROR,
1465 _("Invalid format for IP: `%s'\n"),
1380 &routeList[pos]); 1466 &routeList[pos]);
1381 GNUNET_free (result); 1467 GNUNET_free (result);
1468 GNUNET_free (routeList);
1382 return NULL; 1469 return NULL;
1383 } 1470 }
1384 result[i].network.s_addr = 1471 result[i].network.s_addr =
@@ -1387,24 +1474,29 @@ GNUNET_STRINGS_parse_ipv4_policy (const char *routeList)
1387 result[i].netmask.s_addr = 1474 result[i].netmask.s_addr =
1388 htonl ((temps[4] << 24) + (temps[5] << 16) + (temps[6] << 8) + 1475 htonl ((temps[4] << 24) + (temps[5] << 16) + (temps[6] << 8) +
1389 temps[7]); 1476 temps[7]);
1390 while (routeList[pos] != ';') 1477 pos = end + 1;
1391 pos++;
1392 pos++;
1393 i++; 1478 i++;
1394 continue; 1479 continue;
1395 } 1480 }
1396 /* try second notation */ 1481 /* try second notation */
1397 cnt = 1482 cnt =
1398 SSCANF (&routeList[pos], "%u.%u.%u.%u/%u;", &temps[0], &temps[1], 1483 SSCANF (&routeList[pos],
1399 &temps[2], &temps[3], &slash); 1484 "%u.%u.%u.%u/%u",
1485 &temps[0],
1486 &temps[1],
1487 &temps[2],
1488 &temps[3],
1489 &slash);
1400 if (5 == cnt) 1490 if (5 == cnt)
1401 { 1491 {
1402 for (j = 0; j < 4; j++) 1492 for (j = 0; j < 4; j++)
1403 if (temps[j] > 0xFF) 1493 if (temps[j] > 0xFF)
1404 { 1494 {
1405 LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid format for IP: `%s'\n"), 1495 LOG (GNUNET_ERROR_TYPE_ERROR,
1496 _("Invalid format for IP: `%s'\n"),
1406 &routeList[pos]); 1497 &routeList[pos]);
1407 GNUNET_free (result); 1498 GNUNET_free (result);
1499 GNUNET_free (routeList);
1408 return NULL; 1500 return NULL;
1409 } 1501 }
1410 result[i].network.s_addr = 1502 result[i].network.s_addr =
@@ -1420,9 +1512,7 @@ GNUNET_STRINGS_parse_ipv4_policy (const char *routeList)
1420 slash--; 1512 slash--;
1421 } 1513 }
1422 result[i].netmask.s_addr = htonl (result[i].netmask.s_addr); 1514 result[i].netmask.s_addr = htonl (result[i].netmask.s_addr);
1423 while (';' != routeList[pos]) 1515 pos = end + 1;
1424 pos++;
1425 pos++;
1426 i++; 1516 i++;
1427 continue; 1517 continue;
1428 } 1518 }
@@ -1432,6 +1522,7 @@ GNUNET_STRINGS_parse_ipv4_policy (const char *routeList)
1432 _("Invalid network notation ('/%d' is not legal in IPv4 CIDR)."), 1522 _("Invalid network notation ('/%d' is not legal in IPv4 CIDR)."),
1433 slash); 1523 slash);
1434 GNUNET_free (result); 1524 GNUNET_free (result);
1525 GNUNET_free (routeList);
1435 return NULL; /* error */ 1526 return NULL; /* error */
1436 } 1527 }
1437 } 1528 }
@@ -1439,7 +1530,7 @@ GNUNET_STRINGS_parse_ipv4_policy (const char *routeList)
1439 slash = 32; 1530 slash = 32;
1440 cnt = 1531 cnt =
1441 SSCANF (&routeList[pos], 1532 SSCANF (&routeList[pos],
1442 "%u.%u.%u.%u;", 1533 "%u.%u.%u.%u",
1443 &temps[0], 1534 &temps[0],
1444 &temps[1], 1535 &temps[1],
1445 &temps[2], 1536 &temps[2],
@@ -1453,6 +1544,7 @@ GNUNET_STRINGS_parse_ipv4_policy (const char *routeList)
1453 _("Invalid format for IP: `%s'\n"), 1544 _("Invalid format for IP: `%s'\n"),
1454 &routeList[pos]); 1545 &routeList[pos]);
1455 GNUNET_free (result); 1546 GNUNET_free (result);
1547 GNUNET_free (routeList);
1456 return NULL; 1548 return NULL;
1457 } 1549 }
1458 result[i].network.s_addr = 1550 result[i].network.s_addr =
@@ -1465,9 +1557,7 @@ GNUNET_STRINGS_parse_ipv4_policy (const char *routeList)
1465 slash--; 1557 slash--;
1466 } 1558 }
1467 result[i].netmask.s_addr = htonl (result[i].netmask.s_addr); 1559 result[i].netmask.s_addr = htonl (result[i].netmask.s_addr);
1468 while (routeList[pos] != ';') 1560 pos = end + 1;
1469 pos++;
1470 pos++;
1471 i++; 1561 i++;
1472 continue; 1562 continue;
1473 } 1563 }
@@ -1475,6 +1565,7 @@ GNUNET_STRINGS_parse_ipv4_policy (const char *routeList)
1475 _("Invalid format for IP: `%s'\n"), 1565 _("Invalid format for IP: `%s'\n"),
1476 &routeList[pos]); 1566 &routeList[pos]);
1477 GNUNET_free (result); 1567 GNUNET_free (result);
1568 GNUNET_free (routeList);
1478 return NULL; /* error */ 1569 return NULL; /* error */
1479 } 1570 }
1480 if (pos < strlen (routeList)) 1571 if (pos < strlen (routeList))
@@ -1483,18 +1574,21 @@ GNUNET_STRINGS_parse_ipv4_policy (const char *routeList)
1483 _("Invalid format for IP: `%s'\n"), 1574 _("Invalid format for IP: `%s'\n"),
1484 &routeList[pos]); 1575 &routeList[pos]);
1485 GNUNET_free (result); 1576 GNUNET_free (result);
1577 GNUNET_free (routeList);
1486 return NULL; /* oops */ 1578 return NULL; /* oops */
1487 } 1579 }
1580 GNUNET_free (routeList);
1488 return result; /* ok */ 1581 return result; /* ok */
1489} 1582}
1490 1583
1491 1584
1492/** 1585/**
1493 * Parse an IPv6 network policy. The argument specifies a list of 1586 * Parse an IPv6 network policy. The argument specifies a list of
1494 * subnets. The format is <tt>[network/netmask;]*</tt> (no whitespace, 1587 * subnets. The format is <tt>(network[/netmask[:SPORT[-DPORT]]];)*</tt>
1495 * must be terminated with a semicolon). The network must be given in 1588 * (no whitespace, must be terminated with a semicolon). The network
1496 * colon-hex notation. The netmask must be given in CIDR notation 1589 * must be given in colon-hex notation. The netmask must be given in
1497 * (/16) or can be omitted to specify a single host. 1590 * CIDR notation (/16) or can be omitted to specify a single host.
1591 * Note that the netmask is mandatory if ports are specified.
1498 * 1592 *
1499 * @param routeListX a string specifying the policy 1593 * @param routeListX a string specifying the policy
1500 * @return the converted list, 0-terminated, NULL if the synatx is flawed 1594 * @return the converted list, 0-terminated, NULL if the synatx is flawed
@@ -1514,6 +1608,7 @@ GNUNET_STRINGS_parse_ipv6_policy (const char *routeListX)
1514 unsigned int bits; 1608 unsigned int bits;
1515 unsigned int off; 1609 unsigned int off;
1516 int save; 1610 int save;
1611 int colon;
1517 1612
1518 if (NULL == routeListX) 1613 if (NULL == routeListX)
1519 return NULL; 1614 return NULL;
@@ -1545,19 +1640,36 @@ GNUNET_STRINGS_parse_ipv6_policy (const char *routeListX)
1545 slash = pos; 1640 slash = pos;
1546 while ((slash >= start) && (routeList[slash] != '/')) 1641 while ((slash >= start) && (routeList[slash] != '/'))
1547 slash--; 1642 slash--;
1643
1548 if (slash < start) 1644 if (slash < start)
1549 { 1645 {
1550 memset (&result[i].netmask, 0xFF, sizeof (struct in6_addr)); 1646 memset (&result[i].netmask,
1647 0xFF,
1648 sizeof (struct in6_addr));
1551 slash = pos; 1649 slash = pos;
1552 } 1650 }
1553 else 1651 else
1554 { 1652 {
1555 routeList[pos] = '\0'; 1653 routeList[pos] = '\0';
1654 for (colon = pos; ':' != routeList[colon]; colon--)
1655 if ('/' == routeList[colon])
1656 break;
1657 if (':' == routeList[colon])
1658 {
1659 routeList[colon] = '\0';
1660 if (GNUNET_OK != parse_port_policy (&routeList[colon + 1],
1661 &result[i].pp))
1662 {
1663 GNUNET_free (result);
1664 GNUNET_free (routeList);
1665 return NULL;
1666 }
1667 }
1556 ret = inet_pton (AF_INET6, &routeList[slash + 1], &result[i].netmask); 1668 ret = inet_pton (AF_INET6, &routeList[slash + 1], &result[i].netmask);
1557 if (ret <= 0) 1669 if (ret <= 0)
1558 { 1670 {
1559 save = errno; 1671 save = errno;
1560 if ((1 != SSCANF (&routeList[slash + 1], "%u", &bits)) || (bits >= 128)) 1672 if ((1 != SSCANF (&routeList[slash + 1], "%u", &bits)) || (bits > 128))
1561 { 1673 {
1562 if (0 == ret) 1674 if (0 == ret)
1563 LOG (GNUNET_ERROR_TYPE_ERROR, 1675 LOG (GNUNET_ERROR_TYPE_ERROR,
diff --git a/src/vpn/gnunet-service-vpn.c b/src/vpn/gnunet-service-vpn.c
index bba321f8c..edb70f5e0 100644
--- a/src/vpn/gnunet-service-vpn.c
+++ b/src/vpn/gnunet-service-vpn.c
@@ -803,13 +803,11 @@ create_tunnel_to_destination (struct DestinationTunnel *dt,
803 char address[GNUNET_TUN_IPV4_REGEXLEN]; 803 char address[GNUNET_TUN_IPV4_REGEXLEN];
804 804
805 GNUNET_TUN_ipv4toregexsearch (&dt->destination->details.exit_destination.ip.v4, 805 GNUNET_TUN_ipv4toregexsearch (&dt->destination->details.exit_destination.ip.v4,
806 "255.255.255.255", 806 dt->destination_port,
807 address); 807 address);
808 GNUNET_asprintf (&policy, "%s%s%s:%u", 808 GNUNET_asprintf (&policy, "%s%s",
809 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX, 809 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
810 "4", 810 address);
811 address,
812 (unsigned int) dt->destination_port);
813 break; 811 break;
814 } 812 }
815 case AF_INET6: 813 case AF_INET6:
@@ -817,12 +815,11 @@ create_tunnel_to_destination (struct DestinationTunnel *dt,
817 char address[GNUNET_TUN_IPV6_REGEXLEN]; 815 char address[GNUNET_TUN_IPV6_REGEXLEN];
818 816
819 GNUNET_TUN_ipv6toregexsearch (&dt->destination->details.exit_destination.ip.v6, 817 GNUNET_TUN_ipv6toregexsearch (&dt->destination->details.exit_destination.ip.v6,
820 128, address); 818 dt->destination_port,
821 GNUNET_asprintf (&policy, "%s%s%s:%u", 819 address);
820 GNUNET_asprintf (&policy, "%s%s",
822 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX, 821 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
823 "6", 822 address);
824 address,
825 (unsigned int) dt->destination_port);
826 break; 823 break;
827 } 824 }
828 default: 825 default: