1 %{ 2 /* 3 * Copyright (C) 2003 by Darren Reed. 4 * 5 * See the IPFILTER.LICENCE file for details on licencing. 6 * 7 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 8 * Use is subject to license terms. 9 */ 10 11 #pragma ident "%Z%%M% %I% %E% SMI" 12 13 #include "ipf.h" 14 #include <netinet/ip_icmp.h> 15 #include <sys/ioctl.h> 16 #include <syslog.h> 17 #ifdef IPFILTER_BPF 18 # include <net/bpf.h> 19 # include <pcap-int.h> 20 # include <pcap.h> 21 #endif 22 #if SOLARIS2 >= 10 23 #include "ip_pool.h" 24 #include "ip_htable.h" 25 #include "ipl.h" 26 #else 27 #include "netinet/ip_pool.h" 28 #include "netinet/ip_htable.h" 29 #include "netinet/ipl.h" 30 #endif 31 #include "ipf_l.h" 32 33 #define YYDEBUG 1 34 #define DOALL(x) for (fr = frc; fr != NULL; fr = fr->fr_next) { x } 35 #define DOREM(x) for (; fr != NULL; fr = fr->fr_next) { x } 36 #if SOLARIS2 >= 10 37 #define VNI "vni" 38 #define VNISTRLEN 3 39 #endif 40 41 #define OPTION_LOG 0x1 42 #define OPTION_QUICK 0x2 43 #define OPTION_DUP 0x4 44 #define OPTION_PROUTE 0x8 45 #define OPTION_ON 0x10 46 #define OPTION_REPLYTO 0x20 47 #define OPTION_FROUTE 0x40 48 49 extern void yyerror __P((char *)); 50 extern int yyparse __P((void)); 51 extern int yylex __P((void)); 52 extern int yydebug; 53 extern FILE *yyin; 54 extern int yylineNum; 55 56 static void newrule __P((void)); 57 static void setipftype __P((void)); 58 static u_32_t lookuphost __P((char *)); 59 static void dobpf __P((char *)); 60 static void resetaddr __P((void)); 61 static struct alist_s *newalist __P((struct alist_s *)); 62 static u_int makehash __P((struct alist_s *)); 63 static int makepool __P((struct alist_s *)); 64 static frentry_t *addrule __P((void)); 65 static void setsyslog __P((void)); 66 static void unsetsyslog __P((void)); 67 static void fillgroup __P((frentry_t *)); 68 69 frentry_t *fr = NULL, *frc = NULL, *frtop = NULL, *frold = NULL; 70 71 static int ifpflag = 0; 72 static int nowith = 0; 73 static int dynamic = -1; 74 static int pooled = 0; 75 static int hashed = 0; 76 static int nrules = 0; 77 static int newlist = 0; 78 static int added = 0; 79 static int ipffd = -1; 80 static int *yycont = 0; 81 static int ruleopts = 0; 82 static ioctlfunc_t ipfioctl[IPL_LOGSIZE]; 83 static addfunc_t ipfaddfunc = NULL; 84 static wordtab_t addrwords[4]; 85 static wordtab_t maskwords[5]; 86 static wordtab_t *savewords; 87 static int set_ipv6_addr = 0; 88 89 %} 90 %union { 91 char *str; 92 u_32_t num; 93 struct in_addr ipa; 94 frentry_t fr; 95 frtuc_t *frt; 96 struct alist_s *alist; 97 struct { 98 u_short p1; 99 u_short p2; 100 int pc; 101 } pc; 102 struct { 103 union i6addr a; 104 union i6addr m; 105 } ipp; 106 union i6addr ip6; 107 }; 108 109 %type <num> portnum facility priority icmpcode seclevel secname icmptype 110 %type <num> opt compare range opttype flagset optlist ipv6hdrlist ipv6hdr 111 %type <num> portc porteq 112 %type <ipa> hostname ipv4 ipv4mask 113 %type <ip6> ipv6mask 114 %type <ipp> addr ipaddr 115 %type <str> servicename name interfacename 116 %type <pc> portrange portcomp 117 %type <alist> addrlist poollist 118 119 %token <num> YY_NUMBER YY_HEX 120 %token <str> YY_STR 121 %token YY_COMMENT 122 %token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT 123 %token YY_RANGE_OUT YY_RANGE_IN 124 %token <ip6> YY_IPV6 125 126 %token IPFY_PASS IPFY_BLOCK IPFY_COUNT IPFY_CALL 127 %token IPFY_RETICMP IPFY_RETRST IPFY_RETICMPASDST 128 %token IPFY_IN IPFY_OUT 129 %token IPFY_QUICK IPFY_ON IPFY_OUTVIA IPFY_INVIA 130 %token IPFY_DUPTO IPFY_TO IPFY_FROUTE IPFY_REPLY_TO 131 %token IPFY_TOS IPFY_TTL IPFY_PROTO 132 %token IPFY_HEAD IPFY_GROUP 133 %token IPFY_AUTH IPFY_PREAUTH IPFY_DIVERT 134 %token IPFY_LOG IPFY_BODY IPFY_FIRST IPFY_LEVEL IPFY_ORBLOCK 135 %token IPFY_LOGTAG IPFY_TAG IPFY_SKIP 136 %token IPFY_FROM IPFY_ALL IPFY_ANY IPFY_BPF IPFY_POOL IPFY_HASH 137 %token IPFY_PPS 138 %token IPFY_ESP IPFY_AH 139 %token IPFY_WITH IPFY_AND IPFY_NOT IPFY_NO IPFY_OPT 140 %token IPFY_TCPUDP IPFY_TCP IPFY_UDP 141 %token IPFY_FLAGS IPFY_MULTICAST 142 %token IPFY_MASK IPFY_BROADCAST IPFY_NETWORK IPFY_NETMASKED IPFY_PEER 143 %token IPFY_PORT 144 %token IPFY_NOW 145 %token IPFY_ICMP IPFY_ICMPTYPE IPFY_ICMPCODE 146 %token IPFY_IPOPTS IPFY_SHORT IPFY_NAT IPFY_BADSRC IPFY_LOWTTL IPFY_FRAG 147 %token IPFY_MBCAST IPFY_BAD IPFY_BADNAT IPFY_OOW IPFY_NEWISN IPFY_NOICMPERR 148 %token IPFY_KEEP IPFY_STATE IPFY_FRAGS IPFY_LIMIT IPFY_STRICT IPFY_AGE 149 %token IPFY_IPOPT_NOP IPFY_IPOPT_RR IPFY_IPOPT_ZSU IPFY_IPOPT_MTUP 150 %token IPFY_IPOPT_MTUR IPFY_IPOPT_ENCODE IPFY_IPOPT_TS IPFY_IPOPT_TR 151 %token IPFY_IPOPT_SEC IPFY_IPOPT_LSRR IPFY_IPOPT_ESEC IPFY_IPOPT_CIPSO 152 %token IPFY_IPOPT_SATID IPFY_IPOPT_SSRR IPFY_IPOPT_ADDEXT IPFY_IPOPT_VISA 153 %token IPFY_IPOPT_IMITD IPFY_IPOPT_EIP IPFY_IPOPT_FINN IPFY_IPOPT_DPS 154 %token IPFY_IPOPT_SDB IPFY_IPOPT_NSAPA IPFY_IPOPT_RTRALRT IPFY_IPOPT_UMP 155 %token IPFY_SECCLASS IPFY_SEC_UNC IPFY_SEC_CONF IPFY_SEC_RSV1 IPFY_SEC_RSV2 156 %token IPFY_SEC_RSV4 IPFY_SEC_SEC IPFY_SEC_TS IPFY_SEC_RSV3 157 158 %token IPF6_V6HDRS IPFY_IPV6OPT IPFY_IPV6OPT_DSTOPTS IPFY_IPV6OPT_HOPOPTS 159 %token IPFY_IPV6OPT_IPV6 IPFY_IPV6OPT_NONE IPFY_IPV6OPT_ROUTING 160 161 %token IPFY_ICMPT_UNR IPFY_ICMPT_ECHO IPFY_ICMPT_ECHOR IPFY_ICMPT_SQUENCH 162 %token IPFY_ICMPT_REDIR IPFY_ICMPT_TIMEX IPFY_ICMPT_PARAMP IPFY_ICMPT_TIMEST 163 %token IPFY_ICMPT_TIMESTREP IPFY_ICMPT_INFOREQ IPFY_ICMPT_INFOREP 164 %token IPFY_ICMPT_MASKREQ IPFY_ICMPT_MASKREP IPFY_ICMPT_ROUTERAD 165 %token IPFY_ICMPT_ROUTERSOL 166 167 %token IPFY_ICMPC_NETUNR IPFY_ICMPC_HSTUNR IPFY_ICMPC_PROUNR IPFY_ICMPC_PORUNR 168 %token IPFY_ICMPC_NEEDF IPFY_ICMPC_SRCFAIL IPFY_ICMPC_NETUNK IPFY_ICMPC_HSTUNK 169 %token IPFY_ICMPC_ISOLATE IPFY_ICMPC_NETPRO IPFY_ICMPC_HSTPRO 170 %token IPFY_ICMPC_NETTOS IPFY_ICMPC_HSTTOS IPFY_ICMPC_FLTPRO IPFY_ICMPC_HSTPRE 171 %token IPFY_ICMPC_CUTPRE 172 173 %token IPFY_FAC_KERN IPFY_FAC_USER IPFY_FAC_MAIL IPFY_FAC_DAEMON IPFY_FAC_AUTH 174 %token IPFY_FAC_SYSLOG IPFY_FAC_LPR IPFY_FAC_NEWS IPFY_FAC_UUCP IPFY_FAC_CRON 175 %token IPFY_FAC_LOCAL0 IPFY_FAC_LOCAL1 IPFY_FAC_LOCAL2 IPFY_FAC_LOCAL3 176 %token IPFY_FAC_LOCAL4 IPFY_FAC_LOCAL5 IPFY_FAC_LOCAL6 IPFY_FAC_LOCAL7 177 %token IPFY_FAC_SECURITY IPFY_FAC_FTP IPFY_FAC_AUTHPRIV IPFY_FAC_AUDIT 178 %token IPFY_FAC_LFMT IPFY_FAC_CONSOLE 179 180 %token IPFY_PRI_EMERG IPFY_PRI_ALERT IPFY_PRI_CRIT IPFY_PRI_ERR IPFY_PRI_WARN 181 %token IPFY_PRI_NOTICE IPFY_PRI_INFO IPFY_PRI_DEBUG 182 %% 183 file: line 184 | assign 185 | file line 186 | file assign 187 ; 188 189 line: xx rule { while ((fr = frtop) != NULL) { 190 frtop = fr->fr_next; 191 fr->fr_next = NULL; 192 (*ipfaddfunc)(ipffd, ipfioctl[IPL_LOGIPF], fr); 193 fr->fr_next = frold; 194 frold = fr; 195 } 196 resetlexer(); 197 } 198 | YY_COMMENT 199 ; 200 201 xx: { newrule(); } 202 ; 203 204 assign: YY_STR assigning YY_STR ';' { set_variable($1, $3); 205 resetlexer(); 206 free($1); 207 free($3); 208 } 209 ; 210 211 assigning: 212 '=' { yyvarnext = 1; } 213 ; 214 215 rule: inrule 216 | outrule 217 ; 218 219 inrule: 220 rulehead markin { ruleopts = 0; } inopts rulemain ruletail 221 ; 222 223 outrule: 224 rulehead markout { ruleopts = 0; } outopts rulemain ruletail 225 ; 226 227 rulehead: 228 collection action 229 | insert collection action 230 ; 231 232 markin: IPFY_IN { fr->fr_flags |= FR_INQUE; } 233 ; 234 235 markout: 236 IPFY_OUT { fr->fr_flags |= FR_OUTQUE; } 237 ; 238 239 rulemain: 240 ipfrule 241 | bpfrule 242 ; 243 244 ipfrule: 245 tos ttl proto ip 246 ; 247 248 bpfrule: 249 IPFY_BPF '{' YY_STR '}' { dobpf($3); free($3); } 250 ; 251 252 ruletail: 253 keep head group tag pps age new 254 ; 255 256 insert: 257 '@' YY_NUMBER { fr->fr_hits = (U_QUAD_T)$2; } 258 ; 259 260 collection: 261 | YY_NUMBER { fr->fr_collect = $1; } 262 ; 263 264 action: block 265 | IPFY_PASS { fr->fr_flags |= FR_PASS; } 266 | IPFY_DIVERT YY_NUMBER { fr->fr_flags |= FR_DIVERT; 267 fr->fr_arg = $2; } 268 | log 269 | IPFY_COUNT { fr->fr_flags |= FR_ACCOUNT; } 270 | auth 271 | IPFY_SKIP YY_NUMBER { fr->fr_flags |= FR_SKIP; 272 fr->fr_arg = $2; } 273 | IPFY_CALL func 274 | IPFY_CALL IPFY_NOW func { fr->fr_flags |= FR_CALLNOW; } 275 ; 276 277 block: blocked 278 | blocked blockreturn 279 ; 280 281 blocked: 282 IPFY_BLOCK { fr->fr_flags = FR_BLOCK; } 283 ; 284 blockreturn: 285 IPFY_RETICMP { fr->fr_flags |= FR_RETICMP; } 286 | IPFY_RETICMP returncode { fr->fr_flags |= FR_RETICMP; } 287 | IPFY_RETICMPASDST { fr->fr_flags |= FR_FAKEICMP; } 288 | IPFY_RETICMPASDST returncode { fr->fr_flags |= FR_FAKEICMP; } 289 | IPFY_RETRST { fr->fr_flags |= FR_RETRST; } 290 ; 291 292 log: IPFY_LOG { fr->fr_flags |= FR_LOG; } 293 | IPFY_LOG logoptions { fr->fr_flags |= FR_LOG; } 294 ; 295 296 auth: IPFY_AUTH { fr->fr_flags |= FR_AUTH; } 297 | IPFY_AUTH IPFY_RETRST { fr->fr_flags |= (FR_AUTH|FR_RETRST);} 298 | IPFY_PREAUTH { fr->fr_flags |= FR_PREAUTH; } 299 ; 300 301 func: YY_STR '/' YY_NUMBER { fr->fr_func = nametokva($1, 302 ipfioctl[IPL_LOGIPF]); 303 fr->fr_arg = $3; 304 free($1); } 305 ; 306 307 inopts: 308 | inopts inopt 309 ; 310 311 inopt: 312 logopt 313 { 314 if ( ruleopts & OPTION_LOG ) 315 yyerror("Duplicate log option"); 316 ruleopts |= OPTION_LOG; 317 } 318 | quick 319 { 320 if ( ruleopts & OPTION_QUICK ) 321 yyerror("Duplicate quick option"); 322 ruleopts |= OPTION_QUICK; 323 } 324 | on 325 { 326 if ( ruleopts & OPTION_ON ) 327 yyerror("Duplicate on option"); 328 ruleopts |= OPTION_ON; 329 } 330 | dup 331 { 332 if ( ruleopts & OPTION_DUP ) 333 yyerror("Duplicate dup option"); 334 ruleopts |= OPTION_DUP; 335 } 336 | froute 337 { 338 if ( ruleopts & OPTION_FROUTE ) 339 yyerror("Duplicate froute option"); 340 ruleopts |= OPTION_FROUTE; 341 } 342 | proute 343 { 344 if ( ruleopts & OPTION_PROUTE ) 345 yyerror("Duplicate proute option"); 346 ruleopts |= OPTION_PROUTE; 347 } 348 | replyto 349 { 350 if ( ruleopts & OPTION_REPLYTO ) 351 yyerror("Duplicate replyto option"); 352 ruleopts |= OPTION_REPLYTO; 353 } 354 ; 355 356 outopts: 357 | outopts outopt 358 ; 359 360 outopt: 361 logopt 362 { 363 if ( ruleopts & OPTION_LOG ) 364 yyerror("Duplicate log option"); 365 ruleopts |= OPTION_LOG; 366 } 367 | quick 368 { 369 if ( ruleopts & OPTION_QUICK ) 370 yyerror("Duplicate quick option"); 371 ruleopts |= OPTION_QUICK; 372 } 373 | on 374 { 375 if ( ruleopts & OPTION_ON ) 376 yyerror("Duplicate on option"); 377 ruleopts |= OPTION_ON; 378 } 379 | dup 380 { 381 if ( ruleopts & OPTION_DUP ) 382 yyerror("Duplicate dup option"); 383 ruleopts |= OPTION_DUP; 384 } 385 | proute 386 { 387 if ( ruleopts & OPTION_PROUTE ) 388 yyerror("Duplicate proute option"); 389 ruleopts |= OPTION_PROUTE; 390 } 391 | replyto 392 { 393 if ( ruleopts & OPTION_REPLYTO ) 394 yyerror("Duplicate replyto option"); 395 ruleopts |= OPTION_REPLYTO; 396 } 397 ; 398 399 tos: | settos YY_NUMBER { DOALL(fr->fr_tos = $2; fr->fr_mtos = 0xff;) } 400 | settos YY_HEX { DOALL(fr->fr_tos = $2; fr->fr_mtos = 0xff;) } 401 | settos lstart toslist lend 402 ; 403 404 settos: IPFY_TOS { setipftype(); } 405 ; 406 407 toslist: 408 YY_NUMBER { DOALL(fr->fr_tos = $1; fr->fr_mtos = 0xff;) } 409 | YY_HEX { DOREM(fr->fr_tos = $1; fr->fr_mtos = 0xff;) } 410 | toslist lmore YY_NUMBER 411 { DOREM(fr->fr_tos = $3; fr->fr_mtos = 0xff;) } 412 | toslist lmore YY_HEX 413 { DOREM(fr->fr_tos = $3; fr->fr_mtos = 0xff;) } 414 ; 415 416 ttl: | setttl YY_NUMBER 417 { DOALL(fr->fr_ttl = $2; fr->fr_mttl = 0xff;) } 418 | setttl lstart ttllist lend 419 ; 420 421 lstart: '(' { newlist = 1; fr = frc; added = 0; } 422 ; 423 424 lend: ')' { nrules += added; } 425 ; 426 427 lmore: lanother { if (newlist == 1) { 428 newlist = 0; 429 } 430 fr = addrule(); 431 if (yycont != NULL) 432 *yycont = 1; 433 } 434 ; 435 436 lanother: 437 | ',' 438 ; 439 440 setttl: IPFY_TTL { setipftype(); } 441 ; 442 443 ttllist: 444 YY_NUMBER { DOREM(fr->fr_ttl = $1; fr->fr_mttl = 0xff;) } 445 | ttllist lmore YY_NUMBER 446 { DOREM(fr->fr_ttl = $3; fr->fr_mttl = 0xff;) } 447 ; 448 449 proto: | protox protocol { yyresetdict(); } 450 ; 451 452 protox: IPFY_PROTO { setipftype(); 453 fr = frc; 454 yysetdict(NULL); } 455 ; 456 457 ip: srcdst flags with icmp 458 ; 459 460 group: | IPFY_GROUP YY_STR { DOALL(strncpy(fr->fr_group, $2, \ 461 FR_GROUPLEN); \ 462 fillgroup(fr);); 463 free($2); } 464 | IPFY_GROUP YY_NUMBER { DOALL(sprintf(fr->fr_group, "%d", \ 465 $2); \ 466 fillgroup(fr);) } 467 ; 468 469 head: | IPFY_HEAD YY_STR { DOALL(strncpy(fr->fr_grhead, $2, \ 470 FR_GROUPLEN);); 471 free($2); } 472 | IPFY_HEAD YY_NUMBER { DOALL(sprintf(fr->fr_grhead, "%d", \ 473 $2);) } 474 ; 475 476 tag: | IPFY_TAG YY_NUMBER { DOALL(fr->fr_logtag = $2;) } 477 | IPFY_TAG '(' taglist ')' 478 479 taglist: 480 tagspec 481 | taglist ',' tagspec 482 ; 483 484 tagspec: 485 IPFY_NAT '=' YY_STR { DOALL(strncpy(fr->fr_nattag.ipt_tag,\ 486 $3, 16);); 487 free($3); } 488 | IPFY_NAT '=' YY_NUMBER { DOALL(sprintf(fr->fr_nattag.ipt_tag,\ 489 "%15d", $3);) } 490 | IPFY_LOG '=' YY_NUMBER { DOALL(fr->fr_logtag = $3;) } 491 ; 492 493 pps: | IPFY_PPS YY_NUMBER { DOALL(fr->fr_pps = $2;) } 494 ; 495 496 new: | savegroup file restoregroup 497 ; 498 499 savegroup: 500 '{' 501 ; 502 503 restoregroup: 504 '}' 505 ; 506 507 logopt: log 508 ; 509 510 quick: 511 IPFY_QUICK { fr->fr_flags |= FR_QUICK; } 512 ; 513 514 on: IPFY_ON onname 515 | IPFY_ON onname IPFY_INVIA vianame 516 | IPFY_ON onname IPFY_OUTVIA vianame 517 ; 518 519 onname: interfacename 520 { 521 #if SOLARIS2 >=10 522 char *cp; 523 #endif 524 strncpy(fr->fr_ifnames[0], $1, sizeof(fr->fr_ifnames[0])); 525 #if SOLARIS2 >= 10 526 if (strncmp(VNI, $1, VNISTRLEN) == 0) { 527 cp = $1 + VNISTRLEN; 528 cp += strspn(cp, "0123456789"); 529 if (*cp == '\0' || *cp == ':') { 530 fprintf(stderr, "%d: Warning- %s specified. vni" 531 " is a virtual interface, use a physical" 532 " interface instead. See vni(7D)\n", 533 yylineNum, $1); 534 } 535 } 536 #endif 537 free($1); 538 } 539 | interfacename ',' name 540 { 541 #if SOLARIS2 >= 10 542 char *cp; 543 #endif 544 strncpy(fr->fr_ifnames[0], $1, sizeof(fr->fr_ifnames[0])); 545 #if SOLARIS2 >= 10 546 if (strncmp(VNI, $1, VNISTRLEN) == 0) { 547 cp = $1 + VNISTRLEN; 548 cp += strspn(cp, "0123456789"); 549 if (*cp == '\0' || *cp == ':') { 550 fprintf(stderr, "%d: Warning- %s specified. vni" 551 " is a virtual interface, use a physical" 552 " interface instead. See vni(7D)\n", 553 yylineNum, $1); 554 } 555 } 556 #endif 557 free($1); 558 strncpy(fr->fr_ifnames[1], $3, sizeof(fr->fr_ifnames[1])); 559 #if SOLARIS2 >= 10 560 if (strncmp(VNI, $3, VNISTRLEN) == 0) { 561 cp = $3 + VNISTRLEN; 562 cp += strspn(cp, "0123456789"); 563 if (*cp == '\0' || *cp == ':') { 564 fprintf(stderr, "%d: Warning- %s specified. vni" 565 " is a virtual interface, use a physical" 566 " interface instead. See vni(7D)\n", 567 yylineNum, $3); 568 } 569 } 570 #endif 571 free($3); 572 } 573 ; 574 575 vianame: 576 interfacename 577 { 578 #if SOLARIS2 >= 10 579 char *cp; 580 #endif 581 strncpy(fr->fr_ifnames[2], $1, sizeof(fr->fr_ifnames[2])); 582 #if SOLARIS2 >= 10 583 if (strncmp(VNI, $1, VNISTRLEN) == 0) { 584 cp = $1 + VNISTRLEN; 585 cp += strspn(cp, "0123456789"); 586 if (*cp == '\0' || *cp == ':') { 587 fprintf(stderr, "%d: Warning- %s specified. vni" 588 " is a virtual interface, use a physical" 589 " interface instead. See vni(7D)\n", 590 yylineNum, $1); 591 } 592 } 593 #endif 594 free($1); 595 } 596 | interfacename ',' name 597 { 598 #if SOLARIS2 >= 10 599 char *cp; 600 #endif 601 strncpy(fr->fr_ifnames[2], $1, sizeof(fr->fr_ifnames[2])); 602 #if SOLARIS2 >= 10 603 if (strncmp(VNI, $1, VNISTRLEN) == 0) { 604 cp = $1 + VNISTRLEN; 605 cp += strspn(cp, "0123456789"); 606 if (*cp == '\0' || *cp == ':') { 607 fprintf(stderr, "%d: Warning- %s specified. vni" 608 " is a virtual interface, use a physical" 609 " interface instead. See vni(7D)\n", 610 yylineNum, $1); 611 } 612 } 613 #endif 614 free($1); 615 strncpy(fr->fr_ifnames[3], $3, sizeof(fr->fr_ifnames[3])); 616 #if SOLARIS2 >= 10 617 if (strncmp(VNI, $3, VNISTRLEN) == 0) { 618 cp = $3 + VNISTRLEN; 619 cp += strspn(cp, "0123456789"); 620 if (*cp == '\0' || *cp == ':') { 621 fprintf(stderr, "%d: Warning- %s specified. vni" 622 " is a virtual interface, use a physical" 623 " interface instead. See vni(7D)\n", 624 yylineNum, $3); 625 } 626 } 627 #endif 628 free($3); 629 } 630 ; 631 632 dup: IPFY_DUPTO name 633 { strncpy(fr->fr_dif.fd_ifname, $2, sizeof(fr->fr_dif.fd_ifname)); 634 free($2); 635 } 636 | IPFY_DUPTO name ':' hostname 637 { strncpy(fr->fr_dif.fd_ifname, $2, sizeof(fr->fr_dif.fd_ifname)); 638 fr->fr_dif.fd_ip = $4; 639 free($2); 640 } 641 ; 642 643 froute: IPFY_FROUTE { fr->fr_flags |= FR_FASTROUTE; } 644 ; 645 646 proute: IPFY_TO name 647 { strncpy(fr->fr_tif.fd_ifname, $2, sizeof(fr->fr_tif.fd_ifname)); 648 free($2); 649 } 650 | IPFY_TO name ':' hostname 651 { strncpy(fr->fr_tif.fd_ifname, $2, sizeof(fr->fr_tif.fd_ifname)); 652 fr->fr_tif.fd_ip = $4; 653 free($2); 654 } 655 ; 656 657 replyto: 658 IPFY_REPLY_TO name 659 { strncpy(fr->fr_rif.fd_ifname, $2, sizeof(fr->fr_rif.fd_ifname)); 660 free($2); 661 } 662 | IPFY_REPLY_TO name ':' hostname 663 { strncpy(fr->fr_rif.fd_ifname, $2, sizeof(fr->fr_rif.fd_ifname)); 664 fr->fr_rif.fd_ip = $4; 665 free($2); 666 } 667 ; 668 669 logoptions: 670 logoption 671 | logoptions logoption 672 ; 673 674 logoption: 675 IPFY_BODY { fr->fr_flags |= FR_LOGBODY; } 676 | IPFY_FIRST { fr->fr_flags |= FR_LOGFIRST; } 677 | IPFY_ORBLOCK { fr->fr_flags |= FR_LOGORBLOCK; } 678 | level loglevel { unsetsyslog(); } 679 ; 680 681 returncode: 682 starticmpcode icmpcode ')' { fr->fr_icode = $2; yyresetdict(); } 683 ; 684 685 starticmpcode: 686 '(' { yysetdict(icmpcodewords); } 687 ; 688 689 srcdst: IPFY_ALL 690 | fromto 691 ; 692 693 protocol: 694 YY_NUMBER { DOREM(fr->fr_proto = $1; \ 695 fr->fr_mproto = 0xff;) } 696 | YY_STR { if (!strcmp($1, "tcp-udp")) { 697 DOREM(fr->fr_flx |= FI_TCPUDP; \ 698 fr->fr_mflx |= FI_TCPUDP;) 699 } else { 700 int p = getproto($1); 701 if (p == -1) 702 fprintf(stderr, "protocol unknown: %s, line %d\n", $1, yylineNum); 703 DOREM(fr->fr_proto = p; \ 704 fr->fr_mproto = 0xff;) 705 } 706 free($1); 707 } 708 | YY_STR nextstring YY_STR 709 { if (!strcmp($1, "tcp") && 710 !strcmp($3, "udp")) { 711 DOREM(fr->fr_flx |= FI_TCPUDP; \ 712 fr->fr_mflx |= FI_TCPUDP;) 713 } else 714 YYERROR; 715 free($1); 716 free($3); 717 } 718 ; 719 720 nextstring: 721 '/' { yysetdict(NULL); } 722 ; 723 724 fromto: from srcobject to dstobject { yyexpectaddr = 0; yycont = NULL; } 725 | to dstobject { yyexpectaddr = 0; yycont = NULL; } 726 | from srcobject { yyexpectaddr = 0; yycont = NULL; } 727 ; 728 729 from: IPFY_FROM { setipftype(); 730 if (fr == NULL) 731 fr = frc; 732 yyexpectaddr = 1; 733 yycont = &yyexpectaddr; 734 yysetdict(addrwords); 735 resetaddr(); } 736 ; 737 738 to: IPFY_TO { if (fr == NULL) 739 fr = frc; 740 yyexpectaddr = 1; 741 yycont = &yyexpectaddr; 742 yysetdict(addrwords); 743 resetaddr(); } 744 ; 745 746 with: | andwith withlist 747 ; 748 749 andwith: 750 IPFY_WITH { nowith = 0; setipftype(); } 751 | IPFY_AND { nowith = 0; setipftype(); } 752 ; 753 754 flags: | IPFY_FLAGS flagset 755 { DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = FR_TCPFMAX;) } 756 | IPFY_FLAGS flagset '/' flagset 757 { DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) } 758 | IPFY_FLAGS '/' flagset 759 { DOALL(fr->fr_tcpf = 0; fr->fr_tcpfm = $3;) } 760 | IPFY_FLAGS YY_NUMBER 761 { DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = FR_TCPFMAX;) } 762 | IPFY_FLAGS '/' YY_NUMBER 763 { DOALL(fr->fr_tcpf = 0; fr->fr_tcpfm = $3;) } 764 | IPFY_FLAGS YY_NUMBER '/' YY_NUMBER 765 { DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) } 766 | IPFY_FLAGS flagset '/' YY_NUMBER 767 { DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) } 768 | IPFY_FLAGS YY_NUMBER '/' flagset 769 { DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) } 770 ; 771 772 flagset: 773 YY_STR { $$ = tcpflags($1); free($1); } 774 | YY_HEX { $$ = $1; } 775 ; 776 777 srcobject: 778 srcaddr srcport 779 | '!' srcaddr srcport 780 { DOALL(fr->fr_flags |= FR_NOTSRCIP;) } 781 | fromport 782 ; 783 784 srcaddr: 785 addr { DOREM(bcopy(&($1.a), &fr->fr_ip.fi_src, sizeof($1.a)); \ 786 bcopy(&($1.m), &fr->fr_mip.fi_src, sizeof($1.m)); \ 787 if (dynamic != -1) { \ 788 fr->fr_satype = ifpflag; \ 789 fr->fr_ipf->fri_sifpidx = dynamic; \ 790 } else if (pooled || hashed) \ 791 fr->fr_satype = FRI_LOOKUP;) 792 } 793 | lstart srcaddrlist lend 794 ; 795 796 srcaddrlist: 797 addr { DOREM(bcopy(&($1.a), &fr->fr_ip.fi_src, sizeof($1.a)); \ 798 bcopy(&($1.m), &fr->fr_mip.fi_src, sizeof($1.m)); \ 799 if (dynamic != -1) { \ 800 fr->fr_satype = ifpflag; \ 801 fr->fr_ipf->fri_sifpidx = dynamic; \ 802 } else if (pooled || hashed) \ 803 fr->fr_satype = FRI_LOOKUP;) 804 } 805 | srcaddrlist lmore addr 806 { DOREM(bcopy(&($3.a), &fr->fr_ip.fi_src, sizeof($3.a)); \ 807 bcopy(&($3.m), &fr->fr_mip.fi_src, sizeof($3.m)); \ 808 if (dynamic != -1) { \ 809 fr->fr_satype = ifpflag; \ 810 fr->fr_ipf->fri_sifpidx = dynamic; \ 811 } else if (pooled || hashed) \ 812 fr->fr_satype = FRI_LOOKUP;) 813 } 814 ; 815 816 srcport: 817 | portcomp 818 { DOALL(fr->fr_scmp = $1.pc; fr->fr_sport = $1.p1;) } 819 | portrange 820 { DOALL(fr->fr_scmp = $1.pc; fr->fr_sport = $1.p1; \ 821 fr->fr_stop = $1.p2;) } 822 | porteq lstart srcportlist lend 823 { yyresetdict(); } 824 ; 825 826 fromport: 827 portcomp 828 { DOALL(fr->fr_scmp = $1.pc; fr->fr_sport = $1.p1;) } 829 | portrange 830 { DOALL(fr->fr_scmp = $1.pc; fr->fr_sport = $1.p1; \ 831 fr->fr_stop = $1.p2;) } 832 | porteq lstart srcportlist lend 833 { yyresetdict(); } 834 ; 835 836 srcportlist: 837 portnum { DOREM(fr->fr_scmp = FR_EQUAL; fr->fr_sport = $1;) } 838 | srcportlist lmore portnum 839 { DOREM(fr->fr_scmp = FR_EQUAL; fr->fr_sport = $3;) } 840 ; 841 842 dstobject: 843 toport 844 | dstaddr dstport 845 | '!' dstaddr dstport 846 { DOALL(fr->fr_flags |= FR_NOTDSTIP;) } 847 ; 848 849 dstaddr: 850 addr { DOREM(bcopy(&($1.a), &fr->fr_ip.fi_dst, sizeof($1.a)); \ 851 bcopy(&($1.m), &fr->fr_mip.fi_dst, sizeof($1.m)); \ 852 if (dynamic != -1) { \ 853 fr->fr_datype = ifpflag; \ 854 fr->fr_ipf->fri_difpidx = dynamic; \ 855 } else if (pooled || hashed) \ 856 fr->fr_datype = FRI_LOOKUP;) 857 } 858 | lstart dstaddrlist lend 859 ; 860 861 dstaddrlist: 862 addr { DOREM(bcopy(&($1.a), &fr->fr_ip.fi_dst, sizeof($1.a)); \ 863 bcopy(&($1.m), &fr->fr_mip.fi_dst, sizeof($1.m)); \ 864 if (dynamic != -1) { \ 865 fr->fr_datype = ifpflag; \ 866 fr->fr_ipf->fri_difpidx = dynamic; \ 867 } else if (pooled || hashed) \ 868 fr->fr_datype = FRI_LOOKUP;) 869 } 870 | dstaddrlist lmore addr 871 { DOREM(bcopy(&($3.a), &fr->fr_ip.fi_dst, sizeof($3.a)); \ 872 bcopy(&($3.m), &fr->fr_mip.fi_dst, sizeof($3.m)); \ 873 if (dynamic != -1) { \ 874 fr->fr_datype = ifpflag; \ 875 fr->fr_ipf->fri_difpidx = dynamic; \ 876 } else if (pooled || hashed) \ 877 fr->fr_datype = FRI_LOOKUP;) 878 } 879 ; 880 881 882 dstport: 883 | portcomp 884 { DOALL(fr->fr_dcmp = $1.pc; fr->fr_dport = $1.p1;) } 885 | portrange 886 { DOALL(fr->fr_dcmp = $1.pc; fr->fr_dport = $1.p1; \ 887 fr->fr_dtop = $1.p2;) } 888 | porteq lstart dstportlist lend 889 { yyresetdict(); } 890 ; 891 892 toport: 893 portcomp 894 { DOALL(fr->fr_dcmp = $1.pc; fr->fr_dport = $1.p1;) } 895 | portrange 896 { DOALL(fr->fr_dcmp = $1.pc; fr->fr_dport = $1.p1; \ 897 fr->fr_dtop = $1.p2;) } 898 | porteq lstart dstportlist lend 899 { yyresetdict(); } 900 ; 901 902 dstportlist: 903 portnum { DOREM(fr->fr_dcmp = FR_EQUAL; fr->fr_dport = $1;) } 904 | dstportlist lmore portnum 905 { DOREM(fr->fr_dcmp = FR_EQUAL; fr->fr_dport = $3;) } 906 ; 907 908 addr: pool '/' YY_NUMBER { pooled = 1; 909 yyexpectaddr = 0; 910 $$.a.iplookuptype = IPLT_POOL; 911 $$.a.iplookupnum = $3; } 912 | pool '=' '(' poollist ')' { pooled = 1; 913 yyexpectaddr = 0; 914 $$.a.iplookuptype = IPLT_POOL; 915 $$.a.iplookupnum = makepool($4); } 916 | hash '/' YY_NUMBER { hashed = 1; 917 yyexpectaddr = 0; 918 $$.a.iplookuptype = IPLT_HASH; 919 $$.a.iplookupnum = $3; } 920 | hash '=' '(' addrlist ')' { hashed = 1; 921 yyexpectaddr = 0; 922 $$.a.iplookuptype = IPLT_HASH; 923 $$.a.iplookupnum = makehash($4); } 924 | ipaddr { bcopy(&$1, &$$, sizeof($$)); 925 yyexpectaddr = 0; } 926 ; 927 928 ipaddr: IPFY_ANY { bzero(&($$), sizeof($$)); 929 yyresetdict(); 930 yyexpectaddr = 0; } 931 | hostname { $$.a.in4 = $1; 932 $$.m.in4_addr = 0xffffffff; 933 yyexpectaddr = 0; } 934 | hostname { yyresetdict(); 935 $$.a.in4_addr = $1.s_addr; } 936 maskspace { yysetdict(maskwords); } 937 ipv4mask { $$.m.in4_addr = $5.s_addr; 938 $$.a.in4_addr &= $5.s_addr; 939 yyresetdict(); 940 yyexpectaddr = 0; } 941 | YY_IPV6 { set_ipv6_addr = 1; 942 bcopy(&$1, &$$.a, sizeof($$.a)); 943 fill6bits(128, (u_32_t *)&$$.m); 944 yyresetdict(); 945 yyexpectaddr = 0; } 946 | YY_IPV6 { set_ipv6_addr = 1; 947 yyresetdict(); 948 bcopy(&$1, &$$.a, sizeof($$.a)); } 949 maskspace { yysetdict(maskwords); } 950 ipv6mask { bcopy(&$5, &$$.m, sizeof($$.m)); 951 yyresetdict(); 952 yyexpectaddr = 0; } 953 ; 954 955 maskspace: 956 '/' 957 | IPFY_MASK 958 ; 959 960 ipv4mask: 961 ipv4 { $$ = $1; } 962 | YY_HEX { $$.s_addr = htonl($1); } 963 | YY_NUMBER { ntomask(4, $1, (u_32_t *)&$$); } 964 | IPFY_BROADCAST { if (ifpflag == FRI_DYNAMIC) { 965 $$.s_addr = 0; 966 ifpflag = FRI_BROADCAST; 967 } else 968 YYERROR; 969 } 970 | IPFY_NETWORK { if (ifpflag == FRI_DYNAMIC) { 971 $$.s_addr = 0; 972 ifpflag = FRI_NETWORK; 973 } else 974 YYERROR; 975 } 976 | IPFY_NETMASKED { if (ifpflag == FRI_DYNAMIC) { 977 $$.s_addr = 0; 978 ifpflag = FRI_NETMASKED; 979 } else 980 YYERROR; 981 } 982 | IPFY_PEER { if (ifpflag == FRI_DYNAMIC) { 983 $$.s_addr = 0; 984 ifpflag = FRI_PEERADDR; 985 } else 986 YYERROR; 987 } 988 ; 989 990 ipv6mask: 991 YY_NUMBER { ntomask(6, $1, $$.i6); } 992 | IPFY_BROADCAST { if (ifpflag == FRI_DYNAMIC) { 993 bzero(&$$, sizeof($$)); 994 ifpflag = FRI_BROADCAST; 995 } else 996 YYERROR; 997 } 998 | IPFY_NETWORK { if (ifpflag == FRI_DYNAMIC) { 999 bzero(&$$, sizeof($$)); 1000 ifpflag = FRI_BROADCAST; 1001 } else 1002 YYERROR; 1003 } 1004 | IPFY_NETMASKED { if (ifpflag == FRI_DYNAMIC) { 1005 bzero(&$$, sizeof($$)); 1006 ifpflag = FRI_BROADCAST; 1007 } else 1008 YYERROR; 1009 } 1010 | IPFY_PEER { if (ifpflag == FRI_DYNAMIC) { 1011 bzero(&$$, sizeof($$)); 1012 ifpflag = FRI_BROADCAST; 1013 } else 1014 YYERROR; 1015 } 1016 ; 1017 1018 hostname: 1019 ipv4 { $$ = $1; } 1020 | YY_NUMBER { $$.s_addr = $1; } 1021 | YY_HEX { $$.s_addr = $1; } 1022 | YY_STR { $$.s_addr = lookuphost($1); 1023 free($1); 1024 if ($$.s_addr == 0 && 1025 ifpflag != FRI_DYNAMIC) 1026 yyerror("Unknown hostname"); 1027 } 1028 ; 1029 1030 addrlist: 1031 ipaddr { $$ = newalist(NULL); 1032 if (set_ipv6_addr) 1033 $$->al_family = AF_INET6; 1034 else 1035 $$->al_family = AF_INET; 1036 set_ipv6_addr = 0; 1037 bcopy(&($1.a), &($$->al_i6addr), sizeof($1.a)); 1038 bcopy(&($1.m), &($$->al_i6mask), sizeof($1.m)); } 1039 | addrlist ',' ipaddr 1040 { $$ = newalist($1); 1041 if (set_ipv6_addr) 1042 $$->al_family = AF_INET6; 1043 else 1044 $$->al_family = AF_INET; 1045 set_ipv6_addr = 0; 1046 bcopy(&($3.a), &($$->al_i6addr), sizeof($3.a)); 1047 bcopy(&($3.m), &($$->al_i6mask), sizeof($3.m)); } 1048 ; 1049 1050 pool: IPFY_POOL { yyexpectaddr = 0; yycont = NULL; yyresetdict(); } 1051 ; 1052 1053 hash: IPFY_HASH { yyexpectaddr = 0; yycont = NULL; yyresetdict(); } 1054 ; 1055 1056 poollist: 1057 ipaddr { $$ = newalist(NULL); 1058 if (set_ipv6_addr) 1059 $$->al_family = AF_INET6; 1060 else 1061 $$->al_family = AF_INET; 1062 set_ipv6_addr = 0; 1063 bcopy(&($1.a), &($$->al_i6addr), sizeof($1.a)); 1064 bcopy(&($1.m), &($$->al_i6mask), sizeof($1.m)); } 1065 | '!' ipaddr { $$ = newalist(NULL); 1066 $$->al_not = 1; 1067 if (set_ipv6_addr) 1068 $$->al_family = AF_INET6; 1069 else 1070 $$->al_family = AF_INET; 1071 set_ipv6_addr = 0; 1072 bcopy(&($2.a), &($$->al_i6addr), sizeof($2.a)); 1073 bcopy(&($2.m), &($$->al_i6mask), sizeof($2.m)); } 1074 | poollist ',' ipaddr 1075 { $$ = newalist($1); 1076 if (set_ipv6_addr) 1077 $$->al_family = AF_INET6; 1078 else 1079 $$->al_family = AF_INET; 1080 set_ipv6_addr = 0; 1081 bcopy(&($3.a), &($$->al_i6addr), sizeof($3.a)); 1082 bcopy(&($3.m), &($$->al_i6mask), sizeof($3.m)); } 1083 | poollist ',' '!' ipaddr 1084 { $$ = newalist($1); 1085 $$->al_not = 1; 1086 if (set_ipv6_addr) 1087 $$->al_family = AF_INET6; 1088 else 1089 $$->al_family = AF_INET; 1090 set_ipv6_addr = 0; 1091 bcopy(&($4.a), &($$->al_i6addr), sizeof($4.a)); 1092 bcopy(&($4.m), &($$->al_i6mask), sizeof($4.m)); } 1093 ; 1094 1095 port: IPFY_PORT { yyexpectaddr = 0; 1096 yycont = NULL; 1097 } 1098 ; 1099 1100 portc: port compare { $$ = $2; 1101 yysetdict(NULL); } 1102 | porteq { $$ = $1; } 1103 ; 1104 1105 porteq: port '=' { $$ = FR_EQUAL; 1106 yysetdict(NULL); } 1107 ; 1108 1109 portr: IPFY_PORT { yyexpectaddr = 0; 1110 yycont = NULL; 1111 yysetdict(NULL); } 1112 ; 1113 1114 portcomp: 1115 portc portnum { $$.pc = $1; 1116 $$.p1 = $2; 1117 yyresetdict(); } 1118 ; 1119 1120 portrange: 1121 portr portnum range portnum { $$.p1 = $2; 1122 $$.pc = $3; 1123 $$.p2 = $4; 1124 yyresetdict(); } 1125 ; 1126 1127 icmp: | itype icode 1128 ; 1129 1130 itype: seticmptype icmptype 1131 { DOALL(fr->fr_icmp = htons($2 << 8); fr->fr_icmpm = htons(0xff00);); 1132 yyresetdict(); 1133 } 1134 | seticmptype lstart typelist lend { yyresetdict(); } 1135 ; 1136 1137 seticmptype: 1138 IPFY_ICMPTYPE { setipftype(); 1139 yysetdict(icmptypewords); } 1140 ; 1141 1142 icode: | seticmpcode icmpcode 1143 { DOALL(fr->fr_icmp |= htons($2); fr->fr_icmpm |= htons(0xff);); 1144 yyresetdict(); 1145 } 1146 | seticmpcode lstart codelist lend { yyresetdict(); } 1147 ; 1148 1149 seticmpcode: 1150 IPFY_ICMPCODE { yysetdict(icmpcodewords); } 1151 ; 1152 1153 typelist: 1154 icmptype 1155 { DOREM(fr->fr_icmp = htons($1 << 8); fr->fr_icmpm = htons(0xff00);) } 1156 | typelist lmore icmptype 1157 { DOREM(fr->fr_icmp = htons($3 << 8); fr->fr_icmpm = htons(0xff00);) } 1158 ; 1159 1160 codelist: 1161 icmpcode 1162 { DOREM(fr->fr_icmp |= htons($1); fr->fr_icmpm |= htons(0xff);) } 1163 | codelist lmore icmpcode 1164 { DOREM(fr->fr_icmp |= htons($3); fr->fr_icmpm |= htons(0xff);) } 1165 ; 1166 1167 age: | IPFY_AGE YY_NUMBER { DOALL(fr->fr_age[0] = $2; \ 1168 fr->fr_age[1] = $2;) } 1169 | IPFY_AGE YY_NUMBER '/' YY_NUMBER 1170 { DOALL(fr->fr_age[0] = $2; \ 1171 fr->fr_age[1] = $4;) } 1172 ; 1173 1174 keep: | IPFY_KEEP keepstate 1175 | IPFY_KEEP keepfrag 1176 | IPFY_KEEP keepstate IPFY_KEEP keepfrag 1177 ; 1178 1179 keepstate: 1180 IPFY_STATE stateoptlist { DOALL(fr->fr_flags |= FR_KEEPSTATE;)} 1181 ; 1182 1183 keepfrag: 1184 IPFY_FRAGS fragoptlist { DOALL(fr->fr_flags |= FR_KEEPFRAG;) } 1185 ; 1186 1187 fragoptlist: 1188 | '(' fragopts ')' 1189 ; 1190 1191 fragopts: 1192 fragopt lanother fragopts 1193 | fragopt 1194 ; 1195 1196 fragopt: 1197 IPFY_STRICT { DOALL(fr->fr_flags |= FR_FRSTRICT;) } 1198 ; 1199 1200 stateoptlist: 1201 | '(' stateopts ')' 1202 ; 1203 1204 stateopts: 1205 stateopt lanother stateopts 1206 | stateopt 1207 ; 1208 1209 stateopt: 1210 IPFY_LIMIT YY_NUMBER { DOALL(fr->fr_statemax = $2;) } 1211 | IPFY_STRICT { DOALL(if (fr->fr_proto != IPPROTO_TCP) { \ 1212 YYERROR; \ 1213 } else \ 1214 fr->fr_flags |= FR_STSTRICT;) 1215 } 1216 | IPFY_NEWISN { DOALL(if (fr->fr_proto != IPPROTO_TCP) { \ 1217 YYERROR; \ 1218 } else \ 1219 fr->fr_flags |= FR_NEWISN;) 1220 } 1221 | IPFY_NOICMPERR { DOALL(fr->fr_flags |= FR_NOICMPERR;) } 1222 ; 1223 1224 portnum: 1225 servicename { $$ = ntohs(getport(frc, $1)); 1226 if ($$ == -1) 1227 fprintf(stderr, "service unknown: %s, line %d\n", $1, yylineNum); 1228 free($1); 1229 } 1230 | YY_NUMBER { $$ = $1; } 1231 ; 1232 1233 withlist: 1234 withopt 1235 | withlist withopt 1236 ; 1237 1238 withopt: 1239 opttype { DOALL(fr->fr_flx |= $1; fr->fr_mflx |= $1;) } 1240 | notwith opttype 1241 { DOALL(fr->fr_mflx |= $2;) } 1242 | IPFY_OPT ipopts 1243 | notwith IPFY_OPT ipopts 1244 | startv6hdrs ipv6hdrs 1245 ; 1246 1247 startv6hdrs: 1248 IPF6_V6HDRS { if (use_inet6 == 0) 1249 yyerror("only available with IPv6"); 1250 } 1251 ; 1252 1253 notwith: 1254 IPFY_NOT { nowith = 1; } 1255 | IPFY_NO { nowith = 1; } 1256 ; 1257 1258 opttype: 1259 IPFY_IPOPTS { $$ = FI_OPTIONS; } 1260 | IPFY_SHORT { $$ = FI_SHORT; } 1261 | IPFY_NAT { $$ = FI_NATED; } 1262 | IPFY_BAD { $$ = FI_BAD; } 1263 | IPFY_BADNAT { $$ = FI_BADNAT; } 1264 | IPFY_BADSRC { $$ = FI_BADSRC; } 1265 | IPFY_LOWTTL { $$ = FI_LOWTTL; } 1266 | IPFY_FRAG { $$ = FI_FRAG; } 1267 | IPFY_MBCAST { $$ = FI_MBCAST; } 1268 | IPFY_MULTICAST { $$ = FI_MULTICAST; } 1269 | IPFY_BROADCAST { $$ = FI_BROADCAST; } 1270 | IPFY_STATE { $$ = FI_STATE; } 1271 | IPFY_OOW { $$ = FI_OOW; } 1272 ; 1273 1274 ipopts: optlist { DOALL(fr->fr_mip.fi_optmsk |= $1; 1275 if (!nowith) 1276 fr->fr_ip.fi_optmsk |= $1;) 1277 } 1278 ; 1279 1280 optlist: 1281 opt { $$ |= $1; } 1282 | optlist ',' opt { $$ |= $1 | $3; } 1283 ; 1284 1285 ipv6hdrs: 1286 ipv6hdrlist { DOALL(fr->fr_mip.fi_optmsk |= $1; 1287 if (!nowith) 1288 fr->fr_ip.fi_optmsk |= $1;) 1289 } 1290 ; 1291 1292 ipv6hdrlist: 1293 ipv6hdr { $$ |= $1; } 1294 | ipv6hdrlist ',' ipv6hdr { $$ |= $1 | $3; } 1295 ; 1296 1297 secname: 1298 seclevel { $$ |= $1; } 1299 | secname ',' seclevel { $$ |= $1 | $3; } 1300 ; 1301 1302 seclevel: 1303 IPFY_SEC_UNC { $$ = secbit(IPSO_CLASS_UNCL); } 1304 | IPFY_SEC_CONF { $$ = secbit(IPSO_CLASS_CONF); } 1305 | IPFY_SEC_RSV1 { $$ = secbit(IPSO_CLASS_RES1); } 1306 | IPFY_SEC_RSV2 { $$ = secbit(IPSO_CLASS_RES2); } 1307 | IPFY_SEC_RSV3 { $$ = secbit(IPSO_CLASS_RES3); } 1308 | IPFY_SEC_RSV4 { $$ = secbit(IPSO_CLASS_RES4); } 1309 | IPFY_SEC_SEC { $$ = secbit(IPSO_CLASS_SECR); } 1310 | IPFY_SEC_TS { $$ = secbit(IPSO_CLASS_TOPS); } 1311 ; 1312 1313 icmptype: 1314 YY_NUMBER { $$ = $1; } 1315 | IPFY_ICMPT_UNR { $$ = ICMP_UNREACH; } 1316 | IPFY_ICMPT_ECHO { $$ = ICMP_ECHO; } 1317 | IPFY_ICMPT_ECHOR { $$ = ICMP_ECHOREPLY; } 1318 | IPFY_ICMPT_SQUENCH { $$ = ICMP_SOURCEQUENCH; } 1319 | IPFY_ICMPT_REDIR { $$ = ICMP_REDIRECT; } 1320 | IPFY_ICMPT_TIMEX { $$ = ICMP_TIMXCEED; } 1321 | IPFY_ICMPT_PARAMP { $$ = ICMP_PARAMPROB; } 1322 | IPFY_ICMPT_TIMEST { $$ = ICMP_TSTAMP; } 1323 | IPFY_ICMPT_TIMESTREP { $$ = ICMP_TSTAMPREPLY; } 1324 | IPFY_ICMPT_INFOREQ { $$ = ICMP_IREQ; } 1325 | IPFY_ICMPT_INFOREP { $$ = ICMP_IREQREPLY; } 1326 | IPFY_ICMPT_MASKREQ { $$ = ICMP_MASKREQ; } 1327 | IPFY_ICMPT_MASKREP { $$ = ICMP_MASKREPLY; } 1328 | IPFY_ICMPT_ROUTERAD { $$ = ICMP_ROUTERADVERT; } 1329 | IPFY_ICMPT_ROUTERSOL { $$ = ICMP_ROUTERSOLICIT; } 1330 ; 1331 1332 icmpcode: 1333 YY_NUMBER { $$ = $1; } 1334 | IPFY_ICMPC_NETUNR { $$ = ICMP_UNREACH_NET; } 1335 | IPFY_ICMPC_HSTUNR { $$ = ICMP_UNREACH_HOST; } 1336 | IPFY_ICMPC_PROUNR { $$ = ICMP_UNREACH_PROTOCOL; } 1337 | IPFY_ICMPC_PORUNR { $$ = ICMP_UNREACH_PORT; } 1338 | IPFY_ICMPC_NEEDF { $$ = ICMP_UNREACH_NEEDFRAG; } 1339 | IPFY_ICMPC_SRCFAIL { $$ = ICMP_UNREACH_SRCFAIL; } 1340 | IPFY_ICMPC_NETUNK { $$ = ICMP_UNREACH_NET_UNKNOWN; } 1341 | IPFY_ICMPC_HSTUNK { $$ = ICMP_UNREACH_HOST_UNKNOWN; } 1342 | IPFY_ICMPC_ISOLATE { $$ = ICMP_UNREACH_ISOLATED; } 1343 | IPFY_ICMPC_NETPRO { $$ = ICMP_UNREACH_NET_PROHIB; } 1344 | IPFY_ICMPC_HSTPRO { $$ = ICMP_UNREACH_HOST_PROHIB; } 1345 | IPFY_ICMPC_NETTOS { $$ = ICMP_UNREACH_TOSNET; } 1346 | IPFY_ICMPC_HSTTOS { $$ = ICMP_UNREACH_TOSHOST; } 1347 | IPFY_ICMPC_FLTPRO { $$ = ICMP_UNREACH_ADMIN_PROHIBIT; } 1348 | IPFY_ICMPC_HSTPRE { $$ = 14; } 1349 | IPFY_ICMPC_CUTPRE { $$ = 15; } 1350 ; 1351 1352 opt: 1353 IPFY_IPOPT_NOP { $$ = getoptbyvalue(IPOPT_NOP); } 1354 | IPFY_IPOPT_RR { $$ = getoptbyvalue(IPOPT_RR); } 1355 | IPFY_IPOPT_ZSU { $$ = getoptbyvalue(IPOPT_ZSU); } 1356 | IPFY_IPOPT_MTUP { $$ = getoptbyvalue(IPOPT_MTUP); } 1357 | IPFY_IPOPT_MTUR { $$ = getoptbyvalue(IPOPT_MTUR); } 1358 | IPFY_IPOPT_ENCODE { $$ = getoptbyvalue(IPOPT_ENCODE); } 1359 | IPFY_IPOPT_TS { $$ = getoptbyvalue(IPOPT_TS); } 1360 | IPFY_IPOPT_TR { $$ = getoptbyvalue(IPOPT_TR); } 1361 | IPFY_IPOPT_SEC { $$ = getoptbyvalue(IPOPT_SECURITY); } 1362 | IPFY_IPOPT_LSRR { $$ = getoptbyvalue(IPOPT_LSRR); } 1363 | IPFY_IPOPT_ESEC { $$ = getoptbyvalue(IPOPT_E_SEC); } 1364 | IPFY_IPOPT_CIPSO { $$ = getoptbyvalue(IPOPT_CIPSO); } 1365 | IPFY_IPOPT_SATID { $$ = getoptbyvalue(IPOPT_SATID); } 1366 | IPFY_IPOPT_SSRR { $$ = getoptbyvalue(IPOPT_SSRR); } 1367 | IPFY_IPOPT_ADDEXT { $$ = getoptbyvalue(IPOPT_ADDEXT); } 1368 | IPFY_IPOPT_VISA { $$ = getoptbyvalue(IPOPT_VISA); } 1369 | IPFY_IPOPT_IMITD { $$ = getoptbyvalue(IPOPT_IMITD); } 1370 | IPFY_IPOPT_EIP { $$ = getoptbyvalue(IPOPT_EIP); } 1371 | IPFY_IPOPT_FINN { $$ = getoptbyvalue(IPOPT_FINN); } 1372 | IPFY_IPOPT_DPS { $$ = getoptbyvalue(IPOPT_DPS); } 1373 | IPFY_IPOPT_SDB { $$ = getoptbyvalue(IPOPT_SDB); } 1374 | IPFY_IPOPT_NSAPA { $$ = getoptbyvalue(IPOPT_NSAPA); } 1375 | IPFY_IPOPT_RTRALRT { $$ = getoptbyvalue(IPOPT_RTRALRT); } 1376 | IPFY_IPOPT_UMP { $$ = getoptbyvalue(IPOPT_UMP); } 1377 | IPFY_SECCLASS secname 1378 { DOALL(fr->fr_mip.fi_secmsk |= $2; 1379 if (!nowith) 1380 fr->fr_ip.fi_secmsk |= $2;) 1381 $$ = 0; 1382 } 1383 ; 1384 1385 ipv6hdr: 1386 IPFY_AH { $$ = getv6optbyvalue(IPPROTO_AH); } 1387 | IPFY_IPV6OPT_DSTOPTS { $$ = getv6optbyvalue(IPPROTO_DSTOPTS); } 1388 | IPFY_ESP { $$ = getv6optbyvalue(IPPROTO_ESP); } 1389 | IPFY_IPV6OPT_HOPOPTS { $$ = getv6optbyvalue(IPPROTO_HOPOPTS); } 1390 | IPFY_IPV6OPT_IPV6 { $$ = getv6optbyvalue(IPPROTO_IPV6); } 1391 | IPFY_IPV6OPT_NONE { $$ = getv6optbyvalue(IPPROTO_NONE); } 1392 | IPFY_IPV6OPT_ROUTING { $$ = getv6optbyvalue(IPPROTO_ROUTING); } 1393 | IPFY_FRAG { $$ = getv6optbyvalue(IPPROTO_FRAGMENT); } 1394 ; 1395 1396 level: IPFY_LEVEL { setsyslog(); } 1397 ; 1398 1399 loglevel: 1400 priority { fr->fr_loglevel = LOG_LOCAL0|$1; } 1401 | facility '.' priority { fr->fr_loglevel = $1 | $3; } 1402 ; 1403 1404 facility: 1405 IPFY_FAC_KERN { $$ = LOG_KERN; } 1406 | IPFY_FAC_USER { $$ = LOG_USER; } 1407 | IPFY_FAC_MAIL { $$ = LOG_MAIL; } 1408 | IPFY_FAC_DAEMON { $$ = LOG_DAEMON; } 1409 | IPFY_FAC_AUTH { $$ = LOG_AUTH; } 1410 | IPFY_FAC_SYSLOG { $$ = LOG_SYSLOG; } 1411 | IPFY_FAC_LPR { $$ = LOG_LPR; } 1412 | IPFY_FAC_NEWS { $$ = LOG_NEWS; } 1413 | IPFY_FAC_UUCP { $$ = LOG_UUCP; } 1414 | IPFY_FAC_CRON { $$ = LOG_CRON; } 1415 | IPFY_FAC_FTP { $$ = LOG_FTP; } 1416 | IPFY_FAC_AUTHPRIV { $$ = LOG_AUTHPRIV; } 1417 | IPFY_FAC_AUDIT { $$ = LOG_AUDIT; } 1418 | IPFY_FAC_LFMT { $$ = LOG_LFMT; } 1419 | IPFY_FAC_LOCAL0 { $$ = LOG_LOCAL0; } 1420 | IPFY_FAC_LOCAL1 { $$ = LOG_LOCAL1; } 1421 | IPFY_FAC_LOCAL2 { $$ = LOG_LOCAL2; } 1422 | IPFY_FAC_LOCAL3 { $$ = LOG_LOCAL3; } 1423 | IPFY_FAC_LOCAL4 { $$ = LOG_LOCAL4; } 1424 | IPFY_FAC_LOCAL5 { $$ = LOG_LOCAL5; } 1425 | IPFY_FAC_LOCAL6 { $$ = LOG_LOCAL6; } 1426 | IPFY_FAC_LOCAL7 { $$ = LOG_LOCAL7; } 1427 | IPFY_FAC_SECURITY { $$ = LOG_SECURITY; } 1428 ; 1429 1430 priority: 1431 IPFY_PRI_EMERG { $$ = LOG_EMERG; } 1432 | IPFY_PRI_ALERT { $$ = LOG_ALERT; } 1433 | IPFY_PRI_CRIT { $$ = LOG_CRIT; } 1434 | IPFY_PRI_ERR { $$ = LOG_ERR; } 1435 | IPFY_PRI_WARN { $$ = LOG_WARNING; } 1436 | IPFY_PRI_NOTICE { $$ = LOG_NOTICE; } 1437 | IPFY_PRI_INFO { $$ = LOG_INFO; } 1438 | IPFY_PRI_DEBUG { $$ = LOG_DEBUG; } 1439 ; 1440 1441 compare: 1442 '=' { $$ = FR_EQUAL; } 1443 | YY_CMP_EQ { $$ = FR_EQUAL; } 1444 | YY_CMP_NE { $$ = FR_NEQUAL; } 1445 | YY_CMP_LT { $$ = FR_LESST; } 1446 | YY_CMP_LE { $$ = FR_LESSTE; } 1447 | YY_CMP_GT { $$ = FR_GREATERT; } 1448 | YY_CMP_GE { $$ = FR_GREATERTE; } 1449 ; 1450 1451 range: YY_RANGE_IN { $$ = FR_INRANGE; } 1452 | YY_RANGE_OUT { $$ = FR_OUTRANGE; } 1453 | ':' { $$ = FR_INCRANGE; } 1454 ; 1455 1456 servicename: 1457 YY_STR { $$ = $1; } 1458 ; 1459 1460 interfacename: YY_STR { $$ = $1; } 1461 | YY_STR ':' YY_NUMBER 1462 { $$ = $1; 1463 #if SOLARIS2 >= 10 1464 if (strncmp(VNI, $1, VNISTRLEN) != 0) 1465 #endif 1466 fprintf(stderr, "%d: Logical interface %s:%d unsupported, " 1467 "use the physical interface %s instead.\n", 1468 yylineNum, $1, $3, $1); 1469 } 1470 ; 1471 1472 name: YY_STR { $$ = $1; } 1473 ; 1474 1475 ipv4: YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER 1476 { if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) { 1477 yyerror("Invalid octet string for IP address"); 1478 return 0; 1479 } 1480 $$.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7; 1481 $$.s_addr = htonl($$.s_addr); 1482 } 1483 ; 1484 %% 1485 1486 1487 static struct wordtab ipfwords[] = { 1488 { "addext", IPFY_IPOPT_ADDEXT }, 1489 { "age", IPFY_AGE }, 1490 { "ah", IPFY_AH }, 1491 { "all", IPFY_ALL }, 1492 { "and", IPFY_AND }, 1493 { "auth", IPFY_AUTH }, 1494 { "bad", IPFY_BAD }, 1495 { "bad-nat", IPFY_BADNAT }, 1496 { "bad-src", IPFY_BADSRC }, 1497 { "bcast", IPFY_BROADCAST }, 1498 { "block", IPFY_BLOCK }, 1499 { "body", IPFY_BODY }, 1500 { "bpf", IPFY_BPF }, 1501 { "call", IPFY_CALL }, 1502 { "cipso", IPFY_IPOPT_CIPSO }, 1503 { "code", IPFY_ICMPCODE }, 1504 { "confid", IPFY_SEC_CONF }, 1505 { "count", IPFY_COUNT }, 1506 { "divert", IPFY_DIVERT }, 1507 { "dps", IPFY_IPOPT_DPS }, 1508 { "dstopts", IPFY_IPV6OPT_DSTOPTS }, 1509 { "dup-to", IPFY_DUPTO }, 1510 { "e-sec", IPFY_IPOPT_ESEC }, 1511 { "eip", IPFY_IPOPT_EIP }, 1512 { "encode", IPFY_IPOPT_ENCODE }, 1513 { "eq", YY_CMP_EQ }, 1514 { "esp", IPFY_ESP }, 1515 { "fastroute", IPFY_FROUTE }, 1516 { "first", IPFY_FIRST }, 1517 { "finn", IPFY_IPOPT_FINN }, 1518 { "frag", IPFY_FRAG }, 1519 { "flags", IPFY_FLAGS }, 1520 { "frags", IPFY_FRAGS }, 1521 { "from", IPFY_FROM }, 1522 { "ge", YY_CMP_GE }, 1523 { "group", IPFY_GROUP }, 1524 { "gt", YY_CMP_GT }, 1525 { "head", IPFY_HEAD }, 1526 { "hopopts", IPFY_IPV6OPT_HOPOPTS }, 1527 { "host-preced", IPFY_ICMPC_HSTPRE }, 1528 { "host-prohib", IPFY_ICMPC_HSTPRO }, 1529 { "host-tos", IPFY_ICMPC_HSTTOS }, 1530 { "host-unk", IPFY_ICMPC_HSTUNK }, 1531 { "host-unr", IPFY_ICMPC_HSTUNR }, 1532 { "icmp", IPFY_ICMP }, 1533 { "icmp-type", IPFY_ICMPTYPE }, 1534 { "imitd", IPFY_IPOPT_IMITD }, 1535 { "in", IPFY_IN }, 1536 { "in-via", IPFY_INVIA }, 1537 { "ipopt", IPFY_IPOPTS }, 1538 { "ipopts", IPFY_IPOPTS }, 1539 { "ipv6", IPFY_IPV6OPT_IPV6 }, 1540 { "keep", IPFY_KEEP }, 1541 { "le", YY_CMP_LE }, 1542 { "level", IPFY_LEVEL }, 1543 { "limit", IPFY_LIMIT }, 1544 { "log", IPFY_LOG }, 1545 { "lowttl", IPFY_LOWTTL }, 1546 { "lsrr", IPFY_IPOPT_LSRR }, 1547 { "lt", YY_CMP_LT }, 1548 { "mask", IPFY_MASK }, 1549 { "mbcast", IPFY_MBCAST }, 1550 { "mtup", IPFY_IPOPT_MTUP }, 1551 { "mtur", IPFY_IPOPT_MTUR }, 1552 { "multicast", IPFY_MULTICAST }, 1553 { "nat", IPFY_NAT }, 1554 { "ne", YY_CMP_NE }, 1555 { "net", IPFY_NETWORK }, 1556 { "newisn", IPFY_NEWISN }, 1557 { "no", IPFY_NO }, 1558 { "no-icmp-err", IPFY_NOICMPERR }, 1559 { "none", IPFY_IPV6OPT_NONE }, 1560 { "nop", IPFY_IPOPT_NOP }, 1561 { "now", IPFY_NOW }, 1562 { "not", IPFY_NOT }, 1563 { "nsapa", IPFY_IPOPT_NSAPA }, 1564 { "oow", IPFY_OOW }, 1565 { "on", IPFY_ON }, 1566 { "opt", IPFY_OPT }, 1567 { "or-block", IPFY_ORBLOCK }, 1568 { "out", IPFY_OUT }, 1569 { "out-via", IPFY_OUTVIA }, 1570 { "pass", IPFY_PASS }, 1571 { "port", IPFY_PORT }, 1572 { "pps", IPFY_PPS }, 1573 { "preauth", IPFY_PREAUTH }, 1574 { "proto", IPFY_PROTO }, 1575 { "quick", IPFY_QUICK }, 1576 { "reply-to", IPFY_REPLY_TO }, 1577 { "reserv-1", IPFY_SEC_RSV1 }, 1578 { "reserv-2", IPFY_SEC_RSV2 }, 1579 { "reserv-3", IPFY_SEC_RSV3 }, 1580 { "reserv-4", IPFY_SEC_RSV4 }, 1581 { "return-icmp", IPFY_RETICMP }, 1582 { "return-icmp-as-dest", IPFY_RETICMPASDST }, 1583 { "return-rst", IPFY_RETRST }, 1584 { "routing", IPFY_IPV6OPT_ROUTING }, 1585 { "rr", IPFY_IPOPT_RR }, 1586 { "rtralrt", IPFY_IPOPT_RTRALRT }, 1587 { "satid", IPFY_IPOPT_SATID }, 1588 { "sdb", IPFY_IPOPT_SDB }, 1589 { "sec", IPFY_IPOPT_SEC }, 1590 { "sec-class", IPFY_SECCLASS }, 1591 { "secret", IPFY_SEC_SEC }, 1592 { "skip", IPFY_SKIP }, 1593 { "short", IPFY_SHORT }, 1594 { "ssrr", IPFY_IPOPT_SSRR }, 1595 { "state", IPFY_STATE }, 1596 { "strict", IPFY_STRICT }, 1597 { "tag", IPFY_TAG }, 1598 { "tcp", IPFY_TCP }, 1599 { "tcp-udp", IPFY_TCPUDP }, 1600 { "tos", IPFY_TOS }, 1601 { "topsecret", IPFY_SEC_TS }, 1602 { "to", IPFY_TO }, 1603 { "tr", IPFY_IPOPT_TR }, 1604 { "ts", IPFY_IPOPT_TS }, 1605 { "ttl", IPFY_TTL }, 1606 { "udp", IPFY_UDP }, 1607 { "ump", IPFY_IPOPT_UMP }, 1608 { "unclass", IPFY_SEC_UNC }, 1609 { "v6hdrs", IPF6_V6HDRS }, 1610 { "visa", IPFY_IPOPT_VISA }, 1611 { "with", IPFY_WITH }, 1612 { "zsu", IPFY_IPOPT_ZSU }, 1613 { NULL, 0 } 1614 }; 1615 1616 static struct wordtab addrwords[4] = { 1617 { "any", IPFY_ANY }, 1618 { "hash", IPFY_HASH }, 1619 { "pool", IPFY_POOL }, 1620 { NULL, 0 } 1621 }; 1622 1623 static struct wordtab maskwords[5] = { 1624 { "broadcast", IPFY_BROADCAST }, 1625 { "netmasked", IPFY_NETMASKED }, 1626 { "network", IPFY_NETWORK }, 1627 { "peer", IPFY_PEER }, 1628 { NULL, 0 } 1629 }; 1630 1631 static struct wordtab icmptypewords[16] = { 1632 { "echo", IPFY_ICMPT_ECHO }, 1633 { "echorep", IPFY_ICMPT_ECHOR }, 1634 { "inforeq", IPFY_ICMPT_INFOREQ }, 1635 { "inforep", IPFY_ICMPT_INFOREP }, 1636 { "maskrep", IPFY_ICMPT_MASKREP }, 1637 { "maskreq", IPFY_ICMPT_MASKREQ }, 1638 { "paramprob", IPFY_ICMPT_PARAMP }, 1639 { "redir", IPFY_ICMPT_REDIR }, 1640 { "unreach", IPFY_ICMPT_UNR }, 1641 { "routerad", IPFY_ICMPT_ROUTERAD }, 1642 { "routersol", IPFY_ICMPT_ROUTERSOL }, 1643 { "squench", IPFY_ICMPT_SQUENCH }, 1644 { "timest", IPFY_ICMPT_TIMEST }, 1645 { "timestrep", IPFY_ICMPT_TIMESTREP }, 1646 { "timex", IPFY_ICMPT_TIMEX }, 1647 { NULL, 0 }, 1648 }; 1649 1650 static struct wordtab icmpcodewords[17] = { 1651 { "cutoff-preced", IPFY_ICMPC_CUTPRE }, 1652 { "filter-prohib", IPFY_ICMPC_FLTPRO }, 1653 { "isolate", IPFY_ICMPC_ISOLATE }, 1654 { "needfrag", IPFY_ICMPC_NEEDF }, 1655 { "net-prohib", IPFY_ICMPC_NETPRO }, 1656 { "net-tos", IPFY_ICMPC_NETTOS }, 1657 { "host-preced", IPFY_ICMPC_HSTPRE }, 1658 { "host-prohib", IPFY_ICMPC_HSTPRO }, 1659 { "host-tos", IPFY_ICMPC_HSTTOS }, 1660 { "host-unk", IPFY_ICMPC_HSTUNK }, 1661 { "host-unr", IPFY_ICMPC_HSTUNR }, 1662 { "net-unk", IPFY_ICMPC_NETUNK }, 1663 { "net-unr", IPFY_ICMPC_NETUNR }, 1664 { "port-unr", IPFY_ICMPC_PORUNR }, 1665 { "proto-unr", IPFY_ICMPC_PROUNR }, 1666 { "srcfail", IPFY_ICMPC_SRCFAIL }, 1667 { NULL, 0 }, 1668 }; 1669 1670 static struct wordtab logwords[] = { 1671 { "kern", IPFY_FAC_KERN }, 1672 { "user", IPFY_FAC_USER }, 1673 { "mail", IPFY_FAC_MAIL }, 1674 { "daemon", IPFY_FAC_DAEMON }, 1675 { "auth", IPFY_FAC_AUTH }, 1676 { "syslog", IPFY_FAC_SYSLOG }, 1677 { "lpr", IPFY_FAC_LPR }, 1678 { "news", IPFY_FAC_NEWS }, 1679 { "uucp", IPFY_FAC_UUCP }, 1680 { "cron", IPFY_FAC_CRON }, 1681 { "ftp", IPFY_FAC_FTP }, 1682 { "authpriv", IPFY_FAC_AUTHPRIV }, 1683 { "audit", IPFY_FAC_AUDIT }, 1684 { "logalert", IPFY_FAC_LFMT }, 1685 { "console", IPFY_FAC_CONSOLE }, 1686 { "security", IPFY_FAC_SECURITY }, 1687 { "local0", IPFY_FAC_LOCAL0 }, 1688 { "local1", IPFY_FAC_LOCAL1 }, 1689 { "local2", IPFY_FAC_LOCAL2 }, 1690 { "local3", IPFY_FAC_LOCAL3 }, 1691 { "local4", IPFY_FAC_LOCAL4 }, 1692 { "local5", IPFY_FAC_LOCAL5 }, 1693 { "local6", IPFY_FAC_LOCAL6 }, 1694 { "local7", IPFY_FAC_LOCAL7 }, 1695 { "emerg", IPFY_PRI_EMERG }, 1696 { "alert", IPFY_PRI_ALERT }, 1697 { "crit", IPFY_PRI_CRIT }, 1698 { "err", IPFY_PRI_ERR }, 1699 { "warn", IPFY_PRI_WARN }, 1700 { "notice", IPFY_PRI_NOTICE }, 1701 { "info", IPFY_PRI_INFO }, 1702 { "debug", IPFY_PRI_DEBUG }, 1703 { NULL, 0 }, 1704 }; 1705 1706 1707 1708 1709 int ipf_parsefile(fd, addfunc, iocfuncs, filename) 1710 int fd; 1711 addfunc_t addfunc; 1712 ioctlfunc_t *iocfuncs; 1713 char *filename; 1714 { 1715 FILE *fp = NULL; 1716 char *s; 1717 1718 yylineNum = 1; 1719 yysettab(ipfwords); 1720 1721 s = getenv("YYDEBUG"); 1722 if (s != NULL) 1723 yydebug = atoi(s); 1724 else 1725 yydebug = 0; 1726 1727 if (strcmp(filename, "-")) { 1728 fp = fopen(filename, "r"); 1729 if (fp == NULL) { 1730 fprintf(stderr, "fopen(%s) failed: %s\n", filename, 1731 STRERROR(errno)); 1732 return -1; 1733 } 1734 } else 1735 fp = stdin; 1736 1737 while (ipf_parsesome(fd, addfunc, iocfuncs, fp) == 1) 1738 ; 1739 if (fp != NULL) 1740 fclose(fp); 1741 return 0; 1742 } 1743 1744 1745 int ipf_parsesome(fd, addfunc, iocfuncs, fp) 1746 int fd; 1747 addfunc_t addfunc; 1748 ioctlfunc_t *iocfuncs; 1749 FILE *fp; 1750 { 1751 char *s; 1752 int i; 1753 1754 ipffd = fd; 1755 for (i = 0; i <= IPL_LOGMAX; i++) 1756 ipfioctl[i] = iocfuncs[i]; 1757 ipfaddfunc = addfunc; 1758 1759 if (feof(fp)) 1760 return 0; 1761 i = fgetc(fp); 1762 if (i == EOF) 1763 return 0; 1764 if (ungetc(i, fp) == 0) 1765 return 0; 1766 if (feof(fp)) 1767 return 0; 1768 s = getenv("YYDEBUG"); 1769 if (s != NULL) 1770 yydebug = atoi(s); 1771 else 1772 yydebug = 0; 1773 1774 yyin = fp; 1775 yyparse(); 1776 return 1; 1777 } 1778 1779 1780 static void newrule() 1781 { 1782 frentry_t *frn; 1783 1784 frn = (frentry_t *)calloc(1, sizeof(frentry_t)); 1785 for (fr = frtop; fr != NULL && fr->fr_next != NULL; fr = fr->fr_next) 1786 ; 1787 if (fr != NULL) 1788 fr->fr_next = frn; 1789 if (frtop == NULL) 1790 frtop = frn; 1791 fr = frn; 1792 frc = frn; 1793 fr->fr_loglevel = 0xffff; 1794 fr->fr_isc = (void *)-1; 1795 fr->fr_logtag = FR_NOLOGTAG; 1796 fr->fr_type = FR_T_NONE; 1797 if (use_inet6 != 0) 1798 fr->fr_v = 6; 1799 else 1800 fr->fr_v = 4; 1801 1802 nrules = 1; 1803 } 1804 1805 1806 static void setipftype() 1807 { 1808 for (fr = frc; fr != NULL; fr = fr->fr_next) { 1809 if (fr->fr_type == FR_T_NONE) { 1810 fr->fr_type = FR_T_IPF; 1811 fr->fr_data = (void *)calloc(sizeof(fripf_t), 1); 1812 fr->fr_dsize = sizeof(fripf_t); 1813 fr->fr_ip.fi_v = frc->fr_v; 1814 fr->fr_mip.fi_v = 0xf; 1815 fr->fr_ipf->fri_sifpidx = -1; 1816 fr->fr_ipf->fri_difpidx = -1; 1817 } 1818 if (fr->fr_type != FR_T_IPF) { 1819 fprintf(stderr, "IPF Type not set\n"); 1820 } 1821 } 1822 } 1823 1824 1825 static frentry_t *addrule() 1826 { 1827 frentry_t *f, *f1, *f2; 1828 int count; 1829 1830 for (f2 = frc; f2->fr_next != NULL; f2 = f2->fr_next) 1831 ; 1832 1833 count = nrules; 1834 if (count == 0) { 1835 f = (frentry_t *)calloc(sizeof(*f), 1); 1836 added++; 1837 f2->fr_next = f; 1838 bcopy(f2, f, sizeof(*f)); 1839 if (f2->fr_caddr != NULL) { 1840 f->fr_caddr = malloc(f->fr_dsize); 1841 bcopy(f2->fr_caddr, f->fr_caddr, f->fr_dsize); 1842 } 1843 f->fr_next = NULL; 1844 return f; 1845 } 1846 f = f2; 1847 for (f1 = frc; count > 0; count--, f1 = f1->fr_next) { 1848 f->fr_next = (frentry_t *)calloc(sizeof(*f), 1); 1849 added++; 1850 f = f->fr_next; 1851 bcopy(f1, f, sizeof(*f)); 1852 f->fr_next = NULL; 1853 if (f->fr_caddr != NULL) { 1854 f->fr_caddr = malloc(f->fr_dsize); 1855 bcopy(f1->fr_caddr, f->fr_caddr, f->fr_dsize); 1856 } 1857 } 1858 1859 return f2->fr_next; 1860 } 1861 1862 1863 static u_32_t lookuphost(name) 1864 char *name; 1865 { 1866 u_32_t addr; 1867 int i; 1868 1869 hashed = 0; 1870 pooled = 0; 1871 dynamic = -1; 1872 1873 for (i = 0; i < 4; i++) { 1874 if (strncmp(name, frc->fr_ifnames[i], 1875 sizeof(frc->fr_ifnames[i])) == 0) { 1876 ifpflag = FRI_DYNAMIC; 1877 dynamic = i; 1878 return 0; 1879 } 1880 } 1881 1882 if (gethost(name, &addr) == -1) { 1883 return 0; 1884 } 1885 return addr; 1886 } 1887 1888 1889 static void dobpf(phrase) 1890 char *phrase; 1891 { 1892 #ifdef IPFILTER_BPF 1893 struct bpf_program bpf; 1894 struct pcap *p; 1895 u_32_t l; 1896 char *s; 1897 int i; 1898 1899 for (fr = frc; fr != NULL; fr = fr->fr_next) { 1900 if (fr->fr_type != FR_T_NONE) { 1901 fprintf(stderr, "cannoy mix IPF and BPF matching\n"); 1902 return; 1903 } 1904 fr->fr_type = FR_T_IPF; 1905 1906 if (!strncmp(phrase, "\"0x", 2)) { 1907 phrase++; 1908 fr->fr_data = malloc(4); 1909 1910 for (i = 0, s = strtok(phrase, " \r\n\t"; s != NULL; 1911 s = strtok(NULL, " \r\n\t"), i++) { 1912 fr->fr_data = realloc(fr->fr_data, (i + 1) * 4); 1913 l = (u_32_t)strtol(s, NULL, 0); 1914 ((u_32_t *)fr->fr_data)[i] = l; 1915 } 1916 return; 1917 } 1918 1919 bzero((char *)&bpf, sizeof(bpf)); 1920 p = pcap_open_dead(DLT_RAW, 1); 1921 if (!p) { 1922 fprintf(stderr, "pcap_open_dead failed\n"); 1923 return; 1924 } 1925 1926 if (pcap_compile(p, &bpf, phrase, 1, 0xffffffff) { 1927 pcap_perror(p, "ipf"); 1928 pcap_close(p); 1929 fprintf(stderr, "pcap parsing failed\n"); 1930 return; 1931 } 1932 pcap_close(p); 1933 1934 fr->fr_dsize = bpf.bf_len * sizeof(struct bpf_insn); 1935 fr->fr_data = malloc(bpf.bf_len); 1936 bcopy((char *)bpf.bf_insns, fr->fr_data, bpf.bf_len); 1937 if (!bpf_validate(fr->fr_data, bpf.bf_len)) { 1938 fprintf(stderr, "BPF validation failed\n"); 1939 return; 1940 } 1941 } 1942 1943 if (opts & OPT_DEBUG) 1944 bpf_dump(&bpf, 0); 1945 #else 1946 fprintf(stderr, "BPF expressions for matching not supported\n"); 1947 #endif 1948 } 1949 1950 1951 static void resetaddr() 1952 { 1953 hashed = 0; 1954 pooled = 0; 1955 dynamic = -1; 1956 } 1957 1958 1959 static alist_t *newalist(ptr) 1960 alist_t *ptr; 1961 { 1962 alist_t *al; 1963 1964 al = malloc(sizeof(*al)); 1965 if (al == NULL) 1966 return NULL; 1967 al->al_not = 0; 1968 al->al_next = ptr; 1969 return al; 1970 } 1971 1972 1973 static int makepool(list) 1974 alist_t *list; 1975 { 1976 ip_pool_node_t *n, *top; 1977 ip_pool_t pool; 1978 alist_t *a; 1979 int num; 1980 1981 if (list == NULL) 1982 return 0; 1983 top = calloc(1, sizeof(*top)); 1984 if (top == NULL) 1985 return 0; 1986 1987 for (n = top, a = list; (n != NULL) && (a != NULL); a = a->al_next) { 1988 n->ipn_addr.adf_family = a->al_family; 1989 n->ipn_mask.adf_family = a->al_family; 1990 (void *)bcopy((void *)&a->al_i6addr, 1991 (void *)&n->ipn_addr.adf_addr, 1992 sizeof(n->ipn_addr.adf_addr)); 1993 (void *)bcopy((void *)&a->al_i6mask, 1994 (void *)&n->ipn_mask.adf_addr, 1995 sizeof(n->ipn_mask.adf_addr)); 1996 n->ipn_info = a->al_not; 1997 if (a->al_next != NULL) { 1998 n->ipn_next = calloc(1, sizeof(*n)); 1999 n = n->ipn_next; 2000 } 2001 } 2002 2003 bzero((char *)&pool, sizeof(pool)); 2004 pool.ipo_unit = IPL_LOGIPF; 2005 pool.ipo_list = top; 2006 num = load_pool(&pool, ipfioctl[IPL_LOGLOOKUP]); 2007 2008 while ((n = top) != NULL) { 2009 top = n->ipn_next; 2010 free(n); 2011 } 2012 return num; 2013 } 2014 2015 2016 static u_int makehash(list) 2017 alist_t *list; 2018 { 2019 iphtent_t *n, *top; 2020 iphtable_t iph; 2021 alist_t *a; 2022 int num; 2023 2024 if (list == NULL) 2025 return 0; 2026 top = calloc(1, sizeof(*top)); 2027 if (top == NULL) 2028 return 0; 2029 2030 for (n = top, a = list; (n != NULL) && (a != NULL); a = a->al_next) { 2031 n->ipe_family = a->al_family; 2032 (void *)bcopy((void *)&a->al_i6addr, 2033 (void *)&n->ipe_addr, 2034 sizeof(n->ipe_addr)); 2035 (void *)bcopy((void *)&a->al_i6mask, 2036 (void *)&n->ipe_mask, 2037 sizeof(n->ipe_mask)); 2038 n->ipe_value = 0; 2039 if (a->al_next != NULL) { 2040 n->ipe_next = calloc(1, sizeof(*n)); 2041 n = n->ipe_next; 2042 } 2043 } 2044 2045 bzero((char *)&iph, sizeof(iph)); 2046 iph.iph_unit = IPL_LOGIPF; 2047 iph.iph_type = IPHASH_LOOKUP; 2048 *iph.iph_name = '\0'; 2049 2050 if (load_hash(&iph, top, ipfioctl[IPL_LOGLOOKUP]) == 0) 2051 sscanf(iph.iph_name, "%u", &num); 2052 else 2053 num = 0; 2054 2055 while ((n = top) != NULL) { 2056 top = n->ipe_next; 2057 free(n); 2058 } 2059 return num; 2060 } 2061 2062 2063 void ipf_addrule(fd, ioctlfunc, ptr) 2064 int fd; 2065 ioctlfunc_t ioctlfunc; 2066 void *ptr; 2067 { 2068 u_int add, del; 2069 frentry_t *fr; 2070 ipfobj_t obj; 2071 2072 fr = ptr; 2073 add = 0; 2074 del = 0; 2075 2076 bzero((char *)&obj, sizeof(obj)); 2077 obj.ipfo_rev = IPFILTER_VERSION; 2078 obj.ipfo_size = sizeof(*fr); 2079 obj.ipfo_type = IPFOBJ_FRENTRY; 2080 obj.ipfo_ptr = ptr; 2081 2082 if ((opts & OPT_DONOTHING) != 0) 2083 fd = -1; 2084 2085 if (opts & OPT_ZERORULEST) { 2086 add = SIOCZRLST; 2087 } else if (opts & OPT_INACTIVE) { 2088 add = (u_int)fr->fr_hits ? SIOCINIFR : 2089 SIOCADIFR; 2090 del = SIOCRMIFR; 2091 } else { 2092 add = (u_int)fr->fr_hits ? SIOCINAFR : 2093 SIOCADAFR; 2094 del = SIOCRMAFR; 2095 } 2096 2097 if (fr && (opts & OPT_OUTQUE)) 2098 fr->fr_flags |= FR_OUTQUE; 2099 if (fr->fr_hits) 2100 fr->fr_hits--; 2101 if (fr && (opts & OPT_VERBOSE)) 2102 printfr(fr, ioctlfunc); 2103 2104 if (opts & OPT_DEBUG) { 2105 binprint(fr, sizeof(*fr)); 2106 if (fr->fr_data != NULL) 2107 binprint(fr->fr_data, fr->fr_dsize); 2108 } 2109 2110 if ((opts & OPT_ZERORULEST) != 0) { 2111 if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) { 2112 if ((opts & OPT_DONOTHING) == 0) { 2113 fprintf(stderr, "%d:", yylineNum); 2114 perror("ioctl(SIOCZRLST)"); 2115 } 2116 } else { 2117 #ifdef USE_QUAD_T 2118 printf("hits %qd bytes %qd ", 2119 (long long)fr->fr_hits, 2120 (long long)fr->fr_bytes); 2121 #else 2122 printf("hits %ld bytes %ld ", 2123 fr->fr_hits, fr->fr_bytes); 2124 #endif 2125 printfr(fr, ioctlfunc); 2126 } 2127 } else if ((opts & OPT_REMOVE) != 0) { 2128 if ((*ioctlfunc)(fd, del, (void *)&obj) == -1) { 2129 if ((opts & OPT_DONOTHING) == 0) { 2130 fprintf(stderr, "%d:", yylineNum); 2131 perror("ioctl(delete rule)"); 2132 } 2133 } 2134 } else { 2135 if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) { 2136 if (!(opts & OPT_DONOTHING)) { 2137 fprintf(stderr, "%d:", yylineNum); 2138 fprintf(stderr,"ioctl(add/insert rule) failed: rule exists\n"); 2139 } 2140 } 2141 } 2142 } 2143 2144 2145 static void setsyslog() 2146 { 2147 savewords = yysettab(logwords); 2148 yybreakondot = 1; 2149 } 2150 2151 2152 static void unsetsyslog() 2153 { 2154 yysettab(savewords); 2155 yybreakondot = 0; 2156 } 2157 2158 2159 static void fillgroup(fr) 2160 frentry_t *fr; 2161 { 2162 frentry_t *f; 2163 int i; 2164 2165 for (f = frold; f != NULL; f = f->fr_next) 2166 if (strncmp(f->fr_grhead, fr->fr_group, FR_GROUPLEN) == 0) 2167 break; 2168 if (f == NULL) 2169 return; 2170 2171 /* 2172 * Only copy down matching fields if the rules are of the same type 2173 * and are of ipf type. 2174 */ 2175 if (f->fr_type != fr->fr_type || f->fr_type != FR_T_IPF) 2176 return; 2177 2178 if (fr->fr_v == 0 && f->fr_v != 0) 2179 fr->fr_v = f->fr_v; 2180 2181 if (fr->fr_mproto == 0 && f->fr_mproto != 0) 2182 fr->fr_mproto = f->fr_mproto; 2183 if (fr->fr_proto == 0 && f->fr_proto != 0) 2184 fr->fr_proto = f->fr_proto; 2185 2186 if (fr->fr_proto == IPPROTO_TCP) { 2187 if (fr->fr_tcpfm == 0 && f->fr_tcpfm != 0) 2188 fr->fr_tcpfm = f->fr_tcpfm; 2189 if (fr->fr_tcpf == 0 && f->fr_tcpf != 0) 2190 fr->fr_tcpf = f->fr_tcpf; 2191 } 2192 2193 if (fr->fr_proto == IPPROTO_ICMP) { 2194 if (fr->fr_icmpm == 0 && f->fr_icmpm != 0) 2195 fr->fr_icmpm = f->fr_icmpm; 2196 if (fr->fr_icmp == 0 && f->fr_icmp != 0) 2197 fr->fr_icmp = f->fr_icmp; 2198 } 2199 2200 if (fr->fr_optbits == 0 && f->fr_optbits != 0) 2201 fr->fr_optbits = f->fr_optbits; 2202 if (fr->fr_optmask == 0 && f->fr_optmask != 0) 2203 fr->fr_optmask = f->fr_optmask; 2204 if (fr->fr_secbits == 0 && f->fr_secbits != 0) 2205 fr->fr_secbits = f->fr_secbits; 2206 if (fr->fr_secmask == 0 && f->fr_secmask != 0) 2207 fr->fr_secmask = f->fr_secmask; 2208 if (fr->fr_authbits == 0 && f->fr_authbits != 0) 2209 fr->fr_authbits = f->fr_authbits; 2210 if (fr->fr_authmask == 0 && f->fr_authmask != 0) 2211 fr->fr_authmask = f->fr_authmask; 2212 2213 for (i = 0; i < 3; i++) { 2214 if (*f->fr_ifnames[i] != '\0' && *fr->fr_ifnames[i] == '\0') 2215 strncpy(fr->fr_ifnames[i], f->fr_ifnames[i], 2216 sizeof(f->fr_ifnames[i])); 2217 } 2218 } 2219