]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/pf/pfctl/parse.y
This commit was generated by cvs2svn to compensate for changes in r169689,
[FreeBSD/FreeBSD.git] / contrib / pf / pfctl / parse.y
1 /*      $OpenBSD: parse.y,v 1.482 2005/03/07 13:20:03 henning Exp $     */
2
3 /*
4  * Copyright (c) 2001 Markus Friedl.  All rights reserved.
5  * Copyright (c) 2001 Daniel Hartmeier.  All rights reserved.
6  * Copyright (c) 2001 Theo de Raadt.  All rights reserved.
7  * Copyright (c) 2002,2003 Henning Brauer. All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 %{
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <net/if.h>
36 #include <netinet/in.h>
37 #include <netinet/in_systm.h>
38 #include <netinet/ip.h>
39 #include <netinet/ip_icmp.h>
40 #include <netinet/icmp6.h>
41 #include <net/pfvar.h>
42 #include <arpa/inet.h>
43 #include <altq/altq.h>
44 #include <altq/altq_cbq.h>
45 #include <altq/altq_priq.h>
46 #include <altq/altq_hfsc.h>
47
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <netdb.h>
51 #include <stdarg.h>
52 #include <errno.h>
53 #include <string.h>
54 #include <ctype.h>
55 #include <math.h>
56 #include <err.h>
57 #include <limits.h>
58 #include <pwd.h>
59 #include <grp.h>
60 #include <md5.h>
61
62 #include "pfctl_parser.h"
63 #include "pfctl.h"
64
65 #ifdef __FreeBSD__
66 #define HTONL(x)        (x) = htonl((__uint32_t)(x))
67 #endif
68
69 static struct pfctl     *pf = NULL;
70 static FILE             *fin = NULL;
71 static int               debug = 0;
72 static int               lineno = 1;
73 static int               errors = 0;
74 static int               rulestate = 0;
75 static u_int16_t         returnicmpdefault =
76                             (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT;
77 static u_int16_t         returnicmp6default =
78                             (ICMP6_DST_UNREACH << 8) | ICMP6_DST_UNREACH_NOPORT;
79 static int               blockpolicy = PFRULE_DROP;
80 static int               require_order = 1;
81 static int               default_statelock;
82
83 enum {
84         PFCTL_STATE_NONE,
85         PFCTL_STATE_OPTION,
86         PFCTL_STATE_SCRUB,
87         PFCTL_STATE_QUEUE,
88         PFCTL_STATE_NAT,
89         PFCTL_STATE_FILTER
90 };
91
92 struct node_proto {
93         u_int8_t                 proto;
94         struct node_proto       *next;
95         struct node_proto       *tail;
96 };
97
98 struct node_port {
99         u_int16_t                port[2];
100         u_int8_t                 op;
101         struct node_port        *next;
102         struct node_port        *tail;
103 };
104
105 struct node_uid {
106         uid_t                    uid[2];
107         u_int8_t                 op;
108         struct node_uid         *next;
109         struct node_uid         *tail;
110 };
111
112 struct node_gid {
113         gid_t                    gid[2];
114         u_int8_t                 op;
115         struct node_gid         *next;
116         struct node_gid         *tail;
117 };
118
119 struct node_icmp {
120         u_int8_t                 code;
121         u_int8_t                 type;
122         u_int8_t                 proto;
123         struct node_icmp        *next;
124         struct node_icmp        *tail;
125 };
126
127 enum    { PF_STATE_OPT_MAX, PF_STATE_OPT_NOSYNC, PF_STATE_OPT_SRCTRACK,
128             PF_STATE_OPT_MAX_SRC_STATES, PF_STATE_OPT_MAX_SRC_CONN,
129             PF_STATE_OPT_MAX_SRC_CONN_RATE, PF_STATE_OPT_MAX_SRC_NODES,
130             PF_STATE_OPT_OVERLOAD, PF_STATE_OPT_STATELOCK,
131             PF_STATE_OPT_TIMEOUT };
132
133 enum    { PF_SRCTRACK_NONE, PF_SRCTRACK, PF_SRCTRACK_GLOBAL, PF_SRCTRACK_RULE };
134
135 struct node_state_opt {
136         int                      type;
137         union {
138                 u_int32_t        max_states;
139                 u_int32_t        max_src_states;
140                 u_int32_t        max_src_conn;
141                 struct {
142                         u_int32_t       limit;
143                         u_int32_t       seconds;
144                 }                max_src_conn_rate;
145                 struct {
146                         u_int8_t        flush;
147                         char            tblname[PF_TABLE_NAME_SIZE];
148                 }                overload;
149                 u_int32_t        max_src_nodes;
150                 u_int8_t         src_track;
151                 u_int32_t        statelock;
152                 struct {
153                         int             number;
154                         u_int32_t       seconds;
155                 }                timeout;
156         }                        data;
157         struct node_state_opt   *next;
158         struct node_state_opt   *tail;
159 };
160
161 struct peer {
162         struct node_host        *host;
163         struct node_port        *port;
164 };
165
166 struct node_queue {
167         char                     queue[PF_QNAME_SIZE];
168         char                     parent[PF_QNAME_SIZE];
169         char                     ifname[IFNAMSIZ];
170         int                      scheduler;
171         struct node_queue       *next;
172         struct node_queue       *tail;
173 }       *queues = NULL;
174
175 struct node_qassign {
176         char            *qname;
177         char            *pqname;
178 };
179
180 struct filter_opts {
181         int                      marker;
182 #define FOM_FLAGS       0x01
183 #define FOM_ICMP        0x02
184 #define FOM_TOS         0x04
185 #define FOM_KEEP        0x08
186 #define FOM_SRCTRACK    0x10
187         struct node_uid         *uid;
188         struct node_gid         *gid;
189         struct {
190                 u_int8_t         b1;
191                 u_int8_t         b2;
192                 u_int16_t        w;
193                 u_int16_t        w2;
194         } flags;
195         struct node_icmp        *icmpspec;
196         u_int32_t                tos;
197         u_int32_t                prob;
198         struct {
199                 int                      action;
200                 struct node_state_opt   *options;
201         } keep;
202         int                      fragment;
203         int                      allowopts;
204         char                    *label;
205         struct node_qassign      queues;
206         char                    *tag;
207         char                    *match_tag;
208         u_int8_t                 match_tag_not;
209 } filter_opts;
210
211 struct antispoof_opts {
212         char                    *label;
213 } antispoof_opts;
214
215 struct scrub_opts {
216         int                     marker;
217 #define SOM_MINTTL      0x01
218 #define SOM_MAXMSS      0x02
219 #define SOM_FRAGCACHE   0x04
220         int                     nodf;
221         int                     minttl;
222         int                     maxmss;
223         int                     fragcache;
224         int                     randomid;
225         int                     reassemble_tcp;
226 } scrub_opts;
227
228 struct queue_opts {
229         int                     marker;
230 #define QOM_BWSPEC      0x01
231 #define QOM_SCHEDULER   0x02
232 #define QOM_PRIORITY    0x04
233 #define QOM_TBRSIZE     0x08
234 #define QOM_QLIMIT      0x10
235         struct node_queue_bw    queue_bwspec;
236         struct node_queue_opt   scheduler;
237         int                     priority;
238         int                     tbrsize;
239         int                     qlimit;
240 } queue_opts;
241
242 struct table_opts {
243         int                     flags;
244         int                     init_addr;
245         struct node_tinithead   init_nodes;
246 } table_opts;
247
248 struct pool_opts {
249         int                      marker;
250 #define POM_TYPE                0x01
251 #define POM_STICKYADDRESS       0x02
252         u_int8_t                 opts;
253         int                      type;
254         int                      staticport;
255         struct pf_poolhashkey   *key;
256
257 } pool_opts;
258
259
260 struct node_hfsc_opts   hfsc_opts;
261
262 int     yyerror(const char *, ...);
263 int     disallow_table(struct node_host *, const char *);
264 int     disallow_alias(struct node_host *, const char *);
265 int     rule_consistent(struct pf_rule *);
266 int     filter_consistent(struct pf_rule *);
267 int     nat_consistent(struct pf_rule *);
268 int     rdr_consistent(struct pf_rule *);
269 int     process_tabledef(char *, struct table_opts *);
270 int     yyparse(void);
271 void    expand_label_str(char *, size_t, const char *, const char *);
272 void    expand_label_if(const char *, char *, size_t, const char *);
273 void    expand_label_addr(const char *, char *, size_t, u_int8_t,
274             struct node_host *);
275 void    expand_label_port(const char *, char *, size_t, struct node_port *);
276 void    expand_label_proto(const char *, char *, size_t, u_int8_t);
277 void    expand_label_nr(const char *, char *, size_t);
278 void    expand_label(char *, size_t, const char *, u_int8_t, struct node_host *,
279             struct node_port *, struct node_host *, struct node_port *,
280             u_int8_t);
281 void    expand_rule(struct pf_rule *, struct node_if *, struct node_host *,
282             struct node_proto *, struct node_os*, struct node_host *,
283             struct node_port *, struct node_host *, struct node_port *,
284             struct node_uid *, struct node_gid *, struct node_icmp *,
285             const char *);
286 int     expand_altq(struct pf_altq *, struct node_if *, struct node_queue *,
287             struct node_queue_bw bwspec, struct node_queue_opt *);
288 int     expand_queue(struct pf_altq *, struct node_if *, struct node_queue *,
289             struct node_queue_bw, struct node_queue_opt *);
290 int     expand_skip_interface(struct node_if *);
291
292 int      check_rulestate(int);
293 int      kw_cmp(const void *, const void *);
294 int      lookup(char *);
295 int      lgetc(FILE *);
296 int      lungetc(int);
297 int      findeol(void);
298 int      yylex(void);
299 int      atoul(char *, u_long *);
300 int      getservice(char *);
301 int      rule_label(struct pf_rule *, char *);
302
303 TAILQ_HEAD(symhead, sym)         symhead = TAILQ_HEAD_INITIALIZER(symhead);
304 struct sym {
305         TAILQ_ENTRY(sym)         entries;
306         int                      used;
307         int                      persist;
308         char                    *nam;
309         char                    *val;
310 };
311
312
313 int      symset(const char *, const char *, int);
314 char    *symget(const char *);
315
316 void     decide_address_family(struct node_host *, sa_family_t *);
317 void     remove_invalid_hosts(struct node_host **, sa_family_t *);
318 int      invalid_redirect(struct node_host *, sa_family_t);
319 u_int16_t parseicmpspec(char *, sa_family_t);
320
321 TAILQ_HEAD(loadanchorshead, loadanchors)
322     loadanchorshead = TAILQ_HEAD_INITIALIZER(loadanchorshead);
323
324 struct loadanchors {
325         TAILQ_ENTRY(loadanchors)         entries;
326         char                            *anchorname;
327         char                            *filename;
328 };
329
330 typedef struct {
331         union {
332                 u_int32_t                number;
333                 int                      i;
334                 char                    *string;
335                 struct {
336                         u_int8_t         b1;
337                         u_int8_t         b2;
338                         u_int16_t        w;
339                         u_int16_t        w2;
340                 }                        b;
341                 struct range {
342                         int              a;
343                         int              b;
344                         int              t;
345                 }                        range;
346                 struct node_if          *interface;
347                 struct node_proto       *proto;
348                 struct node_icmp        *icmp;
349                 struct node_host        *host;
350                 struct node_os          *os;
351                 struct node_port        *port;
352                 struct node_uid         *uid;
353                 struct node_gid         *gid;
354                 struct node_state_opt   *state_opt;
355                 struct peer              peer;
356                 struct {
357                         struct peer      src, dst;
358                         struct node_os  *src_os;
359                 }                        fromto;
360                 struct {
361                         struct node_host        *host;
362                         u_int8_t                 rt;
363                         u_int8_t                 pool_opts;
364                         sa_family_t              af;
365                         struct pf_poolhashkey   *key;
366                 }                        route;
367                 struct redirection {
368                         struct node_host        *host;
369                         struct range             rport;
370                 }                       *redirection;
371                 struct {
372                         int                      action;
373                         struct node_state_opt   *options;
374                 }                        keep_state;
375                 struct {
376                         u_int8_t         log;
377                         u_int8_t         quick;
378                 }                        logquick;
379                 struct {
380                         int              neg;
381                         char            *name;
382                 }                        tagged;
383                 struct pf_poolhashkey   *hashkey;
384                 struct node_queue       *queue;
385                 struct node_queue_opt    queue_options;
386                 struct node_queue_bw     queue_bwspec;
387                 struct node_qassign      qassign;
388                 struct filter_opts       filter_opts;
389                 struct antispoof_opts    antispoof_opts;
390                 struct queue_opts        queue_opts;
391                 struct scrub_opts        scrub_opts;
392                 struct table_opts        table_opts;
393                 struct pool_opts         pool_opts;
394                 struct node_hfsc_opts    hfsc_opts;
395         } v;
396         int lineno;
397 } YYSTYPE;
398
399 #define DYNIF_MULTIADDR(addr) ((addr).type == PF_ADDR_DYNIFTL && \
400         (!((addr).iflags & PFI_AFLAG_NOALIAS) ||                 \
401         !isdigit((addr).v.ifname[strlen((addr).v.ifname)-1])))
402
403 %}
404
405 %token  PASS BLOCK SCRUB RETURN IN OS OUT LOG LOGALL QUICK ON FROM TO FLAGS
406 %token  RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE
407 %token  ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF
408 %token  MINTTL ERROR ALLOWOPTS FASTROUTE FILENAME ROUTETO DUPTO REPLYTO NO LABEL
409 %token  NOROUTE FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DROP TABLE
410 %token  REASSEMBLE FRAGDROP FRAGCROP ANCHOR NATANCHOR RDRANCHOR BINATANCHOR
411 %token  SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY RANDOMID
412 %token  REQUIREORDER SYNPROXY FINGERPRINTS NOSYNC DEBUG SKIP HOSTID
413 %token  ANTISPOOF FOR
414 %token  BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT PROBABILITY
415 %token  ALTQ CBQ PRIQ HFSC BANDWIDTH TBRSIZE LINKSHARE REALTIME UPPERLIMIT
416 %token  QUEUE PRIORITY QLIMIT
417 %token  LOAD
418 %token  STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE
419 %token  MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH
420 %token  TAGGED TAG IFBOUND GRBOUND FLOATING STATEPOLICY ROUTE
421 %token  <v.string>              STRING
422 %token  <v.i>                   PORTBINARY
423 %type   <v.interface>           interface if_list if_item_not if_item
424 %type   <v.number>              number icmptype icmp6type uid gid
425 %type   <v.number>              tos not yesno natpass
426 %type   <v.i>                   no dir log af fragcache sourcetrack flush
427 %type   <v.i>                   unaryop statelock
428 %type   <v.b>                   action nataction scrubaction
429 %type   <v.b>                   flags flag blockspec
430 %type   <v.range>               port rport
431 %type   <v.hashkey>             hashkey
432 %type   <v.proto>               proto proto_list proto_item
433 %type   <v.icmp>                icmpspec
434 %type   <v.icmp>                icmp_list icmp_item
435 %type   <v.icmp>                icmp6_list icmp6_item
436 %type   <v.fromto>              fromto
437 %type   <v.peer>                ipportspec from to
438 %type   <v.host>                ipspec xhost host dynaddr host_list
439 %type   <v.host>                redir_host_list redirspec
440 %type   <v.host>                route_host route_host_list routespec
441 %type   <v.os>                  os xos os_list
442 %type   <v.port>                portspec port_list port_item
443 %type   <v.uid>                 uids uid_list uid_item
444 %type   <v.gid>                 gids gid_list gid_item
445 %type   <v.route>               route
446 %type   <v.redirection>         redirection redirpool
447 %type   <v.string>              label string tag
448 %type   <v.keep_state>          keep
449 %type   <v.state_opt>           state_opt_spec state_opt_list state_opt_item
450 %type   <v.logquick>            logquick
451 %type   <v.interface>           antispoof_ifspc antispoof_iflst antispoof_if
452 %type   <v.qassign>             qname
453 %type   <v.queue>               qassign qassign_list qassign_item
454 %type   <v.queue_options>       scheduler
455 %type   <v.number>              cbqflags_list cbqflags_item
456 %type   <v.number>              priqflags_list priqflags_item
457 %type   <v.hfsc_opts>           hfscopts_list hfscopts_item hfsc_opts
458 %type   <v.queue_bwspec>        bandwidth
459 %type   <v.filter_opts>         filter_opts filter_opt filter_opts_l
460 %type   <v.antispoof_opts>      antispoof_opts antispoof_opt antispoof_opts_l
461 %type   <v.queue_opts>          queue_opts queue_opt queue_opts_l
462 %type   <v.scrub_opts>          scrub_opts scrub_opt scrub_opts_l
463 %type   <v.table_opts>          table_opts table_opt table_opts_l
464 %type   <v.pool_opts>           pool_opts pool_opt pool_opts_l
465 %type   <v.tagged>              tagged
466 %%
467
468 ruleset         : /* empty */
469                 | ruleset '\n'
470                 | ruleset option '\n'
471                 | ruleset scrubrule '\n'
472                 | ruleset natrule '\n'
473                 | ruleset binatrule '\n'
474                 | ruleset pfrule '\n'
475                 | ruleset anchorrule '\n'
476                 | ruleset loadrule '\n'
477                 | ruleset altqif '\n'
478                 | ruleset queuespec '\n'
479                 | ruleset varset '\n'
480                 | ruleset antispoof '\n'
481                 | ruleset tabledef '\n'
482                 | ruleset error '\n'            { errors++; }
483                 ;
484
485 option          : SET OPTIMIZATION STRING               {
486                         if (check_rulestate(PFCTL_STATE_OPTION)) {
487                                 free($3);
488                                 YYERROR;
489                         }
490                         if (pfctl_set_optimization(pf, $3) != 0) {
491                                 yyerror("unknown optimization %s", $3);
492                                 free($3);
493                                 YYERROR;
494                         }
495                         free ($3);
496                 }
497                 | SET TIMEOUT timeout_spec
498                 | SET TIMEOUT '{' timeout_list '}'
499                 | SET LIMIT limit_spec
500                 | SET LIMIT '{' limit_list '}'
501                 | SET LOGINTERFACE STRING               {
502                         if (check_rulestate(PFCTL_STATE_OPTION)) {
503                                 free($3);
504                                 YYERROR;
505                         }
506                         if (pfctl_set_logif(pf, $3) != 0) {
507                                 yyerror("error setting loginterface %s", $3);
508                                 free($3);
509                                 YYERROR;
510                         }
511                         free($3);
512                 }
513                 | SET HOSTID number {
514                         if ($3 == 0) {
515                                 yyerror("hostid must be non-zero");
516                                 YYERROR;
517                         }
518                         if (pfctl_set_hostid(pf, $3) != 0) {
519                                 yyerror("error setting hostid %08x", $3);
520                                 YYERROR;
521                         }
522                 }
523                 | SET BLOCKPOLICY DROP  {
524                         if (pf->opts & PF_OPT_VERBOSE)
525                                 printf("set block-policy drop\n");
526                         if (check_rulestate(PFCTL_STATE_OPTION))
527                                 YYERROR;
528                         blockpolicy = PFRULE_DROP;
529                 }
530                 | SET BLOCKPOLICY RETURN {
531                         if (pf->opts & PF_OPT_VERBOSE)
532                                 printf("set block-policy return\n");
533                         if (check_rulestate(PFCTL_STATE_OPTION))
534                                 YYERROR;
535                         blockpolicy = PFRULE_RETURN;
536                 }
537                 | SET REQUIREORDER yesno {
538                         if (pf->opts & PF_OPT_VERBOSE)
539                                 printf("set require-order %s\n",
540                                     $3 == 1 ? "yes" : "no");
541                         require_order = $3;
542                 }
543                 | SET FINGERPRINTS STRING {
544                         if (pf->opts & PF_OPT_VERBOSE)
545                                 printf("set fingerprints %s\n", $3);
546                         if (check_rulestate(PFCTL_STATE_OPTION)) {
547                                 free($3);
548                                 YYERROR;
549                         }
550                         if (!pf->anchor[0]) {
551                                 if (pfctl_file_fingerprints(pf->dev,
552                                     pf->opts, $3)) {
553                                         yyerror("error loading "
554                                             "fingerprints %s", $3);
555                                         free($3);
556                                         YYERROR;
557                                 }
558                         }
559                         free($3);
560                 }
561                 | SET STATEPOLICY statelock {
562                         if (pf->opts & PF_OPT_VERBOSE)
563                                 switch ($3) {
564                                 case 0:
565                                         printf("set state-policy floating\n");
566                                         break;
567                                 case PFRULE_IFBOUND:
568                                         printf("set state-policy if-bound\n");
569                                         break;
570                                 case PFRULE_GRBOUND:
571                                         printf("set state-policy "
572                                             "group-bound\n");
573                                         break;
574                                 }
575                         default_statelock = $3;
576                 }
577                 | SET DEBUG STRING {
578                         if (check_rulestate(PFCTL_STATE_OPTION)) {
579                                 free($3);
580                                 YYERROR;
581                         }
582                         if (pfctl_set_debug(pf, $3) != 0) {
583                                 yyerror("error setting debuglevel %s", $3);
584                                 free($3);
585                                 YYERROR;
586                         }
587                         free($3);
588                 }
589                 | SET SKIP interface {
590                         if (expand_skip_interface($3) != 0) {
591                                 yyerror("error setting skip interface(s)");
592                                 YYERROR;
593                         }
594                 }
595                 ;
596
597 string          : string STRING                         {
598                         if (asprintf(&$$, "%s %s", $1, $2) == -1)
599                                 err(1, "string: asprintf");
600                         free($1);
601                         free($2);
602                 }
603                 | STRING
604                 ;
605
606 varset          : STRING '=' string             {
607                         if (pf->opts & PF_OPT_VERBOSE)
608                                 printf("%s = \"%s\"\n", $1, $3);
609                         if (symset($1, $3, 0) == -1)
610                                 err(1, "cannot store variable %s", $1);
611                         free($1);
612                         free($3);
613                 }
614                 ;
615
616 anchorrule      : ANCHOR string dir interface af proto fromto filter_opts {
617                         struct pf_rule  r;
618
619                         if (check_rulestate(PFCTL_STATE_FILTER)) {
620                                 free($2);
621                                 YYERROR;
622                         }
623
624                         memset(&r, 0, sizeof(r));
625                         r.direction = $3;
626                         r.af = $5;
627                         r.prob = $8.prob;
628
629                         if ($8.match_tag)
630                                 if (strlcpy(r.match_tagname, $8.match_tag,
631                                     PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
632                                         yyerror("tag too long, max %u chars",
633                                             PF_TAG_NAME_SIZE - 1);
634                                         YYERROR;
635                                 }
636                         r.match_tag_not = $8.match_tag_not;
637
638                         decide_address_family($7.src.host, &r.af);
639                         decide_address_family($7.dst.host, &r.af);
640
641                         expand_rule(&r, $4, NULL, $6, $7.src_os,
642                             $7.src.host, $7.src.port, $7.dst.host, $7.dst.port,
643                             0, 0, 0, $2);
644                         free($2);
645                 }
646                 | NATANCHOR string interface af proto fromto {
647                         struct pf_rule  r;
648
649                         if (check_rulestate(PFCTL_STATE_NAT)) {
650                                 free($2);
651                                 YYERROR;
652                         }
653
654                         memset(&r, 0, sizeof(r));
655                         r.action = PF_NAT;
656                         r.af = $4;
657
658                         decide_address_family($6.src.host, &r.af);
659                         decide_address_family($6.dst.host, &r.af);
660
661                         expand_rule(&r, $3, NULL, $5, $6.src_os,
662                             $6.src.host, $6.src.port, $6.dst.host, $6.dst.port,
663                             0, 0, 0, $2);
664                         free($2);
665                 }
666                 | RDRANCHOR string interface af proto fromto {
667                         struct pf_rule  r;
668
669                         if (check_rulestate(PFCTL_STATE_NAT)) {
670                                 free($2);
671                                 YYERROR;
672                         }
673
674                         memset(&r, 0, sizeof(r));
675                         r.action = PF_RDR;
676                         r.af = $4;
677
678                         decide_address_family($6.src.host, &r.af);
679                         decide_address_family($6.dst.host, &r.af);
680
681                         if ($6.src.port != NULL) {
682                                 yyerror("source port parameter not supported"
683                                     " in rdr-anchor");
684                                 YYERROR;
685                         }
686                         if ($6.dst.port != NULL) {
687                                 if ($6.dst.port->next != NULL) {
688                                         yyerror("destination port list "
689                                             "expansion not supported in "
690                                             "rdr-anchor");
691                                         YYERROR;
692                                 } else if ($6.dst.port->op != PF_OP_EQ) {
693                                         yyerror("destination port operators"
694                                             " not supported in rdr-anchor");
695                                         YYERROR;
696                                 }
697                                 r.dst.port[0] = $6.dst.port->port[0];
698                                 r.dst.port[1] = $6.dst.port->port[1];
699                                 r.dst.port_op = $6.dst.port->op;
700                         }
701
702                         expand_rule(&r, $3, NULL, $5, $6.src_os,
703                             $6.src.host, $6.src.port, $6.dst.host, $6.dst.port,
704                             0, 0, 0, $2);
705                         free($2);
706                 }
707                 | BINATANCHOR string interface af proto fromto {
708                         struct pf_rule  r;
709
710                         if (check_rulestate(PFCTL_STATE_NAT)) {
711                                 free($2);
712                                 YYERROR;
713                         }
714
715                         memset(&r, 0, sizeof(r));
716                         r.action = PF_BINAT;
717                         r.af = $4;
718                         if ($5 != NULL) {
719                                 if ($5->next != NULL) {
720                                         yyerror("proto list expansion"
721                                             " not supported in binat-anchor");
722                                         YYERROR;
723                                 }
724                                 r.proto = $5->proto;
725                                 free($5);
726                         }
727
728                         if ($6.src.host != NULL || $6.src.port != NULL ||
729                             $6.dst.host != NULL || $6.dst.port != NULL) {
730                                 yyerror("fromto parameter not supported"
731                                     " in binat-anchor");
732                                 YYERROR;
733                         }
734
735                         decide_address_family($6.src.host, &r.af);
736                         decide_address_family($6.dst.host, &r.af);
737
738                         pfctl_add_rule(pf, &r, $2);
739                         free($2);
740                 }
741                 ;
742
743 loadrule        : LOAD ANCHOR string FROM string        {
744                         struct loadanchors      *loadanchor;
745
746                         if (strlen($3) >= MAXPATHLEN) {
747                                 yyerror("anchorname %s too long, max %u\n",
748                                     $3, MAXPATHLEN - 1);
749                                 free($3);
750                                 YYERROR;
751                         }
752                         loadanchor = calloc(1, sizeof(struct loadanchors));
753                         if (loadanchor == NULL)
754                                 err(1, "loadrule: calloc");
755                         if ((loadanchor->anchorname = strdup($3)) == NULL)
756                                 err(1, "loadrule: strdup");
757                         if ((loadanchor->filename = strdup($5)) == NULL)
758                                 err(1, "loadrule: strdup");
759
760                         TAILQ_INSERT_TAIL(&loadanchorshead, loadanchor,
761                             entries);
762
763                         free($3);
764                         free($5);
765                 };
766
767 scrubaction     : no SCRUB {
768                         $$.b2 = $$.w = 0;
769                         if ($1)
770                                 $$.b1 = PF_NOSCRUB;
771                         else
772                                 $$.b1 = PF_SCRUB;
773                 }
774                 ;
775
776 scrubrule       : scrubaction dir logquick interface af proto fromto scrub_opts
777                 {
778                         struct pf_rule  r;
779
780                         if (check_rulestate(PFCTL_STATE_SCRUB))
781                                 YYERROR;
782
783                         memset(&r, 0, sizeof(r));
784
785                         r.action = $1.b1;
786                         r.direction = $2;
787
788                         r.log = $3.log;
789                         if ($3.quick) {
790                                 yyerror("scrub rules do not support 'quick'");
791                                 YYERROR;
792                         }
793
794                         r.af = $5;
795                         if ($8.nodf)
796                                 r.rule_flag |= PFRULE_NODF;
797                         if ($8.randomid)
798                                 r.rule_flag |= PFRULE_RANDOMID;
799                         if ($8.reassemble_tcp) {
800                                 if (r.direction != PF_INOUT) {
801                                         yyerror("reassemble tcp rules can not "
802                                             "specify direction");
803                                         YYERROR;
804                                 }
805                                 r.rule_flag |= PFRULE_REASSEMBLE_TCP;
806                         }
807                         if ($8.minttl)
808                                 r.min_ttl = $8.minttl;
809                         if ($8.maxmss)
810                                 r.max_mss = $8.maxmss;
811                         if ($8.fragcache)
812                                 r.rule_flag |= $8.fragcache;
813
814                         expand_rule(&r, $4, NULL, $6, $7.src_os,
815                             $7.src.host, $7.src.port, $7.dst.host, $7.dst.port,
816                             NULL, NULL, NULL, "");
817                 }
818                 ;
819
820 scrub_opts      :       {
821                         bzero(&scrub_opts, sizeof scrub_opts);
822                 }
823                     scrub_opts_l
824                         { $$ = scrub_opts; }
825                 | /* empty */ {
826                         bzero(&scrub_opts, sizeof scrub_opts);
827                         $$ = scrub_opts;
828                 }
829                 ;
830
831 scrub_opts_l    : scrub_opts_l scrub_opt
832                 | scrub_opt
833                 ;
834
835 scrub_opt       : NODF  {
836                         if (scrub_opts.nodf) {
837                                 yyerror("no-df cannot be respecified");
838                                 YYERROR;
839                         }
840                         scrub_opts.nodf = 1;
841                 }
842                 | MINTTL number {
843                         if (scrub_opts.marker & SOM_MINTTL) {
844                                 yyerror("min-ttl cannot be respecified");
845                                 YYERROR;
846                         }
847                         if ($2 > 255) {
848                                 yyerror("illegal min-ttl value %d", $2);
849                                 YYERROR;
850                         }
851                         scrub_opts.marker |= SOM_MINTTL;
852                         scrub_opts.minttl = $2;
853                 }
854                 | MAXMSS number {
855                         if (scrub_opts.marker & SOM_MAXMSS) {
856                                 yyerror("max-mss cannot be respecified");
857                                 YYERROR;
858                         }
859                         if ($2 > 65535) {
860                                 yyerror("illegal max-mss value %d", $2);
861                                 YYERROR;
862                         }
863                         scrub_opts.marker |= SOM_MAXMSS;
864                         scrub_opts.maxmss = $2;
865                 }
866                 | fragcache {
867                         if (scrub_opts.marker & SOM_FRAGCACHE) {
868                                 yyerror("fragcache cannot be respecified");
869                                 YYERROR;
870                         }
871                         scrub_opts.marker |= SOM_FRAGCACHE;
872                         scrub_opts.fragcache = $1;
873                 }
874                 | REASSEMBLE STRING {
875                         if (strcasecmp($2, "tcp") != 0) {
876                                 yyerror("scrub reassemble supports only tcp, "
877                                     "not '%s'", $2);
878                                 free($2);
879                                 YYERROR;
880                         }
881                         free($2);
882                         if (scrub_opts.reassemble_tcp) {
883                                 yyerror("reassemble tcp cannot be respecified");
884                                 YYERROR;
885                         }
886                         scrub_opts.reassemble_tcp = 1;
887                 }
888                 | RANDOMID {
889                         if (scrub_opts.randomid) {
890                                 yyerror("random-id cannot be respecified");
891                                 YYERROR;
892                         }
893                         scrub_opts.randomid = 1;
894                 }
895                 ;
896
897 fragcache       : FRAGMENT REASSEMBLE   { $$ = 0; /* default */ }
898                 | FRAGMENT FRAGCROP     { $$ = PFRULE_FRAGCROP; }
899                 | FRAGMENT FRAGDROP     { $$ = PFRULE_FRAGDROP; }
900                 ;
901
902 antispoof       : ANTISPOOF logquick antispoof_ifspc af antispoof_opts {
903                         struct pf_rule           r;
904                         struct node_host        *h = NULL, *hh;
905                         struct node_if          *i, *j;
906
907                         if (check_rulestate(PFCTL_STATE_FILTER))
908                                 YYERROR;
909
910                         for (i = $3; i; i = i->next) {
911                                 bzero(&r, sizeof(r));
912
913                                 r.action = PF_DROP;
914                                 r.direction = PF_IN;
915                                 r.log = $2.log;
916                                 r.quick = $2.quick;
917                                 r.af = $4;
918                                 if (rule_label(&r, $5.label))
919                                         YYERROR;
920                                 j = calloc(1, sizeof(struct node_if));
921                                 if (j == NULL)
922                                         err(1, "antispoof: calloc");
923                                 if (strlcpy(j->ifname, i->ifname,
924                                     sizeof(j->ifname)) >= sizeof(j->ifname)) {
925                                         free(j);
926                                         yyerror("interface name too long");
927                                         YYERROR;
928                                 }
929                                 j->not = 1;
930                                 if (i->dynamic) {
931                                         h = calloc(1, sizeof(*h));
932                                         if (h == NULL)
933                                                 err(1, "address: calloc");
934                                         h->addr.type = PF_ADDR_DYNIFTL;
935                                         set_ipmask(h, 128);
936                                         if (strlcpy(h->addr.v.ifname, i->ifname,
937                                             sizeof(h->addr.v.ifname)) >=
938                                             sizeof(h->addr.v.ifname)) {
939                                                 free(h);
940                                                 yyerror(
941                                                     "interface name too long");
942                                                 YYERROR;
943                                         }
944                                         hh = malloc(sizeof(*hh));
945                                         if (hh == NULL)
946                                                  err(1, "address: malloc");
947                                         bcopy(h, hh, sizeof(*hh));
948                                         h->addr.iflags = PFI_AFLAG_NETWORK;
949                                 } else {
950                                         h = ifa_lookup(j->ifname,
951                                             PFI_AFLAG_NETWORK);
952                                         hh = NULL;
953                                 }
954
955                                 if (h != NULL)
956                                         expand_rule(&r, j, NULL, NULL, NULL, h,
957                                             NULL, NULL, NULL, NULL, NULL,
958                                             NULL, "");
959
960                                 if ((i->ifa_flags & IFF_LOOPBACK) == 0) {
961                                         bzero(&r, sizeof(r));
962
963                                         r.action = PF_DROP;
964                                         r.direction = PF_IN;
965                                         r.log = $2.log;
966                                         r.quick = $2.quick;
967                                         r.af = $4;
968                                         if (rule_label(&r, $5.label))
969                                                 YYERROR;
970                                         if (hh != NULL)
971                                                 h = hh;
972                                         else
973                                                 h = ifa_lookup(i->ifname, 0);
974                                         if (h != NULL)
975                                                 expand_rule(&r, NULL, NULL,
976                                                     NULL, NULL, h, NULL, NULL,
977                                                     NULL, NULL, NULL, NULL, "");
978                                 } else
979                                         free(hh);
980                         }
981                         free($5.label);
982                 }
983                 ;
984
985 antispoof_ifspc : FOR antispoof_if              { $$ = $2; }
986                 | FOR '{' antispoof_iflst '}'   { $$ = $3; }
987                 ;
988
989 antispoof_iflst : antispoof_if                          { $$ = $1; }
990                 | antispoof_iflst comma antispoof_if    {
991                         $1->tail->next = $3;
992                         $1->tail = $3;
993                         $$ = $1;
994                 }
995                 ;
996
997 antispoof_if  : if_item                         { $$ = $1; }
998                 | '(' if_item ')'               {
999                         $2->dynamic = 1;
1000                         $$ = $2;
1001                 }
1002                 ;
1003
1004 antispoof_opts  :       { bzero(&antispoof_opts, sizeof antispoof_opts); }
1005                     antispoof_opts_l
1006                         { $$ = antispoof_opts; }
1007                 | /* empty */   {
1008                         bzero(&antispoof_opts, sizeof antispoof_opts);
1009                         $$ = antispoof_opts;
1010                 }
1011                 ;
1012
1013 antispoof_opts_l        : antispoof_opts_l antispoof_opt
1014                         | antispoof_opt
1015                         ;
1016
1017 antispoof_opt   : label {
1018                         if (antispoof_opts.label) {
1019                                 yyerror("label cannot be redefined");
1020                                 YYERROR;
1021                         }
1022                         antispoof_opts.label = $1;
1023                 }
1024                 ;
1025
1026 not             : '!'           { $$ = 1; }
1027                 | /* empty */   { $$ = 0; }
1028                 ;
1029
1030 tabledef        : TABLE '<' STRING '>' table_opts {
1031                         struct node_host         *h, *nh;
1032                         struct node_tinit        *ti, *nti;
1033
1034                         if (strlen($3) >= PF_TABLE_NAME_SIZE) {
1035                                 yyerror("table name too long, max %d chars",
1036                                     PF_TABLE_NAME_SIZE - 1);
1037                                 free($3);
1038                                 YYERROR;
1039                         }
1040                         if (pf->loadopt & PFCTL_FLAG_TABLE)
1041                                 if (process_tabledef($3, &$5)) {
1042                                         free($3);
1043                                         YYERROR;
1044                                 }
1045                         free($3);
1046                         for (ti = SIMPLEQ_FIRST(&$5.init_nodes);
1047                             ti != SIMPLEQ_END(&$5.init_nodes); ti = nti) {
1048                                 if (ti->file)
1049                                         free(ti->file);
1050                                 for (h = ti->host; h != NULL; h = nh) {
1051                                         nh = h->next;
1052                                         free(h);
1053                                 }
1054                                 nti = SIMPLEQ_NEXT(ti, entries);
1055                                 free(ti);
1056                         }
1057                 }
1058                 ;
1059
1060 table_opts      :       {
1061                         bzero(&table_opts, sizeof table_opts);
1062                         SIMPLEQ_INIT(&table_opts.init_nodes);
1063                 }
1064                     table_opts_l
1065                         { $$ = table_opts; }
1066                 | /* empty */
1067                         {
1068                         bzero(&table_opts, sizeof table_opts);
1069                         SIMPLEQ_INIT(&table_opts.init_nodes);
1070                         $$ = table_opts;
1071                 }
1072                 ;
1073
1074 table_opts_l    : table_opts_l table_opt
1075                 | table_opt
1076                 ;
1077
1078 table_opt       : STRING                {
1079                         if (!strcmp($1, "const"))
1080                                 table_opts.flags |= PFR_TFLAG_CONST;
1081                         else if (!strcmp($1, "persist"))
1082                                 table_opts.flags |= PFR_TFLAG_PERSIST;
1083                         else {
1084                                 yyerror("invalid table option '%s'", $1);
1085                                 free($1);
1086                                 YYERROR;
1087                         }
1088                         free($1);
1089                 }
1090                 | '{' '}'               { table_opts.init_addr = 1; }
1091                 | '{' host_list '}'     {
1092                         struct node_host        *n;
1093                         struct node_tinit       *ti;
1094
1095                         for (n = $2; n != NULL; n = n->next) {
1096                                 switch (n->addr.type) {
1097                                 case PF_ADDR_ADDRMASK:
1098                                         continue; /* ok */
1099                                 case PF_ADDR_DYNIFTL:
1100                                         yyerror("dynamic addresses are not "
1101                                             "permitted inside tables");
1102                                         break;
1103                                 case PF_ADDR_TABLE:
1104                                         yyerror("tables cannot contain tables");
1105                                         break;
1106                                 case PF_ADDR_NOROUTE:
1107                                         yyerror("\"no-route\" is not permitted "
1108                                             "inside tables");
1109                                         break;
1110                                 default:
1111                                         yyerror("unknown address type %d",
1112                                             n->addr.type);
1113                                 }
1114                                 YYERROR;
1115                         }
1116                         if (!(ti = calloc(1, sizeof(*ti))))
1117                                 err(1, "table_opt: calloc");
1118                         ti->host = $2;
1119                         SIMPLEQ_INSERT_TAIL(&table_opts.init_nodes, ti,
1120                             entries);
1121                         table_opts.init_addr = 1;
1122                 }
1123                 | FILENAME STRING       {
1124                         struct node_tinit       *ti;
1125
1126                         if (!(ti = calloc(1, sizeof(*ti))))
1127                                 err(1, "table_opt: calloc");
1128                         ti->file = $2;
1129                         SIMPLEQ_INSERT_TAIL(&table_opts.init_nodes, ti,
1130                             entries);
1131                         table_opts.init_addr = 1;
1132                 }
1133                 ;
1134
1135 altqif          : ALTQ interface queue_opts QUEUE qassign {
1136                         struct pf_altq  a;
1137
1138                         if (check_rulestate(PFCTL_STATE_QUEUE))
1139                                 YYERROR;
1140
1141                         memset(&a, 0, sizeof(a));
1142                         if ($3.scheduler.qtype == ALTQT_NONE) {
1143                                 yyerror("no scheduler specified!");
1144                                 YYERROR;
1145                         }
1146                         a.scheduler = $3.scheduler.qtype;
1147                         a.qlimit = $3.qlimit;
1148                         a.tbrsize = $3.tbrsize;
1149                         if ($5 == NULL) {
1150                                 yyerror("no child queues specified");
1151                                 YYERROR;
1152                         }
1153                         if (expand_altq(&a, $2, $5, $3.queue_bwspec,
1154                             &$3.scheduler))
1155                                 YYERROR;
1156                 }
1157                 ;
1158
1159 queuespec       : QUEUE STRING interface queue_opts qassign {
1160                         struct pf_altq  a;
1161
1162                         if (check_rulestate(PFCTL_STATE_QUEUE)) {
1163                                 free($2);
1164                                 YYERROR;
1165                         }
1166
1167                         memset(&a, 0, sizeof(a));
1168
1169                         if (strlcpy(a.qname, $2, sizeof(a.qname)) >=
1170                             sizeof(a.qname)) {
1171                                 yyerror("queue name too long (max "
1172                                     "%d chars)", PF_QNAME_SIZE-1);
1173                                 free($2);
1174                                 YYERROR;
1175                         }
1176                         free($2);
1177                         if ($4.tbrsize) {
1178                                 yyerror("cannot specify tbrsize for queue");
1179                                 YYERROR;
1180                         }
1181                         if ($4.priority > 255) {
1182                                 yyerror("priority out of range: max 255");
1183                                 YYERROR;
1184                         }
1185                         a.priority = $4.priority;
1186                         a.qlimit = $4.qlimit;
1187                         a.scheduler = $4.scheduler.qtype;
1188                         if (expand_queue(&a, $3, $5, $4.queue_bwspec,
1189                             &$4.scheduler)) {
1190                                 yyerror("errors in queue definition");
1191                                 YYERROR;
1192                         }
1193                 }
1194                 ;
1195
1196 queue_opts      :       {
1197                         bzero(&queue_opts, sizeof queue_opts);
1198                         queue_opts.priority = DEFAULT_PRIORITY;
1199                         queue_opts.qlimit = DEFAULT_QLIMIT;
1200                         queue_opts.scheduler.qtype = ALTQT_NONE;
1201                         queue_opts.queue_bwspec.bw_percent = 100;
1202                 }
1203                     queue_opts_l
1204                         { $$ = queue_opts; }
1205                 | /* empty */ {
1206                         bzero(&queue_opts, sizeof queue_opts);
1207                         queue_opts.priority = DEFAULT_PRIORITY;
1208                         queue_opts.qlimit = DEFAULT_QLIMIT;
1209                         queue_opts.scheduler.qtype = ALTQT_NONE;
1210                         queue_opts.queue_bwspec.bw_percent = 100;
1211                         $$ = queue_opts;
1212                 }
1213                 ;
1214
1215 queue_opts_l    : queue_opts_l queue_opt
1216                 | queue_opt
1217                 ;
1218
1219 queue_opt       : BANDWIDTH bandwidth   {
1220                         if (queue_opts.marker & QOM_BWSPEC) {
1221                                 yyerror("bandwidth cannot be respecified");
1222                                 YYERROR;
1223                         }
1224                         queue_opts.marker |= QOM_BWSPEC;
1225                         queue_opts.queue_bwspec = $2;
1226                 }
1227                 | PRIORITY number       {
1228                         if (queue_opts.marker & QOM_PRIORITY) {
1229                                 yyerror("priority cannot be respecified");
1230                                 YYERROR;
1231                         }
1232                         if ($2 > 255) {
1233                                 yyerror("priority out of range: max 255");
1234                                 YYERROR;
1235                         }
1236                         queue_opts.marker |= QOM_PRIORITY;
1237                         queue_opts.priority = $2;
1238                 }
1239                 | QLIMIT number {
1240                         if (queue_opts.marker & QOM_QLIMIT) {
1241                                 yyerror("qlimit cannot be respecified");
1242                                 YYERROR;
1243                         }
1244                         if ($2 > 65535) {
1245                                 yyerror("qlimit out of range: max 65535");
1246                                 YYERROR;
1247                         }
1248                         queue_opts.marker |= QOM_QLIMIT;
1249                         queue_opts.qlimit = $2;
1250                 }
1251                 | scheduler     {
1252                         if (queue_opts.marker & QOM_SCHEDULER) {
1253                                 yyerror("scheduler cannot be respecified");
1254                                 YYERROR;
1255                         }
1256                         queue_opts.marker |= QOM_SCHEDULER;
1257                         queue_opts.scheduler = $1;
1258                 }
1259                 | TBRSIZE number        {
1260                         if (queue_opts.marker & QOM_TBRSIZE) {
1261                                 yyerror("tbrsize cannot be respecified");
1262                                 YYERROR;
1263                         }
1264                         if ($2 > 65535) {
1265                                 yyerror("tbrsize too big: max 65535");
1266                                 YYERROR;
1267                         }
1268                         queue_opts.marker |= QOM_TBRSIZE;
1269                         queue_opts.tbrsize = $2;
1270                 }
1271                 ;
1272
1273 bandwidth       : STRING {
1274                         double   bps;
1275                         char    *cp;
1276
1277                         $$.bw_percent = 0;
1278
1279                         bps = strtod($1, &cp);
1280                         if (cp != NULL) {
1281                                 if (!strcmp(cp, "b"))
1282                                         ; /* nothing */
1283                                 else if (!strcmp(cp, "Kb"))
1284                                         bps *= 1000;
1285                                 else if (!strcmp(cp, "Mb"))
1286                                         bps *= 1000 * 1000;
1287                                 else if (!strcmp(cp, "Gb"))
1288                                         bps *= 1000 * 1000 * 1000;
1289                                 else if (!strcmp(cp, "%")) {
1290                                         if (bps < 0 || bps > 100) {
1291                                                 yyerror("bandwidth spec "
1292                                                     "out of range");
1293                                                 free($1);
1294                                                 YYERROR;
1295                                         }
1296                                         $$.bw_percent = bps;
1297                                         bps = 0;
1298                                 } else {
1299                                         yyerror("unknown unit %s", cp);
1300                                         free($1);
1301                                         YYERROR;
1302                                 }
1303                         }
1304                         free($1);
1305                         $$.bw_absolute = (u_int32_t)bps;
1306                 }
1307                 ;
1308
1309 scheduler       : CBQ                           {
1310                         $$.qtype = ALTQT_CBQ;
1311                         $$.data.cbq_opts.flags = 0;
1312                 }
1313                 | CBQ '(' cbqflags_list ')'     {
1314                         $$.qtype = ALTQT_CBQ;
1315                         $$.data.cbq_opts.flags = $3;
1316                 }
1317                 | PRIQ                          {
1318                         $$.qtype = ALTQT_PRIQ;
1319                         $$.data.priq_opts.flags = 0;
1320                 }
1321                 | PRIQ '(' priqflags_list ')'   {
1322                         $$.qtype = ALTQT_PRIQ;
1323                         $$.data.priq_opts.flags = $3;
1324                 }
1325                 | HFSC                          {
1326                         $$.qtype = ALTQT_HFSC;
1327                         bzero(&$$.data.hfsc_opts,
1328                             sizeof(struct node_hfsc_opts));
1329                 }
1330                 | HFSC '(' hfsc_opts ')'        {
1331                         $$.qtype = ALTQT_HFSC;
1332                         $$.data.hfsc_opts = $3;
1333                 }
1334                 ;
1335
1336 cbqflags_list   : cbqflags_item                         { $$ |= $1; }
1337                 | cbqflags_list comma cbqflags_item     { $$ |= $3; }
1338                 ;
1339
1340 cbqflags_item   : STRING        {
1341                         if (!strcmp($1, "default"))
1342                                 $$ = CBQCLF_DEFCLASS;
1343                         else if (!strcmp($1, "borrow"))
1344                                 $$ = CBQCLF_BORROW;
1345                         else if (!strcmp($1, "red"))
1346                                 $$ = CBQCLF_RED;
1347                         else if (!strcmp($1, "ecn"))
1348                                 $$ = CBQCLF_RED|CBQCLF_ECN;
1349                         else if (!strcmp($1, "rio"))
1350                                 $$ = CBQCLF_RIO;
1351                         else {
1352                                 yyerror("unknown cbq flag \"%s\"", $1);
1353                                 free($1);
1354                                 YYERROR;
1355                         }
1356                         free($1);
1357                 }
1358                 ;
1359
1360 priqflags_list  : priqflags_item                        { $$ |= $1; }
1361                 | priqflags_list comma priqflags_item   { $$ |= $3; }
1362                 ;
1363
1364 priqflags_item  : STRING        {
1365                         if (!strcmp($1, "default"))
1366                                 $$ = PRCF_DEFAULTCLASS;
1367                         else if (!strcmp($1, "red"))
1368                                 $$ = PRCF_RED;
1369                         else if (!strcmp($1, "ecn"))
1370                                 $$ = PRCF_RED|PRCF_ECN;
1371                         else if (!strcmp($1, "rio"))
1372                                 $$ = PRCF_RIO;
1373                         else {
1374                                 yyerror("unknown priq flag \"%s\"", $1);
1375                                 free($1);
1376                                 YYERROR;
1377                         }
1378                         free($1);
1379                 }
1380                 ;
1381
1382 hfsc_opts       :       {
1383                                 bzero(&hfsc_opts,
1384                                     sizeof(struct node_hfsc_opts));
1385                         }
1386                     hfscopts_list                               {
1387                         $$ = hfsc_opts;
1388                 }
1389                 ;
1390
1391 hfscopts_list   : hfscopts_item
1392                 | hfscopts_list comma hfscopts_item
1393                 ;
1394
1395 hfscopts_item   : LINKSHARE bandwidth                           {
1396                         if (hfsc_opts.linkshare.used) {
1397                                 yyerror("linkshare already specified");
1398                                 YYERROR;
1399                         }
1400                         hfsc_opts.linkshare.m2 = $2;
1401                         hfsc_opts.linkshare.used = 1;
1402                 }
1403                 | LINKSHARE '(' bandwidth comma number comma bandwidth ')'
1404                     {
1405                         if (hfsc_opts.linkshare.used) {
1406                                 yyerror("linkshare already specified");
1407                                 YYERROR;
1408                         }
1409                         hfsc_opts.linkshare.m1 = $3;
1410                         hfsc_opts.linkshare.d = $5;
1411                         hfsc_opts.linkshare.m2 = $7;
1412                         hfsc_opts.linkshare.used = 1;
1413                 }
1414                 | REALTIME bandwidth                            {
1415                         if (hfsc_opts.realtime.used) {
1416                                 yyerror("realtime already specified");
1417                                 YYERROR;
1418                         }
1419                         hfsc_opts.realtime.m2 = $2;
1420                         hfsc_opts.realtime.used = 1;
1421                 }
1422                 | REALTIME '(' bandwidth comma number comma bandwidth ')'
1423                     {
1424                         if (hfsc_opts.realtime.used) {
1425                                 yyerror("realtime already specified");
1426                                 YYERROR;
1427                         }
1428                         hfsc_opts.realtime.m1 = $3;
1429                         hfsc_opts.realtime.d = $5;
1430                         hfsc_opts.realtime.m2 = $7;
1431                         hfsc_opts.realtime.used = 1;
1432                 }
1433                 | UPPERLIMIT bandwidth                          {
1434                         if (hfsc_opts.upperlimit.used) {
1435                                 yyerror("upperlimit already specified");
1436                                 YYERROR;
1437                         }
1438                         hfsc_opts.upperlimit.m2 = $2;
1439                         hfsc_opts.upperlimit.used = 1;
1440                 }
1441                 | UPPERLIMIT '(' bandwidth comma number comma bandwidth ')'
1442                     {
1443                         if (hfsc_opts.upperlimit.used) {
1444                                 yyerror("upperlimit already specified");
1445                                 YYERROR;
1446                         }
1447                         hfsc_opts.upperlimit.m1 = $3;
1448                         hfsc_opts.upperlimit.d = $5;
1449                         hfsc_opts.upperlimit.m2 = $7;
1450                         hfsc_opts.upperlimit.used = 1;
1451                 }
1452                 | STRING        {
1453                         if (!strcmp($1, "default"))
1454                                 hfsc_opts.flags |= HFCF_DEFAULTCLASS;
1455                         else if (!strcmp($1, "red"))
1456                                 hfsc_opts.flags |= HFCF_RED;
1457                         else if (!strcmp($1, "ecn"))
1458                                 hfsc_opts.flags |= HFCF_RED|HFCF_ECN;
1459                         else if (!strcmp($1, "rio"))
1460                                 hfsc_opts.flags |= HFCF_RIO;
1461                         else {
1462                                 yyerror("unknown hfsc flag \"%s\"", $1);
1463                                 free($1);
1464                                 YYERROR;
1465                         }
1466                         free($1);
1467                 }
1468                 ;
1469
1470 qassign         : /* empty */           { $$ = NULL; }
1471                 | qassign_item          { $$ = $1; }
1472                 | '{' qassign_list '}'  { $$ = $2; }
1473                 ;
1474
1475 qassign_list    : qassign_item                  { $$ = $1; }
1476                 | qassign_list comma qassign_item       {
1477                         $1->tail->next = $3;
1478                         $1->tail = $3;
1479                         $$ = $1;
1480                 }
1481                 ;
1482
1483 qassign_item    : STRING                        {
1484                         $$ = calloc(1, sizeof(struct node_queue));
1485                         if ($$ == NULL)
1486                                 err(1, "qassign_item: calloc");
1487                         if (strlcpy($$->queue, $1, sizeof($$->queue)) >=
1488                             sizeof($$->queue)) {
1489                                 yyerror("queue name '%s' too long (max "
1490                                     "%d chars)", $1, sizeof($$->queue)-1);
1491                                 free($1);
1492                                 free($$);
1493                                 YYERROR;
1494                         }
1495                         free($1);
1496                         $$->next = NULL;
1497                         $$->tail = $$;
1498                 }
1499                 ;
1500
1501 pfrule          : action dir logquick interface route af proto fromto
1502                     filter_opts
1503                 {
1504                         struct pf_rule           r;
1505                         struct node_state_opt   *o;
1506                         struct node_proto       *proto;
1507                         int                      srctrack = 0;
1508                         int                      statelock = 0;
1509
1510                         if (check_rulestate(PFCTL_STATE_FILTER))
1511                                 YYERROR;
1512
1513                         memset(&r, 0, sizeof(r));
1514
1515                         r.action = $1.b1;
1516                         switch ($1.b2) {
1517                         case PFRULE_RETURNRST:
1518                                 r.rule_flag |= PFRULE_RETURNRST;
1519                                 r.return_ttl = $1.w;
1520                                 break;
1521                         case PFRULE_RETURNICMP:
1522                                 r.rule_flag |= PFRULE_RETURNICMP;
1523                                 r.return_icmp = $1.w;
1524                                 r.return_icmp6 = $1.w2;
1525                                 break;
1526                         case PFRULE_RETURN:
1527                                 r.rule_flag |= PFRULE_RETURN;
1528                                 r.return_icmp = $1.w;
1529                                 r.return_icmp6 = $1.w2;
1530                                 break;
1531                         }
1532                         r.direction = $2;
1533                         r.log = $3.log;
1534                         r.quick = $3.quick;
1535                         r.prob = $9.prob;
1536
1537                         r.af = $6;
1538                         if ($9.tag)
1539                                 if (strlcpy(r.tagname, $9.tag,
1540                                     PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
1541                                         yyerror("tag too long, max %u chars",
1542                                             PF_TAG_NAME_SIZE - 1);
1543                                         YYERROR;
1544                                 }
1545                         if ($9.match_tag)
1546                                 if (strlcpy(r.match_tagname, $9.match_tag,
1547                                     PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
1548                                         yyerror("tag too long, max %u chars",
1549                                             PF_TAG_NAME_SIZE - 1);
1550                                         YYERROR;
1551                                 }
1552                         r.match_tag_not = $9.match_tag_not;
1553                         r.flags = $9.flags.b1;
1554                         r.flagset = $9.flags.b2;
1555                         if (rule_label(&r, $9.label))
1556                                 YYERROR;
1557                         free($9.label);
1558                         if ($9.flags.b1 || $9.flags.b2 || $8.src_os) {
1559                                 for (proto = $7; proto != NULL &&
1560                                     proto->proto != IPPROTO_TCP;
1561                                     proto = proto->next)
1562                                         ;       /* nothing */
1563                                 if (proto == NULL && $7 != NULL) {
1564                                         if ($9.flags.b1 || $9.flags.b2)
1565                                                 yyerror(
1566                                                     "flags only apply to tcp");
1567                                         if ($8.src_os)
1568                                                 yyerror(
1569                                                     "OS fingerprinting only "
1570                                                     "apply to tcp");
1571                                         YYERROR;
1572                                 }
1573 #if 0
1574                                 if (($9.flags.b1 & parse_flags("S")) == 0 &&
1575                                     $8.src_os) {
1576                                         yyerror("OS fingerprinting requires "
1577                                             "the SYN TCP flag (flags S/SA)");
1578                                         YYERROR;
1579                                 }
1580 #endif
1581                         }
1582
1583                         r.tos = $9.tos;
1584                         r.keep_state = $9.keep.action;
1585                         o = $9.keep.options;
1586                         while (o) {
1587                                 struct node_state_opt   *p = o;
1588
1589                                 switch (o->type) {
1590                                 case PF_STATE_OPT_MAX:
1591                                         if (r.max_states) {
1592                                                 yyerror("state option 'max' "
1593                                                     "multiple definitions");
1594                                                 YYERROR;
1595                                         }
1596                                         r.max_states = o->data.max_states;
1597                                         break;
1598                                 case PF_STATE_OPT_NOSYNC:
1599                                         if (r.rule_flag & PFRULE_NOSYNC) {
1600                                                 yyerror("state option 'sync' "
1601                                                     "multiple definitions");
1602                                                 YYERROR;
1603                                         }
1604                                         r.rule_flag |= PFRULE_NOSYNC;
1605                                         break;
1606                                 case PF_STATE_OPT_SRCTRACK:
1607                                         if (srctrack) {
1608                                                 yyerror("state option "
1609                                                     "'source-track' "
1610                                                     "multiple definitions");
1611                                                 YYERROR;
1612                                         }
1613                                         srctrack =  o->data.src_track;
1614                                         r.rule_flag |= PFRULE_SRCTRACK;
1615                                         break;
1616                                 case PF_STATE_OPT_MAX_SRC_STATES:
1617                                         if (r.max_src_states) {
1618                                                 yyerror("state option "
1619                                                     "'max-src-states' "
1620                                                     "multiple definitions");
1621                                                 YYERROR;
1622                                         }
1623                                         if (o->data.max_src_states == 0) {
1624                                                 yyerror("'max-src-states' must "
1625                                                     "be > 0");
1626                                                 YYERROR;
1627                                         }
1628                                         r.max_src_states =
1629                                             o->data.max_src_states;
1630                                         r.rule_flag |= PFRULE_SRCTRACK;
1631                                         break;
1632                                 case PF_STATE_OPT_OVERLOAD:
1633                                         if (r.overload_tblname[0]) {
1634                                                 yyerror("multiple 'overload' "
1635                                                     "table definitions");
1636                                                 YYERROR;
1637                                         }
1638                                         if (strlcpy(r.overload_tblname,
1639                                             o->data.overload.tblname,
1640                                             PF_TABLE_NAME_SIZE) >=
1641                                             PF_TABLE_NAME_SIZE) {
1642                                                 yyerror("state option: "
1643                                                     "strlcpy");
1644                                                 YYERROR;
1645                                         }
1646                                         r.flush = o->data.overload.flush;
1647                                         break;
1648                                 case PF_STATE_OPT_MAX_SRC_CONN:
1649                                         if (r.max_src_conn) {
1650                                                 yyerror("state option "
1651                                                     "'max-src-conn' "
1652                                                     "multiple definitions");
1653                                                 YYERROR;
1654                                         }
1655                                         if (o->data.max_src_conn == 0) {
1656                                                 yyerror("'max-src-conn' "
1657                                                     "must be > 0");
1658                                                 YYERROR;
1659                                         }
1660                                         r.max_src_conn =
1661                                             o->data.max_src_conn;
1662                                         r.rule_flag |= PFRULE_SRCTRACK |
1663                                             PFRULE_RULESRCTRACK;
1664                                         break;
1665                                 case PF_STATE_OPT_MAX_SRC_CONN_RATE:
1666                                         if (r.max_src_conn_rate.limit) {
1667                                                 yyerror("state option "
1668                                                     "'max-src-conn-rate' "
1669                                                     "multiple definitions");
1670                                                 YYERROR;
1671                                         }
1672                                         if (!o->data.max_src_conn_rate.limit ||
1673                                             !o->data.max_src_conn_rate.seconds) {
1674                                                 yyerror("'max-src-conn-rate' "
1675                                                     "values must be > 0");
1676                                                 YYERROR;
1677                                         }
1678                                         if (o->data.max_src_conn_rate.limit >
1679                                             PF_THRESHOLD_MAX) {
1680                                                 yyerror("'max-src-conn-rate' "
1681                                                    "maximum rate must be < %u",
1682                                                    PF_THRESHOLD_MAX);
1683                                                 YYERROR;
1684                                         }
1685                                         r.max_src_conn_rate.limit =
1686                                             o->data.max_src_conn_rate.limit;
1687                                         r.max_src_conn_rate.seconds =
1688                                             o->data.max_src_conn_rate.seconds;
1689                                         r.rule_flag |= PFRULE_SRCTRACK |
1690                                             PFRULE_RULESRCTRACK;
1691                                         break;
1692                                 case PF_STATE_OPT_MAX_SRC_NODES:
1693                                         if (r.max_src_nodes) {
1694                                                 yyerror("state option "
1695                                                     "'max-src-nodes' "
1696                                                     "multiple definitions");
1697                                                 YYERROR;
1698                                         }
1699                                         if (o->data.max_src_nodes == 0) {
1700                                                 yyerror("'max-src-nodes' must "
1701                                                     "be > 0");
1702                                                 YYERROR;
1703                                         }
1704                                         r.max_src_nodes =
1705                                             o->data.max_src_nodes;
1706                                         r.rule_flag |= PFRULE_SRCTRACK |
1707                                             PFRULE_RULESRCTRACK;
1708                                         break;
1709                                 case PF_STATE_OPT_STATELOCK:
1710                                         if (statelock) {
1711                                                 yyerror("state locking option: "
1712                                                     "multiple definitions");
1713                                                 YYERROR;
1714                                         }
1715                                         statelock = 1;
1716                                         r.rule_flag |= o->data.statelock;
1717                                         break;
1718                                 case PF_STATE_OPT_TIMEOUT:
1719                                         if (r.timeout[o->data.timeout.number]) {
1720                                                 yyerror("state timeout %s "
1721                                                     "multiple definitions",
1722                                                     pf_timeouts[o->data.
1723                                                     timeout.number].name);
1724                                                 YYERROR;
1725                                         }
1726                                         r.timeout[o->data.timeout.number] =
1727                                             o->data.timeout.seconds;
1728                                 }
1729                                 o = o->next;
1730                                 free(p);
1731                         }
1732                         if (r.rule_flag & PFRULE_SRCTRACK) {
1733                                 if (srctrack == PF_SRCTRACK_GLOBAL &&
1734                                     r.max_src_nodes) {
1735                                         yyerror("'max-src-nodes' is "
1736                                             "incompatible with "
1737                                             "'source-track global'");
1738                                         YYERROR;
1739                                 }
1740                                 if (srctrack == PF_SRCTRACK_GLOBAL &&
1741                                     r.max_src_conn) {
1742                                         yyerror("'max-src-conn' is "
1743                                             "incompatible with "
1744                                             "'source-track global'");
1745                                         YYERROR;
1746                                 }
1747                                 if (srctrack == PF_SRCTRACK_GLOBAL &&
1748                                     r.max_src_conn_rate.seconds) {
1749                                         yyerror("'max-src-conn-rate' is "
1750                                             "incompatible with "
1751                                             "'source-track global'");
1752                                         YYERROR;
1753                                 }
1754                                 if (r.timeout[PFTM_SRC_NODE] <
1755                                     r.max_src_conn_rate.seconds)
1756                                         r.timeout[PFTM_SRC_NODE] =
1757                                             r.max_src_conn_rate.seconds;
1758                                 r.rule_flag |= PFRULE_SRCTRACK;
1759                                 if (srctrack == PF_SRCTRACK_RULE)
1760                                         r.rule_flag |= PFRULE_RULESRCTRACK;
1761                         }
1762                         if (r.keep_state && !statelock)
1763                                 r.rule_flag |= default_statelock;
1764
1765                         if ($9.fragment)
1766                                 r.rule_flag |= PFRULE_FRAGMENT;
1767                         r.allow_opts = $9.allowopts;
1768
1769                         decide_address_family($8.src.host, &r.af);
1770                         decide_address_family($8.dst.host, &r.af);
1771
1772                         if ($5.rt) {
1773                                 if (!r.direction) {
1774                                         yyerror("direction must be explicit "
1775                                             "with rules that specify routing");
1776                                         YYERROR;
1777                                 }
1778                                 r.rt = $5.rt;
1779                                 r.rpool.opts = $5.pool_opts;
1780                                 if ($5.key != NULL)
1781                                         memcpy(&r.rpool.key, $5.key,
1782                                             sizeof(struct pf_poolhashkey));
1783                         }
1784                         if (r.rt && r.rt != PF_FASTROUTE) {
1785                                 decide_address_family($5.host, &r.af);
1786                                 remove_invalid_hosts(&$5.host, &r.af);
1787                                 if ($5.host == NULL) {
1788                                         yyerror("no routing address with "
1789                                             "matching address family found.");
1790                                         YYERROR;
1791                                 }
1792                                 if ((r.rpool.opts & PF_POOL_TYPEMASK) ==
1793                                     PF_POOL_NONE && ($5.host->next != NULL ||
1794                                     $5.host->addr.type == PF_ADDR_TABLE ||
1795                                     DYNIF_MULTIADDR($5.host->addr)))
1796                                         r.rpool.opts |= PF_POOL_ROUNDROBIN;
1797                                 if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
1798                                     PF_POOL_ROUNDROBIN &&
1799                                     disallow_table($5.host, "tables are only "
1800                                     "supported in round-robin routing pools"))
1801                                         YYERROR;
1802                                 if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
1803                                     PF_POOL_ROUNDROBIN &&
1804                                     disallow_alias($5.host, "interface (%s) "
1805                                     "is only supported in round-robin "
1806                                     "routing pools"))
1807                                         YYERROR;
1808                                 if ($5.host->next != NULL) {
1809                                         if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
1810                                             PF_POOL_ROUNDROBIN) {
1811                                                 yyerror("r.rpool.opts must "
1812                                                     "be PF_POOL_ROUNDROBIN");
1813                                                 YYERROR;
1814                                         }
1815                                 }
1816                         }
1817                         if ($9.queues.qname != NULL) {
1818                                 if (strlcpy(r.qname, $9.queues.qname,
1819                                     sizeof(r.qname)) >= sizeof(r.qname)) {
1820                                         yyerror("rule qname too long (max "
1821                                             "%d chars)", sizeof(r.qname)-1);
1822                                         YYERROR;
1823                                 }
1824                                 free($9.queues.qname);
1825                         }
1826                         if ($9.queues.pqname != NULL) {
1827                                 if (strlcpy(r.pqname, $9.queues.pqname,
1828                                     sizeof(r.pqname)) >= sizeof(r.pqname)) {
1829                                         yyerror("rule pqname too long (max "
1830                                             "%d chars)", sizeof(r.pqname)-1);
1831                                         YYERROR;
1832                                 }
1833                                 free($9.queues.pqname);
1834                         }
1835
1836                         expand_rule(&r, $4, $5.host, $7, $8.src_os,
1837                             $8.src.host, $8.src.port, $8.dst.host, $8.dst.port,
1838                             $9.uid, $9.gid, $9.icmpspec, "");
1839                 }
1840                 ;
1841
1842 filter_opts     :       { bzero(&filter_opts, sizeof filter_opts); }
1843                     filter_opts_l
1844                         { $$ = filter_opts; }
1845                 | /* empty */   {
1846                         bzero(&filter_opts, sizeof filter_opts);
1847                         $$ = filter_opts;
1848                 }
1849                 ;
1850
1851 filter_opts_l   : filter_opts_l filter_opt
1852                 | filter_opt
1853                 ;
1854
1855 filter_opt      : USER uids {
1856                         if (filter_opts.uid)
1857                                 $2->tail->next = filter_opts.uid;
1858                         filter_opts.uid = $2;
1859                 }
1860                 | GROUP gids {
1861                         if (filter_opts.gid)
1862                                 $2->tail->next = filter_opts.gid;
1863                         filter_opts.gid = $2;
1864                 }
1865                 | flags {
1866                         if (filter_opts.marker & FOM_FLAGS) {
1867                                 yyerror("flags cannot be redefined");
1868                                 YYERROR;
1869                         }
1870                         filter_opts.marker |= FOM_FLAGS;
1871                         filter_opts.flags.b1 |= $1.b1;
1872                         filter_opts.flags.b2 |= $1.b2;
1873                         filter_opts.flags.w |= $1.w;
1874                         filter_opts.flags.w2 |= $1.w2;
1875                 }
1876                 | icmpspec {
1877                         if (filter_opts.marker & FOM_ICMP) {
1878                                 yyerror("icmp-type cannot be redefined");
1879                                 YYERROR;
1880                         }
1881                         filter_opts.marker |= FOM_ICMP;
1882                         filter_opts.icmpspec = $1;
1883                 }
1884                 | tos {
1885                         if (filter_opts.marker & FOM_TOS) {
1886                                 yyerror("tos cannot be redefined");
1887                                 YYERROR;
1888                         }
1889                         filter_opts.marker |= FOM_TOS;
1890                         filter_opts.tos = $1;
1891                 }
1892                 | keep {
1893                         if (filter_opts.marker & FOM_KEEP) {
1894                                 yyerror("modulate or keep cannot be redefined");
1895                                 YYERROR;
1896                         }
1897                         filter_opts.marker |= FOM_KEEP;
1898                         filter_opts.keep.action = $1.action;
1899                         filter_opts.keep.options = $1.options;
1900                 }
1901                 | FRAGMENT {
1902                         filter_opts.fragment = 1;
1903                 }
1904                 | ALLOWOPTS {
1905                         filter_opts.allowopts = 1;
1906                 }
1907                 | label {
1908                         if (filter_opts.label) {
1909                                 yyerror("label cannot be redefined");
1910                                 YYERROR;
1911                         }
1912                         filter_opts.label = $1;
1913                 }
1914                 | qname {
1915                         if (filter_opts.queues.qname) {
1916                                 yyerror("queue cannot be redefined");
1917                                 YYERROR;
1918                         }
1919                         filter_opts.queues = $1;
1920                 }
1921                 | TAG string                            {
1922                         filter_opts.tag = $2;
1923                 }
1924                 | not TAGGED string                     {
1925                         filter_opts.match_tag = $3;
1926                         filter_opts.match_tag_not = $1;
1927                 }
1928                 | PROBABILITY STRING                    {
1929                         char    *e;
1930                         double   p = strtod($2, &e);
1931
1932                         if (*e == '%') {
1933                                 p *= 0.01;
1934                                 e++;
1935                         }
1936                         if (*e) {
1937                                 yyerror("invalid probability: %s", $2);
1938                                 free($2);
1939                                 YYERROR;
1940                         }
1941                         p = floor(p * (UINT_MAX+1.0) + 0.5);
1942                         if (p < 1.0 || p >= (UINT_MAX+1.0)) {
1943                                 yyerror("invalid probability: %s", $2);
1944                                 free($2);
1945                                 YYERROR;
1946                         }
1947                         filter_opts.prob = (u_int32_t)p;
1948                         free($2);
1949                 }
1950                 ;
1951
1952 action          : PASS                  { $$.b1 = PF_PASS; $$.b2 = $$.w = 0; }
1953                 | BLOCK blockspec       { $$ = $2; $$.b1 = PF_DROP; }
1954                 ;
1955
1956 blockspec       : /* empty */           {
1957                         $$.b2 = blockpolicy;
1958                         $$.w = returnicmpdefault;
1959                         $$.w2 = returnicmp6default;
1960                 }
1961                 | DROP                  {
1962                         $$.b2 = PFRULE_DROP;
1963                         $$.w = 0;
1964                         $$.w2 = 0;
1965                 }
1966                 | RETURNRST             {
1967                         $$.b2 = PFRULE_RETURNRST;
1968                         $$.w = 0;
1969                         $$.w2 = 0;
1970                 }
1971                 | RETURNRST '(' TTL number ')'  {
1972                         if ($4 > 255) {
1973                                 yyerror("illegal ttl value %d", $4);
1974                                 YYERROR;
1975                         }
1976                         $$.b2 = PFRULE_RETURNRST;
1977                         $$.w = $4;
1978                         $$.w2 = 0;
1979                 }
1980                 | RETURNICMP            {
1981                         $$.b2 = PFRULE_RETURNICMP;
1982                         $$.w = returnicmpdefault;
1983                         $$.w2 = returnicmp6default;
1984                 }
1985                 | RETURNICMP6           {
1986                         $$.b2 = PFRULE_RETURNICMP;
1987                         $$.w = returnicmpdefault;
1988                         $$.w2 = returnicmp6default;
1989                 }
1990                 | RETURNICMP '(' STRING ')'     {
1991                         $$.b2 = PFRULE_RETURNICMP;
1992                         if (!($$.w = parseicmpspec($3, AF_INET))) {
1993                                 free($3);
1994                                 YYERROR;
1995                         }
1996                         free($3);
1997                         $$.w2 = returnicmp6default;
1998                 }
1999                 | RETURNICMP6 '(' STRING ')'    {
2000                         $$.b2 = PFRULE_RETURNICMP;
2001                         $$.w = returnicmpdefault;
2002                         if (!($$.w2 = parseicmpspec($3, AF_INET6))) {
2003                                 free($3);
2004                                 YYERROR;
2005                         }
2006                         free($3);
2007                 }
2008                 | RETURNICMP '(' STRING comma STRING ')' {
2009                         $$.b2 = PFRULE_RETURNICMP;
2010                         if (!($$.w = parseicmpspec($3, AF_INET)) ||
2011                             !($$.w2 = parseicmpspec($5, AF_INET6))) {
2012                                 free($3);
2013                                 free($5);
2014                                 YYERROR;
2015                         }
2016                         free($3);
2017                         free($5);
2018                 }
2019                 | RETURN {
2020                         $$.b2 = PFRULE_RETURN;
2021                         $$.w = returnicmpdefault;
2022                         $$.w2 = returnicmp6default;
2023                 }
2024                 ;
2025
2026 dir             : /* empty */                   { $$ = 0; }
2027                 | IN                            { $$ = PF_IN; }
2028                 | OUT                           { $$ = PF_OUT; }
2029                 ;
2030
2031 logquick        : /* empty */                   { $$.log = 0; $$.quick = 0; }
2032                 | log                           { $$.log = $1; $$.quick = 0; }
2033                 | QUICK                         { $$.log = 0; $$.quick = 1; }
2034                 | log QUICK                     { $$.log = $1; $$.quick = 1; }
2035                 | QUICK log                     { $$.log = $2; $$.quick = 1; }
2036                 ;
2037
2038 log             : LOG                           { $$ = 1; }
2039                 | LOGALL                        { $$ = 2; }
2040                 ;
2041
2042 interface       : /* empty */                   { $$ = NULL; }
2043                 | ON if_item_not                { $$ = $2; }
2044                 | ON '{' if_list '}'            { $$ = $3; }
2045                 ;
2046
2047 if_list         : if_item_not                   { $$ = $1; }
2048                 | if_list comma if_item_not     {
2049                         $1->tail->next = $3;
2050                         $1->tail = $3;
2051                         $$ = $1;
2052                 }
2053                 ;
2054
2055 if_item_not     : not if_item                   { $$ = $2; $$->not = $1; }
2056                 ;
2057
2058 if_item         : STRING                        {
2059                         struct node_host        *n;
2060
2061                         $$ = calloc(1, sizeof(struct node_if));
2062                         if ($$ == NULL)
2063                                 err(1, "if_item: calloc");
2064                         if (strlcpy($$->ifname, $1, sizeof($$->ifname)) >=
2065                             sizeof($$->ifname)) {
2066                                 free($1);
2067                                 free($$);
2068                                 yyerror("interface name too long");
2069                                 YYERROR;
2070                         }
2071
2072                         if ((n = ifa_exists($1, 1)) != NULL)
2073                                 $$->ifa_flags = n->ifa_flags;
2074
2075                         free($1);
2076                         $$->not = 0;
2077                         $$->next = NULL;
2078                         $$->tail = $$;
2079                 }
2080                 ;
2081
2082 af              : /* empty */                   { $$ = 0; }
2083                 | INET                          { $$ = AF_INET; }
2084                 | INET6                         { $$ = AF_INET6; }
2085                 ;
2086
2087 proto           : /* empty */                   { $$ = NULL; }
2088                 | PROTO proto_item              { $$ = $2; }
2089                 | PROTO '{' proto_list '}'      { $$ = $3; }
2090                 ;
2091
2092 proto_list      : proto_item                    { $$ = $1; }
2093                 | proto_list comma proto_item   {
2094                         $1->tail->next = $3;
2095                         $1->tail = $3;
2096                         $$ = $1;
2097                 }
2098                 ;
2099
2100 proto_item      : STRING                        {
2101                         u_int8_t        pr;
2102                         u_long          ulval;
2103
2104                         if (atoul($1, &ulval) == 0) {
2105                                 if (ulval > 255) {
2106                                         yyerror("protocol outside range");
2107                                         free($1);
2108                                         YYERROR;
2109                                 }
2110                                 pr = (u_int8_t)ulval;
2111                         } else {
2112                                 struct protoent *p;
2113
2114                                 p = getprotobyname($1);
2115                                 if (p == NULL) {
2116                                         yyerror("unknown protocol %s", $1);
2117                                         free($1);
2118                                         YYERROR;
2119                                 }
2120                                 pr = p->p_proto;
2121                         }
2122                         free($1);
2123                         if (pr == 0) {
2124                                 yyerror("proto 0 cannot be used");
2125                                 YYERROR;
2126                         }
2127                         $$ = calloc(1, sizeof(struct node_proto));
2128                         if ($$ == NULL)
2129                                 err(1, "proto_item: calloc");
2130                         $$->proto = pr;
2131                         $$->next = NULL;
2132                         $$->tail = $$;
2133                 }
2134                 ;
2135
2136 fromto          : ALL                           {
2137                         $$.src.host = NULL;
2138                         $$.src.port = NULL;
2139                         $$.dst.host = NULL;
2140                         $$.dst.port = NULL;
2141                         $$.src_os = NULL;
2142                 }
2143                 | from os to                    {
2144                         $$.src = $1;
2145                         $$.src_os = $2;
2146                         $$.dst = $3;
2147                 }
2148                 ;
2149
2150 os              : /* empty */                   { $$ = NULL; }
2151                 | OS xos                        { $$ = $2; }
2152                 | OS '{' os_list '}'            { $$ = $3; }
2153                 ;
2154
2155 xos             : STRING {
2156                         $$ = calloc(1, sizeof(struct node_os));
2157                         if ($$ == NULL)
2158                                 err(1, "os: calloc");
2159                         $$->os = $1;
2160                         $$->tail = $$;
2161                 }
2162                 ;
2163
2164 os_list         : xos                           { $$ = $1; }
2165                 | os_list comma xos             {
2166                         $1->tail->next = $3;
2167                         $1->tail = $3;
2168                         $$ = $1;
2169                 }
2170                 ;
2171
2172 from            : /* empty */                   {
2173                         $$.host = NULL;
2174                         $$.port = NULL;
2175                 }
2176                 | FROM ipportspec               {
2177                         $$ = $2;
2178                 }
2179                 ;
2180
2181 to              : /* empty */                   {
2182                         $$.host = NULL;
2183                         $$.port = NULL;
2184                 }
2185                 | TO ipportspec         {
2186                         $$ = $2;
2187                 }
2188                 ;
2189
2190 ipportspec      : ipspec                        {
2191                         $$.host = $1;
2192                         $$.port = NULL;
2193                 }
2194                 | ipspec PORT portspec          {
2195                         $$.host = $1;
2196                         $$.port = $3;
2197                 }
2198                 | PORT portspec                 {
2199                         $$.host = NULL;
2200                         $$.port = $2;
2201                 }
2202                 ;
2203
2204 ipspec          : ANY                           { $$ = NULL; }
2205                 | xhost                         { $$ = $1; }
2206                 | '{' host_list '}'             { $$ = $2; }
2207                 ;
2208
2209 host_list       : xhost                         { $$ = $1; }
2210                 | host_list comma xhost         {
2211                         if ($3 == NULL)
2212                                 $$ = $1;
2213                         else if ($1 == NULL)
2214                                 $$ = $3;
2215                         else {
2216                                 $1->tail->next = $3;
2217                                 $1->tail = $3->tail;
2218                                 $$ = $1;
2219                         }
2220                 }
2221                 ;
2222
2223 xhost           : not host                      {
2224                         struct node_host        *n;
2225
2226                         for (n = $2; n != NULL; n = n->next)
2227                                 n->not = $1;
2228                         $$ = $2;
2229                 }
2230                 | NOROUTE                       {
2231                         $$ = calloc(1, sizeof(struct node_host));
2232                         if ($$ == NULL)
2233                                 err(1, "xhost: calloc");
2234                         $$->addr.type = PF_ADDR_NOROUTE;
2235                         $$->next = NULL;
2236                         $$->tail = $$;
2237                 }
2238                 ;
2239
2240 host            : STRING                        {
2241                         if (($$ = host($1)) == NULL)    {
2242                                 /* error. "any" is handled elsewhere */
2243                                 free($1);
2244                                 yyerror("could not parse host specification");
2245                                 YYERROR;
2246                         }
2247                         free($1);
2248
2249                 }
2250                 | STRING '/' number             {
2251                         char    *buf;
2252
2253                         if (asprintf(&buf, "%s/%u", $1, $3) == -1)
2254                                 err(1, "host: asprintf");
2255                         free($1);
2256                         if (($$ = host(buf)) == NULL)   {
2257                                 /* error. "any" is handled elsewhere */
2258                                 free(buf);
2259                                 yyerror("could not parse host specification");
2260                                 YYERROR;
2261                         }
2262                         free(buf);
2263                 }
2264                 | dynaddr
2265                 | dynaddr '/' number            {
2266                         struct node_host        *n;
2267
2268                         $$ = $1;
2269                         for (n = $1; n != NULL; n = n->next)
2270                                 set_ipmask(n, $3);
2271                 }
2272                 | '<' STRING '>'        {
2273                         if (strlen($2) >= PF_TABLE_NAME_SIZE) {
2274                                 yyerror("table name '%s' too long", $2);
2275                                 free($2);
2276                                 YYERROR;
2277                         }
2278                         $$ = calloc(1, sizeof(struct node_host));
2279                         if ($$ == NULL)
2280                                 err(1, "host: calloc");
2281                         $$->addr.type = PF_ADDR_TABLE;
2282                         if (strlcpy($$->addr.v.tblname, $2,
2283                             sizeof($$->addr.v.tblname)) >=
2284                             sizeof($$->addr.v.tblname))
2285                                 errx(1, "host: strlcpy");
2286                         free($2);
2287                         $$->next = NULL;
2288                         $$->tail = $$;
2289                 }
2290                 | ROUTE STRING          {
2291                         $$ = calloc(1, sizeof(struct node_host));
2292                         if ($$ == NULL) {
2293                                 free($2);
2294                                 err(1, "host: calloc");
2295                         }
2296                         $$->addr.type = PF_ADDR_RTLABEL;
2297                         if (strlcpy($$->addr.v.rtlabelname, $2,
2298                             sizeof($$->addr.v.rtlabelname)) >=
2299                             sizeof($$->addr.v.rtlabelname)) {
2300                                 yyerror("route label too long, max %u chars",
2301                                     sizeof($$->addr.v.rtlabelname) - 1);
2302                                 free($2);
2303                                 free($$);
2304                                 YYERROR;
2305                         }
2306                         $$->next = NULL;
2307                         $$->tail = $$;
2308                         free($2);
2309                 }
2310                 ;
2311
2312 number          : STRING                        {
2313                         u_long  ulval;
2314
2315                         if (atoul($1, &ulval) == -1) {
2316                                 yyerror("%s is not a number", $1);
2317                                 free($1);
2318                                 YYERROR;
2319                         } else
2320                                 $$ = ulval;
2321                         free($1);
2322                 }
2323                 ;
2324
2325 dynaddr         : '(' STRING ')'                {
2326                         int      flags = 0;
2327                         char    *p, *op;
2328
2329                         op = $2;
2330                         if (!isalpha(op[0])) {
2331                                 yyerror("invalid interface name '%s'", op);
2332                                 free(op);
2333                                 YYERROR;
2334                         }
2335                         while ((p = strrchr($2, ':')) != NULL) {
2336                                 if (!strcmp(p+1, "network"))
2337                                         flags |= PFI_AFLAG_NETWORK;
2338                                 else if (!strcmp(p+1, "broadcast"))
2339                                         flags |= PFI_AFLAG_BROADCAST;
2340                                 else if (!strcmp(p+1, "peer"))
2341                                         flags |= PFI_AFLAG_PEER;
2342                                 else if (!strcmp(p+1, "0"))
2343                                         flags |= PFI_AFLAG_NOALIAS;
2344                                 else {
2345                                         yyerror("interface %s has bad modifier",
2346                                             $2);
2347                                         free(op);
2348                                         YYERROR;
2349                                 }
2350                                 *p = '\0';
2351                         }
2352                         if (flags & (flags - 1) & PFI_AFLAG_MODEMASK) {
2353                                 free(op);
2354                                 yyerror("illegal combination of "
2355                                     "interface modifiers");
2356                                 YYERROR;
2357                         }
2358                         $$ = calloc(1, sizeof(struct node_host));
2359                         if ($$ == NULL)
2360                                 err(1, "address: calloc");
2361                         $$->af = 0;
2362                         set_ipmask($$, 128);
2363                         $$->addr.type = PF_ADDR_DYNIFTL;
2364                         $$->addr.iflags = flags;
2365                         if (strlcpy($$->addr.v.ifname, $2,
2366                             sizeof($$->addr.v.ifname)) >=
2367                             sizeof($$->addr.v.ifname)) {
2368                                 free(op);
2369                                 free($$);
2370                                 yyerror("interface name too long");
2371                                 YYERROR;
2372                         }
2373                         free(op);
2374                         $$->next = NULL;
2375                         $$->tail = $$;
2376                 }
2377                 ;
2378
2379 portspec        : port_item                     { $$ = $1; }
2380                 | '{' port_list '}'             { $$ = $2; }
2381                 ;
2382
2383 port_list       : port_item                     { $$ = $1; }
2384                 | port_list comma port_item     {
2385                         $1->tail->next = $3;
2386                         $1->tail = $3;
2387                         $$ = $1;
2388                 }
2389                 ;
2390
2391 port_item       : port                          {
2392                         $$ = calloc(1, sizeof(struct node_port));
2393                         if ($$ == NULL)
2394                                 err(1, "port_item: calloc");
2395                         $$->port[0] = $1.a;
2396                         $$->port[1] = $1.b;
2397                         if ($1.t)
2398                                 $$->op = PF_OP_RRG;
2399                         else
2400                                 $$->op = PF_OP_EQ;
2401                         $$->next = NULL;
2402                         $$->tail = $$;
2403                 }
2404                 | unaryop port          {
2405                         if ($2.t) {
2406                                 yyerror("':' cannot be used with an other "
2407                                     "port operator");
2408                                 YYERROR;
2409                         }
2410                         $$ = calloc(1, sizeof(struct node_port));
2411                         if ($$ == NULL)
2412                                 err(1, "port_item: calloc");
2413                         $$->port[0] = $2.a;
2414                         $$->port[1] = $2.b;
2415                         $$->op = $1;
2416                         $$->next = NULL;
2417                         $$->tail = $$;
2418                 }
2419                 | port PORTBINARY port          {
2420                         if ($1.t || $3.t) {
2421                                 yyerror("':' cannot be used with an other "
2422                                     "port operator");
2423                                 YYERROR;
2424                         }
2425                         $$ = calloc(1, sizeof(struct node_port));
2426                         if ($$ == NULL)
2427                                 err(1, "port_item: calloc");
2428                         $$->port[0] = $1.a;
2429                         $$->port[1] = $3.a;
2430                         $$->op = $2;
2431                         $$->next = NULL;
2432                         $$->tail = $$;
2433                 }
2434                 ;
2435
2436 port            : STRING                        {
2437                         char    *p = strchr($1, ':');
2438                         struct servent  *s = NULL;
2439                         u_long           ulval;
2440
2441                         if (p == NULL) {
2442                                 if (atoul($1, &ulval) == 0) {
2443                                         if (ulval > 65535) {
2444                                                 free($1);
2445                                                 yyerror("illegal port value %lu",
2446                                                     ulval);
2447                                                 YYERROR;
2448                                         }
2449                                         $$.a = htons(ulval);
2450                                 } else {
2451                                         s = getservbyname($1, "tcp");
2452                                         if (s == NULL)
2453                                                 s = getservbyname($1, "udp");
2454                                         if (s == NULL) {
2455                                                 yyerror("unknown port %s", $1);
2456                                                 free($1);
2457                                                 YYERROR;
2458                                         }
2459                                         $$.a = s->s_port;
2460                                 }
2461                                 $$.b = 0;
2462                                 $$.t = 0;
2463                         } else {
2464                                 int port[2];
2465
2466                                 *p++ = 0;
2467                                 if ((port[0] = getservice($1)) == -1 ||
2468                                     (port[1] = getservice(p)) == -1) {
2469                                         free($1);
2470                                         YYERROR;
2471                                 }
2472                                 $$.a = port[0];
2473                                 $$.b = port[1];
2474                                 $$.t = PF_OP_RRG;
2475                         }
2476                         free($1);
2477                 }
2478                 ;
2479
2480 uids            : uid_item                      { $$ = $1; }
2481                 | '{' uid_list '}'              { $$ = $2; }
2482                 ;
2483
2484 uid_list        : uid_item                      { $$ = $1; }
2485                 | uid_list comma uid_item       {
2486                         $1->tail->next = $3;
2487                         $1->tail = $3;
2488                         $$ = $1;
2489                 }
2490                 ;
2491
2492 uid_item        : uid                           {
2493                         $$ = calloc(1, sizeof(struct node_uid));
2494                         if ($$ == NULL)
2495                                 err(1, "uid_item: calloc");
2496                         $$->uid[0] = $1;
2497                         $$->uid[1] = $1;
2498                         $$->op = PF_OP_EQ;
2499                         $$->next = NULL;
2500                         $$->tail = $$;
2501                 }
2502                 | unaryop uid                   {
2503                         if ($2 == UID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) {
2504                                 yyerror("user unknown requires operator = or "
2505                                     "!=");
2506                                 YYERROR;
2507                         }
2508                         $$ = calloc(1, sizeof(struct node_uid));
2509                         if ($$ == NULL)
2510                                 err(1, "uid_item: calloc");
2511                         $$->uid[0] = $2;
2512                         $$->uid[1] = $2;
2513                         $$->op = $1;
2514                         $$->next = NULL;
2515                         $$->tail = $$;
2516                 }
2517                 | uid PORTBINARY uid            {
2518                         if ($1 == UID_MAX || $3 == UID_MAX) {
2519                                 yyerror("user unknown requires operator = or "
2520                                     "!=");
2521                                 YYERROR;
2522                         }
2523                         $$ = calloc(1, sizeof(struct node_uid));
2524                         if ($$ == NULL)
2525                                 err(1, "uid_item: calloc");
2526                         $$->uid[0] = $1;
2527                         $$->uid[1] = $3;
2528                         $$->op = $2;
2529                         $$->next = NULL;
2530                         $$->tail = $$;
2531                 }
2532                 ;
2533
2534 uid             : STRING                        {
2535                         u_long  ulval;
2536
2537                         if (atoul($1, &ulval) == -1) {
2538                                 if (!strcmp($1, "unknown"))
2539                                         $$ = UID_MAX;
2540                                 else {
2541                                         struct passwd   *pw;
2542
2543                                         if ((pw = getpwnam($1)) == NULL) {
2544                                                 yyerror("unknown user %s", $1);
2545                                                 free($1);
2546                                                 YYERROR;
2547                                         }
2548                                         $$ = pw->pw_uid;
2549                                 }
2550                         } else {
2551                                 if (ulval >= UID_MAX) {
2552                                         free($1);
2553                                         yyerror("illegal uid value %lu", ulval);
2554                                         YYERROR;
2555                                 }
2556                                 $$ = ulval;
2557                         }
2558                         free($1);
2559                 }
2560                 ;
2561
2562 gids            : gid_item                      { $$ = $1; }
2563                 | '{' gid_list '}'              { $$ = $2; }
2564                 ;
2565
2566 gid_list        : gid_item                      { $$ = $1; }
2567                 | gid_list comma gid_item       {
2568                         $1->tail->next = $3;
2569                         $1->tail = $3;
2570                         $$ = $1;
2571                 }
2572                 ;
2573
2574 gid_item        : gid                           {
2575                         $$ = calloc(1, sizeof(struct node_gid));
2576                         if ($$ == NULL)
2577                                 err(1, "gid_item: calloc");
2578                         $$->gid[0] = $1;
2579                         $$->gid[1] = $1;
2580                         $$->op = PF_OP_EQ;
2581                         $$->next = NULL;
2582                         $$->tail = $$;
2583                 }
2584                 | unaryop gid                   {
2585                         if ($2 == GID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) {
2586                                 yyerror("group unknown requires operator = or "
2587                                     "!=");
2588                                 YYERROR;
2589                         }
2590                         $$ = calloc(1, sizeof(struct node_gid));
2591                         if ($$ == NULL)
2592                                 err(1, "gid_item: calloc");
2593                         $$->gid[0] = $2;
2594                         $$->gid[1] = $2;
2595                         $$->op = $1;
2596                         $$->next = NULL;
2597                         $$->tail = $$;
2598                 }
2599                 | gid PORTBINARY gid            {
2600                         if ($1 == GID_MAX || $3 == GID_MAX) {
2601                                 yyerror("group unknown requires operator = or "
2602                                     "!=");
2603                                 YYERROR;
2604                         }
2605                         $$ = calloc(1, sizeof(struct node_gid));
2606                         if ($$ == NULL)
2607                                 err(1, "gid_item: calloc");
2608                         $$->gid[0] = $1;
2609                         $$->gid[1] = $3;
2610                         $$->op = $2;
2611                         $$->next = NULL;
2612                         $$->tail = $$;
2613                 }
2614                 ;
2615
2616 gid             : STRING                        {
2617                         u_long  ulval;
2618
2619                         if (atoul($1, &ulval) == -1) {
2620                                 if (!strcmp($1, "unknown"))
2621                                         $$ = GID_MAX;
2622                                 else {
2623                                         struct group    *grp;
2624
2625                                         if ((grp = getgrnam($1)) == NULL) {
2626                                                 yyerror("unknown group %s", $1);
2627                                                 free($1);
2628                                                 YYERROR;
2629                                         }
2630                                         $$ = grp->gr_gid;
2631                                 }
2632                         } else {
2633                                 if (ulval >= GID_MAX) {
2634                                         yyerror("illegal gid value %lu", ulval);
2635                                         free($1);
2636                                         YYERROR;
2637                                 }
2638                                 $$ = ulval;
2639                         }
2640                         free($1);
2641                 }
2642                 ;
2643
2644 flag            : STRING                        {
2645                         int     f;
2646
2647                         if ((f = parse_flags($1)) < 0) {
2648                                 yyerror("bad flags %s", $1);
2649                                 free($1);
2650                                 YYERROR;
2651                         }
2652                         free($1);
2653                         $$.b1 = f;
2654                 }
2655                 ;
2656
2657 flags           : FLAGS flag '/' flag   { $$.b1 = $2.b1; $$.b2 = $4.b1; }
2658                 | FLAGS '/' flag        { $$.b1 = 0; $$.b2 = $3.b1; }
2659                 ;
2660
2661 icmpspec        : ICMPTYPE icmp_item            { $$ = $2; }
2662                 | ICMPTYPE '{' icmp_list '}'    { $$ = $3; }
2663                 | ICMP6TYPE icmp6_item          { $$ = $2; }
2664                 | ICMP6TYPE '{' icmp6_list '}'  { $$ = $3; }
2665                 ;
2666
2667 icmp_list       : icmp_item                     { $$ = $1; }
2668                 | icmp_list comma icmp_item     {
2669                         $1->tail->next = $3;
2670                         $1->tail = $3;
2671                         $$ = $1;
2672                 }
2673                 ;
2674
2675 icmp6_list      : icmp6_item                    { $$ = $1; }
2676                 | icmp6_list comma icmp6_item   {
2677                         $1->tail->next = $3;
2678                         $1->tail = $3;
2679                         $$ = $1;
2680                 }
2681                 ;
2682
2683 icmp_item       : icmptype              {
2684                         $$ = calloc(1, sizeof(struct node_icmp));
2685                         if ($$ == NULL)
2686                                 err(1, "icmp_item: calloc");
2687                         $$->type = $1;
2688                         $$->code = 0;
2689                         $$->proto = IPPROTO_ICMP;
2690                         $$->next = NULL;
2691                         $$->tail = $$;
2692                 }
2693                 | icmptype CODE STRING  {
2694                         const struct icmpcodeent        *p;
2695                         u_long                           ulval;
2696
2697                         if (atoul($3, &ulval) == 0) {
2698                                 if (ulval > 255) {
2699                                         free($3);
2700                                         yyerror("illegal icmp-code %lu", ulval);
2701                                         YYERROR;
2702                                 }
2703                         } else {
2704                                 if ((p = geticmpcodebyname($1-1, $3,
2705                                     AF_INET)) == NULL) {
2706                                         yyerror("unknown icmp-code %s", $3);
2707                                         free($3);
2708                                         YYERROR;
2709                                 }
2710                                 ulval = p->code;
2711                         }
2712                         free($3);
2713                         $$ = calloc(1, sizeof(struct node_icmp));
2714                         if ($$ == NULL)
2715                                 err(1, "icmp_item: calloc");
2716                         $$->type = $1;
2717                         $$->code = ulval + 1;
2718                         $$->proto = IPPROTO_ICMP;
2719                         $$->next = NULL;
2720                         $$->tail = $$;
2721                 }
2722                 ;
2723
2724 icmp6_item      : icmp6type             {
2725                         $$ = calloc(1, sizeof(struct node_icmp));
2726                         if ($$ == NULL)
2727                                 err(1, "icmp_item: calloc");
2728                         $$->type = $1;
2729                         $$->code = 0;
2730                         $$->proto = IPPROTO_ICMPV6;
2731                         $$->next = NULL;
2732                         $$->tail = $$;
2733                 }
2734                 | icmp6type CODE STRING {
2735                         const struct icmpcodeent        *p;
2736                         u_long                           ulval;
2737
2738                         if (atoul($3, &ulval) == 0) {
2739                                 if (ulval > 255) {
2740                                         yyerror("illegal icmp6-code %lu",
2741                                             ulval);
2742                                         free($3);
2743                                         YYERROR;
2744                                 }
2745                         } else {
2746                                 if ((p = geticmpcodebyname($1-1, $3,
2747                                     AF_INET6)) == NULL) {
2748                                         yyerror("unknown icmp6-code %s", $3);
2749                                         free($3);
2750                                         YYERROR;
2751                                 }
2752                                 ulval = p->code;
2753                         }
2754                         free($3);
2755                         $$ = calloc(1, sizeof(struct node_icmp));
2756                         if ($$ == NULL)
2757                                 err(1, "icmp_item: calloc");
2758                         $$->type = $1;
2759                         $$->code = ulval + 1;
2760                         $$->proto = IPPROTO_ICMPV6;
2761                         $$->next = NULL;
2762                         $$->tail = $$;
2763                 }
2764                 ;
2765
2766 icmptype        : STRING                        {
2767                         const struct icmptypeent        *p;
2768                         u_long                           ulval;
2769
2770                         if (atoul($1, &ulval) == 0) {
2771                                 if (ulval > 255) {
2772                                         yyerror("illegal icmp-type %lu", ulval);
2773                                         free($1);
2774                                         YYERROR;
2775                                 }
2776                                 $$ = ulval + 1;
2777                         } else {
2778                                 if ((p = geticmptypebyname($1, AF_INET)) ==
2779                                     NULL) {
2780                                         yyerror("unknown icmp-type %s", $1);
2781                                         free($1);
2782                                         YYERROR;
2783                                 }
2784                                 $$ = p->type + 1;
2785                         }
2786                         free($1);
2787                 }
2788                 ;
2789
2790 icmp6type       : STRING                        {
2791                         const struct icmptypeent        *p;
2792                         u_long                           ulval;
2793
2794                         if (atoul($1, &ulval) == 0) {
2795                                 if (ulval > 255) {
2796                                         yyerror("illegal icmp6-type %lu", ulval);
2797                                         free($1);
2798                                         YYERROR;
2799                                 }
2800                                 $$ = ulval + 1;
2801                         } else {
2802                                 if ((p = geticmptypebyname($1, AF_INET6)) ==
2803                                     NULL) {
2804                                         yyerror("unknown icmp6-type %s", $1);
2805                                         free($1);
2806                                         YYERROR;
2807                                 }
2808                                 $$ = p->type + 1;
2809                         }
2810                         free($1);
2811                 }
2812                 ;
2813
2814 tos             : TOS STRING                    {
2815                         if (!strcmp($2, "lowdelay"))
2816                                 $$ = IPTOS_LOWDELAY;
2817                         else if (!strcmp($2, "throughput"))
2818                                 $$ = IPTOS_THROUGHPUT;
2819                         else if (!strcmp($2, "reliability"))
2820                                 $$ = IPTOS_RELIABILITY;
2821                         else if ($2[0] == '0' && $2[1] == 'x')
2822                                 $$ = strtoul($2, NULL, 16);
2823                         else
2824                                 $$ = strtoul($2, NULL, 10);
2825                         if (!$$ || $$ > 255) {
2826                                 yyerror("illegal tos value %s", $2);
2827                                 free($2);
2828                                 YYERROR;
2829                         }
2830                         free($2);
2831                 }
2832                 ;
2833
2834 sourcetrack     : SOURCETRACK           { $$ = PF_SRCTRACK; }
2835                 | SOURCETRACK GLOBAL    { $$ = PF_SRCTRACK_GLOBAL; }
2836                 | SOURCETRACK RULE      { $$ = PF_SRCTRACK_RULE; }
2837                 ;
2838
2839 statelock       : IFBOUND {
2840                         $$ = PFRULE_IFBOUND;
2841                 }
2842                 | GRBOUND {
2843                         $$ = PFRULE_GRBOUND;
2844                 }
2845                 | FLOATING {
2846                         $$ = 0;
2847                 }
2848                 ;
2849
2850 keep            : KEEP STATE state_opt_spec     {
2851                         $$.action = PF_STATE_NORMAL;
2852                         $$.options = $3;
2853                 }
2854                 | MODULATE STATE state_opt_spec {
2855                         $$.action = PF_STATE_MODULATE;
2856                         $$.options = $3;
2857                 }
2858                 | SYNPROXY STATE state_opt_spec {
2859                         $$.action = PF_STATE_SYNPROXY;
2860                         $$.options = $3;
2861                 }
2862                 ;
2863
2864 flush           : /* empty */                   { $$ = 0; }
2865                 | FLUSH                         { $$ = PF_FLUSH; }
2866                 | FLUSH GLOBAL                  {
2867                         $$ = PF_FLUSH | PF_FLUSH_GLOBAL;
2868                 }
2869                 ;
2870
2871 state_opt_spec  : '(' state_opt_list ')'        { $$ = $2; }
2872                 | /* empty */                   { $$ = NULL; }
2873                 ;
2874
2875 state_opt_list  : state_opt_item                { $$ = $1; }
2876                 | state_opt_list comma state_opt_item {
2877                         $1->tail->next = $3;
2878                         $1->tail = $3;
2879                         $$ = $1;
2880                 }
2881                 ;
2882
2883 state_opt_item  : MAXIMUM number                {
2884                         $$ = calloc(1, sizeof(struct node_state_opt));
2885                         if ($$ == NULL)
2886                                 err(1, "state_opt_item: calloc");
2887                         $$->type = PF_STATE_OPT_MAX;
2888                         $$->data.max_states = $2;
2889                         $$->next = NULL;
2890                         $$->tail = $$;
2891                 }
2892                 | NOSYNC                                {
2893                         $$ = calloc(1, sizeof(struct node_state_opt));
2894                         if ($$ == NULL)
2895                                 err(1, "state_opt_item: calloc");
2896                         $$->type = PF_STATE_OPT_NOSYNC;
2897                         $$->next = NULL;
2898                         $$->tail = $$;
2899                 }
2900                 | MAXSRCSTATES number                   {
2901                         $$ = calloc(1, sizeof(struct node_state_opt));
2902                         if ($$ == NULL)
2903                                 err(1, "state_opt_item: calloc");
2904                         $$->type = PF_STATE_OPT_MAX_SRC_STATES;
2905                         $$->data.max_src_states = $2;
2906                         $$->next = NULL;
2907                         $$->tail = $$;
2908                 }
2909                 | MAXSRCCONN number                     {
2910                         $$ = calloc(1, sizeof(struct node_state_opt));
2911                         if ($$ == NULL)
2912                                 err(1, "state_opt_item: calloc");
2913                         $$->type = PF_STATE_OPT_MAX_SRC_CONN;
2914                         $$->data.max_src_conn = $2;
2915                         $$->next = NULL;
2916                         $$->tail = $$;
2917                 }
2918                 | MAXSRCCONNRATE number '/' number      {
2919                         $$ = calloc(1, sizeof(struct node_state_opt));
2920                         if ($$ == NULL)
2921                                 err(1, "state_opt_item: calloc");
2922                         $$->type = PF_STATE_OPT_MAX_SRC_CONN_RATE;
2923                         $$->data.max_src_conn_rate.limit = $2;
2924                         $$->data.max_src_conn_rate.seconds = $4;
2925                         $$->next = NULL;
2926                         $$->tail = $$;
2927                 }
2928                 | OVERLOAD '<' STRING '>' flush         {
2929                         if (strlen($3) >= PF_TABLE_NAME_SIZE) {
2930                                 yyerror("table name '%s' too long", $3);
2931                                 free($3);
2932                                 YYERROR;
2933                         }
2934                         $$ = calloc(1, sizeof(struct node_state_opt));
2935                         if ($$ == NULL)
2936                                 err(1, "state_opt_item: calloc");
2937                         if (strlcpy($$->data.overload.tblname, $3,
2938                             PF_TABLE_NAME_SIZE) >= PF_TABLE_NAME_SIZE)
2939                                 errx(1, "state_opt_item: strlcpy");
2940                         free($3);
2941                         $$->type = PF_STATE_OPT_OVERLOAD;
2942                         $$->data.overload.flush = $5;
2943                         $$->next = NULL;
2944                         $$->tail = $$;
2945                 }
2946                 | MAXSRCNODES number                    {
2947                         $$ = calloc(1, sizeof(struct node_state_opt));
2948                         if ($$ == NULL)
2949                                 err(1, "state_opt_item: calloc");
2950                         $$->type = PF_STATE_OPT_MAX_SRC_NODES;
2951                         $$->data.max_src_nodes = $2;
2952                         $$->next = NULL;
2953                         $$->tail = $$;
2954                 }
2955                 | sourcetrack {
2956                         $$ = calloc(1, sizeof(struct node_state_opt));
2957                         if ($$ == NULL)
2958                                 err(1, "state_opt_item: calloc");
2959                         $$->type = PF_STATE_OPT_SRCTRACK;
2960                         $$->data.src_track = $1;
2961                         $$->next = NULL;
2962                         $$->tail = $$;
2963                 }
2964                 | statelock {
2965                         $$ = calloc(1, sizeof(struct node_state_opt));
2966                         if ($$ == NULL)
2967                                 err(1, "state_opt_item: calloc");
2968                         $$->type = PF_STATE_OPT_STATELOCK;
2969                         $$->data.statelock = $1;
2970                         $$->next = NULL;
2971                         $$->tail = $$;
2972                 }
2973                 | STRING number                 {
2974                         int     i;
2975
2976                         for (i = 0; pf_timeouts[i].name &&
2977                             strcmp(pf_timeouts[i].name, $1); ++i)
2978                                 ;       /* nothing */
2979                         if (!pf_timeouts[i].name) {
2980                                 yyerror("illegal timeout name %s", $1);
2981                                 free($1);
2982                                 YYERROR;
2983                         }
2984                         if (strchr(pf_timeouts[i].name, '.') == NULL) {
2985                                 yyerror("illegal state timeout %s", $1);
2986                                 free($1);
2987                                 YYERROR;
2988                         }
2989                         free($1);
2990                         $$ = calloc(1, sizeof(struct node_state_opt));
2991                         if ($$ == NULL)
2992                                 err(1, "state_opt_item: calloc");
2993                         $$->type = PF_STATE_OPT_TIMEOUT;
2994                         $$->data.timeout.number = pf_timeouts[i].timeout;
2995                         $$->data.timeout.seconds = $2;
2996                         $$->next = NULL;
2997                         $$->tail = $$;
2998                 }
2999                 ;
3000
3001 label           : LABEL STRING                  {
3002                         $$ = $2;
3003                 }
3004                 ;
3005
3006 qname           : QUEUE STRING                          {
3007                         $$.qname = $2;
3008                 }
3009                 | QUEUE '(' STRING ')'                  {
3010                         $$.qname = $3;
3011                 }
3012                 | QUEUE '(' STRING comma STRING ')'     {
3013                         $$.qname = $3;
3014                         $$.pqname = $5;
3015                 }
3016                 ;
3017
3018 no              : /* empty */                   { $$ = 0; }
3019                 | NO                            { $$ = 1; }
3020                 ;
3021
3022 rport           : STRING                        {
3023                         char    *p = strchr($1, ':');
3024
3025                         if (p == NULL) {
3026                                 if (($$.a = getservice($1)) == -1) {
3027                                         free($1);
3028                                         YYERROR;
3029                                 }
3030                                 $$.b = $$.t = 0;
3031                         } else if (!strcmp(p+1, "*")) {
3032                                 *p = 0;
3033                                 if (($$.a = getservice($1)) == -1) {
3034                                         free($1);
3035                                         YYERROR;
3036                                 }
3037                                 $$.b = 0;
3038                                 $$.t = 1;
3039                         } else {
3040                                 *p++ = 0;
3041                                 if (($$.a = getservice($1)) == -1 ||
3042                                     ($$.b = getservice(p)) == -1) {
3043                                         free($1);
3044                                         YYERROR;
3045                                 }
3046                                 if ($$.a == $$.b)
3047                                         $$.b = 0;
3048                                 $$.t = 0;
3049                         }
3050                         free($1);
3051                 }
3052                 ;
3053
3054 redirspec       : host                          { $$ = $1; }
3055                 | '{' redir_host_list '}'       { $$ = $2; }
3056                 ;
3057
3058 redir_host_list : host                          { $$ = $1; }
3059                 | redir_host_list comma host    {
3060                         $1->tail->next = $3;
3061                         $1->tail = $3->tail;
3062                         $$ = $1;
3063                 }
3064                 ;
3065
3066 redirpool       : /* empty */                   { $$ = NULL; }
3067                 | ARROW redirspec               {
3068                         $$ = calloc(1, sizeof(struct redirection));
3069                         if ($$ == NULL)
3070                                 err(1, "redirection: calloc");
3071                         $$->host = $2;
3072                         $$->rport.a = $$->rport.b = $$->rport.t = 0;
3073                 }
3074                 | ARROW redirspec PORT rport    {
3075                         $$ = calloc(1, sizeof(struct redirection));
3076                         if ($$ == NULL)
3077                                 err(1, "redirection: calloc");
3078                         $$->host = $2;
3079                         $$->rport = $4;
3080                 }
3081                 ;
3082
3083 hashkey         : /* empty */
3084                 {
3085                         $$ = calloc(1, sizeof(struct pf_poolhashkey));
3086                         if ($$ == NULL)
3087                                 err(1, "hashkey: calloc");
3088                         $$->key32[0] = arc4random();
3089                         $$->key32[1] = arc4random();
3090                         $$->key32[2] = arc4random();
3091                         $$->key32[3] = arc4random();
3092                 }
3093                 | string
3094                 {
3095                         if (!strncmp($1, "0x", 2)) {
3096                                 if (strlen($1) != 34) {
3097                                         free($1);
3098                                         yyerror("hex key must be 128 bits "
3099                                                 "(32 hex digits) long");
3100                                         YYERROR;
3101                                 }
3102                                 $$ = calloc(1, sizeof(struct pf_poolhashkey));
3103                                 if ($$ == NULL)
3104                                         err(1, "hashkey: calloc");
3105
3106                                 if (sscanf($1, "0x%8x%8x%8x%8x",
3107                                     &$$->key32[0], &$$->key32[1],
3108                                     &$$->key32[2], &$$->key32[3]) != 4) {
3109                                         free($$);
3110                                         free($1);
3111                                         yyerror("invalid hex key");
3112                                         YYERROR;
3113                                 }
3114                         } else {
3115                                 MD5_CTX context;
3116
3117                                 $$ = calloc(1, sizeof(struct pf_poolhashkey));
3118                                 if ($$ == NULL)
3119                                         err(1, "hashkey: calloc");
3120                                 MD5Init(&context);
3121                                 MD5Update(&context, (unsigned char *)$1,
3122                                     strlen($1));
3123                                 MD5Final((unsigned char *)$$, &context);
3124                                 HTONL($$->key32[0]);
3125                                 HTONL($$->key32[1]);
3126                                 HTONL($$->key32[2]);
3127                                 HTONL($$->key32[3]);
3128                         }
3129                         free($1);
3130                 }
3131                 ;
3132
3133 pool_opts       :       { bzero(&pool_opts, sizeof pool_opts); }
3134                     pool_opts_l
3135                         { $$ = pool_opts; }
3136                 | /* empty */   {
3137                         bzero(&pool_opts, sizeof pool_opts);
3138                         $$ = pool_opts;
3139                 }
3140                 ;
3141
3142 pool_opts_l     : pool_opts_l pool_opt
3143                 | pool_opt
3144                 ;
3145
3146 pool_opt        : BITMASK       {
3147                         if (pool_opts.type) {
3148                                 yyerror("pool type cannot be redefined");
3149                                 YYERROR;
3150                         }
3151                         pool_opts.type =  PF_POOL_BITMASK;
3152                 }
3153                 | RANDOM        {
3154                         if (pool_opts.type) {
3155                                 yyerror("pool type cannot be redefined");
3156                                 YYERROR;
3157                         }
3158                         pool_opts.type = PF_POOL_RANDOM;
3159                 }
3160                 | SOURCEHASH hashkey {
3161                         if (pool_opts.type) {
3162                                 yyerror("pool type cannot be redefined");
3163                                 YYERROR;
3164                         }
3165                         pool_opts.type = PF_POOL_SRCHASH;
3166                         pool_opts.key = $2;
3167                 }
3168                 | ROUNDROBIN    {
3169                         if (pool_opts.type) {
3170                                 yyerror("pool type cannot be redefined");
3171                                 YYERROR;
3172                         }
3173                         pool_opts.type = PF_POOL_ROUNDROBIN;
3174                 }
3175                 | STATICPORT    {
3176                         if (pool_opts.staticport) {
3177                                 yyerror("static-port cannot be redefined");
3178                                 YYERROR;
3179                         }
3180                         pool_opts.staticport = 1;
3181                 }
3182                 | STICKYADDRESS {
3183                         if (filter_opts.marker & POM_STICKYADDRESS) {
3184                                 yyerror("sticky-address cannot be redefined");
3185                                 YYERROR;
3186                         }
3187                         pool_opts.marker |= POM_STICKYADDRESS;
3188                         pool_opts.opts |= PF_POOL_STICKYADDR;
3189                 }
3190                 ;
3191
3192 redirection     : /* empty */                   { $$ = NULL; }
3193                 | ARROW host                    {
3194                         $$ = calloc(1, sizeof(struct redirection));
3195                         if ($$ == NULL)
3196                                 err(1, "redirection: calloc");
3197                         $$->host = $2;
3198                         $$->rport.a = $$->rport.b = $$->rport.t = 0;
3199                 }
3200                 | ARROW host PORT rport {
3201                         $$ = calloc(1, sizeof(struct redirection));
3202                         if ($$ == NULL)
3203                                 err(1, "redirection: calloc");
3204                         $$->host = $2;
3205                         $$->rport = $4;
3206                 }
3207                 ;
3208
3209 natpass         : /* empty */   { $$ = 0; }
3210                 | PASS          { $$ = 1; }
3211                 ;
3212
3213 nataction       : no NAT natpass {
3214                         $$.b2 = $$.w = 0;
3215                         if ($1)
3216                                 $$.b1 = PF_NONAT;
3217                         else
3218                                 $$.b1 = PF_NAT;
3219                         $$.b2 = $3;
3220                 }
3221                 | no RDR natpass {
3222                         $$.b2 = $$.w = 0;
3223                         if ($1)
3224                                 $$.b1 = PF_NORDR;
3225                         else
3226                                 $$.b1 = PF_RDR;
3227                         $$.b2 = $3;
3228                 }
3229                 ;
3230
3231 natrule         : nataction interface af proto fromto tag tagged redirpool pool_opts
3232                 {
3233                         struct pf_rule  r;
3234
3235                         if (check_rulestate(PFCTL_STATE_NAT))
3236                                 YYERROR;
3237
3238                         memset(&r, 0, sizeof(r));
3239
3240                         r.action = $1.b1;
3241                         r.natpass = $1.b2;
3242                         r.af = $3;
3243
3244                         if (!r.af) {
3245                                 if ($5.src.host && $5.src.host->af &&
3246                                     !$5.src.host->ifindex)
3247                                         r.af = $5.src.host->af;
3248                                 else if ($5.dst.host && $5.dst.host->af &&
3249                                     !$5.dst.host->ifindex)
3250                                         r.af = $5.dst.host->af;
3251                         }
3252
3253                         if ($6 != NULL)
3254                                 if (strlcpy(r.tagname, $6, PF_TAG_NAME_SIZE) >=
3255                                     PF_TAG_NAME_SIZE) {
3256                                         yyerror("tag too long, max %u chars",
3257                                             PF_TAG_NAME_SIZE - 1);
3258                                         YYERROR;
3259                                 }
3260
3261                         if ($7.name)
3262                                 if (strlcpy(r.match_tagname, $7.name,
3263                                     PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
3264                                         yyerror("tag too long, max %u chars",
3265                                             PF_TAG_NAME_SIZE - 1);
3266                                         YYERROR;
3267                                 }
3268                         r.match_tag_not = $7.neg;
3269
3270                         if (r.action == PF_NONAT || r.action == PF_NORDR) {
3271                                 if ($8 != NULL) {
3272                                         yyerror("translation rule with 'no' "
3273                                             "does not need '->'");
3274                                         YYERROR;
3275                                 }
3276                         } else {
3277                                 if ($8 == NULL || $8->host == NULL) {
3278                                         yyerror("translation rule requires '-> "
3279                                             "address'");
3280                                         YYERROR;
3281                                 }
3282                                 if (!r.af && ! $8->host->ifindex)
3283                                         r.af = $8->host->af;
3284
3285                                 remove_invalid_hosts(&$8->host, &r.af);
3286                                 if (invalid_redirect($8->host, r.af))
3287                                         YYERROR;
3288                                 if (check_netmask($8->host, r.af))
3289                                         YYERROR;
3290
3291                                 r.rpool.proxy_port[0] = ntohs($8->rport.a);
3292
3293                                 switch (r.action) {
3294                                 case PF_RDR:
3295                                         if (!$8->rport.b && $8->rport.t &&
3296                                             $5.dst.port != NULL) {
3297                                                 r.rpool.proxy_port[1] =
3298                                                     ntohs($8->rport.a) +
3299                                                     (ntohs(
3300                                                     $5.dst.port->port[1]) -
3301                                                     ntohs(
3302                                                     $5.dst.port->port[0]));
3303                                         } else
3304                                                 r.rpool.proxy_port[1] =
3305                                                     ntohs($8->rport.b);
3306                                         break;
3307                                 case PF_NAT:
3308                                         r.rpool.proxy_port[1] =
3309                                             ntohs($8->rport.b);
3310                                         if (!r.rpool.proxy_port[0] &&
3311                                             !r.rpool.proxy_port[1]) {
3312                                                 r.rpool.proxy_port[0] =
3313                                                     PF_NAT_PROXY_PORT_LOW;
3314                                                 r.rpool.proxy_port[1] =
3315                                                     PF_NAT_PROXY_PORT_HIGH;
3316                                         } else if (!r.rpool.proxy_port[1])
3317                                                 r.rpool.proxy_port[1] =
3318                                                     r.rpool.proxy_port[0];
3319                                         break;
3320                                 default:
3321                                         break;
3322                                 }
3323
3324                                 r.rpool.opts = $9.type;
3325                                 if ((r.rpool.opts & PF_POOL_TYPEMASK) ==
3326                                     PF_POOL_NONE && ($8->host->next != NULL ||
3327                                     $8->host->addr.type == PF_ADDR_TABLE ||
3328                                     DYNIF_MULTIADDR($8->host->addr)))
3329                                         r.rpool.opts = PF_POOL_ROUNDROBIN;
3330                                 if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
3331                                     PF_POOL_ROUNDROBIN &&
3332                                     disallow_table($8->host, "tables are only "
3333                                     "supported in round-robin redirection "
3334                                     "pools"))
3335                                         YYERROR;
3336                                 if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
3337                                     PF_POOL_ROUNDROBIN &&
3338                                     disallow_alias($8->host, "interface (%s) "
3339                                     "is only supported in round-robin "
3340                                     "redirection pools"))
3341                                         YYERROR;
3342                                 if ($8->host->next != NULL) {
3343                                         if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
3344                                             PF_POOL_ROUNDROBIN) {
3345                                                 yyerror("only round-robin "
3346                                                     "valid for multiple "
3347                                                     "redirection addresses");
3348                                                 YYERROR;
3349                                         }
3350                                 }
3351                         }
3352
3353                         if ($9.key != NULL)
3354                                 memcpy(&r.rpool.key, $9.key,
3355                                     sizeof(struct pf_poolhashkey));
3356
3357                          if ($9.opts)
3358                                 r.rpool.opts |= $9.opts;
3359
3360                         if ($9.staticport) {
3361                                 if (r.action != PF_NAT) {
3362                                         yyerror("the 'static-port' option is "
3363                                             "only valid with nat rules");
3364                                         YYERROR;
3365                                 }
3366                                 if (r.rpool.proxy_port[0] !=
3367                                     PF_NAT_PROXY_PORT_LOW &&
3368                                     r.rpool.proxy_port[1] !=
3369                                     PF_NAT_PROXY_PORT_HIGH) {
3370                                         yyerror("the 'static-port' option can't"
3371                                             " be used when specifying a port"
3372                                             " range");
3373                                         YYERROR;
3374                                 }
3375                                 r.rpool.proxy_port[0] = 0;
3376                                 r.rpool.proxy_port[1] = 0;
3377                         }
3378
3379                         expand_rule(&r, $2, $8 == NULL ? NULL : $8->host, $4,
3380                             $5.src_os, $5.src.host, $5.src.port, $5.dst.host,
3381                             $5.dst.port, 0, 0, 0, "");
3382                         free($8);
3383                 }
3384                 ;
3385
3386 binatrule       : no BINAT natpass interface af proto FROM host TO ipspec tag tagged
3387                     redirection
3388                 {
3389                         struct pf_rule          binat;
3390                         struct pf_pooladdr      *pa;
3391
3392                         if (check_rulestate(PFCTL_STATE_NAT))
3393                                 YYERROR;
3394
3395                         memset(&binat, 0, sizeof(binat));
3396
3397                         if ($1)
3398                                 binat.action = PF_NOBINAT;
3399                         else
3400                                 binat.action = PF_BINAT;
3401                         binat.natpass = $3;
3402                         binat.af = $5;
3403                         if (!binat.af && $8 != NULL && $8->af)
3404                                 binat.af = $8->af;
3405                         if (!binat.af && $10 != NULL && $10->af)
3406                                 binat.af = $10->af;
3407
3408                         if (!binat.af && $13 != NULL && $13->host)
3409                                 binat.af = $13->host->af;
3410                         if (!binat.af) {
3411                                 yyerror("address family (inet/inet6) "
3412                                     "undefined");
3413                                 YYERROR;
3414                         }
3415
3416                         if ($4 != NULL) {
3417                                 memcpy(binat.ifname, $4->ifname,
3418                                     sizeof(binat.ifname));
3419                                 binat.ifnot = $4->not;
3420                                 free($4);
3421                         }
3422
3423                         if ($11 != NULL)
3424                                 if (strlcpy(binat.tagname, $11,
3425                                     PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
3426                                         yyerror("tag too long, max %u chars",
3427                                             PF_TAG_NAME_SIZE - 1);
3428                                         YYERROR;
3429                                 }
3430                         if ($12.name)
3431                                 if (strlcpy(binat.match_tagname, $12.name,
3432                                     PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
3433                                         yyerror("tag too long, max %u chars",
3434                                             PF_TAG_NAME_SIZE - 1);
3435                                         YYERROR;
3436                                 }
3437                         binat.match_tag_not = $12.neg;
3438
3439                         if ($6 != NULL) {
3440                                 binat.proto = $6->proto;
3441                                 free($6);
3442                         }
3443
3444                         if ($8 != NULL && disallow_table($8, "invalid use of "
3445                             "table <%s> as the source address of a binat rule"))
3446                                 YYERROR;
3447                         if ($8 != NULL && disallow_alias($8, "invalid use of "
3448                             "interface (%s) as the source address of a binat "
3449                             "rule"))
3450                                 YYERROR;
3451                         if ($13 != NULL && $13->host != NULL && disallow_table(
3452                             $13->host, "invalid use of table <%s> as the "
3453                             "redirect address of a binat rule"))
3454                                 YYERROR;
3455                         if ($13 != NULL && $13->host != NULL && disallow_alias(
3456                             $13->host, "invalid use of interface (%s) as the "
3457                             "redirect address of a binat rule"))
3458                                 YYERROR;
3459
3460                         if ($8 != NULL) {
3461                                 if ($8->next) {
3462                                         yyerror("multiple binat ip addresses");
3463                                         YYERROR;
3464                                 }
3465                                 if ($8->addr.type == PF_ADDR_DYNIFTL)
3466                                         $8->af = binat.af;
3467                                 if ($8->af != binat.af) {
3468                                         yyerror("binat ip versions must match");
3469                                         YYERROR;
3470                                 }
3471                                 if (check_netmask($8, binat.af))
3472                                         YYERROR;
3473                                 memcpy(&binat.src.addr, &$8->addr,
3474                                     sizeof(binat.src.addr));
3475                                 free($8);
3476                         }
3477                         if ($10 != NULL) {
3478                                 if ($10->next) {
3479                                         yyerror("multiple binat ip addresses");
3480                                         YYERROR;
3481                                 }
3482                                 if ($10->af != binat.af && $10->af) {
3483                                         yyerror("binat ip versions must match");
3484                                         YYERROR;
3485                                 }
3486                                 if (check_netmask($10, binat.af))
3487                                         YYERROR;
3488                                 memcpy(&binat.dst.addr, &$10->addr,
3489                                     sizeof(binat.dst.addr));
3490                                 binat.dst.neg = $10->not;
3491                                 free($10);
3492                         }
3493
3494                         if (binat.action == PF_NOBINAT) {
3495                                 if ($13 != NULL) {
3496                                         yyerror("'no binat' rule does not need"
3497                                             " '->'");
3498                                         YYERROR;
3499                                 }
3500                         } else {
3501                                 if ($13 == NULL || $13->host == NULL) {
3502                                         yyerror("'binat' rule requires"
3503                                             " '-> address'");
3504                                         YYERROR;
3505                                 }
3506
3507                                 remove_invalid_hosts(&$13->host, &binat.af);
3508                                 if (invalid_redirect($13->host, binat.af))
3509                                         YYERROR;
3510                                 if ($13->host->next != NULL) {
3511                                         yyerror("binat rule must redirect to "
3512                                             "a single address");
3513                                         YYERROR;
3514                                 }
3515                                 if (check_netmask($13->host, binat.af))
3516                                         YYERROR;
3517
3518                                 if (!PF_AZERO(&binat.src.addr.v.a.mask,
3519                                     binat.af) &&
3520                                     !PF_AEQ(&binat.src.addr.v.a.mask,
3521                                     &$13->host->addr.v.a.mask, binat.af)) {
3522                                         yyerror("'binat' source mask and "
3523                                             "redirect mask must be the same");
3524                                         YYERROR;
3525                                 }
3526
3527                                 TAILQ_INIT(&binat.rpool.list);
3528                                 pa = calloc(1, sizeof(struct pf_pooladdr));
3529                                 if (pa == NULL)
3530                                         err(1, "binat: calloc");
3531                                 pa->addr = $13->host->addr;
3532                                 pa->ifname[0] = 0;
3533                                 TAILQ_INSERT_TAIL(&binat.rpool.list,
3534                                     pa, entries);
3535
3536                                 free($13);
3537                         }
3538
3539                         pfctl_add_rule(pf, &binat, "");
3540                 }
3541                 ;
3542
3543 tag             : /* empty */           { $$ = NULL; }
3544                 | TAG STRING            { $$ = $2; }
3545                 ;
3546
3547 tagged          : /* empty */           { $$.neg = 0; $$.name = NULL; }
3548                 | not TAGGED string     { $$.neg = $1; $$.name = $3; }
3549                 ;
3550
3551 route_host      : STRING                        {
3552                         $$ = calloc(1, sizeof(struct node_host));
3553                         if ($$ == NULL)
3554                                 err(1, "route_host: calloc");
3555                         $$->ifname = $1;
3556                         set_ipmask($$, 128);
3557                         $$->next = NULL;
3558                         $$->tail = $$;
3559                 }
3560                 | '(' STRING host ')'           {
3561                         $$ = $3;
3562                         $$->ifname = $2;
3563                 }
3564                 ;
3565
3566 route_host_list : route_host                            { $$ = $1; }
3567                 | route_host_list comma route_host      {
3568                         if ($1->af == 0)
3569                                 $1->af = $3->af;
3570                         if ($1->af != $3->af) {
3571                                 yyerror("all pool addresses must be in the "
3572                                     "same address family");
3573                                 YYERROR;
3574                         }
3575                         $1->tail->next = $3;
3576                         $1->tail = $3->tail;
3577                         $$ = $1;
3578                 }
3579                 ;
3580
3581 routespec       : route_host                    { $$ = $1; }
3582                 | '{' route_host_list '}'       { $$ = $2; }
3583                 ;
3584
3585 route           : /* empty */                   {
3586                         $$.host = NULL;
3587                         $$.rt = 0;
3588                         $$.pool_opts = 0;
3589                 }
3590                 | FASTROUTE {
3591                         $$.host = NULL;
3592                         $$.rt = PF_FASTROUTE;
3593                         $$.pool_opts = 0;
3594                 }
3595                 | ROUTETO routespec pool_opts {
3596                         $$.host = $2;
3597                         $$.rt = PF_ROUTETO;
3598                         $$.pool_opts = $3.type | $3.opts;
3599                         if ($3.key != NULL)
3600                                 $$.key = $3.key;
3601                 }
3602                 | REPLYTO routespec pool_opts {
3603                         $$.host = $2;
3604                         $$.rt = PF_REPLYTO;
3605                         $$.pool_opts = $3.type | $3.opts;
3606                         if ($3.key != NULL)
3607                                 $$.key = $3.key;
3608                 }
3609                 | DUPTO routespec pool_opts {
3610                         $$.host = $2;
3611                         $$.rt = PF_DUPTO;
3612                         $$.pool_opts = $3.type | $3.opts;
3613                         if ($3.key != NULL)
3614                                 $$.key = $3.key;
3615                 }
3616                 ;
3617
3618 timeout_spec    : STRING number
3619                 {
3620                         if (check_rulestate(PFCTL_STATE_OPTION)) {
3621                                 free($1);
3622                                 YYERROR;
3623                         }
3624                         if (pfctl_set_timeout(pf, $1, $2, 0) != 0) {
3625                                 yyerror("unknown timeout %s", $1);
3626                                 free($1);
3627                                 YYERROR;
3628                         }
3629                         free($1);
3630                 }
3631                 ;
3632
3633 timeout_list    : timeout_list comma timeout_spec
3634                 | timeout_spec
3635                 ;
3636
3637 limit_spec      : STRING number
3638                 {
3639                         if (check_rulestate(PFCTL_STATE_OPTION)) {
3640                                 free($1);
3641                                 YYERROR;
3642                         }
3643                         if (pfctl_set_limit(pf, $1, $2) != 0) {
3644                                 yyerror("unable to set limit %s %u", $1, $2);
3645                                 free($1);
3646                                 YYERROR;
3647                         }
3648                         free($1);
3649                 }
3650                 ;
3651
3652 limit_list      : limit_list comma limit_spec
3653                 | limit_spec
3654                 ;
3655
3656 comma           : ','
3657                 | /* empty */
3658                 ;
3659
3660 yesno           : NO                    { $$ = 0; }
3661                 | STRING                {
3662                         if (!strcmp($1, "yes"))
3663                                 $$ = 1;
3664                         else {
3665                                 yyerror("invalid value '%s', expected 'yes' "
3666                                     "or 'no'", $1);
3667                                 free($1);
3668                                 YYERROR;
3669                         }
3670                         free($1);
3671                 }
3672                 ;
3673
3674 unaryop         : '='           { $$ = PF_OP_EQ; }
3675                 | '!' '='       { $$ = PF_OP_NE; }
3676                 | '<' '='       { $$ = PF_OP_LE; }
3677                 | '<'           { $$ = PF_OP_LT; }
3678                 | '>' '='       { $$ = PF_OP_GE; }
3679                 | '>'           { $$ = PF_OP_GT; }
3680                 ;
3681
3682 %%
3683
3684 int
3685 yyerror(const char *fmt, ...)
3686 {
3687         va_list          ap;
3688         extern char     *infile;
3689
3690         errors = 1;
3691         va_start(ap, fmt);
3692         fprintf(stderr, "%s:%d: ", infile, yylval.lineno);
3693         vfprintf(stderr, fmt, ap);
3694         fprintf(stderr, "\n");
3695         va_end(ap);
3696         return (0);
3697 }
3698
3699 int
3700 disallow_table(struct node_host *h, const char *fmt)
3701 {
3702         for (; h != NULL; h = h->next)
3703                 if (h->addr.type == PF_ADDR_TABLE) {
3704                         yyerror(fmt, h->addr.v.tblname);
3705                         return (1);
3706                 }
3707         return (0);
3708 }
3709
3710 int
3711 disallow_alias(struct node_host *h, const char *fmt)
3712 {
3713         for (; h != NULL; h = h->next)
3714                 if (DYNIF_MULTIADDR(h->addr)) {
3715                         yyerror(fmt, h->addr.v.tblname);
3716                         return (1);
3717                 }
3718         return (0);
3719 }
3720
3721 int
3722 rule_consistent(struct pf_rule *r)
3723 {
3724         int     problems = 0;
3725
3726         switch (r->action) {
3727         case PF_PASS:
3728         case PF_DROP:
3729         case PF_SCRUB:
3730         case PF_NOSCRUB:
3731                 problems = filter_consistent(r);
3732                 break;
3733         case PF_NAT:
3734         case PF_NONAT:
3735                 problems = nat_consistent(r);
3736                 break;
3737         case PF_RDR:
3738         case PF_NORDR:
3739                 problems = rdr_consistent(r);
3740                 break;
3741         case PF_BINAT:
3742         case PF_NOBINAT:
3743         default:
3744                 break;
3745         }
3746         return (problems);
3747 }
3748
3749 int
3750 filter_consistent(struct pf_rule *r)
3751 {
3752         int     problems = 0;
3753
3754         if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP &&
3755             (r->src.port_op || r->dst.port_op)) {
3756                 yyerror("port only applies to tcp/udp");
3757                 problems++;
3758         }
3759         if (r->proto != IPPROTO_ICMP && r->proto != IPPROTO_ICMPV6 &&
3760             (r->type || r->code)) {
3761                 yyerror("icmp-type/code only applies to icmp");
3762                 problems++;
3763         }
3764         if (!r->af && (r->type || r->code)) {
3765                 yyerror("must indicate address family with icmp-type/code");
3766                 problems++;
3767         }
3768         if (r->overload_tblname[0] &&
3769             r->max_src_conn == 0 && r->max_src_conn_rate.seconds == 0) {
3770                 yyerror("'overload' requires 'max-src-conn' "
3771                     "or 'max-src-conn-rate'");
3772                 problems++;
3773         }
3774         if ((r->proto == IPPROTO_ICMP && r->af == AF_INET6) ||
3775             (r->proto == IPPROTO_ICMPV6 && r->af == AF_INET)) {
3776                 yyerror("proto %s doesn't match address family %s",
3777                     r->proto == IPPROTO_ICMP ? "icmp" : "icmp6",
3778                     r->af == AF_INET ? "inet" : "inet6");
3779                 problems++;
3780         }
3781         if (r->allow_opts && r->action != PF_PASS) {
3782                 yyerror("allow-opts can only be specified for pass rules");
3783                 problems++;
3784         }
3785         if (r->rule_flag & PFRULE_FRAGMENT && (r->src.port_op ||
3786             r->dst.port_op || r->flagset || r->type || r->code)) {
3787                 yyerror("fragments can be filtered only on IP header fields");
3788                 problems++;
3789         }
3790         if (r->rule_flag & PFRULE_RETURNRST && r->proto != IPPROTO_TCP) {
3791                 yyerror("return-rst can only be applied to TCP rules");
3792                 problems++;
3793         }
3794         if (r->max_src_nodes && !(r->rule_flag & PFRULE_RULESRCTRACK)) {
3795                 yyerror("max-src-nodes requires 'source-track rule'");
3796                 problems++;
3797         }
3798         if (r->action == PF_DROP && r->keep_state) {
3799                 yyerror("keep state on block rules doesn't make sense");
3800                 problems++;
3801         }
3802         if ((r->tagname[0] || r->match_tagname[0]) && !r->keep_state &&
3803             r->action == PF_PASS) {
3804                 yyerror("tags cannot be used without keep state");
3805                 problems++;
3806         }
3807         return (-problems);
3808 }
3809
3810 int
3811 nat_consistent(struct pf_rule *r)
3812 {
3813         return (0);     /* yeah! */
3814 }
3815
3816 int
3817 rdr_consistent(struct pf_rule *r)
3818 {
3819         int                      problems = 0;
3820
3821         if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP) {
3822                 if (r->src.port_op) {
3823                         yyerror("src port only applies to tcp/udp");
3824                         problems++;
3825                 }
3826                 if (r->dst.port_op) {
3827                         yyerror("dst port only applies to tcp/udp");
3828                         problems++;
3829                 }
3830                 if (r->rpool.proxy_port[0]) {
3831                         yyerror("rpool port only applies to tcp/udp");
3832                         problems++;
3833                 }
3834         }
3835         if (r->dst.port_op &&
3836             r->dst.port_op != PF_OP_EQ && r->dst.port_op != PF_OP_RRG) {
3837                 yyerror("invalid port operator for rdr destination port");
3838                 problems++;
3839         }
3840         return (-problems);
3841 }
3842
3843 int
3844 process_tabledef(char *name, struct table_opts *opts)
3845 {
3846         struct pfr_buffer        ab;
3847         struct node_tinit       *ti;
3848
3849         bzero(&ab, sizeof(ab));
3850         ab.pfrb_type = PFRB_ADDRS;
3851         SIMPLEQ_FOREACH(ti, &opts->init_nodes, entries) {
3852                 if (ti->file)
3853                         if (pfr_buf_load(&ab, ti->file, 0, append_addr)) {
3854                                 if (errno)
3855                                         yyerror("cannot load \"%s\": %s",
3856                                             ti->file, strerror(errno));
3857                                 else
3858                                         yyerror("file \"%s\" contains bad data",
3859                                             ti->file);
3860                                 goto _error;
3861                         }
3862                 if (ti->host)
3863                         if (append_addr_host(&ab, ti->host, 0, 0)) {
3864                                 yyerror("cannot create address buffer: %s",
3865                                     strerror(errno));
3866                                 goto _error;
3867                         }
3868         }
3869         if (pf->opts & PF_OPT_VERBOSE)
3870                 print_tabledef(name, opts->flags, opts->init_addr,
3871                     &opts->init_nodes);
3872         if (!(pf->opts & PF_OPT_NOACTION) &&
3873             pfctl_define_table(name, opts->flags, opts->init_addr,
3874             pf->anchor, &ab, pf->tticket)) {
3875                 yyerror("cannot define table %s: %s", name,
3876                     pfr_strerror(errno));
3877                 goto _error;
3878         }
3879         pf->tdirty = 1;
3880         pfr_buf_clear(&ab);
3881         return (0);
3882 _error:
3883         pfr_buf_clear(&ab);
3884         return (-1);
3885 }
3886
3887 struct keywords {
3888         const char      *k_name;
3889         int              k_val;
3890 };
3891
3892 /* macro gore, but you should've seen the prior indentation nightmare... */
3893
3894 #define FREE_LIST(T,r) \
3895         do { \
3896                 T *p, *node = r; \
3897                 while (node != NULL) { \
3898                         p = node; \
3899                         node = node->next; \
3900                         free(p); \
3901                 } \
3902         } while (0)
3903
3904 #define LOOP_THROUGH(T,n,r,C) \
3905         do { \
3906                 T *n; \
3907                 if (r == NULL) { \
3908                         r = calloc(1, sizeof(T)); \
3909                         if (r == NULL) \
3910                                 err(1, "LOOP: calloc"); \
3911                         r->next = NULL; \
3912                 } \
3913                 n = r; \
3914                 while (n != NULL) { \
3915                         do { \
3916                                 C; \
3917                         } while (0); \
3918                         n = n->next; \
3919                 } \
3920         } while (0)
3921
3922 void
3923 expand_label_str(char *label, size_t len, const char *srch, const char *repl)
3924 {
3925         char *tmp;
3926         char *p, *q;
3927
3928         if ((tmp = calloc(1, len)) == NULL)
3929                 err(1, "expand_label_str: calloc");
3930         p = q = label;
3931         while ((q = strstr(p, srch)) != NULL) {
3932                 *q = '\0';
3933                 if ((strlcat(tmp, p, len) >= len) ||
3934                     (strlcat(tmp, repl, len) >= len))
3935                         errx(1, "expand_label: label too long");
3936                 q += strlen(srch);
3937                 p = q;
3938         }
3939         if (strlcat(tmp, p, len) >= len)
3940                 errx(1, "expand_label: label too long");
3941         strlcpy(label, tmp, len);       /* always fits */
3942         free(tmp);
3943 }
3944
3945 void
3946 expand_label_if(const char *name, char *label, size_t len, const char *ifname)
3947 {
3948         if (strstr(label, name) != NULL) {
3949                 if (!*ifname)
3950                         expand_label_str(label, len, name, "any");
3951                 else
3952                         expand_label_str(label, len, name, ifname);
3953         }
3954 }
3955
3956 void
3957 expand_label_addr(const char *name, char *label, size_t len, sa_family_t af,
3958     struct node_host *h)
3959 {
3960         char tmp[64], tmp_not[66];
3961
3962         if (strstr(label, name) != NULL) {
3963                 switch (h->addr.type) {
3964                 case PF_ADDR_DYNIFTL:
3965                         snprintf(tmp, sizeof(tmp), "(%s)", h->addr.v.ifname);
3966                         break;
3967                 case PF_ADDR_TABLE:
3968                         snprintf(tmp, sizeof(tmp), "<%s>", h->addr.v.tblname);
3969                         break;
3970                 case PF_ADDR_NOROUTE:
3971                         snprintf(tmp, sizeof(tmp), "no-route");
3972                         break;
3973                 case PF_ADDR_ADDRMASK:
3974                         if (!af || (PF_AZERO(&h->addr.v.a.addr, af) &&
3975                             PF_AZERO(&h->addr.v.a.mask, af)))
3976                                 snprintf(tmp, sizeof(tmp), "any");
3977                         else {
3978                                 char    a[48];
3979                                 int     bits;
3980
3981                                 if (inet_ntop(af, &h->addr.v.a.addr, a,
3982                                     sizeof(a)) == NULL)
3983                                         snprintf(tmp, sizeof(tmp), "?");
3984                                 else {
3985                                         bits = unmask(&h->addr.v.a.mask, af);
3986                                         if ((af == AF_INET && bits < 32) ||
3987                                             (af == AF_INET6 && bits < 128))
3988                                                 snprintf(tmp, sizeof(tmp),
3989                                                     "%s/%d", a, bits);
3990                                         else
3991                                                 snprintf(tmp, sizeof(tmp),
3992                                                     "%s", a);
3993                                 }
3994                         }
3995                         break;
3996                 default:
3997                         snprintf(tmp, sizeof(tmp), "?");
3998                         break;
3999                 }
4000
4001                 if (h->not) {
4002                         snprintf(tmp_not, sizeof(tmp_not), "! %s", tmp);
4003                         expand_label_str(label, len, name, tmp_not);
4004                 } else
4005                         expand_label_str(label, len, name, tmp);
4006         }
4007 }
4008
4009 void
4010 expand_label_port(const char *name, char *label, size_t len,
4011     struct node_port *port)
4012 {
4013         char     a1[6], a2[6], op[13] = "";
4014
4015         if (strstr(label, name) != NULL) {
4016                 snprintf(a1, sizeof(a1), "%u", ntohs(port->port[0]));
4017                 snprintf(a2, sizeof(a2), "%u", ntohs(port->port[1]));
4018                 if (!port->op)
4019                         ;
4020                 else if (port->op == PF_OP_IRG)
4021                         snprintf(op, sizeof(op), "%s><%s", a1, a2);
4022                 else if (port->op == PF_OP_XRG)
4023                         snprintf(op, sizeof(op), "%s<>%s", a1, a2);
4024                 else if (port->op == PF_OP_EQ)
4025                         snprintf(op, sizeof(op), "%s", a1);
4026                 else if (port->op == PF_OP_NE)
4027                         snprintf(op, sizeof(op), "!=%s", a1);
4028                 else if (port->op == PF_OP_LT)
4029                         snprintf(op, sizeof(op), "<%s", a1);
4030                 else if (port->op == PF_OP_LE)
4031                         snprintf(op, sizeof(op), "<=%s", a1);
4032                 else if (port->op == PF_OP_GT)
4033                         snprintf(op, sizeof(op), ">%s", a1);
4034                 else if (port->op == PF_OP_GE)
4035                         snprintf(op, sizeof(op), ">=%s", a1);
4036                 expand_label_str(label, len, name, op);
4037         }
4038 }
4039
4040 void
4041 expand_label_proto(const char *name, char *label, size_t len, u_int8_t proto)
4042 {
4043         struct protoent *pe;
4044         char n[4];
4045
4046         if (strstr(label, name) != NULL) {
4047                 pe = getprotobynumber(proto);
4048                 if (pe != NULL)
4049                         expand_label_str(label, len, name, pe->p_name);
4050                 else {
4051                         snprintf(n, sizeof(n), "%u", proto);
4052                         expand_label_str(label, len, name, n);
4053                 }
4054         }
4055 }
4056
4057 void
4058 expand_label_nr(const char *name, char *label, size_t len)
4059 {
4060         char n[11];
4061
4062         if (strstr(label, name) != NULL) {
4063                 snprintf(n, sizeof(n), "%u", pf->rule_nr);
4064                 expand_label_str(label, len, name, n);
4065         }
4066 }
4067
4068 void
4069 expand_label(char *label, size_t len, const char *ifname, sa_family_t af,
4070     struct node_host *src_host, struct node_port *src_port,
4071     struct node_host *dst_host, struct node_port *dst_port,
4072     u_int8_t proto)
4073 {
4074         expand_label_if("$if", label, len, ifname);
4075         expand_label_addr("$srcaddr", label, len, af, src_host);
4076         expand_label_addr("$dstaddr", label, len, af, dst_host);
4077         expand_label_port("$srcport", label, len, src_port);
4078         expand_label_port("$dstport", label, len, dst_port);
4079         expand_label_proto("$proto", label, len, proto);
4080         expand_label_nr("$nr", label, len);
4081 }
4082
4083 int
4084 expand_altq(struct pf_altq *a, struct node_if *interfaces,
4085     struct node_queue *nqueues, struct node_queue_bw bwspec,
4086     struct node_queue_opt *opts)
4087 {
4088         struct pf_altq           pa, pb;
4089         char                     qname[PF_QNAME_SIZE];
4090         struct node_queue       *n;
4091         struct node_queue_bw     bw;
4092         int                      errs = 0;
4093
4094         if ((pf->loadopt & PFCTL_FLAG_ALTQ) == 0) {
4095                 FREE_LIST(struct node_if, interfaces);
4096                 FREE_LIST(struct node_queue, nqueues);
4097                 return (0);
4098         }
4099
4100         LOOP_THROUGH(struct node_if, interface, interfaces,
4101                 memcpy(&pa, a, sizeof(struct pf_altq));
4102                 if (strlcpy(pa.ifname, interface->ifname,
4103                     sizeof(pa.ifname)) >= sizeof(pa.ifname))
4104                         errx(1, "expand_altq: strlcpy");
4105
4106                 if (interface->not) {
4107                         yyerror("altq on ! <interface> is not supported");
4108                         errs++;
4109                 } else {
4110                         if (eval_pfaltq(pf, &pa, &bwspec, opts))
4111                                 errs++;
4112                         else
4113                                 if (pfctl_add_altq(pf, &pa))
4114                                         errs++;
4115
4116                         if (pf->opts & PF_OPT_VERBOSE) {
4117                                 print_altq(&pf->paltq->altq, 0,
4118                                     &bwspec, opts);
4119                                 if (nqueues && nqueues->tail) {
4120                                         printf("queue { ");
4121                                         LOOP_THROUGH(struct node_queue, queue,
4122                                             nqueues,
4123                                                 printf("%s ",
4124                                                     queue->queue);
4125                                         );
4126                                         printf("}");
4127                                 }
4128                                 printf("\n");
4129                         }
4130
4131                         if (pa.scheduler == ALTQT_CBQ ||
4132                             pa.scheduler == ALTQT_HFSC) {
4133                                 /* now create a root queue */
4134                                 memset(&pb, 0, sizeof(struct pf_altq));
4135                                 if (strlcpy(qname, "root_", sizeof(qname)) >=
4136                                     sizeof(qname))
4137                                         errx(1, "expand_altq: strlcpy");
4138                                 if (strlcat(qname, interface->ifname,
4139                                     sizeof(qname)) >= sizeof(qname))
4140                                         errx(1, "expand_altq: strlcat");
4141                                 if (strlcpy(pb.qname, qname,
4142                                     sizeof(pb.qname)) >= sizeof(pb.qname))
4143                                         errx(1, "expand_altq: strlcpy");
4144                                 if (strlcpy(pb.ifname, interface->ifname,
4145                                     sizeof(pb.ifname)) >= sizeof(pb.ifname))
4146                                         errx(1, "expand_altq: strlcpy");
4147                                 pb.qlimit = pa.qlimit;
4148                                 pb.scheduler = pa.scheduler;
4149                                 bw.bw_absolute = pa.ifbandwidth;
4150                                 bw.bw_percent = 0;
4151                                 if (eval_pfqueue(pf, &pb, &bw, opts))
4152                                         errs++;
4153                                 else
4154                                         if (pfctl_add_altq(pf, &pb))
4155                                                 errs++;
4156                         }
4157
4158                         LOOP_THROUGH(struct node_queue, queue, nqueues,
4159                                 n = calloc(1, sizeof(struct node_queue));
4160                                 if (n == NULL)
4161                                         err(1, "expand_altq: calloc");
4162                                 if (pa.scheduler == ALTQT_CBQ ||
4163                                     pa.scheduler == ALTQT_HFSC)
4164                                         if (strlcpy(n->parent, qname,
4165                                             sizeof(n->parent)) >=
4166                                             sizeof(n->parent))
4167                                                 errx(1, "expand_altq: strlcpy");
4168                                 if (strlcpy(n->queue, queue->queue,
4169                                     sizeof(n->queue)) >= sizeof(n->queue))
4170                                         errx(1, "expand_altq: strlcpy");
4171                                 if (strlcpy(n->ifname, interface->ifname,
4172                                     sizeof(n->ifname)) >= sizeof(n->ifname))
4173                                         errx(1, "expand_altq: strlcpy");
4174                                 n->scheduler = pa.scheduler;
4175                                 n->next = NULL;
4176                                 n->tail = n;
4177                                 if (queues == NULL)
4178                                         queues = n;
4179                                 else {
4180                                         queues->tail->next = n;
4181                                         queues->tail = n;
4182                                 }
4183                         );
4184                 }
4185         );
4186         FREE_LIST(struct node_if, interfaces);
4187         FREE_LIST(struct node_queue, nqueues);
4188
4189         return (errs);
4190 }
4191
4192 int
4193 expand_queue(struct pf_altq *a, struct node_if *interfaces,
4194     struct node_queue *nqueues, struct node_queue_bw bwspec,
4195     struct node_queue_opt *opts)
4196 {
4197         struct node_queue       *n, *nq;
4198         struct pf_altq           pa;
4199         u_int8_t                 found = 0;
4200         u_int8_t                 errs = 0;
4201
4202         if ((pf->loadopt & PFCTL_FLAG_ALTQ) == 0) {
4203                 FREE_LIST(struct node_queue, nqueues);
4204                 return (0);
4205         }
4206
4207         if (queues == NULL) {
4208                 yyerror("queue %s has no parent", a->qname);
4209                 FREE_LIST(struct node_queue, nqueues);
4210                 return (1);
4211         }
4212
4213         LOOP_THROUGH(struct node_if, interface, interfaces,
4214                 LOOP_THROUGH(struct node_queue, tqueue, queues,
4215                         if (!strncmp(a->qname, tqueue->queue, PF_QNAME_SIZE) &&
4216                             (interface->ifname[0] == 0 ||
4217                             (!interface->not && !strncmp(interface->ifname,
4218                             tqueue->ifname, IFNAMSIZ)) ||
4219                             (interface->not && strncmp(interface->ifname,
4220                             tqueue->ifname, IFNAMSIZ)))) {
4221                                 /* found ourself in queues */
4222                                 found++;
4223
4224                                 memcpy(&pa, a, sizeof(struct pf_altq));
4225
4226                                 if (pa.scheduler != ALTQT_NONE &&
4227                                     pa.scheduler != tqueue->scheduler) {
4228                                         yyerror("exactly one scheduler type "
4229                                             "per interface allowed");
4230                                         return (1);
4231                                 }
4232                                 pa.scheduler = tqueue->scheduler;
4233
4234                                 /* scheduler dependent error checking */
4235                                 switch (pa.scheduler) {
4236                                 case ALTQT_PRIQ:
4237                                         if (nqueues != NULL) {
4238                                                 yyerror("priq queues cannot "
4239                                                     "have child queues");
4240                                                 return (1);
4241                                         }
4242                                         if (bwspec.bw_absolute > 0 ||
4243                                             bwspec.bw_percent < 100) {
4244                                                 yyerror("priq doesn't take "
4245                                                     "bandwidth");
4246                                                 return (1);
4247                                         }
4248                                         break;
4249                                 default:
4250                                         break;
4251                                 }
4252
4253                                 if (strlcpy(pa.ifname, tqueue->ifname,
4254                                     sizeof(pa.ifname)) >= sizeof(pa.ifname))
4255                                         errx(1, "expand_queue: strlcpy");
4256                                 if (strlcpy(pa.parent, tqueue->parent,
4257                                     sizeof(pa.parent)) >= sizeof(pa.parent))
4258                                         errx(1, "expand_queue: strlcpy");
4259
4260                                 if (eval_pfqueue(pf, &pa, &bwspec, opts))
4261                                         errs++;
4262                                 else
4263                                         if (pfctl_add_altq(pf, &pa))
4264                                                 errs++;
4265
4266                                 for (nq = nqueues; nq != NULL; nq = nq->next) {
4267                                         if (!strcmp(a->qname, nq->queue)) {
4268                                                 yyerror("queue cannot have "
4269                                                     "itself as child");
4270                                                 errs++;
4271                                                 continue;
4272                                         }
4273                                         n = calloc(1,
4274                                             sizeof(struct node_queue));
4275                                         if (n == NULL)
4276                                                 err(1, "expand_queue: calloc");
4277                                         if (strlcpy(n->parent, a->qname,
4278                                             sizeof(n->parent)) >=
4279                                             sizeof(n->parent))
4280                                                 errx(1, "expand_queue strlcpy");
4281                                         if (strlcpy(n->queue, nq->queue,
4282                                             sizeof(n->queue)) >=
4283                                             sizeof(n->queue))
4284                                                 errx(1, "expand_queue strlcpy");
4285                                         if (strlcpy(n->ifname, tqueue->ifname,
4286                                             sizeof(n->ifname)) >=
4287                                             sizeof(n->ifname))
4288                                                 errx(1, "expand_queue strlcpy");
4289                                         n->scheduler = tqueue->scheduler;
4290                                         n->next = NULL;
4291                                         n->tail = n;
4292                                         if (queues == NULL)
4293                                                 queues = n;
4294                                         else {
4295                                                 queues->tail->next = n;
4296                                                 queues->tail = n;
4297                                         }
4298                                 }
4299                                 if ((pf->opts & PF_OPT_VERBOSE) && (
4300                                     (found == 1 && interface->ifname[0] == 0) ||
4301                                     (found > 0 && interface->ifname[0] != 0))) {
4302                                         print_queue(&pf->paltq->altq, 0,
4303                                             &bwspec, interface->ifname[0] != 0,
4304                                             opts);
4305                                         if (nqueues && nqueues->tail) {
4306                                                 printf("{ ");
4307                                                 LOOP_THROUGH(struct node_queue,
4308                                                     queue, nqueues,
4309                                                         printf("%s ",
4310                                                             queue->queue);
4311                                                 );
4312                                                 printf("}");
4313                                         }
4314                                         printf("\n");
4315                                 }
4316                         }
4317                 );
4318         );
4319
4320         FREE_LIST(struct node_queue, nqueues);
4321         FREE_LIST(struct node_if, interfaces);
4322
4323         if (!found) {
4324                 yyerror("queue %s has no parent", a->qname);
4325                 errs++;
4326         }
4327
4328         if (errs)
4329                 return (1);
4330         else
4331                 return (0);
4332 }
4333
4334 void
4335 expand_rule(struct pf_rule *r,
4336     struct node_if *interfaces, struct node_host *rpool_hosts,
4337     struct node_proto *protos, struct node_os *src_oses,
4338     struct node_host *src_hosts, struct node_port *src_ports,
4339     struct node_host *dst_hosts, struct node_port *dst_ports,
4340     struct node_uid *uids, struct node_gid *gids, struct node_icmp *icmp_types,
4341     const char *anchor_call)
4342 {
4343         sa_family_t              af = r->af;
4344         int                      added = 0, error = 0;
4345         char                     ifname[IF_NAMESIZE];
4346         char                     label[PF_RULE_LABEL_SIZE];
4347         char                     tagname[PF_TAG_NAME_SIZE];
4348         char                     match_tagname[PF_TAG_NAME_SIZE];
4349         struct pf_pooladdr      *pa;
4350         struct node_host        *h;
4351         u_int8_t                 flags, flagset, keep_state;
4352
4353         if (strlcpy(label, r->label, sizeof(label)) >= sizeof(label))
4354                 errx(1, "expand_rule: strlcpy");
4355         if (strlcpy(tagname, r->tagname, sizeof(tagname)) >= sizeof(tagname))
4356                 errx(1, "expand_rule: strlcpy");
4357         if (strlcpy(match_tagname, r->match_tagname, sizeof(match_tagname)) >=
4358             sizeof(match_tagname))
4359                 errx(1, "expand_rule: strlcpy");
4360         flags = r->flags;
4361         flagset = r->flagset;
4362         keep_state = r->keep_state;
4363
4364         LOOP_THROUGH(struct node_if, interface, interfaces,
4365         LOOP_THROUGH(struct node_proto, proto, protos,
4366         LOOP_THROUGH(struct node_icmp, icmp_type, icmp_types,
4367         LOOP_THROUGH(struct node_host, src_host, src_hosts,
4368         LOOP_THROUGH(struct node_port, src_port, src_ports,
4369         LOOP_THROUGH(struct node_os, src_os, src_oses,
4370         LOOP_THROUGH(struct node_host, dst_host, dst_hosts,
4371         LOOP_THROUGH(struct node_port, dst_port, dst_ports,
4372         LOOP_THROUGH(struct node_uid, uid, uids,
4373         LOOP_THROUGH(struct node_gid, gid, gids,
4374
4375                 r->af = af;
4376                 /* for link-local IPv6 address, interface must match up */
4377                 if ((r->af && src_host->af && r->af != src_host->af) ||
4378                     (r->af && dst_host->af && r->af != dst_host->af) ||
4379                     (src_host->af && dst_host->af &&
4380                     src_host->af != dst_host->af) ||
4381                     (src_host->ifindex && dst_host->ifindex &&
4382                     src_host->ifindex != dst_host->ifindex) ||
4383                     (src_host->ifindex && *interface->ifname &&
4384                     src_host->ifindex != if_nametoindex(interface->ifname)) ||
4385                     (dst_host->ifindex && *interface->ifname &&
4386                     dst_host->ifindex != if_nametoindex(interface->ifname)))
4387                         continue;
4388                 if (!r->af && src_host->af)
4389                         r->af = src_host->af;
4390                 else if (!r->af && dst_host->af)
4391                         r->af = dst_host->af;
4392
4393                 if (*interface->ifname)
4394                         strlcpy(r->ifname, interface->ifname,
4395                             sizeof(r->ifname));
4396                 else if (if_indextoname(src_host->ifindex, ifname))
4397                         strlcpy(r->ifname, ifname, sizeof(r->ifname));
4398                 else if (if_indextoname(dst_host->ifindex, ifname))
4399                         strlcpy(r->ifname, ifname, sizeof(r->ifname));
4400                 else
4401                         memset(r->ifname, '\0', sizeof(r->ifname));
4402
4403                 if (strlcpy(r->label, label, sizeof(r->label)) >=
4404                     sizeof(r->label))
4405                         errx(1, "expand_rule: strlcpy");
4406                 if (strlcpy(r->tagname, tagname, sizeof(r->tagname)) >=
4407                     sizeof(r->tagname))
4408                         errx(1, "expand_rule: strlcpy");
4409                 if (strlcpy(r->match_tagname, match_tagname,
4410                     sizeof(r->match_tagname)) >= sizeof(r->match_tagname))
4411                         errx(1, "expand_rule: strlcpy");
4412                 expand_label(r->label, PF_RULE_LABEL_SIZE, r->ifname, r->af,
4413                     src_host, src_port, dst_host, dst_port, proto->proto);
4414                 expand_label(r->tagname, PF_TAG_NAME_SIZE, r->ifname, r->af,
4415                     src_host, src_port, dst_host, dst_port, proto->proto);
4416                 expand_label(r->match_tagname, PF_TAG_NAME_SIZE, r->ifname,
4417                     r->af, src_host, src_port, dst_host, dst_port,
4418                     proto->proto);
4419
4420                 error += check_netmask(src_host, r->af);
4421                 error += check_netmask(dst_host, r->af);
4422
4423                 r->ifnot = interface->not;
4424                 r->proto = proto->proto;
4425                 r->src.addr = src_host->addr;
4426                 r->src.neg = src_host->not;
4427                 r->src.port[0] = src_port->port[0];
4428                 r->src.port[1] = src_port->port[1];
4429                 r->src.port_op = src_port->op;
4430                 r->dst.addr = dst_host->addr;
4431                 r->dst.neg = dst_host->not;
4432                 r->dst.port[0] = dst_port->port[0];
4433                 r->dst.port[1] = dst_port->port[1];
4434                 r->dst.port_op = dst_port->op;
4435                 r->uid.op = uid->op;
4436                 r->uid.uid[0] = uid->uid[0];
4437                 r->uid.uid[1] = uid->uid[1];
4438                 r->gid.op = gid->op;
4439                 r->gid.gid[0] = gid->gid[0];
4440                 r->gid.gid[1] = gid->gid[1];
4441                 r->type = icmp_type->type;
4442                 r->code = icmp_type->code;
4443
4444                 if ((keep_state == PF_STATE_MODULATE ||
4445                     keep_state == PF_STATE_SYNPROXY) &&
4446                     r->proto && r->proto != IPPROTO_TCP)
4447                         r->keep_state = PF_STATE_NORMAL;
4448                 else
4449                         r->keep_state = keep_state;
4450
4451                 if (r->proto && r->proto != IPPROTO_TCP) {
4452                         r->flags = 0;
4453                         r->flagset = 0;
4454                 } else {
4455                         r->flags = flags;
4456                         r->flagset = flagset;
4457                 }
4458                 if (icmp_type->proto && r->proto != icmp_type->proto) {
4459                         yyerror("icmp-type mismatch");
4460                         error++;
4461                 }
4462
4463                 if (src_os && src_os->os) {
4464                         r->os_fingerprint = pfctl_get_fingerprint(src_os->os);
4465                         if ((pf->opts & PF_OPT_VERBOSE2) &&
4466                             r->os_fingerprint == PF_OSFP_NOMATCH)
4467                                 fprintf(stderr,
4468                                     "warning: unknown '%s' OS fingerprint\n",
4469                                     src_os->os);
4470                 } else {
4471                         r->os_fingerprint = PF_OSFP_ANY;
4472                 }
4473
4474                 TAILQ_INIT(&r->rpool.list);
4475                 for (h = rpool_hosts; h != NULL; h = h->next) {
4476                         pa = calloc(1, sizeof(struct pf_pooladdr));
4477                         if (pa == NULL)
4478                                 err(1, "expand_rule: calloc");
4479                         pa->addr = h->addr;
4480                         if (h->ifname != NULL) {
4481                                 if (strlcpy(pa->ifname, h->ifname,
4482                                     sizeof(pa->ifname)) >=
4483                                     sizeof(pa->ifname))
4484                                         errx(1, "expand_rule: strlcpy");
4485                         } else
4486                                 pa->ifname[0] = 0;
4487                         TAILQ_INSERT_TAIL(&r->rpool.list, pa, entries);
4488                 }
4489
4490                 if (rule_consistent(r) < 0 || error)
4491                         yyerror("skipping rule due to errors");
4492                 else {
4493                         r->nr = pf->rule_nr++;
4494                         pfctl_add_rule(pf, r, anchor_call);
4495                         added++;
4496                 }
4497
4498         ))))))))));
4499
4500         FREE_LIST(struct node_if, interfaces);
4501         FREE_LIST(struct node_proto, protos);
4502         FREE_LIST(struct node_host, src_hosts);
4503         FREE_LIST(struct node_port, src_ports);
4504         FREE_LIST(struct node_os, src_oses);
4505         FREE_LIST(struct node_host, dst_hosts);
4506         FREE_LIST(struct node_port, dst_ports);
4507         FREE_LIST(struct node_uid, uids);
4508         FREE_LIST(struct node_gid, gids);
4509         FREE_LIST(struct node_icmp, icmp_types);
4510         FREE_LIST(struct node_host, rpool_hosts);
4511
4512         if (!added)
4513                 yyerror("rule expands to no valid combination");
4514 }
4515
4516 int
4517 expand_skip_interface(struct node_if *interfaces)
4518 {
4519         int     errs = 0;
4520
4521         if (!interfaces || (!interfaces->next && !interfaces->not &&
4522             !strcmp(interfaces->ifname, "none"))) {
4523                 if (pf->opts & PF_OPT_VERBOSE)
4524                         printf("set skip on none\n");
4525                 errs = pfctl_set_interface_flags(pf, "", PFI_IFLAG_SKIP, 0);
4526                 return (errs);
4527         }
4528
4529         if (pf->opts & PF_OPT_VERBOSE)
4530                 printf("set skip on {");
4531         LOOP_THROUGH(struct node_if, interface, interfaces,
4532                 if (pf->opts & PF_OPT_VERBOSE)
4533                         printf(" %s", interface->ifname);
4534                 if (interface->not) {
4535                         yyerror("skip on ! <interface> is not supported");
4536                         errs++;
4537                 } else
4538                         errs += pfctl_set_interface_flags(pf,
4539                             interface->ifname, PFI_IFLAG_SKIP, 1);
4540         );
4541         if (pf->opts & PF_OPT_VERBOSE)
4542                 printf(" }\n");
4543
4544         FREE_LIST(struct node_if, interfaces);
4545
4546         if (errs)
4547                 return (1);
4548         else
4549                 return (0);
4550 }
4551
4552 #undef FREE_LIST
4553 #undef LOOP_THROUGH
4554
4555 int
4556 check_rulestate(int desired_state)
4557 {
4558         if (require_order && (rulestate > desired_state)) {
4559                 yyerror("Rules must be in order: options, normalization, "
4560                     "queueing, translation, filtering");
4561                 return (1);
4562         }
4563         rulestate = desired_state;
4564         return (0);
4565 }
4566
4567 int
4568 kw_cmp(const void *k, const void *e)
4569 {
4570         return (strcmp(k, ((const struct keywords *)e)->k_name));
4571 }
4572
4573 int
4574 lookup(char *s)
4575 {
4576         /* this has to be sorted always */
4577         static const struct keywords keywords[] = {
4578                 { "all",                ALL},
4579                 { "allow-opts",         ALLOWOPTS},
4580                 { "altq",               ALTQ},
4581                 { "anchor",             ANCHOR},
4582                 { "antispoof",          ANTISPOOF},
4583                 { "any",                ANY},
4584                 { "bandwidth",          BANDWIDTH},
4585                 { "binat",              BINAT},
4586                 { "binat-anchor",       BINATANCHOR},
4587                 { "bitmask",            BITMASK},
4588                 { "block",              BLOCK},
4589                 { "block-policy",       BLOCKPOLICY},
4590                 { "cbq",                CBQ},
4591                 { "code",               CODE},
4592                 { "crop",               FRAGCROP},
4593                 { "debug",              DEBUG},
4594                 { "drop",               DROP},
4595                 { "drop-ovl",           FRAGDROP},
4596                 { "dup-to",             DUPTO},
4597                 { "fastroute",          FASTROUTE},
4598                 { "file",               FILENAME},
4599                 { "fingerprints",       FINGERPRINTS},
4600                 { "flags",              FLAGS},
4601                 { "floating",           FLOATING},
4602                 { "flush",              FLUSH},
4603                 { "for",                FOR},
4604                 { "fragment",           FRAGMENT},
4605                 { "from",               FROM},
4606                 { "global",             GLOBAL},
4607                 { "group",              GROUP},
4608                 { "group-bound",        GRBOUND},
4609                 { "hfsc",               HFSC},
4610                 { "hostid",             HOSTID},
4611                 { "icmp-type",          ICMPTYPE},
4612                 { "icmp6-type",         ICMP6TYPE},
4613                 { "if-bound",           IFBOUND},
4614                 { "in",                 IN},
4615                 { "inet",               INET},
4616                 { "inet6",              INET6},
4617                 { "keep",               KEEP},
4618                 { "label",              LABEL},
4619                 { "limit",              LIMIT},
4620                 { "linkshare",          LINKSHARE},
4621                 { "load",               LOAD},
4622                 { "log",                LOG},
4623                 { "log-all",            LOGALL},
4624                 { "loginterface",       LOGINTERFACE},
4625                 { "max",                MAXIMUM},
4626                 { "max-mss",            MAXMSS},
4627                 { "max-src-conn",       MAXSRCCONN},
4628                 { "max-src-conn-rate",  MAXSRCCONNRATE},
4629                 { "max-src-nodes",      MAXSRCNODES},
4630                 { "max-src-states",     MAXSRCSTATES},
4631                 { "min-ttl",            MINTTL},
4632                 { "modulate",           MODULATE},
4633                 { "nat",                NAT},
4634                 { "nat-anchor",         NATANCHOR},
4635                 { "no",                 NO},
4636                 { "no-df",              NODF},
4637                 { "no-route",           NOROUTE},
4638                 { "no-sync",            NOSYNC},
4639                 { "on",                 ON},
4640                 { "optimization",       OPTIMIZATION},
4641                 { "os",                 OS},
4642                 { "out",                OUT},
4643                 { "overload",           OVERLOAD},
4644                 { "pass",               PASS},
4645                 { "port",               PORT},
4646                 { "priority",           PRIORITY},
4647                 { "priq",               PRIQ},
4648                 { "probability",        PROBABILITY},
4649                 { "proto",              PROTO},
4650                 { "qlimit",             QLIMIT},
4651                 { "queue",              QUEUE},
4652                 { "quick",              QUICK},
4653                 { "random",             RANDOM},
4654                 { "random-id",          RANDOMID},
4655                 { "rdr",                RDR},
4656                 { "rdr-anchor",         RDRANCHOR},
4657                 { "realtime",           REALTIME},
4658                 { "reassemble",         REASSEMBLE},
4659                 { "reply-to",           REPLYTO},
4660                 { "require-order",      REQUIREORDER},
4661                 { "return",             RETURN},
4662                 { "return-icmp",        RETURNICMP},
4663                 { "return-icmp6",       RETURNICMP6},
4664                 { "return-rst",         RETURNRST},
4665                 { "round-robin",        ROUNDROBIN},
4666                 { "route",              ROUTE},
4667                 { "route-to",           ROUTETO},
4668                 { "rule",               RULE},
4669                 { "scrub",              SCRUB},
4670                 { "set",                SET},
4671                 { "skip",               SKIP},
4672                 { "source-hash",        SOURCEHASH},
4673                 { "source-track",       SOURCETRACK},
4674                 { "state",              STATE},
4675                 { "state-policy",       STATEPOLICY},
4676                 { "static-port",        STATICPORT},
4677                 { "sticky-address",     STICKYADDRESS},
4678                 { "synproxy",           SYNPROXY},
4679                 { "table",              TABLE},
4680                 { "tag",                TAG},
4681                 { "tagged",             TAGGED},
4682                 { "tbrsize",            TBRSIZE},
4683                 { "timeout",            TIMEOUT},
4684                 { "to",                 TO},
4685                 { "tos",                TOS},
4686                 { "ttl",                TTL},
4687                 { "upperlimit",         UPPERLIMIT},
4688                 { "user",               USER},
4689         };
4690         const struct keywords   *p;
4691
4692         p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
4693             sizeof(keywords[0]), kw_cmp);
4694
4695         if (p) {
4696                 if (debug > 1)
4697                         fprintf(stderr, "%s: %d\n", s, p->k_val);
4698                 return (p->k_val);
4699         } else {
4700                 if (debug > 1)
4701                         fprintf(stderr, "string: %s\n", s);
4702                 return (STRING);
4703         }
4704 }
4705
4706 #define MAXPUSHBACK     128
4707
4708 char    *parsebuf;
4709 int      parseindex;
4710 char     pushback_buffer[MAXPUSHBACK];
4711 int      pushback_index = 0;
4712
4713 int
4714 lgetc(FILE *f)
4715 {
4716         int     c, next;
4717
4718         if (parsebuf) {
4719                 /* Read character from the parsebuffer instead of input. */
4720                 if (parseindex >= 0) {
4721                         c = parsebuf[parseindex++];
4722                         if (c != '\0')
4723                                 return (c);
4724                         parsebuf = NULL;
4725                 } else
4726                         parseindex++;
4727         }
4728
4729         if (pushback_index)
4730                 return (pushback_buffer[--pushback_index]);
4731
4732         while ((c = getc(f)) == '\\') {
4733                 next = getc(f);
4734                 if (next != '\n') {
4735                         if (isspace(next))
4736                                 yyerror("whitespace after \\");
4737                         ungetc(next, f);
4738                         break;
4739                 }
4740                 yylval.lineno = lineno;
4741                 lineno++;
4742         }
4743         if (c == '\t' || c == ' ') {
4744                 /* Compress blanks to a single space. */
4745                 do {
4746                         c = getc(f);
4747                 } while (c == '\t' || c == ' ');
4748                 ungetc(c, f);
4749                 c = ' ';
4750         }
4751
4752         return (c);
4753 }
4754
4755 int
4756 lungetc(int c)
4757 {
4758         if (c == EOF)
4759                 return (EOF);
4760         if (parsebuf) {
4761                 parseindex--;
4762                 if (parseindex >= 0)
4763                         return (c);
4764         }
4765         if (pushback_index < MAXPUSHBACK-1)
4766                 return (pushback_buffer[pushback_index++] = c);
4767         else
4768                 return (EOF);
4769 }
4770
4771 int
4772 findeol(void)
4773 {
4774         int     c;
4775
4776         parsebuf = NULL;
4777         pushback_index = 0;
4778
4779         /* skip to either EOF or the first real EOL */
4780         while (1) {
4781                 c = lgetc(fin);
4782                 if (c == '\n') {
4783                         lineno++;
4784                         break;
4785                 }
4786                 if (c == EOF)
4787                         break;
4788         }
4789         return (ERROR);
4790 }
4791
4792 int
4793 yylex(void)
4794 {
4795         char     buf[8096];
4796         char    *p, *val;
4797         int      endc, c, next;
4798         int      token;
4799
4800 top:
4801         p = buf;
4802         while ((c = lgetc(fin)) == ' ')
4803                 ; /* nothing */
4804
4805         yylval.lineno = lineno;
4806         if (c == '#')
4807                 while ((c = lgetc(fin)) != '\n' && c != EOF)
4808                         ; /* nothing */
4809         if (c == '$' && parsebuf == NULL) {
4810                 while (1) {
4811                         if ((c = lgetc(fin)) == EOF)
4812                                 return (0);
4813
4814                         if (p + 1 >= buf + sizeof(buf) - 1) {
4815                                 yyerror("string too long");
4816                                 return (findeol());
4817                         }
4818                         if (isalnum(c) || c == '_') {
4819                                 *p++ = (char)c;
4820                                 continue;
4821                         }
4822                         *p = '\0';
4823                         lungetc(c);
4824                         break;
4825                 }
4826                 val = symget(buf);
4827                 if (val == NULL) {
4828                         yyerror("macro '%s' not defined", buf);
4829                         return (findeol());
4830                 }
4831                 parsebuf = val;
4832                 parseindex = 0;
4833                 goto top;
4834         }
4835
4836         switch (c) {
4837         case '\'':
4838         case '"':
4839                 endc = c;
4840                 while (1) {
4841                         if ((c = lgetc(fin)) == EOF)
4842                                 return (0);
4843                         if (c == endc) {
4844                                 *p = '\0';
4845                                 break;
4846                         }
4847                         if (c == '\n') {
4848                                 lineno++;
4849                                 continue;
4850                         }
4851                         if (p + 1 >= buf + sizeof(buf) - 1) {
4852                                 yyerror("string too long");
4853                                 return (findeol());
4854                         }
4855                         *p++ = (char)c;
4856                 }
4857                 yylval.v.string = strdup(buf);
4858                 if (yylval.v.string == NULL)
4859                         err(1, "yylex: strdup");
4860                 return (STRING);
4861         case '<':
4862                 next = lgetc(fin);
4863                 if (next == '>') {
4864                         yylval.v.i = PF_OP_XRG;
4865                         return (PORTBINARY);
4866                 }
4867                 lungetc(next);
4868                 break;
4869         case '>':
4870                 next = lgetc(fin);
4871                 if (next == '<') {
4872                         yylval.v.i = PF_OP_IRG;
4873                         return (PORTBINARY);
4874                 }
4875                 lungetc(next);
4876                 break;
4877         case '-':
4878                 next = lgetc(fin);
4879                 if (next == '>')
4880                         return (ARROW);
4881                 lungetc(next);
4882                 break;
4883         }
4884
4885 #define allowed_in_string(x) \
4886         (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
4887         x != '{' && x != '}' && x != '<' && x != '>' && \
4888         x != '!' && x != '=' && x != '/' && x != '#' && \
4889         x != ','))
4890
4891         if (isalnum(c) || c == ':' || c == '_') {
4892                 do {
4893                         *p++ = c;
4894                         if ((unsigned)(p-buf) >= sizeof(buf)) {
4895                                 yyerror("string too long");
4896                                 return (findeol());
4897                         }
4898                 } while ((c = lgetc(fin)) != EOF && (allowed_in_string(c)));
4899                 lungetc(c);
4900                 *p = '\0';
4901                 if ((token = lookup(buf)) == STRING)
4902                         if ((yylval.v.string = strdup(buf)) == NULL)
4903                                 err(1, "yylex: strdup");
4904                 return (token);
4905         }
4906         if (c == '\n') {
4907                 yylval.lineno = lineno;
4908                 lineno++;
4909         }
4910         if (c == EOF)
4911                 return (0);
4912         return (c);
4913 }
4914
4915 int
4916 parse_rules(FILE *input, struct pfctl *xpf)
4917 {
4918         struct sym      *sym, *next;
4919
4920         fin = input;
4921         pf = xpf;
4922         lineno = 1;
4923         errors = 0;
4924         rulestate = PFCTL_STATE_NONE;
4925         returnicmpdefault = (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT;
4926         returnicmp6default =
4927             (ICMP6_DST_UNREACH << 8) | ICMP6_DST_UNREACH_NOPORT;
4928         blockpolicy = PFRULE_DROP;
4929         require_order = 1;
4930
4931         yyparse();
4932
4933         /* Free macros and check which have not been used. */
4934         for (sym = TAILQ_FIRST(&symhead); sym != NULL; sym = next) {
4935                 next = TAILQ_NEXT(sym, entries);
4936                 if ((pf->opts & PF_OPT_VERBOSE2) && !sym->used)
4937                         fprintf(stderr, "warning: macro '%s' not "
4938                             "used\n", sym->nam);
4939                 free(sym->nam);
4940                 free(sym->val);
4941                 TAILQ_REMOVE(&symhead, sym, entries);
4942                 free(sym);
4943         }
4944
4945         return (errors ? -1 : 0);
4946 }
4947
4948 /*
4949  * Over-designed efficiency is a French and German concept, so how about
4950  * we wait until they discover this ugliness and make it all fancy.
4951  */
4952 int
4953 symset(const char *nam, const char *val, int persist)
4954 {
4955         struct sym      *sym;
4956
4957         for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam);
4958             sym = TAILQ_NEXT(sym, entries))
4959                 ;       /* nothing */
4960
4961         if (sym != NULL) {
4962                 if (sym->persist == 1)
4963                         return (0);
4964                 else {
4965                         free(sym->nam);
4966                         free(sym->val);
4967                         TAILQ_REMOVE(&symhead, sym, entries);
4968                         free(sym);
4969                 }
4970         }
4971         if ((sym = calloc(1, sizeof(*sym))) == NULL)
4972                 return (-1);
4973
4974         sym->nam = strdup(nam);
4975         if (sym->nam == NULL) {
4976                 free(sym);
4977                 return (-1);
4978         }
4979         sym->val = strdup(val);
4980         if (sym->val == NULL) {
4981                 free(sym->nam);
4982                 free(sym);
4983                 return (-1);
4984         }
4985         sym->used = 0;
4986         sym->persist = persist;
4987         TAILQ_INSERT_TAIL(&symhead, sym, entries);
4988         return (0);
4989 }
4990
4991 int
4992 pfctl_cmdline_symset(char *s)
4993 {
4994         char    *sym, *val;
4995         int      ret;
4996
4997         if ((val = strrchr(s, '=')) == NULL)
4998                 return (-1);
4999
5000         if ((sym = malloc(strlen(s) - strlen(val) + 1)) == NULL)
5001                 err(1, "pfctl_cmdline_symset: malloc");
5002
5003         strlcpy(sym, s, strlen(s) - strlen(val) + 1);
5004
5005         ret = symset(sym, val + 1, 1);
5006         free(sym);
5007
5008         return (ret);
5009 }
5010
5011 char *
5012 symget(const char *nam)
5013 {
5014         struct sym      *sym;
5015
5016         TAILQ_FOREACH(sym, &symhead, entries)
5017                 if (strcmp(nam, sym->nam) == 0) {
5018                         sym->used = 1;
5019                         return (sym->val);
5020                 }
5021         return (NULL);
5022 }
5023
5024 void
5025 decide_address_family(struct node_host *n, sa_family_t *af)
5026 {
5027         sa_family_t     target_af = 0;
5028
5029         while (!*af && n != NULL) {
5030                 if (n->af) {
5031                         if (target_af == 0)
5032                                 target_af = n->af;
5033                         if (target_af != n->af)
5034                                 return;
5035                 }
5036                 n = n->next;
5037         }
5038         if (!*af && target_af)
5039                 *af = target_af;
5040 }
5041
5042 void
5043 remove_invalid_hosts(struct node_host **nh, sa_family_t *af)
5044 {
5045         struct node_host        *n = *nh, *prev = NULL;
5046
5047         while (n != NULL) {
5048                 if (*af && n->af && n->af != *af) {
5049                         /* unlink and free n */
5050                         struct node_host *next = n->next;
5051
5052                         /* adjust tail pointer */
5053                         if (n == (*nh)->tail)
5054                                 (*nh)->tail = prev;
5055                         /* adjust previous node's next pointer */
5056                         if (prev == NULL)
5057                                 *nh = next;
5058                         else
5059                                 prev->next = next;
5060                         /* free node */
5061                         if (n->ifname != NULL)
5062                                 free(n->ifname);
5063                         free(n);
5064                         n = next;
5065                 } else {
5066                         if (n->af && !*af)
5067                                 *af = n->af;
5068                         prev = n;
5069                         n = n->next;
5070                 }
5071         }
5072 }
5073
5074 int
5075 invalid_redirect(struct node_host *nh, sa_family_t af)
5076 {
5077         if (!af) {
5078                 struct node_host *n;
5079
5080                 /* tables and dyniftl are ok without an address family */
5081                 for (n = nh; n != NULL; n = n->next) {
5082                         if (n->addr.type != PF_ADDR_TABLE &&
5083                             n->addr.type != PF_ADDR_DYNIFTL) {
5084                                 yyerror("address family not given and "
5085                                     "translation address expands to multiple "
5086                                     "address families");
5087                                 return (1);
5088                         }
5089                 }
5090         }
5091         if (nh == NULL) {
5092                 yyerror("no translation address with matching address family "
5093                     "found.");
5094                 return (1);
5095         }
5096         return (0);
5097 }
5098
5099 int
5100 atoul(char *s, u_long *ulvalp)
5101 {
5102         u_long   ulval;
5103         char    *ep;
5104
5105         errno = 0;
5106         ulval = strtoul(s, &ep, 0);
5107         if (s[0] == '\0' || *ep != '\0')
5108                 return (-1);
5109         if (errno == ERANGE && ulval == ULONG_MAX)
5110                 return (-1);
5111         *ulvalp = ulval;
5112         return (0);
5113 }
5114
5115 int
5116 getservice(char *n)
5117 {
5118         struct servent  *s;
5119         u_long           ulval;
5120
5121         if (atoul(n, &ulval) == 0) {
5122                 if (ulval > 65535) {
5123                         yyerror("illegal port value %lu", ulval);
5124                         return (-1);
5125                 }
5126                 return (htons(ulval));
5127         } else {
5128                 s = getservbyname(n, "tcp");
5129                 if (s == NULL)
5130                         s = getservbyname(n, "udp");
5131                 if (s == NULL) {
5132                         yyerror("unknown port %s", n);
5133                         return (-1);
5134                 }
5135                 return (s->s_port);
5136         }
5137 }
5138
5139 int
5140 rule_label(struct pf_rule *r, char *s)
5141 {
5142         if (s) {
5143                 if (strlcpy(r->label, s, sizeof(r->label)) >=
5144                     sizeof(r->label)) {
5145                         yyerror("rule label too long (max %d chars)",
5146                             sizeof(r->label)-1);
5147                         return (-1);
5148                 }
5149         }
5150         return (0);
5151 }
5152
5153 u_int16_t
5154 parseicmpspec(char *w, sa_family_t af)
5155 {
5156         const struct icmpcodeent        *p;
5157         u_long                           ulval;
5158         u_int8_t                         icmptype;
5159
5160         if (af == AF_INET)
5161                 icmptype = returnicmpdefault >> 8;
5162         else
5163                 icmptype = returnicmp6default >> 8;
5164
5165         if (atoul(w, &ulval) == -1) {
5166                 if ((p = geticmpcodebyname(icmptype, w, af)) == NULL) {
5167                         yyerror("unknown icmp code %s", w);
5168                         return (0);
5169                 }
5170                 ulval = p->code;
5171         }
5172         if (ulval > 255) {
5173                 yyerror("invalid icmp code %lu", ulval);
5174                 return (0);
5175         }
5176         return (icmptype << 8 | ulval);
5177 }
5178
5179 int
5180 pfctl_load_anchors(int dev, int opts, struct pfr_buffer *trans)
5181 {
5182         struct loadanchors      *la;
5183
5184         TAILQ_FOREACH(la, &loadanchorshead, entries) {
5185                 if (opts & PF_OPT_VERBOSE)
5186                         fprintf(stderr, "\nLoading anchor %s from %s\n",
5187                             la->anchorname, la->filename);
5188                 if (pfctl_rules(dev, la->filename, opts, la->anchorname,
5189                     trans) == -1)
5190                         return (-1);
5191         }
5192
5193         return (0);
5194 }
5195