GNUnet  0.10.x
regex.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet
3  Copyright (C) 2012, 2013, 2015 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
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  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19 */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_tun_lib.h"
29 
33 #define DOT "(0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F)"
34 
35 
44 void
45 GNUNET_TUN_ipv4toregexsearch (const struct in_addr *ip,
46  uint16_t port,
47  char *rxstr)
48 {
49  GNUNET_snprintf (rxstr,
51  "4-%04X-%08X",
52  (unsigned int) port,
53  ntohl (ip->s_addr));
54 }
55 
56 
65 void
66 GNUNET_TUN_ipv6toregexsearch (const struct in6_addr *ipv6,
67  uint16_t port,
68  char *rxstr)
69 {
70  const uint32_t *addr;
71 
72  addr = (const uint32_t *) ipv6;
73  GNUNET_snprintf (rxstr,
75  "6-%04X-%08X%08X%08X%08X",
76  (unsigned int) port,
77  ntohl (addr[0]),
78  ntohl (addr[1]),
79  ntohl (addr[2]),
80  ntohl (addr[3]));
81 }
82 
83 
90 static char *
92  uint8_t mask)
93 {
94  char *ret;
95 
96  value &= mask;
97  switch (mask)
98  {
99  case 0:
100  return GNUNET_strdup (DOT);
101  case 8:
102  GNUNET_asprintf (&ret,
103  "(%X|%X|%X|%X|%X|%X|%X|%X)",
104  value,
105  value + 1,
106  value + 2,
107  value + 3,
108  value + 4,
109  value + 5,
110  value + 6,
111  value + 7);
112  return ret;
113  case 12:
114  GNUNET_asprintf (&ret,
115  "(%X|%X|%X|%X)",
116  value,
117  value + 1,
118  value + 2,
119  value + 3);
120  return ret;
121  case 14:
122  GNUNET_asprintf (&ret,
123  "(%X|%X)",
124  value,
125  value + 1);
126  return ret;
127  case 15:
128  GNUNET_asprintf (&ret,
129  "%X",
130  value);
131  return ret;
132  default:
134  _("Bad mask: %d\n"),
135  mask);
136  GNUNET_break (0);
137  return NULL;
138  }
139 }
140 
141 
148 static char *
149 num_to_regex (uint16_t value,
150  uint16_t mask)
151 {
152  const uint8_t *v = (const uint8_t *) &value;
153  const uint8_t *m = (const uint8_t *) &mask;
154  char *a;
155  char *b;
156  char *c;
157  char *d;
158  char *ret;
159 
160  a = nibble_to_regex (v[0] >> 4, m[0] >> 4);
161  b = nibble_to_regex (v[0] & 15, m[0] & 15);
162  c = nibble_to_regex (v[1] >> 4, m[1] >> 4);
163  d = nibble_to_regex (v[1] & 15, m[1] & 15);
164  ret = NULL;
165  if ( (NULL != a) &&
166  (NULL != b) &&
167  (NULL != c) &&
168  (NULL != d) )
169  GNUNET_asprintf (&ret,
170  "%s%s%s%s",
171  a, b, c, d);
176  return ret;
177 }
178 
179 
187 static int
188 needs_parens (const char *arg)
189 {
190  size_t off;
191  size_t len;
192  unsigned int op;
193 
194  op = 0;
195  len = strlen (arg);
196  for (off=0;off<len;off++)
197  {
198  switch (arg[off])
199  {
200  case '(':
201  op++;
202  break;
203  case ')':
204  GNUNET_assert (op > 0);
205  op--;
206  break;
207  case '|':
208  if (0 == op)
209  return GNUNET_YES;
210  break;
211  default:
212  break;
213  }
214  }
215  return GNUNET_NO;
216 }
217 
218 
229 static char *
230 compute_policy (unsigned int start,
231  unsigned int end,
232  unsigned int step,
233  const struct GNUNET_STRINGS_PortPolicy *pp)
234 {
235  unsigned int i;
236  char before[36]; /* 16 * 2 + 3 dots + 0-terminator */
237  char middlel[33]; /* 16 * 2 + 0-terminator */
238  char middleh[33]; /* 16 * 2 + 0-terminator */
239  char after[36]; /* 16 * 2 + 3 dots + 0-terminator */
240  char beforep[36+2]; /* 16 * 2 + 3 dots + 0-terminator + ()*/
241  char middlehp[33+2]; /* 16 * 2 + 0-terminator + () */
242  char middlelp[33+2]; /* 16 * 2 + 0-terminator + () */
243  char afterp[36+2]; /* 16 * 2 + 3 dots + 0-terminator + () */
244  char dots[5 * strlen (DOT)];
245  char buf[3];
246  char *middle;
247  char *ret;
248  unsigned int xstep;
249  char *recl;
250  char *rech;
251  char *reclp;
252  char *rechp;
253  unsigned int start_port;
254  unsigned int end_port;
255 
257  start_port = pp->start_port;
258  if (1 == start_port)
259  start_port = 0;
260  end_port = pp->end_port;
261  GNUNET_assert ((end - start) / step <= 0xF);
262  before[0] = '\0';
263  middlel[0] = '\0';
264  middleh[0] = '\0';
265  after[0] = '\0';
266  for (i=start;i<=end;i+=step)
267  {
268  GNUNET_snprintf (buf,
269  sizeof (buf),
270  "%X|",
271  (i - start) / step);
272  if (i / step < start_port / step)
273  strcat (before, buf);
274  else if (i / step > end_port / step)
275  strcat (after, buf);
276  else if (i / step == start_port / step)
277  strcat (middlel, buf);
278  else if (i / step == end_port / step)
279  strcat (middleh, buf);
280  }
281  if (strlen (before) > 0)
282  before[strlen (before)-1] = '\0';
283  if (strlen (middlel) > 0)
284  middlel[strlen (middlel)-1] = '\0';
285  if (strlen (middleh) > 0)
286  middleh[strlen (middleh)-1] = '\0';
287  if (strlen (after) > 0)
288  after[strlen (after)-1] = '\0';
289  if (needs_parens (before))
290  GNUNET_snprintf (beforep,
291  sizeof (beforep),
292  "(%s)",
293  before);
294  else
295  strcpy (beforep, before);
296  if (needs_parens (middlel))
297  GNUNET_snprintf (middlelp,
298  sizeof (middlelp),
299  "(%s)",
300  middlel);
301  else
302  strcpy (middlelp, middlel);
303  if (needs_parens (middleh))
304  GNUNET_snprintf (middlehp,
305  sizeof (middlehp),
306  "(%s)",
307  middleh);
308  else
309  strcpy (middlehp, middleh);
310  if (needs_parens (after))
311  GNUNET_snprintf (afterp,
312  sizeof (afterp),
313  "(%s)",
314  after);
315  else
316  strcpy (afterp, after);
317  dots[0] = '\0';
318  for (xstep=step/16;xstep>0;xstep/=16)
319  strcat (dots, DOT);
320  if (step >= 16)
321  {
322  if (strlen (middlel) > 0)
323  recl = compute_policy ((start_port / step) * step,
324  (start_port / step) * step + step - 1,
325  step / 16,
326  pp);
327  else
328  recl = GNUNET_strdup ("");
329  if (strlen (middleh) > 0)
330  rech = compute_policy ((end_port / step) * step,
331  (end_port / step) * step + step - 1,
332  step / 16,
333  pp);
334  else
335  rech = GNUNET_strdup ("");
336  }
337  else
338  {
339  recl = GNUNET_strdup ("");
340  rech = GNUNET_strdup ("");
341  middlel[0] = '\0';
342  middlelp[0] = '\0';
343  middleh[0] = '\0';
344  middlehp[0] = '\0';
345  }
346  if (needs_parens (recl))
347  GNUNET_asprintf (&reclp,
348  "(%s)",
349  recl);
350  else
351  reclp = GNUNET_strdup (recl);
352  if (needs_parens (rech))
353  GNUNET_asprintf (&rechp,
354  "(%s)",
355  rech);
356  else
357  rechp = GNUNET_strdup (rech);
358 
359  if ( (strlen (middleh) > 0) &&
360  (strlen (rech) > 0) &&
361  (strlen (middlel) > 0) &&
362  (strlen (recl) > 0) )
363  {
364  GNUNET_asprintf (&middle,
365  "%s%s|%s%s",
366  middlel,
367  reclp,
368  middleh,
369  rechp);
370  }
371  else if ( (strlen (middleh) > 0) &&
372  (strlen (rech) > 0) )
373  {
374  GNUNET_asprintf (&middle,
375  "%s%s",
376  middleh,
377  rechp);
378  }
379  else if ( (strlen (middlel) > 0) &&
380  (strlen (recl) > 0) )
381  {
382  GNUNET_asprintf (&middle,
383  "%s%s",
384  middlel,
385  reclp);
386  }
387  else
388  {
389  middle = GNUNET_strdup ("");
390  }
391  if ( (strlen(before) > 0) &&
392  (strlen(after) > 0) )
393  {
394  if (strlen (dots) > 0)
395  {
396  if (strlen (middle) > 0)
397  GNUNET_asprintf (&ret,
398  "(%s%s|%s|%s%s)",
399  beforep, dots,
400  middle,
401  afterp, dots);
402  else
403  GNUNET_asprintf (&ret,
404  "(%s|%s)%s",
405  beforep,
406  afterp,
407  dots);
408  }
409  else
410  {
411  if (strlen (middle) > 0)
412  GNUNET_asprintf (&ret,
413  "(%s|%s|%s)",
414  before,
415  middle,
416  after);
417  else if (1 == step)
418  GNUNET_asprintf (&ret,
419  "%s|%s",
420  before,
421  after);
422  else
423  GNUNET_asprintf (&ret,
424  "(%s|%s)",
425  before,
426  after);
427  }
428  }
429  else if (strlen (before) > 0)
430  {
431  if (strlen (dots) > 0)
432  {
433  if (strlen (middle) > 0)
434  GNUNET_asprintf (&ret,
435  "(%s%s|%s)",
436  beforep, dots,
437  middle);
438  else
439  GNUNET_asprintf (&ret,
440  "%s%s",
441  beforep, dots);
442  }
443  else
444  {
445  if (strlen (middle) > 0)
446  GNUNET_asprintf (&ret,
447  "(%s|%s)",
448  before,
449  middle);
450  else
451  GNUNET_asprintf (&ret,
452  "%s",
453  before);
454  }
455  }
456  else if (strlen (after) > 0)
457  {
458  if (strlen (dots) > 0)
459  {
460  if (strlen (middle) > 0)
461  GNUNET_asprintf (&ret,
462  "(%s|%s%s)",
463  middle,
464  afterp, dots);
465  else
466  GNUNET_asprintf (&ret,
467  "%s%s",
468  afterp, dots);
469  }
470  else
471  {
472  if (strlen (middle) > 0)
473  GNUNET_asprintf (&ret,
474  "%s|%s",
475  middle,
476  after);
477  else
478  GNUNET_asprintf (&ret,
479  "%s",
480  after);
481  }
482  }
483  else if (strlen (middle) > 0)
484  {
485  GNUNET_asprintf (&ret,
486  "%s",
487  middle);
488  }
489  else
490  {
491  ret = GNUNET_strdup ("");
492  }
493  GNUNET_free (middle);
494  GNUNET_free (reclp);
495  GNUNET_free (rechp);
496  GNUNET_free (recl);
497  GNUNET_free (rech);
498  return ret;
499 }
500 
501 
511 static char *
513 {
514  char *reg;
515  char *ret;
516  char *pos;
517  unsigned int i;
518  unsigned int cnt;
519 
520  if ( (0 == pp->start_port) ||
521  ( (1 == pp->start_port) &&
522  (0xFFFF == pp->end_port) &&
523  (GNUNET_NO == pp->negate_portrange)) )
524  return GNUNET_strdup (DOT DOT DOT DOT);
525  if ( (pp->start_port == pp->end_port) &&
526  (GNUNET_NO == pp->negate_portrange))
527  {
528  GNUNET_asprintf (&ret,
529  "%04X",
530  pp->start_port);
531  return ret;
532  }
533  if (pp->end_port < pp->start_port)
534  return NULL;
535 
536  if (GNUNET_YES == pp->negate_portrange)
537  {
538  ret = compute_policy (0, 0xFFFF, 0x1000, pp);
539  }
540  else
541  {
542  cnt = pp->end_port - pp->start_port + 1;
543  reg = GNUNET_malloc (cnt * 5 + 1);
544  pos = reg;
545  for (i=1;i<=0xFFFF;i++)
546  {
547  if ( (i >= pp->start_port) && (i <= pp->end_port) )
548  {
549  if (pos == reg)
550  {
551  GNUNET_snprintf (pos,
552  5,
553  "%04X",
554  i);
555  }
556  else
557  {
558  GNUNET_snprintf (pos,
559  6,
560  "|%04X",
561  i);
562  }
563  pos += strlen (pos);
564  }
565  }
566  GNUNET_asprintf (&ret,
567  "(%s)",
568  reg);
569  GNUNET_free (reg);
570  }
571  return ret;
572 }
573 
574 
583 static char *
584 address_to_regex (const void *addr,
585  const void *mask,
586  size_t len)
587 {
588  const uint16_t *a = addr;
589  const uint16_t *m = mask;
590  char *ret;
591  char *tmp;
592  char *reg;
593  unsigned int i;
594 
595  ret = NULL;
596  GNUNET_assert (1 != (len % 2));
597  for (i=0;i<len / 2;i++)
598  {
599  reg = num_to_regex (a[i], m[i]);
600  if (NULL == reg)
601  {
602  GNUNET_free_non_null (ret);
603  return NULL;
604  }
605  if (NULL == ret)
606  {
607  ret = reg;
608  }
609  else
610  {
611  GNUNET_asprintf (&tmp,
612  "%s%s",
613  ret, reg);
614  GNUNET_free (ret);
615  GNUNET_free (reg);
616  ret = tmp;
617  }
618  }
619  return ret;
620 }
621 
622 
629 static char *
631 {
632  char *reg;
633  char *pp;
634  char *ret;
635 
636  reg = address_to_regex (&v4->network,
637  &v4->netmask,
638  sizeof (struct in_addr));
639  if (NULL == reg)
640  return NULL;
641  pp = port_to_regex (&v4->pp);
642  if (NULL == pp)
643  {
644  GNUNET_free (reg);
645  return NULL;
646  }
647  GNUNET_asprintf (&ret,
648  "4-%s-%s",
649  pp, reg);
650  GNUNET_free (pp);
651  GNUNET_free (reg);
652  return ret;
653 }
654 
655 
662 static char *
664 {
665  char *reg;
666  char *pp;
667  char *ret;
668 
669  reg = address_to_regex (&v6->network,
670  &v6->netmask,
671  sizeof (struct in6_addr));
672  if (NULL == reg)
673  return NULL;
674  pp = port_to_regex (&v6->pp);
675  if (NULL == pp)
676  {
677  GNUNET_free (reg);
678  return NULL;
679  }
680  GNUNET_asprintf (&ret,
681  "6-%s-%s",
682  pp, reg);
683  GNUNET_free (pp);
684  GNUNET_free (reg);
685  return ret;
686 }
687 
688 
698 char *
699 GNUNET_TUN_ipv4policy2regex (const char *policy)
700 {
702  char *reg;
703  char *tmp;
704  char *line;
705  unsigned int i;
706 
707  np = GNUNET_STRINGS_parse_ipv4_policy (policy);
708  if (NULL == np)
709  return NULL;
710  reg = NULL;
711  for (i=0; (0 == i) || (0 != np[i].network.s_addr); i++)
712  {
713  line = ipv4_to_regex (&np[i]);
714  if (NULL == line)
715  {
716  GNUNET_free_non_null (reg);
717  GNUNET_free (np);
718  return NULL;
719  }
720  if (NULL == reg)
721  {
722  reg = line;
723  }
724  else
725  {
726  GNUNET_asprintf (&tmp,
727  "%s|(%s)",
728  reg, line);
729  GNUNET_free (reg);
730  GNUNET_free (line);
731  reg = tmp;
732  }
733  if (0 == np[i].network.s_addr)
734  break;
735  }
736  GNUNET_free (np);
737  return reg;
738 }
739 
740 
750 char *
751 GNUNET_TUN_ipv6policy2regex (const char *policy)
752 {
753  struct in6_addr zero;
755  char *reg;
756  char *tmp;
757  char *line;
758  unsigned int i;
759 
760  np = GNUNET_STRINGS_parse_ipv6_policy (policy);
761  if (NULL == np)
762  return NULL;
763  reg = NULL;
764  memset (&zero, 0, sizeof (struct in6_addr));
765  for (i=0; (0 == i) || (0 != memcmp (&zero, &np[i].network, sizeof (struct in6_addr))); i++)
766  {
767  line = ipv6_to_regex (&np[i]);
768  if (NULL == line)
769  {
770  GNUNET_free_non_null (reg);
771  GNUNET_free (np);
772  return NULL;
773  }
774  if (NULL == reg)
775  {
776  reg = line;
777  }
778  else
779  {
780  GNUNET_asprintf (&tmp,
781  "%s|(%s)",
782  reg, line);
783  GNUNET_free (reg);
784  GNUNET_free (line);
785  reg = tmp;
786  }
787  if (0 == memcmp (&zero, &np[i].network, sizeof (struct in6_addr)))
788  break;
789  }
790  GNUNET_free (np);
791  return reg;
792 }
793 
794 
803 void
805  struct GNUNET_HashCode *hc)
806 {
807  GNUNET_CRYPTO_hash (service_name,
808  strlen (service_name),
809  hc);
810 }
811 
812 
822 void
824  uint16_t ip_port,
825  struct GNUNET_HashCode *cadet_port)
826 {
827  uint16_t be_port = htons (ip_port);
828 
829  *cadet_port = *desc;
830  GNUNET_memcpy (cadet_port,
831  &be_port,
832  sizeof (uint16_t));
833 }
834 
835 
836 /* end of regex.c */
struct GNUNET_STRINGS_IPv4NetworkPolicy * GNUNET_STRINGS_parse_ipv4_policy(const char *routeListX)
Parse an IPv4 network policy.
Definition: strings.c:1654
char * GNUNET_TUN_ipv4policy2regex(const char *policy)
Convert an exit policy to a regular expression.
Definition: regex.c:699
static int end
Set if we are to shutdown all services (including ARM).
Definition: gnunet-arm.c:34
#define DOT
&#39;wildcard&#39;, matches all possible values (for HEX encoding).
Definition: regex.c:33
struct GNUNET_STRINGS_PortPolicy pp
Policy for port access.
static char * ipv6_to_regex(const struct GNUNET_STRINGS_IPv6NetworkPolicy *v6)
Convert a single line of an IPv4 policy to a regular expression.
Definition: regex.c:663
int GNUNET_snprintf(char *buf, size_t size, const char *format,...)
Like snprintf, just aborts if the buffer is of insufficient size.
uint16_t start_port
Starting port range (0 if none given).
struct GNUNET_STRINGS_IPv6NetworkPolicy * GNUNET_STRINGS_parse_ipv6_policy(const char *routeListX)
Parse an IPv6 network policy.
Definition: strings.c:1854
static int start
Set if we are to start default services (including ARM).
Definition: gnunet-arm.c:39
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
network in CIDR notation for IPV6.
void GNUNET_TUN_ipv4toregexsearch(const struct in_addr *ip, uint16_t port, char *rxstr)
Create a regex in rxstr from the given ip and netmask.
Definition: regex.c:45
int negate_portrange
GNUNET_YES if the port range should be negated ("!" in policy).
struct in_addr netmask
IPv4 netmask.
#define GNUNET_NO
Definition: gnunet_common.h:81
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
static char * nibble_to_regex(uint8_t value, uint8_t mask)
Convert the given 4-bit (!) number to a regex.
Definition: regex.c:91
static int ret
Final status code.
Definition: gnunet-arm.c:89
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
struct in6_addr netmask
IPv6 netmask.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
struct in_addr network
IPv4 address.
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:99
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
#define GNUNET_memcpy(dst, src, n)
static char * line
Desired phone line (string to be converted to a hash).
static char * value
Value of the record to add/remove.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:44
static char * service_name
Option -s: service name (hash to get service descriptor)
Definition: gnunet-vpn.c:51
IPV4 network in CIDR notation.
static char buf[2048]
void GNUNET_TUN_service_name_to_hash(const char *service_name, struct GNUNET_HashCode *hc)
Hash the service name of a hosted service to the hash code that is used to identify the service on th...
Definition: regex.c:804
A 512-bit hashcode.
void GNUNET_TUN_ipv6toregexsearch(const struct in6_addr *ipv6, uint16_t port, char *rxstr)
Create a regex in rxstr from the given ipv6 and prefixlen.
Definition: regex.c:66
static char * address_to_regex(const void *addr, const void *mask, size_t len)
Convert an address (IPv4 or IPv6) to a regex.
Definition: regex.c:584
void GNUNET_TUN_compute_service_cadet_port(const struct GNUNET_HashCode *desc, uint16_t ip_port, struct GNUNET_HashCode *cadet_port)
Compute the CADET port given a service descriptor (returned from GNUNET_TUN_service_name_to_hash) and...
Definition: regex.c:823
static char * port_to_regex(const struct GNUNET_STRINGS_PortPolicy *pp)
Convert a port policy to a regular expression.
Definition: regex.c:512
#define GNUNET_TUN_IPV4_REGEXLEN
Maximum regex string length for use with GNUNET_TUN_ipv4toregexsearch.
uint16_t end_port
End of port range (0 if none given).
static char * compute_policy(unsigned int start, unsigned int end, unsigned int step, const struct GNUNET_STRINGS_PortPolicy *pp)
Compute port policy for the given range of port numbers.
Definition: regex.c:230
static uint16_t port
Port number.
Definition: gnunet-bcd.c:79
static int needs_parens(const char *arg)
Do we need to put parents around the given argument?
Definition: regex.c:188
char * GNUNET_TUN_ipv6policy2regex(const char *policy)
Convert an exit policy to a regular expression.
Definition: regex.c:751
#define GNUNET_log(kind,...)
struct GNUNET_STRINGS_PortPolicy pp
Policy for port access.
static struct GNUNET_CADET_Port * cadet_port
Listen port for incoming requests.
struct in6_addr network
IPv6 address.
static char * ipv4_to_regex(const struct GNUNET_STRINGS_IPv4NetworkPolicy *v4)
Convert a single line of an IPv4 policy to a regular expression.
Definition: regex.c:630
#define GNUNET_YES
Definition: gnunet_common.h:80
static struct GNUNET_ARM_Operation * op
Current operation.
Definition: gnunet-arm.c:139
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_TUN_IPV6_REGEXLEN
Maximum regex string length for use with GNUNET_TUN_ipv6toregexsearch.
#define GNUNET_free(ptr)
Wrapper around free.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
static char * num_to_regex(uint16_t value, uint16_t mask)
Convert the given 16-bit number to a regex.
Definition: regex.c:149
static int ipv6
Option -6: IPv6 requested.
Definition: gnunet-vpn.c:66