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