1 /* $OpenBSD: parse.y,v 1.718 2024/11/12 04:14:51 dlg 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 - 2013 Henning Brauer <henning@openbsd.org>
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/types.h>
31 #include <sys/socket.h>
32 #include <sys/stat.h>
33 #include <sys/sysctl.h>
34 #include <net/if.h>
35 #include <netinet/in.h>
36 #include <netinet/ip.h>
37 #include <netinet/ip_icmp.h>
38 #include <netinet/icmp6.h>
39 #include <net/pfvar.h>
40 #include <arpa/inet.h>
41
42 #include <stdio.h>
43 #include <unistd.h>
44 #include <stdlib.h>
45 #include <netdb.h>
46 #include <stdarg.h>
47 #include <errno.h>
48 #include <string.h>
49 #include <ctype.h>
50 #include <math.h>
51 #include <err.h>
52 #include <limits.h>
53 #include <pwd.h>
54 #include <grp.h>
55 #include <md5.h>
56
57 #include "pfctl_parser.h"
58 #include "pfctl.h"
59
60 static struct pfctl *pf = NULL;
61 static int debug = 0;
62 static u_int16_t returnicmpdefault =
63 (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT;
64 static u_int16_t returnicmp6default =
65 (ICMP6_DST_UNREACH << 8) | ICMP6_DST_UNREACH_NOPORT;
66 static int blockpolicy = PFRULE_DROP;
67 static int default_statelock;
68
69 TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files);
70 static struct file {
71 TAILQ_ENTRY(file) entry;
72 FILE *stream;
73 char *name;
74 size_t ungetpos;
75 size_t ungetsize;
76 u_char *ungetbuf;
77 int eof_reached;
78 int lineno;
79 int errors;
80 } *file, *topfile;
81 struct file *pushfile(const char *, int);
82 int popfile(void);
83 int check_file_secrecy(int, const char *);
84 int yyparse(void);
85 int yylex(void);
86 int yyerror(const char *, ...)
87 __attribute__((__format__ (printf, 1, 2)))
88 __attribute__((__nonnull__ (1)));
89 int kw_cmp(const void *, const void *);
90 int lookup(char *);
91 int igetc(void);
92 int lgetc(int);
93 void lungetc(int);
94 int findeol(void);
95
96 TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead);
97 struct sym {
98 TAILQ_ENTRY(sym) entry;
99 int used;
100 int persist;
101 char *nam;
102 char *val;
103 };
104 int symset(const char *, const char *, int);
105 char *symget(const char *);
106
107 int atoul(char *, u_long *);
108
109 struct node_proto {
110 u_int8_t proto;
111 struct node_proto *next;
112 struct node_proto *tail;
113 };
114
115 struct node_port {
116 u_int16_t port[2];
117 u_int8_t op;
118 struct node_port *next;
119 struct node_port *tail;
120 };
121
122 struct node_uid {
123 uid_t uid[2];
124 u_int8_t op;
125 struct node_uid *next;
126 struct node_uid *tail;
127 };
128
129 struct node_gid {
130 gid_t gid[2];
131 u_int8_t op;
132 struct node_gid *next;
133 struct node_gid *tail;
134 };
135
136 struct node_icmp {
137 u_int16_t code; /* aux. value 256 is legit */
138 u_int16_t type; /* aux. value 256 is legit */
139 u_int8_t proto;
140 struct node_icmp *next;
141 struct node_icmp *tail;
142 };
143
144 enum { PF_STATE_OPT_MAX, PF_STATE_OPT_NOSYNC, PF_STATE_OPT_SRCTRACK,
145 PF_STATE_OPT_MAX_SRC_STATES, PF_STATE_OPT_MAX_SRC_CONN,
146 PF_STATE_OPT_MAX_SRC_CONN_RATE, PF_STATE_OPT_MAX_SRC_NODES,
147 PF_STATE_OPT_OVERLOAD, PF_STATE_OPT_STATELOCK,
148 PF_STATE_OPT_TIMEOUT, PF_STATE_OPT_SLOPPY,
149 PF_STATE_OPT_PFLOW };
150
151 enum { PF_SRCTRACK_NONE, PF_SRCTRACK, PF_SRCTRACK_GLOBAL, PF_SRCTRACK_RULE };
152
153 struct node_state_opt {
154 int type;
155 union {
156 u_int32_t max_states;
157 u_int32_t max_src_states;
158 u_int32_t max_src_conn;
159 struct {
160 u_int32_t limit;
161 u_int32_t seconds;
162 } max_src_conn_rate;
163 struct {
164 u_int8_t flush;
165 char tblname[PF_TABLE_NAME_SIZE];
166 } overload;
167 u_int32_t max_src_nodes;
168 u_int8_t src_track;
169 u_int32_t statelock;
170 struct {
171 int number;
172 u_int32_t seconds;
173 } timeout;
174 } data;
175 struct node_state_opt *next;
176 struct node_state_opt *tail;
177 };
178
179 struct peer {
180 struct node_host *host;
181 struct node_port *port;
182 };
183
184 struct node_queue {
185 char queue[PF_QNAME_SIZE];
186 char parent[PF_QNAME_SIZE];
187 char ifname[IFNAMSIZ];
188 int scheduler;
189 struct node_queue *next;
190 struct node_queue *tail;
191 };
192
193 struct node_qassign {
194 char *qname;
195 char *pqname;
196 };
197
198 struct range {
199 int a;
200 int b;
201 int t;
202 };
203 struct redirection {
204 struct node_host *host;
205 struct range rport;
206 };
207
208 struct pool_opts {
209 int marker;
210 #define POM_TYPE 0x01
211 #define POM_STICKYADDRESS 0x02
212 u_int8_t opts;
213 int type;
214 int staticport;
215 struct pf_poolhashkey *key;
216
217 } pool_opts;
218
219 struct divertspec {
220 struct node_host *addr;
221 u_int16_t port;
222 enum pf_divert_types type;
223 };
224
225 struct redirspec {
226 struct redirection *rdr;
227 struct pool_opts pool_opts;
228 int binat;
229 int af;
230 };
231
232 struct filter_opts {
233 int marker;
234 #define FOM_FLAGS 0x0001
235 #define FOM_ICMP 0x0002
236 #define FOM_TOS 0x0004
237 #define FOM_KEEP 0x0008
238 #define FOM_SRCTRACK 0x0010
239 #define FOM_MINTTL 0x0020
240 #define FOM_MAXMSS 0x0040
241 #define FOM_AFTO 0x0080
242 #define FOM_SETTOS 0x0100
243 #define FOM_SCRUB_TCP 0x0200
244 #define FOM_SETPRIO 0x0400
245 #define FOM_ONCE 0x1000
246 #define FOM_PRIO 0x2000
247 #define FOM_SETDELAY 0x4000
248 struct node_uid *uid;
249 struct node_gid *gid;
250 struct node_if *rcv;
251 struct {
252 u_int8_t b1;
253 u_int8_t b2;
254 u_int16_t w;
255 u_int16_t w2;
256 } flags;
257 struct node_icmp *icmpspec;
258 u_int32_t tos;
259 u_int32_t prob;
260 struct {
261 int action;
262 struct node_state_opt *options;
263 } keep;
264 int fragment;
265 int allowopts;
266 char *label;
267 struct node_qassign queues;
268 char *tag;
269 char *match_tag;
270 u_int8_t match_tag_not;
271 u_int rtableid;
272 u_int8_t prio;
273 u_int8_t set_prio[2];
274 u_int16_t delay;
275 struct divertspec divert;
276 struct redirspec nat;
277 struct redirspec rdr;
278 struct redirspec rroute;
279 u_int8_t rt;
280
281 /* scrub opts */
282 int nodf;
283 int minttl;
284 int settos;
285 int randomid;
286 int max_mss;
287
288 struct {
289 u_int32_t limit;
290 u_int32_t seconds;
291 } pktrate;
292 } filter_opts;
293
294 struct antispoof_opts {
295 char *label;
296 u_int rtableid;
297 } antispoof_opts;
298
299 struct scrub_opts {
300 int marker;
301 int nodf;
302 int minttl;
303 int maxmss;
304 int randomid;
305 int reassemble_tcp;
306 } scrub_opts;
307
308 struct node_sc {
309 struct node_queue_bw m1;
310 u_int d;
311 struct node_queue_bw m2;
312 };
313
314 struct node_fq {
315 u_int flows;
316 u_int quantum;
317 u_int target;
318 u_int interval;
319 };
320
321 struct queue_opts {
322 int marker;
323 #define QOM_BWSPEC 0x01
324 #define QOM_PARENT 0x02
325 #define QOM_DEFAULT 0x04
326 #define QOM_QLIMIT 0x08
327 #define QOM_FLOWS 0x10
328 #define QOM_QUANTUM 0x20
329 struct node_sc realtime;
330 struct node_sc linkshare;
331 struct node_sc upperlimit;
332 struct node_fq flowqueue;
333 char *parent;
334 int flags;
335 u_int qlimit;
336 } queue_opts;
337
338 struct table_opts {
339 int flags;
340 int init_addr;
341 struct node_tinithead init_nodes;
342 } table_opts;
343
344 struct node_hfsc_opts hfsc_opts;
345 struct node_state_opt *keep_state_defaults = NULL;
346 struct pfctl_watermarks syncookie_opts;
347
348 int validate_range(u_int8_t, u_int16_t, u_int16_t);
349 int disallow_table(struct node_host *, const char *);
350 int disallow_urpf_failed(struct node_host *, const char *);
351 int disallow_alias(struct node_host *, const char *);
352 int rule_consistent(struct pf_rule *);
353 int process_tabledef(char *, struct table_opts *, int);
354 void expand_label_str(char *, size_t, const char *, const char *);
355 void expand_label_if(const char *, char *, size_t, const char *);
356 void expand_label_addr(const char *, char *, size_t, u_int8_t,
357 struct node_host *);
358 void expand_label_port(const char *, char *, size_t,
359 struct node_port *);
360 void expand_label_proto(const char *, char *, size_t, u_int8_t);
361 void expand_label(char *, size_t, const char *, u_int8_t,
362 struct node_host *, struct node_port *, struct node_host *,
363 struct node_port *, u_int8_t);
364 int expand_divertspec(struct pf_rule *, struct divertspec *);
365 int collapse_redirspec(struct pf_pool *, struct pf_rule *,
366 struct redirspec *rs, int);
367 int apply_redirspec(struct pf_pool *, struct pf_rule *,
368 struct redirspec *, int, struct node_port *);
369 void expand_rule(struct pf_rule *, int, struct node_if *,
370 struct redirspec *, struct redirspec *, struct redirspec *,
371 struct node_proto *,
372 struct node_os *, struct node_host *, struct node_port *,
373 struct node_host *, struct node_port *, struct node_uid *,
374 struct node_gid *, struct node_if *, struct node_icmp *);
375 int expand_queue(char *, struct node_if *, struct queue_opts *);
376 int expand_skip_interface(struct node_if *);
377
378 int getservice(char *);
379 int rule_label(struct pf_rule *, char *);
380
381 void mv_rules(struct pf_ruleset *, struct pf_ruleset *);
382 void mv_tables(struct pfctl *, struct pfr_ktablehead *,
383 struct pf_anchor *, struct pf_anchor *);
384 void decide_address_family(struct node_host *, sa_family_t *);
385 int invalid_redirect(struct node_host *, sa_family_t);
386 u_int16_t parseicmpspec(char *, sa_family_t);
387 int kw_casecmp(const void *, const void *);
388 int map_tos(char *string, int *);
389 int lookup_rtable(u_int);
390 int filteropts_to_rule(struct pf_rule *, struct filter_opts *);
391
392 TAILQ_HEAD(loadanchorshead, loadanchors)
393 loadanchorshead = TAILQ_HEAD_INITIALIZER(loadanchorshead);
394
395 struct loadanchors {
396 TAILQ_ENTRY(loadanchors) entries;
397 char *anchorname;
398 char *filename;
399 };
400
401 typedef struct {
402 union {
403 int64_t number;
404 double probability;
405 int i;
406 char *string;
407 u_int rtableid;
408 u_int16_t weight;
409 struct {
410 u_int8_t b1;
411 u_int8_t b2;
412 u_int16_t w;
413 u_int16_t w2;
414 } b;
415 struct range range;
416 struct node_if *interface;
417 struct node_proto *proto;
418 struct node_icmp *icmp;
419 struct node_host *host;
420 struct node_os *os;
421 struct node_port *port;
422 struct node_uid *uid;
423 struct node_gid *gid;
424 struct node_state_opt *state_opt;
425 struct peer peer;
426 struct {
427 struct peer src, dst;
428 struct node_os *src_os;
429 } fromto;
430 struct redirection *redirection;
431 struct {
432 int action;
433 struct node_state_opt *options;
434 } keep_state;
435 struct {
436 u_int8_t log;
437 u_int8_t logif;
438 u_int8_t quick;
439 } logquick;
440 struct {
441 int neg;
442 char *name;
443 } tagged;
444 struct pf_poolhashkey *hashkey;
445 struct node_queue *queue;
446 struct node_queue_opt queue_options;
447 struct node_queue_bw queue_bwspec;
448 struct node_qassign qassign;
449 struct node_sc sc;
450 struct filter_opts filter_opts;
451 struct antispoof_opts antispoof_opts;
452 struct queue_opts queue_opts;
453 struct scrub_opts scrub_opts;
454 struct table_opts table_opts;
455 struct pool_opts pool_opts;
456 struct node_hfsc_opts hfsc_opts;
457 struct pfctl_watermarks *watermarks;
458 } v;
459 int lineno;
460 } YYSTYPE;
461
462 #define PPORT_RANGE 1
463 #define PPORT_STAR 2
464 int parseport(char *, struct range *r, int);
465
466 #define DYNIF_MULTIADDR(addr) ((addr).type == PF_ADDR_DYNIFTL && \
467 (!((addr).iflags & PFI_AFLAG_NOALIAS) || \
468 !isdigit((unsigned char)(addr).v.ifname[strlen((addr).v.ifname)-1])))
469
470 %}
471
472 %token PASS BLOCK MATCH SCRUB RETURN IN OS OUT LOG QUICK ON FROM TO FLAGS
473 %token RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE
474 %token ICMP6TYPE CODE KEEP MODULATE STATE PORT BINATTO NODF
475 %token MINTTL ERROR ALLOWOPTS FILENAME ROUTETO DUPTO REPLYTO NO LABEL
476 %token NOROUTE URPFFAILED FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DROP TABLE
477 %token REASSEMBLE ANCHOR SYNCOOKIES
478 %token SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY RANDOMID
479 %token SYNPROXY FINGERPRINTS NOSYNC DEBUG SKIP HOSTID
480 %token ANTISPOOF FOR INCLUDE MATCHES
481 %token BITMASK RANDOM SOURCEHASH ROUNDROBIN LEASTSTATES STATICPORT PROBABILITY
482 %token WEIGHT BANDWIDTH FLOWS QUANTUM
483 %token QUEUE PRIORITY QLIMIT RTABLE RDOMAIN MINIMUM BURST PARENT
484 %token LOAD RULESET_OPTIMIZATION RTABLE RDOMAIN PRIO ONCE DEFAULT DELAY
485 %token STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE
486 %token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH SLOPPY PFLOW MAXPKTRATE
487 %token TAGGED TAG IFBOUND FLOATING STATEPOLICY STATEDEFAULTS ROUTE
488 %token DIVERTTO DIVERTREPLY DIVERTPACKET NATTO AFTO RDRTO RECEIVEDON NE LE GE
489 %token <v.string> STRING
490 %token <v.number> NUMBER
491 %token <v.i> PORTBINARY
492 %type <v.interface> interface if_list if_item_not if_item
493 %type <v.number> number icmptype icmp6type uid gid
494 %type <v.number> tos not yesno optnodf
495 %type <v.probability> probability
496 %type <v.weight> optweight
497 %type <v.i> dir af optimizer syncookie_val
498 %type <v.i> sourcetrack flush unaryop statelock
499 %type <v.b> action
500 %type <v.b> flags flag blockspec prio
501 %type <v.range> portplain portstar portrange
502 %type <v.hashkey> hashkey
503 %type <v.proto> proto proto_list proto_item
504 %type <v.number> protoval
505 %type <v.icmp> icmpspec
506 %type <v.icmp> icmp_list icmp_item
507 %type <v.icmp> icmp6_list icmp6_item
508 %type <v.number> reticmpspec reticmp6spec
509 %type <v.fromto> fromto
510 %type <v.peer> ipportspec from to
511 %type <v.host> ipspec xhost host dynaddr host_list
512 %type <v.host> table_host_list tablespec
513 %type <v.host> redir_host_list redirspec
514 %type <v.os> os xos os_list
515 %type <v.port> portspec port_list port_item
516 %type <v.uid> uids uid_list uid_item
517 %type <v.gid> gids gid_list gid_item
518 %type <v.redirection> redirpool
519 %type <v.string> label stringall anchorname
520 %type <v.string> string varstring numberstring
521 %type <v.keep_state> keep
522 %type <v.state_opt> state_opt_spec state_opt_list state_opt_item
523 %type <v.logquick> logquick quick log logopts logopt
524 %type <v.interface> antispoof_ifspc antispoof_iflst antispoof_if
525 %type <v.qassign> qname
526 %type <v.queue_bwspec> bandwidth
527 %type <v.filter_opts> filter_opts filter_opt filter_opts_l
528 %type <v.filter_opts> filter_sets filter_set filter_sets_l
529 %type <v.antispoof_opts> antispoof_opts antispoof_opt antispoof_opts_l
530 %type <v.queue_opts> queue_opts queue_opt queue_opts_l optscs
531 %type <v.sc> scspec
532 %type <v.scrub_opts> scrub_opts scrub_opt scrub_opts_l
533 %type <v.table_opts> table_opts table_opt table_opts_l
534 %type <v.pool_opts> pool_opts pool_opt pool_opts_l
535 %type <v.watermarks> syncookie_opts
536 %%
537
538 ruleset : /* empty */
539 | ruleset include '\n'
540 | ruleset '\n'
541 | ruleset option '\n'
542 | ruleset pfrule '\n'
543 | ruleset anchorrule '\n'
544 | ruleset loadrule '\n'
545 | ruleset queuespec '\n'
546 | ruleset varset '\n'
547 | ruleset antispoof '\n'
548 | ruleset tabledef '\n'
549 | '{' fakeanchor '}' '\n';
550 | ruleset error '\n' { file->errors++; }
551 ;
552
553 include : INCLUDE STRING {
554 struct file *nfile;
555
556 if ((nfile = pushfile($2, 0)) == NULL) {
557 yyerror("failed to include file %s", $2);
558 free($2);
559 YYERROR;
560 }
561 free($2);
562
563 file = nfile;
564 lungetc('\n');
565 }
566 ;
567
568 /*
569 * apply to previously specified rule: must be careful to note
570 * what that is: pf or nat or binat or rdr
571 */
572 fakeanchor : fakeanchor '\n'
573 | fakeanchor anchorrule '\n'
574 | fakeanchor pfrule '\n'
575 | fakeanchor error '\n'
576 ;
577
578 optimizer : string {
579 if (!strcmp($1, "none"))
580 $$ = 0;
581 else if (!strcmp($1, "basic"))
582 $$ = PF_OPTIMIZE_BASIC;
583 else if (!strcmp($1, "profile"))
584 $$ = PF_OPTIMIZE_BASIC | PF_OPTIMIZE_PROFILE;
585 else {
586 yyerror("unknown ruleset-optimization %s", $1);
587 YYERROR;
588 }
589 }
590 ;
591
592 optnodf : /* empty */ { $$ = 0; }
593 | NODF { $$ = 1; }
594 ;
595
596 option : SET REASSEMBLE yesno optnodf {
597 pfctl_set_reassembly(pf, $3, $4);
598 }
599 | SET OPTIMIZATION STRING {
600 if (pfctl_set_optimization(pf, $3) != 0) {
601 yyerror("unknown optimization %s", $3);
602 free($3);
603 YYERROR;
604 }
605 free($3);
606 }
607 | SET RULESET_OPTIMIZATION optimizer {
608 if (!(pf->opts & PF_OPT_OPTIMIZE)) {
609 pf->opts |= PF_OPT_OPTIMIZE;
610 pf->optimize = $3;
611 }
612 }
613 | SET TIMEOUT timeout_spec
614 | SET TIMEOUT '{' optnl timeout_list '}'
615 | SET LIMIT limit_spec
616 | SET LIMIT '{' optnl limit_list '}'
617 | SET LOGINTERFACE stringall {
618 if (pfctl_set_logif(pf, $3) != 0) {
619 yyerror("error setting loginterface %s", $3);
620 free($3);
621 YYERROR;
622 }
623 free($3);
624 }
625 | SET HOSTID number {
626 if ($3 == 0 || $3 > UINT_MAX) {
627 yyerror("hostid must be non-zero");
628 YYERROR;
629 }
630 pfctl_set_hostid(pf, $3);
631 }
632 | SET BLOCKPOLICY DROP {
633 if (pf->opts & PF_OPT_VERBOSE)
634 printf("set block-policy drop\n");
635 blockpolicy = PFRULE_DROP;
636 }
637 | SET BLOCKPOLICY RETURN {
638 if (pf->opts & PF_OPT_VERBOSE)
639 printf("set block-policy return\n");
640 blockpolicy = PFRULE_RETURN;
641 }
642 | SET FINGERPRINTS STRING {
643 if (pf->opts & PF_OPT_VERBOSE)
644 printf("set fingerprints \"%s\"\n", $3);
645 if (!pf->anchor->name[0]) {
646 if (pfctl_file_fingerprints(pf->dev,
647 pf->opts, $3)) {
648 yyerror("error loading "
649 "fingerprints %s", $3);
650 free($3);
651 YYERROR;
652 }
653 }
654 free($3);
655 }
656 | SET STATEPOLICY statelock {
657 if (pf->opts & PF_OPT_VERBOSE)
658 switch ($3) {
659 case 0:
660 printf("set state-policy floating\n");
661 break;
662 case PFRULE_IFBOUND:
663 printf("set state-policy if-bound\n");
664 break;
665 }
666 default_statelock = $3;
667 }
668 | SET DEBUG STRING {
669 if (pfctl_set_debug(pf, $3) != 0) {
670 yyerror("error setting debuglevel %s", $3);
671 free($3);
672 YYERROR;
673 }
674 free($3);
675 }
676 | SET DEBUG DEBUG {
677 if (pfctl_set_debug(pf, "debug") != 0) {
678 yyerror("error setting debuglevel %s", "debug");
679 YYERROR;
680 }
681 }
682 | SET SKIP interface {
683 if (expand_skip_interface($3) != 0) {
684 yyerror("error setting skip interface(s)");
685 YYERROR;
686 }
687 }
688 | SET STATEDEFAULTS state_opt_list {
689 if (keep_state_defaults != NULL) {
690 yyerror("cannot redefine state-defaults");
691 YYERROR;
692 }
693 keep_state_defaults = $3;
694 }
695 | SET SYNCOOKIES syncookie_val syncookie_opts {
696 if (pfctl_set_syncookies(pf, $3, $4)) {
697 yyerror("error setting syncookies");
698 YYERROR;
699 }
700 }
701 ;
702
703 syncookie_val : STRING {
704 if (!strcmp($1, "never"))
705 $$ = PF_SYNCOOKIES_NEVER;
706 else if (!strcmp($1, "adaptive"))
707 $$ = PF_SYNCOOKIES_ADAPTIVE;
708 else if (!strcmp($1, "always"))
709 $$ = PF_SYNCOOKIES_ALWAYS;
710 else {
711 yyerror("illegal value for syncookies");
712 YYERROR;
713 }
714 }
715 ;
716
717 syncookie_opts : /* empty */ { $$ = NULL; }
718 | {
719 memset(&syncookie_opts, 0, sizeof(syncookie_opts));
720 } '(' syncookie_opt_l ')' { $$ = &syncookie_opts; }
721 ;
722
723 syncookie_opt_l : syncookie_opt_l comma syncookie_opt
724 | syncookie_opt
725 ;
726
727 syncookie_opt : STRING STRING {
728 double val;
729 char *cp;
730
731 val = strtod($2, &cp);
732 if (cp == NULL || strcmp(cp, "%"))
733 YYERROR;
734 if (val <= 0 || val > 100) {
735 yyerror("illegal percentage value");
736 YYERROR;
737 }
738 if (!strcmp($1, "start")) {
739 syncookie_opts.hi = val;
740 } else if (!strcmp($1, "end")) {
741 syncookie_opts.lo = val;
742 } else {
743 yyerror("illegal syncookie option");
744 YYERROR;
745 }
746 }
747 ;
748
749 stringall : STRING { $$ = $1; }
750 | ALL {
751 if (($$ = strdup("all")) == NULL) {
752 err(1, "stringall: strdup");
753 }
754 }
755 ;
756
757 string : STRING string {
758 if (asprintf(&$$, "%s %s", $1, $2) == -1)
759 err(1, "string: asprintf");
760 free($1);
761 free($2);
762 }
763 | STRING
764 ;
765
766 varstring : numberstring varstring {
767 if (asprintf(&$$, "%s %s", $1, $2) == -1)
768 err(1, "string: asprintf");
769 free($1);
770 free($2);
771 }
772 | numberstring
773 ;
774
775 numberstring : NUMBER {
776 char *s;
777 if (asprintf(&s, "%lld", $1) == -1) {
778 yyerror("string: asprintf");
779 YYERROR;
780 }
781 $$ = s;
782 }
783 | STRING
784 ;
785
786 varset : STRING '=' varstring {
787 char *s = $1;
788 if (pf->opts & PF_OPT_VERBOSE)
789 printf("%s = \"%s\"\n", $1, $3);
790 while (*s++) {
791 if (isspace((unsigned char)*s)) {
792 yyerror("macro name cannot contain "
793 "whitespace");
794 free($1);
795 free($3);
796 YYERROR;
797 }
798 }
799 if (symset($1, $3, 0) == -1)
800 err(1, "cannot store variable %s", $1);
801 free($1);
802 free($3);
803 }
804 ;
805
806 anchorname : STRING {
807 if ($1[0] == '\0') {
808 free($1);
809 yyerror("anchor name must not be empty");
810 YYERROR;
811 }
812 if (strlen(pf->anchor->path) + 1 +
813 strlen($1) >= PATH_MAX) {
814 free($1);
815 yyerror("anchor name is longer than %u",
816 PATH_MAX - 1);
817 YYERROR;
818 }
819 if ($1[0] == '_' || strstr($1, "/_") != NULL) {
820 free($1);
821 yyerror("anchor names beginning with '_' "
822 "are reserved for internal use");
823 YYERROR;
824 }
825 $$ = $1;
826 }
827 | /* empty */ { $$ = NULL; }
828 ;
829
830 pfa_anchorlist : /* empty */
831 | pfa_anchorlist '\n'
832 | pfa_anchorlist tabledef '\n'
833 | pfa_anchorlist pfrule '\n'
834 | pfa_anchorlist anchorrule '\n'
835 | pfa_anchorlist include '\n'
836 ;
837
838 pfa_anchor : '{'
839 {
840 char ta[PF_ANCHOR_NAME_SIZE];
841 struct pf_ruleset *rs;
842
843 /* steping into a brace anchor */
844 pf->asd++;
845 if (pf->asd >= PFCTL_ANCHOR_STACK_DEPTH)
846 errx(1, "pfa_anchor: anchors too deep");
847 pf->bn++;
848 pf->brace = 1;
849
850 /*
851 * Anchor contents are parsed before the anchor rule
852 * production completes, so we don't know the real
853 * location yet. Create a holding ruleset in the root;
854 * contents will be moved afterwards.
855 */
856 snprintf(ta, PF_ANCHOR_NAME_SIZE, "_%d", pf->bn);
857 rs = pf_find_or_create_ruleset(ta);
858 if (rs == NULL)
859 err(1, "pfa_anchor: pf_find_or_create_ruleset (%s)", ta);
860 pf->astack[pf->asd] = rs->anchor;
861 pf->anchor = rs->anchor;
862 } '\n' pfa_anchorlist '}'
863 {
864 pf->alast = pf->anchor;
865 pf->asd--;
866 pf->anchor = pf->astack[pf->asd];
867 }
868 | /* empty */
869 ;
870
871 anchorrule : ANCHOR anchorname dir quick interface af proto fromto
872 filter_opts pfa_anchor
873 {
874 struct pf_rule r;
875 struct node_proto *proto;
876 char *p;
877
878 memset(&r, 0, sizeof(r));
879 if (pf->astack[pf->asd + 1]) {
880 if ($2 && strchr($2, '/') != NULL) {
881 free($2);
882 yyerror("anchor paths containing '/' "
883 "cannot be used for inline anchors.");
884 YYERROR;
885 }
886
887 /* Move inline rules into relative location. */
888 pf_anchor_setup(&r,
889 &pf->astack[pf->asd]->ruleset,
890 $2 ? $2 : pf->alast->name);
891
892 if (r.anchor == NULL)
893 err(1, "anchorrule: unable to "
894 "create ruleset");
895
896 if (pf->alast != r.anchor) {
897 if (r.anchor->match) {
898 yyerror("inline anchor '%s' "
899 "already exists",
900 r.anchor->name);
901 YYERROR;
902 }
903 mv_rules(&pf->alast->ruleset,
904 &r.anchor->ruleset);
905 mv_tables(pf, &pfr_ktables, r.anchor, pf->alast);
906 }
907 pf_remove_if_empty_ruleset(&pf->alast->ruleset);
908 pf->alast = r.anchor;
909 } else {
910 if (!$2) {
911 yyerror("anchors without explicit "
912 "rules must specify a name");
913 YYERROR;
914 }
915
916 /*
917 * Don't make non-brace anchors part of the main anchor pool.
918 */
919 if ((r.anchor = calloc(1, sizeof(*r.anchor))) == NULL) {
920 err(1, "anchorrule: calloc");
921 }
922 pf_init_ruleset(&r.anchor->ruleset);
923 r.anchor->ruleset.anchor = r.anchor;
924 if (strlcpy(r.anchor->path, $2,
925 sizeof(r.anchor->path)) >= sizeof(r.anchor->path)) {
926 errx(1, "anchorrule: strlcpy");
927 }
928 if ((p = strrchr($2, '/')) != NULL) {
929 if (strlen(p) == 1) {
930 yyerror("anchorrule: bad anchor name %s",
931 $2);
932 YYERROR;
933 }
934 } else
935 p = $2;
936 if (strlcpy(r.anchor->name, p,
937 sizeof(r.anchor->name)) >= sizeof(r.anchor->name)) {
938 errx(1, "anchorrule: strlcpy");
939 }
940 }
941
942 r.direction = $3;
943 r.quick = $4.quick;
944 r.af = $6;
945
946 if ($9.flags.b1 || $9.flags.b2 || $8.src_os) {
947 for (proto = $7; proto != NULL &&
948 proto->proto != IPPROTO_TCP;
949 proto = proto->next)
950 ; /* nothing */
951 if (proto == NULL && $7 != NULL) {
952 if ($9.flags.b1 || $9.flags.b2)
953 yyerror(
954 "flags only apply to tcp");
955 if ($8.src_os)
956 yyerror(
957 "OS fingerprinting only "
958 "applies to tcp");
959 YYERROR;
960 }
961 }
962
963 if (filteropts_to_rule(&r, &$9))
964 YYERROR;
965
966 if ($9.keep.action) {
967 yyerror("cannot specify state handling "
968 "on anchors");
969 YYERROR;
970 }
971
972 if ($9.rt) {
973 yyerror("cannot specify route handling "
974 "on anchors");
975 YYERROR;
976 }
977
978 decide_address_family($8.src.host, &r.af);
979 decide_address_family($8.dst.host, &r.af);
980
981 expand_rule(&r, 0, $5, NULL, NULL, NULL, $7, $8.src_os,
982 $8.src.host, $8.src.port, $8.dst.host, $8.dst.port,
983 $9.uid, $9.gid, $9.rcv, $9.icmpspec);
984 free($2);
985 pf->astack[pf->asd + 1] = NULL;
986 }
987 ;
988
989 loadrule : LOAD ANCHOR anchorname FROM string {
990 struct loadanchors *loadanchor;
991
992 if ($3 == NULL) {
993 yyerror("anchor name is missing");
994 YYERROR;
995 }
996 loadanchor = calloc(1, sizeof(struct loadanchors));
997 if (loadanchor == NULL)
998 err(1, "loadrule: calloc");
999 if ((loadanchor->anchorname = malloc(PATH_MAX)) ==
1000 NULL)
1001 err(1, "loadrule: malloc");
1002 if (pf->anchor->name[0])
1003 snprintf(loadanchor->anchorname, PATH_MAX,
1004 "%s/%s", pf->anchor->path, $3);
1005 else
1006 strlcpy(loadanchor->anchorname, $3, PATH_MAX);
1007 if ((loadanchor->filename = strdup($5)) == NULL)
1008 err(1, "loadrule: strdup");
1009
1010 TAILQ_INSERT_TAIL(&loadanchorshead, loadanchor,
1011 entries);
1012
1013 free($3);
1014 free($5);
1015 };
1016
1017 scrub_opts : {
1018 bzero(&scrub_opts, sizeof scrub_opts);
1019 }
1020 scrub_opts_l
1021 { $$ = scrub_opts; }
1022 ;
1023
1024 scrub_opts_l : scrub_opts_l comma scrub_opt
1025 | scrub_opt
1026 ;
1027
1028 scrub_opt : NODF {
1029 if (scrub_opts.nodf) {
1030 yyerror("no-df cannot be respecified");
1031 YYERROR;
1032 }
1033 scrub_opts.nodf = 1;
1034 }
1035 | MINTTL NUMBER {
1036 if (scrub_opts.marker & FOM_MINTTL) {
1037 yyerror("min-ttl cannot be respecified");
1038 YYERROR;
1039 }
1040 if ($2 < 0 || $2 > 255) {
1041 yyerror("illegal min-ttl value %lld", $2);
1042 YYERROR;
1043 }
1044 scrub_opts.marker |= FOM_MINTTL;
1045 scrub_opts.minttl = $2;
1046 }
1047 | MAXMSS NUMBER {
1048 if (scrub_opts.marker & FOM_MAXMSS) {
1049 yyerror("max-mss cannot be respecified");
1050 YYERROR;
1051 }
1052 if ($2 < 0 || $2 > 65535) {
1053 yyerror("illegal max-mss value %lld", $2);
1054 YYERROR;
1055 }
1056 scrub_opts.marker |= FOM_MAXMSS;
1057 scrub_opts.maxmss = $2;
1058 }
1059 | REASSEMBLE STRING {
1060 if (strcasecmp($2, "tcp") != 0) {
1061 yyerror("scrub reassemble supports only tcp, "
1062 "not '%s'", $2);
1063 free($2);
1064 YYERROR;
1065 }
1066 free($2);
1067 if (scrub_opts.reassemble_tcp) {
1068 yyerror("reassemble tcp cannot be respecified");
1069 YYERROR;
1070 }
1071 scrub_opts.reassemble_tcp = 1;
1072 }
1073 | RANDOMID {
1074 if (scrub_opts.randomid) {
1075 yyerror("random-id cannot be respecified");
1076 YYERROR;
1077 }
1078 scrub_opts.randomid = 1;
1079 }
1080 ;
1081
1082 antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts {
1083 struct pf_rule r;
1084 struct node_host *h = NULL, *hh;
1085 struct node_if *i, *j;
1086
1087 for (i = $3; i; i = i->next) {
1088 bzero(&r, sizeof(r));
1089
1090 r.action = PF_DROP;
1091 r.direction = PF_IN;
1092 r.log = $2.log;
1093 r.logif = $2.logif;
1094 r.quick = $2.quick;
1095 r.af = $4;
1096 if (rule_label(&r, $5.label))
1097 YYERROR;
1098 r.rtableid = $5.rtableid;
1099 j = calloc(1, sizeof(struct node_if));
1100 if (j == NULL)
1101 err(1, "antispoof: calloc");
1102 if (strlcpy(j->ifname, i->ifname,
1103 sizeof(j->ifname)) >= sizeof(j->ifname)) {
1104 free(j);
1105 yyerror("interface name too long");
1106 YYERROR;
1107 }
1108 j->not = 1;
1109 if (i->dynamic) {
1110 h = calloc(1, sizeof(*h));
1111 if (h == NULL)
1112 err(1, "address: calloc");
1113 h->addr.type = PF_ADDR_DYNIFTL;
1114 set_ipmask(h, 128);
1115 if (strlcpy(h->addr.v.ifname, i->ifname,
1116 sizeof(h->addr.v.ifname)) >=
1117 sizeof(h->addr.v.ifname)) {
1118 free(h);
1119 yyerror(
1120 "interface name too long");
1121 YYERROR;
1122 }
1123 hh = malloc(sizeof(*hh));
1124 if (hh == NULL)
1125 err(1, "address: malloc");
1126 bcopy(h, hh, sizeof(*hh));
1127 h->addr.iflags = PFI_AFLAG_NETWORK;
1128 } else {
1129 h = ifa_lookup(j->ifname,
1130 PFI_AFLAG_NETWORK);
1131 hh = NULL;
1132 }
1133
1134 if (h != NULL)
1135 expand_rule(&r, 0, j, NULL, NULL, NULL,
1136 NULL, NULL, h, NULL, NULL, NULL,
1137 NULL, NULL, NULL, NULL);
1138
1139 if ((i->ifa_flags & IFF_LOOPBACK) == 0) {
1140 bzero(&r, sizeof(r));
1141
1142 r.action = PF_DROP;
1143 r.direction = PF_IN;
1144 r.log = $2.log;
1145 r.logif = $2.logif;
1146 r.quick = $2.quick;
1147 r.af = $4;
1148 if (rule_label(&r, $5.label))
1149 YYERROR;
1150 r.rtableid = $5.rtableid;
1151 if (hh != NULL)
1152 h = hh;
1153 else
1154 h = ifa_lookup(i->ifname, 0);
1155 if (h != NULL)
1156 expand_rule(&r, 0, NULL, NULL,
1157 NULL, NULL, NULL, NULL, h,
1158 NULL, NULL, NULL, NULL,
1159 NULL, NULL, NULL);
1160 } else
1161 free(hh);
1162 }
1163 free($5.label);
1164 }
1165 ;
1166
1167 antispoof_ifspc : FOR antispoof_if { $$ = $2; }
1168 | FOR '{' optnl antispoof_iflst '}' { $$ = $4; }
1169 ;
1170
1171 antispoof_iflst : antispoof_if optnl { $$ = $1; }
1172 | antispoof_iflst comma antispoof_if optnl {
1173 $1->tail->next = $3;
1174 $1->tail = $3;
1175 $$ = $1;
1176 }
1177 ;
1178
1179 antispoof_if : if_item { $$ = $1; }
1180 | '(' if_item ')' {
1181 $2->dynamic = 1;
1182 $$ = $2;
1183 }
1184 ;
1185
1186 antispoof_opts : {
1187 bzero(&antispoof_opts, sizeof antispoof_opts);
1188 antispoof_opts.rtableid = -1;
1189 }
1190 antispoof_opts_l
1191 { $$ = antispoof_opts; }
1192 | /* empty */ {
1193 bzero(&antispoof_opts, sizeof antispoof_opts);
1194 antispoof_opts.rtableid = -1;
1195 $$ = antispoof_opts;
1196 }
1197 ;
1198
1199 antispoof_opts_l : antispoof_opts_l antispoof_opt
1200 | antispoof_opt
1201 ;
1202
1203 antispoof_opt : LABEL label {
1204 if (antispoof_opts.label) {
1205 yyerror("label cannot be redefined");
1206 YYERROR;
1207 }
1208 antispoof_opts.label = $2;
1209 }
1210 | RTABLE NUMBER {
1211 if ($2 < 0 || $2 > RT_TABLEID_MAX) {
1212 yyerror("invalid rtable id");
1213 YYERROR;
1214 } else if (!lookup_rtable($2)) {
1215 yyerror("rtable %lld does not exist", $2);
1216 YYERROR;
1217 }
1218 antispoof_opts.rtableid = $2;
1219 }
1220 ;
1221
1222 not : '!' { $$ = 1; }
1223 | /* empty */ { $$ = 0; }
1224 ;
1225
1226 tabledef : TABLE '<' STRING '>' table_opts {
1227 struct node_host *h, *nh;
1228 struct node_tinit *ti, *nti;
1229
1230 if (strlen($3) >= PF_TABLE_NAME_SIZE) {
1231 yyerror("table name too long, max %d chars",
1232 PF_TABLE_NAME_SIZE - 1);
1233 free($3);
1234 YYERROR;
1235 }
1236 if (process_tabledef($3, &$5, pf->opts)) {
1237 free($3);
1238 YYERROR;
1239 }
1240 free($3);
1241 for (ti = SIMPLEQ_FIRST(&$5.init_nodes); ti != NULL;
1242 ti = nti) {
1243 if (ti->file)
1244 free(ti->file);
1245 for (h = ti->host; h != NULL; h = nh) {
1246 nh = h->next;
1247 free(h);
1248 }
1249 nti = SIMPLEQ_NEXT(ti, entries);
1250 free(ti);
1251 }
1252 }
1253 ;
1254
1255 table_opts : {
1256 bzero(&table_opts, sizeof table_opts);
1257 SIMPLEQ_INIT(&table_opts.init_nodes);
1258 }
1259 table_opts_l
1260 { $$ = table_opts; }
1261 | /* empty */
1262 {
1263 bzero(&table_opts, sizeof table_opts);
1264 SIMPLEQ_INIT(&table_opts.init_nodes);
1265 $$ = table_opts;
1266 }
1267 ;
1268
1269 table_opts_l : table_opts_l table_opt
1270 | table_opt
1271 ;
1272
1273 table_opt : STRING {
1274 if (!strcmp($1, "const"))
1275 table_opts.flags |= PFR_TFLAG_CONST;
1276 else if (!strcmp($1, "persist"))
1277 table_opts.flags |= PFR_TFLAG_PERSIST;
1278 else if (!strcmp($1, "counters"))
1279 table_opts.flags |= PFR_TFLAG_COUNTERS;
1280 else {
1281 yyerror("invalid table option '%s'", $1);
1282 free($1);
1283 YYERROR;
1284 }
1285 free($1);
1286 }
1287 | '{' optnl '}' { table_opts.init_addr = 1; }
1288 | '{' optnl table_host_list '}' {
1289 struct node_host *n;
1290 struct node_tinit *ti;
1291
1292 for (n = $3; n != NULL; n = n->next) {
1293 switch (n->addr.type) {
1294 case PF_ADDR_ADDRMASK:
1295 continue; /* ok */
1296 case PF_ADDR_RANGE:
1297 yyerror("address ranges are not "
1298 "permitted inside tables");
1299 break;
1300 case PF_ADDR_DYNIFTL:
1301 yyerror("dynamic addresses are not "
1302 "permitted inside tables");
1303 break;
1304 case PF_ADDR_TABLE:
1305 yyerror("tables cannot contain tables");
1306 break;
1307 case PF_ADDR_NOROUTE:
1308 yyerror("\"no-route\" is not permitted "
1309 "inside tables");
1310 break;
1311 case PF_ADDR_URPFFAILED:
1312 yyerror("\"urpf-failed\" is not "
1313 "permitted inside tables");
1314 break;
1315 default:
1316 yyerror("unknown address type %d",
1317 n->addr.type);
1318 }
1319 YYERROR;
1320 }
1321 if (!(ti = calloc(1, sizeof(*ti))))
1322 err(1, "table_opt: calloc");
1323 ti->host = $3;
1324 SIMPLEQ_INSERT_TAIL(&table_opts.init_nodes, ti,
1325 entries);
1326 table_opts.init_addr = 1;
1327 }
1328 | FILENAME STRING {
1329 struct node_tinit *ti;
1330
1331 if (!(ti = calloc(1, sizeof(*ti))))
1332 err(1, "table_opt: calloc");
1333 ti->file = $2;
1334 SIMPLEQ_INSERT_TAIL(&table_opts.init_nodes, ti,
1335 entries);
1336 table_opts.init_addr = 1;
1337 }
1338 ;
1339
1340 tablespec : xhost optweight {
1341 if ($2 > 0) {
1342 struct node_host *n;
1343 for (n = $1; n != NULL; n = n->next)
1344 n->weight = $2;
1345 }
1346 $$ = $1;
1347 }
1348 | '{' optnl table_host_list '}' { $$ = $3; }
1349 ;
1350
1351 table_host_list : tablespec optnl { $$ = $1; }
1352 | table_host_list comma tablespec optnl {
1353 $1->tail->next = $3;
1354 $1->tail = $3->tail;
1355 $$ = $1;
1356 }
1357 ;
1358
1359 queuespec : QUEUE STRING interface queue_opts {
1360 struct node_host *n;
1361
1362 if ($3 == NULL && $4.parent == NULL) {
1363 yyerror("root queue without interface");
1364 YYERROR;
1365 }
1366 if ($3 != NULL &&
1367 ((n = ifa_exists($3->ifname)) == NULL ||
1368 n->af != AF_LINK)) {
1369 yyerror("not an interface");
1370 YYERROR;
1371 }
1372
1373 expand_queue($2, $3, &$4);
1374 }
1375 ;
1376
1377 queue_opts : {
1378 bzero(&queue_opts, sizeof queue_opts);
1379 }
1380 queue_opts_l
1381 { $$ = queue_opts; }
1382 ;
1383
1384 queue_opts_l : queue_opts_l queue_opt
1385 | queue_opt
1386 ;
1387
1388 queue_opt : BANDWIDTH scspec optscs {
1389 if (queue_opts.marker & QOM_BWSPEC) {
1390 yyerror("bandwidth cannot be respecified");
1391 YYERROR;
1392 }
1393 queue_opts.marker |= QOM_BWSPEC;
1394 queue_opts.linkshare = $2;
1395 queue_opts.realtime= $3.realtime;
1396 queue_opts.upperlimit = $3.upperlimit;
1397 }
1398 | PARENT STRING {
1399 if (queue_opts.marker & QOM_PARENT) {
1400 yyerror("parent cannot be respecified");
1401 YYERROR;
1402 }
1403 queue_opts.marker |= QOM_PARENT;
1404 queue_opts.parent = $2;
1405 }
1406 | DEFAULT {
1407 if (queue_opts.marker & QOM_DEFAULT) {
1408 yyerror("default cannot be respecified");
1409 YYERROR;
1410 }
1411 queue_opts.marker |= QOM_DEFAULT;
1412 queue_opts.flags |= PFQS_DEFAULT;
1413 }
1414 | QLIMIT NUMBER {
1415 if (queue_opts.marker & QOM_QLIMIT) {
1416 yyerror("qlimit cannot be respecified");
1417 YYERROR;
1418 }
1419 if ($2 < 0 || $2 > 65535) {
1420 yyerror("qlimit out of range: max 65535");
1421 YYERROR;
1422 }
1423 queue_opts.marker |= QOM_QLIMIT;
1424 queue_opts.qlimit = $2;
1425 }
1426 | FLOWS NUMBER {
1427 if (queue_opts.marker & QOM_FLOWS) {
1428 yyerror("number of flows cannot be respecified");
1429 YYERROR;
1430 }
1431 if ($2 < 1 || $2 > 32767) {
1432 yyerror("number of flows out of range: "
1433 "max 32767");
1434 YYERROR;
1435 }
1436 queue_opts.marker |= QOM_FLOWS;
1437 queue_opts.flags |= PFQS_FLOWQUEUE;
1438 queue_opts.flowqueue.flows = $2;
1439 }
1440 | QUANTUM NUMBER {
1441 if (queue_opts.marker & QOM_QUANTUM) {
1442 yyerror("quantum cannot be respecified");
1443 YYERROR;
1444 }
1445 if ($2 < 1 || $2 > 65535) {
1446 yyerror("quantum out of range: max 65535");
1447 YYERROR;
1448 }
1449 queue_opts.marker |= QOM_QUANTUM;
1450 queue_opts.flowqueue.quantum = $2;
1451 }
1452 ;
1453
1454 optscs : /* nada */ {
1455
1456 }
1457 | comma MINIMUM scspec {
1458 $$.realtime = $3;
1459 }
1460 | comma MAXIMUM scspec {
1461 $$.upperlimit = $3;
1462 }
1463 | comma MINIMUM scspec comma MAXIMUM scspec {
1464 $$.realtime = $3;
1465 $$.upperlimit = $6;
1466 }
1467 | comma MAXIMUM scspec comma MINIMUM scspec {
1468 $$.realtime = $6;
1469 $$.upperlimit = $3;
1470 }
1471 ;
1472
1473 scspec : bandwidth {
1474 $$.m2 = $1;
1475 $$.d = 0;
1476 if ($$.m2.bw_percent) {
1477 yyerror("no bandwidth in %% yet");
1478 YYERROR;
1479 }
1480 }
1481 | bandwidth BURST bandwidth FOR STRING {
1482 u_long ul;
1483 char *cp;
1484
1485 ul = strtoul($5, &cp, 10);
1486 if (cp == NULL || strcmp(cp, "ms")) {
1487 yyerror("time in scspec must be in ms");
1488 YYERROR;
1489 }
1490
1491 $$.m1 = $3;
1492 $$.d = ul;
1493 $$.m2 = $1;
1494
1495 if ($$.m1.bw_percent || $$.m2.bw_percent) {
1496 yyerror("no bandwidth in %% yet");
1497 YYERROR;
1498 }
1499 }
1500 ;
1501
1502 bandwidth : STRING {
1503 double bps;
1504 char *cp;
1505
1506 $$.bw_percent = 0;
1507
1508 bps = strtod($1, &cp);
1509 if (cp != NULL) {
1510 if (strlen(cp) > 1) {
1511 char *cu = cp + 1;
1512 if (!strcmp(cu, "Bit") ||
1513 !strcmp(cu, "B") ||
1514 !strcmp(cu, "bit") ||
1515 !strcmp(cu, "b")) {
1516 *cu = 0;
1517 }
1518 }
1519 if (!strcmp(cp, "b"))
1520 ; /* nothing */
1521 else if (!strcmp(cp, "K"))
1522 bps *= 1000;
1523 else if (!strcmp(cp, "M"))
1524 bps *= 1000 * 1000;
1525 else if (!strcmp(cp, "G"))
1526 bps *= 1000 * 1000 * 1000;
1527 else if (!strcmp(cp, "%")) {
1528 if (bps < 0 || bps > 100) {
1529 yyerror("bandwidth spec "
1530 "out of range");
1531 free($1);
1532 YYERROR;
1533 }
1534 $$.bw_percent = bps;
1535 bps = 0;
1536 } else {
1537 yyerror("unknown unit \"%s\"", cp);
1538 free($1);
1539 YYERROR;
1540 }
1541 }
1542 free($1);
1543 if (bps < 0 || bps > (double)LLONG_MAX) {
1544 yyerror("bandwidth number too big");
1545 YYERROR;
1546 }
1547 $$.bw_absolute = (u_int64_t)bps;
1548 }
1549 | NUMBER {
1550 if ($1 < 0 || $1 > LLONG_MAX) {
1551 yyerror("bandwidth number too big");
1552 YYERROR;
1553 }
1554 $$.bw_percent = 0;
1555 $$.bw_absolute = $1;
1556 }
1557 ;
1558
1559 pfrule : action dir logquick interface af proto fromto
1560 filter_opts
1561 {
1562 struct pf_rule r;
1563 struct node_state_opt *o;
1564 struct node_proto *proto;
1565 int srctrack = 0;
1566 int statelock = 0;
1567 int adaptive = 0;
1568 int defaults = 0;
1569
1570 memset(&r, 0, sizeof(r));
1571 r.action = $1.b1;
1572 switch ($1.b2) {
1573 case PFRULE_RETURNRST:
1574 r.rule_flag |= PFRULE_RETURNRST;
1575 r.return_ttl = $1.w;
1576 break;
1577 case PFRULE_RETURNICMP:
1578 r.rule_flag |= PFRULE_RETURNICMP;
1579 r.return_icmp = $1.w;
1580 r.return_icmp6 = $1.w2;
1581 break;
1582 case PFRULE_RETURN:
1583 r.rule_flag |= PFRULE_RETURN;
1584 r.return_icmp = $1.w;
1585 r.return_icmp6 = $1.w2;
1586 break;
1587 }
1588 r.direction = $2;
1589 r.log = $3.log;
1590 r.logif = $3.logif;
1591 r.quick = $3.quick;
1592 r.af = $5;
1593
1594 if (filteropts_to_rule(&r, &$8))
1595 YYERROR;
1596
1597 if ($8.flags.b1 || $8.flags.b2 || $7.src_os) {
1598 for (proto = $6; proto != NULL &&
1599 proto->proto != IPPROTO_TCP;
1600 proto = proto->next)
1601 ; /* nothing */
1602 if (proto == NULL && $6 != NULL) {
1603 if ($8.flags.b1 || $8.flags.b2)
1604 yyerror(
1605 "flags only apply to tcp");
1606 if ($7.src_os)
1607 yyerror(
1608 "OS fingerprinting only "
1609 "apply to tcp");
1610 YYERROR;
1611 }
1612 }
1613
1614 r.keep_state = $8.keep.action;
1615 o = $8.keep.options;
1616
1617 /* 'keep state' by default on pass rules. */
1618 if (!r.keep_state && !r.action &&
1619 !($8.marker & FOM_KEEP)) {
1620 r.keep_state = PF_STATE_NORMAL;
1621 o = keep_state_defaults;
1622 defaults = 1;
1623 }
1624
1625 while (o) {
1626 struct node_state_opt *p = o;
1627
1628 switch (o->type) {
1629 case PF_STATE_OPT_MAX:
1630 if (r.max_states) {
1631 yyerror("state option 'max' "
1632 "multiple definitions");
1633 YYERROR;
1634 }
1635 r.max_states = o->data.max_states;
1636 break;
1637 case PF_STATE_OPT_NOSYNC:
1638 if (r.rule_flag & PFRULE_NOSYNC) {
1639 yyerror("state option 'sync' "
1640 "multiple definitions");
1641 YYERROR;
1642 }
1643 r.rule_flag |= PFRULE_NOSYNC;
1644 break;
1645 case PF_STATE_OPT_SRCTRACK:
1646 if (srctrack) {
1647 yyerror("state option "
1648 "'source-track' "
1649 "multiple definitions");
1650 YYERROR;
1651 }
1652 srctrack = o->data.src_track;
1653 r.rule_flag |= PFRULE_SRCTRACK;
1654 break;
1655 case PF_STATE_OPT_MAX_SRC_STATES:
1656 if (r.max_src_states) {
1657 yyerror("state option "
1658 "'max-src-states' "
1659 "multiple definitions");
1660 YYERROR;
1661 }
1662 if (o->data.max_src_states == 0) {
1663 yyerror("'max-src-states' must "
1664 "be > 0");
1665 YYERROR;
1666 }
1667 r.max_src_states =
1668 o->data.max_src_states;
1669 r.rule_flag |= PFRULE_SRCTRACK;
1670 break;
1671 case PF_STATE_OPT_OVERLOAD:
1672 if (r.overload_tblname[0]) {
1673 yyerror("multiple 'overload' "
1674 "table definitions");
1675 YYERROR;
1676 }
1677 if (strlcpy(r.overload_tblname,
1678 o->data.overload.tblname,
1679 PF_TABLE_NAME_SIZE) >=
1680 PF_TABLE_NAME_SIZE) {
1681 yyerror("state option: "
1682 "strlcpy");
1683 YYERROR;
1684 }
1685 r.flush = o->data.overload.flush;
1686 break;
1687 case PF_STATE_OPT_MAX_SRC_CONN:
1688 if (r.max_src_conn) {
1689 yyerror("state option "
1690 "'max-src-conn' "
1691 "multiple definitions");
1692 YYERROR;
1693 }
1694 if (o->data.max_src_conn == 0) {
1695 yyerror("'max-src-conn' "
1696 "must be > 0");
1697 YYERROR;
1698 }
1699 r.max_src_conn =
1700 o->data.max_src_conn;
1701 r.rule_flag |= PFRULE_SRCTRACK |
1702 PFRULE_RULESRCTRACK;
1703 break;
1704 case PF_STATE_OPT_MAX_SRC_CONN_RATE:
1705 if (r.max_src_conn_rate.limit) {
1706 yyerror("state option "
1707 "'max-src-conn-rate' "
1708 "multiple definitions");
1709 YYERROR;
1710 }
1711 if (!o->data.max_src_conn_rate.limit ||
1712 !o->data.max_src_conn_rate.seconds) {
1713 yyerror("'max-src-conn-rate' "
1714 "values must be > 0");
1715 YYERROR;
1716 }
1717 if (o->data.max_src_conn_rate.limit >
1718 PF_THRESHOLD_MAX) {
1719 yyerror("'max-src-conn-rate' "
1720 "maximum rate must be < %u",
1721 PF_THRESHOLD_MAX);
1722 YYERROR;
1723 }
1724 r.max_src_conn_rate.limit =
1725 o->data.max_src_conn_rate.limit;
1726 r.max_src_conn_rate.seconds =
1727 o->data.max_src_conn_rate.seconds;
1728 r.rule_flag |= PFRULE_SRCTRACK |
1729 PFRULE_RULESRCTRACK;
1730 break;
1731 case PF_STATE_OPT_MAX_SRC_NODES:
1732 if (r.max_src_nodes) {
1733 yyerror("state option "
1734 "'max-src-nodes' "
1735 "multiple definitions");
1736 YYERROR;
1737 }
1738 if (o->data.max_src_nodes == 0) {
1739 yyerror("'max-src-nodes' must "
1740 "be > 0");
1741 YYERROR;
1742 }
1743 r.max_src_nodes =
1744 o->data.max_src_nodes;
1745 r.rule_flag |= PFRULE_SRCTRACK |
1746 PFRULE_RULESRCTRACK;
1747 break;
1748 case PF_STATE_OPT_STATELOCK:
1749 if (statelock) {
1750 yyerror("state locking option: "
1751 "multiple definitions");
1752 YYERROR;
1753 }
1754 statelock = 1;
1755 r.rule_flag |= o->data.statelock;
1756 break;
1757 case PF_STATE_OPT_SLOPPY:
1758 if (r.rule_flag & PFRULE_STATESLOPPY) {
1759 yyerror("state sloppy option: "
1760 "multiple definitions");
1761 YYERROR;
1762 }
1763 r.rule_flag |= PFRULE_STATESLOPPY;
1764 break;
1765 case PF_STATE_OPT_PFLOW:
1766 if (r.rule_flag & PFRULE_PFLOW) {
1767 yyerror("state pflow "
1768 "option: multiple "
1769 "definitions");
1770 YYERROR;
1771 }
1772 r.rule_flag |= PFRULE_PFLOW;
1773 break;
1774 case PF_STATE_OPT_TIMEOUT:
1775 if (o->data.timeout.number ==
1776 PFTM_ADAPTIVE_START ||
1777 o->data.timeout.number ==
1778 PFTM_ADAPTIVE_END)
1779 adaptive = 1;
1780 if (r.timeout[o->data.timeout.number]) {
1781 yyerror("state timeout %s "
1782 "multiple definitions",
1783 pf_timeouts[o->data.
1784 timeout.number].name);
1785 YYERROR;
1786 }
1787 r.timeout[o->data.timeout.number] =
1788 o->data.timeout.seconds;
1789 }
1790 o = o->next;
1791 if (!defaults)
1792 free(p);
1793 }
1794
1795 /* 'flags S/SA' by default on stateful rules */
1796 if (!r.action && !r.flags && !r.flagset &&
1797 !$8.fragment && !($8.marker & FOM_FLAGS) &&
1798 r.keep_state) {
1799 r.flags = parse_flags("S");
1800 r.flagset = parse_flags("SA");
1801 }
1802 if (!adaptive && r.max_states) {
1803 r.timeout[PFTM_ADAPTIVE_START] =
1804 (r.max_states / 10) * 6;
1805 r.timeout[PFTM_ADAPTIVE_END] =
1806 (r.max_states / 10) * 12;
1807 }
1808 if (r.rule_flag & PFRULE_SRCTRACK) {
1809 if (srctrack == PF_SRCTRACK_GLOBAL &&
1810 r.max_src_nodes) {
1811 yyerror("'max-src-nodes' is "
1812 "incompatible with "
1813 "'source-track global'");
1814 YYERROR;
1815 }
1816 if (srctrack == PF_SRCTRACK_GLOBAL &&
1817 r.max_src_conn) {
1818 yyerror("'max-src-conn' is "
1819 "incompatible with "
1820 "'source-track global'");
1821 YYERROR;
1822 }
1823 if (srctrack == PF_SRCTRACK_GLOBAL &&
1824 r.max_src_conn_rate.seconds) {
1825 yyerror("'max-src-conn-rate' is "
1826 "incompatible with "
1827 "'source-track global'");
1828 YYERROR;
1829 }
1830 if (r.timeout[PFTM_SRC_NODE] <
1831 r.max_src_conn_rate.seconds)
1832 r.timeout[PFTM_SRC_NODE] =
1833 r.max_src_conn_rate.seconds;
1834 r.rule_flag |= PFRULE_SRCTRACK;
1835 if (srctrack == PF_SRCTRACK_RULE)
1836 r.rule_flag |= PFRULE_RULESRCTRACK;
1837 }
1838 if (r.keep_state && !statelock)
1839 r.rule_flag |= default_statelock;
1840
1841 decide_address_family($7.src.host, &r.af);
1842 decide_address_family($7.dst.host, &r.af);
1843
1844 if ($8.rt) {
1845 if ($8.rt != PF_DUPTO && !r.direction) {
1846 yyerror("direction must be explicit "
1847 "with rules that specify routing");
1848 YYERROR;
1849 }
1850 r.rt = $8.rt;
1851 }
1852
1853 if (expand_divertspec(&r, &$8.divert))
1854 YYERROR;
1855
1856 expand_rule(&r, 0, $4, &$8.nat, &$8.rdr, &$8.rroute, $6,
1857 $7.src_os,
1858 $7.src.host, $7.src.port, $7.dst.host, $7.dst.port,
1859 $8.uid, $8.gid, $8.rcv, $8.icmpspec);
1860 }
1861 ;
1862
1863 filter_opts : {
1864 bzero(&filter_opts, sizeof filter_opts);
1865 filter_opts.rtableid = -1;
1866 }
1867 filter_opts_l
1868 { $$ = filter_opts; }
1869 | /* empty */ {
1870 bzero(&filter_opts, sizeof filter_opts);
1871 filter_opts.rtableid = -1;
1872 $$ = filter_opts;
1873 }
1874 ;
1875
1876 filter_opts_l : filter_opts_l filter_opt
1877 | filter_opt
1878 ;
1879
1880 filter_opt : USER uids {
1881 if (filter_opts.uid)
1882 $2->tail->next = filter_opts.uid;
1883 filter_opts.uid = $2;
1884 }
1885 | GROUP gids {
1886 if (filter_opts.gid)
1887 $2->tail->next = filter_opts.gid;
1888 filter_opts.gid = $2;
1889 }
1890 | flags {
1891 if (filter_opts.marker & FOM_FLAGS) {
1892 yyerror("flags cannot be redefined");
1893 YYERROR;
1894 }
1895 filter_opts.marker |= FOM_FLAGS;
1896 filter_opts.flags.b1 |= $1.b1;
1897 filter_opts.flags.b2 |= $1.b2;
1898 filter_opts.flags.w |= $1.w;
1899 filter_opts.flags.w2 |= $1.w2;
1900 }
1901 | icmpspec {
1902 if (filter_opts.marker & FOM_ICMP) {
1903 yyerror("icmp-type cannot be redefined");
1904 YYERROR;
1905 }
1906 filter_opts.marker |= FOM_ICMP;
1907 filter_opts.icmpspec = $1;
1908 }
1909 | PRIO NUMBER {
1910 if (filter_opts.marker & FOM_PRIO) {
1911 yyerror("prio cannot be redefined");
1912 YYERROR;
1913 }
1914 if ($2 < 0 || $2 > IFQ_MAXPRIO) {
1915 yyerror("prio must be 0 - %u", IFQ_MAXPRIO);
1916 YYERROR;
1917 }
1918 filter_opts.marker |= FOM_PRIO;
1919 filter_opts.prio = $2;
1920 }
1921 | TOS tos {
1922 if (filter_opts.marker & FOM_TOS) {
1923 yyerror("tos cannot be redefined");
1924 YYERROR;
1925 }
1926 filter_opts.marker |= FOM_TOS;
1927 filter_opts.tos = $2;
1928 }
1929 | keep {
1930 if (filter_opts.marker & FOM_KEEP) {
1931 yyerror("modulate or keep cannot be redefined");
1932 YYERROR;
1933 }
1934 filter_opts.marker |= FOM_KEEP;
1935 filter_opts.keep.action = $1.action;
1936 filter_opts.keep.options = $1.options;
1937 }
1938 | FRAGMENT {
1939 filter_opts.fragment = 1;
1940 }
1941 | ALLOWOPTS {
1942 filter_opts.allowopts = 1;
1943 }
1944 | LABEL label {
1945 if (filter_opts.label) {
1946 yyerror("label cannot be redefined");
1947 YYERROR;
1948 }
1949 filter_opts.label = $2;
1950 }
1951 | QUEUE qname {
1952 if (filter_opts.queues.qname) {
1953 yyerror("queue cannot be redefined");
1954 YYERROR;
1955 }
1956 filter_opts.queues = $2;
1957 }
1958 | TAG string {
1959 filter_opts.tag = $2;
1960 }
1961 | not TAGGED string {
1962 filter_opts.match_tag = $3;
1963 filter_opts.match_tag_not = $1;
1964 }
1965 | PROBABILITY probability {
1966 double p;
1967
1968 p = floor($2 * UINT_MAX + 0.5);
1969 if (p < 0.0 || p > UINT_MAX) {
1970 yyerror("invalid probability: %g%%", $2 * 100);
1971 YYERROR;
1972 }
1973 filter_opts.prob = (u_int32_t)p;
1974 if (filter_opts.prob == 0)
1975 filter_opts.prob = 1;
1976 }
1977 | RTABLE NUMBER {
1978 if ($2 < 0 || $2 > RT_TABLEID_MAX) {
1979 yyerror("invalid rtable id");
1980 YYERROR;
1981 } else if (!lookup_rtable($2)) {
1982 yyerror("rtable %lld does not exist", $2);
1983 YYERROR;
1984 }
1985 filter_opts.rtableid = $2;
1986 }
1987 | DIVERTTO STRING PORT portplain {
1988 if (filter_opts.divert.type != PF_DIVERT_NONE) {
1989 yyerror("more than one divert option");
1990 YYERROR;
1991 }
1992 filter_opts.divert.type = PF_DIVERT_TO;
1993 if ((filter_opts.divert.addr = host($2, pf->opts)) == NULL) {
1994 yyerror("could not parse divert address: %s",
1995 $2);
1996 free($2);
1997 YYERROR;
1998 }
1999 free($2);
2000 filter_opts.divert.port = $4.a;
2001 if (!filter_opts.divert.port) {
2002 yyerror("invalid divert port: %u", ntohs($4.a));
2003 YYERROR;
2004 }
2005 }
2006 | DIVERTREPLY {
2007 if (filter_opts.divert.type != PF_DIVERT_NONE) {
2008 yyerror("more than one divert option");
2009 YYERROR;
2010 }
2011 filter_opts.divert.type = PF_DIVERT_REPLY;
2012 }
2013 | DIVERTPACKET PORT portplain {
2014 if (filter_opts.divert.type != PF_DIVERT_NONE) {
2015 yyerror("more than one divert option");
2016 YYERROR;
2017 }
2018 filter_opts.divert.type = PF_DIVERT_PACKET;
2019 /*
2020 * If IP reassembly was not turned off, also
2021 * forcibly enable TCP reassembly by default.
2022 */
2023 if (pf->reassemble & PF_REASS_ENABLED)
2024 filter_opts.marker |= FOM_SCRUB_TCP;
2025
2026 filter_opts.divert.port = $3.a;
2027 if (!filter_opts.divert.port) {
2028 yyerror("invalid divert port: %u", ntohs($3.a));
2029 YYERROR;
2030 }
2031 }
2032 | SCRUB '(' scrub_opts ')' {
2033 filter_opts.nodf = $3.nodf;
2034 filter_opts.minttl = $3.minttl;
2035 filter_opts.randomid = $3.randomid;
2036 filter_opts.max_mss = $3.maxmss;
2037 if ($3.reassemble_tcp)
2038 filter_opts.marker |= FOM_SCRUB_TCP;
2039 filter_opts.marker |= $3.marker;
2040 }
2041 | NATTO redirpool pool_opts {
2042 if (filter_opts.nat.rdr) {
2043 yyerror("cannot respecify nat-to/binat-to");
2044 YYERROR;
2045 }
2046 filter_opts.nat.rdr = $2;
2047 memcpy(&filter_opts.nat.pool_opts, &$3,
2048 sizeof(filter_opts.nat.pool_opts));
2049 }
2050 | AFTO af FROM redirpool pool_opts {
2051 if (filter_opts.nat.rdr) {
2052 yyerror("cannot respecify af-to");
2053 YYERROR;
2054 }
2055 if ($2 == 0) {
2056 yyerror("no target address family specified");
2057 YYERROR;
2058 }
2059 filter_opts.nat.af = $2;
2060 filter_opts.nat.rdr = $4;
2061 memcpy(&filter_opts.nat.pool_opts, &$5,
2062 sizeof(filter_opts.nat.pool_opts));
2063 filter_opts.rdr.rdr =
2064 calloc(1, sizeof(struct redirection));
2065 bzero(&filter_opts.rdr.pool_opts,
2066 sizeof(filter_opts.rdr.pool_opts));
2067 filter_opts.marker |= FOM_AFTO;
2068 }
2069 | AFTO af FROM redirpool pool_opts TO redirpool pool_opts {
2070 if (filter_opts.nat.rdr) {
2071 yyerror("cannot respecify af-to");
2072 YYERROR;
2073 }
2074 if ($2 == 0) {
2075 yyerror("no address family specified");
2076 YYERROR;
2077 }
2078 if (($4->host->af && $4->host->af != $2) ||
2079 ($7->host->af && $7->host->af != $2)) {
2080 yyerror("af-to addresses must be in the "
2081 "target address family");
2082 YYERROR;
2083 }
2084 filter_opts.nat.af = $2;
2085 filter_opts.nat.rdr = $4;
2086 memcpy(&filter_opts.nat.pool_opts, &$5,
2087 sizeof(filter_opts.nat.pool_opts));
2088 filter_opts.rdr.af = $2;
2089 filter_opts.rdr.rdr = $7;
2090 memcpy(&filter_opts.nat.pool_opts, &$8,
2091 sizeof(filter_opts.nat.pool_opts));
2092 filter_opts.marker |= FOM_AFTO;
2093 }
2094 | RDRTO redirpool pool_opts {
2095 if (filter_opts.rdr.rdr) {
2096 yyerror("cannot respecify rdr-to");
2097 YYERROR;
2098 }
2099 filter_opts.rdr.rdr = $2;
2100 memcpy(&filter_opts.rdr.pool_opts, &$3,
2101 sizeof(filter_opts.rdr.pool_opts));
2102 }
2103 | BINATTO redirpool pool_opts {
2104 if (filter_opts.nat.rdr) {
2105 yyerror("cannot respecify nat-to/binat-to");
2106 YYERROR;
2107 }
2108 filter_opts.nat.rdr = $2;
2109 filter_opts.nat.binat = 1;
2110 memcpy(&filter_opts.nat.pool_opts, &$3,
2111 sizeof(filter_opts.nat.pool_opts));
2112 filter_opts.nat.pool_opts.staticport = 1;
2113 }
2114 | ROUTETO routespec {
2115 filter_opts.rt = PF_ROUTETO;
2116 }
2117 | REPLYTO routespec {
2118 filter_opts.rt = PF_REPLYTO;
2119 }
2120 | DUPTO routespec {
2121 filter_opts.rt = PF_DUPTO;
2122 }
2123 | not RECEIVEDON if_item {
2124 if (filter_opts.rcv) {
2125 yyerror("cannot respecify received-on");
2126 YYERROR;
2127 }
2128 filter_opts.rcv = $3;
2129 filter_opts.rcv->not = $1;
2130 }
2131 | ONCE {
2132 filter_opts.marker |= FOM_ONCE;
2133 }
2134 | MAXPKTRATE NUMBER '/' NUMBER {
2135 if ($2 < 0 || $2 > UINT_MAX ||
2136 $4 < 0 || $4 > UINT_MAX) {
2137 yyerror("only positive values permitted");
2138 YYERROR;
2139 }
2140 if (filter_opts.pktrate.limit) {
2141 yyerror("cannot respecify max-pkt-rate");
2142 YYERROR;
2143 }
2144 filter_opts.pktrate.limit = $2;
2145 filter_opts.pktrate.seconds = $4;
2146 }
2147 | filter_sets
2148 ;
2149
2150 filter_sets : SET '(' filter_sets_l ')' { $$ = filter_opts; }
2151 | SET filter_set { $$ = filter_opts; }
2152 ;
2153
2154 filter_sets_l : filter_sets_l comma filter_set
2155 | filter_set
2156 ;
2157
2158 filter_set : prio {
2159 if (filter_opts.marker & FOM_SETPRIO) {
2160 yyerror("prio cannot be redefined");
2161 YYERROR;
2162 }
2163 filter_opts.marker |= FOM_SETPRIO;
2164 filter_opts.set_prio[0] = $1.b1;
2165 filter_opts.set_prio[1] = $1.b2;
2166 }
2167 | QUEUE qname {
2168 if (filter_opts.queues.qname) {
2169 yyerror("queue cannot be redefined");
2170 YYERROR;
2171 }
2172 filter_opts.queues = $2;
2173 }
2174 | TOS tos {
2175 if (filter_opts.marker & FOM_SETTOS) {
2176 yyerror("tos cannot be respecified");
2177 YYERROR;
2178 }
2179 filter_opts.marker |= FOM_SETTOS;
2180 filter_opts.settos = $2;
2181 }
2182 | DELAY NUMBER {
2183 if (filter_opts.delay) {
2184 yyerror("delay cannot be respecified");
2185 YYERROR;
2186 }
2187 if ($2 < 0 || $2 > 0xffff) {
2188 yyerror("illegal delay value %lld (0-%u)", $2,
2189 0xffff);
2190 YYERROR;
2191 }
2192 filter_opts.marker |= FOM_SETDELAY;
2193 filter_opts.delay = $2;
2194 }
2195 ;
2196
2197 prio : PRIO NUMBER {
2198 if ($2 < 0 || $2 > IFQ_MAXPRIO) {
2199 yyerror("prio must be 0 - %u", IFQ_MAXPRIO);
2200 YYERROR;
2201 }
2202 $$.b1 = $$.b2 = $2;
2203 }
2204 | PRIO '(' NUMBER comma NUMBER ')' {
2205 if ($3 < 0 || $3 > IFQ_MAXPRIO ||
2206 $5 < 0 || $5 > IFQ_MAXPRIO) {
2207 yyerror("prio must be 0 - %u", IFQ_MAXPRIO);
2208 YYERROR;
2209 }
2210 $$.b1 = $3;
2211 $$.b2 = $5;
2212 }
2213 ;
2214
2215 probability : STRING {
2216 char *e;
2217 double p = strtod($1, &e);
2218
2219 if (*e == '%') {
2220 p *= 0.01;
2221 e++;
2222 }
2223 if (*e) {
2224 yyerror("invalid probability: %s", $1);
2225 free($1);
2226 YYERROR;
2227 }
2228 free($1);
2229 $$ = p;
2230 }
2231 | NUMBER {
2232 $$ = (double)$1;
2233 }
2234 ;
2235
2236
2237 action : PASS { $$.b1 = PF_PASS; $$.b2 = $$.w = 0; }
2238 | MATCH { $$.b1 = PF_MATCH; $$.b2 = $$.w = 0; }
2239 | BLOCK blockspec { $$ = $2; $$.b1 = PF_DROP; }
2240 ;
2241
2242 blockspec : /* empty */ {
2243 $$.b2 = blockpolicy;
2244 $$.w = returnicmpdefault;
2245 $$.w2 = returnicmp6default;
2246 }
2247 | DROP {
2248 $$.b2 = PFRULE_DROP;
2249 $$.w = 0;
2250 $$.w2 = 0;
2251 }
2252 | RETURNRST {
2253 $$.b2 = PFRULE_RETURNRST;
2254 $$.w = 0;
2255 $$.w2 = 0;
2256 }
2257 | RETURNRST '(' TTL NUMBER ')' {
2258 if ($4 < 0 || $4 > 255) {
2259 yyerror("illegal ttl value %lld", $4);
2260 YYERROR;
2261 }
2262 $$.b2 = PFRULE_RETURNRST;
2263 $$.w = $4;
2264 $$.w2 = 0;
2265 }
2266 | RETURNICMP {
2267 $$.b2 = PFRULE_RETURNICMP;
2268 $$.w = returnicmpdefault;
2269 $$.w2 = returnicmp6default;
2270 }
2271 | RETURNICMP6 {
2272 $$.b2 = PFRULE_RETURNICMP;
2273 $$.w = returnicmpdefault;
2274 $$.w2 = returnicmp6default;
2275 }
2276 | RETURNICMP '(' reticmpspec ')' {
2277 $$.b2 = PFRULE_RETURNICMP;
2278 $$.w = $3;
2279 $$.w2 = returnicmpdefault;
2280 }
2281 | RETURNICMP6 '(' reticmp6spec ')' {
2282 $$.b2 = PFRULE_RETURNICMP;
2283 $$.w = returnicmpdefault;
2284 $$.w2 = $3;
2285 }
2286 | RETURNICMP '(' reticmpspec comma reticmp6spec ')' {
2287 $$.b2 = PFRULE_RETURNICMP;
2288 $$.w = $3;
2289 $$.w2 = $5;
2290 }
2291 | RETURN {
2292 $$.b2 = PFRULE_RETURN;
2293 $$.w = returnicmpdefault;
2294 $$.w2 = returnicmp6default;
2295 }
2296 ;
2297
2298 reticmpspec : STRING {
2299 if (!($$ = parseicmpspec($1, AF_INET))) {
2300 free($1);
2301 YYERROR;
2302 }
2303 free($1);
2304 }
2305 | NUMBER {
2306 u_int8_t icmptype;
2307
2308 if ($1 < 0 || $1 > 255) {
2309 yyerror("invalid icmp code %lld", $1);
2310 YYERROR;
2311 }
2312 icmptype = returnicmpdefault >> 8;
2313 $$ = (icmptype << 8 | $1);
2314 }
2315 ;
2316
2317 reticmp6spec : STRING {
2318 if (!($$ = parseicmpspec($1, AF_INET6))) {
2319 free($1);
2320 YYERROR;
2321 }
2322 free($1);
2323 }
2324 | NUMBER {
2325 u_int8_t icmptype;
2326
2327 if ($1 < 0 || $1 > 255) {
2328 yyerror("invalid icmp code %lld", $1);
2329 YYERROR;
2330 }
2331 icmptype = returnicmp6default >> 8;
2332 $$ = (icmptype << 8 | $1);
2333 }
2334 ;
2335
2336 dir : /* empty */ { $$ = PF_INOUT; }
2337 | IN { $$ = PF_IN; }
2338 | OUT { $$ = PF_OUT; }
2339 ;
2340
2341 quick : /* empty */ { $$.quick = 0; }
2342 | QUICK { $$.quick = 1; }
2343 ;
2344
2345 logquick : /* empty */ { $$.log = 0; $$.quick = 0; $$.logif = 0; }
2346 | log { $$ = $1; $$.quick = 0; }
2347 | QUICK { $$.quick = 1; $$.log = 0; $$.logif = 0; }
2348 | log QUICK { $$ = $1; $$.quick = 1; }
2349 | QUICK log { $$ = $2; $$.quick = 1; }
2350 ;
2351
2352 log : LOG { $$.log = PF_LOG; $$.logif = 0; }
2353 | LOG '(' logopts ')' {
2354 $$.log = PF_LOG | $3.log;
2355 $$.logif = $3.logif;
2356 }
2357 ;
2358
2359 logopts : logopt { $$ = $1; }
2360 | logopts comma logopt {
2361 $$.log = $1.log | $3.log;
2362 $$.logif = $3.logif;
2363 if ($$.logif == 0)
2364 $$.logif = $1.logif;
2365 }
2366 ;
2367
2368 logopt : ALL { $$.log = PF_LOG_ALL; $$.logif = 0; }
2369 | MATCHES { $$.log = PF_LOG_MATCHES; $$.logif = 0; }
2370 | USER { $$.log = PF_LOG_USER; $$.logif = 0; }
2371 | TO string {
2372 const char *errstr;
2373 u_int i;
2374
2375 $$.log = 0;
2376 if (strncmp($2, "pflog", 5)) {
2377 yyerror("%s: should be a pflog interface", $2);
2378 free($2);
2379 YYERROR;
2380 }
2381 i = strtonum($2 + 5, 0, 255, &errstr);
2382 if (errstr) {
2383 yyerror("%s: %s", $2, errstr);
2384 free($2);
2385 YYERROR;
2386 }
2387 free($2);
2388 $$.logif = i;
2389 }
2390 ;
2391
2392 interface : /* empty */ { $$ = NULL; }
2393 | ON if_item_not { $$ = $2; }
2394 | ON '{' optnl if_list '}' { $$ = $4; }
2395 ;
2396
2397 if_list : if_item_not optnl { $$ = $1; }
2398 | if_list comma if_item_not optnl {
2399 $1->tail->next = $3;
2400 $1->tail = $3;
2401 $$ = $1;
2402 }
2403 ;
2404
2405 if_item_not : not if_item { $$ = $2; $$->not = $1; }
2406 ;
2407
2408 if_item : STRING {
2409 struct node_host *n;
2410
2411 $$ = calloc(1, sizeof(struct node_if));
2412 if ($$ == NULL)
2413 err(1, "if_item: calloc");
2414 if (strlcpy($$->ifname, $1, sizeof($$->ifname)) >=
2415 sizeof($$->ifname)) {
2416 free($1);
2417 free($$);
2418 yyerror("interface name too long");
2419 YYERROR;
2420 }
2421
2422 if ((n = ifa_exists($1)) != NULL)
2423 $$->ifa_flags = n->ifa_flags;
2424
2425 free($1);
2426 $$->not = 0;
2427 $$->next = NULL;
2428 $$->tail = $$;
2429 }
2430 | ANY {
2431 $$ = calloc(1, sizeof(struct node_if));
2432 if ($$ == NULL)
2433 err(1, "if_item: calloc");
2434 strlcpy($$->ifname, "any", sizeof($$->ifname));
2435 $$->not = 0;
2436 $$->next = NULL;
2437 $$->tail = $$;
2438 }
2439 | RDOMAIN NUMBER {
2440 if ($2 < 0 || $2 > RT_TABLEID_MAX)
2441 yyerror("rdomain %lld outside range", $2);
2442
2443 $$ = calloc(1, sizeof(struct node_if));
2444 if ($$ == NULL)
2445 err(1, "if_item: calloc");
2446 $$->not = 0;
2447 $$->use_rdomain = 1;
2448 $$->rdomain = $2;
2449 $$->next = NULL;
2450 $$->tail = $$;
2451 }
2452 ;
2453
2454 af : /* empty */ { $$ = 0; }
2455 | INET { $$ = AF_INET; }
2456 | INET6 { $$ = AF_INET6; }
2457 ;
2458
2459 proto : /* empty */ { $$ = NULL; }
2460 | PROTO proto_item { $$ = $2; }
2461 | PROTO '{' optnl proto_list '}' { $$ = $4; }
2462 ;
2463
2464 proto_list : proto_item optnl { $$ = $1; }
2465 | proto_list comma proto_item optnl {
2466 $1->tail->next = $3;
2467 $1->tail = $3;
2468 $$ = $1;
2469 }
2470 ;
2471
2472 proto_item : protoval {
2473 u_int8_t pr;
2474
2475 pr = (u_int8_t)$1;
2476 if (pr == 0) {
2477 yyerror("proto 0 cannot be used");
2478 YYERROR;
2479 }
2480 $$ = calloc(1, sizeof(struct node_proto));
2481 if ($$ == NULL)
2482 err(1, "proto_item: calloc");
2483 $$->proto = pr;
2484 $$->next = NULL;
2485 $$->tail = $$;
2486 }
2487 ;
2488
2489 protoval : STRING {
2490 struct protoent *p;
2491
2492 p = getprotobyname($1);
2493 if (p == NULL) {
2494 yyerror("unknown protocol %s", $1);
2495 free($1);
2496 YYERROR;
2497 }
2498 $$ = p->p_proto;
2499 free($1);
2500 }
2501 | NUMBER {
2502 if ($1 < 0 || $1 > 255) {
2503 yyerror("protocol outside range");
2504 YYERROR;
2505 }
2506 }
2507 ;
2508
2509 fromto : ALL {
2510 $$.src.host = NULL;
2511 $$.src.port = NULL;
2512 $$.dst.host = NULL;
2513 $$.dst.port = NULL;
2514 $$.src_os = NULL;
2515 }
2516 | from os to {
2517 $$.src = $1;
2518 $$.src_os = $2;
2519 $$.dst = $3;
2520 }
2521 ;
2522
2523 os : /* empty */ { $$ = NULL; }
2524 | OS xos { $$ = $2; }
2525 | OS '{' optnl os_list '}' { $$ = $4; }
2526 ;
2527
2528 xos : STRING {
2529 $$ = calloc(1, sizeof(struct node_os));
2530 if ($$ == NULL)
2531 err(1, "os: calloc");
2532 $$->os = $1;
2533 $$->tail = $$;
2534 }
2535 ;
2536
2537 os_list : xos optnl { $$ = $1; }
2538 | os_list comma xos optnl {
2539 $1->tail->next = $3;
2540 $1->tail = $3;
2541 $$ = $1;
2542 }
2543 ;
2544
2545 from : /* empty */ {
2546 $$.host = NULL;
2547 $$.port = NULL;
2548 }
2549 | FROM ipportspec {
2550 $$ = $2;
2551 }
2552 ;
2553
2554 to : /* empty */ {
2555 $$.host = NULL;
2556 $$.port = NULL;
2557 }
2558 | TO ipportspec {
2559 if (disallow_urpf_failed($2.host, "\"urpf-failed\" is "
2560 "not permitted in a destination address"))
2561 YYERROR;
2562 $$ = $2;
2563 }
2564 ;
2565
2566 ipportspec : ipspec {
2567 $$.host = $1;
2568 $$.port = NULL;
2569 }
2570 | ipspec PORT portspec {
2571 $$.host = $1;
2572 $$.port = $3;
2573 }
2574 | PORT portspec {
2575 $$.host = NULL;
2576 $$.port = $2;
2577 }
2578 ;
2579
2580 optnl : '\n' optnl
2581 | /* empty */
2582 ;
2583
2584 ipspec : ANY { $$ = NULL; }
2585 | xhost { $$ = $1; }
2586 | '{' optnl host_list '}' { $$ = $3; }
2587 ;
2588
2589
2590 host_list : ipspec optnl { $$ = $1; }
2591 | host_list comma ipspec optnl {
2592 if ($1 == NULL) {
2593 freehostlist($3);
2594 $$ = $1;
2595 } else if ($3 == NULL) {
2596 freehostlist($1);
2597 $$ = $3;
2598 } else {
2599 $1->tail->next = $3;
2600 $1->tail = $3->tail;
2601 $$ = $1;
2602 }
2603 }
2604 ;
2605
2606 xhost : not host {
2607 struct node_host *n;
2608
2609 for (n = $2; n != NULL; n = n->next)
2610 n->not = $1;
2611 $$ = $2;
2612 }
2613 | not NOROUTE {
2614 $$ = calloc(1, sizeof(struct node_host));
2615 if ($$ == NULL)
2616 err(1, "xhost: calloc");
2617 $$->addr.type = PF_ADDR_NOROUTE;
2618 $$->next = NULL;
2619 $$->not = $1;
2620 $$->tail = $$;
2621 }
2622 | not URPFFAILED {
2623 $$ = calloc(1, sizeof(struct node_host));
2624 if ($$ == NULL)
2625 err(1, "xhost: calloc");
2626 $$->addr.type = PF_ADDR_URPFFAILED;
2627 $$->next = NULL;
2628 $$->not = $1;
2629 $$->tail = $$;
2630 }
2631 ;
2632
2633 optweight : WEIGHT NUMBER {
2634 if ($2 < 1 || $2 > USHRT_MAX) {
2635 yyerror("weight out of range");
2636 YYERROR;
2637 }
2638 $$ = $2;
2639 }
2640 | /* empty */ { $$ = 0; }
2641 ;
2642
2643 host : STRING {
2644 if (($$ = host($1, pf->opts)) == NULL) {
2645 /* error. "any" is handled elsewhere */
2646 free($1);
2647 yyerror("could not parse host specification");
2648 YYERROR;
2649 }
2650 free($1);
2651
2652 }
2653 | STRING '-' STRING {
2654 struct node_host *b, *e;
2655
2656 if ((b = host($1, pf->opts)) == NULL ||
2657 (e = host($3, pf->opts)) == NULL) {
2658 free($1);
2659 free($3);
2660 yyerror("could not parse host specification");
2661 YYERROR;
2662 }
2663 if (b->af != e->af ||
2664 b->addr.type != PF_ADDR_ADDRMASK ||
2665 e->addr.type != PF_ADDR_ADDRMASK ||
2666 unmask(&b->addr.v.a.mask) !=
2667 (b->af == AF_INET ? 32 : 128) ||
2668 unmask(&e->addr.v.a.mask) !=
2669 (e->af == AF_INET ? 32 : 128) ||
2670 b->next != NULL || b->not ||
2671 e->next != NULL || e->not) {
2672 free(b);
2673 free(e);
2674 free($1);
2675 free($3);
2676 yyerror("invalid address range");
2677 YYERROR;
2678 }
2679 memcpy(&b->addr.v.a.mask, &e->addr.v.a.addr,
2680 sizeof(b->addr.v.a.mask));
2681 b->addr.type = PF_ADDR_RANGE;
2682 $$ = b;
2683 free(e);
2684 free($1);
2685 free($3);
2686 }
2687 | STRING '/' NUMBER {
2688 char *buf;
2689
2690 if (asprintf(&buf, "%s/%lld", $1, $3) == -1)
2691 err(1, "host: asprintf");
2692 free($1);
2693 if (($$ = host(buf, pf->opts)) == NULL) {
2694 /* error. "any" is handled elsewhere */
2695 free(buf);
2696 yyerror("could not parse host specification");
2697 YYERROR;
2698 }
2699 free(buf);
2700 }
2701 | NUMBER '/' NUMBER {
2702 char *buf;
2703
2704 /* ie. for 10/8 parsing */
2705 if (asprintf(&buf, "%lld/%lld", $1, $3) == -1)
2706 err(1, "host: asprintf");
2707 if (($$ = host(buf, pf->opts)) == NULL) {
2708 /* error. "any" is handled elsewhere */
2709 free(buf);
2710 yyerror("could not parse host specification");
2711 YYERROR;
2712 }
2713 free(buf);
2714 }
2715 | dynaddr
2716 | dynaddr '/' NUMBER {
2717 struct node_host *n;
2718
2719 if ($3 < 0 || $3 > 128) {
2720 yyerror("bit number too big");
2721 YYERROR;
2722 }
2723 $$ = $1;
2724 for (n = $1; n != NULL; n = n->next)
2725 set_ipmask(n, $3);
2726 }
2727 | '<' STRING '>' {
2728 if (strlen($2) >= PF_TABLE_NAME_SIZE) {
2729 yyerror("table name '%s' too long", $2);
2730 free($2);
2731 YYERROR;
2732 }
2733 $$ = calloc(1, sizeof(struct node_host));
2734 if ($$ == NULL)
2735 err(1, "host: calloc");
2736 $$->addr.type = PF_ADDR_TABLE;
2737 if (strlcpy($$->addr.v.tblname, $2,
2738 sizeof($$->addr.v.tblname)) >=
2739 sizeof($$->addr.v.tblname))
2740 errx(1, "host: strlcpy");
2741 free($2);
2742 $$->next = NULL;
2743 $$->tail = $$;
2744 }
2745 | ROUTE STRING {
2746 $$ = calloc(1, sizeof(struct node_host));
2747 if ($$ == NULL) {
2748 free($2);
2749 err(1, "host: calloc");
2750 }
2751 $$->addr.type = PF_ADDR_RTLABEL;
2752 if (strlcpy($$->addr.v.rtlabelname, $2,
2753 sizeof($$->addr.v.rtlabelname)) >=
2754 sizeof($$->addr.v.rtlabelname)) {
2755 yyerror("route label too long, max %zu chars",
2756 sizeof($$->addr.v.rtlabelname) - 1);
2757 free($2);
2758 free($$);
2759 YYERROR;
2760 }
2761 $$->next = NULL;
2762 $$->tail = $$;
2763 free($2);
2764 }
2765 ;
2766
2767 number : NUMBER
2768 | STRING {
2769 u_long ulval;
2770
2771 if (atoul($1, &ulval) == -1) {
2772 yyerror("%s is not a number", $1);
2773 free($1);
2774 YYERROR;
2775 } else
2776 $$ = ulval;
2777 free($1);
2778 }
2779 ;
2780
2781 dynaddr : '(' STRING ')' {
2782 int flags = 0;
2783 char *p, *op;
2784
2785 op = $2;
2786 if (!isalpha((unsigned char)op[0])) {
2787 yyerror("invalid interface name '%s'", op);
2788 free(op);
2789 YYERROR;
2790 }
2791 while ((p = strrchr($2, ':')) != NULL) {
2792 if (!strcmp(p+1, "network"))
2793 flags |= PFI_AFLAG_NETWORK;
2794 else if (!strcmp(p+1, "broadcast"))
2795 flags |= PFI_AFLAG_BROADCAST;
2796 else if (!strcmp(p+1, "peer"))
2797 flags |= PFI_AFLAG_PEER;
2798 else if (!strcmp(p+1, "0"))
2799 flags |= PFI_AFLAG_NOALIAS;
2800 else {
2801 yyerror("interface %s has bad modifier",
2802 $2);
2803 free(op);
2804 YYERROR;
2805 }
2806 *p = '\0';
2807 }
2808 if (flags & (flags - 1) & PFI_AFLAG_MODEMASK) {
2809 free(op);
2810 yyerror("illegal combination of "
2811 "interface modifiers");
2812 YYERROR;
2813 }
2814 $$ = calloc(1, sizeof(struct node_host));
2815 if ($$ == NULL)
2816 err(1, "address: calloc");
2817 $$->af = 0;
2818 set_ipmask($$, 128);
2819 $$->addr.type = PF_ADDR_DYNIFTL;
2820 $$->addr.iflags = flags;
2821 if (strlcpy($$->addr.v.ifname, $2,
2822 sizeof($$->addr.v.ifname)) >=
2823 sizeof($$->addr.v.ifname)) {
2824 free(op);
2825 free($$);
2826 yyerror("interface name too long");
2827 YYERROR;
2828 }
2829 free(op);
2830 $$->next = NULL;
2831 $$->tail = $$;
2832 }
2833 ;
2834
2835 portspec : port_item { $$ = $1; }
2836 | '{' optnl port_list '}' { $$ = $3; }
2837 ;
2838
2839 port_list : port_item optnl { $$ = $1; }
2840 | port_list comma port_item optnl {
2841 $1->tail->next = $3;
2842 $1->tail = $3;
2843 $$ = $1;
2844 }
2845 ;
2846
2847 port_item : portrange {
2848 $$ = calloc(1, sizeof(struct node_port));
2849 if ($$ == NULL)
2850 err(1, "port_item: calloc");
2851 $$->port[0] = $1.a;
2852 $$->port[1] = $1.b;
2853 if ($1.t) {
2854 $$->op = PF_OP_RRG;
2855
2856 if (validate_range($$->op, $$->port[0],
2857 $$->port[1])) {
2858 yyerror("invalid port range");
2859 YYERROR;
2860 }
2861 } else
2862 $$->op = PF_OP_EQ;
2863 $$->next = NULL;
2864 $$->tail = $$;
2865 }
2866 | unaryop portrange {
2867 if ($2.t) {
2868 yyerror("':' cannot be used with an other "
2869 "port operator");
2870 YYERROR;
2871 }
2872 $$ = calloc(1, sizeof(struct node_port));
2873 if ($$ == NULL)
2874 err(1, "port_item: calloc");
2875 $$->port[0] = $2.a;
2876 $$->port[1] = $2.b;
2877 $$->op = $1;
2878 $$->next = NULL;
2879 $$->tail = $$;
2880 }
2881 | portrange PORTBINARY portrange {
2882 if ($1.t || $3.t) {
2883 yyerror("':' cannot be used with an other "
2884 "port operator");
2885 YYERROR;
2886 }
2887 $$ = calloc(1, sizeof(struct node_port));
2888 if ($$ == NULL)
2889 err(1, "port_item: calloc");
2890 $$->port[0] = $1.a;
2891 $$->port[1] = $3.a;
2892 $$->op = $2;
2893 if (validate_range($$->op, $$->port[0], $$->port[1])) {
2894 yyerror("invalid port range");
2895 YYERROR;
2896 }
2897 $$->next = NULL;
2898 $$->tail = $$;
2899 }
2900 ;
2901
2902 portplain : numberstring {
2903 if (parseport($1, &$$, 0) == -1) {
2904 free($1);
2905 YYERROR;
2906 }
2907 free($1);
2908 }
2909 ;
2910
2911 portrange : numberstring {
2912 if (parseport($1, &$$, PPORT_RANGE) == -1) {
2913 free($1);
2914 YYERROR;
2915 }
2916 free($1);
2917 }
2918 ;
2919
2920 uids : uid_item { $$ = $1; }
2921 | '{' optnl uid_list '}' { $$ = $3; }
2922 ;
2923
2924 uid_list : uid_item optnl { $$ = $1; }
2925 | uid_list comma uid_item optnl {
2926 $1->tail->next = $3;
2927 $1->tail = $3;
2928 $$ = $1;
2929 }
2930 ;
2931
2932 uid_item : uid {
2933 $$ = calloc(1, sizeof(struct node_uid));
2934 if ($$ == NULL)
2935 err(1, "uid_item: calloc");
2936 $$->uid[0] = $1;
2937 $$->uid[1] = $1;
2938 $$->op = PF_OP_EQ;
2939 $$->next = NULL;
2940 $$->tail = $$;
2941 }
2942 | unaryop uid {
2943 if ($2 == -1 && $1 != PF_OP_EQ && $1 != PF_OP_NE) {
2944 yyerror("user unknown requires operator = or "
2945 "!=");
2946 YYERROR;
2947 }
2948 $$ = calloc(1, sizeof(struct node_uid));
2949 if ($$ == NULL)
2950 err(1, "uid_item: calloc");
2951 $$->uid[0] = $2;
2952 $$->uid[1] = $2;
2953 $$->op = $1;
2954 $$->next = NULL;
2955 $$->tail = $$;
2956 }
2957 | uid PORTBINARY uid {
2958 if ($1 == -1 || $3 == -1) {
2959 yyerror("user unknown requires operator = or "
2960 "!=");
2961 YYERROR;
2962 }
2963 $$ = calloc(1, sizeof(struct node_uid));
2964 if ($$ == NULL)
2965 err(1, "uid_item: calloc");
2966 $$->uid[0] = $1;
2967 $$->uid[1] = $3;
2968 $$->op = $2;
2969 $$->next = NULL;
2970 $$->tail = $$;
2971 }
2972 ;
2973
2974 uid : STRING {
2975 if (!strcmp($1, "unknown"))
2976 $$ = -1;
2977 else {
2978 uid_t uid;
2979
2980 if (uid_from_user($1, &uid) == -1) {
2981 yyerror("unknown user %s", $1);
2982 free($1);
2983 YYERROR;
2984 }
2985 $$ = uid;
2986 }
2987 free($1);
2988 }
2989 | NUMBER {
2990 if ($1 < 0 || $1 >= UID_MAX) {
2991 yyerror("illegal uid value %lld", $1);
2992 YYERROR;
2993 }
2994 $$ = $1;
2995 }
2996 ;
2997
2998 gids : gid_item { $$ = $1; }
2999 | '{' optnl gid_list '}' { $$ = $3; }
3000 ;
3001
3002 gid_list : gid_item optnl { $$ = $1; }
3003 | gid_list comma gid_item optnl {
3004 $1->tail->next = $3;
3005 $1->tail = $3;
3006 $$ = $1;
3007 }
3008 ;
3009
3010 gid_item : gid {
3011 $$ = calloc(1, sizeof(struct node_gid));
3012 if ($$ == NULL)
3013 err(1, "gid_item: calloc");
3014 $$->gid[0] = $1;
3015 $$->gid[1] = $1;
3016 $$->op = PF_OP_EQ;
3017 $$->next = NULL;
3018 $$->tail = $$;
3019 }
3020 | unaryop gid {
3021 if ($2 == -1 && $1 != PF_OP_EQ && $1 != PF_OP_NE) {
3022 yyerror("group unknown requires operator = or "
3023 "!=");
3024 YYERROR;
3025 }
3026 $$ = calloc(1, sizeof(struct node_gid));
3027 if ($$ == NULL)
3028 err(1, "gid_item: calloc");
3029 $$->gid[0] = $2;
3030 $$->gid[1] = $2;
3031 $$->op = $1;
3032 $$->next = NULL;
3033 $$->tail = $$;
3034 }
3035 | gid PORTBINARY gid {
3036 if ($1 == -1 || $3 == -1) {
3037 yyerror("group unknown requires operator = or "
3038 "!=");
3039 YYERROR;
3040 }
3041 $$ = calloc(1, sizeof(struct node_gid));
3042 if ($$ == NULL)
3043 err(1, "gid_item: calloc");
3044 $$->gid[0] = $1;
3045 $$->gid[1] = $3;
3046 $$->op = $2;
3047 $$->next = NULL;
3048 $$->tail = $$;
3049 }
3050 ;
3051
3052 gid : STRING {
3053 if (!strcmp($1, "unknown"))
3054 $$ = -1;
3055 else {
3056 gid_t gid;
3057
3058 if (gid_from_group($1, &gid) == -1) {
3059 yyerror("unknown group %s", $1);
3060 free($1);
3061 YYERROR;
3062 }
3063 $$ = gid;
3064 }
3065 free($1);
3066 }
3067 | NUMBER {
3068 if ($1 < 0 || $1 >= GID_MAX) {
3069 yyerror("illegal gid value %lld", $1);
3070 YYERROR;
3071 }
3072 $$ = $1;
3073 }
3074 ;
3075
3076 flag : STRING {
3077 int f;
3078
3079 if ((f = parse_flags($1)) < 0) {
3080 yyerror("bad flags %s", $1);
3081 free($1);
3082 YYERROR;
3083 }
3084 free($1);
3085 $$.b1 = f;
3086 }
3087 ;
3088
3089 flags : FLAGS flag '/' flag { $$.b1 = $2.b1; $$.b2 = $4.b1; }
3090 | FLAGS '/' flag { $$.b1 = 0; $$.b2 = $3.b1; }
3091 | FLAGS ANY { $$.b1 = 0; $$.b2 = 0; }
3092 ;
3093
3094 icmpspec : ICMPTYPE icmp_item { $$ = $2; }
3095 | ICMPTYPE '{' optnl icmp_list '}' { $$ = $4; }
3096 | ICMP6TYPE icmp6_item { $$ = $2; }
3097 | ICMP6TYPE '{' optnl icmp6_list '}' { $$ = $4; }
3098 ;
3099
3100 icmp_list : icmp_item optnl { $$ = $1; }
3101 | icmp_list comma icmp_item optnl {
3102 $1->tail->next = $3;
3103 $1->tail = $3;
3104 $$ = $1;
3105 }
3106 ;
3107
3108 icmp6_list : icmp6_item optnl { $$ = $1; }
3109 | icmp6_list comma icmp6_item optnl {
3110 $1->tail->next = $3;
3111 $1->tail = $3;
3112 $$ = $1;
3113 }
3114 ;
3115
3116 icmp_item : icmptype {
3117 $$ = calloc(1, sizeof(struct node_icmp));
3118 if ($$ == NULL)
3119 err(1, "icmp_item: calloc");
3120 $$->type = $1;
3121 $$->code = 0;
3122 $$->proto = IPPROTO_ICMP;
3123 $$->next = NULL;
3124 $$->tail = $$;
3125 }
3126 | icmptype CODE STRING {
3127 const struct icmpcodeent *p;
3128
3129 if ((p = geticmpcodebyname($1-1, $3, AF_INET)) == NULL) {
3130 yyerror("unknown icmp-code %s", $3);
3131 free($3);
3132 YYERROR;
3133 }
3134
3135 free($3);
3136 $$ = calloc(1, sizeof(struct node_icmp));
3137 if ($$ == NULL)
3138 err(1, "icmp_item: calloc");
3139 $$->type = $1;
3140 $$->code = p->code + 1;
3141 $$->proto = IPPROTO_ICMP;
3142 $$->next = NULL;
3143 $$->tail = $$;
3144 }
3145 | icmptype CODE NUMBER {
3146 if ($3 < 0 || $3 > 255) {
3147 yyerror("illegal icmp-code %lld", $3);
3148 YYERROR;
3149 }
3150 $$ = calloc(1, sizeof(struct node_icmp));
3151 if ($$ == NULL)
3152 err(1, "icmp_item: calloc");
3153 $$->type = $1;
3154 $$->code = $3 + 1;
3155 $$->proto = IPPROTO_ICMP;
3156 $$->next = NULL;
3157 $$->tail = $$;
3158 }
3159 ;
3160
3161 icmp6_item : icmp6type {
3162 $$ = calloc(1, sizeof(struct node_icmp));
3163 if ($$ == NULL)
3164 err(1, "icmp_item: calloc");
3165 $$->type = $1;
3166 $$->code = 0;
3167 $$->proto = IPPROTO_ICMPV6;
3168 $$->next = NULL;
3169 $$->tail = $$;
3170 }
3171 | icmp6type CODE STRING {
3172 const struct icmpcodeent *p;
3173
3174 if ((p = geticmpcodebyname($1-1, $3, AF_INET6)) == NULL) {
3175 yyerror("unknown icmp6-code %s", $3);
3176 free($3);
3177 YYERROR;
3178 }
3179 free($3);
3180
3181 $$ = calloc(1, sizeof(struct node_icmp));
3182 if ($$ == NULL)
3183 err(1, "icmp_item: calloc");
3184 $$->type = $1;
3185 $$->code = p->code + 1;
3186 $$->proto = IPPROTO_ICMPV6;
3187 $$->next = NULL;
3188 $$->tail = $$;
3189 }
3190 | icmp6type CODE NUMBER {
3191 if ($3 < 0 || $3 > 255) {
3192 yyerror("illegal icmp-code %lld", $3);
3193 YYERROR;
3194 }
3195 $$ = calloc(1, sizeof(struct node_icmp));
3196 if ($$ == NULL)
3197 err(1, "icmp_item: calloc");
3198 $$->type = $1;
3199 $$->code = $3 + 1;
3200 $$->proto = IPPROTO_ICMPV6;
3201 $$->next = NULL;
3202 $$->tail = $$;
3203 }
3204 ;
3205
3206 icmptype : STRING {
3207 const struct icmptypeent *p;
3208
3209 if ((p = geticmptypebyname($1, AF_INET)) == NULL) {
3210 yyerror("unknown icmp-type %s", $1);
3211 free($1);
3212 YYERROR;
3213 }
3214 $$ = p->type + 1;
3215 free($1);
3216 }
3217 | NUMBER {
3218 if ($1 < 0 || $1 > 255) {
3219 yyerror("illegal icmp-type %lld", $1);
3220 YYERROR;
3221 }
3222 $$ = $1 + 1;
3223 }
3224 ;
3225
3226 icmp6type : STRING {
3227 const struct icmptypeent *p;
3228
3229 if ((p = geticmptypebyname($1, AF_INET6)) ==
3230 NULL) {
3231 yyerror("unknown icmp6-type %s", $1);
3232 free($1);
3233 YYERROR;
3234 }
3235 $$ = p->type + 1;
3236 free($1);
3237 }
3238 | NUMBER {
3239 if ($1 < 0 || $1 > 255) {
3240 yyerror("illegal icmp6-type %lld", $1);
3241 YYERROR;
3242 }
3243 $$ = $1 + 1;
3244 }
3245 ;
3246
3247 tos : STRING {
3248 int val;
3249 char *end;
3250
3251 if (map_tos($1, &val))
3252 $$ = val;
3253 else if ($1[0] == '0' && $1[1] == 'x') {
3254 errno = 0;
3255 $$ = strtoul($1, &end, 16);
3256 if (errno || *end != '\0')
3257 $$ = 256;
3258 } else
3259 $$ = 256; /* flag bad argument */
3260 if ($$ < 0 || $$ > 255) {
3261 yyerror("illegal tos value %s", $1);
3262 free($1);
3263 YYERROR;
3264 }
3265 free($1);
3266 }
3267 | NUMBER {
3268 $$ = $1;
3269 if ($$ < 0 || $$ > 255) {
3270 yyerror("illegal tos value %lld", $1);
3271 YYERROR;
3272 }
3273 }
3274 ;
3275
3276 sourcetrack : /* empty */ { $$ = PF_SRCTRACK; }
3277 | GLOBAL { $$ = PF_SRCTRACK_GLOBAL; }
3278 | RULE { $$ = PF_SRCTRACK_RULE; }
3279 ;
3280
3281 statelock : IFBOUND {
3282 $$ = PFRULE_IFBOUND;
3283 }
3284 | FLOATING {
3285 $$ = 0;
3286 }
3287 ;
3288
3289 keep : NO STATE {
3290 $$.action = 0;
3291 $$.options = NULL;
3292 }
3293 | KEEP STATE state_opt_spec {
3294 $$.action = PF_STATE_NORMAL;
3295 $$.options = $3;
3296 }
3297 | MODULATE STATE state_opt_spec {
3298 $$.action = PF_STATE_MODULATE;
3299 $$.options = $3;
3300 }
3301 | SYNPROXY STATE state_opt_spec {
3302 $$.action = PF_STATE_SYNPROXY;
3303 $$.options = $3;
3304 }
3305 ;
3306
3307 flush : /* empty */ { $$ = 0; }
3308 | FLUSH { $$ = PF_FLUSH; }
3309 | FLUSH GLOBAL {
3310 $$ = PF_FLUSH | PF_FLUSH_GLOBAL;
3311 }
3312 ;
3313
3314 state_opt_spec : '(' state_opt_list ')' { $$ = $2; }
3315 | /* empty */ { $$ = NULL; }
3316 ;
3317
3318 state_opt_list : state_opt_item { $$ = $1; }
3319 | state_opt_list comma state_opt_item {
3320 $1->tail->next = $3;
3321 $1->tail = $3;
3322 $$ = $1;
3323 }
3324 ;
3325
3326 state_opt_item : MAXIMUM NUMBER {
3327 if ($2 < 0 || $2 > UINT_MAX) {
3328 yyerror("only positive values permitted");
3329 YYERROR;
3330 }
3331 $$ = calloc(1, sizeof(struct node_state_opt));
3332 if ($$ == NULL)
3333 err(1, "state_opt_item: calloc");
3334 $$->type = PF_STATE_OPT_MAX;
3335 $$->data.max_states = $2;
3336 $$->next = NULL;
3337 $$->tail = $$;
3338 }
3339 | NOSYNC {
3340 $$ = calloc(1, sizeof(struct node_state_opt));
3341 if ($$ == NULL)
3342 err(1, "state_opt_item: calloc");
3343 $$->type = PF_STATE_OPT_NOSYNC;
3344 $$->next = NULL;
3345 $$->tail = $$;
3346 }
3347 | MAXSRCSTATES NUMBER {
3348 if ($2 < 0 || $2 > UINT_MAX) {
3349 yyerror("only positive values permitted");
3350 YYERROR;
3351 }
3352 $$ = calloc(1, sizeof(struct node_state_opt));
3353 if ($$ == NULL)
3354 err(1, "state_opt_item: calloc");
3355 $$->type = PF_STATE_OPT_MAX_SRC_STATES;
3356 $$->data.max_src_states = $2;
3357 $$->next = NULL;
3358 $$->tail = $$;
3359 }
3360 | MAXSRCCONN NUMBER {
3361 if ($2 < 0 || $2 > UINT_MAX) {
3362 yyerror("only positive values permitted");
3363 YYERROR;
3364 }
3365 $$ = calloc(1, sizeof(struct node_state_opt));
3366 if ($$ == NULL)
3367 err(1, "state_opt_item: calloc");
3368 $$->type = PF_STATE_OPT_MAX_SRC_CONN;
3369 $$->data.max_src_conn = $2;
3370 $$->next = NULL;
3371 $$->tail = $$;
3372 }
3373 | MAXSRCCONNRATE NUMBER '/' NUMBER {
3374 if ($2 < 0 || $2 > UINT_MAX ||
3375 $4 < 0 || $4 > UINT_MAX) {
3376 yyerror("only positive values permitted");
3377 YYERROR;
3378 }
3379 $$ = calloc(1, sizeof(struct node_state_opt));
3380 if ($$ == NULL)
3381 err(1, "state_opt_item: calloc");
3382 $$->type = PF_STATE_OPT_MAX_SRC_CONN_RATE;
3383 $$->data.max_src_conn_rate.limit = $2;
3384 $$->data.max_src_conn_rate.seconds = $4;
3385 $$->next = NULL;
3386 $$->tail = $$;
3387 }
3388 | OVERLOAD '<' STRING '>' flush {
3389 if (strlen($3) >= PF_TABLE_NAME_SIZE) {
3390 yyerror("table name '%s' too long", $3);
3391 free($3);
3392 YYERROR;
3393 }
3394 $$ = calloc(1, sizeof(struct node_state_opt));
3395 if ($$ == NULL)
3396 err(1, "state_opt_item: calloc");
3397 if (strlcpy($$->data.overload.tblname, $3,
3398 PF_TABLE_NAME_SIZE) >= PF_TABLE_NAME_SIZE)
3399 errx(1, "state_opt_item: strlcpy");
3400 free($3);
3401 $$->type = PF_STATE_OPT_OVERLOAD;
3402 $$->data.overload.flush = $5;
3403 $$->next = NULL;
3404 $$->tail = $$;
3405 }
3406 | MAXSRCNODES NUMBER {
3407 if ($2 < 0 || $2 > UINT_MAX) {
3408 yyerror("only positive values permitted");
3409 YYERROR;
3410 }
3411 $$ = calloc(1, sizeof(struct node_state_opt));
3412 if ($$ == NULL)
3413 err(1, "state_opt_item: calloc");
3414 $$->type = PF_STATE_OPT_MAX_SRC_NODES;
3415 $$->data.max_src_nodes = $2;
3416 $$->next = NULL;
3417 $$->tail = $$;
3418 }
3419 | SOURCETRACK sourcetrack {
3420 $$ = calloc(1, sizeof(struct node_state_opt));
3421 if ($$ == NULL)
3422 err(1, "state_opt_item: calloc");
3423 $$->type = PF_STATE_OPT_SRCTRACK;
3424 $$->data.src_track = $2;
3425 $$->next = NULL;
3426 $$->tail = $$;
3427 }
3428 | statelock {
3429 $$ = calloc(1, sizeof(struct node_state_opt));
3430 if ($$ == NULL)
3431 err(1, "state_opt_item: calloc");
3432 $$->type = PF_STATE_OPT_STATELOCK;
3433 $$->data.statelock = $1;
3434 $$->next = NULL;
3435 $$->tail = $$;
3436 }
3437 | SLOPPY {
3438 $$ = calloc(1, sizeof(struct node_state_opt));
3439 if ($$ == NULL)
3440 err(1, "state_opt_item: calloc");
3441 $$->type = PF_STATE_OPT_SLOPPY;
3442 $$->next = NULL;
3443 $$->tail = $$;
3444 }
3445 | PFLOW {
3446 $$ = calloc(1, sizeof(struct node_state_opt));
3447 if ($$ == NULL)
3448 err(1, "state_opt_item: calloc");
3449 $$->type = PF_STATE_OPT_PFLOW;
3450 $$->next = NULL;
3451 $$->tail = $$;
3452 }
3453 | STRING NUMBER {
3454 int i;
3455
3456 if ($2 < 0 || $2 > UINT_MAX) {
3457 yyerror("only positive values permitted");
3458 YYERROR;
3459 }
3460 for (i = 0; pf_timeouts[i].name &&
3461 strcmp(pf_timeouts[i].name, $1); ++i)
3462 ; /* nothing */
3463 if (!pf_timeouts[i].name) {
3464 yyerror("illegal timeout name %s", $1);
3465 free($1);
3466 YYERROR;
3467 }
3468 if (strchr(pf_timeouts[i].name, '.') == NULL) {
3469 yyerror("illegal state timeout %s", $1);
3470 free($1);
3471 YYERROR;
3472 }
3473 free($1);
3474 $$ = calloc(1, sizeof(struct node_state_opt));
3475 if ($$ == NULL)
3476 err(1, "state_opt_item: calloc");
3477 $$->type = PF_STATE_OPT_TIMEOUT;
3478 $$->data.timeout.number = pf_timeouts[i].timeout;
3479 $$->data.timeout.seconds = $2;
3480 $$->next = NULL;
3481 $$->tail = $$;
3482 }
3483 ;
3484
3485 label : STRING {
3486 $$ = $1;
3487 }
3488 ;
3489
3490 qname : STRING {
3491 struct pfctl_qsitem *qsi;
3492
3493 if ((qsi = pfctl_find_queue($1, &qspecs)) == NULL) {
3494 yyerror("queue %s is not defined", $1);
3495 YYERROR;
3496 }
3497 $$.qname = $1;
3498 $$.pqname = NULL;
3499 }
3500 | '(' STRING ')' {
3501 struct pfctl_qsitem *qsi;
3502
3503 if ((qsi = pfctl_find_queue($2, &qspecs)) == NULL) {
3504 yyerror("queue %s is not defined", $2);
3505 YYERROR;
3506 }
3507 $$.qname = $2;
3508 $$.pqname = NULL;
3509 }
3510 | '(' STRING comma STRING ')' {
3511 struct pfctl_qsitem *qsi, *pqsi;
3512
3513 if ((qsi = pfctl_find_queue($2, &qspecs)) == NULL) {
3514 yyerror("queue %s is not defined", $2);
3515 YYERROR;
3516 }
3517 if ((pqsi = pfctl_find_queue($4, &qspecs)) == NULL) {
3518 yyerror("queue %s is not defined", $4);
3519 YYERROR;
3520 }
3521 $$.qname = $2;
3522 $$.pqname = $4;
3523 }
3524 ;
3525
3526 portstar : numberstring {
3527 if (parseport($1, &$$, PPORT_RANGE|PPORT_STAR) == -1) {
3528 free($1);
3529 YYERROR;
3530 }
3531 free($1);
3532 }
3533 ;
3534
3535 redirspec : host optweight {
3536 if ($2 > 0) {
3537 struct node_host *n;
3538 for (n = $1; n != NULL; n = n->next)
3539 n->weight = $2;
3540 }
3541 $$ = $1;
3542 }
3543 | '{' optnl redir_host_list '}' { $$ = $3; }
3544 ;
3545
3546 redir_host_list : host optweight optnl {
3547 if ($1->addr.type != PF_ADDR_ADDRMASK) {
3548 free($1);
3549 yyerror("only addresses can be listed for "
3550 "redirection pools ");
3551 YYERROR;
3552 }
3553 if ($2 > 0) {
3554 struct node_host *n;
3555 for (n = $1; n != NULL; n = n->next)
3556 n->weight = $2;
3557 }
3558 $$ = $1;
3559 }
3560 | redir_host_list comma host optweight optnl {
3561 $1->tail->next = $3;
3562 $1->tail = $3->tail;
3563 if ($4 > 0) {
3564 struct node_host *n;
3565 for (n = $3; n != NULL; n = n->next)
3566 n->weight = $4;
3567 }
3568 $$ = $1;
3569 }
3570 ;
3571
3572 redirpool : redirspec {
3573 $$ = calloc(1, sizeof(struct redirection));
3574 if ($$ == NULL)
3575 err(1, "redirection: calloc");
3576 $$->host = $1;
3577 $$->rport.a = $$->rport.b = $$->rport.t = 0;
3578 }
3579 | redirspec PORT portstar {
3580 $$ = calloc(1, sizeof(struct redirection));
3581 if ($$ == NULL)
3582 err(1, "redirection: calloc");
3583 $$->host = $1;
3584 $$->rport = $3;
3585 }
3586 ;
3587
3588 hashkey : /* empty */
3589 {
3590 $$ = calloc(1, sizeof(struct pf_poolhashkey));
3591 if ($$ == NULL)
3592 err(1, "hashkey: calloc");
3593 $$->key32[0] = arc4random();
3594 $$->key32[1] = arc4random();
3595 $$->key32[2] = arc4random();
3596 $$->key32[3] = arc4random();
3597 }
3598 | string
3599 {
3600 if (!strncmp($1, "0x", 2)) {
3601 if (strlen($1) != 34) {
3602 free($1);
3603 yyerror("hex key must be 128 bits "
3604 "(32 hex digits) long");
3605 YYERROR;
3606 }
3607 $$ = calloc(1, sizeof(struct pf_poolhashkey));
3608 if ($$ == NULL)
3609 err(1, "hashkey: calloc");
3610
3611 if (sscanf($1, "0x%8x%8x%8x%8x",
3612 &$$->key32[0], &$$->key32[1],
3613 &$$->key32[2], &$$->key32[3]) != 4) {
3614 free($$);
3615 free($1);
3616 yyerror("invalid hex key");
3617 YYERROR;
3618 }
3619 } else {
3620 MD5_CTX context;
3621
3622 $$ = calloc(1, sizeof(struct pf_poolhashkey));
3623 if ($$ == NULL)
3624 err(1, "hashkey: calloc");
3625 MD5Init(&context);
3626 MD5Update(&context, (unsigned char *)$1,
3627 strlen($1));
3628 MD5Final((unsigned char *)$$, &context);
3629 HTONL($$->key32[0]);
3630 HTONL($$->key32[1]);
3631 HTONL($$->key32[2]);
3632 HTONL($$->key32[3]);
3633 }
3634 free($1);
3635 }
3636 ;
3637
3638 pool_opts : { bzero(&pool_opts, sizeof pool_opts); }
3639 pool_opts_l
3640 { $$ = pool_opts; }
3641 | /* empty */ {
3642 bzero(&pool_opts, sizeof pool_opts);
3643 $$ = pool_opts;
3644 }
3645 ;
3646
3647 pool_opts_l : pool_opts_l pool_opt
3648 | pool_opt
3649 ;
3650
3651 pool_opt : BITMASK {
3652 if (pool_opts.type) {
3653 yyerror("pool type cannot be redefined");
3654 YYERROR;
3655 }
3656 pool_opts.type = PF_POOL_BITMASK;
3657 }
3658 | RANDOM {
3659 if (pool_opts.type) {
3660 yyerror("pool type cannot be redefined");
3661 YYERROR;
3662 }
3663 pool_opts.type = PF_POOL_RANDOM;
3664 }
3665 | SOURCEHASH hashkey {
3666 if (pool_opts.type) {
3667 yyerror("pool type cannot be redefined");
3668 YYERROR;
3669 }
3670 pool_opts.type = PF_POOL_SRCHASH;
3671 pool_opts.key = $2;
3672 }
3673 | ROUNDROBIN {
3674 if (pool_opts.type) {
3675 yyerror("pool type cannot be redefined");
3676 YYERROR;
3677 }
3678 pool_opts.type = PF_POOL_ROUNDROBIN;
3679 }
3680 | LEASTSTATES {
3681 if (pool_opts.type) {
3682 yyerror("pool type cannot be redefined");
3683 YYERROR;
3684 }
3685 pool_opts.type = PF_POOL_LEASTSTATES;
3686 }
3687 | STATICPORT {
3688 if (pool_opts.staticport) {
3689 yyerror("static-port cannot be redefined");
3690 YYERROR;
3691 }
3692 pool_opts.staticport = 1;
3693 }
3694 | STICKYADDRESS {
3695 if (pool_opts.marker & POM_STICKYADDRESS) {
3696 yyerror("sticky-address cannot be redefined");
3697 YYERROR;
3698 }
3699 pool_opts.marker |= POM_STICKYADDRESS;
3700 pool_opts.opts |= PF_POOL_STICKYADDR;
3701 }
3702 ;
3703
3704 routespec : redirspec pool_opts {
3705 struct redirection *redir;
3706 if (filter_opts.rt != PF_NOPFROUTE) {
3707 yyerror("cannot respecify "
3708 "route-to/reply-to/dup-to");
3709 YYERROR;
3710 }
3711 redir = calloc(1, sizeof(*redir));
3712 if (redir == NULL)
3713 err(1, "routespec calloc");
3714 redir->host = $1;
3715 filter_opts.rroute.rdr = redir;
3716 memcpy(&filter_opts.rroute.pool_opts, &$2,
3717 sizeof(filter_opts.rroute.pool_opts));
3718 }
3719 ;
3720
3721 timeout_spec : STRING NUMBER
3722 {
3723 if ($2 < 0 || $2 > UINT_MAX) {
3724 yyerror("only positive values permitted");
3725 YYERROR;
3726 }
3727 if (pfctl_set_timeout(pf, $1, $2, 0) != 0) {
3728 yyerror("unknown timeout %s", $1);
3729 free($1);
3730 YYERROR;
3731 }
3732 free($1);
3733 }
3734 ;
3735
3736 timeout_list : timeout_list comma timeout_spec optnl
3737 | timeout_spec optnl
3738 ;
3739
3740 limit_spec : STRING NUMBER
3741 {
3742 if ($2 < 0 || $2 > UINT_MAX) {
3743 yyerror("only positive values permitted");
3744 YYERROR;
3745 }
3746 if (pfctl_set_limit(pf, $1, $2) != 0) {
3747 yyerror("unable to set limit %s %lld", $1, $2);
3748 free($1);
3749 YYERROR;
3750 }
3751 free($1);
3752 }
3753 ;
3754
3755 limit_list : limit_list comma limit_spec optnl
3756 | limit_spec optnl
3757 ;
3758
3759 comma : ','
3760 | /* empty */
3761 ;
3762
3763 yesno : NO { $$ = 0; }
3764 | STRING {
3765 if (!strcmp($1, "yes"))
3766 $$ = 1;
3767 else {
3768 yyerror("invalid value '%s', expected 'yes' "
3769 "or 'no'", $1);
3770 free($1);
3771 YYERROR;
3772 }
3773 free($1);
3774 }
3775 ;
3776
3777 unaryop : '=' { $$ = PF_OP_EQ; }
3778 | NE { $$ = PF_OP_NE; }
3779 | LE { $$ = PF_OP_LE; }
3780 | '<' { $$ = PF_OP_LT; }
3781 | GE { $$ = PF_OP_GE; }
3782 | '>' { $$ = PF_OP_GT; }
3783 ;
3784
3785 %%
3786
3787 int
3788 yyerror(const char *fmt, ...)
3789 {
3790 va_list ap;
3791
3792 file->errors++;
3793 va_start(ap, fmt);
3794 fprintf(stderr, "%s:%d: ", file->name, yylval.lineno);
3795 vfprintf(stderr, fmt, ap);
3796 fprintf(stderr, "\n");
3797 va_end(ap);
3798 return (0);
3799 }
3800
3801 int
validate_range(u_int8_t op,u_int16_t p1,u_int16_t p2)3802 validate_range(u_int8_t op, u_int16_t p1, u_int16_t p2)
3803 {
3804 u_int16_t a = ntohs(p1);
3805 u_int16_t b = ntohs(p2);
3806
3807 if ((op == PF_OP_RRG && a > b) || /* 34:12, i.e. none */
3808 (op == PF_OP_IRG && a >= b) || /* 34><12, i.e. none */
3809 (op == PF_OP_XRG && a > b)) /* 34<>22, i.e. all */
3810 return 1;
3811 return 0;
3812 }
3813
3814 int
disallow_table(struct node_host * h,const char * fmt)3815 disallow_table(struct node_host *h, const char *fmt)
3816 {
3817 for (; h != NULL; h = h->next)
3818 if (h->addr.type == PF_ADDR_TABLE) {
3819 yyerror(fmt, h->addr.v.tblname);
3820 return (1);
3821 }
3822 return (0);
3823 }
3824
3825 int
disallow_urpf_failed(struct node_host * h,const char * fmt)3826 disallow_urpf_failed(struct node_host *h, const char *fmt)
3827 {
3828 for (; h != NULL; h = h->next)
3829 if (h->addr.type == PF_ADDR_URPFFAILED) {
3830 yyerror("%s", fmt);
3831 return (1);
3832 }
3833 return (0);
3834 }
3835
3836 int
disallow_alias(struct node_host * h,const char * fmt)3837 disallow_alias(struct node_host *h, const char *fmt)
3838 {
3839 for (; h != NULL; h = h->next)
3840 if (DYNIF_MULTIADDR(h->addr)) {
3841 yyerror(fmt, h->addr.v.tblname);
3842 return (1);
3843 }
3844 return (0);
3845 }
3846
3847 int
rule_consistent(struct pf_rule * r)3848 rule_consistent(struct pf_rule *r)
3849 {
3850 int problems = 0;
3851
3852 if (r->proto != IPPROTO_TCP && r->os_fingerprint != PF_OSFP_ANY) {
3853 yyerror("os only applies to tcp");
3854 problems++;
3855 }
3856 if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP &&
3857 (r->src.port_op || r->dst.port_op)) {
3858 yyerror("port only applies to tcp/udp");
3859 problems++;
3860 }
3861 if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP &&
3862 r->uid.op) {
3863 yyerror("user only applies to tcp/udp");
3864 problems++;
3865 }
3866 if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP &&
3867 r->gid.op) {
3868 yyerror("group only applies to tcp/udp");
3869 problems++;
3870 }
3871 if (r->proto != IPPROTO_ICMP && r->proto != IPPROTO_ICMPV6 &&
3872 (r->type || r->code)) {
3873 yyerror("icmp-type/code only applies to icmp");
3874 problems++;
3875 }
3876 if (!r->af && (r->type || r->code)) {
3877 yyerror("must indicate address family with icmp-type/code");
3878 problems++;
3879 }
3880 if (r->rule_flag & PFRULE_AFTO && r->af == r->naf) {
3881 yyerror("must indicate different address family with af-to");
3882 problems++;
3883 }
3884 if (r->overload_tblname[0] &&
3885 r->max_src_conn == 0 && r->max_src_conn_rate.seconds == 0) {
3886 yyerror("'overload' requires 'max-src-conn' "
3887 "or 'max-src-conn-rate'");
3888 problems++;
3889 }
3890 if ((r->proto == IPPROTO_ICMP && r->af == AF_INET6) ||
3891 (r->proto == IPPROTO_ICMPV6 && r->af == AF_INET)) {
3892 yyerror("proto %s doesn't match address family %s",
3893 r->proto == IPPROTO_ICMP ? "icmp" : "icmp6",
3894 r->af == AF_INET ? "inet" : "inet6");
3895 problems++;
3896 }
3897 if (r->allow_opts && r->action != PF_PASS) {
3898 yyerror("allow-opts can only be specified for pass rules");
3899 problems++;
3900 }
3901 if (r->rule_flag & PFRULE_FRAGMENT && (r->src.port_op ||
3902 r->dst.port_op || r->flagset || r->type || r->code)) {
3903 yyerror("fragments can be filtered only on IP header fields");
3904 problems++;
3905 }
3906 if (r->rule_flag & PFRULE_RETURNRST && r->proto != IPPROTO_TCP) {
3907 yyerror("return-rst can only be applied to TCP rules");
3908 problems++;
3909 }
3910 if (r->max_src_nodes && !(r->rule_flag & PFRULE_RULESRCTRACK)) {
3911 yyerror("max-src-nodes requires 'source-track rule'");
3912 problems++;
3913 }
3914 if (r->action != PF_PASS && r->keep_state) {
3915 yyerror("keep state is great, but only for pass rules");
3916 problems++;
3917 }
3918 if (r->rt && !r->keep_state) {
3919 yyerror("route-to, reply-to and dup-to require keep state");
3920 problems++;
3921 }
3922 if (r->rule_flag & PFRULE_STATESLOPPY &&
3923 (r->keep_state == PF_STATE_MODULATE ||
3924 r->keep_state == PF_STATE_SYNPROXY)) {
3925 yyerror("sloppy state matching cannot be used with "
3926 "synproxy state or modulate state");
3927 problems++;
3928 }
3929
3930 if ((r->keep_state == PF_STATE_SYNPROXY) && (r->direction != PF_IN))
3931 fprintf(stderr, "%s:%d: warning: "
3932 "synproxy used for inbound rules only, "
3933 "ignored for outbound\n", file->name, yylval.lineno);
3934
3935 if ((r->nat.addr.type != PF_ADDR_NONE ||
3936 r->rdr.addr.type != PF_ADDR_NONE) &&
3937 r->action != PF_MATCH && !r->keep_state) {
3938 yyerror("nat-to and rdr-to require keep state");
3939 problems++;
3940 }
3941 if (r->direction == PF_INOUT && (r->nat.addr.type != PF_ADDR_NONE ||
3942 r->rdr.addr.type != PF_ADDR_NONE)) {
3943 yyerror("nat-to and rdr-to require a direction");
3944 problems++;
3945 }
3946 if (r->af == AF_INET6 && (r->scrub_flags &
3947 (PFSTATE_NODF|PFSTATE_RANDOMID))) {
3948 yyerror("address family inet6 does not support scrub options "
3949 "no-df, random-id");
3950 problems++;
3951 }
3952
3953 /* Basic rule sanity check. */
3954 switch (r->action) {
3955 case PF_MATCH:
3956 if (r->divert.type != PF_DIVERT_NONE) {
3957 yyerror("divert is not supported on match rules");
3958 problems++;
3959 }
3960 if (r->rt) {
3961 yyerror("route-to, reply-to and dup-to "
3962 "are not supported on match rules");
3963 problems++;
3964 }
3965 if (r->rule_flag & PFRULE_AFTO) {
3966 yyerror("af-to is not supported on match rules");
3967 problems++;
3968 }
3969 break;
3970 case PF_DROP:
3971 if (r->rt) {
3972 yyerror("route-to, reply-to and dup-to "
3973 "are not supported on block rules");
3974 problems++;
3975 }
3976 break;
3977 default:;
3978 }
3979 return (-problems);
3980 }
3981
3982 int
process_tabledef(char * name,struct table_opts * opts,int popts)3983 process_tabledef(char *name, struct table_opts *opts, int popts)
3984 {
3985 struct pfr_buffer ab;
3986 struct node_tinit *ti;
3987 struct pfr_uktable *ukt;
3988
3989 bzero(&ab, sizeof(ab));
3990 ab.pfrb_type = PFRB_ADDRS;
3991 SIMPLEQ_FOREACH(ti, &opts->init_nodes, entries) {
3992 if (ti->file)
3993 if (pfr_buf_load(&ab, ti->file, 0, popts)) {
3994 if (errno)
3995 yyerror("cannot load \"%s\": %s",
3996 ti->file, strerror(errno));
3997 else
3998 yyerror("file \"%s\" contains bad data",
3999 ti->file);
4000 goto _error;
4001 }
4002 if (ti->host)
4003 if (append_addr_host(&ab, ti->host, 0, 0)) {
4004 yyerror("cannot create address buffer: %s",
4005 strerror(errno));
4006 goto _error;
4007 }
4008 }
4009 if (pf->opts & PF_OPT_VERBOSE)
4010 print_tabledef(name, opts->flags, opts->init_addr,
4011 &opts->init_nodes);
4012 if (!(pf->opts & PF_OPT_NOACTION) ||
4013 (pf->opts & PF_OPT_DUMMYACTION))
4014 warn_duplicate_tables(name, pf->anchor->path);
4015 else if (pf->opts & PF_OPT_VERBOSE)
4016 fprintf(stderr, "%s:%d: skipping duplicate table checks"
4017 " for <%s>\n", file->name, yylval.lineno, name);
4018
4019 /*
4020 * postpone definition of non-root tables to moment
4021 * when path is fully resolved.
4022 */
4023 if (pf->asd > 0) {
4024 ukt = calloc(1, sizeof(struct pfr_uktable));
4025 if (ukt == NULL) {
4026 DBGPRINT(
4027 "%s:%d: not enough memory for <%s>\n", file->name,
4028 yylval.lineno, name);
4029 goto _error;
4030 }
4031 } else
4032 ukt = NULL;
4033
4034 if (!(pf->opts & PF_OPT_NOACTION) &&
4035 pfctl_define_table(name, opts->flags, opts->init_addr,
4036 pf->anchor->path, &ab, pf->anchor->ruleset.tticket, ukt)) {
4037 yyerror("cannot define table %s: %s", name,
4038 pf_strerror(errno));
4039 goto _error;
4040 }
4041
4042 if (ukt != NULL) {
4043 ukt->pfrukt_init_addr = opts->init_addr;
4044 if (RB_INSERT(pfr_ktablehead, &pfr_ktables,
4045 &ukt->pfrukt_kt) != NULL) {
4046 /*
4047 * I think this should not happen, because
4048 * pfctl_define_table() above does the same check
4049 * effectively.
4050 */
4051 DBGPRINT(
4052 "%s:%d table %s already exists in %s\n",
4053 file->name, yylval.lineno,
4054 ukt->pfrukt_name, pf->anchor->path);
4055 free(ukt);
4056 goto _error;
4057 }
4058 DBGPRINT("%s %s@%s inserted to tree\n",
4059 __func__, ukt->pfrukt_name, pf->anchor->path);
4060
4061 } else
4062 DBGPRINT("%s ukt is null\n", __func__);
4063
4064 pf->tdirty = 1;
4065 pfr_buf_clear(&ab);
4066 return (0);
4067 _error:
4068 pfr_buf_clear(&ab);
4069 return (-1);
4070 }
4071
4072 struct keywords {
4073 const char *k_name;
4074 int k_val;
4075 };
4076
4077 /* macro gore, but you should've seen the prior indentation nightmare... */
4078
4079 #define FREE_LIST(T,r) \
4080 do { \
4081 T *p, *node = r; \
4082 while (node != NULL) { \
4083 p = node; \
4084 node = node->next; \
4085 free(p); \
4086 } \
4087 } while (0)
4088
4089 #define LOOP_THROUGH(T,n,r,C) \
4090 do { \
4091 T *n; \
4092 if (r == NULL) { \
4093 r = calloc(1, sizeof(T)); \
4094 if (r == NULL) \
4095 err(1, "LOOP: calloc"); \
4096 r->next = NULL; \
4097 } \
4098 n = r; \
4099 while (n != NULL) { \
4100 do { \
4101 C; \
4102 } while (0); \
4103 n = n->next; \
4104 } \
4105 } while (0)
4106
4107 void
expand_label_str(char * label,size_t len,const char * srch,const char * repl)4108 expand_label_str(char *label, size_t len, const char *srch, const char *repl)
4109 {
4110 char *tmp;
4111 char *p, *q;
4112
4113 if ((tmp = calloc(1, len)) == NULL)
4114 err(1, "%s", __func__);
4115 p = q = label;
4116 while ((q = strstr(p, srch)) != NULL) {
4117 *q = '\0';
4118 if ((strlcat(tmp, p, len) >= len) ||
4119 (strlcat(tmp, repl, len) >= len))
4120 errx(1, "expand_label: label too long");
4121 q += strlen(srch);
4122 p = q;
4123 }
4124 if (strlcat(tmp, p, len) >= len)
4125 errx(1, "expand_label: label too long");
4126 strlcpy(label, tmp, len); /* always fits */
4127 free(tmp);
4128 }
4129
4130 void
expand_label_if(const char * name,char * label,size_t len,const char * ifname)4131 expand_label_if(const char *name, char *label, size_t len, const char *ifname)
4132 {
4133 if (strstr(label, name) != NULL) {
4134 if (!*ifname)
4135 expand_label_str(label, len, name, "any");
4136 else
4137 expand_label_str(label, len, name, ifname);
4138 }
4139 }
4140
4141 void
expand_label_addr(const char * name,char * label,size_t len,sa_family_t af,struct node_host * h)4142 expand_label_addr(const char *name, char *label, size_t len, sa_family_t af,
4143 struct node_host *h)
4144 {
4145 char tmp[64], tmp_not[66];
4146
4147 if (strstr(label, name) != NULL) {
4148 switch (h->addr.type) {
4149 case PF_ADDR_DYNIFTL:
4150 snprintf(tmp, sizeof(tmp), "(%s)", h->addr.v.ifname);
4151 break;
4152 case PF_ADDR_TABLE:
4153 snprintf(tmp, sizeof(tmp), "<%s>", h->addr.v.tblname);
4154 break;
4155 case PF_ADDR_NOROUTE:
4156 snprintf(tmp, sizeof(tmp), "no-route");
4157 break;
4158 case PF_ADDR_URPFFAILED:
4159 snprintf(tmp, sizeof(tmp), "urpf-failed");
4160 break;
4161 case PF_ADDR_ADDRMASK:
4162 if (!af || (PF_AZERO(&h->addr.v.a.addr, af) &&
4163 PF_AZERO(&h->addr.v.a.mask, af)))
4164 snprintf(tmp, sizeof(tmp), "any");
4165 else {
4166 char a[48];
4167 int bits;
4168
4169 if (inet_ntop(af, &h->addr.v.a.addr, a,
4170 sizeof(a)) == NULL)
4171 snprintf(tmp, sizeof(tmp), "?");
4172 else {
4173 bits = unmask(&h->addr.v.a.mask);
4174 if ((af == AF_INET && bits < 32) ||
4175 (af == AF_INET6 && bits < 128))
4176 snprintf(tmp, sizeof(tmp),
4177 "%s/%d", a, bits);
4178 else
4179 snprintf(tmp, sizeof(tmp),
4180 "%s", a);
4181 }
4182 }
4183 break;
4184 default:
4185 snprintf(tmp, sizeof(tmp), "?");
4186 break;
4187 }
4188
4189 if (h->not) {
4190 snprintf(tmp_not, sizeof(tmp_not), "! %s", tmp);
4191 expand_label_str(label, len, name, tmp_not);
4192 } else
4193 expand_label_str(label, len, name, tmp);
4194 }
4195 }
4196
4197 void
expand_label_port(const char * name,char * label,size_t len,struct node_port * port)4198 expand_label_port(const char *name, char *label, size_t len,
4199 struct node_port *port)
4200 {
4201 char a1[6], a2[6], op[13] = "";
4202
4203 if (strstr(label, name) != NULL) {
4204 snprintf(a1, sizeof(a1), "%u", ntohs(port->port[0]));
4205 snprintf(a2, sizeof(a2), "%u", ntohs(port->port[1]));
4206 if (!port->op)
4207 ;
4208 else if (port->op == PF_OP_IRG)
4209 snprintf(op, sizeof(op), "%s><%s", a1, a2);
4210 else if (port->op == PF_OP_XRG)
4211 snprintf(op, sizeof(op), "%s<>%s", a1, a2);
4212 else if (port->op == PF_OP_EQ)
4213 snprintf(op, sizeof(op), "%s", a1);
4214 else if (port->op == PF_OP_NE)
4215 snprintf(op, sizeof(op), "!=%s", a1);
4216 else if (port->op == PF_OP_LT)
4217 snprintf(op, sizeof(op), "<%s", a1);
4218 else if (port->op == PF_OP_LE)
4219 snprintf(op, sizeof(op), "<=%s", a1);
4220 else if (port->op == PF_OP_GT)
4221 snprintf(op, sizeof(op), ">%s", a1);
4222 else if (port->op == PF_OP_GE)
4223 snprintf(op, sizeof(op), ">=%s", a1);
4224 expand_label_str(label, len, name, op);
4225 }
4226 }
4227
4228 void
expand_label_proto(const char * name,char * label,size_t len,u_int8_t proto)4229 expand_label_proto(const char *name, char *label, size_t len, u_int8_t proto)
4230 {
4231 struct protoent *pe;
4232 char n[4];
4233
4234 if (strstr(label, name) != NULL) {
4235 pe = getprotobynumber(proto);
4236 if (pe != NULL)
4237 expand_label_str(label, len, name, pe->p_name);
4238 else {
4239 snprintf(n, sizeof(n), "%u", proto);
4240 expand_label_str(label, len, name, n);
4241 }
4242 }
4243 }
4244
4245 void
pfctl_expand_label_nr(struct pf_rule * r,unsigned int rno)4246 pfctl_expand_label_nr(struct pf_rule *r, unsigned int rno)
4247 {
4248 char n[11];
4249
4250 snprintf(n, sizeof(n), "%u", rno);
4251
4252 if (strstr(r->label, "$nr") != NULL)
4253 expand_label_str(r->label, PF_RULE_LABEL_SIZE, "$nr", n);
4254
4255 if (strstr(r->tagname, "$nr") != NULL)
4256 expand_label_str(r->tagname, PF_TAG_NAME_SIZE, "$nr", n);
4257
4258 if (strstr(r->match_tagname, "$nr") != NULL)
4259 expand_label_str(r->match_tagname, PF_TAG_NAME_SIZE, "$nr", n);
4260 }
4261
4262 void
expand_label(char * label,size_t len,const char * ifname,sa_family_t af,struct node_host * src_host,struct node_port * src_port,struct node_host * dst_host,struct node_port * dst_port,u_int8_t proto)4263 expand_label(char *label, size_t len, const char *ifname, sa_family_t af,
4264 struct node_host *src_host, struct node_port *src_port,
4265 struct node_host *dst_host, struct node_port *dst_port,
4266 u_int8_t proto)
4267 {
4268 expand_label_if("$if", label, len, ifname);
4269 expand_label_addr("$srcaddr", label, len, af, src_host);
4270 expand_label_addr("$dstaddr", label, len, af, dst_host);
4271 expand_label_port("$srcport", label, len, src_port);
4272 expand_label_port("$dstport", label, len, dst_port);
4273 expand_label_proto("$proto", label, len, proto);
4274 /* rule number, '$nr', gets expanded after optimizer */
4275 }
4276
4277 int
expand_queue(char * qname,struct node_if * interfaces,struct queue_opts * opts)4278 expand_queue(char *qname, struct node_if *interfaces, struct queue_opts *opts)
4279 {
4280 struct pf_queuespec qspec;
4281
4282 LOOP_THROUGH(struct node_if, interface, interfaces,
4283 bzero(&qspec, sizeof(qspec));
4284 if (!opts->parent && (opts->marker & QOM_BWSPEC))
4285 opts->flags |= PFQS_ROOTCLASS;
4286 if (!(opts->marker & QOM_BWSPEC) &&
4287 !(opts->marker & QOM_FLOWS)) {
4288 yyerror("no bandwidth or flow specification");
4289 return (1);
4290 }
4291 if (strlcpy(qspec.qname, qname, sizeof(qspec.qname)) >=
4292 sizeof(qspec.qname)) {
4293 yyerror("queuename too long");
4294 return (1);
4295 }
4296 if (opts->parent && strlcpy(qspec.parent, opts->parent,
4297 sizeof(qspec.parent)) >= sizeof(qspec.parent)) {
4298 yyerror("parent too long");
4299 return (1);
4300 }
4301 if (strlcpy(qspec.ifname, interface->ifname,
4302 sizeof(qspec.ifname)) >= sizeof(qspec.ifname)) {
4303 yyerror("interface too long");
4304 return (1);
4305 }
4306 qspec.realtime.m1.absolute = opts->realtime.m1.bw_absolute;
4307 qspec.realtime.m1.percent = opts->realtime.m1.bw_percent;
4308 qspec.realtime.m2.absolute = opts->realtime.m2.bw_absolute;
4309 qspec.realtime.m2.percent = opts->realtime.m2.bw_percent;
4310 qspec.realtime.d = opts->realtime.d;
4311
4312 qspec.linkshare.m1.absolute = opts->linkshare.m1.bw_absolute;
4313 qspec.linkshare.m1.percent = opts->linkshare.m1.bw_percent;
4314 qspec.linkshare.m2.absolute = opts->linkshare.m2.bw_absolute;
4315 qspec.linkshare.m2.percent = opts->linkshare.m2.bw_percent;
4316 qspec.linkshare.d = opts->linkshare.d;
4317
4318 qspec.upperlimit.m1.absolute = opts->upperlimit.m1.bw_absolute;
4319 qspec.upperlimit.m1.percent = opts->upperlimit.m1.bw_percent;
4320 qspec.upperlimit.m2.absolute = opts->upperlimit.m2.bw_absolute;
4321 qspec.upperlimit.m2.percent = opts->upperlimit.m2.bw_percent;
4322 qspec.upperlimit.d = opts->upperlimit.d;
4323
4324 qspec.flowqueue.flows = opts->flowqueue.flows;
4325 qspec.flowqueue.quantum = opts->flowqueue.quantum;
4326 qspec.flowqueue.interval = opts->flowqueue.interval;
4327 qspec.flowqueue.target = opts->flowqueue.target;
4328
4329 qspec.flags = opts->flags;
4330 qspec.qlimit = opts->qlimit;
4331
4332 if (pfctl_add_queue(pf, &qspec)) {
4333 yyerror("cannot add queue");
4334 return (1);
4335 }
4336 );
4337
4338 FREE_LIST(struct node_if, interfaces);
4339 return (0);
4340 }
4341
4342 int
expand_divertspec(struct pf_rule * r,struct divertspec * ds)4343 expand_divertspec(struct pf_rule *r, struct divertspec *ds)
4344 {
4345 struct node_host *n;
4346
4347 switch (ds->type) {
4348 case PF_DIVERT_NONE:
4349 return (0);
4350 case PF_DIVERT_TO:
4351 if (r->direction == PF_OUT) {
4352 yyerror("divert-to used with outgoing rule");
4353 return (1);
4354 }
4355 if (r->af) {
4356 for (n = ds->addr; n != NULL; n = n->next)
4357 if (n->af == r->af)
4358 break;
4359 if (n == NULL) {
4360 yyerror("divert-to address family mismatch");
4361 return (1);
4362 }
4363 r->divert.addr = n->addr.v.a.addr;
4364 } else {
4365 r->af = ds->addr->af;
4366 r->divert.addr = ds->addr->addr.v.a.addr;
4367 }
4368 r->divert.port = ds->port;
4369 r->divert.type = ds->type;
4370 return (0);
4371 case PF_DIVERT_REPLY:
4372 if (r->direction == PF_IN) {
4373 yyerror("divert-reply used with incoming rule");
4374 return (1);
4375 }
4376 r->divert.type = ds->type;
4377 return (0);
4378 case PF_DIVERT_PACKET:
4379 r->divert.port = ds->port;
4380 r->divert.type = ds->type;
4381 return (0);
4382 }
4383 return (1);
4384 }
4385
4386 int
collapse_redirspec(struct pf_pool * rpool,struct pf_rule * r,struct redirspec * rs,int routing)4387 collapse_redirspec(struct pf_pool *rpool, struct pf_rule *r,
4388 struct redirspec *rs, int routing)
4389 {
4390 struct pf_opt_tbl *tbl = NULL;
4391 struct node_host *h, *hprev = NULL;
4392 struct pf_rule_addr ra;
4393 int af = 0, naddr = 0;
4394
4395 if (!rs || !rs->rdr || rs->rdr->host == NULL) {
4396 rpool->addr.type = PF_ADDR_NONE;
4397 return (0);
4398 }
4399
4400 if (r->rule_flag & PFRULE_AFTO)
4401 r->naf = rs->af;
4402
4403 for (h = rs->rdr->host; h != NULL; h = h->next) {
4404 if (routing) {
4405 if (h->addr.type == PF_ADDR_DYNIFTL &&
4406 h->addr.iflags != PFI_AFLAG_PEER) {
4407 yyerror("route spec requires :peer with "
4408 "dynamic interface addresses");
4409 return (1);
4410 }
4411 }
4412
4413 /* set rule address family if redirect spec has one */
4414 if (rs->af && !r->af && !af) {
4415 /* swap address families for af-to */
4416 if (r->naf == AF_INET6)
4417 af = AF_INET;
4418 else if (r->naf == AF_INET)
4419 af = AF_INET6;
4420 else
4421 af = rs->af;
4422 }
4423 if (h->af && !r->naf) { /* nat-to/rdr-to case */
4424 /* skip if the rule af doesn't match redirect af */
4425 if (r->af && r->af != h->af)
4426 continue;
4427 /*
4428 * fail if the chosen af is not universal for
4429 * all addresses in the redirect address pool
4430 */
4431 if (!r->af && af && af != h->af) {
4432 yyerror("%s spec contains addresses with "
4433 "different address families",
4434 routing ? "routing" : "translation");
4435 return (1);
4436 }
4437 } else if (h->af) { /* af-to case */
4438 /*
4439 * fail if the redirect spec af is not universal
4440 * for all addresses in the redirect address pool
4441 */
4442 if (rs->af && rs->af != h->af) {
4443 yyerror("%s spec contains addresses that "
4444 "don't match target address family",
4445 routing ? "routing" : "translation");
4446 return (1);
4447 }
4448 }
4449 /* else if (!h->af):
4450 * we silently allow any not af-specific host specs,
4451 * e.g. (em0) and let the kernel deal with them
4452 */
4453
4454 /* if we haven't selected the rule af yet, now it's time */
4455 if (!r->af && !af)
4456 af = h->af;
4457
4458 if (naddr == 0) { /* the first host */
4459 rpool->addr = h->addr;
4460 if (h->ifname) {
4461 yyerror("@if not permitted for %s",
4462 routing ? "routing" : "translation");
4463 return (1);
4464 }
4465 if (h->ifname && strlcpy(rpool->ifname, h->ifname,
4466 sizeof(rpool->ifname)) >= sizeof(rpool->ifname))
4467 errx(1, "collapse_redirspec: strlcpy");
4468 hprev = h; /* in case we need to conver to a table */
4469 } else { /* multiple hosts */
4470 if (rs->pool_opts.type &&
4471 !PF_POOL_DYNTYPE(rs->pool_opts.type)) {
4472 yyerror("pool type is not valid for multiple "
4473 "translation or routing addresses");
4474 return (1);
4475 }
4476 if ((hprev && hprev->addr.type != PF_ADDR_ADDRMASK) &&
4477 (hprev && hprev->addr.type != PF_ADDR_NONE) &&
4478 h->addr.type != PF_ADDR_ADDRMASK &&
4479 h->addr.type != PF_ADDR_NONE) {
4480 yyerror("multiple tables or dynamic interfaces "
4481 "not supported for translation or routing");
4482 return (1);
4483 }
4484 if (h->ifname) {
4485 yyerror("@if not permitted for %s",
4486 routing ? "routing" : "translation");
4487 return (1);
4488 }
4489 if (hprev) {
4490 /*
4491 * undo some damage and convert the single
4492 * host pool to the table
4493 */
4494 memset(&ra, 0, sizeof(ra));
4495 memset(rpool->ifname, 0, sizeof(rpool->ifname));
4496 ra.addr = hprev->addr;
4497 ra.weight = hprev->weight;
4498 if (add_opt_table(pf, &tbl,
4499 hprev->af, &ra, hprev->ifname))
4500 return (1);
4501 hprev = NULL;
4502 }
4503 memset(&ra, 0, sizeof(ra));
4504 ra.addr = h->addr;
4505 ra.weight = h->weight;
4506 if (add_opt_table(pf, &tbl,
4507 h->af, &ra, h->ifname))
4508 return (1);
4509 }
4510 naddr++;
4511 }
4512 /* set rule af to the one chosen above */
4513 if (!r->af && af)
4514 r->af = af;
4515 if (!naddr) {
4516 yyerror("af mismatch in %s spec",
4517 routing ? "routing" : "translation");
4518 return (1);
4519 }
4520 if (tbl) {
4521 if ((pf->opts & PF_OPT_NOACTION) == 0 &&
4522 pf_opt_create_table(pf, tbl))
4523 return (1);
4524
4525 pf->tdirty = 1;
4526
4527 if (pf->opts & PF_OPT_VERBOSE)
4528 print_tabledef(tbl->pt_name,
4529 PFR_TFLAG_CONST | tbl->pt_flags,
4530 1, &tbl->pt_nodes);
4531
4532 memset(&rpool->addr, 0, sizeof(rpool->addr));
4533 rpool->addr.type = PF_ADDR_TABLE;
4534 strlcpy(rpool->addr.v.tblname, tbl->pt_name,
4535 sizeof(rpool->addr.v.tblname));
4536
4537 pfr_buf_clear(tbl->pt_buf);
4538 free(tbl->pt_buf);
4539 tbl->pt_buf = NULL;
4540 free(tbl);
4541 }
4542 return (0);
4543 }
4544
4545
4546 int
apply_redirspec(struct pf_pool * rpool,struct pf_rule * r,struct redirspec * rs,int isrdr,struct node_port * np)4547 apply_redirspec(struct pf_pool *rpool, struct pf_rule *r, struct redirspec *rs,
4548 int isrdr, struct node_port *np)
4549 {
4550 if (!rs || !rs->rdr)
4551 return (0);
4552
4553 rpool->proxy_port[0] = ntohs(rs->rdr->rport.a);
4554
4555 if (isrdr) {
4556 if (!rs->rdr->rport.b && rs->rdr->rport.t) {
4557 rpool->proxy_port[1] = ntohs(rs->rdr->rport.a) +
4558 (ntohs(np->port[1]) - ntohs(np->port[0]));
4559 } else {
4560 if (validate_range(rs->rdr->rport.t, rs->rdr->rport.a,
4561 rs->rdr->rport.b)) {
4562 yyerror("invalid rdr-to port range");
4563 return (1);
4564 }
4565
4566 rpool->port_op = rs->rdr->rport.t;
4567 rpool->proxy_port[1] = ntohs(rs->rdr->rport.b);
4568 }
4569 } else {
4570 rpool->proxy_port[1] = ntohs(rs->rdr->rport.b);
4571 if (!rpool->proxy_port[0] && !rpool->proxy_port[1]) {
4572 rpool->proxy_port[0] = PF_NAT_PROXY_PORT_LOW;
4573 rpool->proxy_port[1] = PF_NAT_PROXY_PORT_HIGH;
4574 } else if (!rpool->proxy_port[1])
4575 rpool->proxy_port[1] = rpool->proxy_port[0];
4576 }
4577
4578 rpool->opts = rs->pool_opts.type;
4579 if ((rpool->opts & PF_POOL_TYPEMASK) == PF_POOL_NONE &&
4580 (rpool->addr.type == PF_ADDR_TABLE ||
4581 DYNIF_MULTIADDR(rpool->addr)))
4582 rpool->opts |= PF_POOL_ROUNDROBIN;
4583
4584 if (!PF_POOL_DYNTYPE(rpool->opts) &&
4585 (disallow_table(rs->rdr->host,
4586 "tables are not supported by pool type") ||
4587 disallow_alias(rs->rdr->host,
4588 "interface (%s) is not supported by pool type")))
4589 return (1);
4590
4591 if (rs->pool_opts.key != NULL)
4592 memcpy(&rpool->key, rs->pool_opts.key,
4593 sizeof(struct pf_poolhashkey));
4594
4595 if (rs->pool_opts.opts)
4596 rpool->opts |= rs->pool_opts.opts;
4597
4598 if (rs->pool_opts.staticport) {
4599 if (isrdr) {
4600 yyerror("the 'static-port' option is only valid with "
4601 "nat rules");
4602 return (1);
4603 }
4604 if (rpool->proxy_port[0] != PF_NAT_PROXY_PORT_LOW &&
4605 rpool->proxy_port[1] != PF_NAT_PROXY_PORT_HIGH) {
4606 yyerror("the 'static-port' option can't be used when "
4607 "specifying a port range");
4608 return (1);
4609 }
4610 rpool->proxy_port[0] = 0;
4611 rpool->proxy_port[1] = 0;
4612 }
4613
4614 return (0);
4615 }
4616
4617
4618 void
expand_rule(struct pf_rule * r,int keeprule,struct node_if * interfaces,struct redirspec * nat,struct redirspec * rdr,struct redirspec * rroute,struct node_proto * protos,struct node_os * src_oses,struct node_host * src_hosts,struct node_port * src_ports,struct node_host * dst_hosts,struct node_port * dst_ports,struct node_uid * uids,struct node_gid * gids,struct node_if * rcv,struct node_icmp * icmp_types)4619 expand_rule(struct pf_rule *r, int keeprule, struct node_if *interfaces,
4620 struct redirspec *nat, struct redirspec *rdr, struct redirspec *rroute,
4621 struct node_proto *protos, struct node_os *src_oses,
4622 struct node_host *src_hosts, struct node_port *src_ports,
4623 struct node_host *dst_hosts, struct node_port *dst_ports,
4624 struct node_uid *uids, struct node_gid *gids, struct node_if *rcv,
4625 struct node_icmp *icmp_types)
4626 {
4627 sa_family_t af = r->af;
4628 int added = 0, error = 0;
4629 char ifname[IF_NAMESIZE];
4630 char label[PF_RULE_LABEL_SIZE];
4631 char tagname[PF_TAG_NAME_SIZE];
4632 char match_tagname[PF_TAG_NAME_SIZE];
4633 u_int8_t flags, flagset, keep_state;
4634 struct node_host *srch, *dsth, *osrch, *odsth;
4635 struct redirspec binat;
4636 struct pf_rule rb;
4637 int dir = r->direction;
4638
4639 if (strlcpy(label, r->label, sizeof(label)) >= sizeof(label))
4640 errx(1, "expand_rule: strlcpy");
4641 if (strlcpy(tagname, r->tagname, sizeof(tagname)) >= sizeof(tagname))
4642 errx(1, "expand_rule: strlcpy");
4643 if (strlcpy(match_tagname, r->match_tagname, sizeof(match_tagname)) >=
4644 sizeof(match_tagname))
4645 errx(1, "expand_rule: strlcpy");
4646 flags = r->flags;
4647 flagset = r->flagset;
4648 keep_state = r->keep_state;
4649
4650 r->src.addr.type = r->dst.addr.type = PF_ADDR_ADDRMASK;
4651
4652 LOOP_THROUGH(struct node_if, interface, interfaces,
4653 LOOP_THROUGH(struct node_proto, proto, protos,
4654 LOOP_THROUGH(struct node_icmp, icmp_type, icmp_types,
4655 LOOP_THROUGH(struct node_host, src_host, src_hosts,
4656 LOOP_THROUGH(struct node_host, dst_host, dst_hosts,
4657 LOOP_THROUGH(struct node_port, src_port, src_ports,
4658 LOOP_THROUGH(struct node_port, dst_port, dst_ports,
4659 LOOP_THROUGH(struct node_os, src_os, src_oses,
4660 LOOP_THROUGH(struct node_uid, uid, uids,
4661 LOOP_THROUGH(struct node_gid, gid, gids,
4662
4663 r->af = af;
4664
4665 error += collapse_redirspec(&r->rdr, r, rdr, 0);
4666 error += collapse_redirspec(&r->nat, r, nat, 0);
4667 error += collapse_redirspec(&r->route, r, rroute, 1);
4668
4669 /* disallow @if in from or to for the time being */
4670 if ((src_host->addr.type == PF_ADDR_ADDRMASK &&
4671 src_host->ifname) ||
4672 (dst_host->addr.type == PF_ADDR_ADDRMASK &&
4673 dst_host->ifname)) {
4674 yyerror("@if syntax not permitted in from or to");
4675 error++;
4676 }
4677 /* for link-local IPv6 address, interface must match up */
4678 if ((r->af && src_host->af && r->af != src_host->af) ||
4679 (r->af && dst_host->af && r->af != dst_host->af) ||
4680 (src_host->af && dst_host->af &&
4681 src_host->af != dst_host->af) ||
4682 (src_host->ifindex && dst_host->ifindex &&
4683 src_host->ifindex != dst_host->ifindex) ||
4684 (src_host->ifindex && *interface->ifname &&
4685 src_host->ifindex != ifa_nametoindex(interface->ifname)) ||
4686 (dst_host->ifindex && *interface->ifname &&
4687 dst_host->ifindex != ifa_nametoindex(interface->ifname)))
4688 continue;
4689 if (!r->af && src_host->af)
4690 r->af = src_host->af;
4691 else if (!r->af && dst_host->af)
4692 r->af = dst_host->af;
4693
4694 if (*interface->ifname)
4695 strlcpy(r->ifname, interface->ifname,
4696 sizeof(r->ifname));
4697 else if (ifa_indextoname(src_host->ifindex, ifname))
4698 strlcpy(r->ifname, ifname, sizeof(r->ifname));
4699 else if (ifa_indextoname(dst_host->ifindex, ifname))
4700 strlcpy(r->ifname, ifname, sizeof(r->ifname));
4701 else
4702 memset(r->ifname, '\0', sizeof(r->ifname));
4703
4704 if (interface->use_rdomain)
4705 r->onrdomain = interface->rdomain;
4706 else
4707 r->onrdomain = -1;
4708 if (strlcpy(r->label, label, sizeof(r->label)) >=
4709 sizeof(r->label))
4710 errx(1, "expand_rule: strlcpy");
4711 if (strlcpy(r->tagname, tagname, sizeof(r->tagname)) >=
4712 sizeof(r->tagname))
4713 errx(1, "expand_rule: strlcpy");
4714 if (strlcpy(r->match_tagname, match_tagname,
4715 sizeof(r->match_tagname)) >= sizeof(r->match_tagname))
4716 errx(1, "expand_rule: strlcpy");
4717 expand_label(r->label, PF_RULE_LABEL_SIZE, r->ifname, r->af,
4718 src_host, src_port, dst_host, dst_port, proto->proto);
4719 expand_label(r->tagname, PF_TAG_NAME_SIZE, r->ifname, r->af,
4720 src_host, src_port, dst_host, dst_port, proto->proto);
4721 expand_label(r->match_tagname, PF_TAG_NAME_SIZE, r->ifname,
4722 r->af, src_host, src_port, dst_host, dst_port,
4723 proto->proto);
4724
4725 osrch = odsth = NULL;
4726 if (src_host->addr.type == PF_ADDR_DYNIFTL) {
4727 osrch = src_host;
4728 if ((src_host = gen_dynnode(src_host, r->af)) == NULL)
4729 err(1, "%s", __func__);
4730 }
4731 if (dst_host->addr.type == PF_ADDR_DYNIFTL) {
4732 odsth = dst_host;
4733 if ((dst_host = gen_dynnode(dst_host, r->af)) == NULL)
4734 err(1, "%s", __func__);
4735 }
4736
4737 error += check_netmask(src_host, r->af);
4738 error += check_netmask(dst_host, r->af);
4739
4740 r->ifnot = interface->not;
4741 r->proto = proto->proto;
4742 r->src.addr = src_host->addr;
4743 r->src.neg = src_host->not;
4744 r->src.port[0] = src_port->port[0];
4745 r->src.port[1] = src_port->port[1];
4746 r->src.port_op = src_port->op;
4747 r->dst.addr = dst_host->addr;
4748 r->dst.neg = dst_host->not;
4749 r->dst.port[0] = dst_port->port[0];
4750 r->dst.port[1] = dst_port->port[1];
4751 r->dst.port_op = dst_port->op;
4752 r->uid.op = uid->op;
4753 r->uid.uid[0] = uid->uid[0];
4754 r->uid.uid[1] = uid->uid[1];
4755 r->gid.op = gid->op;
4756 r->gid.gid[0] = gid->gid[0];
4757 r->gid.gid[1] = gid->gid[1];
4758 if (rcv) {
4759 strlcpy(r->rcv_ifname, rcv->ifname,
4760 sizeof(r->rcv_ifname));
4761 r->rcvifnot = rcv->not;
4762 }
4763 r->type = icmp_type->type;
4764 r->code = icmp_type->code;
4765
4766 if ((keep_state == PF_STATE_MODULATE ||
4767 keep_state == PF_STATE_SYNPROXY) &&
4768 r->proto && r->proto != IPPROTO_TCP)
4769 r->keep_state = PF_STATE_NORMAL;
4770 else
4771 r->keep_state = keep_state;
4772
4773 if (r->proto && r->proto != IPPROTO_TCP) {
4774 r->flags = 0;
4775 r->flagset = 0;
4776 } else {
4777 r->flags = flags;
4778 r->flagset = flagset;
4779 }
4780 if (icmp_type->proto && r->proto != icmp_type->proto) {
4781 yyerror("icmp-type mismatch");
4782 error++;
4783 }
4784
4785 if (src_os && src_os->os) {
4786 r->os_fingerprint = pfctl_get_fingerprint(src_os->os);
4787 if ((pf->opts & PF_OPT_VERBOSE2) &&
4788 r->os_fingerprint == PF_OSFP_NOMATCH)
4789 fprintf(stderr,
4790 "warning: unknown '%s' OS fingerprint\n",
4791 src_os->os);
4792 } else {
4793 r->os_fingerprint = PF_OSFP_ANY;
4794 }
4795
4796 if (nat && nat->rdr && nat->binat) {
4797 if (disallow_table(src_host, "invalid use of table "
4798 "<%s> as the source address of a binat-to rule") ||
4799 disallow_alias(src_host, "invalid use of interface "
4800 "(%s) as the source address of a binat-to rule")) {
4801 error++;
4802 } else if ((r->src.addr.type != PF_ADDR_ADDRMASK &&
4803 r->src.addr.type != PF_ADDR_DYNIFTL) ||
4804 (r->nat.addr.type != PF_ADDR_ADDRMASK &&
4805 r->nat.addr.type != PF_ADDR_DYNIFTL)) {
4806 yyerror("binat-to requires a specified "
4807 "source and redirect address");
4808 error++;
4809 }
4810 if (DYNIF_MULTIADDR(r->src.addr) ||
4811 DYNIF_MULTIADDR(r->nat.addr)) {
4812 yyerror ("dynamic interfaces must be used with "
4813 ":0 in a binat-to rule");
4814 error++;
4815 }
4816 if (PF_AZERO(&r->src.addr.v.a.mask, af) ||
4817 PF_AZERO(&r->nat.addr.v.a.mask, af)) {
4818 yyerror ("source and redir addresess must have "
4819 "a matching network mask in binat-rule");
4820 error++;
4821 }
4822 if (r->nat.addr.type == PF_ADDR_TABLE) {
4823 yyerror ("tables cannot be used as the redirect "
4824 "address of a binat-to rule");
4825 error++;
4826 }
4827 if (r->direction != PF_INOUT) {
4828 yyerror("binat-to cannot be specified "
4829 "with a direction");
4830 error++;
4831 }
4832
4833 /* first specify outbound NAT rule */
4834 r->direction = PF_OUT;
4835 }
4836
4837 error += apply_redirspec(&r->nat, r, nat, 0, dst_port);
4838 error += apply_redirspec(&r->rdr, r, rdr, 1, dst_port);
4839 error += apply_redirspec(&r->route, r, rroute, 2, dst_port);
4840
4841 if (rule_consistent(r) < 0 || error)
4842 yyerror("skipping rule due to errors");
4843 else {
4844 r->nr = pf->astack[pf->asd]->match++;
4845 pfctl_add_rule(pf, r);
4846 added++;
4847 }
4848 r->direction = dir;
4849
4850 /* Generate binat's matching inbound rule */
4851 if (!error && nat && nat->rdr && nat->binat) {
4852 bcopy(r, &rb, sizeof(rb));
4853
4854 /* now specify inbound rdr rule */
4855 rb.direction = PF_IN;
4856
4857 if ((srch = calloc(1, sizeof(*srch))) == NULL)
4858 err(1, "%s", __func__);
4859 bcopy(src_host, srch, sizeof(*srch));
4860 srch->ifname = NULL;
4861 srch->next = NULL;
4862 srch->tail = NULL;
4863
4864 if ((dsth = calloc(1, sizeof(*dsth))) == NULL)
4865 err(1, "%s", __func__);
4866 bcopy(&rb.nat.addr, &dsth->addr, sizeof(dsth->addr));
4867 dsth->ifname = NULL;
4868 dsth->next = NULL;
4869 dsth->tail = NULL;
4870
4871 bzero(&binat, sizeof(binat));
4872 if ((binat.rdr =
4873 calloc(1, sizeof(*binat.rdr))) == NULL)
4874 err(1, "%s", __func__);
4875 bcopy(nat->rdr, binat.rdr, sizeof(*binat.rdr));
4876 bcopy(&nat->pool_opts, &binat.pool_opts,
4877 sizeof(binat.pool_opts));
4878 binat.pool_opts.staticport = 0;
4879 binat.rdr->host = srch;
4880
4881 expand_rule(&rb, 1, interface, NULL, &binat, NULL,
4882 proto,
4883 src_os, dst_host, dst_port, dsth, src_port,
4884 uid, gid, rcv, icmp_type);
4885 }
4886
4887 if (osrch && src_host->addr.type == PF_ADDR_DYNIFTL) {
4888 free(src_host);
4889 src_host = osrch;
4890 }
4891 if (odsth && dst_host->addr.type == PF_ADDR_DYNIFTL) {
4892 free(dst_host);
4893 dst_host = odsth;
4894 }
4895 ))))))))));
4896
4897 if (!keeprule) {
4898 FREE_LIST(struct node_if, interfaces);
4899 FREE_LIST(struct node_proto, protos);
4900 FREE_LIST(struct node_host, src_hosts);
4901 FREE_LIST(struct node_port, src_ports);
4902 FREE_LIST(struct node_os, src_oses);
4903 FREE_LIST(struct node_host, dst_hosts);
4904 FREE_LIST(struct node_port, dst_ports);
4905 FREE_LIST(struct node_uid, uids);
4906 FREE_LIST(struct node_gid, gids);
4907 FREE_LIST(struct node_icmp, icmp_types);
4908 if (nat && nat->rdr)
4909 FREE_LIST(struct node_host, nat->rdr->host);
4910 if (rdr && rdr->rdr)
4911 FREE_LIST(struct node_host, rdr->rdr->host);
4912
4913 }
4914
4915 if (!added)
4916 yyerror("rule expands to no valid combination");
4917 }
4918
4919 int
expand_skip_interface(struct node_if * interfaces)4920 expand_skip_interface(struct node_if *interfaces)
4921 {
4922 int errs = 0;
4923
4924 if (!interfaces || (!interfaces->next && !interfaces->not &&
4925 !strcmp(interfaces->ifname, "none"))) {
4926 if (pf->opts & PF_OPT_VERBOSE)
4927 printf("set skip on none\n");
4928 errs = pfctl_set_interface_flags(pf, "", PFI_IFLAG_SKIP, 0);
4929 return (errs);
4930 }
4931
4932 if (pf->opts & PF_OPT_VERBOSE)
4933 printf("set skip on {");
4934 LOOP_THROUGH(struct node_if, interface, interfaces,
4935 if (pf->opts & PF_OPT_VERBOSE)
4936 printf(" %s", interface->ifname);
4937 if (interface->not) {
4938 yyerror("skip on ! <interface> is not supported");
4939 errs++;
4940 } else if (interface->use_rdomain) {
4941 yyerror("skip on rdomain <num> is not supported");
4942 errs++;
4943 } else
4944 errs += pfctl_set_interface_flags(pf,
4945 interface->ifname, PFI_IFLAG_SKIP, 1);
4946 );
4947 if (pf->opts & PF_OPT_VERBOSE)
4948 printf(" }\n");
4949
4950 FREE_LIST(struct node_if, interfaces);
4951
4952 if (errs)
4953 return (1);
4954 else
4955 return (0);
4956 }
4957
4958 void
freehostlist(struct node_host * h)4959 freehostlist(struct node_host *h)
4960 {
4961 struct node_host *n;
4962
4963 for (n = h; n != NULL; n = n->next)
4964 if (n->ifname)
4965 free(n->ifname);
4966 FREE_LIST(struct node_host, h);
4967 }
4968
4969 #undef FREE_LIST
4970 #undef LOOP_THROUGH
4971
4972 int
kw_cmp(const void * k,const void * e)4973 kw_cmp(const void *k, const void *e)
4974 {
4975 return (strcmp(k, ((const struct keywords *)e)->k_name));
4976 }
4977
4978 int
lookup(char * s)4979 lookup(char *s)
4980 {
4981 /* this has to be sorted always */
4982 static const struct keywords keywords[] = {
4983 { "af-to", AFTO},
4984 { "all", ALL},
4985 { "allow-opts", ALLOWOPTS},
4986 { "anchor", ANCHOR},
4987 { "antispoof", ANTISPOOF},
4988 { "any", ANY},
4989 { "bandwidth", BANDWIDTH},
4990 { "binat-to", BINATTO},
4991 { "bitmask", BITMASK},
4992 { "block", BLOCK},
4993 { "block-policy", BLOCKPOLICY},
4994 { "burst", BURST},
4995 { "code", CODE},
4996 { "debug", DEBUG},
4997 { "default", DEFAULT},
4998 { "delay", DELAY},
4999 { "divert-packet", DIVERTPACKET},
5000 { "divert-reply", DIVERTREPLY},
5001 { "divert-to", DIVERTTO},
5002 { "drop", DROP},
5003 { "dup-to", DUPTO},
5004 { "file", FILENAME},
5005 { "fingerprints", FINGERPRINTS},
5006 { "flags", FLAGS},
5007 { "floating", FLOATING},
5008 { "flows", FLOWS},
5009 { "flush", FLUSH},
5010 { "for", FOR},
5011 { "fragment", FRAGMENT},
5012 { "from", FROM},
5013 { "global", GLOBAL},
5014 { "group", GROUP},
5015 { "hostid", HOSTID},
5016 { "icmp-type", ICMPTYPE},
5017 { "icmp6-type", ICMP6TYPE},
5018 { "if-bound", IFBOUND},
5019 { "in", IN},
5020 { "include", INCLUDE},
5021 { "inet", INET},
5022 { "inet6", INET6},
5023 { "keep", KEEP},
5024 { "label", LABEL},
5025 { "least-states", LEASTSTATES},
5026 { "limit", LIMIT},
5027 { "load", LOAD},
5028 { "log", LOG},
5029 { "loginterface", LOGINTERFACE},
5030 { "match", MATCH},
5031 { "matches", MATCHES},
5032 { "max", MAXIMUM},
5033 { "max-mss", MAXMSS},
5034 { "max-pkt-rate", MAXPKTRATE},
5035 { "max-src-conn", MAXSRCCONN},
5036 { "max-src-conn-rate", MAXSRCCONNRATE},
5037 { "max-src-nodes", MAXSRCNODES},
5038 { "max-src-states", MAXSRCSTATES},
5039 { "min", MINIMUM},
5040 { "min-ttl", MINTTL},
5041 { "modulate", MODULATE},
5042 { "nat-to", NATTO},
5043 { "no", NO},
5044 { "no-df", NODF},
5045 { "no-route", NOROUTE},
5046 { "no-sync", NOSYNC},
5047 { "on", ON},
5048 { "once", ONCE},
5049 { "optimization", OPTIMIZATION},
5050 { "os", OS},
5051 { "out", OUT},
5052 { "overload", OVERLOAD},
5053 { "parent", PARENT},
5054 { "pass", PASS},
5055 { "pflow", PFLOW},
5056 { "port", PORT},
5057 { "prio", PRIO},
5058 { "probability", PROBABILITY},
5059 { "proto", PROTO},
5060 { "qlimit", QLIMIT},
5061 { "quantum", QUANTUM},
5062 { "queue", QUEUE},
5063 { "quick", QUICK},
5064 { "random", RANDOM},
5065 { "random-id", RANDOMID},
5066 { "rdomain", RDOMAIN},
5067 { "rdr-to", RDRTO},
5068 { "reassemble", REASSEMBLE},
5069 { "received-on", RECEIVEDON},
5070 { "reply-to", REPLYTO},
5071 { "return", RETURN},
5072 { "return-icmp", RETURNICMP},
5073 { "return-icmp6", RETURNICMP6},
5074 { "return-rst", RETURNRST},
5075 { "round-robin", ROUNDROBIN},
5076 { "route", ROUTE},
5077 { "route-to", ROUTETO},
5078 { "rtable", RTABLE},
5079 { "rule", RULE},
5080 { "ruleset-optimization", RULESET_OPTIMIZATION},
5081 { "scrub", SCRUB},
5082 { "set", SET},
5083 { "skip", SKIP},
5084 { "sloppy", SLOPPY},
5085 { "source-hash", SOURCEHASH},
5086 { "source-track", SOURCETRACK},
5087 { "state", STATE},
5088 { "state-defaults", STATEDEFAULTS},
5089 { "state-policy", STATEPOLICY},
5090 { "static-port", STATICPORT},
5091 { "sticky-address", STICKYADDRESS},
5092 { "syncookies", SYNCOOKIES},
5093 { "synproxy", SYNPROXY},
5094 { "table", TABLE},
5095 { "tag", TAG},
5096 { "tagged", TAGGED},
5097 { "timeout", TIMEOUT},
5098 { "to", TO},
5099 { "tos", TOS},
5100 { "ttl", TTL},
5101 { "urpf-failed", URPFFAILED},
5102 { "user", USER},
5103 { "weight", WEIGHT},
5104 };
5105 const struct keywords *p;
5106
5107 p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
5108 sizeof(keywords[0]), kw_cmp);
5109
5110 if (p) {
5111 if (debug > 1)
5112 fprintf(stderr, "%s: %d\n", s, p->k_val);
5113 return (p->k_val);
5114 } else {
5115 if (debug > 1)
5116 fprintf(stderr, "string: %s\n", s);
5117 return (STRING);
5118 }
5119 }
5120
5121 #define START_EXPAND 1
5122 #define DONE_EXPAND 2
5123
5124 static int expanding;
5125
5126 int
igetc(void)5127 igetc(void)
5128 {
5129 int c;
5130 while (1) {
5131 if (file->ungetpos > 0)
5132 c = file->ungetbuf[--file->ungetpos];
5133 else
5134 c = getc(file->stream);
5135 if (c == START_EXPAND)
5136 expanding = 1;
5137 else if (c == DONE_EXPAND)
5138 expanding = 0;
5139 else
5140 break;
5141 }
5142 return (c);
5143 }
5144
5145 int
lgetc(int quotec)5146 lgetc(int quotec)
5147 {
5148 int c, next;
5149
5150 if (quotec) {
5151 if ((c = igetc()) == EOF) {
5152 yyerror("reached end of file while parsing quoted string");
5153 if (file == topfile || popfile() == EOF)
5154 return (EOF);
5155 return (quotec);
5156 }
5157 return (c);
5158 }
5159
5160 while ((c = igetc()) == '\\') {
5161 next = igetc();
5162 if (next != '\n') {
5163 c = next;
5164 break;
5165 }
5166 yylval.lineno = file->lineno;
5167 file->lineno++;
5168 }
5169
5170 if (c == EOF) {
5171 /*
5172 * Fake EOL when hit EOF for the first time. This gets line
5173 * count right if last line in included file is syntactically
5174 * invalid and has no newline.
5175 */
5176 if (file->eof_reached == 0) {
5177 file->eof_reached = 1;
5178 return ('\n');
5179 }
5180 while (c == EOF) {
5181 if (file == topfile || popfile() == EOF)
5182 return (EOF);
5183 c = igetc();
5184 }
5185 }
5186
5187 return (c);
5188 }
5189
5190 void
lungetc(int c)5191 lungetc(int c)
5192 {
5193 if (c == EOF)
5194 return;
5195 if (file->ungetpos >= file->ungetsize) {
5196 void *p = reallocarray(file->ungetbuf, file->ungetsize, 2);
5197 if (p == NULL)
5198 err(1, "%s", __func__);
5199 file->ungetbuf = p;
5200 file->ungetsize *= 2;
5201 }
5202 file->ungetbuf[file->ungetpos++] = c;
5203 }
5204
5205 int
findeol(void)5206 findeol(void)
5207 {
5208 int c;
5209
5210 /* skip to either EOF or the first real EOL */
5211 while (1) {
5212 c = lgetc(0);
5213 if (c == '\n') {
5214 file->lineno++;
5215 break;
5216 }
5217 if (c == EOF)
5218 break;
5219 }
5220 return (ERROR);
5221 }
5222
5223 int
yylex(void)5224 yylex(void)
5225 {
5226 char buf[8096];
5227 char *p, *val;
5228 int quotec, next, c;
5229 int token;
5230
5231 top:
5232 p = buf;
5233 while ((c = lgetc(0)) == ' ' || c == '\t')
5234 ; /* nothing */
5235
5236 yylval.lineno = file->lineno;
5237 if (c == '#')
5238 while ((c = lgetc(0)) != '\n' && c != EOF)
5239 ; /* nothing */
5240 if (c == '$' && !expanding) {
5241 while (1) {
5242 if ((c = lgetc(0)) == EOF)
5243 return (0);
5244
5245 if (p + 1 >= buf + sizeof(buf) - 1) {
5246 yyerror("string too long");
5247 return (findeol());
5248 }
5249 if (isalnum(c) || c == '_') {
5250 *p++ = c;
5251 continue;
5252 }
5253 *p = '\0';
5254 lungetc(c);
5255 break;
5256 }
5257 val = symget(buf);
5258 if (val == NULL) {
5259 yyerror("macro '%s' not defined", buf);
5260 return (findeol());
5261 }
5262 p = val + strlen(val) - 1;
5263 lungetc(DONE_EXPAND);
5264 while (p >= val) {
5265 lungetc((unsigned char)*p);
5266 p--;
5267 }
5268 lungetc(START_EXPAND);
5269 goto top;
5270 }
5271
5272 switch (c) {
5273 case '\'':
5274 case '"':
5275 quotec = c;
5276 while (1) {
5277 if ((c = lgetc(quotec)) == EOF)
5278 return (0);
5279 if (c == '\n') {
5280 file->lineno++;
5281 continue;
5282 } else if (c == '\\') {
5283 if ((next = lgetc(quotec)) == EOF)
5284 return (0);
5285 if (next == quotec || next == ' ' ||
5286 next == '\t')
5287 c = next;
5288 else if (next == '\n') {
5289 file->lineno++;
5290 continue;
5291 } else
5292 lungetc(next);
5293 } else if (c == quotec) {
5294 *p = '\0';
5295 break;
5296 } else if (c == '\0') {
5297 yyerror("syntax error");
5298 return (findeol());
5299 }
5300 if (p + 1 >= buf + sizeof(buf) - 1) {
5301 yyerror("string too long");
5302 return (findeol());
5303 }
5304 *p++ = c;
5305 }
5306 yylval.v.string = strdup(buf);
5307 if (yylval.v.string == NULL)
5308 err(1, "%s", __func__);
5309 return (STRING);
5310 case '!':
5311 next = lgetc(0);
5312 if (next == '=')
5313 return (NE);
5314 lungetc(next);
5315 break;
5316 case '<':
5317 next = lgetc(0);
5318 if (next == '>') {
5319 yylval.v.i = PF_OP_XRG;
5320 return (PORTBINARY);
5321 } else if (next == '=')
5322 return (LE);
5323 lungetc(next);
5324 break;
5325 case '>':
5326 next = lgetc(0);
5327 if (next == '<') {
5328 yylval.v.i = PF_OP_IRG;
5329 return (PORTBINARY);
5330 } else if (next == '=')
5331 return (GE);
5332 lungetc(next);
5333 break;
5334 }
5335
5336 #define allowed_to_end_number(x) \
5337 (isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
5338
5339 if (c == '-' || isdigit(c)) {
5340 do {
5341 *p++ = c;
5342 if ((size_t)(p-buf) >= sizeof(buf)) {
5343 yyerror("string too long");
5344 return (findeol());
5345 }
5346 } while ((c = lgetc(0)) != EOF && isdigit(c));
5347 lungetc(c);
5348 if (p == buf + 1 && buf[0] == '-')
5349 goto nodigits;
5350 if (c == EOF || allowed_to_end_number(c)) {
5351 const char *errstr = NULL;
5352
5353 *p = '\0';
5354 yylval.v.number = strtonum(buf, LLONG_MIN,
5355 LLONG_MAX, &errstr);
5356 if (errstr) {
5357 yyerror("\"%s\" invalid number: %s",
5358 buf, errstr);
5359 return (findeol());
5360 }
5361 return (NUMBER);
5362 } else {
5363 nodigits:
5364 while (p > buf + 1)
5365 lungetc((unsigned char)*--p);
5366 c = (unsigned char)*--p;
5367 if (c == '-')
5368 return (c);
5369 }
5370 }
5371
5372 #define allowed_in_string(x) \
5373 (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
5374 x != '{' && x != '}' && x != '<' && x != '>' && \
5375 x != '!' && x != '=' && x != '/' && x != '#' && \
5376 x != ','))
5377
5378 if (isalnum(c) || c == ':' || c == '_') {
5379 do {
5380 *p++ = c;
5381 if ((size_t)(p-buf) >= sizeof(buf)) {
5382 yyerror("string too long");
5383 return (findeol());
5384 }
5385 } while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
5386 lungetc(c);
5387 *p = '\0';
5388 if ((token = lookup(buf)) == STRING)
5389 if ((yylval.v.string = strdup(buf)) == NULL)
5390 err(1, "%s", __func__);
5391 return (token);
5392 }
5393 if (c == '\n') {
5394 yylval.lineno = file->lineno;
5395 file->lineno++;
5396 }
5397 if (c == EOF)
5398 return (0);
5399 return (c);
5400 }
5401
5402 int
check_file_secrecy(int fd,const char * fname)5403 check_file_secrecy(int fd, const char *fname)
5404 {
5405 struct stat st;
5406
5407 if (fstat(fd, &st)) {
5408 warn("cannot stat %s", fname);
5409 return (-1);
5410 }
5411 if (st.st_uid != 0 && st.st_uid != getuid()) {
5412 warnx("%s: owner not root or current user", fname);
5413 return (-1);
5414 }
5415 if (st.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)) {
5416 warnx("%s: group writable or world read/writable", fname);
5417 return (-1);
5418 }
5419 return (0);
5420 }
5421
5422 struct file *
pushfile(const char * name,int secret)5423 pushfile(const char *name, int secret)
5424 {
5425 struct file *nfile;
5426
5427 if ((nfile = calloc(1, sizeof(struct file))) == NULL ||
5428 (nfile->name = strdup(name)) == NULL) {
5429 warn("%s", __func__);
5430 if (nfile)
5431 free(nfile);
5432 return (NULL);
5433 }
5434 if (TAILQ_FIRST(&files) == NULL && strcmp(nfile->name, "-") == 0) {
5435 nfile->stream = stdin;
5436 free(nfile->name);
5437 if ((nfile->name = strdup("stdin")) == NULL) {
5438 warn("%s", __func__);
5439 free(nfile);
5440 return (NULL);
5441 }
5442 } else if ((nfile->stream = pfctl_fopen(nfile->name, "r")) == NULL) {
5443 warn("%s: %s", __func__, nfile->name);
5444 free(nfile->name);
5445 free(nfile);
5446 return (NULL);
5447 } else if (secret &&
5448 check_file_secrecy(fileno(nfile->stream), nfile->name)) {
5449 fclose(nfile->stream);
5450 free(nfile->name);
5451 free(nfile);
5452 return (NULL);
5453 }
5454 nfile->lineno = TAILQ_EMPTY(&files) ? 1 : 0;
5455 nfile->ungetsize = 16;
5456 nfile->ungetbuf = malloc(nfile->ungetsize);
5457 if (nfile->ungetbuf == NULL) {
5458 warn("%s", __func__);
5459 fclose(nfile->stream);
5460 free(nfile->name);
5461 free(nfile);
5462 return (NULL);
5463 }
5464 TAILQ_INSERT_TAIL(&files, nfile, entry);
5465 return (nfile);
5466 }
5467
5468 int
popfile(void)5469 popfile(void)
5470 {
5471 struct file *prev;
5472
5473 if ((prev = TAILQ_PREV(file, files, entry)) != NULL)
5474 prev->errors += file->errors;
5475
5476 TAILQ_REMOVE(&files, file, entry);
5477 fclose(file->stream);
5478 free(file->name);
5479 free(file->ungetbuf);
5480 free(file);
5481 file = prev;
5482
5483 return (file ? 0 : EOF);
5484 }
5485
5486 int
parse_config(char * filename,struct pfctl * xpf)5487 parse_config(char *filename, struct pfctl *xpf)
5488 {
5489 int errors = 0;
5490 struct sym *sym;
5491
5492 pf = xpf;
5493 returnicmpdefault = (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT;
5494 returnicmp6default =
5495 (ICMP6_DST_UNREACH << 8) | ICMP6_DST_UNREACH_NOPORT;
5496 blockpolicy = PFRULE_DROP;
5497
5498 if ((file = pushfile(filename, 0)) == NULL) {
5499 warn("cannot open the main config file!");
5500 return (-1);
5501 }
5502 topfile = file;
5503
5504 yyparse();
5505 errors = file->errors;
5506 popfile();
5507
5508 /* Free macros and check which have not been used. */
5509 while ((sym = TAILQ_FIRST(&symhead))) {
5510 if ((pf->opts & PF_OPT_VERBOSE2) && !sym->used)
5511 fprintf(stderr, "warning: macro '%s' not "
5512 "used\n", sym->nam);
5513 free(sym->nam);
5514 free(sym->val);
5515 TAILQ_REMOVE(&symhead, sym, entry);
5516 free(sym);
5517 }
5518
5519 return (errors ? -1 : 0);
5520 }
5521
5522 int
symset(const char * nam,const char * val,int persist)5523 symset(const char *nam, const char *val, int persist)
5524 {
5525 struct sym *sym;
5526
5527 TAILQ_FOREACH(sym, &symhead, entry) {
5528 if (strcmp(nam, sym->nam) == 0)
5529 break;
5530 }
5531
5532 if (sym != NULL) {
5533 if (sym->persist == 1)
5534 return (0);
5535 else {
5536 free(sym->nam);
5537 free(sym->val);
5538 TAILQ_REMOVE(&symhead, sym, entry);
5539 free(sym);
5540 }
5541 }
5542 if ((sym = calloc(1, sizeof(*sym))) == NULL)
5543 return (-1);
5544
5545 sym->nam = strdup(nam);
5546 if (sym->nam == NULL) {
5547 free(sym);
5548 return (-1);
5549 }
5550 sym->val = strdup(val);
5551 if (sym->val == NULL) {
5552 free(sym->nam);
5553 free(sym);
5554 return (-1);
5555 }
5556 sym->used = 0;
5557 sym->persist = persist;
5558 TAILQ_INSERT_TAIL(&symhead, sym, entry);
5559 return (0);
5560 }
5561
5562 int
pfctl_cmdline_symset(char * s)5563 pfctl_cmdline_symset(char *s)
5564 {
5565 char *sym, *val;
5566 int ret;
5567
5568 if ((val = strrchr(s, '=')) == NULL)
5569 return (-1);
5570
5571 sym = strndup(s, val - s);
5572 if (sym == NULL)
5573 err(1, "%s", __func__);
5574 ret = symset(sym, val + 1, 1);
5575 free(sym);
5576
5577 return (ret);
5578 }
5579
5580 char *
symget(const char * nam)5581 symget(const char *nam)
5582 {
5583 struct sym *sym;
5584
5585 TAILQ_FOREACH(sym, &symhead, entry) {
5586 if (strcmp(nam, sym->nam) == 0) {
5587 sym->used = 1;
5588 return (sym->val);
5589 }
5590 }
5591 return (NULL);
5592 }
5593
5594 void
mv_rules(struct pf_ruleset * src,struct pf_ruleset * dst)5595 mv_rules(struct pf_ruleset *src, struct pf_ruleset *dst)
5596 {
5597 struct pf_rule *r;
5598
5599 TAILQ_FOREACH(r, src->rules.active.ptr, entries)
5600 dst->anchor->match++;
5601 TAILQ_CONCAT(dst->rules.active.ptr, src->rules.active.ptr, entries);
5602 src->anchor->match = 0;
5603 TAILQ_CONCAT(dst->rules.inactive.ptr, src->rules.inactive.ptr, entries);
5604 }
5605
5606 void
mv_tables(struct pfctl * pf,struct pfr_ktablehead * ktables,struct pf_anchor * a,struct pf_anchor * alast)5607 mv_tables(struct pfctl *pf, struct pfr_ktablehead *ktables,
5608 struct pf_anchor *a, struct pf_anchor *alast)
5609 {
5610
5611 struct pfr_ktable *kt, *kt_safe;
5612 char new_path[PF_ANCHOR_MAXPATH];
5613 char *path_cut;
5614 int sz;
5615 struct pfr_uktable *ukt;
5616 SLIST_HEAD(, pfr_uktable) ukt_list;
5617
5618 /*
5619 * Here we need to rename anchor path from temporal names such as
5620 * _1/_2/foo to _1/bar/foo etc.
5621 *
5622 * This also means we need to remove and insert table to ktables
5623 * tree as anchor path is being updated.
5624 */
5625 SLIST_INIT(&ukt_list);
5626 DBGPRINT("%s [ %s ] (%s)\n", __func__, a->path, alast->path);
5627 RB_FOREACH_SAFE(kt, pfr_ktablehead, ktables, kt_safe) {
5628 path_cut = strstr(kt->pfrkt_anchor, alast->path);
5629 if (path_cut != NULL) {
5630 path_cut += strlen(alast->path);
5631 if (*path_cut)
5632 sz = snprintf(new_path, sizeof (new_path),
5633 "%s%s", a->path, path_cut);
5634 else
5635 sz = snprintf(new_path, sizeof (new_path),
5636 "%s", a->path);
5637 if (sz >= sizeof (new_path))
5638 errx(1, "new path is too long for %s@%s\n",
5639 kt->pfrkt_name, kt->pfrkt_anchor);
5640
5641 DBGPRINT("%s %s@%s -> %s@%s\n", __func__,
5642 kt->pfrkt_name, kt->pfrkt_anchor,
5643 kt->pfrkt_name, new_path);
5644 RB_REMOVE(pfr_ktablehead, ktables, kt);
5645 strlcpy(kt->pfrkt_anchor, new_path,
5646 sizeof(kt->pfrkt_anchor));
5647 SLIST_INSERT_HEAD(&ukt_list, (struct pfr_uktable *)kt,
5648 pfrukt_entry);
5649 }
5650 }
5651
5652 while ((ukt = SLIST_FIRST(&ukt_list)) != NULL) {
5653 SLIST_REMOVE_HEAD(&ukt_list, pfrukt_entry);
5654 if (RB_INSERT(pfr_ktablehead, ktables,
5655 (struct pfr_ktable *)ukt) != NULL)
5656 errx(1, "%s@%s exists already\n",
5657 ukt->pfrukt_name,
5658 ukt->pfrukt_anchor);
5659 }
5660 }
5661
5662 void
decide_address_family(struct node_host * n,sa_family_t * af)5663 decide_address_family(struct node_host *n, sa_family_t *af)
5664 {
5665 if (*af != 0 || n == NULL)
5666 return;
5667 *af = n->af;
5668 while ((n = n->next) != NULL) {
5669 if (n->af != *af) {
5670 *af = 0;
5671 return;
5672 }
5673 }
5674 }
5675
5676 int
invalid_redirect(struct node_host * nh,sa_family_t af)5677 invalid_redirect(struct node_host *nh, sa_family_t af)
5678 {
5679 if (!af) {
5680 struct node_host *n;
5681
5682 /* tables and dyniftl are ok without an address family */
5683 for (n = nh; n != NULL; n = n->next) {
5684 if (n->addr.type != PF_ADDR_TABLE &&
5685 n->addr.type != PF_ADDR_DYNIFTL) {
5686 yyerror("address family not given and "
5687 "translation address expands to multiple "
5688 "address families");
5689 return (1);
5690 }
5691 }
5692 }
5693 if (nh == NULL) {
5694 yyerror("no translation address with matching address family "
5695 "found.");
5696 return (1);
5697 }
5698 return (0);
5699 }
5700
5701 int
atoul(char * s,u_long * ulvalp)5702 atoul(char *s, u_long *ulvalp)
5703 {
5704 u_long ulval;
5705 char *ep;
5706
5707 errno = 0;
5708 ulval = strtoul(s, &ep, 0);
5709 if (s[0] == '\0' || *ep != '\0')
5710 return (-1);
5711 if (errno == ERANGE && ulval == ULONG_MAX)
5712 return (-1);
5713 *ulvalp = ulval;
5714 return (0);
5715 }
5716
5717 int
getservice(char * n)5718 getservice(char *n)
5719 {
5720 struct servent *s;
5721 u_long ulval;
5722
5723 if (atoul(n, &ulval) == 0) {
5724 if (ulval > 65535) {
5725 yyerror("illegal port value %lu", ulval);
5726 return (-1);
5727 }
5728 return (htons(ulval));
5729 } else {
5730 s = getservbyname(n, "tcp");
5731 if (s == NULL)
5732 s = getservbyname(n, "udp");
5733 if (s == NULL) {
5734 yyerror("unknown port %s", n);
5735 return (-1);
5736 }
5737 return (s->s_port);
5738 }
5739 }
5740
5741 int
rule_label(struct pf_rule * r,char * s)5742 rule_label(struct pf_rule *r, char *s)
5743 {
5744 if (s) {
5745 if (strlcpy(r->label, s, sizeof(r->label)) >=
5746 sizeof(r->label)) {
5747 yyerror("rule label too long (max %zu chars)",
5748 sizeof(r->label)-1);
5749 return (-1);
5750 }
5751 }
5752 return (0);
5753 }
5754
5755 u_int16_t
parseicmpspec(char * w,sa_family_t af)5756 parseicmpspec(char *w, sa_family_t af)
5757 {
5758 const struct icmpcodeent *p;
5759 u_long ulval;
5760 u_int8_t icmptype;
5761
5762 if (af == AF_INET)
5763 icmptype = returnicmpdefault >> 8;
5764 else
5765 icmptype = returnicmp6default >> 8;
5766
5767 if (atoul(w, &ulval) == -1) {
5768 if ((p = geticmpcodebyname(icmptype, w, af)) == NULL) {
5769 yyerror("unknown icmp code %s", w);
5770 return (0);
5771 }
5772 ulval = p->code;
5773 }
5774 if (ulval > 255) {
5775 yyerror("invalid icmp code %lu", ulval);
5776 return (0);
5777 }
5778 return (icmptype << 8 | ulval);
5779 }
5780
5781 int
parseport(char * port,struct range * r,int extensions)5782 parseport(char *port, struct range *r, int extensions)
5783 {
5784 char *p = strchr(port, ':');
5785
5786 if (p == NULL) {
5787 if ((r->a = getservice(port)) == -1)
5788 return (-1);
5789 r->b = 0;
5790 r->t = PF_OP_NONE;
5791 return (0);
5792 }
5793 if ((extensions & PPORT_STAR) && !strcmp(p+1, "*")) {
5794 *p = 0;
5795 if ((r->a = getservice(port)) == -1)
5796 return (-1);
5797 r->b = 0;
5798 r->t = PF_OP_IRG;
5799 return (0);
5800 }
5801 if ((extensions & PPORT_RANGE)) {
5802 *p++ = 0;
5803 if ((r->a = getservice(port)) == -1 ||
5804 (r->b = getservice(p)) == -1)
5805 return (-1);
5806 if (r->a == r->b) {
5807 r->b = 0;
5808 r->t = PF_OP_NONE;
5809 } else
5810 r->t = PF_OP_RRG;
5811 return (0);
5812 }
5813 yyerror("port is invalid: %s", port);
5814 return (-1);
5815 }
5816
5817 int
pfctl_load_anchors(int dev,struct pfctl * pf)5818 pfctl_load_anchors(int dev, struct pfctl *pf)
5819 {
5820 struct loadanchors *la;
5821
5822 TAILQ_FOREACH(la, &loadanchorshead, entries) {
5823 if (pf->opts & PF_OPT_VERBOSE)
5824 fprintf(stderr, "\nLoading anchor %s from %s\n",
5825 la->anchorname, la->filename);
5826 if (pfctl_rules(dev, la->filename, pf->opts, pf->optimize,
5827 la->anchorname, pf->trans) == -1)
5828 return (-1);
5829 }
5830
5831 return (0);
5832 }
5833
5834 int
kw_casecmp(const void * k,const void * e)5835 kw_casecmp(const void *k, const void *e)
5836 {
5837 return (strcasecmp(k, ((const struct keywords *)e)->k_name));
5838 }
5839
5840 int
map_tos(char * s,int * val)5841 map_tos(char *s, int *val)
5842 {
5843 /* DiffServ Codepoints and other TOS mappings */
5844 const struct keywords toswords[] = {
5845 { "af11", IPTOS_DSCP_AF11 },
5846 { "af12", IPTOS_DSCP_AF12 },
5847 { "af13", IPTOS_DSCP_AF13 },
5848 { "af21", IPTOS_DSCP_AF21 },
5849 { "af22", IPTOS_DSCP_AF22 },
5850 { "af23", IPTOS_DSCP_AF23 },
5851 { "af31", IPTOS_DSCP_AF31 },
5852 { "af32", IPTOS_DSCP_AF32 },
5853 { "af33", IPTOS_DSCP_AF33 },
5854 { "af41", IPTOS_DSCP_AF41 },
5855 { "af42", IPTOS_DSCP_AF42 },
5856 { "af43", IPTOS_DSCP_AF43 },
5857 { "critical", IPTOS_PREC_CRITIC_ECP },
5858 { "cs0", IPTOS_DSCP_CS0 },
5859 { "cs1", IPTOS_DSCP_CS1 },
5860 { "cs2", IPTOS_DSCP_CS2 },
5861 { "cs3", IPTOS_DSCP_CS3 },
5862 { "cs4", IPTOS_DSCP_CS4 },
5863 { "cs5", IPTOS_DSCP_CS5 },
5864 { "cs6", IPTOS_DSCP_CS6 },
5865 { "cs7", IPTOS_DSCP_CS7 },
5866 { "ef", IPTOS_DSCP_EF },
5867 { "inetcontrol", IPTOS_PREC_INTERNETCONTROL },
5868 { "lowdelay", IPTOS_LOWDELAY },
5869 { "netcontrol", IPTOS_PREC_NETCONTROL },
5870 { "reliability", IPTOS_RELIABILITY },
5871 { "throughput", IPTOS_THROUGHPUT }
5872 };
5873 const struct keywords *p;
5874
5875 p = bsearch(s, toswords, sizeof(toswords)/sizeof(toswords[0]),
5876 sizeof(toswords[0]), kw_casecmp);
5877
5878 if (p) {
5879 *val = p->k_val;
5880 return (1);
5881 }
5882 return (0);
5883 }
5884
5885 int
lookup_rtable(u_int rtableid)5886 lookup_rtable(u_int rtableid)
5887 {
5888 size_t len;
5889 struct rt_tableinfo info;
5890 int mib[6];
5891 static u_int found[RT_TABLEID_MAX+1];
5892
5893 if (found[rtableid])
5894 return found[rtableid];
5895
5896 mib[0] = CTL_NET;
5897 mib[1] = PF_ROUTE;
5898 mib[2] = 0;
5899 mib[3] = 0;
5900 mib[4] = NET_RT_TABLE;
5901 mib[5] = rtableid;
5902
5903 len = sizeof(info);
5904 if (sysctl(mib, 6, &info, &len, NULL, 0) == -1) {
5905 if (errno == ENOENT) {
5906 /* table nonexistent */
5907 found[rtableid] = 0;
5908 return 0;
5909 }
5910 err(1, "%s", __func__);
5911 }
5912 found[rtableid] = 1;
5913 return 1;
5914 }
5915
5916 int
filteropts_to_rule(struct pf_rule * r,struct filter_opts * opts)5917 filteropts_to_rule(struct pf_rule *r, struct filter_opts *opts)
5918 {
5919 if (opts->marker & FOM_ONCE) {
5920 if ((r->action != PF_PASS && r->action != PF_DROP) || r->anchor) {
5921 yyerror("'once' only applies to pass/block rules");
5922 return (1);
5923 }
5924 r->rule_flag |= PFRULE_ONCE;
5925 }
5926
5927 r->keep_state = opts->keep.action;
5928 r->pktrate.limit = opts->pktrate.limit;
5929 r->pktrate.seconds = opts->pktrate.seconds;
5930 r->prob = opts->prob;
5931 r->rtableid = opts->rtableid;
5932 r->tos = opts->tos;
5933
5934 if (opts->nodf)
5935 r->scrub_flags |= PFSTATE_NODF;
5936 if (opts->randomid)
5937 r->scrub_flags |= PFSTATE_RANDOMID;
5938 if (opts->minttl)
5939 r->min_ttl = opts->minttl;
5940 if (opts->max_mss)
5941 r->max_mss = opts->max_mss;
5942
5943 if (opts->tag)
5944 if (strlcpy(r->tagname, opts->tag,
5945 PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
5946 yyerror("tag too long, max %u chars",
5947 PF_TAG_NAME_SIZE - 1);
5948 return (1);
5949 }
5950 if (opts->match_tag)
5951 if (strlcpy(r->match_tagname, opts->match_tag,
5952 PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
5953 yyerror("tag too long, max %u chars",
5954 PF_TAG_NAME_SIZE - 1);
5955 return (1);
5956 }
5957 r->match_tag_not = opts->match_tag_not;
5958
5959 if (rule_label(r, opts->label))
5960 return (1);
5961 free(opts->label);
5962
5963 if (opts->marker & FOM_AFTO)
5964 r->rule_flag |= PFRULE_AFTO;
5965 if ((opts->marker & FOM_AFTO) && r->direction != PF_IN) {
5966 yyerror("af-to can only be used with direction in");
5967 return (1);
5968 }
5969 if ((opts->marker & FOM_AFTO) && opts->rt) {
5970 yyerror("af-to cannot be used together with "
5971 "route-to, reply-to, dup-to");
5972 return (1);
5973 }
5974 if (opts->marker & FOM_SCRUB_TCP)
5975 r->scrub_flags |= PFSTATE_SCRUB_TCP;
5976 if (opts->marker & FOM_SETDELAY) {
5977 r->delay = opts->delay;
5978 r->rule_flag |= PFRULE_SETDELAY;
5979 }
5980 if (opts->marker & FOM_SETPRIO) {
5981 r->set_prio[0] = opts->set_prio[0];
5982 r->set_prio[1] = opts->set_prio[1];
5983 r->scrub_flags |= PFSTATE_SETPRIO;
5984 }
5985 if (opts->marker & FOM_SETTOS) {
5986 r->scrub_flags |= PFSTATE_SETTOS;
5987 r->set_tos = opts->settos;
5988 }
5989 if (opts->marker & FOM_PRIO)
5990 r->prio = opts->prio ? opts->prio : PF_PRIO_ZERO;
5991 if (opts->marker & FOM_SETPRIO) {
5992 r->set_prio[0] = opts->set_prio[0];
5993 r->set_prio[1] = opts->set_prio[1];
5994 r->scrub_flags |= PFSTATE_SETPRIO;
5995 }
5996
5997 r->flags = opts->flags.b1;
5998 r->flagset = opts->flags.b2;
5999 if ((opts->flags.b1 & opts->flags.b2) != opts->flags.b1) {
6000 yyerror("flags always false");
6001 return (1);
6002 }
6003
6004 if (opts->queues.qname != NULL) {
6005 if (strlcpy(r->qname, opts->queues.qname,
6006 sizeof(r->qname)) >= sizeof(r->qname)) {
6007 yyerror("rule qname too long (max "
6008 "%zu chars)", sizeof(r->qname)-1);
6009 return (1);
6010 }
6011 free(opts->queues.qname);
6012 }
6013 if (opts->queues.pqname != NULL) {
6014 if (strlcpy(r->pqname, opts->queues.pqname,
6015 sizeof(r->pqname)) >= sizeof(r->pqname)) {
6016 yyerror("rule pqname too long (max "
6017 "%zu chars)", sizeof(r->pqname)-1);
6018 return (1);
6019 }
6020 free(opts->queues.pqname);
6021 }
6022
6023 if (opts->fragment)
6024 r->rule_flag |= PFRULE_FRAGMENT;
6025 r->allow_opts = opts->allowopts;
6026
6027 return (0);
6028 }
6029