ipscan_y.y revision 145510
1/* $NetBSD$ */ 2 3%{ 4#include <sys/types.h> 5#include <sys/ioctl.h> 6#include "ipf.h" 7#include "opts.h" 8#include "kmem.h" 9#include "ipscan_l.h" 10#include "netinet/ip_scan.h" 11 12#define YYDEBUG 1 13 14extern char *optarg; 15extern void yyerror __P((char *)); 16extern int yyparse __P((void)); 17extern int yylex __P((void)); 18extern int yydebug; 19extern FILE *yyin; 20extern int yylineNum; 21extern void printbuf __P((char *, int, int)); 22 23 24void printent __P((ipscan_t *)); 25void showlist __P((void)); 26int getportnum __P((char *)); 27struct in_addr gethostip __P((char *)); 28struct in_addr combine __P((int, int, int, int)); 29char **makepair __P((char *, char *)); 30void addtag __P((char *, char **, char **, struct action *)); 31int cram __P((char *, char *)); 32void usage __P((char *)); 33int main __P((int, char **)); 34 35int opts = 0; 36int fd = -1; 37 38 39%} 40 41%union { 42 char *str; 43 char **astr; 44 u_32_t num; 45 struct in_addr ipa; 46 struct action act; 47 union i6addr ip6; 48} 49 50%type <str> tag 51%type <act> action redirect result 52%type <ipa> ipaddr 53%type <num> portnum 54%type <astr> matchup onehalf twohalves 55 56%token <num> YY_NUMBER YY_HEX 57%token <str> YY_STR 58%token YY_COMMENT 59%token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT 60%token YY_RANGE_OUT YY_RANGE_IN 61%token <ip6> YY_IPV6 62%token IPSL_START IPSL_STARTGROUP IPSL_CONTENT 63 64%token IPSL_CLOSE IPSL_TRACK IPSL_EOF IPSL_REDIRECT IPSL_ELSE 65 66%% 67file: line ';' 68 | assign ';' 69 | file line ';' 70 | file assign ';' 71 | YY_COMMENT 72 ; 73 74line: IPSL_START dline 75 | IPSL_STARTGROUP gline 76 | IPSL_CONTENT oline 77 ; 78 79dline: cline { resetlexer(); } 80 | sline { resetlexer(); } 81 | csline { resetlexer(); } 82 ; 83 84gline: YY_STR ':' glist '=' action 85 ; 86 87oline: cline 88 | sline 89 | csline 90 ; 91 92assign: YY_STR assigning YY_STR 93 { set_variable($1, $3); 94 resetlexer(); 95 free($1); 96 free($3); 97 } 98 ; 99 100assigning: 101 '=' { yyvarnext = 1; } 102 ; 103 104cline: tag ':' matchup '=' action { addtag($1, $3, NULL, &$5); } 105 ; 106 107sline: tag ':' '(' ')' ',' matchup '=' action { addtag($1, NULL, $6, &$8); } 108 ; 109 110csline: tag ':' matchup ',' matchup '=' action { addtag($1, $3, $5, &$7); } 111 ; 112 113glist: YY_STR 114 | glist ',' YY_STR 115 ; 116 117tag: YY_STR { $$ = $1; } 118 ; 119 120matchup: 121 onehalf { $$ = $1; } 122 | twohalves { $$ = $1; } 123 ; 124 125action: result { $$.act_val = $1.act_val; 126 $$.act_ip = $1.act_ip; 127 $$.act_port = $1.act_port; } 128 | result IPSL_ELSE result { $$.act_val = $1.act_val; 129 $$.act_else = $3.act_val; 130 if ($1.act_val == IPSL_REDIRECT) { 131 $$.act_ip = $1.act_ip; 132 $$.act_port = $1.act_port; 133 } 134 if ($3.act_val == IPSL_REDIRECT) { 135 $$.act_eip = $3.act_eip; 136 $$.act_eport = $3.act_eport; 137 } 138 } 139 140result: IPSL_CLOSE { $$.act_val = IPSL_CLOSE; } 141 | IPSL_TRACK { $$.act_val = IPSL_TRACK; } 142 | redirect { $$.act_val = IPSL_REDIRECT; 143 $$.act_ip = $1.act_ip; 144 $$.act_port = $1.act_port; } 145 ; 146 147onehalf: 148 '(' YY_STR ')' { $$ = makepair($2, NULL); } 149 ; 150 151twohalves: 152 '(' YY_STR ',' YY_STR ')' { $$ = makepair($2, $4); } 153 ; 154 155redirect: 156 IPSL_REDIRECT '(' ipaddr ')' { $$.act_ip = $3; 157 $$.act_port = 0; } 158 | IPSL_REDIRECT '(' ipaddr ',' portnum ')' 159 { $$.act_ip = $3; 160 $$.act_port = $5; } 161 ; 162 163 164ipaddr: YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER 165 { $$ = combine($1,$3,$5,$7); } 166 | YY_STR { $$ = gethostip($1); 167 free($1); 168 } 169 ; 170 171portnum: 172 YY_NUMBER { $$ = htons($1); } 173 | YY_STR { $$ = getportnum($1); 174 free($1); 175 } 176 ; 177 178%% 179 180 181static struct wordtab yywords[] = { 182 { "close", IPSL_CLOSE }, 183 { "content", IPSL_CONTENT }, 184 { "else", IPSL_ELSE }, 185 { "start-group", IPSL_STARTGROUP }, 186 { "redirect", IPSL_REDIRECT }, 187 { "start", IPSL_START }, 188 { "track", IPSL_TRACK }, 189 { NULL, 0 } 190}; 191 192 193int cram(dst, src) 194char *dst; 195char *src; 196{ 197 char c, *s, *t, *u; 198 int i, j, k; 199 200 c = *src; 201 s = src + 1; 202 t = strchr(s, c); 203 *t = '\0'; 204 for (u = dst, i = 0; (i <= ISC_TLEN) && (s < t); ) { 205 c = *s++; 206 if (c == '\\') { 207 if (s >= t) 208 break; 209 j = k = 0; 210 do { 211 c = *s++; 212 if (j && (!ISDIGIT(c) || (c > '7') || 213 (k >= 248))) { 214 *u++ = k, i++; 215 j = k = 0; 216 s--; 217 break; 218 } 219 i++; 220 221 if (ISALPHA(c) || (c > '7')) { 222 switch (c) 223 { 224 case 'n' : 225 *u++ = '\n'; 226 break; 227 case 'r' : 228 *u++ = '\r'; 229 break; 230 case 't' : 231 *u++ = '\t'; 232 break; 233 default : 234 *u++ = c; 235 break; 236 } 237 } else if (ISDIGIT(c)) { 238 j = 1; 239 k <<= 3; 240 k |= (c - '0'); 241 i--; 242 } else 243 *u++ = c; 244 } while ((i <= ISC_TLEN) && (s <= t) && (j > 0)); 245 } else 246 *u++ = c, i++; 247 } 248 return i; 249} 250 251 252void printent(isc) 253ipscan_t *isc; 254{ 255 char buf[ISC_TLEN+1]; 256 u_char *u; 257 int i, j; 258 259 buf[ISC_TLEN] = '\0'; 260 bcopy(isc->ipsc_ctxt, buf, ISC_TLEN); 261 printf("%s : (\"", isc->ipsc_tag); 262 printbuf(isc->ipsc_ctxt, isc->ipsc_clen, 0); 263 264 bcopy(isc->ipsc_cmsk, buf, ISC_TLEN); 265 printf("\", \"%s\"), (\"", buf); 266 267 printbuf(isc->ipsc_stxt, isc->ipsc_slen, 0); 268 269 bcopy(isc->ipsc_smsk, buf, ISC_TLEN); 270 printf("\", \"%s\") = ", buf); 271 272 switch (isc->ipsc_action) 273 { 274 case ISC_A_TRACK : 275 printf("track"); 276 break; 277 case ISC_A_REDIRECT : 278 printf("redirect"); 279 printf("(%s", inet_ntoa(isc->ipsc_ip)); 280 if (isc->ipsc_port) 281 printf(",%d", isc->ipsc_port); 282 printf(")"); 283 break; 284 case ISC_A_CLOSE : 285 printf("close"); 286 break; 287 default : 288 break; 289 } 290 291 if (isc->ipsc_else != ISC_A_NONE) { 292 printf(" else "); 293 switch (isc->ipsc_else) 294 { 295 case ISC_A_TRACK : 296 printf("track"); 297 break; 298 case ISC_A_REDIRECT : 299 printf("redirect"); 300 printf("(%s", inet_ntoa(isc->ipsc_eip)); 301 if (isc->ipsc_eport) 302 printf(",%d", isc->ipsc_eport); 303 printf(")"); 304 break; 305 case ISC_A_CLOSE : 306 printf("close"); 307 break; 308 default : 309 break; 310 } 311 } 312 printf("\n"); 313 314 if (opts & OPT_DEBUG) { 315 for (u = (u_char *)isc, i = sizeof(*isc); i; ) { 316 printf("#"); 317 for (j = 32; (j > 0) && (i > 0); j--, i--) 318 printf("%s%02x", (j & 7) ? "" : " ", *u++); 319 printf("\n"); 320 } 321 } 322 if (opts & OPT_VERBOSE) { 323 printf("# hits %d active %d fref %d sref %d\n", 324 isc->ipsc_hits, isc->ipsc_active, isc->ipsc_fref, 325 isc->ipsc_sref); 326 } 327} 328 329 330void addtag(tstr, cp, sp, act) 331char *tstr; 332char **cp, **sp; 333struct action *act; 334{ 335 ipscan_t isc, *iscp; 336 337 bzero((char *)&isc, sizeof(isc)); 338 339 strncpy(isc.ipsc_tag, tstr, sizeof(isc.ipsc_tag)); 340 isc.ipsc_tag[sizeof(isc.ipsc_tag) - 1] = '\0'; 341 342 if (cp) { 343 isc.ipsc_clen = cram(isc.ipsc_ctxt, cp[0]); 344 if (cp[1]) { 345 if (cram(isc.ipsc_cmsk, cp[1]) != isc.ipsc_clen) { 346 fprintf(stderr, 347 "client text/mask strings different length\n"); 348 return; 349 } 350 } 351 } 352 353 if (sp) { 354 isc.ipsc_slen = cram(isc.ipsc_stxt, sp[0]); 355 if (sp[1]) { 356 if (cram(isc.ipsc_smsk, sp[1]) != isc.ipsc_slen) { 357 fprintf(stderr, 358 "server text/mask strings different length\n"); 359 return; 360 } 361 } 362 } 363 364 if (act->act_val == IPSL_CLOSE) { 365 isc.ipsc_action = ISC_A_CLOSE; 366 } else if (act->act_val == IPSL_TRACK) { 367 isc.ipsc_action = ISC_A_TRACK; 368 } else if (act->act_val == IPSL_REDIRECT) { 369 isc.ipsc_action = ISC_A_REDIRECT; 370 isc.ipsc_ip = act->act_ip; 371 isc.ipsc_port = act->act_port; 372 fprintf(stderr, "%d: redirect unsupported\n", yylineNum + 1); 373 } 374 375 if (act->act_else == IPSL_CLOSE) { 376 isc.ipsc_else = ISC_A_CLOSE; 377 } else if (act->act_else == IPSL_TRACK) { 378 isc.ipsc_else = ISC_A_TRACK; 379 } else if (act->act_else == IPSL_REDIRECT) { 380 isc.ipsc_else = ISC_A_REDIRECT; 381 isc.ipsc_eip = act->act_eip; 382 isc.ipsc_eport = act->act_eport; 383 fprintf(stderr, "%d: redirect unsupported\n", yylineNum + 1); 384 } 385 386 if (!(opts & OPT_DONOTHING)) { 387 iscp = &isc; 388 if (opts & OPT_REMOVE) { 389 if (ioctl(fd, SIOCRMSCA, &iscp) == -1) 390 perror("SIOCADSCA"); 391 } else { 392 if (ioctl(fd, SIOCADSCA, &iscp) == -1) 393 perror("SIOCADSCA"); 394 } 395 } 396 397 if (opts & OPT_VERBOSE) 398 printent(&isc); 399} 400 401 402char **makepair(s1, s2) 403char *s1, *s2; 404{ 405 char **a; 406 407 a = malloc(sizeof(char *) * 2); 408 a[0] = s1; 409 a[1] = s2; 410 return a; 411} 412 413 414struct in_addr combine(a1, a2, a3, a4) 415int a1, a2, a3, a4; 416{ 417 struct in_addr in; 418 419 a1 &= 0xff; 420 in.s_addr = a1 << 24; 421 a2 &= 0xff; 422 in.s_addr |= (a2 << 16); 423 a3 &= 0xff; 424 in.s_addr |= (a3 << 8); 425 a4 &= 0xff; 426 in.s_addr |= a4; 427 in.s_addr = htonl(in.s_addr); 428 return in; 429} 430 431 432struct in_addr gethostip(host) 433char *host; 434{ 435 struct hostent *hp; 436 struct in_addr in; 437 438 in.s_addr = 0; 439 440 hp = gethostbyname(host); 441 if (!hp) 442 return in; 443 bcopy(hp->h_addr, (char *)&in, sizeof(in)); 444 return in; 445} 446 447 448int getportnum(port) 449char *port; 450{ 451 struct servent *s; 452 453 s = getservbyname(port, "tcp"); 454 if (s == NULL) 455 return -1; 456 return s->s_port; 457} 458 459 460void showlist() 461{ 462 ipscanstat_t ipsc, *ipscp = &ipsc; 463 ipscan_t isc; 464 465 if (ioctl(fd, SIOCGSCST, &ipscp) == -1) 466 perror("ioctl(SIOCGSCST)"); 467 else if (opts & OPT_SHOWLIST) { 468 while (ipsc.iscs_list != NULL) { 469 if (kmemcpy((char *)&isc, (u_long)ipsc.iscs_list, 470 sizeof(isc)) == -1) { 471 perror("kmemcpy"); 472 break; 473 } else { 474 printent(&isc); 475 ipsc.iscs_list = isc.ipsc_next; 476 } 477 } 478 } else { 479 printf("scan entries loaded\t%d\n", ipsc.iscs_entries); 480 printf("scan entries matches\t%ld\n", ipsc.iscs_acted); 481 printf("negative matches\t%ld\n", ipsc.iscs_else); 482 } 483} 484 485 486void usage(prog) 487char *prog; 488{ 489 fprintf(stderr, "Usage:\t%s [-dnrv] -f <filename>\n", prog); 490 fprintf(stderr, "\t%s [-dlv]\n", prog); 491 exit(1); 492} 493 494 495int main(argc, argv) 496int argc; 497char *argv[]; 498{ 499 FILE *fp = NULL; 500 int c; 501 502 (void) yysettab(yywords); 503 504 if (argc < 2) 505 usage(argv[0]); 506 507 while ((c = getopt(argc, argv, "df:lnrsv")) != -1) 508 switch (c) 509 { 510 case 'd' : 511 opts |= OPT_DEBUG; 512 yydebug++; 513 break; 514 case 'f' : 515 if (!strcmp(optarg, "-")) 516 fp = stdin; 517 else { 518 fp = fopen(optarg, "r"); 519 if (!fp) { 520 perror("open"); 521 exit(1); 522 } 523 } 524 yyin = fp; 525 break; 526 case 'l' : 527 opts |= OPT_SHOWLIST; 528 break; 529 case 'n' : 530 opts |= OPT_DONOTHING; 531 break; 532 case 'r' : 533 opts |= OPT_REMOVE; 534 break; 535 case 's' : 536 opts |= OPT_STAT; 537 break; 538 case 'v' : 539 opts |= OPT_VERBOSE; 540 break; 541 } 542 543 if (!(opts & OPT_DONOTHING)) { 544 fd = open(IPL_SCAN, O_RDWR); 545 if (fd == -1) { 546 perror("open(IPL_SCAN)"); 547 exit(1); 548 } 549 } 550 551 if (fp != NULL) { 552 yylineNum = 1; 553 554 while (!feof(fp)) 555 yyparse(); 556 fclose(fp); 557 exit(0); 558 } 559 560 if (opts & (OPT_SHOWLIST|OPT_STAT)) { 561 showlist(); 562 exit(0); 563 } 564 exit(1); 565} 566