1 /* $OpenBSD: parse.y,v 1.449 2004/03/20 23:20:20 david Exp $ */
2 /* $DragonFly: src/usr.sbin/pfctl/parse.y,v 1.5 2008/04/11 18:21:49 dillon Exp $ */
5 * Copyright (c) 2001 Markus Friedl. All rights reserved.
6 * Copyright (c) 2001 Daniel Hartmeier. All rights reserved.
7 * Copyright (c) 2001 Theo de Raadt. All rights reserved.
8 * Copyright (c) 2002,2003 Henning Brauer. All rights reserved.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <sys/types.h>
32 #include <sys/socket.h>
34 #include <netinet/in.h>
35 #include <netinet/in_systm.h>
36 #include <netinet/ip.h>
37 #include <netinet/ip_icmp.h>
38 #include <netinet/icmp6.h>
39 #include <net/pf/pfvar.h>
40 #include <arpa/inet.h>
41 #include <net/altq/altq.h>
42 #include <net/altq/altq_cbq.h>
43 #include <net/altq/altq_priq.h>
44 #include <net/altq/altq_hfsc.h>
45 #include <net/altq/altq_fairq.h>
61 #include "pfctl_parser.h"
64 static struct pfctl
*pf
= NULL
;
65 static FILE *fin
= NULL
;
67 static int lineno
= 1;
68 static int errors
= 0;
69 static int rulestate
= 0;
70 static u_int16_t returnicmpdefault
=
71 (ICMP_UNREACH
<< 8) | ICMP_UNREACH_PORT
;
72 static u_int16_t returnicmp6default
=
73 (ICMP6_DST_UNREACH
<< 8) | ICMP6_DST_UNREACH_NOPORT
;
74 static int blockpolicy
= PFRULE_DROP
;
75 static int require_order
= 1;
76 static int default_statelock
;
77 static int default_keeppolicy_action
;
78 static struct node_state_opt
*default_keeppolicy_options
;
91 struct node_proto
*next
;
92 struct node_proto
*tail
;
98 struct node_port
*next
;
99 struct node_port
*tail
;
105 struct node_uid
*next
;
106 struct node_uid
*tail
;
112 struct node_gid
*next
;
113 struct node_gid
*tail
;
120 struct node_icmp
*next
;
121 struct node_icmp
*tail
;
124 enum { PF_STATE_OPT_MAX
, PF_STATE_OPT_NOSYNC
, PF_STATE_OPT_SRCTRACK
,
125 PF_STATE_OPT_MAX_SRC_STATES
, PF_STATE_OPT_MAX_SRC_NODES
,
126 PF_STATE_OPT_STATELOCK
, PF_STATE_OPT_TIMEOUT
,
127 PF_STATE_OPT_PICKUPS
};
129 enum { PF_SRCTRACK_NONE
, PF_SRCTRACK
, PF_SRCTRACK_GLOBAL
, PF_SRCTRACK_RULE
};
131 struct node_state_opt
{
134 u_int32_t max_states
;
135 u_int32_t max_src_states
;
136 u_int32_t max_src_nodes
;
138 u_int8_t pickup_mode
;
145 struct node_state_opt
*next
;
146 struct node_state_opt
*tail
;
150 struct node_host
*host
;
151 struct node_port
*port
;
155 char queue
[PF_QNAME_SIZE
];
156 char parent
[PF_QNAME_SIZE
];
157 char ifname
[IFNAMSIZ
];
159 struct node_queue
*next
;
160 struct node_queue
*tail
;
163 struct node_qassign
{
170 #define FOM_FLAGS 0x01
171 #define FOM_ICMP 0x02
173 #define FOM_KEEP 0x08
174 #define FOM_SRCTRACK 0x10
175 struct node_uid
*uid
;
176 struct node_gid
*gid
;
183 struct node_icmp
*icmpspec
;
188 struct node_state_opt
*options
;
193 struct node_qassign queues
;
196 u_int8_t match_tag_not
;
199 struct antispoof_opts
{
205 #define SOM_MINTTL 0x01
206 #define SOM_MAXMSS 0x02
207 #define SOM_FRAGCACHE 0x04
218 #define QOM_BWSPEC 0x01
219 #define QOM_SCHEDULER 0x02
220 #define QOM_PRIORITY 0x04
221 #define QOM_TBRSIZE 0x08
222 #define QOM_QLIMIT 0x10
223 struct node_queue_bw queue_bwspec
;
224 struct node_queue_opt scheduler
;
233 struct node_tinithead init_nodes
;
238 #define POM_TYPE 0x01
239 #define POM_STICKYADDRESS 0x02
243 struct pf_poolhashkey
*key
;
248 struct node_hfsc_opts hfsc_opts
;
249 struct node_fairq_opts fairq_opts
;
251 int yyerror(const char *, ...
);
252 int disallow_table
(struct node_host
*, const char *);
253 int disallow_alias
(struct node_host
*, const char *);
254 int rule_consistent
(struct pf_rule
*);
255 int filter_consistent
(struct pf_rule
*);
256 int nat_consistent
(struct pf_rule
*);
257 int rdr_consistent
(struct pf_rule
*);
258 int process_tabledef
(char *, struct table_opts
*);
260 void expand_label_str
(char *, size_t, const char *, const char *);
261 void expand_label_if
(const char *, char *, size_t, const char *);
262 void expand_label_addr
(const char *, char *, size_t, u_int8_t
,
264 void expand_label_port
(const char *, char *, size_t, struct node_port
*);
265 void expand_label_proto
(const char *, char *, size_t, u_int8_t
);
266 void expand_label_nr
(const char *, char *, size_t);
267 void expand_label
(char *, size_t, const char *, u_int8_t
, struct node_host
*,
268 struct node_port
*, struct node_host
*, struct node_port
*,
270 void expand_rule
(struct pf_rule
*, struct node_if
*, struct node_host
*,
271 struct node_proto
*, struct node_os
*, struct node_host
*,
272 struct node_port
*, struct node_host
*, struct node_port
*,
273 struct node_uid
*, struct node_gid
*, struct node_icmp
*);
274 int expand_altq
(struct pf_altq
*, struct node_if
*, struct node_queue
*,
275 struct node_queue_bw bwspec
, struct node_queue_opt
*);
276 int expand_queue
(struct pf_altq
*, struct node_if
*, struct node_queue
*,
277 struct node_queue_bw
, struct node_queue_opt
*);
279 int check_rulestate
(int);
280 int kw_cmp
(const void *, const void *);
286 int atoul
(char *, u_long
*);
287 int getservice
(char *);
288 int rule_label
(struct pf_rule
*, char *);
290 TAILQ_HEAD
(symhead
, sym
) symhead
= TAILQ_HEAD_INITIALIZER
(symhead
);
292 TAILQ_ENTRY
(sym
) entries
;
300 int symset
(const char *, const char *, int);
301 char *symget
(const char *);
303 void decide_address_family
(struct node_host
*, sa_family_t
*);
304 void remove_invalid_hosts
(struct node_host
**, sa_family_t
*);
305 int invalid_redirect
(struct node_host
*, sa_family_t
);
306 u_int16_t parseicmpspec
(char *, sa_family_t
);
308 TAILQ_HEAD
(loadanchorshead
, loadanchors
)
309 loadanchorshead
= TAILQ_HEAD_INITIALIZER
(loadanchorshead
);
312 TAILQ_ENTRY
(loadanchors
) entries
;
334 struct node_if
*interface
;
335 struct node_proto
*proto
;
336 struct node_icmp
*icmp
;
337 struct node_host
*host
;
339 struct node_port
*port
;
340 struct node_uid
*uid
;
341 struct node_gid
*gid
;
342 struct node_state_opt
*state_opt
;
345 struct peer src
, dst
;
346 struct node_os
*src_os
;
349 struct node_host
*host
;
353 struct pf_poolhashkey
*key
;
356 struct node_host
*host
;
361 struct node_state_opt
*options
;
367 struct pf_poolhashkey
*hashkey
;
368 struct node_queue
*queue
;
369 struct node_queue_opt queue_options
;
370 struct node_queue_bw queue_bwspec
;
371 struct node_qassign qassign
;
372 struct filter_opts filter_opts
;
373 struct antispoof_opts antispoof_opts
;
374 struct queue_opts queue_opts
;
375 struct scrub_opts scrub_opts
;
376 struct table_opts table_opts
;
377 struct pool_opts pool_opts
;
378 struct node_hfsc_opts hfsc_opts
;
379 struct node_fairq_opts fairq_opts
;
384 #define PREPARE_ANCHOR_RULE(r, a) \
386 memset
(&(r
), 0, sizeof
(r
)); \
387 if
(strlcpy
(r.anchorname
, (a
), \
388 sizeof
(r.anchorname
)) >= \
389 sizeof
(r.anchorname
)) { \
390 yyerror("anchor name '%s' too long", \
396 #define DYNIF_MULTIADDR(addr) ((addr).type == PF_ADDR_DYNIFTL && \
397 (!((addr
).iflags
& PFI_AFLAG_NOALIAS
) || \
398 !isdigit
((addr
).v.ifname
[strlen
((addr
).v.ifname
)-1])))
404 %token PASS BLOCK SCRUB RETURN IN OS OUT LOG LOGALL QUICK ON FROM TO FLAGS
405 %token RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE
406 %token ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF
407 %token MINTTL ERROR ALLOWOPTS FASTROUTE FILENAME ROUTETO DUPTO REPLYTO NO LABEL
408 %token NOROUTE FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DROP TABLE
409 %token REASSEMBLE FRAGDROP FRAGCROP ANCHOR NATANCHOR RDRANCHOR BINATANCHOR
410 %token SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY RANDOMID
411 %token REQUIREORDER SYNPROXY FINGERPRINTS NOSYNC DEBUG HOSTID
413 %token BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT PROBABILITY
414 %token ALTQ CBQ PRIQ HFSC FAIRQ BANDWIDTH TBRSIZE LINKSHARE REALTIME UPPERLIMIT
415 %token QUEUE PRIORITY QLIMIT HOGS BUCKETS
417 %token PICKUPS NOPICKUPS HASHONLY
418 %token STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE
419 %token TAGGED TAG IFBOUND GRBOUND FLOATING STATEPOLICY KEEPPOLICY
420 %token
<v.
string> STRING
421 %token
<v.i
> PORTBINARY
422 %type
<v.interface
> interface if_list if_item_not if_item
423 %type
<v.number
> number icmptype icmp6type uid gid
424 %type
<v.number
> tos not yesno natpass
425 %type
<v.i
> no dir log af fragcache sourcetrack
426 %type
<v.i
> unaryop statelock
427 %type
<v.b
> action nataction flags flag blockspec
428 %type
<v.range
> port rport
429 %type
<v.hashkey
> hashkey
430 %type
<v.proto
> proto proto_list proto_item
431 %type
<v.icmp
> icmpspec
432 %type
<v.icmp
> icmp_list icmp_item
433 %type
<v.icmp
> icmp6_list icmp6_item
434 %type
<v.fromto
> fromto
435 %type
<v.peer
> ipportspec from to
436 %type
<v.host
> ipspec xhost host dynaddr host_list
437 %type
<v.host
> redir_host_list redirspec
438 %type
<v.host
> route_host route_host_list routespec
439 %type
<v.os
> os xos os_list
440 %type
<v.port
> portspec port_list port_item
441 %type
<v.uid
> uids uid_list uid_item
442 %type
<v.gid
> gids gid_list gid_item
443 %type
<v.route
> route
444 %type
<v.redirection
> redirection redirpool
445 %type
<v.
string> label
string tag
446 %type
<v.keep_state
> keep
447 %type
<v.state_opt
> state_opt_spec state_opt_list state_opt_item
448 %type
<v.logquick
> logquick
449 %type
<v.interface
> antispoof_ifspc antispoof_iflst
450 %type
<v.qassign
> qname
451 %type
<v.queue
> qassign qassign_list qassign_item
452 %type
<v.queue_options
> scheduler
453 %type
<v.number
> cbqflags_list cbqflags_item
454 %type
<v.number
> priqflags_list priqflags_item
455 %type
<v.hfsc_opts
> hfscopts_list hfscopts_item hfsc_opts
456 %type
<v.fairq_opts
> fairqopts_list fairqopts_item fairq_opts
457 %type
<v.queue_bwspec
> bandwidth
458 %type
<v.filter_opts
> filter_opts filter_opt filter_opts_l
459 %type
<v.antispoof_opts
> antispoof_opts antispoof_opt antispoof_opts_l
460 %type
<v.queue_opts
> queue_opts queue_opt queue_opts_l
461 %type
<v.scrub_opts
> scrub_opts scrub_opt scrub_opts_l
462 %type
<v.table_opts
> table_opts table_opt table_opts_l
463 %type
<v.pool_opts
> pool_opts pool_opt pool_opts_l
466 ruleset
: /* empty */
468 | ruleset option
'\n'
469 | ruleset scrubrule
'\n'
470 | ruleset natrule
'\n'
471 | ruleset binatrule
'\n'
472 | ruleset pfrule
'\n'
473 | ruleset anchorrule
'\n'
474 | ruleset loadrule
'\n'
475 | ruleset altqif
'\n'
476 | ruleset queuespec
'\n'
477 | ruleset varset
'\n'
478 | ruleset antispoof
'\n'
479 | ruleset tabledef
'\n'
480 | ruleset
error '\n' { errors
++; }
483 option
: SET OPTIMIZATION STRING
{
484 if
(check_rulestate
(PFCTL_STATE_OPTION
)) {
488 if
(pfctl_set_optimization
(pf
, $3) != 0) {
489 yyerror("unknown optimization %s", $3);
495 | SET TIMEOUT timeout_spec
496 | SET TIMEOUT
'{' timeout_list
'}'
497 | SET LIMIT limit_spec
498 | SET LIMIT
'{' limit_list
'}'
499 | SET LOGINTERFACE STRING
{
500 if
(check_rulestate
(PFCTL_STATE_OPTION
)) {
504 if
((ifa_exists
($3, 0) == NULL
) && strcmp
($3, "none")) {
505 yyerror("interface %s doesn't exist", $3);
509 if
(pfctl_set_logif
(pf
, $3) != 0) {
510 yyerror("error setting loginterface %s", $3);
516 | SET HOSTID number
{
518 yyerror("hostid must be non-zero");
521 if
(pfctl_set_hostid
(pf
, $3) != 0) {
522 yyerror("error setting loginterface %08x", $3);
526 | SET BLOCKPOLICY DROP
{
527 if
(pf
->opts
& PF_OPT_VERBOSE
)
528 printf
("set block-policy drop\n");
529 if
(check_rulestate
(PFCTL_STATE_OPTION
))
531 blockpolicy
= PFRULE_DROP
;
533 | SET BLOCKPOLICY RETURN
{
534 if
(pf
->opts
& PF_OPT_VERBOSE
)
535 printf
("set block-policy return\n");
536 if
(check_rulestate
(PFCTL_STATE_OPTION
))
538 blockpolicy
= PFRULE_RETURN
;
540 | SET REQUIREORDER yesno
{
541 if
(pf
->opts
& PF_OPT_VERBOSE
)
542 printf
("set require-order %s\n",
543 $3 == 1 ?
"yes" : "no");
546 | SET FINGERPRINTS STRING
{
547 if
(pf
->opts
& PF_OPT_VERBOSE
)
548 printf
("fingerprints %s\n", $3);
549 if
(check_rulestate
(PFCTL_STATE_OPTION
)) {
553 if
(pfctl_file_fingerprints
(pf
->dev
, pf
->opts
, $3)) {
554 yyerror("error loading fingerprints %s", $3);
560 | SET STATEPOLICY statelock
{
561 if
(pf
->opts
& PF_OPT_VERBOSE
)
564 printf
("set state-policy floating\n");
567 printf
("set state-policy if-bound\n");
570 printf
("set state-policy "
574 default_statelock
= $3;
576 | SET KEEPPOLICY keep
{
577 if
(pf
->opts
& PF_OPT_VERBOSE
)
578 printf
("A default keeppolicy was set\n");
579 default_keeppolicy_action
= $3.action
;
580 default_keeppolicy_options
= $3.options
;
583 if
(check_rulestate
(PFCTL_STATE_OPTION
)) {
587 if
(pfctl_set_debug
(pf
, $3) != 0) {
588 yyerror("error setting debuglevel %s", $3);
596 string : string STRING
{
597 if
(asprintf
(&$$
, "%s %s", $1, $2) == -1)
598 err
(1, "string: asprintf");
605 varset
: STRING
'=' string {
606 if
(pf
->opts
& PF_OPT_VERBOSE
)
607 printf
("%s = \"%s\"\n", $1, $3);
608 if
(symset
($1, $3, 0) == -1)
609 err
(1, "cannot store variable %s", $1);
615 anchorrule
: ANCHOR
string dir interface af proto fromto filter_opts
{
618 if
(check_rulestate
(PFCTL_STATE_FILTER
)) {
623 PREPARE_ANCHOR_RULE
(r
, $2);
629 if
(strlcpy
(r.match_tagname
, $8.match_tag
,
630 PF_TAG_NAME_SIZE
) >= PF_TAG_NAME_SIZE
) {
631 yyerror("tag too long, max %u chars",
632 PF_TAG_NAME_SIZE
- 1);
635 r.match_tag_not
= $8.match_tag_not
;
637 decide_address_family
($7.src.host
, &r.af
);
638 decide_address_family
($7.dst.host
, &r.af
);
640 expand_rule
(&r
, $4, NULL
, $6, $7.src_os
,
641 $7.src.host
, $7.src.port
, $7.dst.host
, $7.dst.port
,
644 | NATANCHOR
string interface af proto fromto
{
647 if
(check_rulestate
(PFCTL_STATE_NAT
)) {
652 PREPARE_ANCHOR_RULE
(r
, $2);
657 decide_address_family
($6.src.host
, &r.af
);
658 decide_address_family
($6.dst.host
, &r.af
);
660 expand_rule
(&r
, $3, NULL
, $5, $6.src_os
,
661 $6.src.host
, $6.src.port
, $6.dst.host
, $6.dst.port
,
664 | RDRANCHOR
string interface af proto fromto
{
667 if
(check_rulestate
(PFCTL_STATE_NAT
)) {
672 PREPARE_ANCHOR_RULE
(r
, $2);
677 decide_address_family
($6.src.host
, &r.af
);
678 decide_address_family
($6.dst.host
, &r.af
);
680 if
($6.src.port
!= NULL
) {
681 yyerror("source port parameter not supported"
685 if
($6.dst.port
!= NULL
) {
686 if
($6.dst.port
->next
!= NULL
) {
687 yyerror("destination port list "
688 "expansion not supported in "
691 } else if
($6.dst.port
->op
!= PF_OP_EQ
) {
692 yyerror("destination port operators"
693 " not supported in rdr-anchor");
696 r.dst.port
[0] = $6.dst.port
->port
[0];
697 r.dst.port
[1] = $6.dst.port
->port
[1];
698 r.dst.port_op
= $6.dst.port
->op
;
701 expand_rule
(&r
, $3, NULL
, $5, $6.src_os
,
702 $6.src.host
, $6.src.port
, $6.dst.host
, $6.dst.port
,
705 | BINATANCHOR
string interface af proto fromto
{
708 if
(check_rulestate
(PFCTL_STATE_NAT
)) {
713 PREPARE_ANCHOR_RULE
(r
, $2);
718 if
($5->next
!= NULL
) {
719 yyerror("proto list expansion"
720 " not supported in binat-anchor");
727 if
($6.src.host
!= NULL ||
$6.src.port
!= NULL ||
728 $6.dst.host
!= NULL ||
$6.dst.port
!= NULL
) {
729 yyerror("fromto parameter not supported"
734 decide_address_family
($6.src.host
, &r.af
);
735 decide_address_family
($6.dst.host
, &r.af
);
737 pfctl_add_rule
(pf
, &r
);
741 loadrule
: LOAD ANCHOR
string FROM
string {
743 struct loadanchors
*loadanchor
;
745 t
= strsep
(&$3, ":");
746 if
(*t
== '\0' ||
$3 == NULL ||
*$3 == '\0') {
747 yyerror("anchor '%s' invalid\n", $3);
751 if
(strlen
(t
) >= PF_ANCHOR_NAME_SIZE
) {
752 yyerror("anchorname %s too long, max %u\n",
753 t
, PF_ANCHOR_NAME_SIZE
- 1);
757 if
(strlen
($3) >= PF_RULESET_NAME_SIZE
) {
758 yyerror("rulesetname %s too long, max %u\n",
759 $3, PF_RULESET_NAME_SIZE
- 1);
764 loadanchor
= calloc
(1, sizeof
(struct loadanchors
));
765 if
(loadanchor
== NULL
)
766 err
(1, "loadrule: calloc");
767 if
((loadanchor
->anchorname
= strdup
(t
)) == NULL
)
768 err
(1, "loadrule: strdup");
769 if
((loadanchor
->rulesetname
= strdup
($3)) == NULL
)
770 err
(1, "loadrule: strdup");
771 if
((loadanchor
->filename
= strdup
($5)) == NULL
)
772 err
(1, "loadrule: strdup");
774 TAILQ_INSERT_TAIL
(&loadanchorshead
, loadanchor
,
777 free
(t
); /* not $3 */
781 scrubrule
: SCRUB dir logquick interface af proto fromto scrub_opts
785 if
(check_rulestate
(PFCTL_STATE_SCRUB
))
788 memset
(&r
, 0, sizeof
(r
));
795 yyerror("scrub rules do not support 'quick'");
801 r.rule_flag |
= PFRULE_NODF
;
803 r.rule_flag |
= PFRULE_RANDOMID
;
804 if
($8.reassemble_tcp
) {
805 if
(r.direction
!= PF_INOUT
) {
806 yyerror("reassemble tcp rules can not "
807 "specify direction");
810 r.rule_flag |
= PFRULE_REASSEMBLE_TCP
;
813 r.min_ttl
= $8.minttl
;
815 r.max_mss
= $8.maxmss
;
817 r.rule_flag |
= $8.fragcache
;
819 expand_rule
(&r
, $4, NULL
, $6, $7.src_os
,
820 $7.src.host
, $7.src.port
, $7.dst.host
, $7.dst.port
,
826 bzero
(&scrub_opts
, sizeof scrub_opts
);
831 bzero
(&scrub_opts
, sizeof scrub_opts
);
836 scrub_opts_l
: scrub_opts_l scrub_opt
841 if
(scrub_opts.nodf
) {
842 yyerror("no-df cannot be respecified");
848 if
(scrub_opts.marker
& SOM_MINTTL
) {
849 yyerror("min-ttl cannot be respecified");
853 yyerror("illegal min-ttl value %d", $2);
856 scrub_opts.marker |
= SOM_MINTTL
;
857 scrub_opts.minttl
= $2;
860 if
(scrub_opts.marker
& SOM_MAXMSS
) {
861 yyerror("max-mss cannot be respecified");
865 yyerror("illegal max-mss value %d", $2);
868 scrub_opts.marker |
= SOM_MAXMSS
;
869 scrub_opts.maxmss
= $2;
872 if
(scrub_opts.marker
& SOM_FRAGCACHE
) {
873 yyerror("fragcache cannot be respecified");
876 scrub_opts.marker |
= SOM_FRAGCACHE
;
877 scrub_opts.fragcache
= $1;
879 | REASSEMBLE STRING
{
880 if
(strcasecmp
($2, "tcp") != 0) {
885 if
(scrub_opts.reassemble_tcp
) {
886 yyerror("reassemble tcp cannot be respecified");
889 scrub_opts.reassemble_tcp
= 1;
892 if
(scrub_opts.randomid
) {
893 yyerror("random-id cannot be respecified");
896 scrub_opts.randomid
= 1;
900 fragcache
: FRAGMENT REASSEMBLE
{ $$
= 0; /* default */ }
901 | FRAGMENT FRAGCROP
{ $$
= PFRULE_FRAGCROP
; }
902 | FRAGMENT FRAGDROP
{ $$
= PFRULE_FRAGDROP
; }
905 antispoof
: ANTISPOOF logquick antispoof_ifspc af antispoof_opts
{
907 struct node_host
*h
= NULL
;
908 struct node_if
*i
, *j
;
910 if
(check_rulestate
(PFCTL_STATE_FILTER
))
913 for
(i
= $3; i
; i
= i
->next
) {
914 bzero
(&r
, sizeof
(r
));
921 if
(rule_label
(&r
, $5.label
))
923 j
= calloc
(1, sizeof
(struct node_if
));
925 err
(1, "antispoof: calloc");
926 if
(strlcpy
(j
->ifname
, i
->ifname
,
927 sizeof
(j
->ifname
)) >= sizeof
(j
->ifname
)) {
929 yyerror("interface name too long");
933 h
= ifa_lookup
(j
->ifname
, PFI_AFLAG_NETWORK
);
936 expand_rule
(&r
, j
, NULL
, NULL
, NULL
, h
,
937 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
939 if
((i
->ifa_flags
& IFF_LOOPBACK
) == 0) {
940 bzero
(&r
, sizeof
(r
));
947 if
(rule_label
(&r
, $5.label
))
949 h
= ifa_lookup
(i
->ifname
, 0);
951 expand_rule
(&r
, NULL
, NULL
,
952 NULL
, NULL
, h
, NULL
, NULL
,
953 NULL
, NULL
, NULL
, NULL
);
960 antispoof_ifspc
: FOR if_item
{ $$
= $2; }
961 | FOR
'{' antispoof_iflst
'}' { $$
= $3; }
964 antispoof_iflst
: if_item
{ $$
= $1; }
965 | antispoof_iflst comma if_item
{
972 antispoof_opts
: { bzero
(&antispoof_opts
, sizeof antispoof_opts
); }
974 { $$
= antispoof_opts
; }
976 bzero
(&antispoof_opts
, sizeof antispoof_opts
);
981 antispoof_opts_l
: antispoof_opts_l antispoof_opt
985 antispoof_opt
: label
{
986 if
(antispoof_opts.label
) {
987 yyerror("label cannot be redefined");
990 antispoof_opts.label
= $1;
994 not
: '!' { $$
= 1; }
995 |
/* empty */ { $$
= 0; }
998 tabledef
: TABLE
'<' STRING
'>' table_opts
{
999 struct node_host
*h
, *nh
;
1000 struct node_tinit
*ti
, *nti
;
1002 if
(strlen
($3) >= PF_TABLE_NAME_SIZE
) {
1003 yyerror("table name too long, max %d chars",
1004 PF_TABLE_NAME_SIZE
- 1);
1008 if
(pf
->loadopt
& PFCTL_FLAG_TABLE
)
1009 if
(process_tabledef
($3, &$5)) {
1014 for
(ti
= SIMPLEQ_FIRST
(&$5.init_nodes
);
1015 ti
!= SIMPLEQ_END
(&$5.init_nodes
); ti
= nti
) {
1018 for
(h
= ti
->host
; h
!= NULL
; h
= nh
) {
1022 nti
= SIMPLEQ_NEXT
(ti
, entries
);
1029 bzero
(&table_opts
, sizeof table_opts
);
1030 SIMPLEQ_INIT
(&table_opts.init_nodes
);
1033 { $$
= table_opts
; }
1036 bzero
(&table_opts
, sizeof table_opts
);
1037 SIMPLEQ_INIT
(&table_opts.init_nodes
);
1042 table_opts_l
: table_opts_l table_opt
1046 table_opt
: STRING
{
1047 if
(!strcmp
($1, "const"))
1048 table_opts.flags |
= PFR_TFLAG_CONST
;
1049 else if
(!strcmp
($1, "persist"))
1050 table_opts.flags |
= PFR_TFLAG_PERSIST
;
1057 |
'{' '}' { table_opts.init_addr
= 1; }
1058 |
'{' host_list
'}' {
1059 struct node_host
*n
;
1060 struct node_tinit
*ti
;
1062 for
(n
= $2; n
!= NULL
; n
= n
->next
) {
1063 switch
(n
->addr.type
) {
1064 case PF_ADDR_ADDRMASK
:
1066 case PF_ADDR_DYNIFTL
:
1067 yyerror("dynamic addresses are not "
1068 "permitted inside tables");
1071 yyerror("tables cannot contain tables");
1073 case PF_ADDR_NOROUTE
:
1074 yyerror("\"no-route\" is not permitted "
1078 yyerror("unknown address type %d",
1083 if
(!(ti
= calloc
(1, sizeof
(*ti
))))
1084 err
(1, "table_opt: calloc");
1086 SIMPLEQ_INSERT_TAIL
(&table_opts.init_nodes
, ti
,
1088 table_opts.init_addr
= 1;
1091 struct node_tinit
*ti
;
1093 if
(!(ti
= calloc
(1, sizeof
(*ti
))))
1094 err
(1, "table_opt: calloc");
1096 SIMPLEQ_INSERT_TAIL
(&table_opts.init_nodes
, ti
,
1098 table_opts.init_addr
= 1;
1102 altqif
: ALTQ interface queue_opts QUEUE qassign
{
1105 if
(check_rulestate
(PFCTL_STATE_QUEUE
))
1108 memset
(&a
, 0, sizeof
(a
));
1109 if
($3.scheduler.qtype
== ALTQT_NONE
) {
1110 yyerror("no scheduler specified!");
1113 a.scheduler
= $3.scheduler.qtype
;
1114 a.qlimit
= $3.qlimit
;
1115 a.tbrsize
= $3.tbrsize
;
1117 yyerror("no child queues specified");
1120 if
(expand_altq
(&a
, $2, $5, $3.queue_bwspec
,
1126 queuespec
: QUEUE STRING interface queue_opts qassign
{
1129 if
(check_rulestate
(PFCTL_STATE_QUEUE
)) {
1134 memset
(&a
, 0, sizeof
(a
));
1136 if
(strlcpy
(a.qname
, $2, sizeof
(a.qname
)) >=
1138 yyerror("queue name too long (max "
1139 "%d chars)", PF_QNAME_SIZE
-1);
1145 yyerror("cannot specify tbrsize for queue");
1148 if
($4.priority
> 255) {
1149 yyerror("priority out of range: max 255");
1152 a.priority
= $4.priority
;
1153 a.qlimit
= $4.qlimit
;
1154 a.scheduler
= $4.scheduler.qtype
;
1155 if
(expand_queue
(&a
, $3, $5, $4.queue_bwspec
,
1157 yyerror("errors in queue definition");
1164 bzero
(&queue_opts
, sizeof queue_opts
);
1165 queue_opts.priority
= DEFAULT_PRIORITY
;
1166 queue_opts.qlimit
= DEFAULT_QLIMIT
;
1167 queue_opts.scheduler.qtype
= ALTQT_NONE
;
1168 queue_opts.queue_bwspec.bw_percent
= 100;
1171 { $$
= queue_opts
; }
1173 bzero
(&queue_opts
, sizeof queue_opts
);
1174 queue_opts.priority
= DEFAULT_PRIORITY
;
1175 queue_opts.qlimit
= DEFAULT_QLIMIT
;
1176 queue_opts.scheduler.qtype
= ALTQT_NONE
;
1177 queue_opts.queue_bwspec.bw_percent
= 100;
1182 queue_opts_l
: queue_opts_l queue_opt
1186 queue_opt
: BANDWIDTH bandwidth
{
1187 if
(queue_opts.marker
& QOM_BWSPEC
) {
1188 yyerror("bandwidth cannot be respecified");
1191 queue_opts.marker |
= QOM_BWSPEC
;
1192 queue_opts.queue_bwspec
= $2;
1195 if
(queue_opts.marker
& QOM_PRIORITY
) {
1196 yyerror("priority cannot be respecified");
1200 yyerror("priority out of range: max 255");
1203 queue_opts.marker |
= QOM_PRIORITY
;
1204 queue_opts.priority
= $2;
1207 if
(queue_opts.marker
& QOM_QLIMIT
) {
1208 yyerror("qlimit cannot be respecified");
1212 yyerror("qlimit out of range: max 65535");
1215 queue_opts.marker |
= QOM_QLIMIT
;
1216 queue_opts.qlimit
= $2;
1219 if
(queue_opts.marker
& QOM_SCHEDULER
) {
1220 yyerror("scheduler cannot be respecified");
1223 queue_opts.marker |
= QOM_SCHEDULER
;
1224 queue_opts.scheduler
= $1;
1227 if
(queue_opts.marker
& QOM_TBRSIZE
) {
1228 yyerror("tbrsize cannot be respecified");
1232 yyerror("tbrsize too big: max 65535");
1235 queue_opts.marker |
= QOM_TBRSIZE
;
1236 queue_opts.tbrsize
= $2;
1240 bandwidth
: STRING
{
1246 bps
= strtod
($1, &cp
);
1248 if
(!strcmp
(cp
, "b"))
1250 else if
(!strcmp
(cp
, "Kb"))
1252 else if
(!strcmp
(cp
, "Mb"))
1254 else if
(!strcmp
(cp
, "Gb"))
1255 bps
*= 1000 * 1000 * 1000;
1256 else if
(!strcmp
(cp
, "%")) {
1257 if
(bps
< 0 || bps
> 100) {
1258 yyerror("bandwidth spec "
1263 $$.bw_percent
= bps
;
1266 yyerror("unknown unit %s", cp
);
1272 $$.bw_absolute
= (u_int32_t
)bps
;
1277 $$.qtype
= ALTQT_CBQ
;
1278 $$.data.cbq_opts.flags
= 0;
1280 | CBQ
'(' cbqflags_list
')' {
1281 $$.qtype
= ALTQT_CBQ
;
1282 $$.data.cbq_opts.flags
= $3;
1285 $$.qtype
= ALTQT_PRIQ
;
1286 $$.data.priq_opts.flags
= 0;
1288 | PRIQ
'(' priqflags_list
')' {
1289 $$.qtype
= ALTQT_PRIQ
;
1290 $$.data.priq_opts.flags
= $3;
1293 $$.qtype
= ALTQT_HFSC
;
1294 bzero
(&$$.data.hfsc_opts
,
1295 sizeof
(struct node_hfsc_opts
));
1297 | HFSC
'(' hfsc_opts
')' {
1298 $$.qtype
= ALTQT_HFSC
;
1299 $$.data.hfsc_opts
= $3;
1302 $$.qtype
= ALTQT_FAIRQ
;
1303 bzero
(&$$.data.fairq_opts
,
1304 sizeof
(struct node_fairq_opts
));
1306 | FAIRQ
'(' fairq_opts
')' {
1307 $$.qtype
= ALTQT_FAIRQ
;
1308 $$.data.fairq_opts
= $3;
1312 cbqflags_list
: cbqflags_item
{ $$ |
= $1; }
1313 | cbqflags_list comma cbqflags_item
{ $$ |
= $3; }
1316 cbqflags_item
: STRING
{
1317 if
(!strcmp
($1, "default"))
1318 $$
= CBQCLF_DEFCLASS
;
1319 else if
(!strcmp
($1, "borrow"))
1321 else if
(!strcmp
($1, "red"))
1323 else if
(!strcmp
($1, "ecn"))
1324 $$
= CBQCLF_RED|CBQCLF_ECN
;
1325 else if
(!strcmp
($1, "rio"))
1328 yyerror("unknown cbq flag \"%s\"", $1);
1336 priqflags_list
: priqflags_item
{ $$ |
= $1; }
1337 | priqflags_list comma priqflags_item
{ $$ |
= $3; }
1340 priqflags_item
: STRING
{
1341 if
(!strcmp
($1, "default"))
1342 $$
= PRCF_DEFAULTCLASS
;
1343 else if
(!strcmp
($1, "red"))
1345 else if
(!strcmp
($1, "ecn"))
1346 $$
= PRCF_RED|PRCF_ECN
;
1347 else if
(!strcmp
($1, "rio"))
1350 yyerror("unknown priq flag \"%s\"", $1);
1360 sizeof
(struct node_hfsc_opts
));
1367 hfscopts_list
: hfscopts_item
1368 | hfscopts_list comma hfscopts_item
1371 hfscopts_item
: LINKSHARE bandwidth
{
1372 if
(hfsc_opts.linkshare.used
) {
1373 yyerror("linkshare already specified");
1376 hfsc_opts.linkshare.m2
= $2;
1377 hfsc_opts.linkshare.used
= 1;
1379 | LINKSHARE
'(' bandwidth number bandwidth
')' {
1380 if
(hfsc_opts.linkshare.used
) {
1381 yyerror("linkshare already specified");
1384 hfsc_opts.linkshare.m1
= $3;
1385 hfsc_opts.linkshare.d
= $4;
1386 hfsc_opts.linkshare.m2
= $5;
1387 hfsc_opts.linkshare.used
= 1;
1389 | REALTIME bandwidth
{
1390 if
(hfsc_opts.realtime.used
) {
1391 yyerror("realtime already specified");
1394 hfsc_opts.realtime.m2
= $2;
1395 hfsc_opts.realtime.used
= 1;
1397 | REALTIME
'(' bandwidth number bandwidth
')' {
1398 if
(hfsc_opts.realtime.used
) {
1399 yyerror("realtime already specified");
1402 hfsc_opts.realtime.m1
= $3;
1403 hfsc_opts.realtime.d
= $4;
1404 hfsc_opts.realtime.m2
= $5;
1405 hfsc_opts.realtime.used
= 1;
1407 | UPPERLIMIT bandwidth
{
1408 if
(hfsc_opts.upperlimit.used
) {
1409 yyerror("upperlimit already specified");
1412 hfsc_opts.upperlimit.m2
= $2;
1413 hfsc_opts.upperlimit.used
= 1;
1415 | UPPERLIMIT
'(' bandwidth number bandwidth
')' {
1416 if
(hfsc_opts.upperlimit.used
) {
1417 yyerror("upperlimit already specified");
1420 hfsc_opts.upperlimit.m1
= $3;
1421 hfsc_opts.upperlimit.d
= $4;
1422 hfsc_opts.upperlimit.m2
= $5;
1423 hfsc_opts.upperlimit.used
= 1;
1426 if
(!strcmp
($1, "default"))
1427 hfsc_opts.flags |
= HFCF_DEFAULTCLASS
;
1428 else if
(!strcmp
($1, "red"))
1429 hfsc_opts.flags |
= HFCF_RED
;
1430 else if
(!strcmp
($1, "ecn"))
1431 hfsc_opts.flags |
= HFCF_RED|HFCF_ECN
;
1432 else if
(!strcmp
($1, "rio"))
1433 hfsc_opts.flags |
= HFCF_RIO
;
1435 yyerror("unknown hfsc flag \"%s\"", $1);
1445 sizeof
(struct node_fairq_opts
));
1452 fairqopts_list
: fairqopts_item
1453 | fairqopts_list comma fairqopts_item
1456 fairqopts_item
: LINKSHARE bandwidth
{
1457 if
(fairq_opts.linkshare.used
) {
1458 yyerror("linkshare already specified");
1461 fairq_opts.linkshare.m2
= $2;
1462 fairq_opts.linkshare.used
= 1;
1464 | LINKSHARE
'(' bandwidth number bandwidth
')' {
1465 if
(fairq_opts.linkshare.used
) {
1466 yyerror("linkshare already specified");
1469 fairq_opts.linkshare.m1
= $3;
1470 fairq_opts.linkshare.d
= $4;
1471 fairq_opts.linkshare.m2
= $5;
1472 fairq_opts.linkshare.used
= 1;
1475 fairq_opts.hogs_bw
= $2;
1478 fairq_opts.nbuckets
= $2;
1481 if
(!strcmp
($1, "default"))
1482 fairq_opts.flags |
= FARF_DEFAULTCLASS
;
1483 else if
(!strcmp
($1, "red"))
1484 fairq_opts.flags |
= FARF_RED
;
1485 else if
(!strcmp
($1, "ecn"))
1486 fairq_opts.flags |
= FARF_RED|FARF_ECN
;
1487 else if
(!strcmp
($1, "rio"))
1488 fairq_opts.flags |
= FARF_RIO
;
1490 yyerror("unknown fairq flag \"%s\"", $1);
1498 qassign
: /* empty */ { $$
= NULL
; }
1499 | qassign_item
{ $$
= $1; }
1500 |
'{' qassign_list
'}' { $$
= $2; }
1503 qassign_list
: qassign_item
{ $$
= $1; }
1504 | qassign_list comma qassign_item
{
1505 $1->tail
->next
= $3;
1511 qassign_item
: STRING
{
1512 $$
= calloc
(1, sizeof
(struct node_queue
));
1514 err
(1, "qassign_item: calloc");
1515 if
(strlcpy
($$
->queue
, $1, sizeof
($$
->queue
)) >=
1516 sizeof
($$
->queue
)) {
1517 yyerror("queue name '%s' too long (max "
1518 "%d chars)", $1, sizeof
($$
->queue
)-1);
1529 pfrule
: action dir logquick interface route af proto fromto
1533 struct node_state_opt
*o
;
1534 struct node_proto
*proto
;
1539 if
(check_rulestate
(PFCTL_STATE_FILTER
))
1542 memset
(&r
, 0, sizeof
(r
));
1546 case PFRULE_RETURNRST
:
1547 r.rule_flag |
= PFRULE_RETURNRST
;
1548 r.return_ttl
= $1.w
;
1550 case PFRULE_RETURNICMP
:
1551 r.rule_flag |
= PFRULE_RETURNICMP
;
1552 r.return_icmp
= $1.w
;
1553 r.return_icmp6
= $1.w2
;
1556 r.rule_flag |
= PFRULE_RETURN
;
1557 r.return_icmp
= $1.w
;
1558 r.return_icmp6
= $1.w2
;
1568 if
(strlcpy
(r.tagname
, $9.tag
,
1569 PF_TAG_NAME_SIZE
) >= PF_TAG_NAME_SIZE
) {
1570 yyerror("tag too long, max %u chars",
1571 PF_TAG_NAME_SIZE
- 1);
1575 if
(strlcpy
(r.match_tagname
, $9.match_tag
,
1576 PF_TAG_NAME_SIZE
) >= PF_TAG_NAME_SIZE
) {
1577 yyerror("tag too long, max %u chars",
1578 PF_TAG_NAME_SIZE
- 1);
1581 r.match_tag_not
= $9.match_tag_not
;
1582 r.flags
= $9.flags.b1
;
1583 r.flagset
= $9.flags.b2
;
1584 if
(rule_label
(&r
, $9.label
))
1587 if
($9.flags.b1 ||
$9.flags.b2 ||
$8.src_os
) {
1588 for
(proto
= $7; proto
!= NULL
&&
1589 proto
->proto
!= IPPROTO_TCP
;
1590 proto
= proto
->next
)
1592 if
(proto
== NULL
&& $7 != NULL
) {
1593 if
($9.flags.b1 ||
$9.flags.b2
)
1595 "flags only apply to tcp");
1598 "OS fingerprinting only "
1603 if
(($9.flags.b1
& parse_flags
("S")) == 0 &&
1605 yyerror("OS fingerprinting requires "
1606 "the SYN TCP flag (flags S/SA)");
1614 if
(filter_opts.marker
& FOM_KEEP
) {
1615 r.keep_state
= $9.keep.action
;
1616 o
= $9.keep.options
;
1618 } else if
(r.action
== PF_PASS
) {
1619 r.keep_state
= default_keeppolicy_action
;
1620 o
= default_keeppolicy_options
;
1627 struct node_state_opt
*p
= o
;
1630 case PF_STATE_OPT_MAX
:
1632 yyerror("state option 'max' "
1633 "multiple definitions");
1636 r.max_states
= o
->data.max_states
;
1638 case PF_STATE_OPT_NOSYNC
:
1639 if
(r.rule_flag
& PFRULE_NOSYNC
) {
1640 yyerror("state option 'sync' "
1641 "multiple definitions");
1644 r.rule_flag |
= PFRULE_NOSYNC
;
1646 case PF_STATE_OPT_SRCTRACK
:
1648 yyerror("state option "
1650 "multiple definitions");
1653 srctrack
= o
->data.src_track
;
1655 case PF_STATE_OPT_MAX_SRC_STATES
:
1656 if
(r.max_src_states
) {
1657 yyerror("state option "
1659 "multiple definitions");
1662 if
(o
->data.max_src_nodes
== 0) {
1663 yyerror("'max-src-states' must "
1668 o
->data.max_src_states
;
1669 r.rule_flag |
= PFRULE_SRCTRACK
;
1671 case PF_STATE_OPT_MAX_SRC_NODES
:
1672 if
(r.max_src_nodes
) {
1673 yyerror("state option "
1675 "multiple definitions");
1678 if
(o
->data.max_src_nodes
== 0) {
1679 yyerror("'max-src-nodes' must "
1684 o
->data.max_src_nodes
;
1685 r.rule_flag |
= PFRULE_SRCTRACK |
1686 PFRULE_RULESRCTRACK
;
1688 case PF_STATE_OPT_STATELOCK
:
1690 yyerror("state locking option: "
1691 "multiple definitions");
1695 r.rule_flag |
= o
->data.statelock
;
1697 case PF_STATE_OPT_TIMEOUT
:
1698 if
(r.timeout
[o
->data.timeout.number
]) {
1699 yyerror("state timeout %s "
1700 "multiple definitions",
1701 pf_timeouts
[o
->data.
1702 timeout.number
].name
);
1705 r.timeout
[o
->data.timeout.number
] =
1706 o
->data.timeout.seconds
;
1708 case PF_STATE_OPT_PICKUPS
:
1709 r.pickup_mode
= o
->data.pickup_mode
;
1718 * 'flags S/SA' by default on stateful rules if
1719 * the pickup mode is unspecified or disabled.
1721 * If the pickup mode is enabled or hashonly we
1722 * want to create state regardless of the flags.
1724 if
(!r.action
&& !r.flags
&& !r.flagset
&&
1725 !$9.fragment
&& !($9.marker
& FOM_FLAGS
) &&
1727 switch
(r.pickup_mode
) {
1728 case PF_PICKUPS_UNSPECIFIED
:
1729 case PF_PICKUPS_DISABLED
:
1730 r.flags
= parse_flags
("S");
1731 r.flagset
= parse_flags
("SA");
1733 case PF_PICKUPS_HASHONLY
:
1734 case PF_PICKUPS_ENABLED
:
1735 /* no flag restrictions */
1741 if
(srctrack
== PF_SRCTRACK_GLOBAL
&&
1743 yyerror("'max-src-nodes' is "
1744 "incompatible with "
1745 "'source-track global'");
1748 r.rule_flag |
= PFRULE_SRCTRACK
;
1749 if
(srctrack
== PF_SRCTRACK_RULE
)
1750 r.rule_flag |
= PFRULE_RULESRCTRACK
;
1752 if
(r.keep_state
&& !statelock
)
1753 r.rule_flag |
= default_statelock
;
1756 r.rule_flag |
= PFRULE_FRAGMENT
;
1757 r.allow_opts
= $9.allowopts
;
1759 decide_address_family
($8.src.host
, &r.af
);
1760 decide_address_family
($8.dst.host
, &r.af
);
1764 yyerror("direction must be explicit "
1765 "with rules that specify routing");
1769 r.rpool.opts
= $5.pool_opts
;
1771 memcpy
(&r.rpool.key
, $5.key
,
1772 sizeof
(struct pf_poolhashkey
));
1774 if
(r.rt
&& r.rt
!= PF_FASTROUTE
) {
1775 decide_address_family
($5.host
, &r.af
);
1776 remove_invalid_hosts
(&$5.host
, &r.af
);
1777 if
($5.host
== NULL
) {
1778 yyerror("no routing address with "
1779 "matching address family found.");
1782 if
((r.rpool.opts
& PF_POOL_TYPEMASK
) ==
1783 PF_POOL_NONE
&& ($5.host
->next
!= NULL ||
1784 $5.host
->addr.type
== PF_ADDR_TABLE ||
1785 DYNIF_MULTIADDR
($5.host
->addr
)))
1786 r.rpool.opts |
= PF_POOL_ROUNDROBIN
;
1787 if
((r.rpool.opts
& PF_POOL_TYPEMASK
) !=
1788 PF_POOL_ROUNDROBIN
&&
1789 disallow_table
($5.host
, "tables are only "
1790 "supported in round-robin routing pools"))
1792 if
((r.rpool.opts
& PF_POOL_TYPEMASK
) !=
1793 PF_POOL_ROUNDROBIN
&&
1794 disallow_alias
($5.host
, "interface (%s) "
1795 "is only supported in round-robin "
1798 if
($5.host
->next
!= NULL
) {
1799 if
((r.rpool.opts
& PF_POOL_TYPEMASK
) !=
1800 PF_POOL_ROUNDROBIN
) {
1801 yyerror("r.rpool.opts must "
1802 "be PF_POOL_ROUNDROBIN");
1807 if
($9.queues.qname
!= NULL
) {
1808 if
(strlcpy
(r.qname
, $9.queues.qname
,
1809 sizeof
(r.qname
)) >= sizeof
(r.qname
)) {
1810 yyerror("rule qname too long (max "
1811 "%d chars)", sizeof
(r.qname
)-1);
1814 free
($9.queues.qname
);
1816 if
($9.queues.pqname
!= NULL
) {
1817 if
(strlcpy
(r.pqname
, $9.queues.pqname
,
1818 sizeof
(r.pqname
)) >= sizeof
(r.pqname
)) {
1819 yyerror("rule pqname too long (max "
1820 "%d chars)", sizeof
(r.pqname
)-1);
1823 free
($9.queues.pqname
);
1826 expand_rule
(&r
, $4, $5.host
, $7, $8.src_os
,
1827 $8.src.host
, $8.src.port
, $8.dst.host
, $8.dst.port
,
1828 $9.uid
, $9.gid
, $9.icmpspec
);
1832 filter_opts
: { bzero
(&filter_opts
, sizeof filter_opts
); }
1834 { $$
= filter_opts
; }
1836 bzero
(&filter_opts
, sizeof filter_opts
);
1841 filter_opts_l
: filter_opts_l filter_opt
1845 filter_opt
: USER uids
{
1846 if
(filter_opts.uid
)
1847 $2->tail
->next
= filter_opts.uid
;
1848 filter_opts.uid
= $2;
1851 if
(filter_opts.gid
)
1852 $2->tail
->next
= filter_opts.gid
;
1853 filter_opts.gid
= $2;
1856 if
(filter_opts.marker
& FOM_FLAGS
) {
1857 yyerror("flags cannot be redefined");
1860 filter_opts.marker |
= FOM_FLAGS
;
1861 filter_opts.flags.b1 |
= $1.b1
;
1862 filter_opts.flags.b2 |
= $1.b2
;
1863 filter_opts.flags.w |
= $1.w
;
1864 filter_opts.flags.w2 |
= $1.w2
;
1867 if
(filter_opts.marker
& FOM_ICMP
) {
1868 yyerror("icmp-type cannot be redefined");
1871 filter_opts.marker |
= FOM_ICMP
;
1872 filter_opts.icmpspec
= $1;
1875 if
(filter_opts.marker
& FOM_TOS
) {
1876 yyerror("tos cannot be redefined");
1879 filter_opts.marker |
= FOM_TOS
;
1880 filter_opts.tos
= $1;
1883 if
(filter_opts.marker
& FOM_KEEP
) {
1884 yyerror("modulate or keep cannot be redefined");
1887 filter_opts.marker |
= FOM_KEEP
;
1888 filter_opts.keep.action
= $1.action
;
1889 filter_opts.keep.options
= $1.options
;
1892 filter_opts.fragment
= 1;
1895 filter_opts.allowopts
= 1;
1898 if
(filter_opts.label
) {
1899 yyerror("label cannot be redefined");
1902 filter_opts.label
= $1;
1905 if
(filter_opts.queues.qname
) {
1906 yyerror("queue cannot be redefined");
1909 filter_opts.queues
= $1;
1912 filter_opts.tag
= $2;
1914 | not TAGGED
string {
1915 filter_opts.match_tag
= $3;
1916 filter_opts.match_tag_not
= $1;
1918 | PROBABILITY STRING
{
1920 double p
= strtod
($2, &e
);
1927 yyerror("invalid probability: %s", $2);
1931 p
= floor
(p
* (UINT_MAX
+1.0) + 0.5);
1932 if
(p
< 1.0 || p
>= (UINT_MAX
+1.0)) {
1933 yyerror("invalid probability: %s", $2);
1937 filter_opts.prob
= (u_int32_t
)p
;
1942 action
: PASS
{ $$.b1
= PF_PASS
; $$.b2
= $$.w
= 0; }
1943 | BLOCK blockspec
{ $$
= $2; $$.b1
= PF_DROP
; }
1946 blockspec
: /* empty */ {
1947 $$.b2
= blockpolicy
;
1948 $$.w
= returnicmpdefault
;
1949 $$.w2
= returnicmp6default
;
1952 $$.b2
= PFRULE_DROP
;
1957 $$.b2
= PFRULE_RETURNRST
;
1961 | RETURNRST
'(' TTL number
')' {
1963 yyerror("illegal ttl value %d", $4);
1966 $$.b2
= PFRULE_RETURNRST
;
1971 $$.b2
= PFRULE_RETURNICMP
;
1972 $$.w
= returnicmpdefault
;
1973 $$.w2
= returnicmp6default
;
1976 $$.b2
= PFRULE_RETURNICMP
;
1977 $$.w
= returnicmpdefault
;
1978 $$.w2
= returnicmp6default
;
1980 | RETURNICMP
'(' STRING
')' {
1981 $$.b2
= PFRULE_RETURNICMP
;
1982 if
(!($$.w
= parseicmpspec
($3, AF_INET
))) {
1987 $$.w2
= returnicmp6default
;
1989 | RETURNICMP6
'(' STRING
')' {
1990 $$.b2
= PFRULE_RETURNICMP
;
1991 $$.w
= returnicmpdefault
;
1992 if
(!($$.w2
= parseicmpspec
($3, AF_INET6
))) {
1998 | RETURNICMP
'(' STRING comma STRING
')' {
1999 $$.b2
= PFRULE_RETURNICMP
;
2000 if
(!($$.w
= parseicmpspec
($3, AF_INET
)) ||
2001 !($$.w2
= parseicmpspec
($5, AF_INET6
))) {
2010 $$.b2
= PFRULE_RETURN
;
2011 $$.w
= returnicmpdefault
;
2012 $$.w2
= returnicmp6default
;
2016 dir
: /* empty */ { $$
= 0; }
2017 | IN
{ $$
= PF_IN
; }
2018 | OUT
{ $$
= PF_OUT
; }
2021 logquick
: /* empty */ { $$.log
= 0; $$.quick
= 0; }
2022 | log
{ $$.log
= $1; $$.quick
= 0; }
2023 | QUICK
{ $$.log
= 0; $$.quick
= 1; }
2024 | log QUICK
{ $$.log
= $1; $$.quick
= 1; }
2025 | QUICK log
{ $$.log
= $2; $$.quick
= 1; }
2028 log
: LOG
{ $$
= 1; }
2029 | LOGALL
{ $$
= 2; }
2032 interface
: /* empty */ { $$
= NULL
; }
2033 | ON if_item_not
{ $$
= $2; }
2034 | ON
'{' if_list
'}' { $$
= $3; }
2037 if_list
: if_item_not
{ $$
= $1; }
2038 | if_list comma if_item_not
{
2039 $1->tail
->next
= $3;
2045 if_item_not
: not if_item
{ $$
= $2; $$
->not
= $1; }
2049 struct node_host
*n
;
2051 if
((n
= ifa_exists
($1, 1)) == NULL
) {
2052 yyerror("unknown interface %s", $1);
2056 $$
= calloc
(1, sizeof
(struct node_if
));
2058 err
(1, "if_item: calloc");
2059 if
(strlcpy
($$
->ifname
, $1, sizeof
($$
->ifname
)) >=
2060 sizeof
($$
->ifname
)) {
2063 yyerror("interface name too long");
2067 $$
->ifa_flags
= n
->ifa_flags
;
2074 af
: /* empty */ { $$
= 0; }
2075 | INET
{ $$
= AF_INET
; }
2076 | INET6
{ $$
= AF_INET6
; }
2079 proto
: /* empty */ { $$
= NULL
; }
2080 | PROTO proto_item
{ $$
= $2; }
2081 | PROTO
'{' proto_list
'}' { $$
= $3; }
2084 proto_list
: proto_item
{ $$
= $1; }
2085 | proto_list comma proto_item
{
2086 $1->tail
->next
= $3;
2092 proto_item
: STRING
{
2096 if
(atoul
($1, &ulval
) == 0) {
2098 yyerror("protocol outside range");
2102 pr
= (u_int8_t
)ulval
;
2106 p
= getprotobyname
($1);
2108 yyerror("unknown protocol %s", $1);
2116 yyerror("proto 0 cannot be used");
2119 $$
= calloc
(1, sizeof
(struct node_proto
));
2121 err
(1, "proto_item: calloc");
2142 os
: /* empty */ { $$
= NULL
; }
2143 | OS xos
{ $$
= $2; }
2144 | OS
'{' os_list
'}' { $$
= $3; }
2148 $$
= calloc
(1, sizeof
(struct node_os
));
2150 err
(1, "os: calloc");
2156 os_list
: xos
{ $$
= $1; }
2157 | os_list comma xos
{
2158 $1->tail
->next
= $3;
2164 from
: /* empty */ {
2182 ipportspec
: ipspec
{
2186 | ipspec PORT portspec
{
2196 ipspec
: ANY
{ $$
= NULL
; }
2197 | xhost
{ $$
= $1; }
2198 |
'{' host_list
'}' { $$
= $2; }
2201 host_list
: xhost
{ $$
= $1; }
2202 | host_list comma xhost
{
2205 else if
($1 == NULL
)
2208 $1->tail
->next
= $3;
2209 $1->tail
= $3->tail
;
2216 struct node_host
*n
;
2218 for
(n
= $2; n
!= NULL
; n
= n
->next
)
2223 $$
= calloc
(1, sizeof
(struct node_host
));
2225 err
(1, "xhost: calloc");
2226 $$
->addr.type
= PF_ADDR_NOROUTE
;
2233 if
(($$
= host
($1)) == NULL
) {
2234 /* error. "any" is handled elsewhere */
2236 yyerror("could not parse host specification");
2242 | STRING
'/' number
{
2245 if
(asprintf
(&buf
, "%s/%u", $1, $3) == -1)
2246 err
(1, "host: asprintf");
2248 if
(($$
= host
(buf
)) == NULL
) {
2249 /* error. "any" is handled elsewhere */
2251 yyerror("could not parse host specification");
2257 | dynaddr
'/' number
{
2258 struct node_host
*n
;
2261 for
(n
= $1; n
!= NULL
; n
= n
->next
)
2265 if
(strlen
($2) >= PF_TABLE_NAME_SIZE
) {
2266 yyerror("table name '%s' too long", $2);
2270 $$
= calloc
(1, sizeof
(struct node_host
));
2272 err
(1, "host: calloc");
2273 $$
->addr.type
= PF_ADDR_TABLE
;
2274 if
(strlcpy
($$
->addr.v.tblname
, $2,
2275 sizeof
($$
->addr.v.tblname
)) >=
2276 sizeof
($$
->addr.v.tblname
))
2277 errx
(1, "host: strlcpy");
2287 if
(atoul
($1, &ulval
) == -1) {
2288 yyerror("%s is not a number", $1);
2297 dynaddr
: '(' STRING
')' {
2302 while
((p
= strrchr
($2, ':')) != NULL
) {
2303 if
(!strcmp
(p
+1, "network"))
2304 flags |
= PFI_AFLAG_NETWORK
;
2305 else if
(!strcmp
(p
+1, "broadcast"))
2306 flags |
= PFI_AFLAG_BROADCAST
;
2307 else if
(!strcmp
(p
+1, "peer"))
2308 flags |
= PFI_AFLAG_PEER
;
2309 else if
(!strcmp
(p
+1, "0"))
2310 flags |
= PFI_AFLAG_NOALIAS
;
2312 yyerror("interface %s has bad modifier",
2319 if
(flags
& (flags
- 1) & PFI_AFLAG_MODEMASK
) {
2321 yyerror("illegal combination of "
2322 "interface modifiers");
2325 if
(ifa_exists
($2, 1) == NULL
&& strcmp
($2, "self")) {
2326 yyerror("interface %s does not exist", $2);
2330 $$
= calloc
(1, sizeof
(struct node_host
));
2332 err
(1, "address: calloc");
2334 set_ipmask
($$
, 128);
2335 $$
->addr.type
= PF_ADDR_DYNIFTL
;
2336 $$
->addr.iflags
= flags
;
2337 if
(strlcpy
($$
->addr.v.ifname
, $2,
2338 sizeof
($$
->addr.v.ifname
)) >=
2339 sizeof
($$
->addr.v.ifname
)) {
2342 yyerror("interface name too long");
2351 portspec
: port_item
{ $$
= $1; }
2352 |
'{' port_list
'}' { $$
= $2; }
2355 port_list
: port_item
{ $$
= $1; }
2356 | port_list comma port_item
{
2357 $1->tail
->next
= $3;
2364 $$
= calloc
(1, sizeof
(struct node_port
));
2366 err
(1, "port_item: calloc");
2378 yyerror("':' cannot be used with an other "
2382 $$
= calloc
(1, sizeof
(struct node_port
));
2384 err
(1, "port_item: calloc");
2391 | port PORTBINARY port
{
2393 yyerror("':' cannot be used with an other "
2397 $$
= calloc
(1, sizeof
(struct node_port
));
2399 err
(1, "port_item: calloc");
2409 char *p
= strchr
($1, ':');
2410 struct servent
*s
= NULL
;
2414 if
(atoul
($1, &ulval
) == 0) {
2415 if
(ulval
> 65535) {
2417 yyerror("illegal port value %d",
2421 $$.a
= htons
(ulval
);
2423 s
= getservbyname
($1, "tcp");
2425 s
= getservbyname
($1, "udp");
2427 yyerror("unknown port %s", $1);
2439 if
((port
[0] = getservice
($1)) == -1 ||
2440 (port
[1] = getservice
(p
)) == -1) {
2452 uids
: uid_item
{ $$
= $1; }
2453 |
'{' uid_list
'}' { $$
= $2; }
2456 uid_list
: uid_item
{ $$
= $1; }
2457 | uid_list comma uid_item
{
2458 $1->tail
->next
= $3;
2465 $$
= calloc
(1, sizeof
(struct node_uid
));
2467 err
(1, "uid_item: calloc");
2475 if
($2 == UID_MAX
&& $1 != PF_OP_EQ
&& $1 != PF_OP_NE
) {
2476 yyerror("user unknown requires operator = or "
2480 $$
= calloc
(1, sizeof
(struct node_uid
));
2482 err
(1, "uid_item: calloc");
2489 | uid PORTBINARY uid
{
2490 if
($1 == UID_MAX ||
$3 == UID_MAX
) {
2491 yyerror("user unknown requires operator = or "
2495 $$
= calloc
(1, sizeof
(struct node_uid
));
2497 err
(1, "uid_item: calloc");
2509 if
(atoul
($1, &ulval
) == -1) {
2510 if
(!strcmp
($1, "unknown"))
2515 if
((pw
= getpwnam
($1)) == NULL
) {
2516 yyerror("unknown user %s", $1);
2523 if
(ulval
>= UID_MAX
) {
2525 yyerror("illegal uid value %lu", ulval
);
2534 gids
: gid_item
{ $$
= $1; }
2535 |
'{' gid_list
'}' { $$
= $2; }
2538 gid_list
: gid_item
{ $$
= $1; }
2539 | gid_list comma gid_item
{
2540 $1->tail
->next
= $3;
2547 $$
= calloc
(1, sizeof
(struct node_gid
));
2549 err
(1, "gid_item: calloc");
2557 if
($2 == GID_MAX
&& $1 != PF_OP_EQ
&& $1 != PF_OP_NE
) {
2558 yyerror("group unknown requires operator = or "
2562 $$
= calloc
(1, sizeof
(struct node_gid
));
2564 err
(1, "gid_item: calloc");
2571 | gid PORTBINARY gid
{
2572 if
($1 == GID_MAX ||
$3 == GID_MAX
) {
2573 yyerror("group unknown requires operator = or "
2577 $$
= calloc
(1, sizeof
(struct node_gid
));
2579 err
(1, "gid_item: calloc");
2591 if
(atoul
($1, &ulval
) == -1) {
2592 if
(!strcmp
($1, "unknown"))
2597 if
((grp
= getgrnam
($1)) == NULL
) {
2598 yyerror("unknown group %s", $1);
2605 if
(ulval
>= GID_MAX
) {
2606 yyerror("illegal gid value %lu", ulval
);
2619 if
((f
= parse_flags
($1)) < 0) {
2620 yyerror("bad flags %s", $1);
2629 flags
: FLAGS flag
'/' flag
{ $$.b1
= $2.b1
; $$.b2
= $4.b1
; }
2630 | FLAGS
'/' flag
{ $$.b1
= 0; $$.b2
= $3.b1
; }
2633 icmpspec
: ICMPTYPE icmp_item
{ $$
= $2; }
2634 | ICMPTYPE
'{' icmp_list
'}' { $$
= $3; }
2635 | ICMP6TYPE icmp6_item
{ $$
= $2; }
2636 | ICMP6TYPE
'{' icmp6_list
'}' { $$
= $3; }
2639 icmp_list
: icmp_item
{ $$
= $1; }
2640 | icmp_list comma icmp_item
{
2641 $1->tail
->next
= $3;
2647 icmp6_list
: icmp6_item
{ $$
= $1; }
2648 | icmp6_list comma icmp6_item
{
2649 $1->tail
->next
= $3;
2655 icmp_item
: icmptype
{
2656 $$
= calloc
(1, sizeof
(struct node_icmp
));
2658 err
(1, "icmp_item: calloc");
2661 $$
->proto
= IPPROTO_ICMP
;
2665 | icmptype CODE STRING
{
2666 const struct icmpcodeent
*p
;
2669 if
(atoul
($3, &ulval
) == 0) {
2672 yyerror("illegal icmp-code %d", ulval
);
2676 if
((p
= geticmpcodebyname
($1-1, $3,
2677 AF_INET
)) == NULL
) {
2678 yyerror("unknown icmp-code %s", $3);
2685 $$
= calloc
(1, sizeof
(struct node_icmp
));
2687 err
(1, "icmp_item: calloc");
2689 $$
->code
= ulval
+ 1;
2690 $$
->proto
= IPPROTO_ICMP
;
2696 icmp6_item
: icmp6type
{
2697 $$
= calloc
(1, sizeof
(struct node_icmp
));
2699 err
(1, "icmp_item: calloc");
2702 $$
->proto
= IPPROTO_ICMPV6
;
2706 | icmp6type CODE STRING
{
2707 const struct icmpcodeent
*p
;
2710 if
(atoul
($3, &ulval
) == 0) {
2712 yyerror("illegal icmp6-code %ld",
2718 if
((p
= geticmpcodebyname
($1-1, $3,
2719 AF_INET6
)) == NULL
) {
2720 yyerror("unknown icmp6-code %s", $3);
2727 $$
= calloc
(1, sizeof
(struct node_icmp
));
2729 err
(1, "icmp_item: calloc");
2731 $$
->code
= ulval
+ 1;
2732 $$
->proto
= IPPROTO_ICMPV6
;
2739 const struct icmptypeent
*p
;
2742 if
(atoul
($1, &ulval
) == 0) {
2744 yyerror("illegal icmp-type %d", ulval
);
2750 if
((p
= geticmptypebyname
($1, AF_INET
)) ==
2752 yyerror("unknown icmp-type %s", $1);
2762 icmp6type
: STRING
{
2763 const struct icmptypeent
*p
;
2766 if
(atoul
($1, &ulval
) == 0) {
2768 yyerror("illegal icmp6-type %d", ulval
);
2774 if
((p
= geticmptypebyname
($1, AF_INET6
)) ==
2776 yyerror("unknown icmp6-type %s", $1);
2787 if
(!strcmp
($2, "lowdelay"))
2788 $$
= IPTOS_LOWDELAY
;
2789 else if
(!strcmp
($2, "throughput"))
2790 $$
= IPTOS_THROUGHPUT
;
2791 else if
(!strcmp
($2, "reliability"))
2792 $$
= IPTOS_RELIABILITY
;
2793 else if
($2[0] == '0' && $2[1] == 'x')
2794 $$
= strtoul
($2, NULL
, 16);
2796 $$
= strtoul
($2, NULL
, 10);
2797 if
(!$$ || $$
> 255) {
2798 yyerror("illegal tos value %s", $2);
2806 sourcetrack
: SOURCETRACK
{ $$
= PF_SRCTRACK
; }
2807 | SOURCETRACK GLOBAL
{ $$
= PF_SRCTRACK_GLOBAL
; }
2808 | SOURCETRACK RULE
{ $$
= PF_SRCTRACK_RULE
; }
2811 statelock
: IFBOUND
{
2812 $$
= PFRULE_IFBOUND
;
2815 $$
= PFRULE_GRBOUND
;
2826 | KEEP STATE state_opt_spec
{
2827 $$.action
= PF_STATE_NORMAL
;
2830 | MODULATE STATE state_opt_spec
{
2831 $$.action
= PF_STATE_MODULATE
;
2834 | SYNPROXY STATE state_opt_spec
{
2835 $$.action
= PF_STATE_SYNPROXY
;
2840 state_opt_spec
: '(' state_opt_list
')' { $$
= $2; }
2841 |
/* empty */ { $$
= NULL
; }
2844 state_opt_list
: state_opt_item
{ $$
= $1; }
2845 | state_opt_list comma state_opt_item
{
2846 $1->tail
->next
= $3;
2852 state_opt_item
: MAXIMUM number
{
2853 $$
= calloc
(1, sizeof
(struct node_state_opt
));
2855 err
(1, "state_opt_item: calloc");
2856 $$
->type
= PF_STATE_OPT_MAX
;
2857 $$
->data.max_states
= $2;
2862 $$
= calloc
(1, sizeof
(struct node_state_opt
));
2864 err
(1, "state_opt_item: calloc");
2865 $$
->type
= PF_STATE_OPT_NOSYNC
;
2869 | MAXSRCSTATES number
{
2870 $$
= calloc
(1, sizeof
(struct node_state_opt
));
2872 err
(1, "state_opt_item: calloc");
2873 $$
->type
= PF_STATE_OPT_MAX_SRC_STATES
;
2874 $$
->data.max_src_states
= $2;
2878 | MAXSRCNODES number
{
2879 $$
= calloc
(1, sizeof
(struct node_state_opt
));
2881 err
(1, "state_opt_item: calloc");
2882 $$
->type
= PF_STATE_OPT_MAX_SRC_NODES
;
2883 $$
->data.max_src_nodes
= $2;
2888 $$
= calloc
(1, sizeof
(struct node_state_opt
));
2890 err
(1, "state_opt_item: calloc");
2891 $$
->type
= PF_STATE_OPT_PICKUPS
;
2892 $$
->data.pickup_mode
= PF_PICKUPS_ENABLED
;
2897 $$
= calloc
(1, sizeof
(struct node_state_opt
));
2899 err
(1, "state_opt_item: calloc");
2900 $$
->type
= PF_STATE_OPT_PICKUPS
;
2901 $$
->data.pickup_mode
= PF_PICKUPS_DISABLED
;
2906 $$
= calloc
(1, sizeof
(struct node_state_opt
));
2908 err
(1, "state_opt_item: calloc");
2909 $$
->type
= PF_STATE_OPT_PICKUPS
;
2910 $$
->data.pickup_mode
= PF_PICKUPS_HASHONLY
;
2915 $$
= calloc
(1, sizeof
(struct node_state_opt
));
2917 err
(1, "state_opt_item: calloc");
2918 $$
->type
= PF_STATE_OPT_SRCTRACK
;
2919 $$
->data.src_track
= $1;
2924 $$
= calloc
(1, sizeof
(struct node_state_opt
));
2926 err
(1, "state_opt_item: calloc");
2927 $$
->type
= PF_STATE_OPT_STATELOCK
;
2928 $$
->data.statelock
= $1;
2935 for
(i
= 0; pf_timeouts
[i
].name
&&
2936 strcmp
(pf_timeouts
[i
].name
, $1); ++i
)
2938 if
(!pf_timeouts
[i
].name
) {
2939 yyerror("illegal timeout name %s", $1);
2943 if
(strchr
(pf_timeouts
[i
].name
, '.') == NULL
) {
2944 yyerror("illegal state timeout %s", $1);
2949 $$
= calloc
(1, sizeof
(struct node_state_opt
));
2951 err
(1, "state_opt_item: calloc");
2952 $$
->type
= PF_STATE_OPT_TIMEOUT
;
2953 $$
->data.timeout.number
= pf_timeouts
[i
].timeout
;
2954 $$
->data.timeout.seconds
= $2;
2960 label
: LABEL STRING
{
2965 qname
: QUEUE STRING
{
2968 | QUEUE
'(' STRING
')' {
2971 | QUEUE
'(' STRING comma STRING
')' {
2977 no
: /* empty */ { $$
= 0; }
2982 char *p
= strchr
($1, ':');
2985 if
(($$.a
= getservice
($1)) == -1) {
2990 } else if
(!strcmp
(p
+1, "*")) {
2992 if
(($$.a
= getservice
($1)) == -1) {
3000 if
(($$.a
= getservice
($1)) == -1 ||
3001 ($$.b
= getservice
(p
)) == -1) {
3013 redirspec
: host
{ $$
= $1; }
3014 |
'{' redir_host_list
'}' { $$
= $2; }
3017 redir_host_list
: host
{ $$
= $1; }
3018 | redir_host_list comma host
{
3019 $1->tail
->next
= $3;
3020 $1->tail
= $3->tail
;
3025 redirpool
: /* empty */ { $$
= NULL
; }
3027 $$
= calloc
(1, sizeof
(struct redirection
));
3029 err
(1, "redirection: calloc");
3031 $$
->rport.a
= $$
->rport.b
= $$
->rport.t
= 0;
3033 | ARROW redirspec PORT rport
{
3034 $$
= calloc
(1, sizeof
(struct redirection
));
3036 err
(1, "redirection: calloc");
3042 hashkey
: /* empty */
3044 $$
= calloc
(1, sizeof
(struct pf_poolhashkey
));
3046 err
(1, "hashkey: calloc");
3047 $$
->key32
[0] = arc4random
();
3048 $$
->key32
[1] = arc4random
();
3049 $$
->key32
[2] = arc4random
();
3050 $$
->key32
[3] = arc4random
();
3054 if
(!strncmp
($1, "0x", 2)) {
3055 if
(strlen
($1) != 34) {
3057 yyerror("hex key must be 128 bits "
3058 "(32 hex digits) long");
3061 $$
= calloc
(1, sizeof
(struct pf_poolhashkey
));
3063 err
(1, "hashkey: calloc");
3065 if
(sscanf
($1, "0x%8x%8x%8x%8x",
3066 &$$
->key32
[0], &$$
->key32
[1],
3067 &$$
->key32
[2], &$$
->key32
[3]) != 4) {
3070 yyerror("invalid hex key");
3076 $$
= calloc
(1, sizeof
(struct pf_poolhashkey
));
3078 err
(1, "hashkey: calloc");
3080 MD5Update
(&context
, (unsigned char *)$1,
3082 MD5Final
((unsigned char *)$$
, &context
);
3083 $$
->key32
[0] = htonl
($$
->key32
[0]);
3084 $$
->key32
[1] = htonl
($$
->key32
[1]);
3085 $$
->key32
[2] = htonl
($$
->key32
[2]);
3086 $$
->key32
[3] = htonl
($$
->key32
[3]);
3092 pool_opts
: { bzero
(&pool_opts
, sizeof pool_opts
); }
3096 bzero
(&pool_opts
, sizeof pool_opts
);
3101 pool_opts_l
: pool_opts_l pool_opt
3105 pool_opt
: BITMASK
{
3106 if
(pool_opts.type
) {
3107 yyerror("pool type cannot be redefined");
3110 pool_opts.type
= PF_POOL_BITMASK
;
3113 if
(pool_opts.type
) {
3114 yyerror("pool type cannot be redefined");
3117 pool_opts.type
= PF_POOL_RANDOM
;
3119 | SOURCEHASH hashkey
{
3120 if
(pool_opts.type
) {
3121 yyerror("pool type cannot be redefined");
3124 pool_opts.type
= PF_POOL_SRCHASH
;
3128 if
(pool_opts.type
) {
3129 yyerror("pool type cannot be redefined");
3132 pool_opts.type
= PF_POOL_ROUNDROBIN
;
3135 if
(pool_opts.staticport
) {
3136 yyerror("static-port cannot be redefined");
3139 pool_opts.staticport
= 1;
3142 if
(filter_opts.marker
& POM_STICKYADDRESS
) {
3143 yyerror("sticky-address cannot be redefined");
3146 pool_opts.marker |
= POM_STICKYADDRESS
;
3147 pool_opts.opts |
= PF_POOL_STICKYADDR
;
3151 redirection
: /* empty */ { $$
= NULL
; }
3153 $$
= calloc
(1, sizeof
(struct redirection
));
3155 err
(1, "redirection: calloc");
3157 $$
->rport.a
= $$
->rport.b
= $$
->rport.t
= 0;
3159 | ARROW host PORT rport
{
3160 $$
= calloc
(1, sizeof
(struct redirection
));
3162 err
(1, "redirection: calloc");
3168 natpass
: /* empty */ { $$
= 0; }
3172 nataction
: no NAT natpass
{
3190 natrule
: nataction interface af proto fromto tag redirpool pool_opts
3194 if
(check_rulestate
(PFCTL_STATE_NAT
))
3197 memset
(&r
, 0, sizeof
(r
));
3204 if
($5.src.host
&& $5.src.host
->af
&&
3205 !$5.src.host
->ifindex
)
3206 r.af
= $5.src.host
->af
;
3207 else if
($5.dst.host
&& $5.dst.host
->af
&&
3208 !$5.dst.host
->ifindex
)
3209 r.af
= $5.dst.host
->af
;
3213 if
(strlcpy
(r.tagname
, $6, PF_TAG_NAME_SIZE
) >=
3215 yyerror("tag too long, max %u chars",
3216 PF_TAG_NAME_SIZE
- 1);
3220 if
(r.action
== PF_NONAT || r.action
== PF_NORDR
) {
3222 yyerror("translation rule with 'no' "
3223 "does not need '->'");
3227 if
($7 == NULL ||
$7->host
== NULL
) {
3228 yyerror("translation rule requires '-> "
3232 if
(!r.af
&& ! $7->host
->ifindex
)
3233 r.af
= $7->host
->af
;
3235 remove_invalid_hosts
(&$7->host
, &r.af
);
3236 if
(invalid_redirect
($7->host
, r.af
))
3238 if
(check_netmask
($7->host
, r.af
))
3241 r.rpool.proxy_port
[0] = ntohs
($7->rport.a
);
3245 if
(!$7->rport.b
&& $7->rport.t
&&
3246 $5.dst.port
!= NULL
) {
3247 r.rpool.proxy_port
[1] =
3248 ntohs
($7->rport.a
) +
3250 $5.dst.port
->port
[1]) -
3252 $5.dst.port
->port
[0]));
3254 r.rpool.proxy_port
[1] =
3258 r.rpool.proxy_port
[1] =
3260 if
(!r.rpool.proxy_port
[0] &&
3261 !r.rpool.proxy_port
[1]) {
3262 r.rpool.proxy_port
[0] =
3263 PF_NAT_PROXY_PORT_LOW
;
3264 r.rpool.proxy_port
[1] =
3265 PF_NAT_PROXY_PORT_HIGH
;
3266 } else if
(!r.rpool.proxy_port
[1])
3267 r.rpool.proxy_port
[1] =
3268 r.rpool.proxy_port
[0];
3274 r.rpool.opts
= $8.type
;
3275 if
((r.rpool.opts
& PF_POOL_TYPEMASK
) ==
3276 PF_POOL_NONE
&& ($7->host
->next
!= NULL ||
3277 $7->host
->addr.type
== PF_ADDR_TABLE ||
3278 DYNIF_MULTIADDR
($7->host
->addr
)))
3279 r.rpool.opts
= PF_POOL_ROUNDROBIN
;
3280 if
((r.rpool.opts
& PF_POOL_TYPEMASK
) !=
3281 PF_POOL_ROUNDROBIN
&&
3282 disallow_table
($7->host
, "tables are only "
3283 "supported in round-robin redirection "
3286 if
((r.rpool.opts
& PF_POOL_TYPEMASK
) !=
3287 PF_POOL_ROUNDROBIN
&&
3288 disallow_alias
($7->host
, "interface (%s) "
3289 "is only supported in round-robin "
3290 "redirection pools"))
3292 if
($7->host
->next
!= NULL
) {
3293 if
((r.rpool.opts
& PF_POOL_TYPEMASK
) !=
3294 PF_POOL_ROUNDROBIN
) {
3295 yyerror("only round-robin "
3296 "valid for multiple "
3297 "redirection addresses");
3304 memcpy
(&r.rpool.key
, $8.key
,
3305 sizeof
(struct pf_poolhashkey
));
3308 r.rpool.opts |
= $8.opts
;
3310 if
($8.staticport
) {
3311 if
(r.action
!= PF_NAT
) {
3312 yyerror("the 'static-port' option is "
3313 "only valid with nat rules");
3316 if
(r.rpool.proxy_port
[0] !=
3317 PF_NAT_PROXY_PORT_LOW
&&
3318 r.rpool.proxy_port
[1] !=
3319 PF_NAT_PROXY_PORT_HIGH
) {
3320 yyerror("the 'static-port' option can't"
3321 " be used when specifying a port"
3325 r.rpool.proxy_port
[0] = 0;
3326 r.rpool.proxy_port
[1] = 0;
3329 expand_rule
(&r
, $2, $7 == NULL ? NULL
: $7->host
, $4,
3330 $5.src_os
, $5.src.host
, $5.src.port
, $5.dst.host
,
3331 $5.dst.port
, 0, 0, 0);
3336 binatrule
: no BINAT natpass interface af proto FROM host TO ipspec tag
3339 struct pf_rule binat
;
3340 struct pf_pooladdr
*pa
;
3342 if
(check_rulestate
(PFCTL_STATE_NAT
))
3345 memset
(&binat
, 0, sizeof
(binat
));
3348 binat.action
= PF_NOBINAT
;
3350 binat.action
= PF_BINAT
;
3353 if
(!binat.af
&& $8 != NULL
&& $8->af
)
3355 if
(!binat.af
&& $10 != NULL
&& $10->af
)
3357 if
(!binat.af
&& $12 != NULL
&& $12->host
)
3358 binat.af
= $12->host
->af
;
3360 yyerror("address family (inet/inet6) "
3366 memcpy
(binat.ifname
, $4->ifname
,
3367 sizeof
(binat.ifname
));
3368 binat.ifnot
= $4->not
;
3372 if
(strlcpy
(binat.tagname
, $11,
3373 PF_TAG_NAME_SIZE
) >= PF_TAG_NAME_SIZE
) {
3374 yyerror("tag too long, max %u chars",
3375 PF_TAG_NAME_SIZE
- 1);
3380 binat.proto
= $6->proto
;
3384 if
($8 != NULL
&& disallow_table
($8, "invalid use of "
3385 "table <%s> as the source address of a binat rule"))
3387 if
($8 != NULL
&& disallow_alias
($8, "invalid use of "
3388 "interface (%s) as the source address of a binat "
3391 if
($12 != NULL
&& $12->host
!= NULL
&& disallow_table
(
3392 $12->host
, "invalid use of table <%s> as the "
3393 "redirect address of a binat rule"))
3395 if
($12 != NULL
&& $12->host
!= NULL
&& disallow_alias
(
3396 $12->host
, "invalid use of interface (%s) as the "
3397 "redirect address of a binat rule"))
3402 yyerror("multiple binat ip addresses");
3405 if
($8->addr.type
== PF_ADDR_DYNIFTL
)
3407 if
($8->af
!= binat.af
) {
3408 yyerror("binat ip versions must match");
3411 if
(check_netmask
($8, binat.af
))
3413 memcpy
(&binat.src.addr
, &$8->addr
,
3414 sizeof
(binat.src.addr
));
3419 yyerror("multiple binat ip addresses");
3422 if
($10->af
!= binat.af
&& $10->af
) {
3423 yyerror("binat ip versions must match");
3426 if
(check_netmask
($10, binat.af
))
3428 memcpy
(&binat.dst.addr
, &$10->addr
,
3429 sizeof
(binat.dst.addr
));
3430 binat.dst.not
= $10->not
;
3434 if
(binat.action
== PF_NOBINAT
) {
3436 yyerror("'no binat' rule does not need"
3441 if
($12 == NULL ||
$12->host
== NULL
) {
3442 yyerror("'binat' rule requires"
3447 remove_invalid_hosts
(&$12->host
, &binat.af
);
3448 if
(invalid_redirect
($12->host
, binat.af
))
3450 if
($12->host
->next
!= NULL
) {
3451 yyerror("binat rule must redirect to "
3452 "a single address");
3455 if
(check_netmask
($12->host
, binat.af
))
3458 if
(!PF_AZERO
(&binat.src.addr.v.a.mask
,
3460 !PF_AEQ
(&binat.src.addr.v.a.mask
,
3461 &$12->host
->addr.v.a.mask
, binat.af
)) {
3462 yyerror("'binat' source mask and "
3463 "redirect mask must be the same");
3467 TAILQ_INIT
(&binat.rpool.list
);
3468 pa
= calloc
(1, sizeof
(struct pf_pooladdr
));
3470 err
(1, "binat: calloc");
3471 pa
->addr
= $12->host
->addr
;
3473 TAILQ_INSERT_TAIL
(&binat.rpool.list
,
3479 pfctl_add_rule
(pf
, &binat
);
3483 tag
: /* empty */ { $$
= NULL
; }
3484 | TAG STRING
{ $$
= $2; }
3487 route_host
: STRING
{
3488 $$
= calloc
(1, sizeof
(struct node_host
));
3490 err
(1, "route_host: calloc");
3492 if
(ifa_exists
($$
->ifname
, 0) == NULL
) {
3493 yyerror("routeto: unknown interface %s",
3499 set_ipmask
($$
, 128);
3503 |
'(' STRING host
')' {
3506 if
(ifa_exists
($$
->ifname
, 0) == NULL
) {
3507 yyerror("routeto: unknown interface %s",
3514 route_host_list
: route_host
{ $$
= $1; }
3515 | route_host_list comma route_host
{
3518 if
($1->af
!= $3->af
) {
3519 yyerror("all pool addresses must be in the "
3520 "same address family");
3523 $1->tail
->next
= $3;
3524 $1->tail
= $3->tail
;
3529 routespec
: route_host
{ $$
= $1; }
3530 |
'{' route_host_list
'}' { $$
= $2; }
3533 route
: /* empty */ {
3540 $$.rt
= PF_FASTROUTE
;
3543 | ROUTETO routespec pool_opts
{
3546 $$.pool_opts
= $3.type |
$3.opts
;
3550 | REPLYTO routespec pool_opts
{
3553 $$.pool_opts
= $3.type |
$3.opts
;
3557 | DUPTO routespec pool_opts
{
3560 $$.pool_opts
= $3.type |
$3.opts
;
3566 timeout_spec
: STRING number
3568 if
(check_rulestate
(PFCTL_STATE_OPTION
)) {
3572 if
(pfctl_set_timeout
(pf
, $1, $2, 0) != 0) {
3573 yyerror("unknown timeout %s", $1);
3581 timeout_list
: timeout_list comma timeout_spec
3585 limit_spec
: STRING number
3587 if
(check_rulestate
(PFCTL_STATE_OPTION
)) {
3591 if
(pfctl_set_limit
(pf
, $1, $2) != 0) {
3592 yyerror("unable to set limit %s %u", $1, $2);
3600 limit_list
: limit_list comma limit_spec
3608 yesno
: NO
{ $$
= 0; }
3610 if
(!strcmp
($1, "yes"))
3620 unaryop
: '=' { $$
= PF_OP_EQ
; }
3621 |
'!' '=' { $$
= PF_OP_NE
; }
3622 |
'<' '=' { $$
= PF_OP_LE
; }
3623 |
'<' { $$
= PF_OP_LT
; }
3624 |
'>' '=' { $$
= PF_OP_GE
; }
3625 |
'>' { $$
= PF_OP_GT
; }
3631 yyerror(const char *fmt
, ...
)
3637 fprintf
(stderr
, "%s:%d: ", infile
, yylval.lineno
);
3638 vfprintf
(stderr
, fmt
, ap
);
3639 fprintf
(stderr
, "\n");
3645 disallow_table
(struct node_host
*h
, const char *fmt
)
3647 for
(; h
!= NULL
; h
= h
->next
)
3648 if
(h
->addr.type
== PF_ADDR_TABLE
) {
3649 yyerror(fmt
, h
->addr.v.tblname
);
3656 disallow_alias
(struct node_host
*h
, const char *fmt
)
3658 for
(; h
!= NULL
; h
= h
->next
)
3659 if
(DYNIF_MULTIADDR
(h
->addr
)) {
3660 yyerror(fmt
, h
->addr.v.tblname
);
3667 rule_consistent
(struct pf_rule
*r
)
3671 switch
(r
->action
) {
3675 problems
= filter_consistent
(r
);
3679 problems
= nat_consistent
(r
);
3683 problems
= rdr_consistent
(r
);
3694 filter_consistent
(struct pf_rule
*r
)
3698 if
(r
->proto
!= IPPROTO_TCP
&& r
->proto
!= IPPROTO_UDP
&&
3699 (r
->src.port_op || r
->dst.port_op
)) {
3700 yyerror("port only applies to tcp/udp");
3703 if
(r
->proto
!= IPPROTO_ICMP
&& r
->proto
!= IPPROTO_ICMPV6
&&
3704 (r
->type || r
->code
)) {
3705 yyerror("icmp-type/code only applies to icmp");
3708 if
(!r
->af
&& (r
->type || r
->code
)) {
3709 yyerror("must indicate address family with icmp-type/code");
3712 if
((r
->proto
== IPPROTO_ICMP
&& r
->af
== AF_INET6
) ||
3713 (r
->proto
== IPPROTO_ICMPV6
&& r
->af
== AF_INET
)) {
3714 yyerror("proto %s doesn't match address family %s",
3715 r
->proto
== IPPROTO_ICMP ?
"icmp" : "icmp6",
3716 r
->af
== AF_INET ?
"inet" : "inet6");
3719 if
(r
->allow_opts
&& r
->action
!= PF_PASS
) {
3720 yyerror("allow-opts can only be specified for pass rules");
3723 if
(r
->rule_flag
& PFRULE_FRAGMENT
&& (r
->src.port_op ||
3724 r
->dst.port_op || r
->flagset || r
->type || r
->code
)) {
3725 yyerror("fragments can be filtered only on IP header fields");
3728 if
(r
->rule_flag
& PFRULE_RETURNRST
&& r
->proto
!= IPPROTO_TCP
) {
3729 yyerror("return-rst can only be applied to TCP rules");
3732 if
(r
->max_src_nodes
&& !(r
->rule_flag
& PFRULE_RULESRCTRACK
)) {
3733 yyerror("max-src-nodes requires 'source-track rule'");
3736 if
(r
->action
== PF_DROP
&& r
->keep_state
) {
3737 yyerror("keep state on block rules doesn't make sense");
3740 if
((r
->tagname
[0] || r
->match_tagname
[0]) && !r
->keep_state
&&
3741 r
->action
== PF_PASS
&& !r
->anchorname
[0]) {
3742 yyerror("tags cannot be used without keep state");
3749 nat_consistent
(struct pf_rule
*r __unused
)
3751 return
(0); /* yeah! */
3755 rdr_consistent
(struct pf_rule
*r
)
3759 if
(r
->proto
!= IPPROTO_TCP
&& r
->proto
!= IPPROTO_UDP
) {
3760 if
(r
->src.port_op
) {
3761 yyerror("src port only applies to tcp/udp");
3764 if
(r
->dst.port_op
) {
3765 yyerror("dst port only applies to tcp/udp");
3768 if
(r
->rpool.proxy_port
[0]) {
3769 yyerror("rpool port only applies to tcp/udp");
3773 if
(r
->dst.port_op
&&
3774 r
->dst.port_op
!= PF_OP_EQ
&& r
->dst.port_op
!= PF_OP_RRG
) {
3775 yyerror("invalid port operator for rdr destination port");
3782 process_tabledef
(char *name
, struct table_opts
*opts
)
3784 struct pfr_buffer ab
;
3785 struct node_tinit
*ti
;
3787 bzero
(&ab
, sizeof
(ab
));
3788 ab.pfrb_type
= PFRB_ADDRS
;
3789 SIMPLEQ_FOREACH
(ti
, &opts
->init_nodes
, entries
) {
3791 if
(pfr_buf_load
(&ab
, ti
->file
, 0, append_addr
)) {
3793 yyerror("cannot load \"%s\": %s",
3794 ti
->file
, strerror
(errno
));
3796 yyerror("file \"%s\" contains bad data",
3801 if
(append_addr_host
(&ab
, ti
->host
, 0, 0)) {
3802 yyerror("cannot create address buffer: %s",
3807 if
(pf
->opts
& PF_OPT_VERBOSE
)
3808 print_tabledef
(name
, opts
->flags
, opts
->init_addr
,
3810 if
(!(pf
->opts
& PF_OPT_NOACTION
) &&
3811 pfctl_define_table
(name
, opts
->flags
, opts
->init_addr
,
3812 pf
->anchor
, pf
->ruleset
, &ab
, pf
->tticket
)) {
3813 yyerror("cannot define table %s: %s", name
,
3814 pfr_strerror
(errno
));
3830 /* macro gore, but you should've seen the prior indentation nightmare... */
3832 #define FREE_LIST(T,r) \
3835 while
(node
!= NULL
) { \
3837 node
= node
->next
; \
3842 #define LOOP_THROUGH(T,n,r,C) \
3846 r
= calloc
(1, sizeof
(T
)); \
3848 err
(1, "LOOP: calloc"); \
3852 while
(n
!= NULL
) { \
3861 expand_label_str
(char *label
, size_t len
, const char *srch
, const char *repl
)
3866 if
((tmp
= calloc
(1, len
)) == NULL
)
3867 err
(1, "expand_label_str: calloc");
3869 while
((q
= strstr
(p
, srch
)) != NULL
) {
3871 if
((strlcat
(tmp
, p
, len
) >= len
) ||
3872 (strlcat
(tmp
, repl
, len
) >= len
))
3873 errx
(1, "expand_label: label too long");
3877 if
(strlcat
(tmp
, p
, len
) >= len
)
3878 errx
(1, "expand_label: label too long");
3879 strlcpy
(label
, tmp
, len
); /* always fits */
3884 expand_label_if
(const char *name
, char *label
, size_t len
, const char *ifname
)
3886 if
(strstr
(label
, name
) != NULL
) {
3888 expand_label_str
(label
, len
, name
, "any");
3890 expand_label_str
(label
, len
, name
, ifname
);
3895 expand_label_addr
(const char *name
, char *label
, size_t len
, sa_family_t af
,
3896 struct node_host
*h
)
3898 char tmp
[64], tmp_not
[66];
3900 if
(strstr
(label
, name
) != NULL
) {
3901 switch
(h
->addr.type
) {
3902 case PF_ADDR_DYNIFTL
:
3903 snprintf
(tmp
, sizeof
(tmp
), "(%s)", h
->addr.v.ifname
);
3906 snprintf
(tmp
, sizeof
(tmp
), "<%s>", h
->addr.v.tblname
);
3908 case PF_ADDR_NOROUTE
:
3909 snprintf
(tmp
, sizeof
(tmp
), "no-route");
3911 case PF_ADDR_ADDRMASK
:
3912 if
(!af ||
(PF_AZERO
(&h
->addr.v.a.addr
, af
) &&
3913 PF_AZERO
(&h
->addr.v.a.mask
, af
)))
3914 snprintf
(tmp
, sizeof
(tmp
), "any");
3919 if
(inet_ntop
(af
, &h
->addr.v.a.addr
, a
,
3921 snprintf
(tmp
, sizeof
(tmp
), "?");
3923 bits
= unmask
(&h
->addr.v.a.mask
, af
);
3924 if
((af
== AF_INET
&& bits
< 32) ||
3925 (af
== AF_INET6
&& bits
< 128))
3926 snprintf
(tmp
, sizeof
(tmp
),
3929 snprintf
(tmp
, sizeof
(tmp
),
3935 snprintf
(tmp
, sizeof
(tmp
), "?");
3940 snprintf
(tmp_not
, sizeof
(tmp_not
), "! %s", tmp
);
3941 expand_label_str
(label
, len
, name
, tmp_not
);
3943 expand_label_str
(label
, len
, name
, tmp
);
3948 expand_label_port
(const char *name
, char *label
, size_t len
,
3949 struct node_port
*port
)
3951 char a1
[6], a2
[6], op
[13] = "";
3953 if
(strstr
(label
, name
) != NULL
) {
3954 snprintf
(a1
, sizeof
(a1
), "%u", ntohs
(port
->port
[0]));
3955 snprintf
(a2
, sizeof
(a2
), "%u", ntohs
(port
->port
[1]));
3958 else if
(port
->op
== PF_OP_IRG
)
3959 snprintf
(op
, sizeof
(op
), "%s><%s", a1
, a2
);
3960 else if
(port
->op
== PF_OP_XRG
)
3961 snprintf
(op
, sizeof
(op
), "%s<>%s", a1
, a2
);
3962 else if
(port
->op
== PF_OP_EQ
)
3963 snprintf
(op
, sizeof
(op
), "%s", a1
);
3964 else if
(port
->op
== PF_OP_NE
)
3965 snprintf
(op
, sizeof
(op
), "!=%s", a1
);
3966 else if
(port
->op
== PF_OP_LT
)
3967 snprintf
(op
, sizeof
(op
), "<%s", a1
);
3968 else if
(port
->op
== PF_OP_LE
)
3969 snprintf
(op
, sizeof
(op
), "<=%s", a1
);
3970 else if
(port
->op
== PF_OP_GT
)
3971 snprintf
(op
, sizeof
(op
), ">%s", a1
);
3972 else if
(port
->op
== PF_OP_GE
)
3973 snprintf
(op
, sizeof
(op
), ">=%s", a1
);
3974 expand_label_str
(label
, len
, name
, op
);
3979 expand_label_proto
(const char *name
, char *label
, size_t len
, u_int8_t proto
)
3981 struct protoent
*pe
;
3984 if
(strstr
(label
, name
) != NULL
) {
3985 pe
= getprotobynumber
(proto
);
3987 expand_label_str
(label
, len
, name
, pe
->p_name
);
3989 snprintf
(n
, sizeof
(n
), "%u", proto
);
3990 expand_label_str
(label
, len
, name
, n
);
3996 expand_label_nr
(const char *name
, char *label
, size_t len
)
4000 if
(strstr
(label
, name
) != NULL
) {
4001 snprintf
(n
, sizeof
(n
), "%u", pf
->rule_nr
);
4002 expand_label_str
(label
, len
, name
, n
);
4007 expand_label
(char *label
, size_t len
, const char *ifname
, sa_family_t af
,
4008 struct node_host
*src_host
, struct node_port
*src_port
,
4009 struct node_host
*dst_host
, struct node_port
*dst_port
,
4012 expand_label_if
("$if", label
, len
, ifname
);
4013 expand_label_addr
("$srcaddr", label
, len
, af
, src_host
);
4014 expand_label_addr
("$dstaddr", label
, len
, af
, dst_host
);
4015 expand_label_port
("$srcport", label
, len
, src_port
);
4016 expand_label_port
("$dstport", label
, len
, dst_port
);
4017 expand_label_proto
("$proto", label
, len
, proto
);
4018 expand_label_nr
("$nr", label
, len
);
4022 expand_altq
(struct pf_altq
*a
, struct node_if
*interfaces
,
4023 struct node_queue
*nqueues
, struct node_queue_bw bwspec
,
4024 struct node_queue_opt
*opts
)
4026 struct pf_altq pa
, pb
;
4027 char qname
[PF_QNAME_SIZE
];
4028 struct node_queue
*n
;
4029 struct node_queue_bw bw
;
4032 if
((pf
->loadopt
& PFCTL_FLAG_ALTQ
) == 0) {
4033 FREE_LIST
(struct node_if
, interfaces
);
4034 FREE_LIST
(struct node_queue
, nqueues
);
4038 LOOP_THROUGH
(struct node_if
, interface
, interfaces
,
4039 memcpy
(&pa
, a
, sizeof
(struct pf_altq
));
4040 if
(strlcpy
(pa.ifname
, interface
->ifname
,
4041 sizeof
(pa.ifname
)) >= sizeof
(pa.ifname
))
4042 errx
(1, "expand_altq: strlcpy");
4044 if
(interface
->not
) {
4045 yyerror("altq on ! <interface> is not supported");
4048 if
(eval_pfaltq
(pf
, &pa
, &bwspec
, opts
))
4051 if
(pfctl_add_altq
(pf
, &pa
))
4054 if
(pf
->opts
& PF_OPT_VERBOSE
) {
4055 print_altq
(&pf
->paltq
->altq
, 0,
4057 if
(nqueues
&& nqueues
->tail
) {
4059 LOOP_THROUGH
(struct node_queue
, queue
,
4069 if
(pa.scheduler
== ALTQT_CBQ ||
4070 pa.scheduler
== ALTQT_HFSC
) {
4071 /* now create a root queue */
4072 memset
(&pb
, 0, sizeof
(struct pf_altq
));
4073 if
(strlcpy
(qname
, "root_", sizeof
(qname
)) >=
4075 errx
(1, "expand_altq: strlcpy");
4076 if
(strlcat
(qname
, interface
->ifname
,
4077 sizeof
(qname
)) >= sizeof
(qname
))
4078 errx
(1, "expand_altq: strlcat");
4079 if
(strlcpy
(pb.qname
, qname
,
4080 sizeof
(pb.qname
)) >= sizeof
(pb.qname
))
4081 errx
(1, "expand_altq: strlcpy");
4082 if
(strlcpy
(pb.ifname
, interface
->ifname
,
4083 sizeof
(pb.ifname
)) >= sizeof
(pb.ifname
))
4084 errx
(1, "expand_altq: strlcpy");
4085 pb.qlimit
= pa.qlimit
;
4086 pb.scheduler
= pa.scheduler
;
4087 bw.bw_absolute
= pa.ifbandwidth
;
4089 if
(eval_pfqueue
(pf
, &pb
, &bw
, opts
))
4092 if
(pfctl_add_altq
(pf
, &pb
))
4096 LOOP_THROUGH
(struct node_queue
, queue
, nqueues
,
4097 n
= calloc
(1, sizeof
(struct node_queue
));
4099 err
(1, "expand_altq: calloc");
4100 if
(pa.scheduler
== ALTQT_CBQ ||
4101 pa.scheduler
== ALTQT_HFSC
/*||
4102 pa.scheduler == ALTQT_FAIRQ*/)
4103 if
(strlcpy
(n
->parent
, qname
,
4104 sizeof
(n
->parent
)) >=
4106 errx
(1, "expand_altq: strlcpy");
4107 if
(strlcpy
(n
->queue
, queue
->queue
,
4108 sizeof
(n
->queue
)) >= sizeof
(n
->queue
))
4109 errx
(1, "expand_altq: strlcpy");
4110 if
(strlcpy
(n
->ifname
, interface
->ifname
,
4111 sizeof
(n
->ifname
)) >= sizeof
(n
->ifname
))
4112 errx
(1, "expand_altq: strlcpy");
4113 n
->scheduler
= pa.scheduler
;
4119 queues
->tail
->next
= n
;
4125 FREE_LIST
(struct node_if
, interfaces
);
4126 FREE_LIST
(struct node_queue
, nqueues
);
4132 expand_queue
(struct pf_altq
*a
, struct node_if
*interfaces
,
4133 struct node_queue
*nqueues
, struct node_queue_bw bwspec
,
4134 struct node_queue_opt
*opts
)
4136 struct node_queue
*n
, *nq
;
4141 if
((pf
->loadopt
& PFCTL_FLAG_ALTQ
) == 0) {
4142 FREE_LIST
(struct node_queue
, nqueues
);
4146 if
(queues
== NULL
) {
4147 yyerror("queue %s has no parent", a
->qname
);
4148 FREE_LIST
(struct node_queue
, nqueues
);
4152 LOOP_THROUGH
(struct node_if
, interface
, interfaces
,
4153 LOOP_THROUGH
(struct node_queue
, tqueue
, queues
,
4154 if
(!strncmp
(a
->qname
, tqueue
->queue
, PF_QNAME_SIZE
) &&
4155 (interface
->ifname
[0] == 0 ||
4156 (!interface
->not
&& !strncmp
(interface
->ifname
,
4157 tqueue
->ifname
, IFNAMSIZ
)) ||
4158 (interface
->not
&& strncmp
(interface
->ifname
,
4159 tqueue
->ifname
, IFNAMSIZ
)))) {
4160 /* found ourself in queues */
4163 memcpy
(&pa
, a
, sizeof
(struct pf_altq
));
4165 if
(pa.scheduler
!= ALTQT_NONE
&&
4166 pa.scheduler
!= tqueue
->scheduler
) {
4167 yyerror("exactly one scheduler type "
4168 "per interface allowed");
4171 pa.scheduler
= tqueue
->scheduler
;
4173 /* scheduler dependent error checking */
4174 switch
(pa.scheduler
) {
4176 if
(nqueues
!= NULL
) {
4177 yyerror("priq queues cannot "
4178 "have child queues");
4181 if
(bwspec.bw_absolute
> 0 ||
4182 bwspec.bw_percent
< 100) {
4183 yyerror("priq doesn't take "
4192 if
(strlcpy
(pa.ifname
, tqueue
->ifname
,
4193 sizeof
(pa.ifname
)) >= sizeof
(pa.ifname
))
4194 errx
(1, "expand_queue: strlcpy");
4195 if
(strlcpy
(pa.parent
, tqueue
->parent
,
4196 sizeof
(pa.parent
)) >= sizeof
(pa.parent
))
4197 errx
(1, "expand_queue: strlcpy");
4199 if
(eval_pfqueue
(pf
, &pa
, &bwspec
, opts
))
4202 if
(pfctl_add_altq
(pf
, &pa
))
4205 for
(nq
= nqueues
; nq
!= NULL
; nq
= nq
->next
) {
4206 if
(!strcmp
(a
->qname
, nq
->queue
)) {
4207 yyerror("queue cannot have "
4213 sizeof
(struct node_queue
));
4215 err
(1, "expand_queue: calloc");
4216 if
(strlcpy
(n
->parent
, a
->qname
,
4217 sizeof
(n
->parent
)) >=
4219 errx
(1, "expand_queue strlcpy");
4220 if
(strlcpy
(n
->queue
, nq
->queue
,
4221 sizeof
(n
->queue
)) >=
4223 errx
(1, "expand_queue strlcpy");
4224 if
(strlcpy
(n
->ifname
, tqueue
->ifname
,
4225 sizeof
(n
->ifname
)) >=
4227 errx
(1, "expand_queue strlcpy");
4228 n
->scheduler
= tqueue
->scheduler
;
4234 queues
->tail
->next
= n
;
4238 if
((pf
->opts
& PF_OPT_VERBOSE
) && (
4239 (found
== 1 && interface
->ifname
[0] == 0) ||
4240 (found
> 0 && interface
->ifname
[0] != 0))) {
4241 print_queue
(&pf
->paltq
->altq
, 0,
4242 &bwspec
, interface
->ifname
[0] != 0,
4244 if
(nqueues
&& nqueues
->tail
) {
4246 LOOP_THROUGH
(struct node_queue
,
4259 FREE_LIST
(struct node_queue
, nqueues
);
4260 FREE_LIST
(struct node_if
, interfaces
);
4263 yyerror("queue %s has no parent", a
->qname
);
4274 expand_rule
(struct pf_rule
*r
,
4275 struct node_if
*interfaces
, struct node_host
*rpool_hosts
,
4276 struct node_proto
*protos
, struct node_os
*src_oses
,
4277 struct node_host
*src_hosts
, struct node_port
*src_ports
,
4278 struct node_host
*dst_hosts
, struct node_port
*dst_ports
,
4279 struct node_uid
*uids
, struct node_gid
*gids
, struct node_icmp
*icmp_types
)
4281 sa_family_t af
= r
->af
;
4282 int added
= 0, error = 0;
4283 char ifname
[IF_NAMESIZE
];
4284 char label
[PF_RULE_LABEL_SIZE
];
4285 char tagname
[PF_TAG_NAME_SIZE
];
4286 char match_tagname
[PF_TAG_NAME_SIZE
];
4287 struct pf_pooladdr
*pa
;
4288 struct node_host
*h
;
4289 u_int8_t flags
, flagset
, keep_state
;
4291 if
(strlcpy
(label
, r
->label
, sizeof
(label
)) >= sizeof
(label
))
4292 errx
(1, "expand_rule: strlcpy");
4293 if
(strlcpy
(tagname
, r
->tagname
, sizeof
(tagname
)) >= sizeof
(tagname
))
4294 errx
(1, "expand_rule: strlcpy");
4295 if
(strlcpy
(match_tagname
, r
->match_tagname
, sizeof
(match_tagname
)) >=
4296 sizeof
(match_tagname
))
4297 errx
(1, "expand_rule: strlcpy");
4299 flagset
= r
->flagset
;
4300 keep_state
= r
->keep_state
;
4302 LOOP_THROUGH
(struct node_if
, interface
, interfaces
,
4303 LOOP_THROUGH
(struct node_proto
, proto
, protos
,
4304 LOOP_THROUGH
(struct node_icmp
, icmp_type
, icmp_types
,
4305 LOOP_THROUGH
(struct node_host
, src_host
, src_hosts
,
4306 LOOP_THROUGH
(struct node_port
, src_port
, src_ports
,
4307 LOOP_THROUGH
(struct node_os
, src_os
, src_oses
,
4308 LOOP_THROUGH
(struct node_host
, dst_host
, dst_hosts
,
4309 LOOP_THROUGH
(struct node_port
, dst_port
, dst_ports
,
4310 LOOP_THROUGH
(struct node_uid
, uid
, uids
,
4311 LOOP_THROUGH
(struct node_gid
, gid
, gids
,
4314 /* for link-local IPv6 address, interface must match up */
4315 if
((r
->af
&& src_host
->af
&& r
->af
!= src_host
->af
) ||
4316 (r
->af
&& dst_host
->af
&& r
->af
!= dst_host
->af
) ||
4317 (src_host
->af
&& dst_host
->af
&&
4318 src_host
->af
!= dst_host
->af
) ||
4319 (src_host
->ifindex
&& dst_host
->ifindex
&&
4320 src_host
->ifindex
!= dst_host
->ifindex
) ||
4321 (src_host
->ifindex
&& *interface
->ifname
&&
4322 src_host
->ifindex
!= if_nametoindex
(interface
->ifname
)) ||
4323 (dst_host
->ifindex
&& *interface
->ifname
&&
4324 dst_host
->ifindex
!= if_nametoindex
(interface
->ifname
)))
4326 if
(!r
->af
&& src_host
->af
)
4327 r
->af
= src_host
->af
;
4328 else if
(!r
->af
&& dst_host
->af
)
4329 r
->af
= dst_host
->af
;
4331 if
(*interface
->ifname
)
4332 memcpy
(r
->ifname
, interface
->ifname
, sizeof
(r
->ifname
));
4333 else if
(if_indextoname
(src_host
->ifindex
, ifname
))
4334 memcpy
(r
->ifname
, ifname
, sizeof
(r
->ifname
));
4335 else if
(if_indextoname
(dst_host
->ifindex
, ifname
))
4336 memcpy
(r
->ifname
, ifname
, sizeof
(r
->ifname
));
4338 memset
(r
->ifname
, '\0', sizeof
(r
->ifname
));
4340 if
(strlcpy
(r
->label
, label
, sizeof
(r
->label
)) >=
4342 errx
(1, "expand_rule: strlcpy");
4343 if
(strlcpy
(r
->tagname
, tagname
, sizeof
(r
->tagname
)) >=
4345 errx
(1, "expand_rule: strlcpy");
4346 if
(strlcpy
(r
->match_tagname
, match_tagname
,
4347 sizeof
(r
->match_tagname
)) >= sizeof
(r
->match_tagname
))
4348 errx
(1, "expand_rule: strlcpy");
4349 expand_label
(r
->label
, PF_RULE_LABEL_SIZE
, r
->ifname
, r
->af
,
4350 src_host
, src_port
, dst_host
, dst_port
, proto
->proto
);
4351 expand_label
(r
->tagname
, PF_TAG_NAME_SIZE
, r
->ifname
, r
->af
,
4352 src_host
, src_port
, dst_host
, dst_port
, proto
->proto
);
4353 expand_label
(r
->match_tagname
, PF_TAG_NAME_SIZE
, r
->ifname
,
4354 r
->af
, src_host
, src_port
, dst_host
, dst_port
,
4357 error += check_netmask
(src_host
, r
->af
);
4358 error += check_netmask
(dst_host
, r
->af
);
4360 r
->ifnot
= interface
->not
;
4361 r
->proto
= proto
->proto
;
4362 r
->src.addr
= src_host
->addr
;
4363 r
->src.not
= src_host
->not
;
4364 r
->src.port
[0] = src_port
->port
[0];
4365 r
->src.port
[1] = src_port
->port
[1];
4366 r
->src.port_op
= src_port
->op
;
4367 r
->dst.addr
= dst_host
->addr
;
4368 r
->dst.not
= dst_host
->not
;
4369 r
->dst.port
[0] = dst_port
->port
[0];
4370 r
->dst.port
[1] = dst_port
->port
[1];
4371 r
->dst.port_op
= dst_port
->op
;
4372 r
->uid.op
= uid
->op
;
4373 r
->uid.uid
[0] = uid
->uid
[0];
4374 r
->uid.uid
[1] = uid
->uid
[1];
4375 r
->gid.op
= gid
->op
;
4376 r
->gid.gid
[0] = gid
->gid
[0];
4377 r
->gid.gid
[1] = gid
->gid
[1];
4378 r
->type
= icmp_type
->type
;
4379 r
->code
= icmp_type
->code
;
4381 if
((keep_state
== PF_STATE_MODULATE ||
4382 keep_state
== PF_STATE_SYNPROXY
) &&
4383 r
->proto
&& r
->proto
!= IPPROTO_TCP
)
4384 r
->keep_state
= PF_STATE_NORMAL
;
4386 r
->keep_state
= keep_state
;
4388 if
(r
->proto
&& r
->proto
!= IPPROTO_TCP
) {
4393 r
->flagset
= flagset
;
4395 if
(icmp_type
->proto
&& r
->proto
!= icmp_type
->proto
) {
4396 yyerror("icmp-type mismatch");
4400 if
(src_os
&& src_os
->os
) {
4401 r
->os_fingerprint
= pfctl_get_fingerprint
(src_os
->os
);
4402 if
((pf
->opts
& PF_OPT_VERBOSE2
) &&
4403 r
->os_fingerprint
== PF_OSFP_NOMATCH
)
4405 "warning: unknown '%s' OS fingerprint\n",
4408 r
->os_fingerprint
= PF_OSFP_ANY
;
4411 TAILQ_INIT
(&r
->rpool.list
);
4412 for
(h
= rpool_hosts
; h
!= NULL
; h
= h
->next
) {
4413 pa
= calloc
(1, sizeof
(struct pf_pooladdr
));
4415 err
(1, "expand_rule: calloc");
4417 if
(h
->ifname
!= NULL
) {
4418 if
(strlcpy
(pa
->ifname
, h
->ifname
,
4419 sizeof
(pa
->ifname
)) >=
4421 errx
(1, "expand_rule: strlcpy");
4424 TAILQ_INSERT_TAIL
(&r
->rpool.list
, pa
, entries
);
4427 if
(rule_consistent
(r
) < 0 ||
error)
4428 yyerror("skipping rule due to errors");
4430 r
->nr
= pf
->rule_nr
++;
4431 pfctl_add_rule
(pf
, r
);
4437 FREE_LIST
(struct node_if
, interfaces
);
4438 FREE_LIST
(struct node_proto
, protos
);
4439 FREE_LIST
(struct node_host
, src_hosts
);
4440 FREE_LIST
(struct node_port
, src_ports
);
4441 FREE_LIST
(struct node_os
, src_oses
);
4442 FREE_LIST
(struct node_host
, dst_hosts
);
4443 FREE_LIST
(struct node_port
, dst_ports
);
4444 FREE_LIST
(struct node_uid
, uids
);
4445 FREE_LIST
(struct node_gid
, gids
);
4446 FREE_LIST
(struct node_icmp
, icmp_types
);
4447 FREE_LIST
(struct node_host
, rpool_hosts
);
4450 yyerror("rule expands to no valid combination");
4457 check_rulestate
(int desired_state
)
4459 if
(require_order
&& (rulestate
> desired_state
)) {
4460 yyerror("Rules must be in order: options, normalization, "
4461 "queueing, translation, filtering");
4464 rulestate
= desired_state
;
4469 kw_cmp
(const void *k
, const void *e
)
4471 return
(strcmp
(k
, ((const struct keywords
*)e
)->k_name
));
4477 /* this has to be sorted always */
4478 static const struct keywords keywords
[] = {
4480 { "allow-opts", ALLOWOPTS
},
4482 { "anchor", ANCHOR
},
4483 { "antispoof", ANTISPOOF
},
4485 { "bandwidth", BANDWIDTH
},
4487 { "binat-anchor", BINATANCHOR
},
4488 { "bitmask", BITMASK
},
4490 { "block-policy", BLOCKPOLICY
},
4491 { "buckets", BUCKETS
},
4494 { "crop", FRAGCROP
},
4497 { "drop-ovl", FRAGDROP
},
4500 { "fastroute", FASTROUTE
},
4501 { "file", FILENAME
},
4502 { "fingerprints", FINGERPRINTS
},
4504 { "floating", FLOATING
},
4506 { "fragment", FRAGMENT
},
4508 { "global", GLOBAL
},
4510 { "group-bound", GRBOUND
},
4511 { "hash-only", HASHONLY
},
4514 { "hostid", HOSTID
},
4515 { "icmp-type", ICMPTYPE
},
4516 { "icmp6-type", ICMP6TYPE
},
4517 { "if-bound", IFBOUND
},
4522 { "keep-policy", KEEPPOLICY
},
4525 { "linkshare", LINKSHARE
},
4528 { "log-all", LOGALL
},
4529 { "loginterface", LOGINTERFACE
},
4531 { "max-mss", MAXMSS
},
4532 { "max-src-nodes", MAXSRCNODES
},
4533 { "max-src-states", MAXSRCSTATES
},
4534 { "min-ttl", MINTTL
},
4535 { "modulate", MODULATE
},
4537 { "nat-anchor", NATANCHOR
},
4540 { "no-pickups", NOPICKUPS
},
4541 { "no-route", NOROUTE
},
4542 { "no-sync", NOSYNC
},
4544 { "optimization", OPTIMIZATION
},
4548 { "pickups", PICKUPS
},
4550 { "priority", PRIORITY
},
4552 { "probability", PROBABILITY
},
4554 { "qlimit", QLIMIT
},
4557 { "random", RANDOM
},
4558 { "random-id", RANDOMID
},
4560 { "rdr-anchor", RDRANCHOR
},
4561 { "realtime", REALTIME
},
4562 { "reassemble", REASSEMBLE
},
4563 { "reply-to", REPLYTO
},
4564 { "require-order", REQUIREORDER
},
4565 { "return", RETURN
},
4566 { "return-icmp", RETURNICMP
},
4567 { "return-icmp6", RETURNICMP6
},
4568 { "return-rst", RETURNRST
},
4569 { "round-robin", ROUNDROBIN
},
4570 { "route-to", ROUTETO
},
4574 { "source-hash", SOURCEHASH
},
4575 { "source-track", SOURCETRACK
},
4577 { "state-policy", STATEPOLICY
},
4578 { "static-port", STATICPORT
},
4579 { "sticky-address", STICKYADDRESS
},
4580 { "synproxy", SYNPROXY
},
4583 { "tagged", TAGGED
},
4584 { "tbrsize", TBRSIZE
},
4585 { "timeout", TIMEOUT
},
4589 { "upperlimit", UPPERLIMIT
},
4592 const struct keywords
*p
;
4594 p
= bsearch
(s
, keywords
, sizeof
(keywords
)/sizeof
(keywords
[0]),
4595 sizeof
(keywords
[0]), kw_cmp
);
4599 fprintf
(stderr
, "%s: %d\n", s
, p
->k_val
);
4603 fprintf
(stderr
, "string: %s\n", s
);
4608 #define MAXPUSHBACK 128
4612 char pushback_buffer
[MAXPUSHBACK
];
4613 int pushback_index
= 0;
4621 /* Read character from the parsebuffer instead of input. */
4622 if
(parseindex
>= 0) {
4623 c
= parsebuf
[parseindex
++];
4632 return
(pushback_buffer
[--pushback_index
]);
4634 while
((c
= getc
(f
)) == '\\') {
4638 yyerror("whitespace after \\");
4642 yylval.lineno
= lineno
;
4645 if
(c
== '\t' || c
== ' ') {
4646 /* Compress blanks to a single space. */
4649 } while
(c
== '\t' || c
== ' ');
4664 if
(parseindex
>= 0)
4667 if
(pushback_index
< MAXPUSHBACK
-1)
4668 return
(pushback_buffer
[pushback_index
++] = c
);
4681 /* skip to either EOF or the first real EOL */
4704 while
((c
= lgetc
(fin
)) == ' ')
4707 yylval.lineno
= lineno
;
4709 while
((c
= lgetc
(fin
)) != '\n' && c
!= EOF
)
4711 if
(c
== '$' && parsebuf
== NULL
) {
4713 if
((c
= lgetc
(fin
)) == EOF
)
4716 if
(p
+ 1 >= buf
+ sizeof
(buf
) - 1) {
4717 yyerror("string too long");
4720 if
(isalnum
(c
) || c
== '_') {
4730 yyerror("macro '%s' not defined", buf
);
4743 if
((c
= lgetc
(fin
)) == EOF
)
4753 if
(p
+ 1 >= buf
+ sizeof
(buf
) - 1) {
4754 yyerror("string too long");
4759 yylval.v.
string = strdup
(buf
);
4760 if
(yylval.v.
string == NULL
)
4761 err
(1, "yylex: strdup");
4766 yylval.v.i
= PF_OP_XRG
;
4767 return
(PORTBINARY
);
4774 yylval.v.i
= PF_OP_IRG
;
4775 return
(PORTBINARY
);
4787 #define allowed_in_string(x) \
4788 (isalnum
(x
) ||
(ispunct
(x
) && x
!= '(' && x
!= ')' && \
4789 x
!= '{' && x
!= '}' && x
!= '<' && x
!= '>' && \
4790 x
!= '!' && x
!= '=' && x
!= '/' && x
!= '#' && \
4793 if
(isalnum
(c
) || c
== ':' || c
== '_') {
4796 if
((unsigned)(p
-buf
) >= sizeof
(buf
)) {
4797 yyerror("string too long");
4800 } while
((c
= lgetc
(fin
)) != EOF
&& (allowed_in_string
(c
)));
4803 if
((token
= lookup
(buf
)) == STRING
)
4804 if
((yylval.v.
string = strdup
(buf
)) == NULL
)
4805 err
(1, "yylex: strdup");
4809 yylval.lineno
= lineno
;
4818 parse_rules
(FILE *input
, struct pfctl
*xpf
)
4820 struct sym
*sym
, *next
;
4826 rulestate
= PFCTL_STATE_NONE
;
4827 returnicmpdefault
= (ICMP_UNREACH
<< 8) | ICMP_UNREACH_PORT
;
4828 returnicmp6default
=
4829 (ICMP6_DST_UNREACH
<< 8) | ICMP6_DST_UNREACH_NOPORT
;
4830 blockpolicy
= PFRULE_DROP
;
4835 /* Free macros and check which have not been used. */
4836 for
(sym
= TAILQ_FIRST
(&symhead
); sym
!= NULL
; sym
= next
) {
4837 next
= TAILQ_NEXT
(sym
, entries
);
4838 if
((pf
->opts
& PF_OPT_VERBOSE2
) && !sym
->used
)
4839 fprintf
(stderr
, "warning: macro '%s' not "
4840 "used\n", sym
->nam
);
4843 TAILQ_REMOVE
(&symhead
, sym
, entries
);
4847 return
(errors ?
-1 : 0);
4851 * Over-designed efficiency is a French and German concept, so how about
4852 * we wait until they discover this ugliness and make it all fancy.
4855 symset
(const char *nam
, const char *val
, int persist
)
4859 for
(sym
= TAILQ_FIRST
(&symhead
); sym
&& strcmp
(nam
, sym
->nam
);
4860 sym
= TAILQ_NEXT
(sym
, entries
))
4864 if
(sym
->persist
== 1)
4869 TAILQ_REMOVE
(&symhead
, sym
, entries
);
4873 if
((sym
= calloc
(1, sizeof
(*sym
))) == NULL
)
4876 sym
->nam
= strdup
(nam
);
4877 if
(sym
->nam
== NULL
) {
4881 sym
->val
= strdup
(val
);
4882 if
(sym
->val
== NULL
) {
4888 sym
->persist
= persist
;
4889 TAILQ_INSERT_TAIL
(&symhead
, sym
, entries
);
4894 pfctl_cmdline_symset
(char *s
)
4899 if
((val
= strrchr
(s
, '=')) == NULL
)
4902 if
((sym
= malloc
(strlen
(s
) - strlen
(val
) + 1)) == NULL
)
4903 err
(1, "pfctl_cmdline_symset: malloc");
4905 strlcpy
(sym
, s
, strlen
(s
) - strlen
(val
) + 1);
4907 ret
= symset
(sym
, val
+ 1, 1);
4914 symget
(const char *nam
)
4918 TAILQ_FOREACH
(sym
, &symhead
, entries
)
4919 if
(strcmp
(nam
, sym
->nam
) == 0) {
4927 decide_address_family
(struct node_host
*n
, sa_family_t
*af
)
4929 sa_family_t target_af
= 0;
4931 while
(!*af
&& n
!= NULL
) {
4935 if
(target_af
!= n
->af
)
4940 if
(!*af
&& target_af
)
4945 remove_invalid_hosts
(struct node_host
**nh
, sa_family_t
*af
)
4947 struct node_host
*n
= *nh
, *prev
= NULL
;
4950 if
(*af
&& n
->af
&& n
->af
!= *af
) {
4951 /* unlink and free n */
4952 struct node_host
*next
= n
->next
;
4954 /* adjust tail pointer */
4955 if
(n
== (*nh
)->tail
)
4957 /* adjust previous node's next pointer */
4963 if
(n
->ifname
!= NULL
)
4977 invalid_redirect
(struct node_host
*nh
, sa_family_t af
)
4980 struct node_host
*n
;
4982 /* tables and dyniftl are ok without an address family */
4983 for
(n
= nh
; n
!= NULL
; n
= n
->next
) {
4984 if
(n
->addr.type
!= PF_ADDR_TABLE
&&
4985 n
->addr.type
!= PF_ADDR_DYNIFTL
) {
4986 yyerror("address family not given and "
4987 "translation address expands to multiple "
4988 "address families");
4994 yyerror("no translation address with matching address family "
5002 atoul
(char *s
, u_long
*ulvalp
)
5008 ulval
= strtoul
(s
, &ep
, 0);
5009 if
(s
[0] == '\0' ||
*ep
!= '\0')
5011 if
(errno
== ERANGE
&& ulval
== ULONG_MAX
)
5023 if
(atoul
(n
, &ulval
) == 0) {
5024 if
(ulval
> 65535) {
5025 yyerror("illegal port value %d", ulval
);
5028 return
(htons
(ulval
));
5030 s
= getservbyname
(n
, "tcp");
5032 s
= getservbyname
(n
, "udp");
5034 yyerror("unknown port %s", n
);
5042 rule_label
(struct pf_rule
*r
, char *s
)
5045 if
(strlcpy
(r
->label
, s
, sizeof
(r
->label
)) >=
5047 yyerror("rule label too long (max %d chars)",
5048 sizeof
(r
->label
)-1);
5056 parseicmpspec
(char *w
, sa_family_t af
)
5058 const struct icmpcodeent
*p
;
5063 icmptype
= returnicmpdefault
>> 8;
5065 icmptype
= returnicmp6default
>> 8;
5067 if
(atoul
(w
, &ulval
) == -1) {
5068 if
((p
= geticmpcodebyname
(icmptype
, w
, af
)) == NULL
) {
5069 yyerror("unknown icmp code %s", w
);
5075 yyerror("invalid icmp code %ld", ulval
);
5078 return
(icmptype
<< 8 | ulval
);
5082 pfctl_load_anchors
(int dev
, int opts
, struct pfr_buffer
*trans
)
5084 struct loadanchors
*la
;
5086 TAILQ_FOREACH
(la
, &loadanchorshead
, entries
) {
5087 if
(opts
& PF_OPT_VERBOSE
)
5088 fprintf
(stderr
, "\nLoading anchor %s:%s from %s\n",
5089 la
->anchorname
, la
->rulesetname
, la
->filename
);
5090 if
(pfctl_rules
(dev
, la
->filename
, opts
, la
->anchorname
,
5091 la
->rulesetname
, trans
) == -1)