aboutsummaryrefslogtreecommitdiff
path: root/src/util/service.c
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/util/service.c
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/util/service.c')
-rw-r--r--src/util/service.c325
1 files changed, 10 insertions, 315 deletions
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"),