aboutsummaryrefslogtreecommitdiff
path: root/src/tun
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2014-01-12 20:19:43 +0000
committerChristian Grothoff <christian@grothoff.org>2014-01-12 20:19:43 +0000
commit75b754d269802f2072514d55b94946912c55e067 (patch)
tree4cb9f0c2baa0ddd55694b72936646427ed27932b /src/tun
parentf2a94edfe687f220160f2f58d92a53063ab98357 (diff)
downloadgnunet-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.c375
-rw-r--r--src/tun/test_regex.c5
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 */
182static int
183needs_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 */
224static char *
225compute_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");