diff options
author | Christian Grothoff <christian@grothoff.org> | 2014-01-12 20:19:43 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2014-01-12 20:19:43 +0000 |
commit | 75b754d269802f2072514d55b94946912c55e067 (patch) | |
tree | 4cb9f0c2baa0ddd55694b72936646427ed27932b /src/tun | |
parent | f2a94edfe687f220160f2f58d92a53063ab98357 (diff) | |
download | gnunet-75b754d269802f2072514d55b94946912c55e067.tar.gz gnunet-75b754d269802f2072514d55b94946912c55e067.zip |
generate compact regular expressions if range is negated (#3226), switch default policy to not-25 (SMTP) as we can now work with that
Diffstat (limited to 'src/tun')
-rw-r--r-- | src/tun/regex.c | 375 | ||||
-rw-r--r-- | src/tun/test_regex.c | 5 |
2 files changed, 355 insertions, 25 deletions
diff --git a/src/tun/regex.c b/src/tun/regex.c index f37c35122..5ed94d6f8 100644 --- a/src/tun/regex.c +++ b/src/tun/regex.c | |||
@@ -173,6 +173,328 @@ num_to_regex (uint16_t value, | |||
173 | 173 | ||
174 | 174 | ||
175 | /** | 175 | /** |
176 | * Do we need to put parents around the given argument? | ||
177 | * | ||
178 | * @param arg part of a regular expression | ||
179 | * @return #GNUNET_YES if we should parens, | ||
180 | * #GNUNET_NO if not | ||
181 | */ | ||
182 | static int | ||
183 | needs_parens (const char *arg) | ||
184 | { | ||
185 | size_t off; | ||
186 | size_t len; | ||
187 | unsigned int op; | ||
188 | |||
189 | op = 0; | ||
190 | len = strlen (arg); | ||
191 | for (off=0;off<len;off++) | ||
192 | { | ||
193 | switch (arg[off]) | ||
194 | { | ||
195 | case '(': | ||
196 | op++; | ||
197 | break; | ||
198 | case ')': | ||
199 | GNUNET_assert (op > 0); | ||
200 | op--; | ||
201 | break; | ||
202 | case '|': | ||
203 | if (0 == op) | ||
204 | return GNUNET_YES; | ||
205 | break; | ||
206 | default: | ||
207 | break; | ||
208 | } | ||
209 | } | ||
210 | return GNUNET_NO; | ||
211 | } | ||
212 | |||
213 | |||
214 | /** | ||
215 | * Compute port policy for the given range of | ||
216 | * port numbers. | ||
217 | * | ||
218 | * @param start starting offset | ||
219 | * @param end end offset | ||
220 | * @param step increment level (power of 16) | ||
221 | * @param pp port policy to convert | ||
222 | * @return corresponding regex | ||
223 | */ | ||
224 | static char * | ||
225 | compute_policy (unsigned int start, | ||
226 | unsigned int end, | ||
227 | unsigned int step, | ||
228 | const struct GNUNET_STRINGS_PortPolicy *pp) | ||
229 | { | ||
230 | unsigned int i; | ||
231 | char before[36]; /* 16 * 2 + 3 dots + 0-terminator */ | ||
232 | char middlel[33]; /* 16 * 2 + 0-terminator */ | ||
233 | char middleh[33]; /* 16 * 2 + 0-terminator */ | ||
234 | char after[36]; /* 16 * 2 + 3 dots + 0-terminator */ | ||
235 | char beforep[36+2]; /* 16 * 2 + 3 dots + 0-terminator + ()*/ | ||
236 | char middlehp[33+2]; /* 16 * 2 + 0-terminator + () */ | ||
237 | char middlelp[33+2]; /* 16 * 2 + 0-terminator + () */ | ||
238 | char afterp[36+2]; /* 16 * 2 + 3 dots + 0-terminator + () */ | ||
239 | char dots[4]; | ||
240 | char buf[3]; | ||
241 | char *middle; | ||
242 | char *ret; | ||
243 | unsigned int xstep; | ||
244 | char *recl; | ||
245 | char *rech; | ||
246 | char *reclp; | ||
247 | char *rechp; | ||
248 | unsigned int start_port; | ||
249 | unsigned int end_port; | ||
250 | |||
251 | GNUNET_assert (GNUNET_YES == pp->negate_portrange); | ||
252 | start_port = pp->start_port; | ||
253 | if (1 == start_port) | ||
254 | start_port = 0; | ||
255 | end_port = pp->end_port; | ||
256 | GNUNET_assert ((end - start) / step <= 0xF); | ||
257 | before[0] = '\0'; | ||
258 | middlel[0] = '\0'; | ||
259 | middleh[0] = '\0'; | ||
260 | after[0] = '\0'; | ||
261 | for (i=start;i<=end;i+=step) | ||
262 | { | ||
263 | GNUNET_snprintf (buf, | ||
264 | sizeof (buf), | ||
265 | "%X|", | ||
266 | (i - start) / step); | ||
267 | if (i / step < start_port / step) | ||
268 | strcat (before, buf); | ||
269 | else if (i / step > end_port / step) | ||
270 | strcat (after, buf); | ||
271 | else if (i / step == start_port / step) | ||
272 | strcat (middlel, buf); | ||
273 | else if (i / step == end_port / step) | ||
274 | strcat (middleh, buf); | ||
275 | } | ||
276 | if (strlen (before) > 0) | ||
277 | before[strlen (before)-1] = '\0'; | ||
278 | if (strlen (middlel) > 0) | ||
279 | middlel[strlen (middlel)-1] = '\0'; | ||
280 | if (strlen (middleh) > 0) | ||
281 | middleh[strlen (middleh)-1] = '\0'; | ||
282 | if (strlen (after) > 0) | ||
283 | after[strlen (after)-1] = '\0'; | ||
284 | if (needs_parens (before)) | ||
285 | GNUNET_snprintf (beforep, | ||
286 | sizeof (beforep), | ||
287 | "(%s)", | ||
288 | before); | ||
289 | else | ||
290 | strcpy (beforep, before); | ||
291 | if (needs_parens (middlel)) | ||
292 | GNUNET_snprintf (middlelp, | ||
293 | sizeof (middlelp), | ||
294 | "(%s)", | ||
295 | middlel); | ||
296 | else | ||
297 | strcpy (middlelp, middlel); | ||
298 | if (needs_parens (middleh)) | ||
299 | GNUNET_snprintf (middlehp, | ||
300 | sizeof (middlehp), | ||
301 | "(%s)", | ||
302 | middleh); | ||
303 | else | ||
304 | strcpy (middlehp, middleh); | ||
305 | if (needs_parens (after)) | ||
306 | GNUNET_snprintf (afterp, | ||
307 | sizeof (afterp), | ||
308 | "(%s)", | ||
309 | after); | ||
310 | else | ||
311 | strcpy (afterp, after); | ||
312 | dots[0] = '\0'; | ||
313 | for (xstep=step/16;xstep>0;xstep/=16) | ||
314 | strcat (dots, "."); | ||
315 | if (step >= 16) | ||
316 | { | ||
317 | if (strlen (middlel) > 0) | ||
318 | recl = compute_policy ((start_port / step) * step, | ||
319 | (start_port / step) * step + step - 1, | ||
320 | step / 16, | ||
321 | pp); | ||
322 | else | ||
323 | recl = GNUNET_strdup (""); | ||
324 | if (strlen (middleh) > 0) | ||
325 | rech = compute_policy ((end_port / step) * step, | ||
326 | (end_port / step) * step + step - 1, | ||
327 | step / 16, | ||
328 | pp); | ||
329 | else | ||
330 | rech = GNUNET_strdup (""); | ||
331 | } | ||
332 | else | ||
333 | { | ||
334 | recl = GNUNET_strdup (""); | ||
335 | rech = GNUNET_strdup (""); | ||
336 | middlel[0] = '\0'; | ||
337 | middlelp[0] = '\0'; | ||
338 | middleh[0] = '\0'; | ||
339 | middlehp[0] = '\0'; | ||
340 | } | ||
341 | if (needs_parens (recl)) | ||
342 | GNUNET_asprintf (&reclp, | ||
343 | "(%s)", | ||
344 | recl); | ||
345 | else | ||
346 | reclp = GNUNET_strdup (recl); | ||
347 | if (needs_parens (rech)) | ||
348 | GNUNET_asprintf (&rechp, | ||
349 | "(%s)", | ||
350 | rech); | ||
351 | else | ||
352 | rechp = GNUNET_strdup (rech); | ||
353 | |||
354 | if ( (strlen (middleh) > 0) && | ||
355 | (strlen (rech) > 0) && | ||
356 | (strlen (middlel) > 0) && | ||
357 | (strlen (recl) > 0) ) | ||
358 | { | ||
359 | GNUNET_asprintf (&middle, | ||
360 | "%s%s|%s%s", | ||
361 | middlel, | ||
362 | reclp, | ||
363 | middleh, | ||
364 | rechp); | ||
365 | } | ||
366 | else if ( (strlen (middleh) > 0) && | ||
367 | (strlen (rech) > 0) ) | ||
368 | { | ||
369 | GNUNET_asprintf (&middle, | ||
370 | "%s%s", | ||
371 | middleh, | ||
372 | rechp); | ||
373 | } | ||
374 | else if ( (strlen (middlel) > 0) && | ||
375 | (strlen (recl) > 0) ) | ||
376 | { | ||
377 | GNUNET_asprintf (&middle, | ||
378 | "%s%s", | ||
379 | middlel, | ||
380 | reclp); | ||
381 | } | ||
382 | else | ||
383 | { | ||
384 | middle = GNUNET_strdup (""); | ||
385 | } | ||
386 | if ( (strlen(before) > 0) && | ||
387 | (strlen(after) > 0) ) | ||
388 | { | ||
389 | if (strlen (dots) > 0) | ||
390 | { | ||
391 | if (strlen (middle) > 0) | ||
392 | GNUNET_asprintf (&ret, | ||
393 | "(%s%s|%s|%s%s)", | ||
394 | beforep, dots, | ||
395 | middle, | ||
396 | afterp, dots); | ||
397 | else | ||
398 | GNUNET_asprintf (&ret, | ||
399 | "(%s|%s)%s", | ||
400 | beforep, | ||
401 | afterp, | ||
402 | dots); | ||
403 | } | ||
404 | else | ||
405 | { | ||
406 | if (strlen (middle) > 0) | ||
407 | GNUNET_asprintf (&ret, | ||
408 | "(%s|%s|%s)", | ||
409 | before, | ||
410 | middle, | ||
411 | after); | ||
412 | else if (1 == step) | ||
413 | GNUNET_asprintf (&ret, | ||
414 | "%s|%s", | ||
415 | before, | ||
416 | after); | ||
417 | else | ||
418 | GNUNET_asprintf (&ret, | ||
419 | "(%s|%s)", | ||
420 | before, | ||
421 | after); | ||
422 | } | ||
423 | } | ||
424 | else if (strlen (before) > 0) | ||
425 | { | ||
426 | if (strlen (dots) > 0) | ||
427 | { | ||
428 | if (strlen (middle) > 0) | ||
429 | GNUNET_asprintf (&ret, | ||
430 | "(%s%s|%s)", | ||
431 | beforep, dots, | ||
432 | middle); | ||
433 | else | ||
434 | GNUNET_asprintf (&ret, | ||
435 | "%s%s", | ||
436 | beforep, dots); | ||
437 | } | ||
438 | else | ||
439 | { | ||
440 | if (strlen (middle) > 0) | ||
441 | GNUNET_asprintf (&ret, | ||
442 | "(%s|%s)", | ||
443 | before, | ||
444 | middle); | ||
445 | else | ||
446 | GNUNET_asprintf (&ret, | ||
447 | "%s", | ||
448 | before); | ||
449 | } | ||
450 | } | ||
451 | else if (strlen (after) > 0) | ||
452 | { | ||
453 | if (strlen (dots) > 0) | ||
454 | { | ||
455 | if (strlen (middle) > 0) | ||
456 | GNUNET_asprintf (&ret, | ||
457 | "(%s|%s%s)", | ||
458 | middle, | ||
459 | afterp, dots); | ||
460 | else | ||
461 | GNUNET_asprintf (&ret, | ||
462 | "%s%s", | ||
463 | afterp, dots); | ||
464 | } | ||
465 | else | ||
466 | { | ||
467 | if (strlen (middle) > 0) | ||
468 | GNUNET_asprintf (&ret, | ||
469 | "%s|%s", | ||
470 | middle, | ||
471 | after); | ||
472 | else | ||
473 | GNUNET_asprintf (&ret, | ||
474 | "%s", | ||
475 | after); | ||
476 | } | ||
477 | } | ||
478 | else if (strlen (middle) > 0) | ||
479 | { | ||
480 | GNUNET_asprintf (&ret, | ||
481 | "%s", | ||
482 | middle); | ||
483 | } | ||
484 | else | ||
485 | { | ||
486 | ret = GNUNET_strdup (""); | ||
487 | } | ||
488 | GNUNET_free (middle); | ||
489 | GNUNET_free (reclp); | ||
490 | GNUNET_free (rechp); | ||
491 | GNUNET_free (recl); | ||
492 | GNUNET_free (rech); | ||
493 | return ret; | ||
494 | } | ||
495 | |||
496 | |||
497 | /** | ||
176 | * Convert a port policy to a regular expression. Note: this is a | 498 | * Convert a port policy to a regular expression. Note: this is a |
177 | * very simplistic implementation, we might want to consider doing | 499 | * very simplistic implementation, we might want to consider doing |
178 | * something more sophisiticated (resulting in smaller regular | 500 | * something more sophisiticated (resulting in smaller regular |
@@ -205,37 +527,42 @@ port_to_regex (const struct GNUNET_STRINGS_PortPolicy *pp) | |||
205 | } | 527 | } |
206 | if (pp->end_port < pp->start_port) | 528 | if (pp->end_port < pp->start_port) |
207 | return NULL; | 529 | return NULL; |
208 | cnt = pp->end_port - pp->start_port + 1; | 530 | |
209 | if (GNUNET_YES == pp->negate_portrange) | 531 | if (GNUNET_YES == pp->negate_portrange) |
210 | cnt = 0xFFFF - cnt; | ||
211 | reg = GNUNET_malloc (cnt * 5 + 1); | ||
212 | pos = reg; | ||
213 | for (i=1;i<=0xFFFF;i++) | ||
214 | { | 532 | { |
215 | if ( ( (i >= pp->start_port) && (i <= pp->end_port) ) ^ | 533 | ret = compute_policy (0, 0xFFFF, 0x1000, pp); |
216 | (GNUNET_YES == pp->negate_portrange) ) | 534 | } |
535 | else | ||
536 | { | ||
537 | cnt = pp->end_port - pp->start_port + 1; | ||
538 | reg = GNUNET_malloc (cnt * 5 + 1); | ||
539 | pos = reg; | ||
540 | for (i=1;i<=0xFFFF;i++) | ||
217 | { | 541 | { |
218 | if (pos == reg) | 542 | if ( (i >= pp->start_port) && (i <= pp->end_port) ) |
219 | { | ||
220 | GNUNET_snprintf (pos, | ||
221 | 5, | ||
222 | "%04X", | ||
223 | i); | ||
224 | } | ||
225 | else | ||
226 | { | 543 | { |
227 | GNUNET_snprintf (pos, | 544 | if (pos == reg) |
228 | 6, | 545 | { |
229 | "|%04X", | 546 | GNUNET_snprintf (pos, |
230 | i); | 547 | 5, |
548 | "%04X", | ||
549 | i); | ||
550 | } | ||
551 | else | ||
552 | { | ||
553 | GNUNET_snprintf (pos, | ||
554 | 6, | ||
555 | "|%04X", | ||
556 | i); | ||
557 | } | ||
558 | pos += strlen (pos); | ||
231 | } | 559 | } |
232 | pos += strlen (pos); | ||
233 | } | 560 | } |
561 | GNUNET_asprintf (&ret, | ||
562 | "(%s)", | ||
563 | reg); | ||
564 | GNUNET_free (reg); | ||
234 | } | 565 | } |
235 | GNUNET_asprintf (&ret, | ||
236 | "(%s)", | ||
237 | reg); | ||
238 | GNUNET_free (reg); | ||
239 | return ret; | 566 | return ret; |
240 | } | 567 | } |
241 | 568 | ||
diff --git a/src/tun/test_regex.c b/src/tun/test_regex.c index 3f0f898a9..21a2eed1e 100644 --- a/src/tun/test_regex.c +++ b/src/tun/test_regex.c | |||
@@ -153,7 +153,10 @@ main (int argc, char *argv[]) | |||
153 | "4-(0050|0051)-C001...."); | 153 | "4-(0050|0051)-C001...."); |
154 | error += | 154 | error += |
155 | test_policy4toregex ("192.1.0.0/8:!3-65535;", | 155 | test_policy4toregex ("192.1.0.0/8:!3-65535;", |
156 | "4-(0001|0002)-C0......"); | 156 | "4-000(0|1|2)-C0......"); |
157 | error += | ||
158 | test_policy4toregex ("192.1.0.0/8:!25-56;", | ||
159 | "4-(0(0(0.|1(0|1|2|3|4|5|6|7|8)|3(9|A|B|C|D|E|F)|(4|5|6|7|8|9|A|B|C|D|E|F).)|(1|2|3|4|5|6|7|8|9|A|B|C|D|E|F)..)|(1|2|3|4|5|6|7|8|9|A|B|C|D|E|F)...)-C0......"); | ||
157 | error += | 160 | error += |
158 | test_policy6toregex ("E1E1::1;", | 161 | test_policy6toregex ("E1E1::1;", |
159 | "6-....-E1E10000000000000000000000000001"); | 162 | "6-....-E1E10000000000000000000000000001"); |