2 This file is part of GNUnet
3 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
21 * @file src/tun/regex.c
22 * @brief functions to convert IP networks to regexes
23 * @author Maximilian Szengel
24 * @author Christian Grothoff
27 #include "gnunet_util_lib.h"
28 #include "gnunet_tun_lib.h"
32 * Create a regex in @a rxstr from the given @a ip and @a netmask.
34 * @param ip IPv4 representation.
35 * @param port destination port
36 * @param rxstr generated regex, must be at least #GNUNET_TUN_IPV4_REGEXLEN
40 GNUNET_TUN_ipv4toregexsearch (const struct in_addr *ip,
44 GNUNET_snprintf (rxstr,
45 GNUNET_TUN_IPV4_REGEXLEN,
53 * Create a regex in @a rxstr from the given @a ipv6 and @a prefixlen.
55 * @param ipv6 IPv6 representation.
56 * @param port destination port
57 * @param rxstr generated regex, must be at least #GNUNET_TUN_IPV6_REGEXLEN
61 GNUNET_TUN_ipv6toregexsearch (const struct in6_addr *ipv6,
67 addr = (const uint32_t *) ipv6;
68 GNUNET_snprintf (rxstr,
69 GNUNET_TUN_IPV6_REGEXLEN,
70 "6-%04X-%08X%08X%08X%08X",
80 * Convert the given 4-bit (!) number to a regex.
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)?
86 nibble_to_regex (uint8_t value,
95 return GNUNET_strdup ("."); /* wildcard */
97 GNUNET_asprintf (&ret,
98 "(%X|%X|%X|%X|%X|%X|%X|%X)",
109 GNUNET_asprintf (&ret,
117 GNUNET_asprintf (&ret,
123 GNUNET_asprintf (&ret,
128 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
138 * Convert the given 16-bit number to a regex.
140 * @param value the value
141 * @param mask which bits in value are wildcards (any value)?
144 num_to_regex (uint16_t value,
147 const uint8_t *v = (const uint8_t *) &value;
148 const uint8_t *m = (const uint8_t *) &mask;
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);
164 GNUNET_asprintf (&ret,
167 GNUNET_free_non_null (a);
168 GNUNET_free_non_null (b);
169 GNUNET_free_non_null (c);
170 GNUNET_free_non_null (d);
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.
181 * @param pp port policy to convert
182 * @return NULL on error
185 port_to_regex (const struct GNUNET_STRINGS_PortPolicy *pp)
193 if ( (0 == pp->start_port) ||
194 ( (1 == pp->start_port) &&
195 (0xFFFF == pp->end_port) &&
196 (GNUNET_NO == pp->negate_portrange)) )
197 return GNUNET_strdup ("....");
198 if ( (pp->start_port == pp->end_port) &&
199 (GNUNET_NO == pp->negate_portrange))
201 GNUNET_asprintf (&ret,
206 if (pp->end_port < pp->start_port)
208 cnt = pp->end_port - pp->start_port + 1;
209 if (GNUNET_YES == pp->negate_portrange)
211 reg = GNUNET_malloc (cnt * 5 + 1);
213 for (i=1;i<=0xFFFF;i++)
215 if ( ( (i >= pp->start_port) && (i <= pp->end_port) ) ^
216 (GNUNET_YES == pp->negate_portrange) )
220 GNUNET_snprintf (pos,
227 GNUNET_snprintf (pos,
235 GNUNET_asprintf (&ret,
244 * Convert an address (IPv4 or IPv6) to a regex.
246 * @param addr address
247 * @param mask network mask
248 * @param len number of bytes in @a addr and @a mask
249 * @return NULL on error, otherwise regex for the address
252 address_to_regex (const void *addr,
256 const uint16_t *a = addr;
257 const uint16_t *m = mask;
264 GNUNET_assert (1 != (len % 2));
265 for (i=0;i<len / 2;i++)
267 reg = num_to_regex (a[i], m[i]);
270 GNUNET_free_non_null (ret);
279 GNUNET_asprintf (&tmp,
292 * Convert a single line of an IPv4 policy to a regular expression.
294 * @param v4 line to convert
295 * @return NULL on error
298 ipv4_to_regex (const struct GNUNET_STRINGS_IPv4NetworkPolicy *v4)
304 reg = address_to_regex (&v4->network,
306 sizeof (struct in_addr));
309 pp = port_to_regex (&v4->pp);
315 GNUNET_asprintf (&ret,
325 * Convert a single line of an IPv4 policy to a regular expression.
327 * @param v6 line to convert
328 * @return NULL on error
331 ipv6_to_regex (const struct GNUNET_STRINGS_IPv6NetworkPolicy *v6)
337 reg = address_to_regex (&v6->network,
339 sizeof (struct in6_addr));
342 pp = port_to_regex (&v6->pp);
348 GNUNET_asprintf (&ret,
358 * Convert an exit policy to a regular expression. The exit policy
359 * specifies a set of subnets this peer is willing to serve as an
360 * exit for; the resulting regular expression will match the
361 * IPv4 address strings as returned by 'GNUNET_TUN_ipv4toregexsearch'.
363 * @param policy exit policy specification
364 * @return regular expression, NULL on error
367 GNUNET_TUN_ipv4policy2regex (const char *policy)
369 struct GNUNET_STRINGS_IPv4NetworkPolicy *np;
375 np = GNUNET_STRINGS_parse_ipv4_policy (policy);
379 for (i=0; (0 == i) || (0 != np[i].network.s_addr); i++)
381 line = ipv4_to_regex (&np[i]);
384 GNUNET_free_non_null (reg);
393 GNUNET_asprintf (&tmp,
400 if (0 == np[i].network.s_addr)
408 * Convert an exit policy to a regular expression. The exit policy
409 * specifies a set of subnets this peer is willing to serve as an
410 * exit for; the resulting regular expression will match the
411 * IPv6 address strings as returned by 'GNUNET_TUN_ipv6toregexsearch'.
413 * @param policy exit policy specification
414 * @return regular expression, NULL on error
417 GNUNET_TUN_ipv6policy2regex (const char *policy)
419 struct in6_addr zero;
420 struct GNUNET_STRINGS_IPv6NetworkPolicy *np;
426 np = GNUNET_STRINGS_parse_ipv6_policy (policy);
430 memset (&zero, 0, sizeof (struct in6_addr));
431 for (i=0; (0 == i) || (0 != memcmp (&zero, &np[i].network, sizeof (struct in6_addr))); i++)
433 line = ipv6_to_regex (&np[i]);
436 GNUNET_free_non_null (reg);
445 GNUNET_asprintf (&tmp,
452 if (0 == memcmp (&zero, &np[i].network, sizeof (struct in6_addr)))