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