aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2013-10-26 12:36:51 +0000
committerChristian Grothoff <christian@grothoff.org>2013-10-26 12:36:51 +0000
commitaeb922926c639ffdd992f96cd125e47bb0e2c301 (patch)
tree85097e40305035ad337f0c0e8dc0f95343dbed3a /src
parent7679eb4a51b8d0e9e4671dae00ca83c9f1b22de7 (diff)
downloadgnunet-aeb922926c639ffdd992f96cd125e47bb0e2c301.tar.gz
gnunet-aeb922926c639ffdd992f96cd125e47bb0e2c301.zip
-moving code to parse IPv4/IPv6 subnet specifications to strings and making it part of the public API
Diffstat (limited to 'src')
-rw-r--r--src/gns/Makefile.am6
-rw-r--r--src/gns/gnunet-gns-proxy.c34
-rw-r--r--src/include/gnunet_strings_lib.h68
-rw-r--r--src/util/service.c325
-rw-r--r--src/util/strings.c281
5 files changed, 364 insertions, 350 deletions
diff --git a/src/gns/Makefile.am b/src/gns/Makefile.am
index 75c3d0133..8e701ad96 100644
--- a/src/gns/Makefile.am
+++ b/src/gns/Makefile.am
@@ -50,7 +50,7 @@ lib_LTLIBRARIES = \
50if HAVE_MHD 50if HAVE_MHD
51if HAVE_GNUTLS 51if HAVE_GNUTLS
52if HAVE_LIBGNURL 52if HAVE_LIBGNURL
53# DO_PROXY=gnunet-gns-proxy 53 DO_PROXY=gnunet-gns-proxy
54endif 54endif
55endif 55endif
56endif 56endif
@@ -58,8 +58,8 @@ endif
58libexec_PROGRAMS = \ 58libexec_PROGRAMS = \
59 gnunet-service-gns \ 59 gnunet-service-gns \
60 $(DO_W32_HELPER) \ 60 $(DO_W32_HELPER) \
61 gnunet-dns2gns 61 gnunet-dns2gns \
62# $(DO_PROXY) 62 $(DO_PROXY)
63 63
64bin_PROGRAMS = \ 64bin_PROGRAMS = \
65 $(DO_W32_NSPTOOLS) \ 65 $(DO_W32_NSPTOOLS) \
diff --git a/src/gns/gnunet-gns-proxy.c b/src/gns/gnunet-gns-proxy.c
index 968470bd9..4f65574dd 100644
--- a/src/gns/gnunet-gns-proxy.c
+++ b/src/gns/gnunet-gns-proxy.c
@@ -26,7 +26,6 @@
26 * 26 *
27 * TODO: 27 * TODO:
28 * - double-check queueing logic 28 * - double-check queueing logic
29 * - actually check SSL certificates (#3038)
30 */ 29 */
31#include "platform.h" 30#include "platform.h"
32#include <microhttpd.h> 31#include <microhttpd.h>
@@ -877,6 +876,9 @@ check_ssl_certificate (struct Socks5Request *s5r)
877 876
878 /* FIXME: add flags to gnutls to NOT read UNBOUND_ROOT_KEY_FILE here! */ 877 /* FIXME: add flags to gnutls to NOT read UNBOUND_ROOT_KEY_FILE here! */
879 if (0 != (rc = dane_state_init (&dane_state, 878 if (0 != (rc = dane_state_init (&dane_state,
879#ifdef DANE_F_IGNORE_DNSSEC
880 DANE_F_IGNORE_DNSSEC |
881#endif
880 DANE_F_IGNORE_LOCAL_RESOLVER))) 882 DANE_F_IGNORE_LOCAL_RESOLVER)))
881 { 883 {
882 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 884 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -957,36 +959,6 @@ check_ssl_certificate (struct Socks5Request *s5r)
957 } 959 }
958 } 960 }
959 gnutls_x509_crt_deinit (x509_cert); 961 gnutls_x509_crt_deinit (x509_cert);
960#if 0
961 {
962 unsigned int i;
963
964 for(i=0;i<cert_list_size;i++)
965 {
966 gnutls_x509_crt_t cert;
967 gnutls_datum_t dn;
968
969 if (GNUTLS_E_SUCCESS == gnutls_x509_crt_init (&cert))
970 {
971 if (GNUTLS_E_SUCCESS ==
972 gnutls_x509_crt_import (cert, &chainp[i],
973 GNUTLS_X509_FMT_DER))
974 {
975 if (GNUTLS_E_SUCCESS ==
976 gnutls_x509_crt_print (cert,
977 GNUTLS_CRT_PRINT_FULL,
978 &dn))
979 {
980 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
981 "Certificate #%d: %.*s", i, dn.size, dn.data);
982 gnutls_free (dn.data);
983 }
984 }
985 gnutls_x509_crt_deinit (cert);
986 }
987 }
988 }
989#endif
990 return GNUNET_OK; 962 return GNUNET_OK;
991} 963}
992 964
diff --git a/src/include/gnunet_strings_lib.h b/src/include/gnunet_strings_lib.h
index 2e6f599d1..e0a299ac3 100644
--- a/src/include/gnunet_strings_lib.h
+++ b/src/include/gnunet_strings_lib.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2012 Christian Grothoff (and other contributing authors) 3 (C) 2001-2013 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 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 6 it under the terms of the GNU General Public License as published
@@ -469,6 +469,72 @@ GNUNET_STRINGS_get_utf8_args (int argc,
469 char *const **u8argv); 469 char *const **u8argv);
470 470
471 471
472/* ***************** IPv4/IPv6 parsing ****************** */
473
474/**
475 * @brief IPV4 network in CIDR notation.
476 */
477struct GNUNET_STRINGS_IPv4NetworkPolicy
478{
479 /**
480 * IPv4 address.
481 */
482 struct in_addr network;
483
484 /**
485 * IPv4 netmask.
486 */
487 struct in_addr netmask;
488};
489
490/**
491
492 * @brief network in CIDR notation for IPV6.
493 */
494struct GNUNET_STRINGS_IPv6NetworkPolicy
495{
496 /**
497 * IPv6 address.
498 */
499 struct in6_addr network;
500
501 /**
502 * IPv6 netmask.
503 */
504 struct in6_addr netmask;
505};
506
507
508/**
509 * Parse an IPv4 network policy. The argument specifies a list of
510 * subnets. The format is <tt>[network/netmask;]*</tt> (no whitespace,
511 * must be terminated with a semicolon). The network must be given in
512 * dotted-decimal notation. The netmask can be given in CIDR notation
513 * (/16) or in dotted-decimal (/255.255.0.0).
514 *
515 * @param routeList a string specifying the IPv4 subnets
516 * @return the converted list, terminated with all zeros;
517 * NULL if the synatx is flawed
518 */
519struct GNUNET_STRINGS_IPv4NetworkPolicy *
520GNUNET_STRINGS_parse_ipv4_policy (const char *routeList);
521
522
523/**
524 * Parse an IPv6 network policy. The argument specifies a list of
525 * subnets. The format is <tt>[network/netmask;]*</tt> (no whitespace,
526 * must be terminated with a semicolon). The network must be given in
527 * colon-hex notation. The netmask must be given in CIDR notation
528 * (/16) or can be omitted to specify a single host.
529 *
530 * @param routeListX a string specifying the policy
531 * @return the converted list, 0-terminated, NULL if the synatx is flawed
532 */
533struct GNUNET_STRINGS_IPv6NetworkPolicy *
534GNUNET_STRINGS_parse_ipv6_policy (const char *routeListX);
535
536
537
472#if 0 /* keep Emacsens' auto-indent happy */ 538#if 0 /* keep Emacsens' auto-indent happy */
473{ 539{
474#endif 540#endif
diff --git a/src/util/service.c b/src/util/service.c
index 3ba20d64a..e7d4c1c6f 100644
--- a/src/util/service.c
+++ b/src/util/service.c
@@ -45,40 +45,6 @@
45/* ******************* access control ******************** */ 45/* ******************* access control ******************** */
46 46
47/** 47/**
48 * @brief IPV4 network in CIDR notation.
49 */
50struct IPv4NetworkSet
51{
52 /**
53 * IPv4 address.
54 */
55 struct in_addr network;
56
57 /**
58 * IPv4 netmask.
59 */
60 struct in_addr netmask;
61};
62
63/**
64
65 * @brief network in CIDR notation for IPV6.
66 */
67struct IPv6NetworkSet
68{
69 /**
70 * IPv6 address.
71 */
72 struct in6_addr network;
73
74 /**
75 * IPv6 netmask.
76 */
77 struct in6_addr netmask;
78};
79
80
81/**
82 * Start task that may speed up our system clock artificially 48 * Start task that may speed up our system clock artificially
83 * 49 *
84 * @param cfg configuration to use 50 * @param cfg configuration to use
@@ -95,277 +61,6 @@ GNUNET_SPEEDUP_stop_ (void);
95 61
96 62
97/** 63/**
98 * Parse a network specification. The argument specifies
99 * a list of networks. The format is
100 * <tt>[network/netmask;]*</tt> (no whitespace, must be terminated
101 * with a semicolon). The network must be given in dotted-decimal
102 * notation. The netmask can be given in CIDR notation (/16) or
103 * in dotted-decimal (/255.255.0.0).
104 *
105 * @param routeList a string specifying the forbidden networks
106 * @return the converted list, NULL if the synatx is flawed
107 */
108static struct IPv4NetworkSet *
109parse_ipv4_specification (const char *routeList)
110{
111 unsigned int count;
112 unsigned int i;
113 unsigned int j;
114 unsigned int len;
115 int cnt;
116 unsigned int pos;
117 unsigned int temps[8];
118 int slash;
119 struct IPv4NetworkSet *result;
120
121 if (NULL == routeList)
122 return NULL;
123 len = strlen (routeList);
124 if (0 == len)
125 return NULL;
126 count = 0;
127 for (i = 0; i < len; i++)
128 if (routeList[i] == ';')
129 count++;
130 result = GNUNET_malloc (sizeof (struct IPv4NetworkSet) * (count + 1));
131 i = 0;
132 pos = 0;
133 while (i < count)
134 {
135 cnt =
136 SSCANF (&routeList[pos], "%u.%u.%u.%u/%u.%u.%u.%u;", &temps[0],
137 &temps[1], &temps[2], &temps[3], &temps[4], &temps[5],
138 &temps[6], &temps[7]);
139 if (8 == cnt)
140 {
141 for (j = 0; j < 8; j++)
142 if (temps[j] > 0xFF)
143 {
144 LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid format for IP: `%s'\n"),
145 &routeList[pos]);
146 GNUNET_free (result);
147 return NULL;
148 }
149 result[i].network.s_addr =
150 htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) +
151 temps[3]);
152 result[i].netmask.s_addr =
153 htonl ((temps[4] << 24) + (temps[5] << 16) + (temps[6] << 8) +
154 temps[7]);
155 while (routeList[pos] != ';')
156 pos++;
157 pos++;
158 i++;
159 continue;
160 }
161 /* try second notation */
162 cnt =
163 SSCANF (&routeList[pos], "%u.%u.%u.%u/%u;", &temps[0], &temps[1],
164 &temps[2], &temps[3], &slash);
165 if (5 == cnt)
166 {
167 for (j = 0; j < 4; j++)
168 if (temps[j] > 0xFF)
169 {
170 LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid format for IP: `%s'\n"),
171 &routeList[pos]);
172 GNUNET_free (result);
173 return NULL;
174 }
175 result[i].network.s_addr =
176 htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) +
177 temps[3]);
178 if ((slash <= 32) && (slash >= 0))
179 {
180 result[i].netmask.s_addr = 0;
181 while (slash > 0)
182 {
183 result[i].netmask.s_addr =
184 (result[i].netmask.s_addr >> 1) + 0x80000000;
185 slash--;
186 }
187 result[i].netmask.s_addr = htonl (result[i].netmask.s_addr);
188 while (';' != routeList[pos])
189 pos++;
190 pos++;
191 i++;
192 continue;
193 }
194 else
195 {
196 LOG (GNUNET_ERROR_TYPE_ERROR,
197 _("Invalid network notation ('/%d' is not legal in IPv4 CIDR)."),
198 slash);
199 GNUNET_free (result);
200 return NULL; /* error */
201 }
202 }
203 /* try third notation */
204 slash = 32;
205 cnt =
206 SSCANF (&routeList[pos], "%u.%u.%u.%u;", &temps[0], &temps[1],
207 &temps[2], &temps[3]);
208 if (4 == cnt)
209 {
210 for (j = 0; j < 4; j++)
211 if (temps[j] > 0xFF)
212 {
213 LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid format for IP: `%s'\n"),
214 &routeList[pos]);
215 GNUNET_free (result);
216 return NULL;
217 }
218 result[i].network.s_addr =
219 htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) +
220 temps[3]);
221 result[i].netmask.s_addr = 0;
222 while (slash > 0)
223 {
224 result[i].netmask.s_addr = (result[i].netmask.s_addr >> 1) + 0x80000000;
225 slash--;
226 }
227 result[i].netmask.s_addr = htonl (result[i].netmask.s_addr);
228 while (routeList[pos] != ';')
229 pos++;
230 pos++;
231 i++;
232 continue;
233 }
234 LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid format for IP: `%s'\n"),
235 &routeList[pos]);
236 GNUNET_free (result);
237 return NULL; /* error */
238 }
239 if (pos < strlen (routeList))
240 {
241 LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid format for IP: `%s'\n"),
242 &routeList[pos]);
243 GNUNET_free (result);
244 return NULL; /* oops */
245 }
246 return result; /* ok */
247}
248
249
250/**
251 * Parse a network specification. The argument specifies
252 * a list of networks. The format is
253 * <tt>[network/netmask;]*</tt> (no whitespace, must be terminated
254 * with a semicolon). The network must be given in colon-hex
255 * notation. The netmask must be given in CIDR notation (/16) or
256 * can be omitted to specify a single host.
257 *
258 * @param routeListX a string specifying the forbidden networks
259 * @return the converted list, NULL if the synatx is flawed
260 */
261static struct IPv6NetworkSet *
262parse_ipv6_specification (const char *routeListX)
263{
264 unsigned int count;
265 unsigned int i;
266 unsigned int len;
267 unsigned int pos;
268 int start;
269 int slash;
270 int ret;
271 char *routeList;
272 struct IPv6NetworkSet *result;
273 unsigned int bits;
274 unsigned int off;
275 int save;
276
277 if (NULL == routeListX)
278 return NULL;
279 len = strlen (routeListX);
280 if (0 == len)
281 return NULL;
282 routeList = GNUNET_strdup (routeListX);
283 count = 0;
284 for (i = 0; i < len; i++)
285 if (';' == routeList[i])
286 count++;
287 if (';' != routeList[len - 1])
288 {
289 LOG (GNUNET_ERROR_TYPE_ERROR,
290 _("Invalid network notation (does not end with ';': `%s')\n"),
291 routeList);
292 GNUNET_free (routeList);
293 return NULL;
294 }
295
296 result = GNUNET_malloc (sizeof (struct IPv6NetworkSet) * (count + 1));
297 i = 0;
298 pos = 0;
299 while (i < count)
300 {
301 start = pos;
302 while (';' != routeList[pos])
303 pos++;
304 slash = pos;
305 while ((slash >= start) && (routeList[slash] != '/'))
306 slash--;
307 if (slash < start)
308 {
309 memset (&result[i].netmask, 0xFF, sizeof (struct in6_addr));
310 slash = pos;
311 }
312 else
313 {
314 routeList[pos] = '\0';
315 ret = inet_pton (AF_INET6, &routeList[slash + 1], &result[i].netmask);
316 if (ret <= 0)
317 {
318 save = errno;
319 if ((1 != SSCANF (&routeList[slash + 1], "%u", &bits)) || (bits >= 128))
320 {
321 if (0 == ret)
322 LOG (GNUNET_ERROR_TYPE_ERROR, _("Wrong format `%s' for netmask\n"),
323 &routeList[slash + 1]);
324 else
325 {
326 errno = save;
327 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "inet_pton");
328 }
329 GNUNET_free (result);
330 GNUNET_free (routeList);
331 return NULL;
332 }
333 off = 0;
334 while (bits > 8)
335 {
336 result[i].netmask.s6_addr[off++] = 0xFF;
337 bits -= 8;
338 }
339 while (bits > 0)
340 {
341 result[i].netmask.s6_addr[off] =
342 (result[i].netmask.s6_addr[off] >> 1) + 0x80;
343 bits--;
344 }
345 }
346 }
347 routeList[slash] = '\0';
348 ret = inet_pton (AF_INET6, &routeList[start], &result[i].network);
349 if (ret <= 0)
350 {
351 if (0 == ret)
352 LOG (GNUNET_ERROR_TYPE_ERROR, _("Wrong format `%s' for network\n"),
353 &routeList[slash + 1]);
354 else
355 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "inet_pton");
356 GNUNET_free (result);
357 GNUNET_free (routeList);
358 return NULL;
359 }
360 pos++;
361 i++;
362 }
363 GNUNET_free (routeList);
364 return result;
365}
366
367
368/**
369 * Check if the given IP address is in the list of IP addresses. 64 * Check if the given IP address is in the list of IP addresses.
370 * 65 *
371 * @param list a list of networks 66 * @param list a list of networks
@@ -373,7 +68,7 @@ parse_ipv6_specification (const char *routeListX)
373 * @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
374 */ 69 */
375static int 70static int
376check_ipv4_listed (const struct IPv4NetworkSet *list, const struct in_addr *add) 71check_ipv4_listed (const struct GNUNET_STRINGS_IPv4NetworkPolicy *list, const struct in_addr *add)
377{ 72{
378 unsigned int i; 73 unsigned int i;
379 74
@@ -399,7 +94,7 @@ check_ipv4_listed (const struct IPv4NetworkSet *list, const struct in_addr *add)
399 * @return GNUNET_NO if the IP is not in the list, GNUNET_YES if it it is 94 * @return GNUNET_NO if the IP is not in the list, GNUNET_YES if it it is
400 */ 95 */
401static int 96static int
402check_ipv6_listed (const struct IPv6NetworkSet *list, const struct in6_addr *ip) 97check_ipv6_listed (const struct GNUNET_STRINGS_IPv6NetworkPolicy *list, const struct in6_addr *ip)
403{ 98{
404 unsigned int i; 99 unsigned int i;
405 unsigned int j; 100 unsigned int j;
@@ -467,24 +162,24 @@ struct GNUNET_SERVICE_Context
467 /** 162 /**
468 * IPv4 addresses that are not allowed to connect. 163 * IPv4 addresses that are not allowed to connect.
469 */ 164 */
470 struct IPv4NetworkSet *v4_denied; 165 struct GNUNET_STRINGS_IPv4NetworkPolicy *v4_denied;
471 166
472 /** 167 /**
473 * IPv6 addresses that are not allowed to connect. 168 * IPv6 addresses that are not allowed to connect.
474 */ 169 */
475 struct IPv6NetworkSet *v6_denied; 170 struct GNUNET_STRINGS_IPv6NetworkPolicy *v6_denied;
476 171
477 /** 172 /**
478 * IPv4 addresses that are allowed to connect (if not 173 * IPv4 addresses that are allowed to connect (if not
479 * set, all are allowed). 174 * set, all are allowed).
480 */ 175 */
481 struct IPv4NetworkSet *v4_allowed; 176 struct GNUNET_STRINGS_IPv4NetworkPolicy *v4_allowed;
482 177
483 /** 178 /**
484 * IPv6 addresses that are allowed to connect (if not 179 * IPv6 addresses that are allowed to connect (if not
485 * set, all are allowed). 180 * set, all are allowed).
486 */ 181 */
487 struct IPv6NetworkSet *v6_allowed; 182 struct GNUNET_STRINGS_IPv6NetworkPolicy *v6_allowed;
488 183
489 /** 184 /**
490 * My (default) message handlers. Adjusted copy 185 * My (default) message handlers. Adjusted copy
@@ -707,7 +402,7 @@ get_pid_file_name (struct GNUNET_SERVICE_Context *sctx)
707 * no ACL configured) 402 * no ACL configured)
708 */ 403 */
709static int 404static int
710process_acl4 (struct IPv4NetworkSet **ret, struct GNUNET_SERVICE_Context *sctx, 405process_acl4 (struct GNUNET_STRINGS_IPv4NetworkPolicy **ret, struct GNUNET_SERVICE_Context *sctx,
711 const char *option) 406 const char *option)
712{ 407{
713 char *opt; 408 char *opt;
@@ -721,7 +416,7 @@ process_acl4 (struct IPv4NetworkSet **ret, struct GNUNET_SERVICE_Context *sctx,
721 GNUNET_CONFIGURATION_get_value_string (sctx->cfg, 416 GNUNET_CONFIGURATION_get_value_string (sctx->cfg,
722 sctx->service_name, 417 sctx->service_name,
723 option, &opt)); 418 option, &opt));
724 if (NULL == (*ret = parse_ipv4_specification (opt))) 419 if (NULL == (*ret = GNUNET_STRINGS_parse_ipv4_policy (opt)))
725 { 420 {
726 LOG (GNUNET_ERROR_TYPE_WARNING, 421 LOG (GNUNET_ERROR_TYPE_WARNING,
727 _("Could not parse IPv4 network specification `%s' for `%s:%s'\n"), 422 _("Could not parse IPv4 network specification `%s' for `%s:%s'\n"),
@@ -744,7 +439,7 @@ process_acl4 (struct IPv4NetworkSet **ret, struct GNUNET_SERVICE_Context *sctx,
744 * no ACL configured) 439 * no ACL configured)
745 */ 440 */
746static int 441static int
747process_acl6 (struct IPv6NetworkSet **ret, struct GNUNET_SERVICE_Context *sctx, 442process_acl6 (struct GNUNET_STRINGS_IPv6NetworkPolicy **ret, struct GNUNET_SERVICE_Context *sctx,
748 const char *option) 443 const char *option)
749{ 444{
750 char *opt; 445 char *opt;
@@ -758,7 +453,7 @@ process_acl6 (struct IPv6NetworkSet **ret, struct GNUNET_SERVICE_Context *sctx,
758 GNUNET_CONFIGURATION_get_value_string (sctx->cfg, 453 GNUNET_CONFIGURATION_get_value_string (sctx->cfg,
759 sctx->service_name, 454 sctx->service_name,
760 option, &opt)); 455 option, &opt));
761 if (NULL == (*ret = parse_ipv6_specification (opt))) 456 if (NULL == (*ret = GNUNET_STRINGS_parse_ipv6_policy (opt)))
762 { 457 {
763 LOG (GNUNET_ERROR_TYPE_WARNING, 458 LOG (GNUNET_ERROR_TYPE_WARNING,
764 _("Could not parse IPv6 network specification `%s' for `%s:%s'\n"), 459 _("Could not parse IPv6 network specification `%s' for `%s:%s'\n"),
diff --git a/src/util/strings.c b/src/util/strings.c
index 581ac013d..c50669e62 100644
--- a/src/util/strings.c
+++ b/src/util/strings.c
@@ -1328,4 +1328,285 @@ GNUNET_STRINGS_get_utf8_args (int argc, char *const *argv, int *u8argc, char *co
1328#endif 1328#endif
1329} 1329}
1330 1330
1331
1332/**
1333 * Parse an IPv4 network policy. The argument specifies a list of
1334 * subnets. The format is <tt>[network/netmask;]*</tt> (no whitespace,
1335 * must be terminated with a semicolon). The network must be given in
1336 * dotted-decimal notation. The netmask can be given in CIDR notation
1337 * (/16) or in dotted-decimal (/255.255.0.0).
1338 *
1339 * @param routeList a string specifying the IPv4 subnets
1340 * @return the converted list, terminated with all zeros;
1341 * NULL if the synatx is flawed
1342 */
1343struct GNUNET_STRINGS_IPv4NetworkPolicy *
1344GNUNET_STRINGS_parse_ipv4_policy (const char *routeList)
1345{
1346 unsigned int count;
1347 unsigned int i;
1348 unsigned int j;
1349 unsigned int len;
1350 int cnt;
1351 unsigned int pos;
1352 unsigned int temps[8];
1353 int slash;
1354 struct GNUNET_STRINGS_IPv4NetworkPolicy *result;
1355
1356 if (NULL == routeList)
1357 return NULL;
1358 len = strlen (routeList);
1359 if (0 == len)
1360 return NULL;
1361 count = 0;
1362 for (i = 0; i < len; i++)
1363 if (routeList[i] == ';')
1364 count++;
1365 result = GNUNET_malloc (sizeof (struct GNUNET_STRINGS_IPv4NetworkPolicy) * (count + 1));
1366 i = 0;
1367 pos = 0;
1368 while (i < count)
1369 {
1370 cnt =
1371 SSCANF (&routeList[pos], "%u.%u.%u.%u/%u.%u.%u.%u;", &temps[0],
1372 &temps[1], &temps[2], &temps[3], &temps[4], &temps[5],
1373 &temps[6], &temps[7]);
1374 if (8 == cnt)
1375 {
1376 for (j = 0; j < 8; j++)
1377 if (temps[j] > 0xFF)
1378 {
1379 LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid format for IP: `%s'\n"),
1380 &routeList[pos]);
1381 GNUNET_free (result);
1382 return NULL;
1383 }
1384 result[i].network.s_addr =
1385 htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) +
1386 temps[3]);
1387 result[i].netmask.s_addr =
1388 htonl ((temps[4] << 24) + (temps[5] << 16) + (temps[6] << 8) +
1389 temps[7]);
1390 while (routeList[pos] != ';')
1391 pos++;
1392 pos++;
1393 i++;
1394 continue;
1395 }
1396 /* try second notation */
1397 cnt =
1398 SSCANF (&routeList[pos], "%u.%u.%u.%u/%u;", &temps[0], &temps[1],
1399 &temps[2], &temps[3], &slash);
1400 if (5 == cnt)
1401 {
1402 for (j = 0; j < 4; j++)
1403 if (temps[j] > 0xFF)
1404 {
1405 LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid format for IP: `%s'\n"),
1406 &routeList[pos]);
1407 GNUNET_free (result);
1408 return NULL;
1409 }
1410 result[i].network.s_addr =
1411 htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) +
1412 temps[3]);
1413 if ((slash <= 32) && (slash >= 0))
1414 {
1415 result[i].netmask.s_addr = 0;
1416 while (slash > 0)
1417 {
1418 result[i].netmask.s_addr =
1419 (result[i].netmask.s_addr >> 1) + 0x80000000;
1420 slash--;
1421 }
1422 result[i].netmask.s_addr = htonl (result[i].netmask.s_addr);
1423 while (';' != routeList[pos])
1424 pos++;
1425 pos++;
1426 i++;
1427 continue;
1428 }
1429 else
1430 {
1431 LOG (GNUNET_ERROR_TYPE_ERROR,
1432 _("Invalid network notation ('/%d' is not legal in IPv4 CIDR)."),
1433 slash);
1434 GNUNET_free (result);
1435 return NULL; /* error */
1436 }
1437 }
1438 /* try third notation */
1439 slash = 32;
1440 cnt =
1441 SSCANF (&routeList[pos],
1442 "%u.%u.%u.%u;",
1443 &temps[0],
1444 &temps[1],
1445 &temps[2],
1446 &temps[3]);
1447 if (4 == cnt)
1448 {
1449 for (j = 0; j < 4; j++)
1450 if (temps[j] > 0xFF)
1451 {
1452 LOG (GNUNET_ERROR_TYPE_ERROR,
1453 _("Invalid format for IP: `%s'\n"),
1454 &routeList[pos]);
1455 GNUNET_free (result);
1456 return NULL;
1457 }
1458 result[i].network.s_addr =
1459 htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) +
1460 temps[3]);
1461 result[i].netmask.s_addr = 0;
1462 while (slash > 0)
1463 {
1464 result[i].netmask.s_addr = (result[i].netmask.s_addr >> 1) + 0x80000000;
1465 slash--;
1466 }
1467 result[i].netmask.s_addr = htonl (result[i].netmask.s_addr);
1468 while (routeList[pos] != ';')
1469 pos++;
1470 pos++;
1471 i++;
1472 continue;
1473 }
1474 LOG (GNUNET_ERROR_TYPE_ERROR,
1475 _("Invalid format for IP: `%s'\n"),
1476 &routeList[pos]);
1477 GNUNET_free (result);
1478 return NULL; /* error */
1479 }
1480 if (pos < strlen (routeList))
1481 {
1482 LOG (GNUNET_ERROR_TYPE_ERROR,
1483 _("Invalid format for IP: `%s'\n"),
1484 &routeList[pos]);
1485 GNUNET_free (result);
1486 return NULL; /* oops */
1487 }
1488 return result; /* ok */
1489}
1490
1491
1492/**
1493 * Parse an IPv6 network policy. The argument specifies a list of
1494 * subnets. The format is <tt>[network/netmask;]*</tt> (no whitespace,
1495 * must be terminated with a semicolon). The network must be given in
1496 * colon-hex notation. The netmask must be given in CIDR notation
1497 * (/16) or can be omitted to specify a single host.
1498 *
1499 * @param routeListX a string specifying the policy
1500 * @return the converted list, 0-terminated, NULL if the synatx is flawed
1501 */
1502struct GNUNET_STRINGS_IPv6NetworkPolicy *
1503GNUNET_STRINGS_parse_ipv6_policy (const char *routeListX)
1504{
1505 unsigned int count;
1506 unsigned int i;
1507 unsigned int len;
1508 unsigned int pos;
1509 int start;
1510 int slash;
1511 int ret;
1512 char *routeList;
1513 struct GNUNET_STRINGS_IPv6NetworkPolicy *result;
1514 unsigned int bits;
1515 unsigned int off;
1516 int save;
1517
1518 if (NULL == routeListX)
1519 return NULL;
1520 len = strlen (routeListX);
1521 if (0 == len)
1522 return NULL;
1523 routeList = GNUNET_strdup (routeListX);
1524 count = 0;
1525 for (i = 0; i < len; i++)
1526 if (';' == routeList[i])
1527 count++;
1528 if (';' != routeList[len - 1])
1529 {
1530 LOG (GNUNET_ERROR_TYPE_ERROR,
1531 _("Invalid network notation (does not end with ';': `%s')\n"),
1532 routeList);
1533 GNUNET_free (routeList);
1534 return NULL;
1535 }
1536
1537 result = GNUNET_malloc (sizeof (struct GNUNET_STRINGS_IPv6NetworkPolicy) * (count + 1));
1538 i = 0;
1539 pos = 0;
1540 while (i < count)
1541 {
1542 start = pos;
1543 while (';' != routeList[pos])
1544 pos++;
1545 slash = pos;
1546 while ((slash >= start) && (routeList[slash] != '/'))
1547 slash--;
1548 if (slash < start)
1549 {
1550 memset (&result[i].netmask, 0xFF, sizeof (struct in6_addr));
1551 slash = pos;
1552 }
1553 else
1554 {
1555 routeList[pos] = '\0';
1556 ret = inet_pton (AF_INET6, &routeList[slash + 1], &result[i].netmask);
1557 if (ret <= 0)
1558 {
1559 save = errno;
1560 if ((1 != SSCANF (&routeList[slash + 1], "%u", &bits)) || (bits >= 128))
1561 {
1562 if (0 == ret)
1563 LOG (GNUNET_ERROR_TYPE_ERROR,
1564 _("Wrong format `%s' for netmask\n"),
1565 &routeList[slash + 1]);
1566 else
1567 {
1568 errno = save;
1569 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "inet_pton");
1570 }
1571 GNUNET_free (result);
1572 GNUNET_free (routeList);
1573 return NULL;
1574 }
1575 off = 0;
1576 while (bits > 8)
1577 {
1578 result[i].netmask.s6_addr[off++] = 0xFF;
1579 bits -= 8;
1580 }
1581 while (bits > 0)
1582 {
1583 result[i].netmask.s6_addr[off] =
1584 (result[i].netmask.s6_addr[off] >> 1) + 0x80;
1585 bits--;
1586 }
1587 }
1588 }
1589 routeList[slash] = '\0';
1590 ret = inet_pton (AF_INET6, &routeList[start], &result[i].network);
1591 if (ret <= 0)
1592 {
1593 if (0 == ret)
1594 LOG (GNUNET_ERROR_TYPE_ERROR,
1595 _("Wrong format `%s' for network\n"),
1596 &routeList[slash + 1]);
1597 else
1598 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR,
1599 "inet_pton");
1600 GNUNET_free (result);
1601 GNUNET_free (routeList);
1602 return NULL;
1603 }
1604 pos++;
1605 i++;
1606 }
1607 GNUNET_free (routeList);
1608 return result;
1609}
1610
1611
1331/* end of strings.c */ 1612/* end of strings.c */