1 /* $FreeBSD$ */ 2 3 /* 4 * Copyright (C) 2012 by Darren Reed. 5 * 6 * See the IPFILTER.LICENCE file for details on licencing. 7 */ 8 %{ 9 #include "ipf.h" 10 #include <sys/ioctl.h> 11 #include <syslog.h> 12 #include <err.h> 13 #ifdef IPFILTER_BPF 14 # include <pcap.h> 15 #endif 16 #include "netinet/ip_pool.h" 17 #include "netinet/ip_htable.h" 18 #include "netinet/ipl.h" 19 #include "ipf_l.h" 20 21 #define YYDEBUG 1 22 #define DOALL(x) for (fr = frc; fr != NULL; fr = fr->fr_next) { x } 23 #define DOREM(x) for (; fr != NULL; fr = fr->fr_next) { x } 24 25 extern void yyerror(char *); 26 extern int yyparse(void); 27 extern int yylex(void); 28 extern int yydebug; 29 extern FILE *yyin; 30 extern int yylineNum; 31 32 static int addname(frentry_t **, char *); 33 static frentry_t *addrule(void); 34 static frentry_t *allocfr(void); 35 static void build_dstaddr_af(frentry_t *, void *); 36 static void build_srcaddr_af(frentry_t *, void *); 37 static void dobpf(int, char *); 38 static void doipfexpr(char *); 39 static void do_tuneint(char *, int); 40 static void do_tunestr(char *, char *); 41 static void fillgroup(frentry_t *); 42 static int lookuphost(char *, i6addr_t *); 43 static u_int makehash(struct alist_s *); 44 static int makepool(struct alist_s *); 45 static struct alist_s *newalist(struct alist_s *); 46 static void newrule(void); 47 static void resetaddr(void); 48 static void setgroup(frentry_t **, char *); 49 static void setgrhead(frentry_t **, char *); 50 static void seticmphead(frentry_t **, char *); 51 static void setifname(frentry_t **, int, char *); 52 static void setipftype(void); 53 static void setsyslog(void); 54 static void unsetsyslog(void); 55 56 frentry_t *fr = NULL, *frc = NULL, *frtop = NULL, *frold = NULL; 57 58 static int ifpflag = 0; 59 static int nowith = 0; 60 static int dynamic = -1; 61 static int pooled = 0; 62 static int hashed = 0; 63 static int nrules = 0; 64 static int newlist = 0; 65 static int added = 0; 66 static int ipffd = -1; 67 static int *yycont = NULL; 68 static ioctlfunc_t ipfioctls[IPL_LOGSIZE]; 69 static addfunc_t ipfaddfunc = NULL; 70 71 %} 72 %union { 73 char *str; 74 u_32_t num; 75 frentry_t fr; 76 frtuc_t *frt; 77 struct alist_s *alist; 78 u_short port; 79 struct in_addr ip4; 80 struct { 81 u_short p1; 82 u_short p2; 83 int pc; 84 } pc; 85 struct ipp_s { 86 int type; 87 int ifpos; 88 int f; 89 int v; 90 int lif; 91 union i6addr a; 92 union i6addr m; 93 char *name; 94 } ipp; 95 struct { 96 i6addr_t adr; 97 int f; 98 } adr; 99 i6addr_t ip6; 100 struct { 101 char *if1; 102 char *if2; 103 } ifs; 104 char gname[FR_GROUPLEN]; 105 }; 106 107 %type <port> portnum 108 %type <num> facility priority icmpcode seclevel secname icmptype 109 %type <num> opt compare range opttype flagset optlist ipv6hdrlist ipv6hdr 110 %type <num> portc porteq ipmask maskopts 111 %type <ip4> ipv4 ipv4_16 ipv4_24 112 %type <adr> hostname 113 %type <ipp> addr ipaddr 114 %type <str> servicename name interfacename groupname 115 %type <pc> portrange portcomp 116 %type <alist> addrlist poollist 117 %type <ifs> onname 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_SET 127 %token IPFY_PASS IPFY_BLOCK IPFY_COUNT IPFY_CALL IPFY_NOMATCH 128 %token IPFY_RETICMP IPFY_RETRST IPFY_RETICMPASDST 129 %token IPFY_IN IPFY_OUT 130 %token IPFY_QUICK IPFY_ON IPFY_OUTVIA IPFY_INVIA 131 %token IPFY_DUPTO IPFY_TO IPFY_FROUTE IPFY_REPLY_TO IPFY_ROUTETO 132 %token IPFY_TOS IPFY_TTL IPFY_PROTO IPFY_INET IPFY_INET6 133 %token IPFY_HEAD IPFY_GROUP 134 %token IPFY_AUTH IPFY_PREAUTH 135 %token IPFY_LOG IPFY_BODY IPFY_FIRST IPFY_LEVEL IPFY_ORBLOCK IPFY_L5AS 136 %token IPFY_LOGTAG IPFY_MATCHTAG IPFY_SETTAG IPFY_SKIP IPFY_DECAPS 137 %token IPFY_FROM IPFY_ALL IPFY_ANY IPFY_BPFV4 IPFY_BPFV6 IPFY_POOL IPFY_HASH 138 %token IPFY_IPFEXPR IPFY_PPS IPFY_FAMILY IPFY_DSTLIST 139 %token IPFY_ESP IPFY_AH 140 %token IPFY_WITH IPFY_AND IPFY_NOT IPFY_NO IPFY_OPT 141 %token IPFY_TCPUDP IPFY_TCP IPFY_UDP 142 %token IPFY_FLAGS IPFY_MULTICAST 143 %token IPFY_MASK IPFY_BROADCAST IPFY_NETWORK IPFY_NETMASKED IPFY_PEER 144 %token IPFY_RPC IPFY_PORT 145 %token IPFY_NOW IPFY_COMMENT IPFY_RULETTL 146 %token IPFY_ICMP IPFY_ICMPTYPE IPFY_ICMPCODE 147 %token IPFY_IPOPTS IPFY_SHORT IPFY_NAT IPFY_BADSRC IPFY_LOWTTL IPFY_FRAG 148 %token IPFY_MBCAST IPFY_BAD IPFY_BADNAT IPFY_OOW IPFY_NEWISN IPFY_NOICMPERR 149 %token IPFY_KEEP IPFY_STATE IPFY_FRAGS IPFY_LIMIT IPFY_STRICT IPFY_AGE 150 %token IPFY_SYNC IPFY_FRAGBODY IPFY_ICMPHEAD IPFY_NOLOG IPFY_LOOSE 151 %token IPFY_MAX_SRCS IPFY_MAX_PER_SRC 152 %token IPFY_IPOPT_NOP IPFY_IPOPT_RR IPFY_IPOPT_ZSU IPFY_IPOPT_MTUP 153 %token IPFY_IPOPT_MTUR IPFY_IPOPT_ENCODE IPFY_IPOPT_TS IPFY_IPOPT_TR 154 %token IPFY_IPOPT_SEC IPFY_IPOPT_LSRR IPFY_IPOPT_ESEC IPFY_IPOPT_CIPSO 155 %token IPFY_IPOPT_SATID IPFY_IPOPT_SSRR IPFY_IPOPT_ADDEXT IPFY_IPOPT_VISA 156 %token IPFY_IPOPT_IMITD IPFY_IPOPT_EIP IPFY_IPOPT_FINN IPFY_IPOPT_DPS 157 %token IPFY_IPOPT_SDB IPFY_IPOPT_NSAPA IPFY_IPOPT_RTRALRT IPFY_IPOPT_UMP 158 %token IPFY_SECCLASS IPFY_SEC_UNC IPFY_SEC_CONF IPFY_SEC_RSV1 IPFY_SEC_RSV2 159 %token IPFY_SEC_RSV4 IPFY_SEC_SEC IPFY_SEC_TS IPFY_SEC_RSV3 IPFY_DOI 160 161 %token IPFY_V6HDRS IPFY_IPV6OPT IPFY_IPV6OPT_DSTOPTS IPFY_IPV6OPT_HOPOPTS 162 %token IPFY_IPV6OPT_IPV6 IPFY_IPV6OPT_NONE IPFY_IPV6OPT_ROUTING IPFY_V6HDR 163 %token IPFY_IPV6OPT_MOBILITY IPFY_IPV6OPT_ESP IPFY_IPV6OPT_FRAG 164 165 %token IPFY_ICMPT_UNR IPFY_ICMPT_ECHO IPFY_ICMPT_ECHOR IPFY_ICMPT_SQUENCH 166 %token IPFY_ICMPT_REDIR IPFY_ICMPT_TIMEX IPFY_ICMPT_PARAMP IPFY_ICMPT_TIMEST 167 %token IPFY_ICMPT_TIMESTREP IPFY_ICMPT_INFOREQ IPFY_ICMPT_INFOREP 168 %token IPFY_ICMPT_MASKREQ IPFY_ICMPT_MASKREP IPFY_ICMPT_ROUTERAD 169 %token IPFY_ICMPT_ROUTERSOL 170 171 %token IPFY_ICMPC_NETUNR IPFY_ICMPC_HSTUNR IPFY_ICMPC_PROUNR IPFY_ICMPC_PORUNR 172 %token IPFY_ICMPC_NEEDF IPFY_ICMPC_SRCFAIL IPFY_ICMPC_NETUNK IPFY_ICMPC_HSTUNK 173 %token IPFY_ICMPC_ISOLATE IPFY_ICMPC_NETPRO IPFY_ICMPC_HSTPRO 174 %token IPFY_ICMPC_NETTOS IPFY_ICMPC_HSTTOS IPFY_ICMPC_FLTPRO IPFY_ICMPC_HSTPRE 175 %token IPFY_ICMPC_CUTPRE 176 177 %token IPFY_FAC_KERN IPFY_FAC_USER IPFY_FAC_MAIL IPFY_FAC_DAEMON IPFY_FAC_AUTH 178 %token IPFY_FAC_SYSLOG IPFY_FAC_LPR IPFY_FAC_NEWS IPFY_FAC_UUCP IPFY_FAC_CRON 179 %token IPFY_FAC_LOCAL0 IPFY_FAC_LOCAL1 IPFY_FAC_LOCAL2 IPFY_FAC_LOCAL3 180 %token IPFY_FAC_LOCAL4 IPFY_FAC_LOCAL5 IPFY_FAC_LOCAL6 IPFY_FAC_LOCAL7 181 %token IPFY_FAC_SECURITY IPFY_FAC_FTP IPFY_FAC_AUTHPRIV IPFY_FAC_AUDIT 182 %token IPFY_FAC_LFMT IPFY_FAC_CONSOLE 183 184 %token IPFY_PRI_EMERG IPFY_PRI_ALERT IPFY_PRI_CRIT IPFY_PRI_ERR IPFY_PRI_WARN 185 %token IPFY_PRI_NOTICE IPFY_PRI_INFO IPFY_PRI_DEBUG 186 %% 187 file: settings rules 188 | rules 189 ; 190 191 settings: 192 YY_COMMENT 193 | setting 194 | settings setting 195 ; 196 197 rules: line 198 | assign 199 | rules line 200 | rules assign 201 ; 202 203 setting: 204 IPFY_SET YY_STR YY_NUMBER ';' { do_tuneint($2, $3); } 205 | IPFY_SET YY_STR YY_HEX ';' { do_tuneint($2, $3); } 206 | IPFY_SET YY_STR YY_STR ';' { do_tunestr($2, $3); } 207 ; 208 209 line: rule { while ((fr = frtop) != NULL) { 210 frtop = fr->fr_next; 211 fr->fr_next = NULL; 212 if ((fr->fr_type == FR_T_IPF) && 213 (fr->fr_ip.fi_v == 0)) 214 fr->fr_mip.fi_v = 0; 215 /* XXX validate ? */ 216 (*ipfaddfunc)(ipffd, ipfioctls[IPL_LOGIPF], fr); 217 fr->fr_next = frold; 218 frold = fr; 219 } 220 resetlexer(); 221 } 222 | YY_COMMENT 223 ; 224 225 xx: { newrule(); } 226 ; 227 228 assign: YY_STR assigning YY_STR ';' { set_variable($1, $3); 229 resetlexer(); 230 free($1); 231 free($3); 232 yyvarnext = 0; 233 } 234 ; 235 236 assigning: 237 '=' { yyvarnext = 1; } 238 ; 239 240 rule: inrule eol 241 | outrule eol 242 ; 243 244 eol: | ';' 245 ; 246 247 inrule: 248 rulehead markin inopts rulemain ruletail intag ruletail2 249 ; 250 251 outrule: 252 rulehead markout outopts rulemain ruletail outtag ruletail2 253 ; 254 255 rulehead: 256 xx collection action 257 | xx insert collection action 258 ; 259 260 markin: IPFY_IN { fr->fr_flags |= FR_INQUE; } 261 ; 262 263 markout: 264 IPFY_OUT { fr->fr_flags |= FR_OUTQUE; } 265 ; 266 267 rulemain: 268 ipfrule 269 | bpfrule 270 | exprrule 271 ; 272 273 ipfrule: 274 family tos ttl proto ip 275 ; 276 277 family: | IPFY_FAMILY IPFY_INET { if (use_inet6 == 1) { 278 YYERROR; 279 } else { 280 frc->fr_family = AF_INET; 281 } 282 } 283 | IPFY_INET { if (use_inet6 == 1) { 284 YYERROR; 285 } else { 286 frc->fr_family = AF_INET; 287 } 288 } 289 | IPFY_FAMILY IPFY_INET6 { if (use_inet6 == -1) { 290 YYERROR; 291 } else { 292 frc->fr_family = AF_INET6; 293 } 294 } 295 | IPFY_INET6 { if (use_inet6 == -1) { 296 YYERROR; 297 } else { 298 frc->fr_family = AF_INET6; 299 } 300 } 301 ; 302 303 bpfrule: 304 IPFY_BPFV4 '{' YY_STR '}' { dobpf(4, $3); free($3); } 305 | IPFY_BPFV6 '{' YY_STR '}' { dobpf(6, $3); free($3); } 306 ; 307 308 exprrule: 309 IPFY_IPFEXPR '{' YY_STR '}' { doipfexpr($3); } 310 ; 311 312 ruletail: 313 with keep head group 314 ; 315 316 ruletail2: 317 pps age new rulettl comment 318 ; 319 320 intag: settagin matchtagin 321 ; 322 323 outtag: settagout matchtagout 324 ; 325 326 insert: 327 '@' YY_NUMBER { fr->fr_hits = (U_QUAD_T)$2 + 1; } 328 ; 329 330 collection: 331 | YY_NUMBER { fr->fr_collect = $1; } 332 ; 333 334 action: block 335 | IPFY_PASS { fr->fr_flags |= FR_PASS; } 336 | IPFY_NOMATCH { fr->fr_flags |= FR_NOMATCH; } 337 | log 338 | IPFY_COUNT { fr->fr_flags |= FR_ACCOUNT; } 339 | decaps { fr->fr_flags |= FR_DECAPSULATE; } 340 | auth 341 | IPFY_SKIP YY_NUMBER { fr->fr_flags |= FR_SKIP; 342 fr->fr_arg = $2; } 343 | IPFY_CALL func 344 | IPFY_CALL IPFY_NOW func { fr->fr_flags |= FR_CALLNOW; } 345 ; 346 347 block: blocked 348 | blocked blockreturn 349 ; 350 351 blocked: 352 IPFY_BLOCK { fr->fr_flags = FR_BLOCK; } 353 ; 354 blockreturn: 355 IPFY_RETICMP { fr->fr_flags |= FR_RETICMP; } 356 | IPFY_RETICMP returncode { fr->fr_flags |= FR_RETICMP; } 357 | IPFY_RETICMPASDST { fr->fr_flags |= FR_FAKEICMP; } 358 | IPFY_RETICMPASDST returncode { fr->fr_flags |= FR_FAKEICMP; } 359 | IPFY_RETRST { fr->fr_flags |= FR_RETRST; } 360 ; 361 362 decaps: IPFY_DECAPS 363 | IPFY_DECAPS IPFY_L5AS '(' YY_STR ')' 364 { fr->fr_icode = atoi($4); } 365 ; 366 367 log: IPFY_LOG { fr->fr_flags |= FR_LOG; } 368 | IPFY_LOG logoptions { fr->fr_flags |= FR_LOG; } 369 ; 370 371 auth: IPFY_AUTH { fr->fr_flags |= FR_AUTH; } 372 | IPFY_AUTH blockreturn { fr->fr_flags |= FR_AUTH;} 373 | IPFY_PREAUTH { fr->fr_flags |= FR_PREAUTH; } 374 ; 375 376 func: YY_STR '/' YY_NUMBER 377 { fr->fr_func = nametokva($1, ipfioctls[IPL_LOGIPF]); 378 fr->fr_arg = $3; 379 free($1); 380 } 381 ; 382 383 inopts: 384 | inopts inopt 385 ; 386 387 inopt: 388 logopt 389 | quick 390 | on 391 | dup 392 | froute 393 | proute 394 | replyto 395 ; 396 397 outopts: 398 | outopts outopt 399 ; 400 401 outopt: 402 logopt 403 | quick 404 | on 405 | dup 406 | proute 407 | froute 408 | replyto 409 ; 410 411 tos: | settos YY_NUMBER { DOALL(fr->fr_tos = $2; fr->fr_mtos = 0xff;) } 412 | settos YY_HEX { DOALL(fr->fr_tos = $2; fr->fr_mtos = 0xff;) } 413 | settos lstart toslist lend 414 ; 415 416 settos: IPFY_TOS { setipftype(); } 417 ; 418 419 toslist: 420 YY_NUMBER { DOALL(fr->fr_tos = $1; fr->fr_mtos = 0xff;) } 421 | YY_HEX { DOREM(fr->fr_tos = $1; fr->fr_mtos = 0xff;) } 422 | toslist lmore YY_NUMBER 423 { DOREM(fr->fr_tos = $3; fr->fr_mtos = 0xff;) } 424 | toslist lmore YY_HEX 425 { DOREM(fr->fr_tos = $3; fr->fr_mtos = 0xff;) } 426 ; 427 428 ttl: | setttl YY_NUMBER 429 { DOALL(fr->fr_ttl = $2; fr->fr_mttl = 0xff;) } 430 | setttl lstart ttllist lend 431 ; 432 433 lstart: '{' { newlist = 1; fr = frc; added = 0; } 434 ; 435 436 lend: '}' { nrules += added; } 437 ; 438 439 lmore: lanother { if (newlist == 1) { 440 newlist = 0; 441 } 442 fr = addrule(); 443 if (yycont != NULL) 444 *yycont = 1; 445 } 446 ; 447 448 lanother: 449 | ',' 450 ; 451 452 setttl: IPFY_TTL { setipftype(); } 453 ; 454 455 ttllist: 456 YY_NUMBER { DOREM(fr->fr_ttl = $1; fr->fr_mttl = 0xff;) } 457 | ttllist lmore YY_NUMBER 458 { DOREM(fr->fr_ttl = $3; fr->fr_mttl = 0xff;) } 459 ; 460 461 proto: | protox protocol { yyresetdict(); } 462 ; 463 464 protox: IPFY_PROTO { setipftype(); 465 fr = frc; 466 yysetdict(NULL); } 467 ; 468 469 ip: srcdst flags icmp 470 ; 471 472 group: | IPFY_GROUP groupname { DOALL(setgroup(&fr, $2); \ 473 fillgroup(fr);); 474 free($2); 475 } 476 ; 477 478 head: | IPFY_HEAD groupname { DOALL(setgrhead(&fr, $2);); 479 free($2); 480 } 481 ; 482 483 groupname: 484 YY_STR { $$ = $1; 485 if (strlen($$) >= FR_GROUPLEN) 486 $$[FR_GROUPLEN - 1] = '\0'; 487 } 488 | YY_NUMBER { $$ = malloc(16); 489 sprintf($$, "%d", $1); 490 } 491 ; 492 493 settagin: 494 | IPFY_SETTAG '(' taginlist ')' 495 ; 496 497 taginlist: 498 taginspec 499 | taginlist ',' taginspec 500 ; 501 502 taginspec: 503 logtag 504 ; 505 506 nattag: IPFY_NAT '=' YY_STR { DOALL(strncpy(fr->fr_nattag.ipt_tag,\ 507 $3, IPFTAG_LEN);); 508 free($3); } 509 | IPFY_NAT '=' YY_NUMBER { DOALL(sprintf(fr->fr_nattag.ipt_tag,\ 510 "%d", $3 & 0xffffffff);) } 511 ; 512 513 logtag: IPFY_LOG '=' YY_NUMBER { DOALL(fr->fr_logtag = $3;) } 514 ; 515 516 settagout: 517 | IPFY_SETTAG '(' tagoutlist ')' 518 ; 519 520 tagoutlist: 521 tagoutspec 522 | tagoutlist ',' tagoutspec 523 ; 524 525 tagoutspec: 526 logtag 527 | nattag 528 ; 529 530 matchtagin: 531 | IPFY_MATCHTAG '(' tagoutlist ')' 532 ; 533 534 matchtagout: 535 | IPFY_MATCHTAG '(' taginlist ')' 536 ; 537 538 pps: | IPFY_PPS YY_NUMBER { DOALL(fr->fr_pps = $2;) } 539 ; 540 541 new: | savegroup file restoregroup 542 ; 543 544 rulettl: 545 | IPFY_RULETTL YY_NUMBER { DOALL(fr->fr_die = $2;) } 546 ; 547 548 comment: 549 | IPFY_COMMENT YY_STR { DOALL(fr->fr_comment = addname(&fr, \ 550 $2);) } 551 ; 552 553 savegroup: 554 '{' 555 ; 556 557 restoregroup: 558 '}' 559 ; 560 561 logopt: log 562 ; 563 564 quick: IPFY_QUICK { fr->fr_flags |= FR_QUICK; } 565 ; 566 567 on: IPFY_ON onname { setifname(&fr, 0, $2.if1); 568 free($2.if1); 569 if ($2.if2 != NULL) { 570 setifname(&fr, 1, 571 $2.if2); 572 free($2.if2); 573 } 574 } 575 | IPFY_ON lstart onlist lend 576 | IPFY_ON onname IPFY_INVIA vianame { setifname(&fr, 0, $2.if1); 577 free($2.if1); 578 if ($2.if2 != NULL) { 579 setifname(&fr, 1, 580 $2.if2); 581 free($2.if2); 582 } 583 } 584 | IPFY_ON onname IPFY_OUTVIA vianame { setifname(&fr, 0, $2.if1); 585 free($2.if1); 586 if ($2.if2 != NULL) { 587 setifname(&fr, 1, 588 $2.if2); 589 free($2.if2); 590 } 591 } 592 ; 593 594 onlist: onname { DOREM(setifname(&fr, 0, $1.if1); \ 595 if ($1.if2 != NULL) \ 596 setifname(&fr, 1, $1.if2); \ 597 ) 598 free($1.if1); 599 if ($1.if2 != NULL) 600 free($1.if2); 601 } 602 | onlist lmore onname { DOREM(setifname(&fr, 0, $3.if1); \ 603 if ($3.if2 != NULL) \ 604 setifname(&fr, 1, $3.if2); \ 605 ) 606 free($3.if1); 607 if ($3.if2 != NULL) 608 free($3.if2); 609 } 610 ; 611 612 onname: interfacename { $$.if1 = $1; 613 $$.if2 = NULL; 614 } 615 | interfacename ',' interfacename 616 { $$.if1 = $1; 617 $$.if2 = $3; 618 } 619 ; 620 621 vianame: 622 name { setifname(&fr, 2, $1); 623 free($1); 624 } 625 | name ',' name { setifname(&fr, 2, $1); 626 free($1); 627 setifname(&fr, 3, $3); 628 free($3); 629 } 630 ; 631 632 dup: IPFY_DUPTO name 633 { int idx = addname(&fr, $2); 634 fr->fr_dif.fd_name = idx; 635 free($2); 636 } 637 | IPFY_DUPTO IPFY_DSTLIST '/' name 638 { int idx = addname(&fr, $4); 639 fr->fr_dif.fd_name = idx; 640 fr->fr_dif.fd_type = FRD_DSTLIST; 641 free($4); 642 } 643 | IPFY_DUPTO name duptoseparator hostname 644 { int idx = addname(&fr, $2); 645 fr->fr_dif.fd_name = idx; 646 fr->fr_dif.fd_ptr = (void *)-1; 647 fr->fr_dif.fd_ip6 = $4.adr; 648 if (fr->fr_family == AF_UNSPEC && $4.f != AF_UNSPEC) 649 fr->fr_family = $4.f; 650 yyexpectaddr = 0; 651 free($2); 652 } 653 ; 654 655 duptoseparator: 656 ':' { yyexpectaddr = 1; yycont = &yyexpectaddr; resetaddr(); } 657 ; 658 659 froute: IPFY_FROUTE { fr->fr_flags |= FR_FASTROUTE; } 660 ; 661 662 proute: routeto name 663 { int idx = addname(&fr, $2); 664 fr->fr_tif.fd_name = idx; 665 free($2); 666 } 667 | routeto IPFY_DSTLIST '/' name 668 { int idx = addname(&fr, $4); 669 fr->fr_tif.fd_name = idx; 670 fr->fr_tif.fd_type = FRD_DSTLIST; 671 free($4); 672 } 673 | routeto name duptoseparator hostname 674 { int idx = addname(&fr, $2); 675 fr->fr_tif.fd_name = idx; 676 fr->fr_tif.fd_ptr = (void *)-1; 677 fr->fr_tif.fd_ip6 = $4.adr; 678 if (fr->fr_family == AF_UNSPEC && $4.f != AF_UNSPEC) 679 fr->fr_family = $4.f; 680 yyexpectaddr = 0; 681 free($2); 682 } 683 ; 684 685 routeto: 686 IPFY_TO 687 | IPFY_ROUTETO 688 ; 689 690 replyto: 691 IPFY_REPLY_TO name 692 { int idx = addname(&fr, $2); 693 fr->fr_rif.fd_name = idx; 694 free($2); 695 } 696 | IPFY_REPLY_TO IPFY_DSTLIST '/' name 697 { fr->fr_rif.fd_name = addname(&fr, $4); 698 fr->fr_rif.fd_type = FRD_DSTLIST; 699 free($4); 700 } 701 | IPFY_REPLY_TO name duptoseparator hostname 702 { int idx = addname(&fr, $2); 703 fr->fr_rif.fd_name = idx; 704 fr->fr_rif.fd_ptr = (void *)-1; 705 fr->fr_rif.fd_ip6 = $4.adr; 706 if (fr->fr_family == AF_UNSPEC && $4.f != AF_UNSPEC) 707 fr->fr_family = $4.f; 708 free($2); 709 } 710 ; 711 712 logoptions: 713 logoption 714 | logoptions logoption 715 ; 716 717 logoption: 718 IPFY_BODY { fr->fr_flags |= FR_LOGBODY; } 719 | IPFY_FIRST { fr->fr_flags |= FR_LOGFIRST; } 720 | IPFY_ORBLOCK { fr->fr_flags |= FR_LOGORBLOCK; } 721 | level loglevel { unsetsyslog(); } 722 ; 723 724 returncode: 725 starticmpcode icmpcode ')' { fr->fr_icode = $2; yyresetdict(); } 726 ; 727 728 starticmpcode: 729 '(' { yysetdict(icmpcodewords); } 730 ; 731 732 srcdst: | IPFY_ALL 733 | fromto 734 ; 735 736 protocol: 737 YY_NUMBER { DOALL(fr->fr_proto = $1; \ 738 fr->fr_mproto = 0xff;) 739 } 740 | YY_STR { if (!strcmp($1, "tcp-udp")) { 741 DOALL(fr->fr_flx |= FI_TCPUDP; \ 742 fr->fr_mflx |= FI_TCPUDP;) 743 } else { 744 int p = getproto($1); 745 if (p == -1) 746 yyerror("protocol unknown"); 747 DOALL(fr->fr_proto = p; \ 748 fr->fr_mproto = 0xff;) 749 } 750 free($1); 751 } 752 | YY_STR nextstring YY_STR 753 { if (!strcmp($1, "tcp") && 754 !strcmp($3, "udp")) { 755 DOREM(fr->fr_flx |= FI_TCPUDP; \ 756 fr->fr_mflx |= FI_TCPUDP;) 757 } else { 758 YYERROR; 759 } 760 free($1); 761 free($3); 762 } 763 ; 764 765 nextstring: 766 '/' { yysetdict(NULL); } 767 ; 768 769 fromto: from srcobject to dstobject { yyexpectaddr = 0; yycont = NULL; } 770 | to dstobject { yyexpectaddr = 0; yycont = NULL; } 771 | from srcobject { yyexpectaddr = 0; yycont = NULL; } 772 ; 773 774 from: IPFY_FROM { setipftype(); 775 if (fr == NULL) 776 fr = frc; 777 yyexpectaddr = 1; 778 if (yydebug) 779 printf("set yyexpectaddr\n"); 780 yycont = &yyexpectaddr; 781 yysetdict(addrwords); 782 resetaddr(); } 783 ; 784 785 to: IPFY_TO { if (fr == NULL) 786 fr = frc; 787 yyexpectaddr = 1; 788 if (yydebug) 789 printf("set yyexpectaddr\n"); 790 yycont = &yyexpectaddr; 791 yysetdict(addrwords); 792 resetaddr(); 793 } 794 ; 795 796 with: | andwith withlist 797 ; 798 799 andwith: 800 IPFY_WITH { nowith = 0; setipftype(); } 801 | IPFY_AND { nowith = 0; setipftype(); } 802 ; 803 804 flags: | startflags flagset 805 { DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = FR_TCPFMAX;) } 806 | startflags flagset '/' flagset 807 { DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) } 808 | startflags '/' flagset 809 { DOALL(fr->fr_tcpf = 0; fr->fr_tcpfm = $3;) } 810 | startflags YY_NUMBER 811 { DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = FR_TCPFMAX;) } 812 | startflags '/' YY_NUMBER 813 { DOALL(fr->fr_tcpf = 0; fr->fr_tcpfm = $3;) } 814 | startflags YY_NUMBER '/' YY_NUMBER 815 { DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) } 816 | startflags flagset '/' YY_NUMBER 817 { DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) } 818 | startflags YY_NUMBER '/' flagset 819 { DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) } 820 ; 821 822 startflags: 823 IPFY_FLAGS { if (frc->fr_type != FR_T_IPF) 824 yyerror("flags with non-ipf type rule"); 825 if (frc->fr_proto != IPPROTO_TCP) 826 yyerror("flags with non-TCP rule"); 827 } 828 ; 829 830 flagset: 831 YY_STR { $$ = tcpflags($1); free($1); } 832 | YY_HEX { $$ = $1; } 833 ; 834 835 srcobject: 836 { yyresetdict(); } fromport 837 | srcaddr srcport 838 | '!' srcaddr srcport 839 { DOALL(fr->fr_flags |= FR_NOTSRCIP;) } 840 ; 841 842 srcaddr: 843 addr { build_srcaddr_af(fr, &$1); } 844 | lstart srcaddrlist lend 845 ; 846 847 srcaddrlist: 848 addr { build_srcaddr_af(fr, &$1); } 849 | srcaddrlist lmore addr 850 { build_srcaddr_af(fr, &$3); } 851 ; 852 853 srcport: 854 | portcomp 855 { DOALL(fr->fr_scmp = $1.pc; fr->fr_sport = $1.p1;) } 856 | portrange 857 { DOALL(fr->fr_scmp = $1.pc; fr->fr_sport = $1.p1; \ 858 fr->fr_stop = $1.p2;) } 859 | porteq lstart srcportlist lend 860 { yyresetdict(); } 861 ; 862 863 fromport: 864 portcomp 865 { DOALL(fr->fr_scmp = $1.pc; fr->fr_sport = $1.p1;) } 866 | portrange 867 { DOALL(fr->fr_scmp = $1.pc; fr->fr_sport = $1.p1; \ 868 fr->fr_stop = $1.p2;) } 869 | porteq lstart srcportlist lend 870 { yyresetdict(); } 871 ; 872 873 srcportlist: 874 portnum { DOREM(fr->fr_scmp = FR_EQUAL; fr->fr_sport = $1;) } 875 | portnum ':' portnum 876 { DOREM(fr->fr_scmp = FR_INCRANGE; fr->fr_sport = $1; \ 877 fr->fr_stop = $3;) } 878 | portnum YY_RANGE_IN portnum 879 { DOREM(fr->fr_scmp = FR_INRANGE; fr->fr_sport = $1; \ 880 fr->fr_stop = $3;) } 881 | srcportlist lmore portnum 882 { DOREM(fr->fr_scmp = FR_EQUAL; fr->fr_sport = $3;) } 883 | srcportlist lmore portnum ':' portnum 884 { DOREM(fr->fr_scmp = FR_INCRANGE; fr->fr_sport = $3; \ 885 fr->fr_stop = $5;) } 886 | srcportlist lmore portnum YY_RANGE_IN portnum 887 { DOREM(fr->fr_scmp = FR_INRANGE; fr->fr_sport = $3; \ 888 fr->fr_stop = $5;) } 889 ; 890 891 dstobject: 892 { yyresetdict(); } toport 893 | dstaddr dstport 894 | '!' dstaddr dstport 895 { DOALL(fr->fr_flags |= FR_NOTDSTIP;) } 896 ; 897 898 dstaddr: 899 addr { if (($1.f != AF_UNSPEC) && (frc->fr_family != AF_UNSPEC) && 900 ($1.f != frc->fr_family)) 901 yyerror("1.src/dst address family mismatch"); 902 build_dstaddr_af(fr, &$1); 903 } 904 | lstart dstaddrlist lend 905 ; 906 907 dstaddrlist: 908 addr { if (($1.f != AF_UNSPEC) && (frc->fr_family != AF_UNSPEC) && 909 ($1.f != frc->fr_family)) 910 yyerror("2.src/dst address family mismatch"); 911 build_dstaddr_af(fr, &$1); 912 } 913 | dstaddrlist lmore addr 914 { if (($3.f != AF_UNSPEC) && (frc->fr_family != AF_UNSPEC) && 915 ($3.f != frc->fr_family)) 916 yyerror("3.src/dst address family mismatch"); 917 build_dstaddr_af(fr, &$3); 918 } 919 ; 920 921 922 dstport: 923 | portcomp 924 { DOALL(fr->fr_dcmp = $1.pc; fr->fr_dport = $1.p1;) } 925 | portrange 926 { DOALL(fr->fr_dcmp = $1.pc; fr->fr_dport = $1.p1; \ 927 fr->fr_dtop = $1.p2;) } 928 | porteq lstart dstportlist lend 929 { yyresetdict(); } 930 ; 931 932 toport: 933 portcomp 934 { DOALL(fr->fr_dcmp = $1.pc; fr->fr_dport = $1.p1;) } 935 | portrange 936 { DOALL(fr->fr_dcmp = $1.pc; fr->fr_dport = $1.p1; \ 937 fr->fr_dtop = $1.p2;) } 938 | porteq lstart dstportlist lend 939 { yyresetdict(); } 940 ; 941 942 dstportlist: 943 portnum { DOREM(fr->fr_dcmp = FR_EQUAL; fr->fr_dport = $1;) } 944 | portnum ':' portnum 945 { DOREM(fr->fr_dcmp = FR_INCRANGE; fr->fr_dport = $1; \ 946 fr->fr_dtop = $3;) } 947 | portnum YY_RANGE_IN portnum 948 { DOREM(fr->fr_dcmp = FR_INRANGE; fr->fr_dport = $1; \ 949 fr->fr_dtop = $3;) } 950 | dstportlist lmore portnum 951 { DOREM(fr->fr_dcmp = FR_EQUAL; fr->fr_dport = $3;) } 952 | dstportlist lmore portnum ':' portnum 953 { DOREM(fr->fr_dcmp = FR_INCRANGE; fr->fr_dport = $3; \ 954 fr->fr_dtop = $5;) } 955 | dstportlist lmore portnum YY_RANGE_IN portnum 956 { DOREM(fr->fr_dcmp = FR_INRANGE; fr->fr_dport = $3; \ 957 fr->fr_dtop = $5;) } 958 ; 959 960 addr: pool '/' YY_NUMBER { pooled = 1; 961 yyexpectaddr = 0; 962 $$.type = FRI_LOOKUP; 963 $$.v = 0; 964 $$.ifpos = -1; 965 $$.f = AF_UNSPEC; 966 $$.a.iplookuptype = IPLT_POOL; 967 $$.a.iplookupsubtype = 0; 968 $$.a.iplookupnum = $3; } 969 | pool '/' YY_STR { pooled = 1; 970 $$.ifpos = -1; 971 $$.f = AF_UNSPEC; 972 $$.type = FRI_LOOKUP; 973 $$.a.iplookuptype = IPLT_POOL; 974 $$.a.iplookupsubtype = 1; 975 $$.a.iplookupname = addname(&fr, $3); 976 } 977 | pool '=' '(' { yyexpectaddr = 1; 978 pooled = 1; 979 } 980 poollist ')' { yyexpectaddr = 0; 981 $$.v = 0; 982 $$.ifpos = -1; 983 $$.f = AF_UNSPEC; 984 $$.type = FRI_LOOKUP; 985 $$.a.iplookuptype = IPLT_POOL; 986 $$.a.iplookupsubtype = 0; 987 $$.a.iplookupnum = makepool($5); 988 } 989 | hash '/' YY_NUMBER { hashed = 1; 990 yyexpectaddr = 0; 991 $$.v = 0; 992 $$.ifpos = -1; 993 $$.f = AF_UNSPEC; 994 $$.type = FRI_LOOKUP; 995 $$.a.iplookuptype = IPLT_HASH; 996 $$.a.iplookupsubtype = 0; 997 $$.a.iplookupnum = $3; 998 } 999 | hash '/' YY_STR { hashed = 1; 1000 $$.type = FRI_LOOKUP; 1001 $$.v = 0; 1002 $$.ifpos = -1; 1003 $$.f = AF_UNSPEC; 1004 $$.a.iplookuptype = IPLT_HASH; 1005 $$.a.iplookupsubtype = 1; 1006 $$.a.iplookupname = addname(&fr, $3); 1007 } 1008 | hash '=' '(' { hashed = 1; 1009 yyexpectaddr = 1; 1010 } 1011 addrlist ')' { yyexpectaddr = 0; 1012 $$.v = 0; 1013 $$.ifpos = -1; 1014 $$.f = AF_UNSPEC; 1015 $$.type = FRI_LOOKUP; 1016 $$.a.iplookuptype = IPLT_HASH; 1017 $$.a.iplookupsubtype = 0; 1018 $$.a.iplookupnum = makehash($5); 1019 } 1020 | ipaddr { $$ = $1; 1021 yyexpectaddr = 0; } 1022 ; 1023 1024 ipaddr: IPFY_ANY { memset(&($$), 0, sizeof($$)); 1025 $$.type = FRI_NORMAL; 1026 $$.ifpos = -1; 1027 yyexpectaddr = 0; 1028 } 1029 | hostname { memset(&($$), 0, sizeof($$)); 1030 $$.a = $1.adr; 1031 $$.f = $1.f; 1032 if ($1.f == AF_INET6) 1033 fill6bits(128, $$.m.i6); 1034 else if ($1.f == AF_INET) 1035 fill6bits(32, $$.m.i6); 1036 $$.v = ftov($1.f); 1037 $$.ifpos = dynamic; 1038 $$.type = FRI_NORMAL; 1039 } 1040 | hostname { yyresetdict(); } 1041 maskspace { yysetdict(maskwords); 1042 yyexpectaddr = 2; } 1043 ipmask { memset(&($$), 0, sizeof($$)); 1044 ntomask($1.f, $5, $$.m.i6); 1045 $$.a = $1.adr; 1046 $$.a.i6[0] &= $$.m.i6[0]; 1047 $$.a.i6[1] &= $$.m.i6[1]; 1048 $$.a.i6[2] &= $$.m.i6[2]; 1049 $$.a.i6[3] &= $$.m.i6[3]; 1050 $$.f = $1.f; 1051 $$.v = ftov($1.f); 1052 $$.type = ifpflag; 1053 $$.ifpos = dynamic; 1054 if (ifpflag != 0 && $$.v == 0) { 1055 if (frc->fr_family == AF_INET6){ 1056 $$.v = 6; 1057 $$.f = AF_INET6; 1058 } else { 1059 $$.v = 4; 1060 $$.f = AF_INET; 1061 } 1062 } 1063 yyresetdict(); 1064 yyexpectaddr = 0; 1065 } 1066 | '(' YY_STR ')' { memset(&($$), 0, sizeof($$)); 1067 $$.type = FRI_DYNAMIC; 1068 ifpflag = FRI_DYNAMIC; 1069 $$.ifpos = addname(&fr, $2); 1070 $$.lif = 0; 1071 } 1072 | '(' YY_STR ')' '/' 1073 { ifpflag = FRI_DYNAMIC; yysetdict(maskwords); } 1074 maskopts 1075 { memset(&($$), 0, sizeof($$)); 1076 $$.type = ifpflag; 1077 $$.ifpos = addname(&fr, $2); 1078 $$.lif = 0; 1079 if (frc->fr_family == AF_UNSPEC) 1080 frc->fr_family = AF_INET; 1081 if (ifpflag == FRI_DYNAMIC) { 1082 ntomask(frc->fr_family, 1083 $6, $$.m.i6); 1084 } 1085 yyresetdict(); 1086 yyexpectaddr = 0; 1087 } 1088 | '(' YY_STR ':' YY_NUMBER ')' '/' 1089 { ifpflag = FRI_DYNAMIC; yysetdict(maskwords); } 1090 maskopts 1091 { memset(&($$), 0, sizeof($$)); 1092 $$.type = ifpflag; 1093 $$.ifpos = addname(&fr, $2); 1094 $$.lif = $4; 1095 if (frc->fr_family == AF_UNSPEC) 1096 frc->fr_family = AF_INET; 1097 if (ifpflag == FRI_DYNAMIC) { 1098 ntomask(frc->fr_family, 1099 $8, $$.m.i6); 1100 } 1101 yyresetdict(); 1102 yyexpectaddr = 0; 1103 } 1104 ; 1105 1106 maskspace: 1107 '/' 1108 | IPFY_MASK 1109 ; 1110 1111 ipmask: ipv4 { $$ = count4bits($1.s_addr); } 1112 | YY_HEX { $$ = count4bits(htonl($1)); } 1113 | YY_NUMBER { $$ = $1; } 1114 | YY_IPV6 { $$ = count6bits($1.i6); } 1115 | maskopts { $$ = $1; } 1116 ; 1117 1118 maskopts: 1119 IPFY_BROADCAST { if (ifpflag == FRI_DYNAMIC) { 1120 ifpflag = FRI_BROADCAST; 1121 } else { 1122 YYERROR; 1123 } 1124 $$ = 0; 1125 } 1126 | IPFY_NETWORK { if (ifpflag == FRI_DYNAMIC) { 1127 ifpflag = FRI_NETWORK; 1128 } else { 1129 YYERROR; 1130 } 1131 $$ = 0; 1132 } 1133 | IPFY_NETMASKED { if (ifpflag == FRI_DYNAMIC) { 1134 ifpflag = FRI_NETMASKED; 1135 } else { 1136 YYERROR; 1137 } 1138 $$ = 0; 1139 } 1140 | IPFY_PEER { if (ifpflag == FRI_DYNAMIC) { 1141 ifpflag = FRI_PEERADDR; 1142 } else { 1143 YYERROR; 1144 } 1145 $$ = 0; 1146 } 1147 | YY_NUMBER { $$ = $1; } 1148 ; 1149 1150 hostname: 1151 ipv4 { memset(&($$), 0, sizeof($$)); 1152 $$.adr.in4 = $1; 1153 if (frc->fr_family == AF_INET6) 1154 YYERROR; 1155 $$.f = AF_INET; 1156 yyexpectaddr = 2; 1157 } 1158 | YY_NUMBER { memset(&($$), 0, sizeof($$)); 1159 if (frc->fr_family == AF_INET6) 1160 YYERROR; 1161 $$.adr.in4_addr = $1; 1162 $$.f = AF_INET; 1163 yyexpectaddr = 2; 1164 } 1165 | YY_HEX { memset(&($$), 0, sizeof($$)); 1166 if (frc->fr_family == AF_INET6) 1167 YYERROR; 1168 $$.adr.in4_addr = $1; 1169 $$.f = AF_INET; 1170 yyexpectaddr = 2; 1171 } 1172 | YY_STR { memset(&($$), 0, sizeof($$)); 1173 if (lookuphost($1, &$$.adr) == 0) 1174 $$.f = AF_INET; 1175 free($1); 1176 yyexpectaddr = 2; 1177 } 1178 | YY_IPV6 { memset(&($$), 0, sizeof($$)); 1179 if (frc->fr_family == AF_INET) 1180 YYERROR; 1181 $$.adr = $1; 1182 $$.f = AF_INET6; 1183 yyexpectaddr = 2; 1184 } 1185 ; 1186 1187 addrlist: 1188 ipaddr { $$ = newalist(NULL); 1189 $$->al_family = $1.f; 1190 $$->al_i6addr = $1.a; 1191 $$->al_i6mask = $1.m; 1192 } 1193 | ipaddr ',' { yyexpectaddr = 1; } addrlist 1194 { $$ = newalist($4); 1195 $$->al_family = $1.f; 1196 $$->al_i6addr = $1.a; 1197 $$->al_i6mask = $1.m; 1198 } 1199 ; 1200 1201 pool: IPFY_POOL { yyexpectaddr = 0; yycont = NULL; yyresetdict(); } 1202 ; 1203 1204 hash: IPFY_HASH { yyexpectaddr = 0; yycont = NULL; yyresetdict(); } 1205 ; 1206 1207 poollist: 1208 ipaddr { $$ = newalist(NULL); 1209 $$->al_family = $1.f; 1210 $$->al_i6addr = $1.a; 1211 $$->al_i6mask = $1.m; 1212 } 1213 | '!' ipaddr { $$ = newalist(NULL); 1214 $$->al_not = 1; 1215 $$->al_family = $2.f; 1216 $$->al_i6addr = $2.a; 1217 $$->al_i6mask = $2.m; 1218 } 1219 | poollist ',' ipaddr 1220 { $$ = newalist($1); 1221 $$->al_family = $3.f; 1222 $$->al_i6addr = $3.a; 1223 $$->al_i6mask = $3.m; 1224 } 1225 | poollist ',' '!' ipaddr 1226 { $$ = newalist($1); 1227 $$->al_not = 1; 1228 $$->al_family = $4.f; 1229 $$->al_i6addr = $4.a; 1230 $$->al_i6mask = $4.m; 1231 } 1232 ; 1233 1234 port: IPFY_PORT { yyexpectaddr = 0; 1235 yycont = NULL; 1236 if (frc->fr_proto != 0 && 1237 frc->fr_proto != IPPROTO_UDP && 1238 frc->fr_proto != IPPROTO_TCP) 1239 yyerror("port use incorrect"); 1240 } 1241 ; 1242 1243 portc: port compare { $$ = $2; 1244 yysetdict(NULL); 1245 } 1246 | porteq { $$ = $1; } 1247 ; 1248 1249 porteq: port '=' { $$ = FR_EQUAL; 1250 yysetdict(NULL); 1251 } 1252 ; 1253 1254 portr: IPFY_PORT { yyexpectaddr = 0; 1255 yycont = NULL; 1256 yysetdict(NULL); 1257 } 1258 ; 1259 1260 portcomp: 1261 portc portnum { $$.pc = $1; 1262 $$.p1 = $2; 1263 yyresetdict(); 1264 } 1265 ; 1266 1267 portrange: 1268 portr portnum range portnum { $$.p1 = $2; 1269 $$.pc = $3; 1270 $$.p2 = $4; 1271 yyresetdict(); 1272 } 1273 ; 1274 1275 icmp: | itype icode 1276 ; 1277 1278 itype: seticmptype icmptype 1279 { DOALL(fr->fr_icmp = htons($2 << 8); fr->fr_icmpm = htons(0xff00);); 1280 yyresetdict(); 1281 } 1282 | seticmptype lstart typelist lend { yyresetdict(); } 1283 ; 1284 1285 seticmptype: 1286 IPFY_ICMPTYPE { if (frc->fr_family == AF_UNSPEC) 1287 frc->fr_family = AF_INET; 1288 if (frc->fr_family == AF_INET && 1289 frc->fr_type == FR_T_IPF && 1290 frc->fr_proto != IPPROTO_ICMP) { 1291 yyerror("proto not icmp"); 1292 } 1293 if (frc->fr_family == AF_INET6 && 1294 frc->fr_type == FR_T_IPF && 1295 frc->fr_proto != IPPROTO_ICMPV6) { 1296 yyerror("proto not ipv6-icmp"); 1297 } 1298 setipftype(); 1299 DOALL(if (fr->fr_family == AF_INET) { \ 1300 fr->fr_ip.fi_v = 4; \ 1301 fr->fr_mip.fi_v = 0xf; \ 1302 } 1303 if (fr->fr_family == AF_INET6) { \ 1304 fr->fr_ip.fi_v = 6; \ 1305 fr->fr_mip.fi_v = 0xf; \ 1306 } 1307 ) 1308 yysetdict(NULL); 1309 } 1310 ; 1311 1312 icode: | seticmpcode icmpcode 1313 { DOALL(fr->fr_icmp |= htons($2); fr->fr_icmpm |= htons(0xff);); 1314 yyresetdict(); 1315 } 1316 | seticmpcode lstart codelist lend { yyresetdict(); } 1317 ; 1318 1319 seticmpcode: 1320 IPFY_ICMPCODE { yysetdict(icmpcodewords); } 1321 ; 1322 1323 typelist: 1324 icmptype 1325 { DOREM(fr->fr_icmp = htons($1 << 8); fr->fr_icmpm = htons(0xff00);) } 1326 | typelist lmore icmptype 1327 { DOREM(fr->fr_icmp = htons($3 << 8); fr->fr_icmpm = htons(0xff00);) } 1328 ; 1329 1330 codelist: 1331 icmpcode 1332 { DOREM(fr->fr_icmp |= htons($1); fr->fr_icmpm |= htons(0xff);) } 1333 | codelist lmore icmpcode 1334 { DOREM(fr->fr_icmp &= htons(0xff00); fr->fr_icmp |= htons($3); \ 1335 fr->fr_icmpm |= htons(0xff);) } 1336 ; 1337 1338 age: | IPFY_AGE YY_NUMBER { DOALL(fr->fr_age[0] = $2; \ 1339 fr->fr_age[1] = $2;) } 1340 | IPFY_AGE YY_NUMBER '/' YY_NUMBER 1341 { DOALL(fr->fr_age[0] = $2; \ 1342 fr->fr_age[1] = $4;) } 1343 ; 1344 1345 keep: | IPFY_KEEP keepstate keep 1346 | IPFY_KEEP keepfrag keep 1347 ; 1348 1349 keepstate: 1350 IPFY_STATE stateoptlist { DOALL(fr->fr_flags |= FR_KEEPSTATE;)} 1351 ; 1352 1353 keepfrag: 1354 IPFY_FRAGS fragoptlist { DOALL(fr->fr_flags |= FR_KEEPFRAG;) } 1355 | IPFY_FRAG fragoptlist { DOALL(fr->fr_flags |= FR_KEEPFRAG;) } 1356 ; 1357 1358 fragoptlist: 1359 | '(' fragopts ')' 1360 ; 1361 1362 fragopts: 1363 fragopt lanother fragopts 1364 | fragopt 1365 ; 1366 1367 fragopt: 1368 IPFY_STRICT { DOALL(fr->fr_flags |= FR_FRSTRICT;) } 1369 ; 1370 1371 stateoptlist: 1372 | '(' stateopts ')' 1373 ; 1374 1375 stateopts: 1376 stateopt lanother stateopts 1377 | stateopt 1378 ; 1379 1380 stateopt: 1381 IPFY_LIMIT YY_NUMBER { DOALL(fr->fr_statemax = $2;) } 1382 | IPFY_STRICT { DOALL(if (fr->fr_proto != IPPROTO_TCP) { \ 1383 YYERROR; \ 1384 } else if (fr->fr_flags & FR_STLOOSE) {\ 1385 YYERROR; \ 1386 } else \ 1387 fr->fr_flags |= FR_STSTRICT;) 1388 } 1389 | IPFY_LOOSE { DOALL(if (fr->fr_proto != IPPROTO_TCP) { \ 1390 YYERROR; \ 1391 } else if (fr->fr_flags & FR_STSTRICT){\ 1392 YYERROR; \ 1393 } else \ 1394 fr->fr_flags |= FR_STLOOSE;) 1395 } 1396 | IPFY_NEWISN { DOALL(if (fr->fr_proto != IPPROTO_TCP) { \ 1397 YYERROR; \ 1398 } else \ 1399 fr->fr_flags |= FR_NEWISN;) 1400 } 1401 | IPFY_NOICMPERR { DOALL(fr->fr_flags |= FR_NOICMPERR;) } 1402 1403 | IPFY_SYNC { DOALL(fr->fr_flags |= FR_STATESYNC;) } 1404 | IPFY_AGE YY_NUMBER { DOALL(fr->fr_age[0] = $2; \ 1405 fr->fr_age[1] = $2;) } 1406 | IPFY_AGE YY_NUMBER '/' YY_NUMBER 1407 { DOALL(fr->fr_age[0] = $2; \ 1408 fr->fr_age[1] = $4;) } 1409 | IPFY_ICMPHEAD groupname 1410 { DOALL(seticmphead(&fr, $2);) 1411 free($2); 1412 } 1413 | IPFY_NOLOG 1414 { DOALL(fr->fr_nostatelog = 1;) } 1415 | IPFY_RPC 1416 { DOALL(fr->fr_rpc = 1;) } 1417 | IPFY_RPC IPFY_IN YY_STR 1418 { DOALL(fr->fr_rpc = 1;) } 1419 | IPFY_MAX_SRCS YY_NUMBER 1420 { DOALL(fr->fr_srctrack.ht_max_nodes = $2;) } 1421 | IPFY_MAX_PER_SRC YY_NUMBER 1422 { DOALL(fr->fr_srctrack.ht_max_per_node = $2; \ 1423 fr->fr_srctrack.ht_netmask = \ 1424 fr->fr_family == AF_INET ? 32: 128;) 1425 } 1426 | IPFY_MAX_PER_SRC YY_NUMBER '/' YY_NUMBER 1427 { DOALL(fr->fr_srctrack.ht_max_per_node = $2; \ 1428 fr->fr_srctrack.ht_netmask = $4;) 1429 } 1430 ; 1431 1432 portnum: 1433 servicename { if (getport(frc, $1, 1434 &($$), NULL) == -1) 1435 yyerror("service unknown"); 1436 $$ = ntohs($$); 1437 free($1); 1438 } 1439 | YY_NUMBER { if ($1 > 65535) /* Unsigned */ 1440 yyerror("invalid port number"); 1441 else 1442 $$ = $1; 1443 } 1444 ; 1445 1446 withlist: 1447 withopt { nowith = 0; } 1448 | withlist withopt { nowith = 0; } 1449 | withlist ',' withopt { nowith = 0; } 1450 ; 1451 1452 withopt: 1453 opttype { DOALL(fr->fr_flx |= $1; fr->fr_mflx |= $1;) } 1454 | notwith opttype { DOALL(fr->fr_mflx |= $2;) } 1455 | ipopt ipopts { yyresetdict(); } 1456 | notwith ipopt ipopts { yyresetdict(); } 1457 | startv6hdr ipv6hdrs { yyresetdict(); } 1458 ; 1459 1460 ipopt: IPFY_OPT { yysetdict(ipv4optwords); } 1461 ; 1462 1463 startv6hdr: 1464 IPFY_V6HDR { if (frc->fr_family != AF_INET6) 1465 yyerror("only available with IPv6"); 1466 yysetdict(ipv6optwords); 1467 } 1468 ; 1469 1470 notwith: 1471 IPFY_NOT { nowith = 1; } 1472 | IPFY_NO { nowith = 1; } 1473 ; 1474 1475 opttype: 1476 IPFY_IPOPTS { $$ = FI_OPTIONS; } 1477 | IPFY_SHORT { $$ = FI_SHORT; } 1478 | IPFY_NAT { $$ = FI_NATED; } 1479 | IPFY_BAD { $$ = FI_BAD; } 1480 | IPFY_BADNAT { $$ = FI_BADNAT; } 1481 | IPFY_BADSRC { $$ = FI_BADSRC; } 1482 | IPFY_LOWTTL { $$ = FI_LOWTTL; } 1483 | IPFY_FRAG { $$ = FI_FRAG; } 1484 | IPFY_FRAGBODY { $$ = FI_FRAGBODY; } 1485 | IPFY_FRAGS { $$ = FI_FRAG; } 1486 | IPFY_MBCAST { $$ = FI_MBCAST; } 1487 | IPFY_MULTICAST { $$ = FI_MULTICAST; } 1488 | IPFY_BROADCAST { $$ = FI_BROADCAST; } 1489 | IPFY_STATE { $$ = FI_STATE; } 1490 | IPFY_OOW { $$ = FI_OOW; } 1491 | IPFY_AH { $$ = FI_AH; } 1492 | IPFY_V6HDRS { $$ = FI_V6EXTHDR; } 1493 ; 1494 1495 ipopts: optlist { DOALL(fr->fr_mip.fi_optmsk |= $1; 1496 if (fr->fr_family == AF_UNSPEC) { 1497 fr->fr_family = AF_INET; 1498 fr->fr_ip.fi_v = 4; 1499 fr->fr_mip.fi_v = 0xf; 1500 } else if (fr->fr_family != AF_INET) { 1501 YYERROR; 1502 } 1503 if (!nowith) 1504 fr->fr_ip.fi_optmsk |= $1;) 1505 } 1506 ; 1507 1508 optlist: 1509 opt { $$ |= $1; } 1510 | optlist ',' opt { $$ |= $1 | $3; } 1511 ; 1512 1513 ipv6hdrs: 1514 ipv6hdrlist { DOALL(fr->fr_mip.fi_optmsk |= $1; 1515 if (!nowith) 1516 fr->fr_ip.fi_optmsk |= $1;) 1517 } 1518 ; 1519 1520 ipv6hdrlist: 1521 ipv6hdr { $$ |= $1; } 1522 | ipv6hdrlist ',' ipv6hdr { $$ |= $1 | $3; } 1523 ; 1524 1525 secname: 1526 seclevel { $$ |= $1; } 1527 | secname ',' seclevel { $$ |= $1 | $3; } 1528 ; 1529 1530 seclevel: 1531 IPFY_SEC_UNC { $$ = secbit(IPSO_CLASS_UNCL); } 1532 | IPFY_SEC_CONF { $$ = secbit(IPSO_CLASS_CONF); } 1533 | IPFY_SEC_RSV1 { $$ = secbit(IPSO_CLASS_RES1); } 1534 | IPFY_SEC_RSV2 { $$ = secbit(IPSO_CLASS_RES2); } 1535 | IPFY_SEC_RSV3 { $$ = secbit(IPSO_CLASS_RES3); } 1536 | IPFY_SEC_RSV4 { $$ = secbit(IPSO_CLASS_RES4); } 1537 | IPFY_SEC_SEC { $$ = secbit(IPSO_CLASS_SECR); } 1538 | IPFY_SEC_TS { $$ = secbit(IPSO_CLASS_TOPS); } 1539 ; 1540 1541 icmptype: 1542 YY_NUMBER { $$ = $1; } 1543 | YY_STR { $$ = geticmptype(frc->fr_family, $1); 1544 if ($$ == -1) 1545 yyerror("unrecognised icmp type"); 1546 } 1547 ; 1548 1549 icmpcode: 1550 YY_NUMBER { $$ = $1; } 1551 | IPFY_ICMPC_NETUNR { $$ = ICMP_UNREACH_NET; } 1552 | IPFY_ICMPC_HSTUNR { $$ = ICMP_UNREACH_HOST; } 1553 | IPFY_ICMPC_PROUNR { $$ = ICMP_UNREACH_PROTOCOL; } 1554 | IPFY_ICMPC_PORUNR { $$ = ICMP_UNREACH_PORT; } 1555 | IPFY_ICMPC_NEEDF { $$ = ICMP_UNREACH_NEEDFRAG; } 1556 | IPFY_ICMPC_SRCFAIL { $$ = ICMP_UNREACH_SRCFAIL; } 1557 | IPFY_ICMPC_NETUNK { $$ = ICMP_UNREACH_NET_UNKNOWN; } 1558 | IPFY_ICMPC_HSTUNK { $$ = ICMP_UNREACH_HOST_UNKNOWN; } 1559 | IPFY_ICMPC_ISOLATE { $$ = ICMP_UNREACH_ISOLATED; } 1560 | IPFY_ICMPC_NETPRO { $$ = ICMP_UNREACH_NET_PROHIB; } 1561 | IPFY_ICMPC_HSTPRO { $$ = ICMP_UNREACH_HOST_PROHIB; } 1562 | IPFY_ICMPC_NETTOS { $$ = ICMP_UNREACH_TOSNET; } 1563 | IPFY_ICMPC_HSTTOS { $$ = ICMP_UNREACH_TOSHOST; } 1564 | IPFY_ICMPC_FLTPRO { $$ = ICMP_UNREACH_ADMIN_PROHIBIT; } 1565 | IPFY_ICMPC_HSTPRE { $$ = 14; } 1566 | IPFY_ICMPC_CUTPRE { $$ = 15; } 1567 ; 1568 1569 opt: 1570 IPFY_IPOPT_NOP { $$ = getoptbyvalue(IPOPT_NOP); } 1571 | IPFY_IPOPT_RR { $$ = getoptbyvalue(IPOPT_RR); } 1572 | IPFY_IPOPT_ZSU { $$ = getoptbyvalue(IPOPT_ZSU); } 1573 | IPFY_IPOPT_MTUP { $$ = getoptbyvalue(IPOPT_MTUP); } 1574 | IPFY_IPOPT_MTUR { $$ = getoptbyvalue(IPOPT_MTUR); } 1575 | IPFY_IPOPT_ENCODE { $$ = getoptbyvalue(IPOPT_ENCODE); } 1576 | IPFY_IPOPT_TS { $$ = getoptbyvalue(IPOPT_TS); } 1577 | IPFY_IPOPT_TR { $$ = getoptbyvalue(IPOPT_TR); } 1578 | IPFY_IPOPT_SEC { $$ = getoptbyvalue(IPOPT_SECURITY); } 1579 | IPFY_IPOPT_LSRR { $$ = getoptbyvalue(IPOPT_LSRR); } 1580 | IPFY_IPOPT_ESEC { $$ = getoptbyvalue(IPOPT_E_SEC); } 1581 | IPFY_IPOPT_CIPSO { $$ = getoptbyvalue(IPOPT_CIPSO); } 1582 | IPFY_IPOPT_CIPSO doi { $$ = getoptbyvalue(IPOPT_CIPSO); } 1583 | IPFY_IPOPT_SATID { $$ = getoptbyvalue(IPOPT_SATID); } 1584 | IPFY_IPOPT_SSRR { $$ = getoptbyvalue(IPOPT_SSRR); } 1585 | IPFY_IPOPT_ADDEXT { $$ = getoptbyvalue(IPOPT_ADDEXT); } 1586 | IPFY_IPOPT_VISA { $$ = getoptbyvalue(IPOPT_VISA); } 1587 | IPFY_IPOPT_IMITD { $$ = getoptbyvalue(IPOPT_IMITD); } 1588 | IPFY_IPOPT_EIP { $$ = getoptbyvalue(IPOPT_EIP); } 1589 | IPFY_IPOPT_FINN { $$ = getoptbyvalue(IPOPT_FINN); } 1590 | IPFY_IPOPT_DPS { $$ = getoptbyvalue(IPOPT_DPS); } 1591 | IPFY_IPOPT_SDB { $$ = getoptbyvalue(IPOPT_SDB); } 1592 | IPFY_IPOPT_NSAPA { $$ = getoptbyvalue(IPOPT_NSAPA); } 1593 | IPFY_IPOPT_RTRALRT { $$ = getoptbyvalue(IPOPT_RTRALRT); } 1594 | IPFY_IPOPT_UMP { $$ = getoptbyvalue(IPOPT_UMP); } 1595 | setsecclass secname 1596 { DOALL(fr->fr_mip.fi_secmsk |= $2; 1597 if (fr->fr_family == AF_UNSPEC) { 1598 fr->fr_family = AF_INET; 1599 fr->fr_ip.fi_v = 4; 1600 fr->fr_mip.fi_v = 0xf; 1601 } else if (fr->fr_family != AF_INET) { 1602 YYERROR; 1603 } 1604 if (!nowith) 1605 fr->fr_ip.fi_secmsk |= $2;) 1606 $$ = 0; 1607 yyresetdict(); 1608 } 1609 ; 1610 1611 setsecclass: 1612 IPFY_SECCLASS { yysetdict(ipv4secwords); } 1613 ; 1614 1615 doi: IPFY_DOI YY_NUMBER { DOALL(fr->fr_doimask = 0xffffffff; \ 1616 if (!nowith) \ 1617 fr->fr_doi = $2;) } 1618 | IPFY_DOI YY_HEX { DOALL(fr->fr_doimask = 0xffffffff; \ 1619 if (!nowith) \ 1620 fr->fr_doi = $2;) } 1621 ; 1622 1623 ipv6hdr: 1624 IPFY_AH { $$ = getv6optbyvalue(IPPROTO_AH); } 1625 | IPFY_IPV6OPT_DSTOPTS { $$ = getv6optbyvalue(IPPROTO_DSTOPTS); } 1626 | IPFY_IPV6OPT_ESP { $$ = getv6optbyvalue(IPPROTO_ESP); } 1627 | IPFY_IPV6OPT_HOPOPTS { $$ = getv6optbyvalue(IPPROTO_HOPOPTS); } 1628 | IPFY_IPV6OPT_IPV6 { $$ = getv6optbyvalue(IPPROTO_IPV6); } 1629 | IPFY_IPV6OPT_NONE { $$ = getv6optbyvalue(IPPROTO_NONE); } 1630 | IPFY_IPV6OPT_ROUTING { $$ = getv6optbyvalue(IPPROTO_ROUTING); } 1631 | IPFY_IPV6OPT_FRAG { $$ = getv6optbyvalue(IPPROTO_FRAGMENT); } 1632 | IPFY_IPV6OPT_MOBILITY { $$ = getv6optbyvalue(IPPROTO_MOBILITY); } 1633 ; 1634 1635 level: IPFY_LEVEL { setsyslog(); } 1636 ; 1637 1638 loglevel: 1639 priority { fr->fr_loglevel = LOG_LOCAL0|$1; } 1640 | facility '.' priority { fr->fr_loglevel = $1 | $3; } 1641 ; 1642 1643 facility: 1644 IPFY_FAC_KERN { $$ = LOG_KERN; } 1645 | IPFY_FAC_USER { $$ = LOG_USER; } 1646 | IPFY_FAC_MAIL { $$ = LOG_MAIL; } 1647 | IPFY_FAC_DAEMON { $$ = LOG_DAEMON; } 1648 | IPFY_FAC_AUTH { $$ = LOG_AUTH; } 1649 | IPFY_FAC_SYSLOG { $$ = LOG_SYSLOG; } 1650 | IPFY_FAC_LPR { $$ = LOG_LPR; } 1651 | IPFY_FAC_NEWS { $$ = LOG_NEWS; } 1652 | IPFY_FAC_UUCP { $$ = LOG_UUCP; } 1653 | IPFY_FAC_CRON { $$ = LOG_CRON; } 1654 | IPFY_FAC_FTP { $$ = LOG_FTP; } 1655 | IPFY_FAC_AUTHPRIV { $$ = LOG_AUTHPRIV; } 1656 | IPFY_FAC_AUDIT { $$ = LOG_AUDIT; } 1657 | IPFY_FAC_LFMT { $$ = LOG_LFMT; } 1658 | IPFY_FAC_LOCAL0 { $$ = LOG_LOCAL0; } 1659 | IPFY_FAC_LOCAL1 { $$ = LOG_LOCAL1; } 1660 | IPFY_FAC_LOCAL2 { $$ = LOG_LOCAL2; } 1661 | IPFY_FAC_LOCAL3 { $$ = LOG_LOCAL3; } 1662 | IPFY_FAC_LOCAL4 { $$ = LOG_LOCAL4; } 1663 | IPFY_FAC_LOCAL5 { $$ = LOG_LOCAL5; } 1664 | IPFY_FAC_LOCAL6 { $$ = LOG_LOCAL6; } 1665 | IPFY_FAC_LOCAL7 { $$ = LOG_LOCAL7; } 1666 | IPFY_FAC_SECURITY { $$ = LOG_SECURITY; } 1667 ; 1668 1669 priority: 1670 IPFY_PRI_EMERG { $$ = LOG_EMERG; } 1671 | IPFY_PRI_ALERT { $$ = LOG_ALERT; } 1672 | IPFY_PRI_CRIT { $$ = LOG_CRIT; } 1673 | IPFY_PRI_ERR { $$ = LOG_ERR; } 1674 | IPFY_PRI_WARN { $$ = LOG_WARNING; } 1675 | IPFY_PRI_NOTICE { $$ = LOG_NOTICE; } 1676 | IPFY_PRI_INFO { $$ = LOG_INFO; } 1677 | IPFY_PRI_DEBUG { $$ = LOG_DEBUG; } 1678 ; 1679 1680 compare: 1681 YY_CMP_EQ { $$ = FR_EQUAL; } 1682 | YY_CMP_NE { $$ = FR_NEQUAL; } 1683 | YY_CMP_LT { $$ = FR_LESST; } 1684 | YY_CMP_LE { $$ = FR_LESSTE; } 1685 | YY_CMP_GT { $$ = FR_GREATERT; } 1686 | YY_CMP_GE { $$ = FR_GREATERTE; } 1687 ; 1688 1689 range: YY_RANGE_IN { $$ = FR_INRANGE; } 1690 | YY_RANGE_OUT { $$ = FR_OUTRANGE; } 1691 | ':' { $$ = FR_INCRANGE; } 1692 ; 1693 1694 servicename: 1695 YY_STR { $$ = $1; } 1696 ; 1697 1698 interfacename: name { $$ = $1; } 1699 | name ':' YY_NUMBER 1700 { $$ = $1; 1701 fprintf(stderr, "%d: Logical interface %s:%d unsupported, " 1702 "use the physical interface %s instead.\n", 1703 yylineNum, $1, $3, $1); 1704 } 1705 ; 1706 1707 name: YY_STR { $$ = $1; } 1708 | '-' { $$ = strdup("-"); } 1709 ; 1710 1711 ipv4_16: 1712 YY_NUMBER '.' YY_NUMBER 1713 { if ($1 > 255 || $3 > 255) { 1714 yyerror("Invalid octet string for IP address"); 1715 return(0); 1716 } 1717 $$.s_addr = ($1 << 24) | ($3 << 16); 1718 $$.s_addr = htonl($$.s_addr); 1719 } 1720 ; 1721 1722 ipv4_24: 1723 ipv4_16 '.' YY_NUMBER 1724 { if ($3 > 255) { 1725 yyerror("Invalid octet string for IP address"); 1726 return(0); 1727 } 1728 $$.s_addr |= htonl($3 << 8); 1729 } 1730 ; 1731 1732 ipv4: ipv4_24 '.' YY_NUMBER 1733 { if ($3 > 255) { 1734 yyerror("Invalid octet string for IP address"); 1735 return(0); 1736 } 1737 $$.s_addr |= htonl($3); 1738 } 1739 | ipv4_24 1740 | ipv4_16 1741 ; 1742 1743 %% 1744 1745 1746 static struct wordtab ipfwords[] = { 1747 { "age", IPFY_AGE }, 1748 { "ah", IPFY_AH }, 1749 { "all", IPFY_ALL }, 1750 { "and", IPFY_AND }, 1751 { "auth", IPFY_AUTH }, 1752 { "bad", IPFY_BAD }, 1753 { "bad-nat", IPFY_BADNAT }, 1754 { "bad-src", IPFY_BADSRC }, 1755 { "bcast", IPFY_BROADCAST }, 1756 { "block", IPFY_BLOCK }, 1757 { "body", IPFY_BODY }, 1758 { "bpf-v4", IPFY_BPFV4 }, 1759 #ifdef USE_INET6 1760 { "bpf-v6", IPFY_BPFV6 }, 1761 #endif 1762 { "call", IPFY_CALL }, 1763 { "code", IPFY_ICMPCODE }, 1764 { "comment", IPFY_COMMENT }, 1765 { "count", IPFY_COUNT }, 1766 { "decapsulate", IPFY_DECAPS }, 1767 { "dstlist", IPFY_DSTLIST }, 1768 { "doi", IPFY_DOI }, 1769 { "dup-to", IPFY_DUPTO }, 1770 { "eq", YY_CMP_EQ }, 1771 { "esp", IPFY_ESP }, 1772 { "exp", IPFY_IPFEXPR }, 1773 { "family", IPFY_FAMILY }, 1774 { "fastroute", IPFY_FROUTE }, 1775 { "first", IPFY_FIRST }, 1776 { "flags", IPFY_FLAGS }, 1777 { "frag", IPFY_FRAG }, 1778 { "frag-body", IPFY_FRAGBODY }, 1779 { "frags", IPFY_FRAGS }, 1780 { "from", IPFY_FROM }, 1781 { "ge", YY_CMP_GE }, 1782 { "group", IPFY_GROUP }, 1783 { "gt", YY_CMP_GT }, 1784 { "head", IPFY_HEAD }, 1785 { "icmp", IPFY_ICMP }, 1786 { "icmp-head", IPFY_ICMPHEAD }, 1787 { "icmp-type", IPFY_ICMPTYPE }, 1788 { "in", IPFY_IN }, 1789 { "in-via", IPFY_INVIA }, 1790 { "inet", IPFY_INET }, 1791 { "inet6", IPFY_INET6 }, 1792 { "ipopt", IPFY_IPOPTS }, 1793 { "ipopts", IPFY_IPOPTS }, 1794 { "keep", IPFY_KEEP }, 1795 { "l5-as", IPFY_L5AS }, 1796 { "le", YY_CMP_LE }, 1797 { "level", IPFY_LEVEL }, 1798 { "limit", IPFY_LIMIT }, 1799 { "log", IPFY_LOG }, 1800 { "loose", IPFY_LOOSE }, 1801 { "lowttl", IPFY_LOWTTL }, 1802 { "lt", YY_CMP_LT }, 1803 { "mask", IPFY_MASK }, 1804 { "match-tag", IPFY_MATCHTAG }, 1805 { "max-per-src", IPFY_MAX_PER_SRC }, 1806 { "max-srcs", IPFY_MAX_SRCS }, 1807 { "mbcast", IPFY_MBCAST }, 1808 { "mcast", IPFY_MULTICAST }, 1809 { "multicast", IPFY_MULTICAST }, 1810 { "nat", IPFY_NAT }, 1811 { "ne", YY_CMP_NE }, 1812 { "net", IPFY_NETWORK }, 1813 { "newisn", IPFY_NEWISN }, 1814 { "no", IPFY_NO }, 1815 { "no-icmp-err", IPFY_NOICMPERR }, 1816 { "nolog", IPFY_NOLOG }, 1817 { "nomatch", IPFY_NOMATCH }, 1818 { "now", IPFY_NOW }, 1819 { "not", IPFY_NOT }, 1820 { "oow", IPFY_OOW }, 1821 { "on", IPFY_ON }, 1822 { "opt", IPFY_OPT }, 1823 { "or-block", IPFY_ORBLOCK }, 1824 { "out", IPFY_OUT }, 1825 { "out-via", IPFY_OUTVIA }, 1826 { "pass", IPFY_PASS }, 1827 { "port", IPFY_PORT }, 1828 { "pps", IPFY_PPS }, 1829 { "preauth", IPFY_PREAUTH }, 1830 { "proto", IPFY_PROTO }, 1831 { "quick", IPFY_QUICK }, 1832 { "reply-to", IPFY_REPLY_TO }, 1833 { "return-icmp", IPFY_RETICMP }, 1834 { "return-icmp-as-dest", IPFY_RETICMPASDST }, 1835 { "return-rst", IPFY_RETRST }, 1836 { "route-to", IPFY_ROUTETO }, 1837 { "rule-ttl", IPFY_RULETTL }, 1838 { "rpc", IPFY_RPC }, 1839 { "sec-class", IPFY_SECCLASS }, 1840 { "set", IPFY_SET }, 1841 { "set-tag", IPFY_SETTAG }, 1842 { "skip", IPFY_SKIP }, 1843 { "short", IPFY_SHORT }, 1844 { "state", IPFY_STATE }, 1845 { "state-age", IPFY_AGE }, 1846 { "strict", IPFY_STRICT }, 1847 { "sync", IPFY_SYNC }, 1848 { "tcp", IPFY_TCP }, 1849 { "tcp-udp", IPFY_TCPUDP }, 1850 { "tos", IPFY_TOS }, 1851 { "to", IPFY_TO }, 1852 { "ttl", IPFY_TTL }, 1853 { "udp", IPFY_UDP }, 1854 { "v6hdr", IPFY_V6HDR }, 1855 { "v6hdrs", IPFY_V6HDRS }, 1856 { "with", IPFY_WITH }, 1857 { NULL, 0 } 1858 }; 1859 1860 static struct wordtab addrwords[] = { 1861 { "any", IPFY_ANY }, 1862 { "hash", IPFY_HASH }, 1863 { "pool", IPFY_POOL }, 1864 { NULL, 0 } 1865 }; 1866 1867 static struct wordtab maskwords[] = { 1868 { "broadcast", IPFY_BROADCAST }, 1869 { "netmasked", IPFY_NETMASKED }, 1870 { "network", IPFY_NETWORK }, 1871 { "peer", IPFY_PEER }, 1872 { NULL, 0 } 1873 }; 1874 1875 static struct wordtab icmpcodewords[] = { 1876 { "cutoff-preced", IPFY_ICMPC_CUTPRE }, 1877 { "filter-prohib", IPFY_ICMPC_FLTPRO }, 1878 { "isolate", IPFY_ICMPC_ISOLATE }, 1879 { "needfrag", IPFY_ICMPC_NEEDF }, 1880 { "net-prohib", IPFY_ICMPC_NETPRO }, 1881 { "net-tos", IPFY_ICMPC_NETTOS }, 1882 { "host-preced", IPFY_ICMPC_HSTPRE }, 1883 { "host-prohib", IPFY_ICMPC_HSTPRO }, 1884 { "host-tos", IPFY_ICMPC_HSTTOS }, 1885 { "host-unk", IPFY_ICMPC_HSTUNK }, 1886 { "host-unr", IPFY_ICMPC_HSTUNR }, 1887 { "net-unk", IPFY_ICMPC_NETUNK }, 1888 { "net-unr", IPFY_ICMPC_NETUNR }, 1889 { "port-unr", IPFY_ICMPC_PORUNR }, 1890 { "proto-unr", IPFY_ICMPC_PROUNR }, 1891 { "srcfail", IPFY_ICMPC_SRCFAIL }, 1892 { NULL, 0 }, 1893 }; 1894 1895 static struct wordtab ipv4optwords[] = { 1896 { "addext", IPFY_IPOPT_ADDEXT }, 1897 { "cipso", IPFY_IPOPT_CIPSO }, 1898 { "dps", IPFY_IPOPT_DPS }, 1899 { "e-sec", IPFY_IPOPT_ESEC }, 1900 { "eip", IPFY_IPOPT_EIP }, 1901 { "encode", IPFY_IPOPT_ENCODE }, 1902 { "finn", IPFY_IPOPT_FINN }, 1903 { "imitd", IPFY_IPOPT_IMITD }, 1904 { "lsrr", IPFY_IPOPT_LSRR }, 1905 { "mtup", IPFY_IPOPT_MTUP }, 1906 { "mtur", IPFY_IPOPT_MTUR }, 1907 { "nop", IPFY_IPOPT_NOP }, 1908 { "nsapa", IPFY_IPOPT_NSAPA }, 1909 { "rr", IPFY_IPOPT_RR }, 1910 { "rtralrt", IPFY_IPOPT_RTRALRT }, 1911 { "satid", IPFY_IPOPT_SATID }, 1912 { "sdb", IPFY_IPOPT_SDB }, 1913 { "sec", IPFY_IPOPT_SEC }, 1914 { "ssrr", IPFY_IPOPT_SSRR }, 1915 { "tr", IPFY_IPOPT_TR }, 1916 { "ts", IPFY_IPOPT_TS }, 1917 { "ump", IPFY_IPOPT_UMP }, 1918 { "visa", IPFY_IPOPT_VISA }, 1919 { "zsu", IPFY_IPOPT_ZSU }, 1920 { NULL, 0 }, 1921 }; 1922 1923 static struct wordtab ipv4secwords[] = { 1924 { "confid", IPFY_SEC_CONF }, 1925 { "reserv-1", IPFY_SEC_RSV1 }, 1926 { "reserv-2", IPFY_SEC_RSV2 }, 1927 { "reserv-3", IPFY_SEC_RSV3 }, 1928 { "reserv-4", IPFY_SEC_RSV4 }, 1929 { "secret", IPFY_SEC_SEC }, 1930 { "topsecret", IPFY_SEC_TS }, 1931 { "unclass", IPFY_SEC_UNC }, 1932 { NULL, 0 }, 1933 }; 1934 1935 static struct wordtab ipv6optwords[] = { 1936 { "dstopts", IPFY_IPV6OPT_DSTOPTS }, 1937 { "esp", IPFY_IPV6OPT_ESP }, 1938 { "frag", IPFY_IPV6OPT_FRAG }, 1939 { "hopopts", IPFY_IPV6OPT_HOPOPTS }, 1940 { "ipv6", IPFY_IPV6OPT_IPV6 }, 1941 { "mobility", IPFY_IPV6OPT_MOBILITY }, 1942 { "none", IPFY_IPV6OPT_NONE }, 1943 { "routing", IPFY_IPV6OPT_ROUTING }, 1944 { NULL, 0 }, 1945 }; 1946 1947 static struct wordtab logwords[] = { 1948 { "kern", IPFY_FAC_KERN }, 1949 { "user", IPFY_FAC_USER }, 1950 { "mail", IPFY_FAC_MAIL }, 1951 { "daemon", IPFY_FAC_DAEMON }, 1952 { "auth", IPFY_FAC_AUTH }, 1953 { "syslog", IPFY_FAC_SYSLOG }, 1954 { "lpr", IPFY_FAC_LPR }, 1955 { "news", IPFY_FAC_NEWS }, 1956 { "uucp", IPFY_FAC_UUCP }, 1957 { "cron", IPFY_FAC_CRON }, 1958 { "ftp", IPFY_FAC_FTP }, 1959 { "authpriv", IPFY_FAC_AUTHPRIV }, 1960 { "audit", IPFY_FAC_AUDIT }, 1961 { "logalert", IPFY_FAC_LFMT }, 1962 { "console", IPFY_FAC_CONSOLE }, 1963 { "security", IPFY_FAC_SECURITY }, 1964 { "local0", IPFY_FAC_LOCAL0 }, 1965 { "local1", IPFY_FAC_LOCAL1 }, 1966 { "local2", IPFY_FAC_LOCAL2 }, 1967 { "local3", IPFY_FAC_LOCAL3 }, 1968 { "local4", IPFY_FAC_LOCAL4 }, 1969 { "local5", IPFY_FAC_LOCAL5 }, 1970 { "local6", IPFY_FAC_LOCAL6 }, 1971 { "local7", IPFY_FAC_LOCAL7 }, 1972 { "emerg", IPFY_PRI_EMERG }, 1973 { "alert", IPFY_PRI_ALERT }, 1974 { "crit", IPFY_PRI_CRIT }, 1975 { "err", IPFY_PRI_ERR }, 1976 { "warn", IPFY_PRI_WARN }, 1977 { "notice", IPFY_PRI_NOTICE }, 1978 { "info", IPFY_PRI_INFO }, 1979 { "debug", IPFY_PRI_DEBUG }, 1980 { NULL, 0 }, 1981 }; 1982 1983 1984 1985 1986 int 1987 ipf_parsefile(int fd, addfunc_t addfunc, ioctlfunc_t *iocfuncs, char *filename) 1988 { 1989 FILE *fp = NULL; 1990 char *s; 1991 1992 yylineNum = 1; 1993 yysettab(ipfwords); 1994 1995 s = getenv("YYDEBUG"); 1996 if (s != NULL) 1997 yydebug = atoi(s); 1998 else 1999 yydebug = 0; 2000 2001 if (strcmp(filename, "-")) { 2002 fp = fopen(filename, "r"); 2003 if (fp == NULL) { 2004 fprintf(stderr, "fopen(%s) failed: %s\n", filename, 2005 STRERROR(errno)); 2006 return(-1); 2007 } 2008 } else 2009 fp = stdin; 2010 2011 while (ipf_parsesome(fd, addfunc, iocfuncs, fp) == 1) 2012 ; 2013 if (fp != NULL) 2014 fclose(fp); 2015 return(0); 2016 } 2017 2018 2019 int 2020 ipf_parsesome(int fd, addfunc_t addfunc, ioctlfunc_t *iocfuncs, FILE *fp) 2021 { 2022 char *s; 2023 int i; 2024 2025 ipffd = fd; 2026 for (i = 0; i <= IPL_LOGMAX; i++) 2027 ipfioctls[i] = iocfuncs[i]; 2028 ipfaddfunc = addfunc; 2029 2030 if (feof(fp)) 2031 return(0); 2032 i = fgetc(fp); 2033 if (i == EOF) 2034 return(0); 2035 if (ungetc(i, fp) == 0) 2036 return(0); 2037 if (feof(fp)) 2038 return(0); 2039 s = getenv("YYDEBUG"); 2040 if (s != NULL) 2041 yydebug = atoi(s); 2042 else 2043 yydebug = 0; 2044 2045 yyin = fp; 2046 yyparse(); 2047 return(1); 2048 } 2049 2050 2051 static void 2052 newrule(void) 2053 { 2054 frentry_t *frn; 2055 2056 frn = allocfr(); 2057 for (fr = frtop; fr != NULL && fr->fr_next != NULL; fr = fr->fr_next) 2058 ; 2059 if (fr != NULL) { 2060 fr->fr_next = frn; 2061 frn->fr_pnext = &fr->fr_next; 2062 } 2063 if (frtop == NULL) { 2064 frtop = frn; 2065 frn->fr_pnext = &frtop; 2066 } 2067 fr = frn; 2068 frc = frn; 2069 fr->fr_loglevel = 0xffff; 2070 fr->fr_isc = (void *)-1; 2071 fr->fr_logtag = FR_NOLOGTAG; 2072 fr->fr_type = FR_T_NONE; 2073 fr->fr_flineno = yylineNum; 2074 2075 if (use_inet6 == 1) 2076 fr->fr_family = AF_INET6; 2077 else if (use_inet6 == -1) 2078 fr->fr_family = AF_INET; 2079 2080 nrules = 1; 2081 } 2082 2083 2084 static void 2085 setipftype(void) 2086 { 2087 for (fr = frc; fr != NULL; fr = fr->fr_next) { 2088 if (fr->fr_type == FR_T_NONE) { 2089 fr->fr_type = FR_T_IPF; 2090 fr->fr_data = (void *)calloc(sizeof(fripf_t), 1); 2091 fr->fr_dsize = sizeof(fripf_t); 2092 fr->fr_family = frc->fr_family; 2093 if (fr->fr_family == AF_INET) { 2094 fr->fr_ip.fi_v = 4; 2095 } 2096 else if (fr->fr_family == AF_INET6) { 2097 fr->fr_ip.fi_v = 6; 2098 } 2099 fr->fr_mip.fi_v = 0xf; 2100 fr->fr_ipf->fri_sifpidx = -1; 2101 fr->fr_ipf->fri_difpidx = -1; 2102 } 2103 if (fr->fr_type != FR_T_IPF) { 2104 fprintf(stderr, "IPF Type not set\n"); 2105 } 2106 } 2107 } 2108 2109 2110 static frentry_t * 2111 addrule(void) 2112 { 2113 frentry_t *f, *f1, *f2; 2114 int count; 2115 2116 for (f2 = frc; f2->fr_next != NULL; f2 = f2->fr_next) 2117 ; 2118 2119 count = nrules; 2120 f = f2; 2121 for (f1 = frc; count > 0; count--, f1 = f1->fr_next) { 2122 f->fr_next = allocfr(); 2123 if (f->fr_next == NULL) 2124 return(NULL); 2125 f->fr_next->fr_pnext = &f->fr_next; 2126 added++; 2127 f = f->fr_next; 2128 *f = *f1; 2129 f->fr_next = NULL; 2130 if (f->fr_caddr != NULL) { 2131 f->fr_caddr = malloc(f->fr_dsize); 2132 bcopy(f1->fr_caddr, f->fr_caddr, f->fr_dsize); 2133 } 2134 } 2135 2136 return(f2->fr_next); 2137 } 2138 2139 2140 static int 2141 lookuphost(char *name, i6addr_t *addrp) 2142 { 2143 int i; 2144 2145 hashed = 0; 2146 pooled = 0; 2147 dynamic = -1; 2148 2149 for (i = 0; i < 4; i++) { 2150 if (fr->fr_ifnames[i] == -1) 2151 continue; 2152 if (strcmp(name, fr->fr_names + fr->fr_ifnames[i]) == 0) { 2153 ifpflag = FRI_DYNAMIC; 2154 dynamic = addname(&fr, name); 2155 return(1); 2156 } 2157 } 2158 2159 if (gethost(AF_INET, name, addrp) == -1) { 2160 fprintf(stderr, "unknown name \"%s\"\n", name); 2161 return(-1); 2162 } 2163 return(0); 2164 } 2165 2166 2167 static void 2168 dobpf(int v, char *phrase) 2169 { 2170 #ifdef IPFILTER_BPF 2171 struct bpf_program bpf; 2172 struct pcap *p; 2173 #endif 2174 fakebpf_t *fb; 2175 u_32_t l; 2176 char *s; 2177 int i; 2178 2179 for (fr = frc; fr != NULL; fr = fr->fr_next) { 2180 if (fr->fr_type != FR_T_NONE) { 2181 fprintf(stderr, "cannot mix IPF and BPF matching\n"); 2182 return; 2183 } 2184 fr->fr_family = vtof(v); 2185 fr->fr_type = FR_T_BPFOPC; 2186 2187 if (!strncmp(phrase, "0x", 2)) { 2188 fb = malloc(sizeof(fakebpf_t)); 2189 2190 for (i = 0, s = strtok(phrase, " \r\n\t"); s != NULL; 2191 s = strtok(NULL, " \r\n\t"), i++) { 2192 fb = reallocarray(fb, i / 4 + 1, sizeof(*fb)); 2193 if (fb == NULL) { 2194 warnx("memory allocation error at %d in %s in %s", __LINE__, __FUNCTION__, __FILE__); 2195 abort(); 2196 } 2197 l = (u_32_t)strtol(s, NULL, 0); 2198 switch (i & 3) 2199 { 2200 case 0 : 2201 fb[i / 4].fb_c = l & 0xffff; 2202 break; 2203 case 1 : 2204 fb[i / 4].fb_t = l & 0xff; 2205 break; 2206 case 2 : 2207 fb[i / 4].fb_f = l & 0xff; 2208 break; 2209 case 3 : 2210 fb[i / 4].fb_k = l; 2211 break; 2212 } 2213 } 2214 if ((i & 3) != 0) { 2215 fprintf(stderr, 2216 "Odd number of bytes in BPF code\n"); 2217 exit(1); 2218 } 2219 i--; 2220 fr->fr_dsize = (i / 4 + 1) * sizeof(*fb); 2221 fr->fr_data = fb; 2222 return; 2223 } 2224 2225 #ifdef IPFILTER_BPF 2226 bzero((char *)&bpf, sizeof(bpf)); 2227 p = pcap_open_dead(DLT_RAW, 1); 2228 if (!p) { 2229 fprintf(stderr, "pcap_open_dead failed\n"); 2230 return; 2231 } 2232 2233 if (pcap_compile(p, &bpf, phrase, 1, 0xffffffff)) { 2234 pcap_perror(p, "ipf"); 2235 pcap_close(p); 2236 fprintf(stderr, "pcap parsing failed (%s)\n", phrase); 2237 return; 2238 } 2239 pcap_close(p); 2240 2241 fr->fr_dsize = bpf.bf_len * sizeof(struct bpf_insn); 2242 fr->fr_data = malloc(fr->fr_dsize); 2243 bcopy((char *)bpf.bf_insns, fr->fr_data, fr->fr_dsize); 2244 if (!bpf_validate(fr->fr_data, bpf.bf_len)) { 2245 fprintf(stderr, "BPF validation failed\n"); 2246 return; 2247 } 2248 #endif 2249 } 2250 2251 #ifdef IPFILTER_BPF 2252 if (opts & OPT_DEBUG) 2253 bpf_dump(&bpf, 0); 2254 #else 2255 fprintf(stderr, "BPF filter expressions not supported\n"); 2256 exit(1); 2257 #endif 2258 } 2259 2260 2261 static void 2262 resetaddr(void) 2263 { 2264 hashed = 0; 2265 pooled = 0; 2266 dynamic = -1; 2267 } 2268 2269 2270 static alist_t * 2271 newalist(alist_t *ptr) 2272 { 2273 alist_t *al; 2274 2275 al = malloc(sizeof(*al)); 2276 if (al == NULL) 2277 return(NULL); 2278 al->al_not = 0; 2279 al->al_next = ptr; 2280 return(al); 2281 } 2282 2283 2284 static int 2285 makepool(alist_t *list) 2286 { 2287 ip_pool_node_t *n, *top; 2288 ip_pool_t pool; 2289 alist_t *a; 2290 int num; 2291 2292 if (list == NULL) 2293 return(0); 2294 top = calloc(1, sizeof(*top)); 2295 if (top == NULL) 2296 return(0); 2297 2298 for (n = top, a = list; (n != NULL) && (a != NULL); a = a->al_next) { 2299 if (use_inet6 == 1) { 2300 #ifdef USE_INET6 2301 n->ipn_addr.adf_family = AF_INET6; 2302 n->ipn_addr.adf_addr = a->al_i6addr; 2303 n->ipn_addr.adf_len = offsetof(addrfamily_t, 2304 adf_addr) + 16; 2305 n->ipn_mask.adf_family = AF_INET6; 2306 n->ipn_mask.adf_addr = a->al_i6mask; 2307 n->ipn_mask.adf_len = offsetof(addrfamily_t, 2308 adf_addr) + 16; 2309 2310 #endif 2311 } else { 2312 n->ipn_addr.adf_family = AF_INET; 2313 n->ipn_addr.adf_addr.in4.s_addr = a->al_1; 2314 n->ipn_addr.adf_len = offsetof(addrfamily_t, 2315 adf_addr) + 4; 2316 n->ipn_mask.adf_family = AF_INET; 2317 n->ipn_mask.adf_addr.in4.s_addr = a->al_2; 2318 n->ipn_mask.adf_len = offsetof(addrfamily_t, 2319 adf_addr) + 4; 2320 } 2321 n->ipn_info = a->al_not; 2322 if (a->al_next != NULL) { 2323 n->ipn_next = calloc(1, sizeof(*n)); 2324 n = n->ipn_next; 2325 } 2326 } 2327 2328 bzero((char *)&pool, sizeof(pool)); 2329 pool.ipo_unit = IPL_LOGIPF; 2330 pool.ipo_list = top; 2331 num = load_pool(&pool, ipfioctls[IPL_LOGLOOKUP]); 2332 2333 while ((n = top) != NULL) { 2334 top = n->ipn_next; 2335 free(n); 2336 } 2337 return(num); 2338 } 2339 2340 2341 static u_int 2342 makehash(alist_t *list) 2343 { 2344 iphtent_t *n, *top; 2345 iphtable_t iph; 2346 alist_t *a; 2347 int num; 2348 2349 if (list == NULL) 2350 return(0); 2351 top = calloc(1, sizeof(*top)); 2352 if (top == NULL) 2353 return(0); 2354 2355 for (n = top, a = list; (n != NULL) && (a != NULL); a = a->al_next) { 2356 if (a->al_family == AF_INET6) { 2357 n->ipe_family = AF_INET6; 2358 n->ipe_addr = a->al_i6addr; 2359 n->ipe_mask = a->al_i6mask; 2360 } else { 2361 n->ipe_family = AF_INET; 2362 n->ipe_addr.in4_addr = a->al_1; 2363 n->ipe_mask.in4_addr = a->al_2; 2364 } 2365 n->ipe_value = 0; 2366 if (a->al_next != NULL) { 2367 n->ipe_next = calloc(1, sizeof(*n)); 2368 n = n->ipe_next; 2369 } 2370 } 2371 2372 bzero((char *)&iph, sizeof(iph)); 2373 iph.iph_unit = IPL_LOGIPF; 2374 iph.iph_type = IPHASH_LOOKUP; 2375 *iph.iph_name = '\0'; 2376 2377 if (load_hash(&iph, top, ipfioctls[IPL_LOGLOOKUP]) == 0) 2378 sscanf(iph.iph_name, "%u", &num); 2379 else 2380 num = 0; 2381 2382 while ((n = top) != NULL) { 2383 top = n->ipe_next; 2384 free(n); 2385 } 2386 return(num); 2387 } 2388 2389 2390 int 2391 ipf_addrule(int fd, ioctlfunc_t ioctlfunc, void *ptr) 2392 { 2393 ioctlcmd_t add, del; 2394 frentry_t *fr; 2395 ipfobj_t obj; 2396 2397 if (ptr == NULL) 2398 return(0); 2399 2400 fr = ptr; 2401 add = 0; 2402 del = 0; 2403 2404 bzero((char *)&obj, sizeof(obj)); 2405 obj.ipfo_rev = IPFILTER_VERSION; 2406 obj.ipfo_size = fr->fr_size; 2407 obj.ipfo_type = IPFOBJ_FRENTRY; 2408 obj.ipfo_ptr = ptr; 2409 2410 if ((opts & OPT_DONOTHING) != 0) 2411 fd = -1; 2412 2413 if (opts & OPT_ZERORULEST) { 2414 add = SIOCZRLST; 2415 } else if (opts & OPT_INACTIVE) { 2416 add = (u_int)fr->fr_hits ? SIOCINIFR : 2417 SIOCADIFR; 2418 del = SIOCRMIFR; 2419 } else { 2420 add = (u_int)fr->fr_hits ? SIOCINAFR : 2421 SIOCADAFR; 2422 del = SIOCRMAFR; 2423 } 2424 2425 if ((opts & OPT_OUTQUE) != 0) 2426 fr->fr_flags |= FR_OUTQUE; 2427 if (fr->fr_hits) 2428 fr->fr_hits--; 2429 if ((opts & OPT_VERBOSE) != 0) 2430 printfr(fr, ioctlfunc); 2431 2432 if ((opts & OPT_DEBUG) != 0) { 2433 binprint(fr, sizeof(*fr)); 2434 if (fr->fr_data != NULL) 2435 binprint(fr->fr_data, fr->fr_dsize); 2436 } 2437 2438 if ((opts & OPT_ZERORULEST) != 0) { 2439 if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) { 2440 if ((opts & OPT_DONOTHING) == 0) { 2441 char msg[80]; 2442 2443 snprintf(msg, sizeof(msg), "%d:ioctl(zero rule)", 2444 fr->fr_flineno); 2445 return(ipf_perror_fd(fd, ioctlfunc, msg)); 2446 } 2447 } else { 2448 #ifdef USE_QUAD_T 2449 printf("hits %qd bytes %qd ", 2450 (long long)fr->fr_hits, 2451 (long long)fr->fr_bytes); 2452 #else 2453 printf("hits %ld bytes %ld ", 2454 fr->fr_hits, fr->fr_bytes); 2455 #endif 2456 printfr(fr, ioctlfunc); 2457 } 2458 } else if ((opts & OPT_REMOVE) != 0) { 2459 if ((*ioctlfunc)(fd, del, (void *)&obj) == -1) { 2460 if ((opts & OPT_DONOTHING) == 0) { 2461 char msg[80]; 2462 2463 snprintf(msg, sizeof(msg), "%d:ioctl(delete rule)", 2464 fr->fr_flineno); 2465 return(ipf_perror_fd(fd, ioctlfunc, msg)); 2466 } 2467 } 2468 } else { 2469 if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) { 2470 if ((opts & OPT_DONOTHING) == 0) { 2471 char msg[80]; 2472 2473 snprintf(msg, sizeof(msg), "%d:ioctl(add/insert rule)", 2474 fr->fr_flineno); 2475 return(ipf_perror_fd(fd, ioctlfunc, msg)); 2476 } 2477 } 2478 } 2479 return(0); 2480 } 2481 2482 static void 2483 setsyslog(void) 2484 { 2485 yysetdict(logwords); 2486 yybreakondot = 1; 2487 } 2488 2489 2490 static void 2491 unsetsyslog(void) 2492 { 2493 yyresetdict(); 2494 yybreakondot = 0; 2495 } 2496 2497 2498 static void 2499 fillgroup(frentry_t *fr) 2500 { 2501 frentry_t *f; 2502 2503 for (f = frold; f != NULL; f = f->fr_next) { 2504 if (f->fr_grhead == -1 && fr->fr_group == -1) 2505 break; 2506 if (f->fr_grhead == -1 || fr->fr_group == -1) 2507 continue; 2508 if (strcmp(f->fr_names + f->fr_grhead, 2509 fr->fr_names + fr->fr_group) == 0) 2510 break; 2511 } 2512 2513 if (f == NULL) 2514 return; 2515 2516 /* 2517 * Only copy down matching fields if the rules are of the same type 2518 * and are of ipf type. The only fields that are copied are those 2519 * that impact the rule parsing itself, eg. need for knowing what the 2520 * protocol should be for rules with port comparisons in them. 2521 */ 2522 if (f->fr_type != fr->fr_type || f->fr_type != FR_T_IPF) 2523 return; 2524 2525 if (fr->fr_family == 0 && f->fr_family != 0) 2526 fr->fr_family = f->fr_family; 2527 2528 if (fr->fr_mproto == 0 && f->fr_mproto != 0) 2529 fr->fr_mproto = f->fr_mproto; 2530 if (fr->fr_proto == 0 && f->fr_proto != 0) 2531 fr->fr_proto = f->fr_proto; 2532 2533 if ((fr->fr_mproto == 0) && ((fr->fr_flx & FI_TCPUDP) == 0) && 2534 ((f->fr_flx & FI_TCPUDP) != 0)) { 2535 fr->fr_flx |= FI_TCPUDP; 2536 fr->fr_mflx |= FI_TCPUDP; 2537 } 2538 } 2539 2540 2541 static void 2542 doipfexpr(char *line) 2543 { 2544 int *array; 2545 char *error; 2546 2547 array = parseipfexpr(line, &error); 2548 if (array == NULL) { 2549 fprintf(stderr, "%s:", error); 2550 yyerror("error parsing ipf matching expression"); 2551 return; 2552 } 2553 2554 fr->fr_type = FR_T_IPFEXPR; 2555 fr->fr_data = array; 2556 fr->fr_dsize = array[0] * sizeof(*array); 2557 } 2558 2559 2560 static void 2561 do_tuneint(char *varname, int value) 2562 { 2563 char buffer[80]; 2564 2565 strncpy(buffer, varname, 60); 2566 buffer[59] = '\0'; 2567 strcat(buffer, "="); 2568 snprintf(buffer, sizeof(buffer), "%u", value); 2569 ipf_dotuning(ipffd, buffer, ioctl); 2570 } 2571 2572 2573 static void 2574 do_tunestr(char *varname, char *value) 2575 { 2576 2577 if (!strcasecmp(value, "true")) { 2578 do_tuneint(varname, 1); 2579 } else if (!strcasecmp(value, "false")) { 2580 do_tuneint(varname, 0); 2581 } else { 2582 yyerror("did not find true/false where expected"); 2583 } 2584 } 2585 2586 2587 static void 2588 setifname(frentry_t **frp, int idx, char *name) 2589 { 2590 int pos; 2591 2592 pos = addname(frp, name); 2593 if (pos == -1) 2594 return; 2595 (*frp)->fr_ifnames[idx] = pos; 2596 } 2597 2598 2599 static int 2600 addname(frentry_t **frp, char *name) 2601 { 2602 frentry_t *f; 2603 int nlen; 2604 int pos; 2605 2606 nlen = strlen(name) + 1; 2607 f = realloc(*frp, (*frp)->fr_size + nlen); 2608 if (*frp == frc) 2609 frc = f; 2610 *frp = f; 2611 if (f == NULL) 2612 return(-1); 2613 if (f->fr_pnext != NULL) 2614 *f->fr_pnext = f; 2615 f->fr_size += nlen; 2616 pos = f->fr_namelen; 2617 f->fr_namelen += nlen; 2618 strcpy(f->fr_names + pos, name); 2619 f->fr_names[f->fr_namelen] = '\0'; 2620 return(pos); 2621 } 2622 2623 2624 static frentry_t * 2625 allocfr(void) 2626 { 2627 frentry_t *fr; 2628 2629 fr = calloc(1, sizeof(*fr)); 2630 if (fr != NULL) { 2631 fr->fr_size = sizeof(*fr); 2632 fr->fr_comment = -1; 2633 fr->fr_group = -1; 2634 fr->fr_grhead = -1; 2635 fr->fr_icmphead = -1; 2636 fr->fr_ifnames[0] = -1; 2637 fr->fr_ifnames[1] = -1; 2638 fr->fr_ifnames[2] = -1; 2639 fr->fr_ifnames[3] = -1; 2640 fr->fr_tif.fd_name = -1; 2641 fr->fr_rif.fd_name = -1; 2642 fr->fr_dif.fd_name = -1; 2643 } 2644 return(fr); 2645 } 2646 2647 2648 static void 2649 setgroup(frentry_t **frp, char *name) 2650 { 2651 int pos; 2652 2653 pos = addname(frp, name); 2654 if (pos == -1) 2655 return; 2656 (*frp)->fr_group = pos; 2657 } 2658 2659 2660 static void 2661 setgrhead(frentry_t **frp, char *name) 2662 { 2663 int pos; 2664 2665 pos = addname(frp, name); 2666 if (pos == -1) 2667 return; 2668 (*frp)->fr_grhead = pos; 2669 } 2670 2671 2672 static void 2673 seticmphead(frentry_t **frp, char *name) 2674 { 2675 int pos; 2676 2677 pos = addname(frp, name); 2678 if (pos == -1) 2679 return; 2680 (*frp)->fr_icmphead = pos; 2681 } 2682 2683 2684 static void 2685 build_dstaddr_af(frentry_t *fp, void *ptr) 2686 { 2687 struct ipp_s *ipp = ptr; 2688 frentry_t *f = fp; 2689 2690 if (f->fr_family != AF_UNSPEC && ipp->f == AF_UNSPEC) { 2691 ipp->f = f->fr_family; 2692 ipp->v = f->fr_ip.fi_v; 2693 } 2694 if (ipp->f == AF_INET) 2695 ipp->v = 4; 2696 else if (ipp->f == AF_INET6) 2697 ipp->v = 6; 2698 2699 for (; f != NULL; f = f->fr_next) { 2700 f->fr_ip.fi_dst = ipp->a; 2701 f->fr_mip.fi_dst = ipp->m; 2702 f->fr_family = ipp->f; 2703 f->fr_ip.fi_v = ipp->v; 2704 f->fr_mip.fi_v = 0xf; 2705 f->fr_datype = ipp->type; 2706 if (ipp->ifpos != -1) 2707 f->fr_ipf->fri_difpidx = ipp->ifpos; 2708 } 2709 fr = NULL; 2710 } 2711 2712 2713 static void 2714 build_srcaddr_af(frentry_t *fp, void *ptr) 2715 { 2716 struct ipp_s *ipp = ptr; 2717 frentry_t *f = fp; 2718 2719 if (f->fr_family != AF_UNSPEC && ipp->f == AF_UNSPEC) { 2720 ipp->f = f->fr_family; 2721 ipp->v = f->fr_ip.fi_v; 2722 } 2723 if (ipp->f == AF_INET) 2724 ipp->v = 4; 2725 else if (ipp->f == AF_INET6) 2726 ipp->v = 6; 2727 2728 for (; f != NULL; f = f->fr_next) { 2729 f->fr_ip.fi_src = ipp->a; 2730 f->fr_mip.fi_src = ipp->m; 2731 f->fr_family = ipp->f; 2732 f->fr_ip.fi_v = ipp->v; 2733 f->fr_mip.fi_v = 0xf; 2734 f->fr_satype = ipp->type; 2735 f->fr_ipf->fri_sifpidx = ipp->ifpos; 2736 } 2737 fr = NULL; 2738 } 2739