lexer.c revision 161357
1251876Speter/* $FreeBSD: head/contrib/ipfilter/tools/lexer.c 161357 2006-08-16 12:23:02Z guido $ */ 2251876Speter 3251876Speter/* 4251876Speter * Copyright (C) 2003 by Darren Reed. 5251876Speter * 6251876Speter * See the IPFILTER.LICENCE file for details on licencing. 7251876Speter */ 8251876Speter#include <ctype.h> 9251876Speter#include "ipf.h" 10251876Speter#ifdef IPFILTER_SCAN 11251876Speter# include "netinet/ip_scan.h" 12251876Speter#endif 13251876Speter#include <sys/ioctl.h> 14251876Speter#include <syslog.h> 15251876Speter#ifdef TEST_LEXER 16251876Speter# define NO_YACC 17251876Speterunion { 18251876Speter int num; 19251876Speter char *str; 20251876Speter struct in_addr ipa; 21251876Speter i6addr_t ip6; 22251876Speter} yylval; 23251876Speter#endif 24251876Speter#include "lexer.h" 25251876Speter#include "y.tab.h" 26251876Speter 27251876SpeterFILE *yyin; 28251876Speter 29251876Speter#define ishex(c) (ISDIGIT(c) || ((c) >= 'a' && (c) <= 'f') || \ 30251876Speter ((c) >= 'A' && (c) <= 'F')) 31251876Speter#define TOOLONG -3 32251876Speter 33251876Speterextern int string_start; 34251876Speterextern int string_end; 35251876Speterextern char *string_val; 36251876Speterextern int pos; 37251876Speterextern int yydebug; 38251876Speter 39251876Speterchar *yystr = NULL; 40251876Speterint yytext[YYBUFSIZ+1]; 41251876Speterint yylineNum = 1; 42251876Speterint yypos = 0; 43251876Speterint yylast = -1; 44251876Speterint yyexpectaddr = 0; 45251876Speterint yybreakondot = 0; 46251876Speterint yyvarnext = 0; 47251876Speterint yytokentype = 0; 48251876Speterwordtab_t *yywordtab = NULL; 49251876Speterint yysavedepth = 0; 50251876Speterwordtab_t *yysavewords[30]; 51251876Speter 52251876Speter 53251876Speterstatic wordtab_t *yyfindkey __P((char *)); 54251876Speterstatic int yygetc __P((void)); 55251876Speterstatic void yyunputc __P((int)); 56251876Speterstatic int yyswallow __P((int)); 57251876Speterstatic char *yytexttostr __P((int, int)); 58251876Speterstatic void yystrtotext __P((char *)); 59251876Speter 60251876Speterstatic int yygetc() 61251876Speter{ 62251876Speter int c; 63251876Speter 64251876Speter if (yypos < yylast) { 65251876Speter c = yytext[yypos++]; 66251876Speter if (c == '\n') 67251876Speter yylineNum++; 68251876Speter return c; 69251876Speter } 70251876Speter 71251876Speter if (yypos == YYBUFSIZ) 72251876Speter return TOOLONG; 73251876Speter 74251876Speter if (pos >= string_start && pos <= string_end) { 75251876Speter c = string_val[pos - string_start]; 76251876Speter yypos++; 77251876Speter } else { 78251876Speter c = fgetc(yyin); 79251876Speter } 80251876Speter if (c == '\n') 81251876Speter yylineNum++; 82251876Speter yytext[yypos++] = c; 83251876Speter yylast = yypos; 84251876Speter yytext[yypos] = '\0'; 85251876Speter 86251876Speter return c; 87251876Speter} 88251876Speter 89251876Speter 90251876Speterstatic void yyunputc(c) 91251876Speterint c; 92251876Speter{ 93251876Speter if (c == '\n') 94251876Speter yylineNum--; 95251876Speter yytext[--yypos] = c; 96251876Speter} 97251876Speter 98251876Speter 99251876Speterstatic int yyswallow(last) 100251876Speterint last; 101251876Speter{ 102251876Speter int c; 103251876Speter 104251876Speter while (((c = yygetc()) > '\0') && (c != last)) 105251876Speter ; 106251876Speter 107251876Speter if (c != EOF) 108251876Speter yyunputc(c); 109251876Speter if (c == last) 110251876Speter return 0; 111251876Speter return -1; 112251876Speter} 113251876Speter 114251876Speter 115251876Speterstatic void yystrtotext(str) 116251876Speterchar *str; 117251876Speter{ 118251876Speter int len; 119251876Speter char *s; 120251876Speter 121251876Speter len = strlen(str); 122251876Speter if (len > YYBUFSIZ) 123251876Speter len = YYBUFSIZ; 124251876Speter 125251876Speter for (s = str; *s != '\0' && len > 0; s++, len--) 126251876Speter yytext[yylast++] = *s; 127251876Speter yytext[yylast] = '\0'; 128251876Speter} 129251876Speter 130251876Speter 131251876Speterstatic char *yytexttostr(offset, max) 132251876Speterint offset, max; 133251876Speter{ 134251876Speter char *str; 135251876Speter int i; 136251876Speter 137251876Speter if ((yytext[offset] == '\'' || yytext[offset] == '"') && 138251876Speter (yytext[offset] == yytext[offset + max - 1])) { 139251876Speter offset++; 140251876Speter max--; 141251876Speter } 142251876Speter 143251876Speter if (max > yylast) 144251876Speter max = yylast; 145251876Speter str = malloc(max + 1); 146251876Speter if (str != NULL) { 147251876Speter for (i = offset; i < max; i++) 148251876Speter str[i - offset] = (char)(yytext[i] & 0xff); 149251876Speter str[i - offset] = '\0'; 150251876Speter } 151251876Speter return str; 152251876Speter} 153251876Speter 154251876Speter 155251876Speterint yylex() 156251876Speter{ 157251876Speter int c, n, isbuilding, rval, lnext, nokey = 0; 158251876Speter char *name; 159251876Speter 160251876Speter isbuilding = 0; 161251876Speter lnext = 0; 162251876Speter rval = 0; 163251876Speter 164251876Speter if (yystr != NULL) { 165251876Speter free(yystr); 166251876Speter yystr = NULL; 167251876Speter } 168251876Speter 169251876Speternextchar: 170251876Speter c = yygetc(); 171251876Speter 172251876Speter switch (c) 173251876Speter { 174251876Speter case '\n' : 175251876Speter lnext = 0; 176251876Speter nokey = 0; 177251876Speter case '\t' : 178251876Speter case '\r' : 179251876Speter case ' ' : 180251876Speter if (isbuilding == 1) { 181251876Speter yyunputc(c); 182251876Speter goto done; 183251876Speter } 184251876Speter if (yylast > yypos) { 185251876Speter bcopy(yytext + yypos, yytext, 186251876Speter sizeof(yytext[0]) * (yylast - yypos + 1)); 187251876Speter } 188251876Speter yylast -= yypos; 189251876Speter yypos = 0; 190251876Speter lnext = 0; 191251876Speter nokey = 0; 192251876Speter goto nextchar; 193251876Speter 194251876Speter case '\\' : 195251876Speter if (lnext == 0) { 196251876Speter lnext = 1; 197251876Speter if (yylast == yypos) { 198251876Speter yylast--; 199251876Speter yypos--; 200251876Speter } else 201251876Speter yypos--; 202251876Speter if (yypos == 0) 203251876Speter nokey = 1; 204251876Speter goto nextchar; 205251876Speter } 206251876Speter break; 207251876Speter } 208251876Speter 209251876Speter if (lnext == 1) { 210251876Speter lnext = 0; 211251876Speter if ((isbuilding == 0) && !ISALNUM(c)) { 212251876Speter return c; 213251876Speter } 214251876Speter goto nextchar; 215251876Speter } 216251876Speter 217251876Speter switch (c) 218251876Speter { 219251876Speter case '#' : 220251876Speter if (isbuilding == 1) { 221251876Speter yyunputc(c); 222251876Speter goto done; 223251876Speter } 224251876Speter yyswallow('\n'); 225251876Speter rval = YY_COMMENT; 226251876Speter goto nextchar; 227251876Speter 228251876Speter case '$' : 229251876Speter if (isbuilding == 1) { 230251876Speter yyunputc(c); 231251876Speter goto done; 232251876Speter } 233251876Speter n = yygetc(); 234251876Speter if (n == '{') { 235251876Speter if (yyswallow('}') == -1) { 236251876Speter rval = -2; 237251876Speter goto done; 238251876Speter } 239251876Speter (void) yygetc(); 240251876Speter } else { 241251876Speter if (!ISALPHA(n)) { 242251876Speter yyunputc(n); 243251876Speter break; 244251876Speter } 245251876Speter do { 246251876Speter n = yygetc(); 247251876Speter } while (ISALPHA(n) || ISDIGIT(n) || n == '_'); 248251876Speter yyunputc(n); 249251876Speter } 250251876Speter 251251876Speter name = yytexttostr(1, yypos); /* skip $ */ 252251876Speter 253251876Speter if (name != NULL) { 254251876Speter string_val = get_variable(name, NULL, yylineNum); 255251876Speter free(name); 256251876Speter if (string_val != NULL) { 257251876Speter name = yytexttostr(yypos, yylast); 258251876Speter if (name != NULL) { 259251876Speter yypos = 0; 260251876Speter yylast = 0; 261251876Speter yystrtotext(string_val); 262251876Speter yystrtotext(name); 263251876Speter free(string_val); 264251876Speter free(name); 265251876Speter goto nextchar; 266251876Speter } 267251876Speter free(string_val); 268251876Speter } 269251876Speter } 270251876Speter break; 271251876Speter 272251876Speter case '\'': 273251876Speter case '"' : 274251876Speter if (isbuilding == 1) { 275251876Speter goto done; 276251876Speter } 277251876Speter do { 278251876Speter n = yygetc(); 279251876Speter if (n == EOF || n == TOOLONG) { 280251876Speter rval = -2; 281251876Speter goto done; 282251876Speter } 283251876Speter if (n == '\n') { 284251876Speter yyunputc(' '); 285251876Speter yypos++; 286251876Speter } 287251876Speter } while (n != c); 288251876Speter yyunputc(n); 289251876Speter break; 290251876Speter 291251876Speter case EOF : 292251876Speter yylineNum = 1; 293251876Speter yypos = 0; 294251876Speter yylast = -1; 295251876Speter yyexpectaddr = 0; 296251876Speter yybreakondot = 0; 297251876Speter yyvarnext = 0; 298251876Speter yytokentype = 0; 299251876Speter return 0; 300251876Speter } 301251876Speter 302251876Speter if (strchr("=,/;{}()@", c) != NULL) { 303251876Speter if (isbuilding == 1) { 304251876Speter yyunputc(c); 305251876Speter goto done; 306251876Speter } 307251876Speter rval = c; 308251876Speter goto done; 309251876Speter } else if (c == '.') { 310251876Speter if (isbuilding == 0) { 311251876Speter rval = c; 312251876Speter goto done; 313251876Speter } 314251876Speter if (yybreakondot != 0) { 315251876Speter yyunputc(c); 316251876Speter goto done; 317251876Speter } 318251876Speter } 319251876Speter 320251876Speter switch (c) 321251876Speter { 322251876Speter case '-' : 323251876Speter if (yyexpectaddr) 324251876Speter break; 325251876Speter if (isbuilding == 1) 326251876Speter break; 327251876Speter n = yygetc(); 328253734Speter if (n == '>') { 329251876Speter isbuilding = 1; 330251876Speter goto done; 331251876Speter } 332251876Speter yyunputc(n); 333251876Speter rval = '-'; 334251876Speter goto done; 335251876Speter 336251876Speter case '!' : 337251876Speter if (isbuilding == 1) { 338251876Speter yyunputc(c); 339251876Speter goto done; 340251876Speter } 341251876Speter n = yygetc(); 342251876Speter if (n == '=') { 343251876Speter rval = YY_CMP_NE; 344251876Speter goto done; 345251876Speter } 346251876Speter yyunputc(n); 347251876Speter rval = '!'; 348251876Speter goto done; 349251876Speter 350251876Speter case '<' : 351251876Speter if (yyexpectaddr) 352251876Speter break; 353251876Speter if (isbuilding == 1) { 354251876Speter yyunputc(c); 355251876Speter goto done; 356251876Speter } 357251876Speter n = yygetc(); 358251876Speter if (n == '=') { 359251876Speter rval = YY_CMP_LE; 360251876Speter goto done; 361251876Speter } 362251876Speter if (n == '>') { 363251876Speter rval = YY_RANGE_OUT; 364251876Speter goto done; 365251876Speter } 366251876Speter yyunputc(n); 367251876Speter rval = YY_CMP_LT; 368251876Speter goto done; 369251876Speter 370251876Speter case '>' : 371251876Speter if (yyexpectaddr) 372251876Speter break; 373251876Speter if (isbuilding == 1) { 374251876Speter yyunputc(c); 375251876Speter goto done; 376251876Speter } 377251876Speter n = yygetc(); 378251876Speter if (n == '=') { 379251876Speter rval = YY_CMP_GE; 380251876Speter goto done; 381251876Speter } 382251876Speter if (n == '<') { 383251876Speter rval = YY_RANGE_IN; 384251876Speter goto done; 385251876Speter } 386251876Speter yyunputc(n); 387251876Speter rval = YY_CMP_GT; 388251876Speter goto done; 389251876Speter } 390251876Speter 391251876Speter /* 392251876Speter * Now for the reason this is here...IPv6 address parsing. 393251876Speter * The longest string we can expect is of this form: 394251876Speter * 0000:0000:0000:0000:0000:0000:000.000.000.000 395251876Speter * not: 396251876Speter * 0000:0000:0000:0000:0000:0000:0000:0000 397251876Speter */ 398251876Speter#ifdef USE_INET6 399251876Speter if (yyexpectaddr == 1 && isbuilding == 0 && (ishex(c) || c == ':')) { 400251876Speter char ipv6buf[45 + 1], *s, oc; 401251876Speter int start; 402251876Speter 403251876Speter start = yypos; 404251876Speter s = ipv6buf; 405251876Speter oc = c; 406251876Speter 407251876Speter /* 408251876Speter * Perhaps we should implement stricter controls on what we 409251876Speter * swallow up here, but surely it would just be duplicating 410251876Speter * the code in inet_pton() anyway. 411251876Speter */ 412251876Speter do { 413251876Speter *s++ = c; 414251876Speter c = yygetc(); 415251876Speter } while ((ishex(c) || c == ':' || c == '.') && 416251876Speter (s - ipv6buf < 46)); 417251876Speter yyunputc(c); 418251876Speter *s = '\0'; 419251876Speter 420251876Speter if (inet_pton(AF_INET6, ipv6buf, &yylval.ip6) == 1) { 421251876Speter rval = YY_IPV6; 422251876Speter yyexpectaddr = 0; 423251876Speter goto done; 424251876Speter } 425251876Speter yypos = start; 426251876Speter c = oc; 427251876Speter } 428251876Speter#endif 429251876Speter 430251876Speter if (c == ':') { 431251876Speter if (isbuilding == 1) { 432251876Speter yyunputc(c); 433251876Speter goto done; 434251876Speter } 435251876Speter rval = ':'; 436251876Speter goto done; 437251876Speter } 438251876Speter 439251876Speter if (isbuilding == 0 && c == '0') { 440251876Speter n = yygetc(); 441251876Speter if (n == 'x') { 442251876Speter do { 443251876Speter n = yygetc(); 444251876Speter } while (ishex(n)); 445251876Speter yyunputc(n); 446251876Speter rval = YY_HEX; 447251876Speter goto done; 448251876Speter } 449251876Speter yyunputc(n); 450251876Speter } 451251876Speter 452251876Speter /* 453251876Speter * No negative numbers with leading - sign.. 454251876Speter */ 455251876Speter if (isbuilding == 0 && ISDIGIT(c)) { 456251876Speter do { 457251876Speter n = yygetc(); 458251876Speter } while (ISDIGIT(n)); 459251876Speter yyunputc(n); 460251876Speter rval = YY_NUMBER; 461251876Speter goto done; 462251876Speter } 463251876Speter 464251876Speter isbuilding = 1; 465251876Speter goto nextchar; 466251876Speter 467251876Speterdone: 468251876Speter yystr = yytexttostr(0, yypos); 469251876Speter 470251876Speter if (isbuilding == 1) { 471251876Speter wordtab_t *w; 472251876Speter 473251876Speter w = NULL; 474251876Speter isbuilding = 0; 475251876Speter 476251876Speter if ((yyvarnext == 0) && (nokey == 0)) { 477251876Speter w = yyfindkey(yystr); 478251876Speter if (w == NULL && yywordtab != NULL) { 479251876Speter yyresetdict(); 480251876Speter w = yyfindkey(yystr); 481251876Speter } 482251876Speter } else 483251876Speter yyvarnext = 0; 484251876Speter if (w != NULL) 485251876Speter rval = w->w_value; 486251876Speter else 487251876Speter rval = YY_STR; 488251876Speter } 489251876Speter 490251876Speter if (rval == YY_STR && yysavedepth > 0) 491251876Speter yyresetdict(); 492251876Speter 493251876Speter yytokentype = rval; 494251876Speter 495251876Speter if (yydebug) 496251876Speter printf("lexed(%s) [%d,%d,%d] => %d\n", yystr, string_start, 497251876Speter string_end, pos, rval); 498251876Speter 499251876Speter switch (rval) 500251876Speter { 501251876Speter case YY_NUMBER : 502251876Speter sscanf(yystr, "%u", &yylval.num); 503251876Speter break; 504251876Speter 505251876Speter case YY_HEX : 506251876Speter sscanf(yystr, "0x%x", (u_int *)&yylval.num); 507251876Speter break; 508251876Speter 509251876Speter case YY_STR : 510251876Speter yylval.str = strdup(yystr); 511251876Speter break; 512251876Speter 513251876Speter default : 514251876Speter break; 515251876Speter } 516251876Speter 517251876Speter if (yylast > 0) { 518251876Speter bcopy(yytext + yypos, yytext, 519251876Speter sizeof(yytext[0]) * (yylast - yypos + 1)); 520251876Speter yylast -= yypos; 521251876Speter yypos = 0; 522251876Speter } 523251876Speter 524251876Speter return rval; 525251876Speter} 526251876Speter 527251876Speter 528251876Speterstatic wordtab_t *yyfindkey(key) 529251876Speterchar *key; 530251876Speter{ 531251876Speter wordtab_t *w; 532251876Speter 533251876Speter if (yywordtab == NULL) 534251876Speter return NULL; 535251876Speter 536251876Speter for (w = yywordtab; w->w_word != 0; w++) 537251876Speter if (strcasecmp(key, w->w_word) == 0) 538251876Speter return w; 539251876Speter return NULL; 540251876Speter} 541251876Speter 542251876Speter 543251876Speterchar *yykeytostr(num) 544251876Speterint num; 545251876Speter{ 546251876Speter wordtab_t *w; 547251876Speter 548251876Speter if (yywordtab == NULL) 549251876Speter return "<unknown>"; 550251876Speter 551251876Speter for (w = yywordtab; w->w_word; w++) 552251876Speter if (w->w_value == num) 553251876Speter return w->w_word; 554251876Speter return "<unknown>"; 555251876Speter} 556251876Speter 557251876Speter 558251876Speterwordtab_t *yysettab(words) 559251876Speterwordtab_t *words; 560251876Speter{ 561251876Speter wordtab_t *save; 562251876Speter 563251876Speter save = yywordtab; 564251876Speter yywordtab = words; 565251876Speter return save; 566251876Speter} 567251876Speter 568251876Speter 569251876Spetervoid yyerror(msg) 570251876Speterchar *msg; 571251876Speter{ 572251876Speter char *txt, letter[2]; 573251876Speter int freetxt = 0; 574251876Speter 575251876Speter if (yytokentype < 256) { 576251876Speter letter[0] = yytokentype; 577251876Speter letter[1] = '\0'; 578251876Speter txt = letter; 579251876Speter } else if (yytokentype == YY_STR || yytokentype == YY_HEX || 580251876Speter yytokentype == YY_NUMBER) { 581251876Speter if (yystr == NULL) { 582251876Speter txt = yytexttostr(yypos, YYBUFSIZ); 583251876Speter freetxt = 1; 584251876Speter } else 585251876Speter txt = yystr; 586251876Speter } else { 587251876Speter txt = yykeytostr(yytokentype); 588251876Speter } 589251876Speter fprintf(stderr, "%s error at \"%s\", line %d\n", msg, txt, yylineNum); 590251876Speter if (freetxt == 1) 591251876Speter free(txt); 592251876Speter exit(1); 593251876Speter} 594251876Speter 595251876Speter 596251876Spetervoid yysetdict(newdict) 597251876Speterwordtab_t *newdict; 598251876Speter{ 599251876Speter if (yysavedepth == sizeof(yysavewords)/sizeof(yysavewords[0])) { 600251876Speter fprintf(stderr, "%d: at maximum dictionary depth\n", 601251876Speter yylineNum); 602251876Speter return; 603251876Speter } 604251876Speter 605251876Speter yysavewords[yysavedepth++] = yysettab(newdict); 606251876Speter if (yydebug) 607251876Speter printf("yysavedepth++ => %d\n", yysavedepth); 608251876Speter} 609251876Speter 610251876Spetervoid yyresetdict() 611251876Speter{ 612251876Speter if (yysavedepth > 0) { 613251876Speter yysettab(yysavewords[--yysavedepth]); 614251876Speter if (yydebug) 615251876Speter printf("yysavedepth-- => %d\n", yysavedepth); 616251876Speter } 617251876Speter} 618251876Speter 619251876Speter 620251876Speter 621251876Speter#ifdef TEST_LEXER 622251876Speterint main(argc, argv) 623251876Speterint argc; 624251876Speterchar *argv[]; 625251876Speter{ 626251876Speter int n; 627251876Speter 628251876Speter yyin = stdin; 629251876Speter 630251876Speter while ((n = yylex()) != 0) 631251876Speter printf("%d.n = %d [%s] %d %d\n", 632251876Speter yylineNum, n, yystr, yypos, yylast); 633251876Speter} 634251876Speter#endif 635251876Speter