parse.y revision 1.168
1/*	$OpenBSD: parse.y,v 1.168 2002/10/14 12:58:28 henning Exp $	*/
2
3/*
4 * Copyright (c) 2001 Markus Friedl.  All rights reserved.
5 * Copyright (c) 2001 Daniel Hartmeier.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27%{
28#include <sys/types.h>
29#include <sys/socket.h>
30#include <sys/ioctl.h>
31#include <net/if.h>
32#include <netinet/in.h>
33#include <netinet/in_systm.h>
34#include <netinet/ip.h>
35#include <netinet/ip_icmp.h>
36#include <netinet/icmp6.h>
37#include <net/pfvar.h>
38#include <arpa/inet.h>
39
40#include <stdio.h>
41#include <stdlib.h>
42#include <ifaddrs.h>
43#include <netdb.h>
44#include <stdarg.h>
45#include <errno.h>
46#include <string.h>
47#include <ctype.h>
48#include <err.h>
49#include <pwd.h>
50#include <grp.h>
51
52#include "pfctl_parser.h"
53
54static struct pfctl *pf = NULL;
55static FILE *fin = NULL;
56static int debug = 0;
57static int lineno = 1;
58static int errors = 0;
59static int rulestate = 0;
60static u_int16_t returnicmpdefault =  (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT;
61static u_int16_t returnicmp6default = (ICMP6_DST_UNREACH << 8) |
62    ICMP6_DST_UNREACH_NOPORT;
63static int blockpolicy = PFRULE_DROP;
64
65enum {
66	PFCTL_STATE_NONE = 0,
67	PFCTL_STATE_OPTION = 1,
68	PFCTL_STATE_SCRUB = 2,
69	PFCTL_STATE_NAT = 3,
70	PFCTL_STATE_FILTER = 4
71};
72
73enum pfctl_iflookup_mode {
74	PFCTL_IFLOOKUP_HOST = 0,
75	PFCTL_IFLOOKUP_NET = 1,
76	PFCTL_IFLOOKUP_BCAST = 2
77};
78
79struct node_if {
80	char			 ifname[IFNAMSIZ];
81	u_int8_t		 not;
82	u_int			 ifa_flags;
83	struct node_if		*next;
84	struct node_if		*tail;
85};
86
87struct node_proto {
88	u_int8_t		 proto;
89	struct node_proto	*next;
90	struct node_proto	*tail;
91};
92
93struct node_host {
94	struct pf_addr_wrap	 addr;
95	struct pf_addr		 mask;
96	struct pf_addr		 bcast;
97	u_int8_t		 af;
98	u_int8_t		 not;
99	u_int8_t		 noroute;
100	u_int32_t		 ifindex;	/* link-local IPv6 addrs */
101	char			*ifname;
102	u_int			 ifa_flags;
103	struct node_host	*next;
104	struct node_host	*tail;
105};
106
107struct node_port {
108	u_int16_t		 port[2];
109	u_int8_t		 op;
110	struct node_port	*next;
111	struct node_port	*tail;
112};
113
114struct node_uid {
115	uid_t			 uid[2];
116	u_int8_t		 op;
117	struct node_uid		*next;
118	struct node_uid		*tail;
119};
120
121struct node_gid {
122	gid_t			 gid[2];
123	u_int8_t		 op;
124	struct node_gid		*next;
125	struct node_gid		*tail;
126};
127
128struct node_icmp {
129	u_int8_t		 code;
130	u_int8_t		 type;
131	u_int8_t		 proto;
132	struct node_icmp	*next;
133	struct node_icmp	*tail;
134};
135
136enum	{ PF_STATE_OPT_MAX=0, PF_STATE_OPT_TIMEOUT=1 };
137struct node_state_opt {
138	int			 type;
139	union {
140		u_int32_t	 max_states;
141		struct {
142			int		number;
143			u_int32_t	seconds;
144		}		 timeout;
145	}			 data;
146	struct node_state_opt	*next;
147	struct node_state_opt	*tail;
148};
149
150struct peer {
151	struct node_host	*host;
152	struct node_port	*port;
153};
154
155int	yyerror(char *, ...);
156int	rule_consistent(struct pf_rule *);
157int	nat_consistent(struct pf_nat *);
158int	rdr_consistent(struct pf_rdr *);
159int	yyparse(void);
160void	ipmask(struct pf_addr *, u_int8_t);
161void	expand_rdr(struct pf_rdr *, struct node_if *, struct node_proto *,
162	    struct node_host *, struct node_host *);
163void	expand_nat(struct pf_nat *, struct node_if *, struct node_proto *,
164	    struct node_host *, struct node_port *,
165	    struct node_host *, struct node_port *);
166void	expand_label_addr(const char *, char *, u_int8_t, struct node_host *);
167void	expand_label_port(const char *, char *, struct node_port *);
168void	expand_label_proto(const char *, char *, u_int8_t);
169void	expand_label_nr(const char *, char *);
170void	expand_label(char *, u_int8_t, struct node_host *, struct node_port *,
171	    struct node_host *, struct node_port *, u_int8_t);
172void	expand_rule(struct pf_rule *, struct node_if *, struct node_proto *,
173	    struct node_host *, struct node_port *, struct node_host *,
174	    struct node_port *, struct node_uid *, struct node_gid *,
175	    struct node_icmp *);
176int	check_rulestate(int);
177int	kw_cmp(const void *, const void *);
178int	lookup(char *);
179int	lgetc(FILE *);
180int	lungetc(int, FILE *);
181int	findeol(void);
182int	yylex(void);
183struct	node_host *host(char *);
184int	atoul(char *, u_long *);
185int	getservice(char *);
186
187
188struct sym {
189	struct sym *next;
190	int used;
191	char *nam;
192	char *val;
193};
194struct sym *symhead = NULL;
195
196int	symset(const char *, const char *);
197char *	symget(const char *);
198
199void	ifa_load(void);
200struct	node_host *ifa_exists(char *);
201struct	node_host *ifa_lookup(char *, enum pfctl_iflookup_mode);
202struct	node_host *ifa_pick_ip(struct node_host *, u_int8_t);
203u_int16_t	parseicmpspec(char *, u_int8_t);
204
205typedef struct {
206	union {
207		u_int32_t		number;
208		int			i;
209		char			*string;
210		struct {
211			u_int8_t	b1;
212			u_int8_t	b2;
213			u_int16_t	w;
214			u_int16_t	w2;
215		}			b;
216		struct range {
217			int		a;
218			int		b;
219			int		t;
220		}			range;
221		struct node_if		*interface;
222		struct node_proto	*proto;
223		struct node_icmp	*icmp;
224		struct node_host	*host;
225		struct node_port	*port;
226		struct node_uid		*uid;
227		struct node_gid		*gid;
228		struct node_state_opt	*state_opt;
229		struct peer		peer;
230		struct {
231			struct peer	src, dst;
232		}			fromto;
233		struct {
234			char		*string;
235			struct pf_addr	*addr;
236			u_int8_t	rt;
237			u_int8_t	af;
238		}			route;
239		struct redirection {
240			struct node_host	*address;
241			struct range		 rport;
242		}			*redirection;
243		struct {
244			int			 action;
245			struct node_state_opt	*options;
246		}			keep_state;
247		struct {
248			u_int8_t	log;
249			u_int8_t	quick;
250		}			logquick;
251	} v;
252	int lineno;
253} YYSTYPE;
254
255%}
256
257%token	PASS BLOCK SCRUB RETURN IN OUT LOG LOGALL QUICK ON FROM TO FLAGS
258%token	RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE
259%token	ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF
260%token	MINTTL ERROR ALLOWOPTS FASTROUTE ROUTETO DUPTO REPLYTO NO LABEL
261%token	NOROUTE FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DROP
262%token	FRAGNORM FRAGDROP FRAGCROP
263%token	SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY
264%token	ANTISPOOF FOR
265%token	<v.string> STRING
266%token	<v.i>	PORTUNARY PORTBINARY
267%type	<v.interface>	interface if_list if_item_not if_item
268%type	<v.number>	number port icmptype icmp6type minttl uid gid maxmss
269%type	<v.number>	tos
270%type	<v.i>	no dir log af nodf allowopts fragment fragcache
271%type	<v.b>	action flag flags blockspec
272%type	<v.range>	dport rport
273%type	<v.proto>	proto proto_list proto_item
274%type	<v.icmp>	icmpspec icmp_list icmp6_list icmp_item icmp6_item
275%type	<v.fromto>	fromto
276%type	<v.peer>	ipportspec
277%type	<v.host>	ipspec xhost host address host_list
278%type	<v.port>	portspec port_list port_item
279%type	<v.uid>		uids uid_list uid_item
280%type	<v.gid>		gids gid_list gid_item
281%type	<v.route>	route
282%type	<v.redirection>	redirection
283%type	<v.string>	label string
284%type	<v.keep_state>	keep
285%type	<v.state_opt>	state_opt_spec state_opt_list state_opt_item
286%type	<v.logquick>	logquick
287%type	<v.interface>	antispoof_ifspc antispoof_iflst
288%%
289
290ruleset		: /* empty */
291		| ruleset '\n'
292		| ruleset option '\n'
293		| ruleset scrubrule '\n'
294		| ruleset natrule '\n'
295		| ruleset binatrule '\n'
296		| ruleset rdrrule '\n'
297		| ruleset pfrule '\n'
298		| ruleset varset '\n'
299		| ruleset antispoof '\n'
300		| ruleset error '\n'		{ errors++; }
301		;
302
303option		: SET OPTIMIZATION STRING		{
304			if (pf->opts & PF_OPT_VERBOSE)
305				printf("set optimization %s\n", $3);
306			if (check_rulestate(PFCTL_STATE_OPTION))
307				YYERROR;
308			if (pfctl_set_optimization(pf, $3) != 0) {
309				yyerror("unknown optimization %s", $3);
310				YYERROR;
311			}
312		}
313		| SET TIMEOUT timeout_spec
314		| SET TIMEOUT '{' timeout_list '}'
315		| SET LIMIT limit_spec
316		| SET LIMIT '{' limit_list '}'
317		| SET LOGINTERFACE STRING		{
318			if (pf->opts & PF_OPT_VERBOSE)
319				printf("set loginterface %s\n", $3);
320			if (check_rulestate(PFCTL_STATE_OPTION))
321				YYERROR;
322			if (pfctl_set_logif(pf, $3) != 0) {
323				yyerror("error setting loginterface %s", $3);
324				YYERROR;
325			}
326		}
327		| SET BLOCKPOLICY DROP	{
328			if (pf->opts & PF_OPT_VERBOSE)
329				printf("set block-policy drop\n");
330			if (check_rulestate(PFCTL_STATE_OPTION))
331				YYERROR;
332			blockpolicy = PFRULE_DROP;
333		}
334		| SET BLOCKPOLICY RETURN {
335			if (pf->opts & PF_OPT_VERBOSE)
336				printf("set block-policy return\n");
337			if (check_rulestate(PFCTL_STATE_OPTION))
338				YYERROR;
339			blockpolicy = PFRULE_RETURN;
340		}
341		;
342
343string		: string STRING				{
344			if (asprintf(&$$, "%s %s", $1, $2) == -1) {
345				yyerror("malloc failed");
346				YYERROR;
347			}
348			free($1);
349			free($2);
350		}
351		| STRING
352		;
353
354varset		: STRING PORTUNARY string		{
355			if (pf->opts & PF_OPT_VERBOSE)
356				printf("%s = %s\n", $1, $3);
357			if (symset($1, $3) == -1) {
358				yyerror("cannot store variable %s", $1);
359				YYERROR;
360			}
361		}
362		;
363
364scrubrule	: SCRUB dir interface fromto nodf minttl maxmss fragcache
365		{
366			struct pf_rule r;
367
368			if (check_rulestate(PFCTL_STATE_SCRUB))
369				YYERROR;
370
371			memset(&r, 0, sizeof(r));
372
373			r.action = PF_SCRUB;
374			r.direction = $2;
375
376			if ($3) {
377				if ($3->not) {
378					yyerror("scrub rules don't support "
379					    "'! <if>'");
380					YYERROR;
381				} else if ($3->next) {
382					yyerror("scrub rules don't support "
383					    "{} expansion");
384					YYERROR;
385				}
386				memcpy(r.ifname, $3->ifname,
387				    sizeof(r.ifname));
388				free($3);
389			}
390			if ($5)
391				r.rule_flag |= PFRULE_NODF;
392			if ($6)
393				r.min_ttl = $6;
394			if ($7)
395				r.max_mss = $7;
396			if ($8)
397				r.rule_flag |= $8;
398
399			r.nr = pf->rule_nr++;
400			if (rule_consistent(&r) < 0)
401				yyerror("skipping scrub rule due to errors");
402			else
403				pfctl_add_rule(pf, &r);
404
405		}
406		;
407
408antispoof	: ANTISPOOF logquick antispoof_ifspc af {
409			struct pf_rule r;
410			struct node_host *h = NULL;
411			struct node_if *i, *j;
412
413			if (check_rulestate(PFCTL_STATE_FILTER))
414				YYERROR;
415
416			for (i = $3; i; i = i->next) {
417				memset(&r, 0, sizeof(r));
418
419				r.action = PF_DROP;
420				r.direction = PF_IN;
421				r.log = $2.log;
422				r.quick = $2.quick;
423				r.af = $4;
424
425				j = calloc(1, sizeof(struct node_if));
426				if (j == NULL)
427					errx(1, "antispoof: calloc");
428				strlcpy(j->ifname, i->ifname, IFNAMSIZ);
429				j->not = 1;
430				h = ifa_lookup(j->ifname, PFCTL_IFLOOKUP_NET);
431
432				expand_rule(&r, j, NULL, h, NULL, NULL, NULL,
433				    NULL, NULL, NULL);
434
435				if ((i->ifa_flags & IFF_LOOPBACK) == 0) {
436					memset(&r, 0, sizeof(r));
437
438					r.action = PF_DROP;
439					r.direction = PF_IN;
440					r.log = $2.log;
441					r.quick = $2.quick;
442					r.af = $4;
443
444					h = ifa_lookup(i->ifname,
445					    PFCTL_IFLOOKUP_HOST);
446
447					expand_rule(&r, NULL, NULL, h, NULL,
448					    NULL, NULL, NULL, NULL, NULL);
449				}
450			}
451		}
452		;
453
454antispoof_ifspc	: FOR if_item			{ $$ = $2; }
455		| FOR '{' antispoof_iflst '}'	{ $$ = $3; }
456		;
457
458antispoof_iflst	: if_item			{ $$ = $1; }
459		| antispoof_iflst comma if_item	{
460			$1->tail->next = $3;
461			$1->tail = $3;
462			$$ = $1;
463		}
464		;
465
466pfrule		: action dir logquick interface route af proto fromto
467		  uids gids flags icmpspec tos keep fragment allowopts label
468		{
469			struct pf_rule r;
470			struct node_state_opt *o;
471			struct node_proto *proto;
472
473			if (check_rulestate(PFCTL_STATE_FILTER))
474				YYERROR;
475
476			memset(&r, 0, sizeof(r));
477
478			r.action = $1.b1;
479			switch ($1.b2) {
480			case PFRULE_RETURNRST:
481				r.rule_flag |= PFRULE_RETURNRST;
482				r.return_ttl = $1.w;
483				break;
484			case PFRULE_RETURNICMP:
485				r.rule_flag |= PFRULE_RETURNICMP;
486				r.return_icmp = $1.w;
487				r.return_icmp6 = $1.w2;
488				break;
489			case PFRULE_RETURN:
490				r.rule_flag |= PFRULE_RETURN;
491				r.return_icmp = $1.w;
492				r.return_icmp6 = $1.w2;
493				break;
494			}
495			r.direction = $2;
496			r.log = $3.log;
497			r.quick = $3.quick;
498
499			r.af = $6;
500			r.flags = $11.b1;
501			r.flagset = $11.b2;
502
503			if ($11.b1 || $11.b2) {
504				for (proto = $7; proto != NULL &&
505				    proto->proto != IPPROTO_TCP;
506				    proto = proto->next)
507					;	/* nothing */
508				if (proto == NULL && $7 != NULL) {
509					yyerror("flags only apply to tcp");
510					YYERROR;
511				}
512			}
513
514			r.tos = $13;
515			r.keep_state = $14.action;
516			o = $14.options;
517			while (o) {
518				struct node_state_opt *p = o;
519
520				switch (o->type) {
521				case PF_STATE_OPT_MAX:
522					if (r.max_states) {
523						yyerror("state option 'max' "
524						    "multiple definitions");
525						YYERROR;
526					}
527					r.max_states = o->data.max_states;
528					break;
529				case PF_STATE_OPT_TIMEOUT:
530					if (r.timeout[o->data.timeout.number]) {
531						yyerror("state timeout %s "
532						    "multiple definitions",
533						    pf_timeouts[o->data.
534						    timeout.number].name);
535						YYERROR;
536					}
537					r.timeout[o->data.timeout.number] =
538					    o->data.timeout.seconds;
539				}
540				o = o->next;
541				free(p);
542			}
543
544			if ($15)
545				r.rule_flag |= PFRULE_FRAGMENT;
546			r.allow_opts = $16;
547
548			if ($5.rt) {
549				r.rt = $5.rt;
550				if ($5.string) {
551					strlcpy(r.rt_ifname, $5.string,
552					    IFNAMSIZ);
553					if (ifa_exists(r.rt_ifname) == NULL) {
554						yyerror("unknown interface %s",
555						    r.rt_ifname);
556						YYERROR;
557					}
558					free($5.string);
559				}
560				if ($5.addr) {
561					if (!r.af)
562						r.af = $5.af;
563					else if (r.af != $5.af) {
564						yyerror("address family"
565						    " mismatch");
566						YYERROR;
567					}
568					memcpy(&r.rt_addr, $5.addr,
569					    sizeof(r.rt_addr));
570					free($5.addr);
571				}
572			}
573
574			if ($17) {
575				if (strlen($17) >= PF_RULE_LABEL_SIZE) {
576					yyerror("rule label too long (max "
577					    "%d chars)", PF_RULE_LABEL_SIZE-1);
578					YYERROR;
579				}
580				strlcpy(r.label, $17, sizeof(r.label));
581				free($17);
582			}
583
584			expand_rule(&r, $4, $7, $8.src.host, $8.src.port,
585			    $8.dst.host, $8.dst.port, $9, $10, $12);
586		}
587		;
588
589action		: PASS			{ $$.b1 = PF_PASS; $$.b2 = $$.w = 0; }
590		| BLOCK blockspec	{ $$ = $2; $$.b1 = PF_DROP; }
591		;
592
593blockspec	: /* empty */		{
594			$$.b2 = blockpolicy;
595			$$.w = returnicmpdefault;
596			$$.w2 = returnicmp6default;
597		}
598		| DROP			{
599			$$.b2 = PFRULE_DROP;
600			$$.w = 0;
601			$$.w2 = 0;
602		}
603		| RETURNRST		{
604			$$.b2 = PFRULE_RETURNRST;
605			$$.w = 0;
606			$$.w2 = 0;
607		}
608		| RETURNRST '(' TTL number ')'	{
609			$$.b2 = PFRULE_RETURNRST;
610			$$.w = $4;
611			$$.w2 = 0;
612		}
613		| RETURNICMP		{
614			$$.b2 = PFRULE_RETURNICMP;
615			$$.w = returnicmpdefault;
616			$$.w2 = returnicmp6default;
617		}
618		| RETURNICMP6		{
619			$$.b2 = PFRULE_RETURNICMP;
620			$$.w = returnicmpdefault;
621			$$.w2 = returnicmp6default;
622		}
623		| RETURNICMP '(' STRING ')'	{
624			$$.b2 = PFRULE_RETURNICMP;
625			if (!($$.w = parseicmpspec($3, AF_INET)))
626				YYERROR;
627			$$.w2 = returnicmp6default;
628		}
629		| RETURNICMP6 '(' STRING ')'	{
630			$$.b2 = PFRULE_RETURNICMP;
631			$$.w = returnicmpdefault;
632			if (!($$.w2 = parseicmpspec($3, AF_INET6)))
633				YYERROR;
634		}
635		| RETURNICMP '(' STRING comma STRING ')' {
636			$$.b2 = PFRULE_RETURNICMP;
637			if (!($$.w = parseicmpspec($3, AF_INET)))
638				YYERROR;
639			if (!($$.w2 = parseicmpspec($5, AF_INET6)));
640		}
641		| RETURN {
642			$$.b2 = PFRULE_RETURN;
643			$$.w = returnicmpdefault;
644			$$.w2 = returnicmp6default;
645		}
646		;
647
648fragcache	: /* empty */		{ $$ = 0; }
649		| fragment FRAGNORM	{ $$ = 0; /* default */ }
650		| fragment FRAGCROP	{ $$ = PFRULE_FRAGCROP; }
651		| fragment FRAGDROP	{ $$ = PFRULE_FRAGDROP; }
652		;
653
654
655dir		: IN				{ $$ = PF_IN; }
656		| OUT				{ $$ = PF_OUT; }
657		;
658
659logquick	: /* empty */			{ $$.log = 0; $$.quick = 0; }
660		| log				{ $$.log = $1; $$.quick = 0; }
661		| QUICK				{ $$.log = 0; $$.quick = 1; }
662		| log QUICK			{ $$.log = $1; $$.quick = 1; }
663		| QUICK log			{ $$.log = $2; $$.quick = 1; }
664		;
665
666log		: LOG				{ $$ = 1; }
667		| LOGALL			{ $$ = 2; }
668		;
669
670interface	: /* empty */			{ $$ = NULL; }
671		| ON if_item_not		{ $$ = $2; }
672		| ON '{' if_list '}'		{ $$ = $3; }
673		;
674
675if_list		: if_item_not			{ $$ = $1; }
676		| if_list comma if_item_not	{
677			$1->tail->next = $3;
678			$1->tail = $3;
679			$$ = $1;
680		}
681		;
682
683if_item_not	: '!' if_item			{ $$ = $2; $$->not = 1; }
684		| if_item			{ $$ = $1; }
685
686if_item		: STRING			{
687			struct node_host *n;
688
689			if ((n = ifa_exists($1)) == NULL) {
690				yyerror("unknown interface %s", $1);
691				YYERROR;
692			}
693			$$ = malloc(sizeof(struct node_if));
694			if ($$ == NULL)
695				err(1, "if_item: malloc");
696			strlcpy($$->ifname, $1, IFNAMSIZ);
697			$$->ifa_flags = n->ifa_flags;
698			$$->not = 0;
699			$$->next = NULL;
700			$$->tail = $$;
701		}
702		;
703
704af		: /* empty */			{ $$ = 0; }
705		| INET				{ $$ = AF_INET; }
706		| INET6				{ $$ = AF_INET6; }
707
708proto		: /* empty */			{ $$ = NULL; }
709		| PROTO proto_item		{ $$ = $2; }
710		| PROTO '{' proto_list '}'	{ $$ = $3; }
711		;
712
713proto_list	: proto_item			{ $$ = $1; }
714		| proto_list comma proto_item	{
715			$1->tail->next = $3;
716			$1->tail = $3;
717			$$ = $1;
718		}
719		;
720
721proto_item	: STRING			{
722			struct protoent *p;
723			u_long ulval;
724
725			if (atoul($1, &ulval) == 0)
726				p = getprotobynumber(ulval);
727			else
728				p = getprotobyname($1);
729
730			if (p == NULL) {
731				yyerror("unknown protocol %s", $1);
732				YYERROR;
733			}
734			$$ = malloc(sizeof(struct node_proto));
735			if ($$ == NULL)
736				err(1, "proto_item: malloc");
737			$$->proto = p->p_proto;
738			$$->next = NULL;
739			$$->tail = $$;
740		}
741		;
742
743fromto		: ALL				{
744			$$.src.host = NULL;
745			$$.src.port = NULL;
746			$$.dst.host = NULL;
747			$$.dst.port = NULL;
748		}
749		| FROM ipportspec TO ipportspec	{
750			$$.src = $2;
751			$$.dst = $4;
752		}
753		;
754
755ipportspec	: ipspec			{ $$.host = $1; $$.port = NULL; }
756		| ipspec PORT portspec		{
757			$$.host = $1;
758			$$.port = $3;
759		}
760		;
761
762ipspec		: ANY				{ $$ = NULL; }
763		| xhost				{ $$ = $1; }
764		| '{' host_list '}'		{ $$ = $2; }
765		;
766
767host_list	: xhost				{ $$ = $1; }
768		| host_list comma xhost		{
769			/* $3 may be a list, so use its tail pointer */
770			$1->tail->next = $3->tail;
771			$1->tail = $3->tail;
772			$$ = $1;
773		}
774		;
775
776xhost		: '!' host			{
777			struct node_host *h;
778			for (h = $2; h; h = h->next)
779				h->not = 1;
780			$$ = $2;
781		}
782		| host				{ $$ = $1; }
783		| NOROUTE			{
784			$$ = calloc(1, sizeof(struct node_host));
785			if ($$ == NULL)
786				err(1, "xhost: calloc");
787			$$->noroute = 1;
788			$$->next = NULL;
789			$$->tail = $$;
790		}
791		;
792
793host		: address
794		| address '/' number		{
795			struct node_host *n;
796			for (n = $1; n; n = n->next) {
797				if ($1->af == AF_INET) {
798					if ($3 > 32) {
799						yyerror(
800						    "illegal netmask value /%d",
801						    $3);
802						YYERROR;
803					}
804				} else {
805					if ($3 > 128) {
806						yyerror(
807						    "illegal netmask value /%d",
808						    $3);
809						YYERROR;
810					}
811				}
812				ipmask(&n->mask, $3);
813			}
814			$$ = $1;
815		}
816		;
817
818number		: STRING			{
819			u_long ulval;
820
821			if (atoul($1, &ulval) == -1) {
822				yyerror("%s is not a number", $1);
823				YYERROR;
824			} else
825				$$ = ulval;
826		}
827		;
828
829address		: '(' STRING ')'		{
830			$$ = calloc(1, sizeof(struct node_host));
831			if ($$ == NULL)
832				err(1, "address: calloc");
833			$$->af = 0;
834			ipmask(&$$->mask, 128);
835			$$->addr.addr_dyn = (struct pf_addr_dyn *)1;
836			strncpy($$->addr.addr.pfa.ifname, $2,
837			    sizeof($$->addr.addr.pfa.ifname));
838		}
839		| STRING			{ $$ = host($1); }
840		;
841
842portspec	: port_item			{ $$ = $1; }
843		| '{' port_list '}'		{ $$ = $2; }
844		;
845
846port_list	: port_item			{ $$ = $1; }
847		| port_list comma port_item	{
848			$1->tail->next = $3;
849			$1->tail = $3;
850			$$ = $1;
851		}
852		;
853
854port_item	: port				{
855			$$ = malloc(sizeof(struct node_port));
856			if ($$ == NULL)
857				err(1, "port_item: malloc");
858			$$->port[0] = $1;
859			$$->port[1] = $1;
860			$$->op = PF_OP_EQ;
861			$$->next = NULL;
862			$$->tail = $$;
863		}
864		| PORTUNARY port		{
865			$$ = malloc(sizeof(struct node_port));
866			if ($$ == NULL)
867				err(1, "port_item: malloc");
868			$$->port[0] = $2;
869			$$->port[1] = $2;
870			$$->op = $1;
871			$$->next = NULL;
872			$$->tail = $$;
873		}
874		| port PORTBINARY port		{
875			$$ = malloc(sizeof(struct node_port));
876			if ($$ == NULL)
877				err(1, "port_item: malloc");
878			$$->port[0] = $1;
879			$$->port[1] = $3;
880			$$->op = $2;
881			$$->next = NULL;
882			$$->tail = $$;
883		}
884		;
885
886port		: STRING			{
887			struct servent *s = NULL;
888			u_long ulval;
889
890			if (atoul($1, &ulval) == 0) {
891				if (ulval > 65535) {
892					yyerror("illegal port value %d", ulval);
893					YYERROR;
894				}
895				$$ = htons(ulval);
896			} else {
897				s = getservbyname($1, "tcp");
898				if (s == NULL)
899					s = getservbyname($1, "udp");
900				if (s == NULL) {
901					yyerror("unknown port %s", $1);
902					YYERROR;
903				}
904				$$ = s->s_port;
905			}
906		}
907		;
908
909uids		: /* empty */			{ $$ = NULL; }
910		| USER uid_item			{ $$ = $2; }
911		| USER '{' uid_list '}'		{ $$ = $3; }
912		;
913
914uid_list	: uid_item			{ $$ = $1; }
915		| uid_list comma uid_item	{
916			$1->tail->next = $3;
917			$1->tail = $3;
918			$$ = $1;
919		}
920		;
921
922uid_item	: uid				{
923			$$ = malloc(sizeof(struct node_uid));
924			if ($$ == NULL)
925				err(1, "uid_item: malloc");
926			$$->uid[0] = $1;
927			$$->uid[1] = $1;
928			$$->op = PF_OP_EQ;
929			$$->next = NULL;
930			$$->tail = $$;
931		}
932		| PORTUNARY uid			{
933			if ($2 == UID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) {
934				yyerror("user unknown requires operator = or !=");
935				YYERROR;
936			}
937			$$ = malloc(sizeof(struct node_uid));
938			if ($$ == NULL)
939				err(1, "uid_item: malloc");
940			$$->uid[0] = $2;
941			$$->uid[1] = $2;
942			$$->op = $1;
943			$$->next = NULL;
944			$$->tail = $$;
945		}
946		| uid PORTBINARY uid		{
947			if ($1 == UID_MAX || $3 == UID_MAX) {
948				yyerror("user unknown requires operator = or !=");
949				YYERROR;
950			}
951			$$ = malloc(sizeof(struct node_uid));
952			if ($$ == NULL)
953				err(1, "uid_item: malloc");
954			$$->uid[0] = $1;
955			$$->uid[1] = $3;
956			$$->op = $2;
957			$$->next = NULL;
958			$$->tail = $$;
959		}
960		;
961
962uid		: STRING			{
963			u_long ulval;
964
965			if (atoul($1, &ulval) == -1) {
966				if (!strcmp($1, "unknown"))
967					$$ = UID_MAX;
968				else {
969					struct passwd *pw;
970
971					if ((pw = getpwnam($1)) == NULL) {
972						yyerror("unknown user %s", $1);
973						YYERROR;
974					}
975					$$ = pw->pw_uid;
976				}
977			} else {
978				if (ulval >= UID_MAX) {
979					yyerror("illegal uid value %ul", ulval);
980					YYERROR;
981				}
982				$$ = ulval;
983			}
984		}
985		;
986
987gids		: /* empty */			{ $$ = NULL; }
988		| GROUP gid_item		{ $$ = $2; }
989		| GROUP '{' gid_list '}'	{ $$ = $3; }
990		;
991
992gid_list	: gid_item			{ $$ = $1; }
993		| gid_list comma gid_item	{
994			$1->tail->next = $3;
995			$1->tail = $3;
996			$$ = $1;
997		}
998		;
999
1000gid_item	: gid				{
1001			$$ = malloc(sizeof(struct node_gid));
1002			if ($$ == NULL)
1003				err(1, "gid_item: malloc");
1004			$$->gid[0] = $1;
1005			$$->gid[1] = $1;
1006			$$->op = PF_OP_EQ;
1007			$$->next = NULL;
1008			$$->tail = $$;
1009		}
1010		| PORTUNARY gid			{
1011			if ($2 == GID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) {
1012				yyerror("group unknown requires operator = or !=");
1013				YYERROR;
1014			}
1015			$$ = malloc(sizeof(struct node_gid));
1016			if ($$ == NULL)
1017				err(1, "gid_item: malloc");
1018			$$->gid[0] = $2;
1019			$$->gid[1] = $2;
1020			$$->op = $1;
1021			$$->next = NULL;
1022			$$->tail = $$;
1023		}
1024		| gid PORTBINARY gid		{
1025			if ($1 == GID_MAX || $3 == GID_MAX) {
1026				yyerror("group unknown requires operator = or !=");
1027				YYERROR;
1028			}
1029			$$ = malloc(sizeof(struct node_gid));
1030			if ($$ == NULL)
1031				err(1, "gid_item: malloc");
1032			$$->gid[0] = $1;
1033			$$->gid[1] = $3;
1034			$$->op = $2;
1035			$$->next = NULL;
1036			$$->tail = $$;
1037		}
1038		;
1039
1040gid		: STRING			{
1041			u_long ulval;
1042
1043			if (atoul($1, &ulval) == -1) {
1044				if (!strcmp($1, "unknown"))
1045					$$ = GID_MAX;
1046				else {
1047					struct group *grp;
1048
1049					if ((grp = getgrnam($1)) == NULL) {
1050						yyerror("unknown group %s", $1);
1051						YYERROR;
1052					}
1053					$$ = grp->gr_gid;
1054				}
1055			} else {
1056				if (ulval >= GID_MAX) {
1057					yyerror("illegal gid value %ul", ulval);
1058					YYERROR;
1059				}
1060				$$ = ulval;
1061			}
1062		}
1063		;
1064
1065flag		: STRING			{
1066			int f;
1067
1068			if ((f = parse_flags($1)) < 0) {
1069				yyerror("bad flags %s", $1);
1070				YYERROR;
1071			}
1072			$$.b1 = f;
1073		}
1074		;
1075
1076flags		: /* empty */			{ $$.b1 = 0; $$.b2 = 0; }
1077		| FLAGS flag			{ $$.b1 = $2.b1; $$.b2 = PF_TH_ALL; }
1078		| FLAGS flag "/" flag		{ $$.b1 = $2.b1; $$.b2 = $4.b1; }
1079		| FLAGS "/" flag		{ $$.b1 = 0; $$.b2 = $3.b1; }
1080		;
1081
1082icmpspec	: /* empty */			{ $$ = NULL; }
1083		| ICMPTYPE icmp_item		{ $$ = $2; }
1084		| ICMPTYPE '{' icmp_list '}'	{ $$ = $3; }
1085		| ICMP6TYPE icmp6_item		{ $$ = $2; }
1086		| ICMP6TYPE '{' icmp6_list '}'	{ $$ = $3; }
1087		;
1088
1089icmp_list	: icmp_item			{ $$ = $1; }
1090		| icmp_list comma icmp_item	{
1091			$1->tail->next = $3;
1092			$1->tail = $3;
1093			$$ = $1;
1094		}
1095		;
1096
1097icmp6_list	: icmp6_item			{ $$ = $1; }
1098		| icmp6_list comma icmp6_item	{
1099			$1->tail->next = $3;
1100			$1->tail = $3;
1101			$$ = $1;
1102		}
1103		;
1104
1105icmp_item	: icmptype		{
1106			$$ = malloc(sizeof(struct node_icmp));
1107			if ($$ == NULL)
1108				err(1, "icmp_item: malloc");
1109			$$->type = $1;
1110			$$->code = 0;
1111			$$->proto = IPPROTO_ICMP;
1112			$$->next = NULL;
1113			$$->tail = $$;
1114		}
1115		| icmptype CODE STRING	{
1116			const struct icmpcodeent *p;
1117			u_long ulval;
1118
1119			if (atoul($3, &ulval) == 0) {
1120				if (ulval > 255) {
1121					yyerror("illegal icmp-code %d", ulval);
1122					YYERROR;
1123				}
1124			} else {
1125				if ((p = geticmpcodebyname($1, $3,
1126				    AF_INET)) == NULL) {
1127					yyerror("unknown icmp-code %s", $3);
1128					YYERROR;
1129				}
1130				ulval = p->code;
1131			}
1132			$$ = malloc(sizeof(struct node_icmp));
1133			if ($$ == NULL)
1134				err(1, "icmp_item: malloc");
1135			$$->type = $1;
1136			$$->code = ulval + 1;
1137			$$->proto = IPPROTO_ICMP;
1138			$$->next = NULL;
1139			$$->tail = $$;
1140		}
1141		;
1142
1143icmp6_item	: icmp6type		{
1144			$$ = malloc(sizeof(struct node_icmp));
1145			if ($$ == NULL)
1146				err(1, "icmp_item: malloc");
1147			$$->type = $1;
1148			$$->code = 0;
1149			$$->proto = IPPROTO_ICMPV6;
1150			$$->next = NULL;
1151			$$->tail = $$;
1152		}
1153		| icmp6type CODE STRING	{
1154			const struct icmpcodeent *p;
1155			u_long ulval;
1156
1157			if (atoul($3, &ulval) == 0) {
1158				if (ulval > 255) {
1159					yyerror("illegal icmp6-code %ld", ulval);
1160					YYERROR;
1161				}
1162			} else {
1163				if ((p = geticmpcodebyname($1, $3,
1164				    AF_INET6)) == NULL) {
1165					yyerror("unknown icmp6-code %s", $3);
1166					YYERROR;
1167				}
1168				ulval = p->code;
1169			}
1170			$$ = malloc(sizeof(struct node_icmp));
1171			if ($$ == NULL)
1172				err(1, "icmp_item: malloc");
1173			$$->type = $1;
1174			$$->code = ulval + 1;
1175			$$->proto = IPPROTO_ICMPV6;
1176			$$->next = NULL;
1177			$$->tail = $$;
1178		}
1179		;
1180
1181icmptype	: STRING			{
1182			const struct icmptypeent *p;
1183			u_long ulval;
1184
1185			if (atoul($1, &ulval) == 0) {
1186				if (ulval > 255) {
1187					yyerror("illegal icmp-type %d", ulval);
1188					YYERROR;
1189				}
1190				$$ = ulval + 1;
1191			} else {
1192				if ((p = geticmptypebyname($1, AF_INET)) == NULL) {
1193					yyerror("unknown icmp-type %s", $1);
1194					YYERROR;
1195				}
1196				$$ = p->type + 1;
1197			}
1198		}
1199		;
1200
1201icmp6type	: STRING			{
1202			const struct icmptypeent *p;
1203			u_long ulval;
1204
1205			if (atoul($1, &ulval) == 0) {
1206				if (ulval > 255) {
1207					yyerror("illegal icmp6-type %d", ulval);
1208					YYERROR;
1209				}
1210				$$ = ulval + 1;
1211			} else {
1212				if ((p = geticmptypebyname($1, AF_INET6)) == NULL) {
1213					yyerror("unknown ipv6-icmp-type %s", $1);
1214					YYERROR;
1215				}
1216				$$ = p->type + 1;
1217			}
1218		}
1219		;
1220
1221tos		: /* empty */			{ $$ = 0; }
1222		| TOS STRING			{
1223			if (!strcmp($2, "lowdelay"))
1224				$$ = IPTOS_LOWDELAY;
1225			else if (!strcmp($2, "throughput"))
1226				$$ = IPTOS_THROUGHPUT;
1227			else if (!strcmp($2, "reliability"))
1228				$$ = IPTOS_RELIABILITY;
1229			else if ($2[0] == '0' && $2[1] == 'x')
1230				$$ = strtoul($2, NULL, 16);
1231			else
1232				$$ = strtoul($2, NULL, 10);
1233			if (!$$ || $$ > 255) {
1234				yyerror("illegal tos value %s", $2);
1235				YYERROR;
1236			}
1237		}
1238		;
1239
1240keep		: /* empty */			{
1241			$$.action = 0;
1242			$$.options = NULL;
1243		}
1244		| KEEP STATE state_opt_spec	{
1245			$$.action = PF_STATE_NORMAL;
1246			$$.options = $3;
1247		}
1248		| MODULATE STATE state_opt_spec	{
1249			$$.action = PF_STATE_MODULATE;
1250			$$.options = $3;
1251		}
1252		;
1253
1254state_opt_spec	: /* empty */			{ $$ = NULL; }
1255		| '(' state_opt_list ')'	{ $$ = $2; }
1256		;
1257
1258state_opt_list	: state_opt_item		{ $$ = $1; }
1259		| state_opt_list comma state_opt_item {
1260			$1->tail->next = $3;
1261			$1->tail = $3;
1262			$$ = $1;
1263		}
1264		;
1265
1266state_opt_item	: MAXIMUM number		{
1267			if ($2 <= 0) {
1268				yyerror("illegal states max value %d", $2);
1269				YYERROR;
1270			}
1271			$$ = calloc(1, sizeof(struct node_state_opt));
1272			if ($$ == NULL)
1273				err(1, "state_opt_item: calloc");
1274			$$->type = PF_STATE_OPT_MAX;
1275			$$->data.max_states = $2;
1276			$$->next = NULL;
1277			$$->tail = $$;
1278		}
1279		| STRING number			{
1280			int i;
1281
1282			for (i = 0; pf_timeouts[i].name &&
1283			    strcmp(pf_timeouts[i].name, $1); ++i)
1284				;	/* nothing */
1285			if (!pf_timeouts[i].name) {
1286				yyerror("illegal timeout name %s", $1);
1287				YYERROR;
1288			}
1289			if (strchr(pf_timeouts[i].name, '.') == NULL) {
1290				yyerror("illegal state timeout %s", $1);
1291				YYERROR;
1292			}
1293			$$ = calloc(1, sizeof(struct node_state_opt));
1294			if ($$ == NULL)
1295				err(1, "state_opt_item: calloc");
1296			$$->type = PF_STATE_OPT_TIMEOUT;
1297			$$->data.timeout.number = pf_timeouts[i].timeout;
1298			$$->data.timeout.seconds = $2;
1299			$$->next = NULL;
1300			$$->tail = $$;
1301		}
1302		;
1303
1304fragment	: /* empty */			{ $$ = 0; }
1305		| FRAGMENT			{ $$ = 1; }
1306
1307minttl		: /* empty */			{ $$ = 0; }
1308		| MINTTL number			{
1309			if ($2 > 255) {
1310				yyerror("illegal min-ttl value %d", $2);
1311				YYERROR;
1312			}
1313			$$ = $2;
1314		}
1315		;
1316
1317nodf		: /* empty */			{ $$ = 0; }
1318		| NODF				{ $$ = 1; }
1319		;
1320
1321maxmss		: /* empty */			{ $$ = 0; }
1322		| MAXMSS number			{ $$ = $2; }
1323		;
1324
1325allowopts	: /* empty */			{ $$ = 0; }
1326		| ALLOWOPTS			{ $$ = 1; }
1327
1328label		: /* empty */			{ $$ = NULL; }
1329		| LABEL STRING			{
1330			if (($$ = strdup($2)) == NULL) {
1331				yyerror("rule label strdup() failed");
1332				YYERROR;
1333			}
1334		}
1335		;
1336
1337no		: /* empty */			{ $$ = 0; }
1338		| NO				{ $$ = 1; }
1339		;
1340
1341rport		: STRING			{
1342			char *p = strchr($1, ':');
1343
1344			if (p == NULL) {
1345				if (($$.a = getservice($1)) == -1)
1346					YYERROR;
1347				$$.b = $$.t = 0;
1348			} else if (!strcmp(p+1, "*")) {
1349				*p = 0;
1350				if (($$.a = getservice($1)) == -1)
1351					YYERROR;
1352				$$.b = 0;
1353				$$.t = PF_RPORT_RANGE;
1354			} else {
1355				*p++ = 0;
1356				if (($$.a = getservice($1)) == -1 ||
1357				    ($$.b = getservice(p)) == -1)
1358					YYERROR;
1359				$$.t = PF_RPORT_RANGE;
1360			}
1361		}
1362		;
1363
1364redirection	: /* empty */			{ $$ = NULL; }
1365		| ARROW host			{
1366			$$ = malloc(sizeof(struct redirection));
1367			if ($$ == NULL)
1368				err(1, "redirection: malloc");
1369			$$->address = $2;
1370			$$->rport.a = $$->rport.b = $$->rport.t = 0;
1371		}
1372		| ARROW host PORT rport	{
1373			$$ = malloc(sizeof(struct redirection));
1374			if ($$ == NULL)
1375				err(1, "redirection: malloc");
1376			$$->address = $2;
1377			$$->rport = $4;
1378		}
1379		;
1380
1381natrule		: no NAT interface af proto fromto redirection
1382		{
1383			struct pf_nat nat;
1384
1385			if (check_rulestate(PFCTL_STATE_NAT))
1386				YYERROR;
1387
1388			memset(&nat, 0, sizeof(nat));
1389
1390			nat.no = $1;
1391			nat.af = $4;
1392
1393			if (!nat.af) {
1394				if ($6.src.host && $6.src.host->af
1395				    && !$6.src.host->ifindex)
1396					nat.af = $6.src.host->af;
1397				else if ($6.dst.host && $6.dst.host->af
1398				    && !$6.dst.host->ifindex)
1399					nat.af = $6.dst.host->af;
1400			}
1401
1402			if (nat.no) {
1403				if ($7 != NULL) {
1404					yyerror("'no nat' rule does not need "
1405					    "'->'");
1406					YYERROR;
1407				}
1408			} else {
1409				struct node_host *n;
1410
1411				if ($7 == NULL || $7->address == NULL) {
1412					yyerror("'nat' rule requires '-> "
1413					    "address'");
1414					YYERROR;
1415				}
1416				if (!nat.af && !$7->address->ifindex)
1417					nat.af = $7->address->af;
1418				n = ifa_pick_ip($7->address, nat.af);
1419				if (n == NULL)
1420					YYERROR;
1421				if (!nat.af)
1422					nat.af = n->af;
1423				memcpy(&nat.raddr, &n->addr,
1424				    sizeof(nat.raddr));
1425				nat.proxy_port[0] = ntohs($7->rport.a);
1426				nat.proxy_port[1] = ntohs($7->rport.b);
1427				if (!nat.proxy_port[0] && !nat.proxy_port[1]) {
1428					nat.proxy_port[0] =
1429					    PF_NAT_PROXY_PORT_LOW;
1430					nat.proxy_port[1] =
1431					    PF_NAT_PROXY_PORT_HIGH;
1432				} else if (!nat.proxy_port[1])
1433					nat.proxy_port[1] = nat.proxy_port[0];
1434				free($7->address);
1435				free($7);
1436			}
1437
1438			expand_nat(&nat, $3, $5, $6.src.host, $6.src.port,
1439			    $6.dst.host, $6.dst.port);
1440		}
1441		;
1442
1443binatrule	: no BINAT interface af proto FROM host TO ipspec redirection
1444		{
1445			struct pf_binat binat;
1446
1447			if (check_rulestate(PFCTL_STATE_NAT))
1448				YYERROR;
1449
1450			memset(&binat, 0, sizeof(binat));
1451
1452			binat.no = $1;
1453			if ($3 != NULL) {
1454				memcpy(binat.ifname, $3->ifname,
1455				    sizeof(binat.ifname));
1456				free($3);
1457			}
1458			binat.af = $4;
1459			if ($5 != NULL) {
1460				binat.proto = $5->proto;
1461				free($5);
1462			}
1463			if ($7 != NULL && $9 != NULL && $7->af != $9->af) {
1464				yyerror("binat ip versions must match");
1465				YYERROR;
1466			}
1467			if ($7 != NULL) {
1468				if ($7->next) {
1469					yyerror("multiple binat ip addresses");
1470					YYERROR;
1471				}
1472				if ($7->addr.addr_dyn != NULL) {
1473					if (!binat.af) {
1474						yyerror("address family (inet/"
1475						    "inet6) undefined");
1476						YYERROR;
1477					}
1478					$7->af = binat.af;
1479				}
1480				if (binat.af && $7->af != binat.af) {
1481					yyerror("binat ip versions must match");
1482					YYERROR;
1483				}
1484				binat.af = $7->af;
1485				memcpy(&binat.saddr.addr, &$7->addr.addr,
1486				    sizeof(binat.saddr.addr));
1487				memcpy(&binat.smask, &$7->mask,
1488				    sizeof(binat.smask));
1489				free($7);
1490			}
1491			if ($9 != NULL) {
1492				if ($9->next) {
1493					yyerror("multiple binat ip addresses");
1494					YYERROR;
1495				}
1496				if ($9->addr.addr_dyn != NULL) {
1497					if (!binat.af) {
1498						yyerror("address family (inet/"
1499						    "inet6) undefined");
1500						YYERROR;
1501					}
1502					$9->af = binat.af;
1503				}
1504				if (binat.af && $9->af != binat.af) {
1505					yyerror("binat ip versions must match");
1506					YYERROR;
1507				}
1508				binat.af = $9->af;
1509				memcpy(&binat.daddr.addr, &$9->addr.addr,
1510				    sizeof(binat.daddr.addr));
1511				memcpy(&binat.dmask, &$9->mask,
1512				    sizeof(binat.dmask));
1513				binat.dnot  = $9->not;
1514				free($9);
1515			}
1516
1517			if (binat.no) {
1518				if ($10 != NULL) {
1519					yyerror("'no binat' rule does not need"
1520					    " '->'");
1521					YYERROR;
1522				}
1523			} else {
1524				struct node_host *n;
1525
1526				if ($10 == NULL || $10->address == NULL) {
1527					yyerror("'binat' rule requires"
1528					    " '-> address'");
1529					YYERROR;
1530				}
1531				n = ifa_pick_ip($10->address, binat.af);
1532				if (n == NULL)
1533					YYERROR;
1534				if (n->addr.addr_dyn != NULL) {
1535					if (!binat.af) {
1536						yyerror("address family (inet/"
1537						    "inet6) undefined");
1538						YYERROR;
1539					}
1540					n->af = binat.af;
1541				}
1542				if (binat.af && n->af != binat.af) {
1543					yyerror("binat ip versions must match");
1544					YYERROR;
1545				}
1546				binat.af = n->af;
1547				memcpy(&binat.raddr.addr, &n->addr.addr,
1548				    sizeof(binat.raddr.addr));
1549				memcpy(&binat.rmask, &n->mask,
1550				    sizeof(binat.rmask));
1551				if (!PF_AZERO(&binat.smask, binat.af) &&
1552				    !PF_AEQ(&binat.smask,
1553				    &binat.rmask, binat.af)) {
1554					yyerror("'binat' source mask and "
1555					    "redirect mask must be the same");
1556					YYERROR;
1557				}
1558				free($10->address);
1559				free($10);
1560			}
1561
1562			pfctl_add_binat(pf, &binat);
1563		}
1564
1565rdrrule		: no RDR interface af proto FROM ipspec TO ipspec dport redirection
1566		{
1567			struct pf_rdr rdr;
1568
1569			if (check_rulestate(PFCTL_STATE_NAT))
1570				YYERROR;
1571
1572			memset(&rdr, 0, sizeof(rdr));
1573
1574			rdr.no = $1;
1575			rdr.af = $4;
1576			if ($7 != NULL) {
1577				memcpy(&rdr.saddr, &$7->addr,
1578				    sizeof(rdr.saddr));
1579				memcpy(&rdr.smask, &$7->mask,
1580				    sizeof(rdr.smask));
1581				rdr.snot  = $7->not;
1582				if (!rdr.af && !$7->ifindex)
1583					rdr.af = $7->af;
1584			}
1585			if ($9 != NULL) {
1586				memcpy(&rdr.daddr, &$9->addr,
1587				    sizeof(rdr.daddr));
1588				memcpy(&rdr.dmask, &$9->mask,
1589				    sizeof(rdr.dmask));
1590				rdr.dnot  = $9->not;
1591				if (!rdr.af && !$9->ifindex)
1592					rdr.af = $9->af;
1593			}
1594
1595			rdr.dport  = $10.a;
1596			rdr.dport2 = $10.b;
1597			rdr.opts  |= $10.t;
1598
1599			if (rdr.no) {
1600				if ($11 != NULL) {
1601					yyerror("'no rdr' rule does not need '->'");
1602					YYERROR;
1603				}
1604			} else {
1605				struct node_host *n;
1606
1607				if ($11 == NULL || $11->address == NULL) {
1608					yyerror("'rdr' rule requires '-> "
1609					    "address'");
1610					YYERROR;
1611				}
1612				if (!rdr.af && !$11->address->ifindex)
1613					rdr.af = $11->address->af;
1614				n = ifa_pick_ip($11->address, rdr.af);
1615				if (n == NULL)
1616					YYERROR;
1617				if (!rdr.af)
1618					rdr.af = n->af;
1619				memcpy(&rdr.raddr, &n->addr,
1620				    sizeof(rdr.raddr));
1621				free($11->address);
1622				rdr.rport  = $11->rport.a;
1623				rdr.opts  |= $11->rport.t;
1624				free($11);
1625			}
1626
1627			expand_rdr(&rdr, $3, $5, $7, $9);
1628		}
1629		;
1630
1631dport		: /* empty */			{
1632			$$.a = $$.b = $$.t = 0;
1633		}
1634		| PORT STRING			{
1635			char *p = strchr($2, ':');
1636
1637			if (p == NULL) {
1638				if (($$.a = getservice($2)) == -1)
1639					YYERROR;
1640				$$.b = $$.t = 0;
1641			} else {
1642				*p++ = 0;
1643				if (($$.a = getservice($2)) == -1 ||
1644				    ($$.b = getservice(p)) == -1)
1645					YYERROR;
1646				$$.t = PF_DPORT_RANGE;
1647			}
1648		}
1649		;
1650
1651route		: /* empty */			{
1652			$$.string = NULL;
1653			$$.rt = 0;
1654			$$.addr = NULL;
1655			$$.af = 0;
1656		}
1657		| FASTROUTE {
1658			$$.string = NULL;
1659			$$.rt = PF_FASTROUTE;
1660			$$.addr = NULL;
1661		}
1662		| ROUTETO '(' STRING address ')' {
1663			if (($$.string = strdup($3)) == NULL) {
1664				yyerror("routeto: strdup");
1665				YYERROR;
1666			}
1667			$$.rt = PF_ROUTETO;
1668			if ($4->addr.addr_dyn != NULL) {
1669				yyerror("route-to does not support"
1670				    " dynamic addresses");
1671				YYERROR;
1672			}
1673			if ($4->next) {
1674				yyerror("multiple route-to ip addresses");
1675				YYERROR;
1676			}
1677			$$.addr = &$4->addr.addr;
1678			$$.af = $4->af;
1679		}
1680		| ROUTETO STRING {
1681			if (($$.string = strdup($2)) == NULL) {
1682				yyerror("routeto: strdup");
1683				YYERROR;
1684			}
1685			$$.rt = PF_ROUTETO;
1686			$$.addr = NULL;
1687		}
1688		| REPLYTO '(' STRING address ')' {
1689			if (($$.string = strdup($3)) == NULL) {
1690				yyerror("reply-to: strdup");
1691				YYERROR;
1692			}
1693			$$.rt = PF_REPLYTO;
1694			if ($4->addr.addr_dyn != NULL) {
1695				yyerror("reply-to does not support"
1696				    " dynamic addresses");
1697				YYERROR;
1698			}
1699			if ($4->next) {
1700				yyerror("multiple reply-to ip addresses");
1701				YYERROR;
1702			}
1703			$$.addr = &$4->addr.addr;
1704			$$.af = $4->af;
1705		}
1706		| REPLYTO STRING {
1707			if (($$.string = strdup($2)) == NULL) {
1708				yyerror("reply-to: strdup");
1709				YYERROR;
1710			}
1711			$$.rt = PF_REPLYTO;
1712			$$.addr = NULL;
1713		}
1714		| DUPTO '(' STRING address ')' {
1715			if (($$.string = strdup($3)) == NULL) {
1716				yyerror("dupto: strdup");
1717				YYERROR;
1718			}
1719			$$.rt = PF_DUPTO;
1720			if ($4->addr.addr_dyn != NULL) {
1721				yyerror("dup-to does not support"
1722				    " dynamic addresses");
1723				YYERROR;
1724			}
1725			if ($4->next) {
1726				yyerror("multiple dup-to ip addresses");
1727				YYERROR;
1728			}
1729			$$.addr = &$4->addr.addr;
1730			$$.af = $4->af;
1731		}
1732		| DUPTO STRING {
1733			if (($$.string = strdup($2)) == NULL) {
1734				yyerror("dupto: strdup");
1735				YYERROR;
1736			}
1737			$$.rt = PF_DUPTO;
1738			$$.addr = NULL;
1739		}
1740		;
1741
1742timeout_spec	: STRING number
1743		{
1744			if (pf->opts & PF_OPT_VERBOSE)
1745				printf("set timeout %s %us\n", $1, $2);
1746			if (check_rulestate(PFCTL_STATE_OPTION))
1747				YYERROR;
1748			if (pfctl_set_timeout(pf, $1, $2) != 0) {
1749				yyerror("unknown timeout %s", $1);
1750				YYERROR;
1751			}
1752		}
1753		;
1754
1755timeout_list	: timeout_list comma timeout_spec
1756		| timeout_spec
1757		;
1758
1759limit_spec	: STRING number
1760		{
1761			if (pf->opts & PF_OPT_VERBOSE)
1762				printf("set limit %s %u\n", $1, $2);
1763			if (check_rulestate(PFCTL_STATE_OPTION))
1764				YYERROR;
1765			if (pfctl_set_limit(pf, $1, $2) != 0) {
1766				yyerror("unable to set limit %s %u", $1, $2);
1767				YYERROR;
1768			}
1769		}
1770
1771limit_list	: limit_list comma limit_spec
1772		| limit_spec
1773		;
1774
1775comma		: ','
1776		| /* empty */
1777		;
1778
1779%%
1780
1781int
1782yyerror(char *fmt, ...)
1783{
1784	va_list ap;
1785	extern char *infile;
1786	errors = 1;
1787
1788	va_start(ap, fmt);
1789	fprintf(stderr, "%s:%d: ", infile, yylval.lineno);
1790	vfprintf(stderr, fmt, ap);
1791	fprintf(stderr, "\n");
1792	va_end(ap);
1793	return (0);
1794}
1795
1796int
1797rule_consistent(struct pf_rule *r)
1798{
1799	int problems = 0;
1800
1801	if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP &&
1802	    (r->src.port_op || r->dst.port_op)) {
1803		yyerror("port only applies to tcp/udp");
1804		problems++;
1805	}
1806	if (r->proto != IPPROTO_ICMP && r->proto != IPPROTO_ICMPV6 &&
1807	    (r->type || r->code)) {
1808		yyerror("icmp-type/code only applies to icmp");
1809		problems++;
1810	}
1811	if (!r->af && (r->type || r->code)) {
1812		yyerror("must indicate address family with icmp-type/code");
1813		problems++;
1814	}
1815	if ((r->proto == IPPROTO_ICMP && r->af == AF_INET6) ||
1816	    (r->proto == IPPROTO_ICMPV6 && r->af == AF_INET)) {
1817		yyerror("icmp version does not match address family");
1818		problems++;
1819	}
1820	if (r->keep_state == PF_STATE_MODULATE && r->proto &&
1821	    r->proto != IPPROTO_TCP) {
1822		yyerror("modulate state can only be applied to TCP rules");
1823		problems++;
1824	}
1825	if (r->allow_opts && r->action != PF_PASS) {
1826		yyerror("allow-opts can only be specified for pass rules");
1827		problems++;
1828	}
1829	if (!r->af && (r->src.addr.addr_dyn != NULL ||
1830	    r->dst.addr.addr_dyn != NULL)) {
1831		yyerror("dynamic addresses require address family (inet/inet6)");
1832		problems++;
1833	}
1834	if (r->rule_flag & PFRULE_FRAGMENT && (r->src.port_op ||
1835	    r->dst.port_op || r->flagset || r->type || r->code)) {
1836		yyerror("fragments can be filtered only on IP header fields");
1837		problems++;
1838	}
1839	if (r->rule_flag & PFRULE_RETURNRST && r->proto != IPPROTO_TCP) {
1840		yyerror("return-rst can only be applied to TCP rules");
1841		problems++;
1842	}
1843	if (r->action == PF_DROP && r->keep_state) {
1844		yyerror("keep state on block rules doesn't make sense");
1845		problems++;
1846	}
1847	return (-problems);
1848}
1849
1850int
1851nat_consistent(struct pf_nat *r)
1852{
1853	int problems = 0;
1854
1855	if (!r->af && (r->raddr.addr_dyn != NULL)) {
1856		yyerror("dynamic addresses require address family (inet/inet6)");
1857		problems++;
1858	}
1859	return (-problems);
1860}
1861
1862int
1863rdr_consistent(struct pf_rdr *r)
1864{
1865	int problems = 0;
1866
1867	if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP &&
1868	    (r->dport || r->dport2 || r->rport)) {
1869		yyerror("port only applies to tcp/udp");
1870		problems++;
1871	}
1872	if (!r->af && (r->saddr.addr_dyn != NULL ||
1873	    r->daddr.addr_dyn != NULL || r->raddr.addr_dyn != NULL)) {
1874		yyerror("dynamic addresses require address family (inet/inet6)");
1875		problems++;
1876	}
1877	return (-problems);
1878}
1879
1880struct keywords {
1881	const char	*k_name;
1882	int	 k_val;
1883};
1884
1885/* macro gore, but you should've seen the prior indentation nightmare... */
1886
1887#define FREE_LIST(T,r) \
1888	do { \
1889		T *p, *n = r; \
1890		while (n != NULL) { \
1891			p = n; \
1892			n = n->next; \
1893			free(p); \
1894		} \
1895	} while (0)
1896
1897#define LOOP_THROUGH(T,n,r,C) \
1898	do { \
1899		T *n; \
1900		if (r == NULL) { \
1901			r = calloc(1, sizeof(T)); \
1902			if (r == NULL) \
1903				err(1, "LOOP: calloc"); \
1904			r->next = NULL; \
1905		} \
1906		n = r; \
1907		while (n != NULL) { \
1908			do { \
1909				C; \
1910			} while (0); \
1911			n = n->next; \
1912		} \
1913	} while (0)
1914
1915void
1916expand_label_addr(const char *name, char *label, u_int8_t af,
1917    struct node_host *host)
1918{
1919	char tmp[PF_RULE_LABEL_SIZE];
1920	char *p;
1921
1922	while ((p = strstr(label, name)) != NULL) {
1923		tmp[0] = 0;
1924
1925		strlcat(tmp, label, p-label+1);
1926
1927		if (host->not)
1928			strlcat(tmp, "! ", PF_RULE_LABEL_SIZE);
1929		if (host->addr.addr_dyn != NULL) {
1930			strlcat(tmp, "(", PF_RULE_LABEL_SIZE);
1931			strlcat(tmp, host->addr.addr.pfa.ifname,
1932			    PF_RULE_LABEL_SIZE);
1933			strlcat(tmp, ")", PF_RULE_LABEL_SIZE);
1934		} else if (!af || (PF_AZERO(&host->addr.addr, af) &&
1935		    PF_AZERO(&host->mask, af)))
1936			strlcat(tmp, "any", PF_RULE_LABEL_SIZE);
1937		else {
1938			char a[48];
1939			int bits;
1940
1941			if (inet_ntop(af, &host->addr.addr, a,
1942			    sizeof(a)) == NULL)
1943				strlcat(a, "?", sizeof(a));
1944			strlcat(tmp, a, PF_RULE_LABEL_SIZE);
1945			bits = unmask(&host->mask, af);
1946			a[0] = 0;
1947			if ((af == AF_INET && bits < 32) ||
1948			    (af == AF_INET6 && bits < 128))
1949				snprintf(a, sizeof(a), "/%u", bits);
1950			strlcat(tmp, a, PF_RULE_LABEL_SIZE);
1951		}
1952		strlcat(tmp, p+strlen(name), PF_RULE_LABEL_SIZE);
1953		strncpy(label, tmp, PF_RULE_LABEL_SIZE);
1954	}
1955}
1956
1957void
1958expand_label_port(const char *name, char *label, struct node_port *port)
1959{
1960	char tmp[PF_RULE_LABEL_SIZE];
1961	char *p;
1962	char a1[6], a2[6], op[13];
1963
1964	while ((p = strstr(label, name)) != NULL) {
1965		tmp[0] = 0;
1966
1967		strlcat(tmp, label, p-label+1);
1968
1969		snprintf(a1, sizeof(a1), "%u", ntohs(port->port[0]));
1970		snprintf(a2, sizeof(a2), "%u", ntohs(port->port[1]));
1971		if (!port->op)
1972			op[0] = 0;
1973		else if (port->op == PF_OP_IRG)
1974			snprintf(op, sizeof(op), "%s><%s", a1, a2);
1975		else if (port->op == PF_OP_XRG)
1976			snprintf(op, sizeof(op), "%s<>%s", a1, a2);
1977		else if (port->op == PF_OP_EQ)
1978			snprintf(op, sizeof(op), "%s", a1);
1979		else if (port->op == PF_OP_NE)
1980			snprintf(op, sizeof(op), "!=%s", a1);
1981		else if (port->op == PF_OP_LT)
1982			snprintf(op, sizeof(op), "<%s", a1);
1983		else if (port->op == PF_OP_LE)
1984			snprintf(op, sizeof(op), "<=%s", a1);
1985		else if (port->op == PF_OP_GT)
1986			snprintf(op, sizeof(op), ">%s", a1);
1987		else if (port->op == PF_OP_GE)
1988			snprintf(op, sizeof(op), ">=%s", a1);
1989		strlcat(tmp, op, PF_RULE_LABEL_SIZE);
1990		strlcat(tmp, p+strlen(name), PF_RULE_LABEL_SIZE);
1991		strncpy(label, tmp, PF_RULE_LABEL_SIZE);
1992	}
1993}
1994
1995void
1996expand_label_proto(const char *name, char *label, u_int8_t proto)
1997{
1998	char tmp[PF_RULE_LABEL_SIZE];
1999	char *p;
2000	struct protoent *pe;
2001
2002	while ((p = strstr(label, name)) != NULL) {
2003		tmp[0] = 0;
2004		strlcat(tmp, label, p-label+1);
2005		pe = getprotobynumber(proto);
2006		if (pe != NULL)
2007		    strlcat(tmp, pe->p_name, PF_RULE_LABEL_SIZE);
2008		else
2009		    snprintf(tmp+strlen(tmp), PF_RULE_LABEL_SIZE-strlen(tmp),
2010			"%u", proto);
2011		strlcat(tmp, p+strlen(name), PF_RULE_LABEL_SIZE);
2012		strncpy(label, tmp, PF_RULE_LABEL_SIZE);
2013	}
2014}
2015
2016void
2017expand_label_nr(const char *name, char *label)
2018{
2019	char tmp[PF_RULE_LABEL_SIZE];
2020	char *p;
2021
2022	while ((p = strstr(label, name)) != NULL) {
2023		tmp[0] = 0;
2024		strlcat(tmp, label, p-label+1);
2025		snprintf(tmp+strlen(tmp), PF_RULE_LABEL_SIZE-strlen(tmp),
2026		    "%u", pf->rule_nr);
2027		strlcat(tmp, p+strlen(name), PF_RULE_LABEL_SIZE);
2028		strncpy(label, tmp, PF_RULE_LABEL_SIZE);
2029	}
2030}
2031
2032void
2033expand_label(char *label, u_int8_t af,
2034    struct node_host *src_host, struct node_port *src_port,
2035    struct node_host *dst_host, struct node_port *dst_port,
2036    u_int8_t proto)
2037{
2038	expand_label_addr("$srcaddr", label, af, src_host);
2039	expand_label_addr("$dstaddr", label, af, dst_host);
2040	expand_label_port("$srcport", label, src_port);
2041	expand_label_port("$dstport", label, dst_port);
2042	expand_label_proto("$proto", label, proto);
2043	expand_label_nr("$nr", label);
2044}
2045
2046void
2047expand_rule(struct pf_rule *r,
2048    struct node_if *interfaces, struct node_proto *protos,
2049    struct node_host *src_hosts, struct node_port *src_ports,
2050    struct node_host *dst_hosts, struct node_port *dst_ports,
2051    struct node_uid *uids, struct node_gid *gids,
2052    struct node_icmp *icmp_types)
2053{
2054	int	af = r->af, nomatch = 0, added = 0;
2055	char	ifname[IF_NAMESIZE];
2056	char	label[PF_RULE_LABEL_SIZE];
2057	u_int8_t 	flags, flagset;
2058
2059	strlcpy(label, r->label, sizeof(label));
2060	flags = r->flags;
2061	flagset = r->flagset;
2062
2063	LOOP_THROUGH(struct node_if, interface, interfaces,
2064	LOOP_THROUGH(struct node_proto, proto, protos,
2065	LOOP_THROUGH(struct node_icmp, icmp_type, icmp_types,
2066	LOOP_THROUGH(struct node_host, src_host, src_hosts,
2067	LOOP_THROUGH(struct node_port, src_port, src_ports,
2068	LOOP_THROUGH(struct node_host, dst_host, dst_hosts,
2069	LOOP_THROUGH(struct node_port, dst_port, dst_ports,
2070	LOOP_THROUGH(struct node_uid, uid, uids,
2071	LOOP_THROUGH(struct node_gid, gid, gids,
2072
2073		r->af = af;
2074		/* for link-local IPv6 address, interface must match up */
2075		if ((r->af && src_host->af && r->af != src_host->af) ||
2076		    (r->af && dst_host->af && r->af != dst_host->af) ||
2077		    (src_host->af && dst_host->af &&
2078		    src_host->af != dst_host->af) ||
2079		    (src_host->ifindex && dst_host->ifindex &&
2080		    src_host->ifindex != dst_host->ifindex) ||
2081		    (src_host->ifindex && if_nametoindex(interface->ifname) &&
2082		    src_host->ifindex != if_nametoindex(interface->ifname)) ||
2083		    (dst_host->ifindex && if_nametoindex(interface->ifname) &&
2084		    dst_host->ifindex != if_nametoindex(interface->ifname)))
2085			continue;
2086		if (!r->af && src_host->af)
2087			r->af = src_host->af;
2088		else if (!r->af && dst_host->af)
2089			r->af = dst_host->af;
2090
2091		if (if_indextoname(src_host->ifindex, ifname))
2092			memcpy(r->ifname, ifname, sizeof(r->ifname));
2093		else if (if_indextoname(dst_host->ifindex, ifname))
2094			memcpy(r->ifname, ifname, sizeof(r->ifname));
2095		else
2096			memcpy(r->ifname, interface->ifname, sizeof(r->ifname));
2097
2098		strlcpy(r->label, label, PF_RULE_LABEL_SIZE);
2099		expand_label(r->label, r->af, src_host, src_port,
2100		    dst_host, dst_port, proto->proto);
2101		r->ifnot = interface->not;
2102		r->proto = proto->proto;
2103		r->src.addr = src_host->addr;
2104		r->src.mask = src_host->mask;
2105		r->src.noroute = src_host->noroute;
2106		r->src.not = src_host->not;
2107		r->src.port[0] = src_port->port[0];
2108		r->src.port[1] = src_port->port[1];
2109		r->src.port_op = src_port->op;
2110		r->dst.addr = dst_host->addr;
2111		r->dst.mask = dst_host->mask;
2112		r->dst.noroute = dst_host->noroute;
2113		r->dst.not = dst_host->not;
2114		r->dst.port[0] = dst_port->port[0];
2115		r->dst.port[1] = dst_port->port[1];
2116		r->dst.port_op = dst_port->op;
2117		r->uid.op = uid->op;
2118		r->uid.uid[0] = uid->uid[0];
2119		r->uid.uid[1] = uid->uid[1];
2120		r->gid.op = gid->op;
2121		r->gid.gid[0] = gid->gid[0];
2122		r->gid.gid[1] = gid->gid[1];
2123		r->type = icmp_type->type;
2124		r->code = icmp_type->code;
2125
2126		if (r->proto && r->proto != IPPROTO_TCP) {
2127			r->flags = 0;
2128			r->flagset = 0;
2129		} else {
2130			r->flags = flags;
2131			r->flagset = flagset;
2132		}
2133		if (icmp_type->proto && r->proto != icmp_type->proto) {
2134			yyerror("icmp-type mismatch");
2135			nomatch++;
2136		}
2137
2138		if (rule_consistent(r) < 0 || nomatch)
2139			yyerror("skipping filter rule due to errors");
2140		else {
2141			r->nr = pf->rule_nr++;
2142			pfctl_add_rule(pf, r);
2143			added++;
2144		}
2145
2146	)))))))));
2147
2148	FREE_LIST(struct node_if, interfaces);
2149	FREE_LIST(struct node_proto, protos);
2150	FREE_LIST(struct node_host, src_hosts);
2151	FREE_LIST(struct node_port, src_ports);
2152	FREE_LIST(struct node_host, dst_hosts);
2153	FREE_LIST(struct node_port, dst_ports);
2154	FREE_LIST(struct node_uid, uids);
2155	FREE_LIST(struct node_gid, gids);
2156	FREE_LIST(struct node_icmp, icmp_types);
2157
2158	if (!added)
2159		yyerror("rule expands to no valid combination");
2160}
2161
2162void
2163expand_nat(struct pf_nat *n,
2164    struct node_if *interfaces, struct node_proto *protos,
2165    struct node_host *src_hosts, struct node_port *src_ports,
2166    struct node_host *dst_hosts, struct node_port *dst_ports)
2167{
2168	char ifname[IF_NAMESIZE];
2169	int af = n->af, added = 0;
2170
2171	LOOP_THROUGH(struct node_if, interface, interfaces,
2172	LOOP_THROUGH(struct node_proto, proto, protos,
2173	LOOP_THROUGH(struct node_host, src_host, src_hosts,
2174	LOOP_THROUGH(struct node_port, src_port, src_ports,
2175	LOOP_THROUGH(struct node_host, dst_host, dst_hosts,
2176	LOOP_THROUGH(struct node_port, dst_port, dst_ports,
2177
2178		n->af = af;
2179		/* for link-local IPv6 address, interface must match up */
2180		if ((n->af && src_host->af && n->af != src_host->af) ||
2181		    (n->af && dst_host->af && n->af != dst_host->af) ||
2182		    (src_host->af && dst_host->af &&
2183		    src_host->af != dst_host->af) ||
2184		    (src_host->ifindex && dst_host->ifindex &&
2185		    src_host->ifindex != dst_host->ifindex) ||
2186		    (src_host->ifindex && if_nametoindex(interface->ifname) &&
2187		    src_host->ifindex != if_nametoindex(interface->ifname)) ||
2188		    (dst_host->ifindex && if_nametoindex(interface->ifname) &&
2189		    dst_host->ifindex != if_nametoindex(interface->ifname)))
2190			continue;
2191		if (!n->af && src_host->af)
2192			n->af = src_host->af;
2193		else if (!n->af && dst_host->af)
2194			n->af = dst_host->af;
2195
2196		if (if_indextoname(src_host->ifindex, ifname))
2197			memcpy(n->ifname, ifname, sizeof(n->ifname));
2198		else if (if_indextoname(dst_host->ifindex, ifname))
2199			memcpy(n->ifname, ifname, sizeof(n->ifname));
2200		else
2201			memcpy(n->ifname, interface->ifname, sizeof(n->ifname));
2202
2203		if (!n->af && n->raddr.addr_dyn != NULL) {
2204			yyerror("address family (inet/inet6) undefined");
2205			continue;
2206		}
2207
2208		n->ifnot = interface->not;
2209		n->proto = proto->proto;
2210		n->src.addr = src_host->addr;
2211		n->src.mask = src_host->mask;
2212		n->src.noroute = src_host->noroute;
2213		n->src.not = src_host->not;
2214		n->src.port[0] = src_port->port[0];
2215		n->src.port[1] = src_port->port[1];
2216		n->src.port_op = src_port->op;
2217		n->dst.addr = dst_host->addr;
2218		n->dst.mask = dst_host->mask;
2219		n->dst.noroute = dst_host->noroute;
2220		n->dst.not = dst_host->not;
2221		n->dst.port[0] = dst_port->port[0];
2222		n->dst.port[1] = dst_port->port[1];
2223		n->dst.port_op = dst_port->op;
2224
2225		if (nat_consistent(n) < 0)
2226			yyerror("skipping nat rule due to errors");
2227		else {
2228			pfctl_add_nat(pf, n);
2229			added++;
2230		}
2231
2232	))))));
2233
2234	FREE_LIST(struct node_if, interfaces);
2235	FREE_LIST(struct node_proto, protos);
2236	FREE_LIST(struct node_host, src_hosts);
2237	FREE_LIST(struct node_port, src_ports);
2238	FREE_LIST(struct node_host, dst_hosts);
2239	FREE_LIST(struct node_port, dst_ports);
2240
2241	if (!added)
2242		yyerror("nat rule expands to no valid combinations");
2243}
2244
2245void
2246expand_rdr(struct pf_rdr *r, struct node_if *interfaces,
2247    struct node_proto *protos, struct node_host *src_hosts,
2248    struct node_host *dst_hosts)
2249{
2250	int af = r->af, added = 0;
2251	char ifname[IF_NAMESIZE];
2252
2253	LOOP_THROUGH(struct node_if, interface, interfaces,
2254	LOOP_THROUGH(struct node_proto, proto, protos,
2255	LOOP_THROUGH(struct node_host, src_host, src_hosts,
2256	LOOP_THROUGH(struct node_host, dst_host, dst_hosts,
2257
2258		r->af = af;
2259		if ((r->af && src_host->af && r->af != src_host->af) ||
2260		    (r->af && dst_host->af && r->af != dst_host->af) ||
2261		    (src_host->af && dst_host->af &&
2262		    src_host->af != dst_host->af) ||
2263		    (src_host->ifindex && dst_host->ifindex &&
2264		    src_host->ifindex != dst_host->ifindex) ||
2265		    (src_host->ifindex && if_nametoindex(interface->ifname) &&
2266		    src_host->ifindex != if_nametoindex(interface->ifname)) ||
2267		    (dst_host->ifindex && if_nametoindex(interface->ifname) &&
2268		    dst_host->ifindex != if_nametoindex(interface->ifname)))
2269			continue;
2270
2271		if (!r->af && src_host->af)
2272			r->af = src_host->af;
2273		else if (!r->af && dst_host->af)
2274			r->af = dst_host->af;
2275		if (!r->af && (r->saddr.addr_dyn != NULL ||
2276		    r->daddr.addr_dyn != NULL || r->raddr.addr_dyn)) {
2277			yyerror("address family (inet/inet6) undefined");
2278			continue;
2279		}
2280
2281		if (if_indextoname(src_host->ifindex, ifname))
2282			memcpy(r->ifname, ifname, sizeof(r->ifname));
2283		else if (if_indextoname(dst_host->ifindex, ifname))
2284			memcpy(r->ifname, ifname, sizeof(r->ifname));
2285		else
2286			memcpy(r->ifname, interface->ifname, sizeof(r->ifname));
2287
2288		r->proto = proto->proto;
2289		r->ifnot = interface->not;
2290		r->saddr = src_host->addr;
2291		r->smask = src_host->mask;
2292		r->daddr = dst_host->addr;
2293		r->dmask = dst_host->mask;
2294
2295		if (rdr_consistent(r) < 0)
2296			yyerror("skipping rdr rule due to errors");
2297		else {
2298			pfctl_add_rdr(pf, r);
2299			added++;
2300		}
2301
2302	))));
2303
2304	FREE_LIST(struct node_if, interfaces);
2305	FREE_LIST(struct node_proto, protos);
2306	FREE_LIST(struct node_host, src_hosts);
2307	FREE_LIST(struct node_host, dst_hosts);
2308
2309	if (!added)
2310		yyerror("rdr rule expands to no valid combination");
2311}
2312
2313#undef FREE_LIST
2314#undef LOOP_THROUGH
2315
2316int
2317check_rulestate(int desired_state)
2318{
2319	if (rulestate > desired_state) {
2320		yyerror("Rules must be in order: options, normalization, "
2321		    "translation, filter");
2322		return (1);
2323	}
2324	rulestate = desired_state;
2325	return (0);
2326}
2327
2328int
2329kw_cmp(const void *k, const void *e)
2330{
2331	return (strcmp(k, ((const struct keywords *)e)->k_name));
2332}
2333
2334int
2335lookup(char *s)
2336{
2337	/* this has to be sorted always */
2338	static const struct keywords keywords[] = {
2339		{ "all",	ALL},
2340		{ "allow-opts",	ALLOWOPTS},
2341		{ "antispoof",	ANTISPOOF},
2342		{ "any",	ANY},
2343		{ "binat",	BINAT},
2344		{ "block",	BLOCK},
2345		{ "block-policy", BLOCKPOLICY},
2346		{ "code",	CODE},
2347		{ "crop",	FRAGCROP},
2348		{ "drop",	DROP},
2349		{ "drop-ovl",	FRAGDROP},
2350		{ "dup-to",	DUPTO},
2351		{ "fastroute",	FASTROUTE},
2352		{ "flags",	FLAGS},
2353		{ "for", 	FOR},
2354		{ "fragment",	FRAGMENT},
2355		{ "from",	FROM},
2356		{ "group",	GROUP},
2357		{ "icmp-type",	ICMPTYPE},
2358		{ "in",		IN},
2359		{ "inet",	INET},
2360		{ "inet6",	INET6},
2361		{ "ipv6-icmp-type", ICMP6TYPE},
2362		{ "keep",	KEEP},
2363		{ "label",	LABEL},
2364		{ "limit",	LIMIT},
2365		{ "log",	LOG},
2366		{ "log-all",	LOGALL},
2367		{ "loginterface", LOGINTERFACE},
2368		{ "max",	MAXIMUM},
2369		{ "max-mss",	MAXMSS},
2370		{ "min-ttl",	MINTTL},
2371		{ "modulate",	MODULATE},
2372		{ "nat",	NAT},
2373		{ "no",		NO},
2374		{ "no-df",	NODF},
2375		{ "no-route",	NOROUTE},
2376		{ "on",		ON},
2377		{ "optimization", OPTIMIZATION},
2378		{ "out",	OUT},
2379		{ "pass",	PASS},
2380		{ "port",	PORT},
2381		{ "proto",	PROTO},
2382		{ "quick",	QUICK},
2383		{ "rdr",	RDR},
2384		{ "reassemble",	FRAGNORM},
2385		{ "reply-to",	REPLYTO},
2386		{ "return",	RETURN},
2387		{ "return-icmp",RETURNICMP},
2388		{ "return-icmp6",RETURNICMP6},
2389		{ "return-rst",	RETURNRST},
2390		{ "route-to",	ROUTETO},
2391		{ "scrub",	SCRUB},
2392		{ "set",	SET},
2393		{ "state",	STATE},
2394		{ "timeout",	TIMEOUT},
2395		{ "to",		TO},
2396		{ "tos",	TOS},
2397		{ "ttl",	TTL},
2398		{ "user",	USER},
2399	};
2400	const struct keywords *p;
2401
2402	p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
2403	    sizeof(keywords[0]), kw_cmp);
2404
2405	if (p) {
2406		if (debug > 1)
2407			fprintf(stderr, "%s: %d\n", s, p->k_val);
2408		return (p->k_val);
2409	} else {
2410		if (debug > 1)
2411			fprintf(stderr, "string: %s\n", s);
2412		return (STRING);
2413	}
2414}
2415
2416#define MAXPUSHBACK	128
2417
2418char	*parsebuf;
2419int	parseindex;
2420char	pushback_buffer[MAXPUSHBACK];
2421int	pushback_index = 0;
2422
2423int
2424lgetc(FILE *fin)
2425{
2426	int c, next;
2427
2428	if (parsebuf) {
2429		/* Read character from the parsebuffer instead of input. */
2430		if (parseindex >= 0) {
2431			c = parsebuf[parseindex++];
2432			if (c != '\0')
2433				return (c);
2434			parsebuf = NULL;
2435		} else
2436			parseindex++;
2437	}
2438
2439	if (pushback_index)
2440		return (pushback_buffer[--pushback_index]);
2441
2442	while ((c = getc(fin)) == '\\') {
2443		next = getc(fin);
2444		if (next != '\n') {
2445			if (isspace(next))
2446				yyerror("whitespace after \\");
2447			ungetc(next, fin);
2448			break;
2449		}
2450		yylval.lineno = lineno;
2451		lineno++;
2452	}
2453	if (c == '\t' || c == ' ') {
2454		/* Compress blanks to a single space. */
2455		do {
2456			c = getc(fin);
2457		} while (c == '\t' || c == ' ');
2458		ungetc(c, fin);
2459		c = ' ';
2460	}
2461
2462	return (c);
2463}
2464
2465int
2466lungetc(int c, FILE *fin)
2467{
2468	if (c == EOF)
2469		return (EOF);
2470	if (parsebuf) {
2471		parseindex--;
2472		if (parseindex >= 0)
2473			return (c);
2474	}
2475	if (pushback_index < MAXPUSHBACK-1)
2476		return (pushback_buffer[pushback_index++] = c);
2477	else
2478		return (EOF);
2479}
2480
2481int
2482findeol(void)
2483{
2484	int c;
2485
2486	parsebuf = NULL;
2487	pushback_index = 0;
2488
2489	/* skip to either EOF or the first real EOL */
2490	while (1) {
2491		c = lgetc(fin);
2492		if (c == '\n') {
2493			lineno++;
2494			break;
2495		}
2496		if (c == EOF)
2497			break;
2498	}
2499	return (ERROR);
2500}
2501
2502int
2503yylex(void)
2504{
2505	char buf[8096], *p, *val;
2506	int endc, c, next;
2507	int token;
2508
2509top:
2510	p = buf;
2511	while ((c = lgetc(fin)) == ' ')
2512		;
2513
2514	yylval.lineno = lineno;
2515	if (c == '#')
2516		while ((c = lgetc(fin)) != '\n' && c != EOF)
2517			;
2518	if (c == '$' && parsebuf == NULL) {
2519		while (1) {
2520			if ((c = lgetc(fin)) == EOF)
2521				return (0);
2522			if (p + 1 >= buf + sizeof(buf) - 1) {
2523				yyerror("string too long");
2524				return (findeol());
2525			}
2526			if (isalnum(c) || c == '_') {
2527				*p++ = (char)c;
2528				continue;
2529			}
2530			*p = '\0';
2531			lungetc(c, fin);
2532			break;
2533		}
2534		val = symget(buf);
2535		if (val == NULL) {
2536			yyerror("macro '%s' not defined", buf);
2537			return (findeol());
2538		}
2539		parsebuf = val;
2540		parseindex = 0;
2541		goto top;
2542	}
2543
2544	switch (c) {
2545	case '\'':
2546	case '"':
2547		endc = c;
2548		while (1) {
2549			if ((c = lgetc(fin)) == EOF)
2550				return (0);
2551			if (c == endc) {
2552				*p = '\0';
2553				break;
2554			}
2555			if (c == '\n') {
2556				lineno++;
2557				continue;
2558			}
2559			if (p + 1 >= buf + sizeof(buf) - 1) {
2560				yyerror("string too long");
2561				return (findeol());
2562			}
2563			*p++ = (char)c;
2564		}
2565		yylval.v.string = strdup(buf);
2566		if (yylval.v.string == NULL)
2567			err(1, "yylex: strdup");
2568		return (STRING);
2569	case '=':
2570		yylval.v.i = PF_OP_EQ;
2571		return (PORTUNARY);
2572	case '!':
2573		next = lgetc(fin);
2574		if (next == '=') {
2575			yylval.v.i = PF_OP_NE;
2576			return (PORTUNARY);
2577		}
2578		lungetc(next, fin);
2579		break;
2580	case '<':
2581		next = lgetc(fin);
2582		if (next == '>') {
2583			yylval.v.i = PF_OP_XRG;
2584			return (PORTBINARY);
2585		} else  if (next == '=') {
2586			yylval.v.i = PF_OP_LE;
2587		} else {
2588			yylval.v.i = PF_OP_LT;
2589			lungetc(next, fin);
2590		}
2591		return (PORTUNARY);
2592		break;
2593	case '>':
2594		next = lgetc(fin);
2595		if (next == '<') {
2596			yylval.v.i = PF_OP_IRG;
2597			return (PORTBINARY);
2598		} else  if (next == '=') {
2599			yylval.v.i = PF_OP_GE;
2600		} else {
2601			yylval.v.i = PF_OP_GT;
2602			lungetc(next, fin);
2603		}
2604		return (PORTUNARY);
2605		break;
2606	case '-':
2607		next = lgetc(fin);
2608		if (next == '>')
2609			return (ARROW);
2610		lungetc(next, fin);
2611		break;
2612	}
2613
2614#define allowed_in_string(x) \
2615	(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
2616	x != '{' && x != '}' && x != '<' && x != '>' && \
2617	x != '!' && x != '=' && x != '/' && x != '#' && \
2618	x != ','))
2619
2620	if (isalnum(c) || c == ':') {
2621		do {
2622			*p++ = c;
2623			if ((unsigned)(p-buf) >= sizeof(buf)) {
2624				yyerror("string too long");
2625				return (findeol());
2626			}
2627		} while ((c = lgetc(fin)) != EOF && (allowed_in_string(c)));
2628		lungetc(c, fin);
2629		*p = '\0';
2630		token = lookup(buf);
2631		yylval.v.string = strdup(buf);
2632		if (yylval.v.string == NULL)
2633			err(1, "yylex: strdup");
2634		return (token);
2635	}
2636	if (c == '\n') {
2637		yylval.lineno = lineno;
2638		lineno++;
2639	}
2640	if (c == EOF)
2641		return (0);
2642	return (c);
2643}
2644
2645int
2646parse_rules(FILE *input, struct pfctl *xpf)
2647{
2648	struct sym *sym;
2649
2650	fin = input;
2651	pf = xpf;
2652	lineno = 1;
2653	errors = 0;
2654	rulestate = PFCTL_STATE_NONE;
2655	yyparse();
2656
2657	/* Check which macros have not been used. */
2658	for (sym = symhead; sym; sym = sym->next)
2659		if (!sym->used)
2660			fprintf(stderr, "warning: macro '%s' not used\n",
2661			    sym->nam);
2662
2663	return (errors ? -1 : 0);
2664}
2665
2666void
2667ipmask(struct pf_addr *m, u_int8_t b)
2668{
2669	int i, j = 0;
2670
2671	for (i = 0; i < 4; i++)
2672		m->addr32[i] = 0;
2673
2674	while (b >= 32) {
2675		m->addr32[j++] = 0xffffffff;
2676		b -= 32;
2677	}
2678	for (i = 31; i > 31-b; --i)
2679		m->addr32[j] |= (1 << i);
2680	if (b)
2681		m->addr32[j] = htonl(m->addr32[j]);
2682}
2683
2684/*
2685 * Over-designed efficiency is a French and German concept, so how about
2686 * we wait until they discover this ugliness and make it all fancy.
2687 */
2688int
2689symset(const char *nam, const char *val)
2690{
2691	struct sym *sym;
2692
2693	sym = calloc(1, sizeof(*sym));
2694	if (sym == NULL)
2695		return (-1);
2696	sym->nam = strdup(nam);
2697	if (sym->nam == NULL) {
2698		free(sym);
2699		return (-1);
2700	}
2701	sym->val = strdup(val);
2702	if (sym->val == NULL) {
2703		free(sym->nam);
2704		free(sym);
2705		return (-1);
2706	}
2707	sym->next = symhead;
2708	sym->used = 0;
2709	symhead = sym;
2710	return (0);
2711}
2712
2713char *
2714symget(const char *nam)
2715{
2716	struct sym *sym;
2717
2718	for (sym = symhead; sym; sym = sym->next)
2719		if (strcmp(nam, sym->nam) == 0) {
2720			sym->used = 1;
2721			return (sym->val);
2722		}
2723	return (NULL);
2724}
2725
2726/* interface lookup routines */
2727
2728struct node_host *iftab;
2729
2730void
2731ifa_load(void)
2732{
2733	struct ifaddrs *ifap, *ifa;
2734	struct node_host *n = NULL, *h = NULL;
2735
2736	if (getifaddrs(&ifap) < 0)
2737		err(1, "getifaddrs");
2738
2739	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
2740		if (!(ifa->ifa_addr->sa_family == AF_INET ||
2741		    ifa->ifa_addr->sa_family == AF_INET6 ||
2742		    ifa->ifa_addr->sa_family == AF_LINK))
2743				continue;
2744		n = calloc(1, sizeof(struct node_host));
2745		if (n == NULL)
2746			err(1, "address: calloc");
2747		n->af = ifa->ifa_addr->sa_family;
2748		n->addr.addr_dyn = NULL;
2749		n->ifa_flags = ifa->ifa_flags;
2750#ifdef __KAME__
2751		if (n->af == AF_INET6 &&
2752		    IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr) &&
2753		    ((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_scope_id == 0) {
2754			struct sockaddr_in6 *sin6;
2755
2756			sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
2757			sin6->sin6_scope_id = sin6->sin6_addr.s6_addr[2] << 8 |
2758			    sin6->sin6_addr.s6_addr[3];
2759			sin6->sin6_addr.s6_addr[2] = 0;
2760			sin6->sin6_addr.s6_addr[3] = 0;
2761		}
2762#endif
2763		n->ifindex = 0;
2764		if (n->af == AF_INET) {
2765			memcpy(&n->addr.addr, &((struct sockaddr_in *)
2766			    ifa->ifa_addr)->sin_addr.s_addr,
2767			    sizeof(struct in_addr));
2768			memcpy(&n->mask, &((struct sockaddr_in *)
2769			    ifa->ifa_netmask)->sin_addr.s_addr,
2770			    sizeof(struct in_addr));
2771			if (ifa->ifa_broadaddr != NULL)
2772				memcpy(&n->bcast, &((struct sockaddr_in *)
2773				    ifa->ifa_broadaddr)->sin_addr.s_addr,
2774				    sizeof(struct in_addr));
2775		} else if (n->af == AF_INET6) {
2776			memcpy(&n->addr.addr, &((struct sockaddr_in6 *)
2777			    ifa->ifa_addr)->sin6_addr.s6_addr,
2778			    sizeof(struct in6_addr));
2779			memcpy(&n->mask, &((struct sockaddr_in6 *)
2780			    ifa->ifa_netmask)->sin6_addr.s6_addr,
2781			    sizeof(struct in6_addr));
2782			if (ifa->ifa_broadaddr != NULL)
2783				memcpy(&n->bcast, &((struct sockaddr_in6 *)
2784				    ifa->ifa_broadaddr)->sin6_addr.s6_addr,
2785				    sizeof(struct in6_addr));
2786			n->ifindex = ((struct sockaddr_in6 *)
2787			    ifa->ifa_addr)->sin6_scope_id;
2788		}
2789		if ((n->ifname = strdup(ifa->ifa_name)) == NULL) {
2790			yyerror("malloc failed");
2791			exit(1);
2792		}
2793		n->next = NULL;
2794		n->tail = n;
2795		if (h == NULL)
2796			h = n;
2797		else {
2798			h->tail->next = n;
2799			h->tail = n;
2800		}
2801	}
2802	iftab = h;
2803	freeifaddrs(ifap);
2804}
2805
2806struct node_host *
2807ifa_exists(char *ifa_name)
2808{
2809	struct node_host *n;
2810
2811	if (iftab == NULL)
2812		ifa_load();
2813
2814	for (n = iftab; n; n = n->next) {
2815		if (n->af == AF_LINK && !strncmp(n->ifname, ifa_name, IFNAMSIZ))
2816			return (n);
2817	}
2818	return (NULL);
2819}
2820
2821struct node_host *
2822ifa_lookup(char *ifa_name, enum pfctl_iflookup_mode mode)
2823{
2824	struct node_host *p = NULL, *h = NULL, *n = NULL;
2825	int return_all = 0;
2826
2827	if (!strncmp(ifa_name, "self", IFNAMSIZ))
2828		return_all = 1;
2829
2830	if (iftab == NULL)
2831		ifa_load();
2832
2833	for (p = iftab; p; p = p->next) {
2834		if (!((p->af == AF_INET || p->af == AF_INET6)
2835		    && (!strncmp(p->ifname, ifa_name, IFNAMSIZ) || return_all)))
2836			continue;
2837		if (mode == PFCTL_IFLOOKUP_BCAST && p->af != AF_INET)
2838			continue;
2839		if (mode == PFCTL_IFLOOKUP_NET && p->ifindex > 0)
2840			continue;
2841		n = calloc(1, sizeof(struct node_host));
2842		if (n == NULL)
2843			err(1, "address: calloc");
2844		n->af = p->af;
2845		n->addr.addr_dyn = NULL;
2846		if (mode == PFCTL_IFLOOKUP_BCAST) {
2847				memcpy(&n->addr.addr, &p->bcast,
2848				    sizeof(struct pf_addr));
2849		} else
2850			memcpy(&n->addr.addr, &p->addr.addr,
2851			    sizeof(struct pf_addr));
2852		if (mode == PFCTL_IFLOOKUP_NET)
2853			memcpy(&n->mask, &p->mask, sizeof(struct pf_addr));
2854		else {
2855			if (n->af == AF_INET)
2856				ipmask(&n->mask, 32);
2857			else
2858				ipmask(&n->mask, 128);
2859		}
2860		n->ifindex = p->ifindex;
2861
2862		n->next = NULL;
2863		n->tail = n;
2864		if (h == NULL)
2865			h = n;
2866		else {
2867			h->tail->next = n;
2868			h->tail = n;
2869		}
2870	}
2871	if (h == NULL && mode == PFCTL_IFLOOKUP_HOST) {
2872		yyerror("no IP address found for %s", ifa_name);
2873	}
2874	return (h);
2875}
2876
2877struct node_host *
2878ifa_pick_ip(struct node_host *nh, u_int8_t af)
2879{
2880	struct node_host *h, *n = NULL;
2881
2882	if (af == 0 && nh && nh->next) {
2883		yyerror("address family not given and translation address "
2884		    "expands to multiple IPs");
2885		return (NULL);
2886	}
2887	for (h = nh; h; h = h->next) {
2888		if (h->af == af || h->af == 0 || af == 0) {
2889			if (n != NULL) {
2890				yyerror("translation address expands to "
2891				    "multiple IPs of this address family");
2892				return (NULL);
2893			}
2894			n = h;
2895		}
2896	}
2897	if (n == NULL)
2898		yyerror("no translation address with matching address family "
2899		    "found.");
2900	else {
2901		n->next = NULL;
2902		n->tail = n;
2903	}
2904
2905	return (n);
2906}
2907
2908struct node_host *
2909host(char *s)
2910{
2911	struct node_host *h = NULL, *n;
2912	struct in_addr ina;
2913	struct addrinfo hints, *res0, *res;
2914	int error;
2915
2916	if (ifa_exists(s) || !strncmp(s, "self", IFNAMSIZ)) {
2917		/* interface with this name exists */
2918		if ((h = ifa_lookup(s, PFCTL_IFLOOKUP_HOST)) == NULL)
2919			return (NULL);
2920		else {
2921			h->next = NULL;
2922			h->tail = h;
2923			return (h);
2924		}
2925	}
2926
2927	if (inet_aton(s, &ina) == 1) {
2928		h = calloc(1, sizeof(struct node_host));
2929		if (h == NULL)
2930			err(1, "address: calloc");
2931		h->af = AF_INET;
2932		h->addr.addr_dyn = NULL;
2933		h->addr.addr.addr32[0] = ina.s_addr;
2934		ipmask(&h->mask, 32);
2935		h->next = NULL;
2936		h->tail = h;
2937		return (h);
2938	}
2939
2940	memset(&hints, 0, sizeof(hints));
2941	hints.ai_family = AF_INET6;
2942	hints.ai_socktype = SOCK_DGRAM; /*dummy*/
2943	hints.ai_flags = AI_NUMERICHOST;
2944	if (getaddrinfo(s, "0", &hints, &res) == 0) {
2945		n = calloc(1, sizeof(struct node_host));
2946		if (n == NULL)
2947			err(1, "address: calloc");
2948		n->af = AF_INET6;
2949		n->addr.addr_dyn = NULL;
2950		memcpy(&n->addr.addr,
2951		    &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr,
2952		    sizeof(n->addr.addr));
2953		n->ifindex = ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id;
2954		ipmask(&n->mask, 128);
2955		freeaddrinfo(res);
2956		n->next = NULL;
2957		n->tail = n;
2958		return (n);
2959	}
2960
2961	memset(&hints, 0, sizeof(hints));
2962	hints.ai_family = PF_UNSPEC;
2963	hints.ai_socktype = SOCK_STREAM; /* DUMMY */
2964	error = getaddrinfo(s, NULL, &hints, &res0);
2965	if (error) {
2966		yyerror("cannot resolve %s: %s",
2967		    s, gai_strerror(error));
2968		return (NULL);
2969	}
2970	for (res = res0; res; res = res->ai_next) {
2971		if (res->ai_family != AF_INET &&
2972		    res->ai_family != AF_INET6)
2973			continue;
2974		n = calloc(1, sizeof(struct node_host));
2975		if (n == NULL)
2976			err(1, "address: calloc");
2977		n->af = res->ai_family;
2978		n->addr.addr_dyn = NULL;
2979		if (res->ai_family == AF_INET) {
2980			memcpy(&n->addr.addr,
2981			    &((struct sockaddr_in *)res->ai_addr)->sin_addr.s_addr,
2982			    sizeof(struct in_addr));
2983			ipmask(&n->mask, 32);
2984		} else {
2985			memcpy(&n->addr.addr,
2986			    &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr.s6_addr,
2987			    sizeof(struct in6_addr));
2988			n->ifindex =
2989			    ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id;
2990			ipmask(&n->mask, 128);
2991		}
2992		n->next = NULL;
2993		n->tail = n;
2994		if (h == NULL)
2995			h = n;
2996		else {
2997			h->tail->next = n;
2998			h->tail = n;
2999		}
3000	}
3001	freeaddrinfo(res0);
3002	if (h == NULL) {
3003		yyerror("no IP address found for %s", s);
3004		return (NULL);
3005	}
3006	return (h);
3007}
3008
3009int
3010atoul(char *s, u_long *ulvalp)
3011{
3012	u_long ulval;
3013	char *ep;
3014
3015	errno = 0;
3016	ulval = strtoul(s, &ep, 0);
3017	if (s[0] == '\0' || *ep != '\0')
3018		return (-1);
3019	if (errno == ERANGE && ulval == ULONG_MAX)
3020		return (-1);
3021	*ulvalp = ulval;
3022	return (0);
3023}
3024
3025int
3026getservice(char *n)
3027{
3028	struct servent *s;
3029	u_long ulval;
3030
3031	if (atoul(n, &ulval) == 0) {
3032		if (ulval > 65535) {
3033			yyerror("illegal port value %d", ulval);
3034			return (-1);
3035		}
3036		return (htons(ulval));
3037	} else {
3038		s = getservbyname(n, "tcp");
3039		if (s == NULL)
3040			s = getservbyname(n, "udp");
3041		if (s == NULL) {
3042			yyerror("unknown port %s", n);
3043			return (-1);
3044		}
3045		return (s->s_port);
3046	}
3047}
3048
3049u_int16_t
3050parseicmpspec(char *w, u_int8_t af)
3051{
3052	const struct icmpcodeent *p;
3053	u_long ulval;
3054	u_int8_t icmptype;
3055
3056	if (af == AF_INET)
3057		icmptype = returnicmpdefault >> 8;
3058	else
3059		icmptype = returnicmp6default >> 8;
3060
3061	if (atoul(w, &ulval) == -1) {
3062		if ((p = geticmpcodebyname(icmptype, w, af)) == NULL) {
3063			yyerror("unknown icmp code %s", w);
3064			return (0);
3065		}
3066		ulval = p->code;
3067	}
3068	return (icmptype << 8 | ulval);
3069}
3070