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