Print this page
OS-7667 IPFilter needs to keep and report state for cloud firewall logging
Portions contributed by: Mike Gerdts <mike.gerdts@joyent.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/cmd/ipf/tools/lexer.c
+++ new/usr/src/cmd/ipf/tools/lexer.c
1 1 /*
2 2 * Copyright (C) 2002-2008 by Darren Reed.
3 3 *
4 4 * See the IPFILTER.LICENCE file for details on licencing.
5 5 *
6 6 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
7 7 * Use is subject to license terms.
8 + * Copyright 2019 Joyent, Inc.
8 9 */
9 10
10 11 #include <ctype.h>
11 12 #include "ipf.h"
12 13 #ifdef IPFILTER_SCAN
13 14 # include "netinet/ip_scan.h"
14 15 #endif
15 16 #include <sys/ioctl.h>
16 17 #include <syslog.h>
18 +#include <uuid/uuid.h>
17 19 #ifdef TEST_LEXER
18 20 # define NO_YACC
19 21 union {
20 22 int num;
21 23 char *str;
22 24 struct in_addr ipa;
23 25 i6addr_t ip6;
26 + uuid_t uuid;
24 27 } yylval;
25 28 #endif
26 29 #include "lexer.h"
27 30 #include "y.tab.h"
28 31
29 32 FILE *yyin;
30 33
31 34 #define ishex(c) (ISDIGIT(c) || ((c) >= 'a' && (c) <= 'f') || \
32 35 ((c) >= 'A' && (c) <= 'F'))
33 36 #define TOOLONG -3
34 37
35 38 extern int string_start;
36 39 extern int string_end;
37 40 extern char *string_val;
38 41 extern int pos;
39 42 extern int yydebug;
40 43
41 44 char *yystr = NULL;
42 45 int yytext[YYBUFSIZ+1];
43 46 char yychars[YYBUFSIZ+1];
44 47 int yylineNum = 1;
45 48 int yypos = 0;
46 49 int yylast = -1;
47 50 int yyexpectaddr = 0;
48 51 int yybreakondot = 0;
49 52 int yyvarnext = 0;
50 53 int yytokentype = 0;
51 54 wordtab_t *yywordtab = NULL;
52 55 int yysavedepth = 0;
53 56 wordtab_t *yysavewords[30];
54 57
55 58
56 59 static wordtab_t *yyfindkey __P((char *));
57 60 static int yygetc __P((int));
58 61 static void yyunputc __P((int));
59 62 static int yyswallow __P((int));
60 63 static char *yytexttostr __P((int, int));
61 64 static void yystrtotext __P((char *));
62 65 static char *yytexttochar __P((void));
63 66
64 67 static int yygetc(docont)
65 68 int docont;
66 69 {
67 70 int c;
68 71
69 72 if (yypos < yylast) {
70 73 c = yytext[yypos++];
71 74 if (c == '\n')
72 75 yylineNum++;
73 76 return c;
74 77 }
75 78
76 79 if (yypos == YYBUFSIZ)
77 80 return TOOLONG;
78 81
79 82 if (pos >= string_start && pos <= string_end) {
80 83 c = string_val[pos - string_start];
81 84 yypos++;
82 85 } else {
83 86 c = fgetc(yyin);
84 87 if (docont && (c == '\\')) {
85 88 c = fgetc(yyin);
86 89 if (c == '\n') {
87 90 yylineNum++;
88 91 c = fgetc(yyin);
89 92 }
90 93 }
91 94 }
92 95 if (c == '\n')
93 96 yylineNum++;
94 97 yytext[yypos++] = c;
95 98 yylast = yypos;
96 99 yytext[yypos] = '\0';
97 100
98 101 return c;
99 102 }
100 103
101 104
102 105 static void yyunputc(c)
103 106 int c;
104 107 {
105 108 if (c == '\n')
106 109 yylineNum--;
107 110 yytext[--yypos] = c;
108 111 }
109 112
110 113
111 114 static int yyswallow(last)
112 115 int last;
113 116 {
114 117 int c;
115 118
116 119 while (((c = yygetc(0)) > '\0') && (c != last))
117 120 ;
118 121
119 122 if (c != EOF)
120 123 yyunputc(c);
121 124 if (c == last)
122 125 return 0;
123 126 return -1;
124 127 }
125 128
126 129
127 130 static char *yytexttochar()
128 131 {
129 132 int i;
130 133
131 134 for (i = 0; i < yypos; i++)
132 135 yychars[i] = (char)(yytext[i] & 0xff);
133 136 yychars[i] = '\0';
134 137 return yychars;
135 138 }
136 139
137 140
138 141 static void yystrtotext(str)
139 142 char *str;
140 143 {
141 144 int len;
142 145 char *s;
143 146
144 147 len = strlen(str);
145 148 if (len > YYBUFSIZ)
146 149 len = YYBUFSIZ;
147 150
148 151 for (s = str; *s != '\0' && len > 0; s++, len--)
149 152 yytext[yylast++] = *s;
150 153 yytext[yylast] = '\0';
151 154 }
152 155
153 156
154 157 static char *yytexttostr(offset, max)
155 158 int offset, max;
156 159 {
157 160 char *str;
158 161 int i;
159 162
160 163 if ((yytext[offset] == '\'' || yytext[offset] == '"') &&
161 164 (yytext[offset] == yytext[offset + max - 1])) {
162 165 offset++;
163 166 max--;
164 167 }
165 168
166 169 if (max > yylast)
167 170 max = yylast;
168 171 str = malloc(max + 1);
169 172 if (str != NULL) {
170 173 for (i = offset; i < max; i++)
171 174 str[i - offset] = (char)(yytext[i] & 0xff);
172 175 str[i - offset] = '\0';
173 176 }
174 177 return str;
175 178 }
176 179
177 180
178 181 int yylex()
179 182 {
180 183 int c, n, isbuilding, rval, lnext, nokey = 0;
181 184 char *name;
182 185
183 186 isbuilding = 0;
184 187 lnext = 0;
185 188 rval = 0;
186 189
187 190 if (yystr != NULL) {
188 191 free(yystr);
189 192 yystr = NULL;
190 193 }
191 194
192 195 nextchar:
193 196 c = yygetc(0);
194 197 if (yydebug > 1)
195 198 printf("yygetc = (%x) %c [%*.*s]\n", c, c, yypos, yypos,
196 199 yytexttochar());
197 200
198 201 switch (c)
199 202 {
200 203 case '\n' :
201 204 lnext = 0;
202 205 nokey = 0;
203 206 /* FALLTHROUGH */
204 207 case '\t' :
205 208 case '\r' :
206 209 case ' ' :
207 210 if (isbuilding == 1) {
208 211 yyunputc(c);
209 212 goto done;
210 213 }
211 214 if (yylast > yypos) {
212 215 bcopy(yytext + yypos, yytext,
213 216 sizeof(yytext[0]) * (yylast - yypos + 1));
214 217 }
215 218 yylast -= yypos;
216 219 yypos = 0;
217 220 lnext = 0;
218 221 nokey = 0;
219 222 goto nextchar;
220 223
221 224 case '\\' :
222 225 if (lnext == 0) {
223 226 lnext = 1;
224 227 if (yylast == yypos) {
225 228 yylast--;
226 229 yypos--;
227 230 } else
228 231 yypos--;
229 232 if (yypos == 0)
230 233 nokey = 1;
231 234 goto nextchar;
232 235 }
233 236 break;
234 237 }
235 238
236 239 if (lnext == 1) {
237 240 lnext = 0;
238 241 if ((isbuilding == 0) && !ISALNUM(c)) {
239 242 return c;
240 243 }
241 244 goto nextchar;
242 245 }
243 246
244 247 switch (c)
245 248 {
246 249 case '#' :
247 250 if (isbuilding == 1) {
248 251 yyunputc(c);
249 252 goto done;
250 253 }
251 254 yyswallow('\n');
252 255 rval = YY_COMMENT;
253 256 goto done;
254 257
255 258 case '$' :
256 259 if (isbuilding == 1) {
257 260 yyunputc(c);
258 261 goto done;
259 262 }
260 263 n = yygetc(0);
261 264 if (n == '{') {
262 265 if (yyswallow('}') == -1) {
263 266 rval = -2;
264 267 goto done;
265 268 }
266 269 (void) yygetc(0);
267 270 } else {
268 271 if (!ISALPHA(n)) {
269 272 yyunputc(n);
270 273 break;
271 274 }
272 275 do {
273 276 n = yygetc(1);
274 277 } while (ISALPHA(n) || ISDIGIT(n) || n == '_');
275 278 yyunputc(n);
276 279 }
277 280
278 281 name = yytexttostr(1, yypos); /* skip $ */
279 282
280 283 if (name != NULL) {
281 284 string_val = get_variable(name, NULL, yylineNum);
282 285 free(name);
283 286 if (string_val != NULL) {
284 287 name = yytexttostr(yypos, yylast);
285 288 if (name != NULL) {
286 289 yypos = 0;
287 290 yylast = 0;
288 291 yystrtotext(string_val);
289 292 yystrtotext(name);
290 293 free(string_val);
291 294 free(name);
292 295 goto nextchar;
293 296 }
294 297 free(string_val);
295 298 }
296 299 }
297 300 break;
298 301
299 302 case '\'':
300 303 case '"' :
301 304 if (isbuilding == 1) {
302 305 goto done;
303 306 }
304 307 do {
305 308 n = yygetc(1);
306 309 if (n == EOF || n == TOOLONG) {
307 310 rval = -2;
308 311 goto done;
309 312 }
310 313 if (n == '\n') {
311 314 yyunputc(' ');
312 315 yypos++;
313 316 }
314 317 } while (n != c);
315 318 rval = YY_STR;
316 319 goto done;
317 320 /* NOTREACHED */
318 321
319 322 case EOF :
320 323 yylineNum = 1;
321 324 yypos = 0;
322 325 yylast = -1;
323 326 yyexpectaddr = 0;
324 327 yybreakondot = 0;
325 328 yyvarnext = 0;
326 329 yytokentype = 0;
327 330 return 0;
328 331 }
329 332
330 333 if (strchr("=,/;{}()@", c) != NULL) {
331 334 if (isbuilding == 1) {
332 335 yyunputc(c);
333 336 goto done;
334 337 }
335 338 rval = c;
336 339 goto done;
337 340 } else if (c == '.') {
338 341 if (isbuilding == 0) {
339 342 rval = c;
340 343 goto done;
341 344 }
342 345 if (yybreakondot != 0) {
343 346 yyunputc(c);
344 347 goto done;
345 348 }
346 349 }
347 350
348 351 switch (c)
349 352 {
350 353 case '-' :
351 354 if (yyexpectaddr)
352 355 break;
353 356 if (isbuilding == 1)
354 357 break;
355 358 n = yygetc(0);
356 359 if (n == '>') {
357 360 isbuilding = 1;
358 361 goto done;
359 362 }
360 363 yyunputc(n);
361 364 rval = '-';
362 365 goto done;
363 366
364 367 case '!' :
365 368 if (isbuilding == 1) {
366 369 yyunputc(c);
367 370 goto done;
368 371 }
369 372 n = yygetc(0);
370 373 if (n == '=') {
371 374 rval = YY_CMP_NE;
372 375 goto done;
373 376 }
374 377 yyunputc(n);
375 378 rval = '!';
376 379 goto done;
377 380
378 381 case '<' :
379 382 if (yyexpectaddr)
380 383 break;
381 384 if (isbuilding == 1) {
382 385 yyunputc(c);
383 386 goto done;
384 387 }
385 388 n = yygetc(0);
386 389 if (n == '=') {
387 390 rval = YY_CMP_LE;
388 391 goto done;
389 392 }
390 393 if (n == '>') {
391 394 rval = YY_RANGE_OUT;
392 395 goto done;
393 396 }
394 397 yyunputc(n);
395 398 rval = YY_CMP_LT;
396 399 goto done;
397 400
398 401 case '>' :
399 402 if (yyexpectaddr)
400 403 break;
401 404 if (isbuilding == 1) {
402 405 yyunputc(c);
403 406 goto done;
404 407 }
405 408 n = yygetc(0);
406 409 if (n == '=') {
407 410 rval = YY_CMP_GE;
408 411 goto done;
409 412 }
410 413 if (n == '<') {
411 414 rval = YY_RANGE_IN;
412 415 goto done;
413 416 }
414 417 yyunputc(n);
415 418 rval = YY_CMP_GT;
416 419 goto done;
417 420 }
418 421
419 422 /*
420 423 * Now for the reason this is here...IPv6 address parsing.
421 424 * The longest string we can expect is of this form:
422 425 * 0000:0000:0000:0000:0000:0000:000.000.000.000
423 426 * not:
424 427 * 0000:0000:0000:0000:0000:0000:0000:0000
425 428 */
426 429 #ifdef USE_INET6
427 430 if (isbuilding == 0 && (ishex(c) || c == ':')) {
428 431 char ipv6buf[45 + 1], *s, oc;
429 432 int start;
430 433
431 434 start = yypos;
432 435 s = ipv6buf;
433 436 oc = c;
434 437
435 438 /*
436 439 * Perhaps we should implement stricter controls on what we
437 440 * swallow up here, but surely it would just be duplicating
438 441 * the code in inet_pton() anyway.
439 442 */
440 443 do {
441 444 *s++ = c;
442 445 c = yygetc(1);
443 446 } while ((ishex(c) || c == ':' || c == '.') &&
444 447 (s - ipv6buf < 46));
445 448 yyunputc(c);
446 449 *s = '\0';
447 450
|
↓ open down ↓ |
414 lines elided |
↑ open up ↑ |
448 451 if (inet_pton(AF_INET6, ipv6buf, &yylval.ip6) == 1) {
449 452 rval = YY_IPV6;
450 453 yyexpectaddr = 0;
451 454 goto done;
452 455 }
453 456 yypos = start;
454 457 c = oc;
455 458 }
456 459 #endif
457 460
461 + /*
462 + * UUID: 2426e38c-9f63-c0b8-cfd5-9aaeaf992d42 or uppercase
463 + */
464 + if (isbuilding == 0 && (ishex(c) || c == '-')) {
465 + char uuidbuf[UUID_PRINTABLE_STRING_LENGTH], *s, oc;
466 + int start;
467 +
468 + start = yypos;
469 + s = uuidbuf;
470 + oc = c;
471 +
472 + /*
473 + * Don't worry about exact position of hexdigits and hyphens
474 + * because uuid_parse() will provide the sanity check.
475 + */
476 + do {
477 + *s++ = c;
478 + c = yygetc(1);
479 + } while ((ishex(c) || c == '-') &&
480 + (s - uuidbuf < sizeof (uuidbuf)));
481 + yyunputc(c);
482 + *s = '\0';
483 +
484 + if (uuid_parse(uuidbuf, yylval.uuid) == 0) {
485 + rval = YY_UUID;
486 + yyexpectaddr = 0;
487 + goto done;
488 + }
489 + yypos = start;
490 + c = oc;
491 + }
492 +
493 +
458 494 if (c == ':') {
459 495 if (isbuilding == 1) {
460 496 yyunputc(c);
461 497 goto done;
462 498 }
463 499 rval = ':';
464 500 goto done;
465 501 }
466 502
467 503 if (isbuilding == 0 && c == '0') {
468 504 n = yygetc(0);
469 505 if (n == 'x') {
470 506 do {
471 507 n = yygetc(1);
472 508 } while (ishex(n));
473 509 yyunputc(n);
474 510 rval = YY_HEX;
475 511 goto done;
476 512 }
477 513 yyunputc(n);
478 514 }
479 515
480 516 /*
481 517 * No negative numbers with leading - sign..
482 518 */
483 519 if (isbuilding == 0 && ISDIGIT(c)) {
484 520 do {
485 521 n = yygetc(1);
486 522 } while (ISDIGIT(n));
487 523 yyunputc(n);
488 524 rval = YY_NUMBER;
489 525 goto done;
490 526 }
491 527
492 528 isbuilding = 1;
493 529 goto nextchar;
494 530
495 531 done:
496 532 yystr = yytexttostr(0, yypos);
497 533
498 534 if (yydebug)
499 535 printf("isbuilding %d yyvarnext %d nokey %d\n",
500 536 isbuilding, yyvarnext, nokey);
501 537 if (isbuilding == 1) {
502 538 wordtab_t *w;
503 539
504 540 w = NULL;
505 541 isbuilding = 0;
506 542
507 543 if ((yyvarnext == 0) && (nokey == 0)) {
508 544 w = yyfindkey(yystr);
509 545 if (w == NULL && yywordtab != NULL) {
510 546 yyresetdict();
511 547 w = yyfindkey(yystr);
512 548 }
513 549 } else
514 550 yyvarnext = 0;
515 551 if (w != NULL)
516 552 rval = w->w_value;
517 553 else
518 554 rval = YY_STR;
519 555 }
520 556
521 557 if (rval == YY_STR && yysavedepth > 0)
522 558 yyresetdict();
523 559
524 560 yytokentype = rval;
525 561
526 562 if (yydebug)
527 563 printf("lexed(%s) [%d,%d,%d] => %d @%d\n", yystr, string_start,
528 564 string_end, pos, rval, yysavedepth);
529 565
530 566 switch (rval)
531 567 {
532 568 case YY_NUMBER :
533 569 sscanf(yystr, "%u", &yylval.num);
534 570 break;
535 571
536 572 case YY_HEX :
537 573 sscanf(yystr, "0x%x", (u_int *)&yylval.num);
538 574 break;
539 575
540 576 case YY_STR :
541 577 yylval.str = strdup(yystr);
542 578 break;
543 579
544 580 default :
545 581 break;
546 582 }
547 583
548 584 if (yylast > 0) {
549 585 bcopy(yytext + yypos, yytext,
550 586 sizeof(yytext[0]) * (yylast - yypos + 1));
551 587 yylast -= yypos;
552 588 yypos = 0;
553 589 }
554 590
555 591 return rval;
556 592 }
557 593
558 594
559 595 static wordtab_t *yyfindkey(key)
560 596 char *key;
561 597 {
562 598 wordtab_t *w;
563 599
564 600 if (yywordtab == NULL)
565 601 return NULL;
566 602
567 603 for (w = yywordtab; w->w_word != 0; w++)
568 604 if (strcasecmp(key, w->w_word) == 0)
569 605 return w;
570 606 return NULL;
571 607 }
572 608
573 609
574 610 char *yykeytostr(num)
575 611 int num;
576 612 {
577 613 wordtab_t *w;
578 614
579 615 if (yywordtab == NULL)
580 616 return "<unknown>";
581 617
582 618 for (w = yywordtab; w->w_word; w++)
583 619 if (w->w_value == num)
584 620 return w->w_word;
585 621 return "<unknown>";
586 622 }
587 623
588 624
589 625 wordtab_t *yysettab(words)
590 626 wordtab_t *words;
591 627 {
592 628 wordtab_t *save;
593 629
594 630 save = yywordtab;
595 631 yywordtab = words;
596 632 return save;
597 633 }
598 634
599 635
600 636 void yyerror(msg)
601 637 char *msg;
602 638 {
603 639 char *txt, letter[2];
604 640 int freetxt = 0;
605 641
606 642 if (yytokentype < 256) {
607 643 letter[0] = yytokentype;
608 644 letter[1] = '\0';
609 645 txt = letter;
610 646 } else if (yytokentype == YY_STR || yytokentype == YY_HEX ||
611 647 yytokentype == YY_NUMBER) {
612 648 if (yystr == NULL) {
613 649 txt = yytexttostr(yypos, YYBUFSIZ);
614 650 if (txt == NULL) {
615 651 fprintf(stderr, "sorry, out of memory,"
616 652 " bailing out\n");
617 653 exit(1);
618 654 }
619 655 freetxt = 1;
620 656 } else
621 657 txt = yystr;
622 658 } else {
623 659 txt = yykeytostr(yytokentype);
624 660 if (txt == NULL) {
625 661 fprintf(stderr, "sorry, out of memory,"
626 662 " bailing out\n");
627 663 exit(1);
628 664 }
629 665 }
630 666 fprintf(stderr, "%s error at \"%s\", line %d\n", msg, txt, yylineNum);
631 667 if (freetxt == 1)
632 668 free(txt);
633 669 exit(1);
634 670 }
635 671
636 672
637 673 void yysetdict(newdict)
638 674 wordtab_t *newdict;
639 675 {
640 676 if (yysavedepth == sizeof(yysavewords)/sizeof(yysavewords[0])) {
641 677 fprintf(stderr, "%d: at maximum dictionary depth\n",
642 678 yylineNum);
643 679 return;
644 680 }
645 681
646 682 yysavewords[yysavedepth++] = yysettab(newdict);
647 683 if (yydebug)
648 684 printf("yysavedepth++ => %d\n", yysavedepth);
649 685 }
650 686
651 687 void yyresetdict()
652 688 {
653 689 if (yydebug)
654 690 printf("yyresetdict(%d)\n", yysavedepth);
655 691 if (yysavedepth > 0) {
656 692 yysettab(yysavewords[--yysavedepth]);
657 693 if (yydebug)
658 694 printf("yysavedepth-- => %d\n", yysavedepth);
659 695 }
660 696 }
661 697
662 698
663 699
664 700 #ifdef TEST_LEXER
665 701 int main(argc, argv)
666 702 int argc;
667 703 char *argv[];
668 704 {
669 705 int n;
670 706
671 707 yyin = stdin;
672 708
673 709 while ((n = yylex()) != 0)
674 710 printf("%d.n = %d [%s] %d %d\n",
675 711 yylineNum, n, yystr, yypos, yylast);
676 712 }
677 713 #endif
|
↓ open down ↓ |
210 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX