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