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