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