GNUnet  0.19.2
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  */
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 
33 #define DOT "(0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F)"
34 
35 
36 void
37 GNUNET_TUN_ipv4toregexsearch (const struct in_addr *ip,
38  uint16_t port,
39  char *rxstr)
40 {
41  GNUNET_snprintf (rxstr,
43  "4-%04X-%08X",
44  (unsigned int) port,
45  ntohl (ip->s_addr));
46 }
47 
48 
49 void
50 GNUNET_TUN_ipv6toregexsearch (const struct in6_addr *ipv6,
51  uint16_t port,
52  char *rxstr)
53 {
54  const uint32_t *addr;
55 
56  addr = (const uint32_t *) ipv6;
57  GNUNET_snprintf (rxstr,
59  "6-%04X-%08X%08X%08X%08X",
60  (unsigned int) port,
61  ntohl (addr[0]),
62  ntohl (addr[1]),
63  ntohl (addr[2]),
64  ntohl (addr[3]));
65 }
66 
67 
74 static char *
76  uint8_t mask)
77 {
78  char *ret;
79 
80  value &= mask;
81  switch (mask)
82  {
83  case 0:
84  return GNUNET_strdup (DOT);
85 
86  case 8:
88  "(%X|%X|%X|%X|%X|%X|%X|%X)",
89  value,
90  value + 1,
91  value + 2,
92  value + 3,
93  value + 4,
94  value + 5,
95  value + 6,
96  value + 7);
97  return ret;
98 
99  case 12:
101  "(%X|%X|%X|%X)",
102  value,
103  value + 1,
104  value + 2,
105  value + 3);
106  return ret;
107 
108  case 14:
110  "(%X|%X)",
111  value,
112  value + 1);
113  return ret;
114 
115  case 15:
117  "%X",
118  value);
119  return ret;
120 
121  default:
123  _ ("Bad mask: %d\n"),
124  mask);
125  GNUNET_break (0);
126  return NULL;
127  }
128 }
129 
130 
137 static char *
138 num_to_regex (uint16_t value,
139  uint16_t mask)
140 {
141  const uint8_t *v = (const uint8_t *) &value;
142  const uint8_t *m = (const uint8_t *) &mask;
143  char *a;
144  char *b;
145  char *c;
146  char *d;
147  char *ret;
148 
149  a = nibble_to_regex (v[0] >> 4, m[0] >> 4);
150  b = nibble_to_regex (v[0] & 15, m[0] & 15);
151  c = nibble_to_regex (v[1] >> 4, m[1] >> 4);
152  d = nibble_to_regex (v[1] & 15, m[1] & 15);
153  ret = NULL;
154  if ((NULL != a) &&
155  (NULL != b) &&
156  (NULL != c) &&
157  (NULL != d))
159  "%s%s%s%s",
160  a, b, c, d);
161  GNUNET_free (a);
162  GNUNET_free (b);
163  GNUNET_free (c);
164  GNUNET_free (d);
165  return ret;
166 }
167 
168 
176 static int
177 needs_parens (const char *arg)
178 {
179  size_t off;
180  size_t len;
181  unsigned int op;
182 
183  op = 0;
184  len = strlen (arg);
185  for (off = 0; off < len; off++)
186  {
187  switch (arg[off])
188  {
189  case '(':
190  op++;
191  break;
192 
193  case ')':
194  GNUNET_assert (op > 0);
195  op--;
196  break;
197 
198  case '|':
199  if (0 == op)
200  return GNUNET_YES;
201  break;
202 
203  default:
204  break;
205  }
206  }
207  return GNUNET_NO;
208 }
209 
210 
221 static char *
222 compute_policy (unsigned int start,
223  unsigned int end,
224  unsigned int step,
225  const struct GNUNET_STRINGS_PortPolicy *pp)
226 {
227  unsigned int i;
228  char before[36]; /* 16 * 2 + 3 dots + 0-terminator */
229  char middlel[33]; /* 16 * 2 + 0-terminator */
230  char middleh[33]; /* 16 * 2 + 0-terminator */
231  char after[36]; /* 16 * 2 + 3 dots + 0-terminator */
232  char beforep[36 + 2]; /* 16 * 2 + 3 dots + 0-terminator + ()*/
233  char middlehp[33 + 2]; /* 16 * 2 + 0-terminator + () */
234  char middlelp[33 + 2]; /* 16 * 2 + 0-terminator + () */
235  char afterp[36 + 2]; /* 16 * 2 + 3 dots + 0-terminator + () */
236  char dots[5 * strlen (DOT)];
237  char buf[3];
238  char *middle;
239  char *ret;
240  unsigned int xstep;
241  char *recl;
242  char *rech;
243  char *reclp;
244  char *rechp;
245  unsigned int start_port;
246  unsigned int end_port;
247 
249  start_port = pp->start_port;
250  if (1 == start_port)
251  start_port = 0;
252  end_port = pp->end_port;
253  GNUNET_assert ((end - start) / step <= 0xF);
254  before[0] = '\0';
255  middlel[0] = '\0';
256  middleh[0] = '\0';
257  after[0] = '\0';
258  for (i = start; i <= end; i += step)
259  {
261  sizeof(buf),
262  "%X|",
263  (i - start) / step);
264  if (i / step < start_port / step)
265  strcat (before, buf);
266  else if (i / step > end_port / step)
267  strcat (after, buf);
268  else if (i / step == start_port / step)
269  strcat (middlel, buf);
270  else if (i / step == end_port / step)
271  strcat (middleh, buf);
272  }
273  if (strlen (before) > 0)
274  before[strlen (before) - 1] = '\0';
275  if (strlen (middlel) > 0)
276  middlel[strlen (middlel) - 1] = '\0';
277  if (strlen (middleh) > 0)
278  middleh[strlen (middleh) - 1] = '\0';
279  if (strlen (after) > 0)
280  after[strlen (after) - 1] = '\0';
281  if (needs_parens (before))
282  GNUNET_snprintf (beforep,
283  sizeof(beforep),
284  "(%s)",
285  before);
286  else
287  strcpy (beforep, before);
288  if (needs_parens (middlel))
289  GNUNET_snprintf (middlelp,
290  sizeof(middlelp),
291  "(%s)",
292  middlel);
293  else
294  strcpy (middlelp, middlel);
295  if (needs_parens (middleh))
296  GNUNET_snprintf (middlehp,
297  sizeof(middlehp),
298  "(%s)",
299  middleh);
300  else
301  strcpy (middlehp, middleh);
302  if (needs_parens (after))
303  GNUNET_snprintf (afterp,
304  sizeof(afterp),
305  "(%s)",
306  after);
307  else
308  strcpy (afterp, after);
309  dots[0] = '\0';
310  for (xstep = step / 16; xstep > 0; xstep /= 16)
311  strcat (dots, DOT);
312  if (step >= 16)
313  {
314  if (strlen (middlel) > 0)
315  recl = compute_policy ((start_port / step) * step,
316  (start_port / step) * step + step - 1,
317  step / 16,
318  pp);
319  else
320  recl = GNUNET_strdup ("");
321  if (strlen (middleh) > 0)
322  rech = compute_policy ((end_port / step) * step,
323  (end_port / step) * step + step - 1,
324  step / 16,
325  pp);
326  else
327  rech = GNUNET_strdup ("");
328  }
329  else
330  {
331  recl = GNUNET_strdup ("");
332  rech = GNUNET_strdup ("");
333  middlel[0] = '\0';
334  middlelp[0] = '\0';
335  middleh[0] = '\0';
336  middlehp[0] = '\0';
337  }
338  if (needs_parens (recl))
339  GNUNET_asprintf (&reclp,
340  "(%s)",
341  recl);
342  else
343  reclp = GNUNET_strdup (recl);
344  if (needs_parens (rech))
345  GNUNET_asprintf (&rechp,
346  "(%s)",
347  rech);
348  else
349  rechp = GNUNET_strdup (rech);
350 
351  if ((strlen (middleh) > 0) &&
352  (strlen (rech) > 0) &&
353  (strlen (middlel) > 0) &&
354  (strlen (recl) > 0))
355  {
356  GNUNET_asprintf (&middle,
357  "%s%s|%s%s",
358  middlel,
359  reclp,
360  middleh,
361  rechp);
362  }
363  else if ((strlen (middleh) > 0) &&
364  (strlen (rech) > 0))
365  {
366  GNUNET_asprintf (&middle,
367  "%s%s",
368  middleh,
369  rechp);
370  }
371  else if ((strlen (middlel) > 0) &&
372  (strlen (recl) > 0))
373  {
374  GNUNET_asprintf (&middle,
375  "%s%s",
376  middlel,
377  reclp);
378  }
379  else
380  {
381  middle = GNUNET_strdup ("");
382  }
383  if ((strlen (before) > 0) &&
384  (strlen (after) > 0))
385  {
386  if (strlen (dots) > 0)
387  {
388  if (strlen (middle) > 0)
390  "(%s%s|%s|%s%s)",
391  beforep, dots,
392  middle,
393  afterp, dots);
394  else
396  "(%s|%s)%s",
397  beforep,
398  afterp,
399  dots);
400  }
401  else
402  {
403  if (strlen (middle) > 0)
405  "(%s|%s|%s)",
406  before,
407  middle,
408  after);
409  else if (1 == step)
411  "%s|%s",
412  before,
413  after);
414  else
416  "(%s|%s)",
417  before,
418  after);
419  }
420  }
421  else if (strlen (before) > 0)
422  {
423  if (strlen (dots) > 0)
424  {
425  if (strlen (middle) > 0)
427  "(%s%s|%s)",
428  beforep, dots,
429  middle);
430  else
432  "%s%s",
433  beforep, dots);
434  }
435  else
436  {
437  if (strlen (middle) > 0)
439  "(%s|%s)",
440  before,
441  middle);
442  else
444  "%s",
445  before);
446  }
447  }
448  else if (strlen (after) > 0)
449  {
450  if (strlen (dots) > 0)
451  {
452  if (strlen (middle) > 0)
454  "(%s|%s%s)",
455  middle,
456  afterp, dots);
457  else
459  "%s%s",
460  afterp, dots);
461  }
462  else
463  {
464  if (strlen (middle) > 0)
466  "%s|%s",
467  middle,
468  after);
469  else
471  "%s",
472  after);
473  }
474  }
475  else if (strlen (middle) > 0)
476  {
478  "%s",
479  middle);
480  }
481  else
482  {
483  ret = GNUNET_strdup ("");
484  }
485  GNUNET_free (middle);
486  GNUNET_free (reclp);
487  GNUNET_free (rechp);
488  GNUNET_free (recl);
489  GNUNET_free (rech);
490  return ret;
491 }
492 
493 
503 static char *
505 {
506  char *reg;
507  char *ret;
508  char *pos;
509  unsigned int i;
510  unsigned int cnt;
511 
512  if ((0 == pp->start_port) ||
513  ((1 == pp->start_port) &&
514  (0xFFFF == pp->end_port) &&
515  (GNUNET_NO == pp->negate_portrange)))
516  return GNUNET_strdup (DOT DOT DOT DOT);
517  if ((pp->start_port == pp->end_port) &&
518  (GNUNET_NO == pp->negate_portrange))
519  {
521  "%04X",
522  pp->start_port);
523  return ret;
524  }
525  if (pp->end_port < pp->start_port)
526  return NULL;
527 
528  if (GNUNET_YES == pp->negate_portrange)
529  {
530  ret = compute_policy (0, 0xFFFF, 0x1000, pp);
531  }
532  else
533  {
534  cnt = pp->end_port - pp->start_port + 1;
535  reg = GNUNET_malloc (cnt * 5 + 1);
536  pos = reg;
537  for (i = 1; i <= 0xFFFF; i++)
538  {
539  if ((i >= pp->start_port) && (i <= pp->end_port))
540  {
541  if (pos == reg)
542  {
543  GNUNET_snprintf (pos,
544  5,
545  "%04X",
546  i);
547  }
548  else
549  {
550  GNUNET_snprintf (pos,
551  6,
552  "|%04X",
553  i);
554  }
555  pos += strlen (pos);
556  }
557  }
559  "(%s)",
560  reg);
561  GNUNET_free (reg);
562  }
563  return ret;
564 }
565 
566 
575 static char *
576 address_to_regex (const void *addr,
577  const void *mask,
578  size_t len)
579 {
580  const uint16_t *a = addr;
581  const uint16_t *m = mask;
582  char *ret;
583  char *tmp;
584  char *reg;
585  unsigned int i;
586 
587  ret = NULL;
588  GNUNET_assert (1 != (len % 2));
589  for (i = 0; i < len / 2; i++)
590  {
591  reg = num_to_regex (a[i], m[i]);
592  if (NULL == reg)
593  {
594  GNUNET_free (ret);
595  return NULL;
596  }
597  if (NULL == ret)
598  {
599  ret = reg;
600  }
601  else
602  {
603  GNUNET_asprintf (&tmp,
604  "%s%s",
605  ret, reg);
606  GNUNET_free (ret);
607  GNUNET_free (reg);
608  ret = tmp;
609  }
610  }
611  return ret;
612 }
613 
614 
621 static char *
623 {
624  char *reg;
625  char *pp;
626  char *ret;
627 
628  reg = address_to_regex (&v4->network,
629  &v4->netmask,
630  sizeof(struct in_addr));
631  if (NULL == reg)
632  return NULL;
633  pp = port_to_regex (&v4->pp);
634  if (NULL == pp)
635  {
636  GNUNET_free (reg);
637  return NULL;
638  }
640  "4-%s-%s",
641  pp, reg);
642  GNUNET_free (pp);
643  GNUNET_free (reg);
644  return ret;
645 }
646 
647 
654 static char *
656 {
657  char *reg;
658  char *pp;
659  char *ret;
660 
661  reg = address_to_regex (&v6->network,
662  &v6->netmask,
663  sizeof(struct in6_addr));
664  if (NULL == reg)
665  return NULL;
666  pp = port_to_regex (&v6->pp);
667  if (NULL == pp)
668  {
669  GNUNET_free (reg);
670  return NULL;
671  }
673  "6-%s-%s",
674  pp, reg);
675  GNUNET_free (pp);
676  GNUNET_free (reg);
677  return ret;
678 }
679 
680 
681 char *
682 GNUNET_TUN_ipv4policy2regex (const char *policy)
683 {
685  char *reg;
686  char *tmp;
687  char *line;
688  unsigned int i;
689 
690  np = GNUNET_STRINGS_parse_ipv4_policy (policy);
691  if (NULL == np)
692  return NULL;
693  reg = NULL;
694  for (i = 0; (0 == i) || (0 != np[i].network.s_addr); i++)
695  {
696  line = ipv4_to_regex (&np[i]);
697  if (NULL == line)
698  {
699  GNUNET_free (reg);
700  GNUNET_free (np);
701  return NULL;
702  }
703  if (NULL == reg)
704  {
705  reg = line;
706  }
707  else
708  {
709  GNUNET_asprintf (&tmp,
710  "%s|(%s)",
711  reg, line);
712  GNUNET_free (reg);
713  GNUNET_free (line);
714  reg = tmp;
715  }
716  if (0 == np[i].network.s_addr)
717  break;
718  }
719  GNUNET_free (np);
720  return reg;
721 }
722 
723 
724 char *
725 GNUNET_TUN_ipv6policy2regex (const char *policy)
726 {
727  struct in6_addr zero;
729  char *reg;
730  char *tmp;
731  char *line;
732  unsigned int i;
733 
734  np = GNUNET_STRINGS_parse_ipv6_policy (policy);
735  if (NULL == np)
736  return NULL;
737  reg = NULL;
738  memset (&zero, 0, sizeof(struct in6_addr));
739  for (i = 0; (0 == i) || (0 != memcmp (&zero, &np[i].network, sizeof(struct
740  in6_addr)));
741  i++)
742  {
743  line = ipv6_to_regex (&np[i]);
744  if (NULL == line)
745  {
746  GNUNET_free (reg);
747  GNUNET_free (np);
748  return NULL;
749  }
750  if (NULL == reg)
751  {
752  reg = line;
753  }
754  else
755  {
756  GNUNET_asprintf (&tmp,
757  "%s|(%s)",
758  reg, line);
759  GNUNET_free (reg);
760  GNUNET_free (line);
761  reg = tmp;
762  }
763  if (0 == memcmp (&zero, &np[i].network, sizeof(struct in6_addr)))
764  break;
765  }
766  GNUNET_free (np);
767  return reg;
768 }
769 
770 
771 void
773  struct GNUNET_HashCode *hc)
774 {
776  strlen (service_name),
777  hc);
778 }
779 
780 
790 void
792  uint16_t ip_port,
793  struct GNUNET_HashCode *cadet_port)
794 {
795  uint16_t be_port = htons (ip_port);
796 
797  *cadet_port = *desc;
799  &be_port,
800  sizeof(uint16_t));
801 }
802 
803 
804 /* end of regex.c */
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static struct GNUNET_ARM_Operation * op
Current operation.
Definition: gnunet-arm.c:144
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:104
static int start
Set if we are to start default services (including ARM).
Definition: gnunet-arm.c:39
static int end
Set if we are to shutdown all services (including ARM).
Definition: gnunet-arm.c:34
static uint16_t port
Port number.
Definition: gnunet-bcd.c:147
static char * line
Desired phone line (string to be converted to a hash).
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 * value
Value of the record to add/remove.
static struct GNUNET_CADET_Port * cadet_port
Listen port for incoming requests.
static const struct GNUNET_IDENTITY_PrivateKey zero
Public key of all zeros.
static char buf[2048]
static char * service_name
Option -s: service name (hash to get service descriptor)
Definition: gnunet-vpn.c:50
static int ipv6
Option -6: IPv6 requested.
Definition: gnunet-vpn.c:65
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:41
#define GNUNET_log(kind,...)
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
@ GNUNET_YES
@ GNUNET_NO
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
@ GNUNET_ERROR_TYPE_WARNING
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
int GNUNET_snprintf(char *buf, size_t size, const char *format,...) __attribute__((format(printf
Like snprintf, just aborts if the buffer is of insufficient size.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
struct GNUNET_STRINGS_IPv6NetworkPolicy * GNUNET_STRINGS_parse_ipv6_policy(const char *routeListX)
Parse an IPv6 network policy.
Definition: strings.c:1471
struct GNUNET_STRINGS_IPv4NetworkPolicy * GNUNET_STRINGS_parse_ipv4_policy(const char *routeListX)
Parse an IPv4 network policy.
Definition: strings.c:1290
void GNUNET_TUN_ipv6toregexsearch(const struct in6_addr *ipv6, uint16_t port, char *rxstr)
Create a regex in rxstr from the given ipv6 and port.
Definition: regex.c:50
#define GNUNET_TUN_IPV4_REGEXLEN
Maximum regex string length for use with GNUNET_TUN_ipv4toregexsearch.
#define GNUNET_TUN_IPV6_REGEXLEN
Maximum regex string length for use with GNUNET_TUN_ipv6toregexsearch.
char * GNUNET_TUN_ipv4policy2regex(const char *policy)
Convert an exit policy to a regular expression.
Definition: regex.c:682
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:791
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:772
void GNUNET_TUN_ipv4toregexsearch(const struct in_addr *ip, uint16_t port, char *rxstr)
Create a regex in rxstr from the given ip and port.
Definition: regex.c:37
char * GNUNET_TUN_ipv6policy2regex(const char *policy)
Convert an exit policy to a regular expression.
Definition: regex.c:725
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
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:622
static char * num_to_regex(uint16_t value, uint16_t mask)
Convert the given 16-bit number to a regex.
Definition: regex.c:138
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:576
static int needs_parens(const char *arg)
Do we need to put parents around the given argument?
Definition: regex.c:177
#define DOT
'wildcard', matches all possible values (for HEX encoding).
Definition: regex.c:33
static char * port_to_regex(const struct GNUNET_STRINGS_PortPolicy *pp)
Convert a port policy to a regular expression.
Definition: regex.c:504
static char * nibble_to_regex(uint8_t value, uint8_t mask)
Convert the given 4-bit (!) number to a regex.
Definition: regex.c:75
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:655
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:222
A 512-bit hashcode.
IPV4 network in CIDR notation.
struct in_addr network
IPv4 address.
struct GNUNET_STRINGS_PortPolicy pp
Policy for port access.
struct in_addr netmask
IPv4 netmask.
network in CIDR notation for IPV6.
struct GNUNET_STRINGS_PortPolicy pp
Policy for port access.
struct in6_addr network
IPv6 address.
struct in6_addr netmask
IPv6 netmask.
uint16_t start_port
Starting port range (0 if none given).
int negate_portrange
GNUNET_YES if the port range should be negated ("!" in policy).
uint16_t end_port
End of port range (0 if none given).