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