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