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.2 2005/02/11 23:31:45 joerg 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>
59 #include "pfctl_parser.h"
62 static struct pfctl
*pf
= NULL
;
63 static FILE *fin
= NULL
;
65 static int lineno
= 1;
66 static int errors
= 0;
67 static int rulestate
= 0;
68 static u_int16_t returnicmpdefault
=
69 (ICMP_UNREACH
<< 8) | ICMP_UNREACH_PORT
;
70 static u_int16_t returnicmp6default
=
71 (ICMP6_DST_UNREACH
<< 8) | ICMP6_DST_UNREACH_NOPORT
;
72 static int blockpolicy
= PFRULE_DROP
;
73 static int require_order
= 1;
74 static int default_statelock
;
87 struct node_proto
*next
;
88 struct node_proto
*tail
;
94 struct node_port
*next
;
95 struct node_port
*tail
;
101 struct node_uid
*next
;
102 struct node_uid
*tail
;
108 struct node_gid
*next
;
109 struct node_gid
*tail
;
116 struct node_icmp
*next
;
117 struct node_icmp
*tail
;
120 enum { PF_STATE_OPT_MAX
, PF_STATE_OPT_NOSYNC
, PF_STATE_OPT_SRCTRACK
,
121 PF_STATE_OPT_MAX_SRC_STATES
, PF_STATE_OPT_MAX_SRC_NODES
,
122 PF_STATE_OPT_STATELOCK
, PF_STATE_OPT_TIMEOUT
};
124 enum { PF_SRCTRACK_NONE
, PF_SRCTRACK
, PF_SRCTRACK_GLOBAL
, PF_SRCTRACK_RULE
};
126 struct node_state_opt
{
129 u_int32_t max_states
;
130 u_int32_t max_src_states
;
131 u_int32_t max_src_nodes
;
139 struct node_state_opt
*next
;
140 struct node_state_opt
*tail
;
144 struct node_host
*host
;
145 struct node_port
*port
;
149 char queue
[PF_QNAME_SIZE
];
150 char parent
[PF_QNAME_SIZE
];
151 char ifname
[IFNAMSIZ
];
153 struct node_queue
*next
;
154 struct node_queue
*tail
;
157 struct node_qassign
{
164 #define FOM_FLAGS 0x01
165 #define FOM_ICMP 0x02
167 #define FOM_KEEP 0x08
168 #define FOM_SRCTRACK 0x10
169 struct node_uid
*uid
;
170 struct node_gid
*gid
;
177 struct node_icmp
*icmpspec
;
181 struct node_state_opt
*options
;
186 struct node_qassign queues
;
189 u_int8_t match_tag_not
;
192 struct antispoof_opts
{
198 #define SOM_MINTTL 0x01
199 #define SOM_MAXMSS 0x02
200 #define SOM_FRAGCACHE 0x04
211 #define QOM_BWSPEC 0x01
212 #define QOM_SCHEDULER 0x02
213 #define QOM_PRIORITY 0x04
214 #define QOM_TBRSIZE 0x08
215 #define QOM_QLIMIT 0x10
216 struct node_queue_bw queue_bwspec
;
217 struct node_queue_opt scheduler
;
226 struct node_tinithead init_nodes
;
231 #define POM_TYPE 0x01
232 #define POM_STICKYADDRESS 0x02
236 struct pf_poolhashkey
*key
;
241 struct node_hfsc_opts hfsc_opts
;
243 int yyerror(const char *, ...
);
244 int disallow_table
(struct node_host
*, const char *);
245 int disallow_alias
(struct node_host
*, const char *);
246 int rule_consistent
(struct pf_rule
*);
247 int filter_consistent
(struct pf_rule
*);
248 int nat_consistent
(struct pf_rule
*);
249 int rdr_consistent
(struct pf_rule
*);
250 int process_tabledef
(char *, struct table_opts
*);
252 void expand_label_str
(char *, size_t, const char *, const char *);
253 void expand_label_if
(const char *, char *, size_t, const char *);
254 void expand_label_addr
(const char *, char *, size_t, u_int8_t
,
256 void expand_label_port
(const char *, char *, size_t, struct node_port
*);
257 void expand_label_proto
(const char *, char *, size_t, u_int8_t
);
258 void expand_label_nr
(const char *, char *, size_t);
259 void expand_label
(char *, size_t, const char *, u_int8_t
, struct node_host
*,
260 struct node_port
*, struct node_host
*, struct node_port
*,
262 void expand_rule
(struct pf_rule
*, struct node_if
*, struct node_host
*,
263 struct node_proto
*, struct node_os
*, struct node_host
*,
264 struct node_port
*, struct node_host
*, struct node_port
*,
265 struct node_uid
*, struct node_gid
*, struct node_icmp
*);
266 int expand_altq
(struct pf_altq
*, struct node_if
*, struct node_queue
*,
267 struct node_queue_bw bwspec
, struct node_queue_opt
*);
268 int expand_queue
(struct pf_altq
*, struct node_if
*, struct node_queue
*,
269 struct node_queue_bw
, struct node_queue_opt
*);
271 int check_rulestate
(int);
272 int kw_cmp
(const void *, const void *);
278 int atoul
(char *, u_long
*);
279 int getservice
(char *);
280 int rule_label
(struct pf_rule
*, char *);
282 TAILQ_HEAD
(symhead
, sym
) symhead
= TAILQ_HEAD_INITIALIZER
(symhead
);
284 TAILQ_ENTRY
(sym
) entries
;
292 int symset
(const char *, const char *, int);
293 char *symget
(const char *);
295 void decide_address_family
(struct node_host
*, sa_family_t
*);
296 void remove_invalid_hosts
(struct node_host
**, sa_family_t
*);
297 int invalid_redirect
(struct node_host
*, sa_family_t
);
298 u_int16_t parseicmpspec
(char *, sa_family_t
);
300 TAILQ_HEAD
(loadanchorshead
, loadanchors
)
301 loadanchorshead
= TAILQ_HEAD_INITIALIZER
(loadanchorshead
);
304 TAILQ_ENTRY
(loadanchors
) entries
;
326 struct node_if
*interface
;
327 struct node_proto
*proto
;
328 struct node_icmp
*icmp
;
329 struct node_host
*host
;
331 struct node_port
*port
;
332 struct node_uid
*uid
;
333 struct node_gid
*gid
;
334 struct node_state_opt
*state_opt
;
337 struct peer src
, dst
;
338 struct node_os
*src_os
;
341 struct node_host
*host
;
345 struct pf_poolhashkey
*key
;
348 struct node_host
*host
;
353 struct node_state_opt
*options
;
359 struct pf_poolhashkey
*hashkey
;
360 struct node_queue
*queue
;
361 struct node_queue_opt queue_options
;
362 struct node_queue_bw queue_bwspec
;
363 struct node_qassign qassign
;
364 struct filter_opts filter_opts
;
365 struct antispoof_opts antispoof_opts
;
366 struct queue_opts queue_opts
;
367 struct scrub_opts scrub_opts
;
368 struct table_opts table_opts
;
369 struct pool_opts pool_opts
;
370 struct node_hfsc_opts hfsc_opts
;
375 #define PREPARE_ANCHOR_RULE(r, a) \
377 memset
(&(r
), 0, sizeof
(r
)); \
378 if
(strlcpy
(r.anchorname
, (a
), \
379 sizeof
(r.anchorname
)) >= \
380 sizeof
(r.anchorname
)) { \
381 yyerror("anchor name '%s' too long", \
387 #define DYNIF_MULTIADDR(addr) ((addr).type == PF_ADDR_DYNIFTL && \
388 (!((addr
).iflags
& PFI_AFLAG_NOALIAS
) || \
389 !isdigit
((addr
).v.ifname
[strlen
((addr
).v.ifname
)-1])))
395 %token PASS BLOCK SCRUB RETURN IN OS OUT LOG LOGALL QUICK ON FROM TO FLAGS
396 %token RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE
397 %token ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF
398 %token MINTTL ERROR ALLOWOPTS FASTROUTE FILENAME ROUTETO DUPTO REPLYTO NO LABEL
399 %token NOROUTE FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DROP TABLE
400 %token REASSEMBLE FRAGDROP FRAGCROP ANCHOR NATANCHOR RDRANCHOR BINATANCHOR
401 %token SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY RANDOMID
402 %token REQUIREORDER SYNPROXY FINGERPRINTS NOSYNC DEBUG HOSTID
404 %token BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT
405 %token ALTQ CBQ PRIQ HFSC BANDWIDTH TBRSIZE LINKSHARE REALTIME UPPERLIMIT
406 %token QUEUE PRIORITY QLIMIT
408 %token STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE
409 %token TAGGED TAG IFBOUND GRBOUND FLOATING STATEPOLICY
410 %token
<v.
string> STRING
411 %token
<v.i
> PORTBINARY
412 %type
<v.interface
> interface if_list if_item_not if_item
413 %type
<v.number
> number icmptype icmp6type uid gid
414 %type
<v.number
> tos not yesno natpass
415 %type
<v.i
> no dir log af fragcache sourcetrack
416 %type
<v.i
> unaryop statelock
417 %type
<v.b
> action nataction flags flag blockspec
418 %type
<v.range
> port rport
419 %type
<v.hashkey
> hashkey
420 %type
<v.proto
> proto proto_list proto_item
421 %type
<v.icmp
> icmpspec
422 %type
<v.icmp
> icmp_list icmp_item
423 %type
<v.icmp
> icmp6_list icmp6_item
424 %type
<v.fromto
> fromto
425 %type
<v.peer
> ipportspec from to
426 %type
<v.host
> ipspec xhost host dynaddr host_list
427 %type
<v.host
> redir_host_list redirspec
428 %type
<v.host
> route_host route_host_list routespec
429 %type
<v.os
> os xos os_list
430 %type
<v.port
> portspec port_list port_item
431 %type
<v.uid
> uids uid_list uid_item
432 %type
<v.gid
> gids gid_list gid_item
433 %type
<v.route
> route
434 %type
<v.redirection
> redirection redirpool
435 %type
<v.
string> label
string tag
436 %type
<v.keep_state
> keep
437 %type
<v.state_opt
> state_opt_spec state_opt_list state_opt_item
438 %type
<v.logquick
> logquick
439 %type
<v.interface
> antispoof_ifspc antispoof_iflst
440 %type
<v.qassign
> qname
441 %type
<v.queue
> qassign qassign_list qassign_item
442 %type
<v.queue_options
> scheduler
443 %type
<v.number
> cbqflags_list cbqflags_item
444 %type
<v.number
> priqflags_list priqflags_item
445 %type
<v.hfsc_opts
> hfscopts_list hfscopts_item hfsc_opts
446 %type
<v.queue_bwspec
> bandwidth
447 %type
<v.filter_opts
> filter_opts filter_opt filter_opts_l
448 %type
<v.antispoof_opts
> antispoof_opts antispoof_opt antispoof_opts_l
449 %type
<v.queue_opts
> queue_opts queue_opt queue_opts_l
450 %type
<v.scrub_opts
> scrub_opts scrub_opt scrub_opts_l
451 %type
<v.table_opts
> table_opts table_opt table_opts_l
452 %type
<v.pool_opts
> pool_opts pool_opt pool_opts_l
455 ruleset
: /* empty */
457 | ruleset option
'\n'
458 | ruleset scrubrule
'\n'
459 | ruleset natrule
'\n'
460 | ruleset binatrule
'\n'
461 | ruleset pfrule
'\n'
462 | ruleset anchorrule
'\n'
463 | ruleset loadrule
'\n'
464 | ruleset altqif
'\n'
465 | ruleset queuespec
'\n'
466 | ruleset varset
'\n'
467 | ruleset antispoof
'\n'
468 | ruleset tabledef
'\n'
469 | ruleset
error '\n' { errors
++; }
472 option
: SET OPTIMIZATION STRING
{
473 if
(check_rulestate
(PFCTL_STATE_OPTION
)) {
477 if
(pfctl_set_optimization
(pf
, $3) != 0) {
478 yyerror("unknown optimization %s", $3);
484 | SET TIMEOUT timeout_spec
485 | SET TIMEOUT
'{' timeout_list
'}'
486 | SET LIMIT limit_spec
487 | SET LIMIT
'{' limit_list
'}'
488 | SET LOGINTERFACE STRING
{
489 if
(check_rulestate
(PFCTL_STATE_OPTION
)) {
493 if
((ifa_exists
($3, 0) == NULL
) && strcmp
($3, "none")) {
494 yyerror("interface %s doesn't exist", $3);
498 if
(pfctl_set_logif
(pf
, $3) != 0) {
499 yyerror("error setting loginterface %s", $3);
505 | SET HOSTID number
{
507 yyerror("hostid must be non-zero");
510 if
(pfctl_set_hostid
(pf
, $3) != 0) {
511 yyerror("error setting loginterface %08x", $3);
515 | SET BLOCKPOLICY DROP
{
516 if
(pf
->opts
& PF_OPT_VERBOSE
)
517 printf
("set block-policy drop\n");
518 if
(check_rulestate
(PFCTL_STATE_OPTION
))
520 blockpolicy
= PFRULE_DROP
;
522 | SET BLOCKPOLICY RETURN
{
523 if
(pf
->opts
& PF_OPT_VERBOSE
)
524 printf
("set block-policy return\n");
525 if
(check_rulestate
(PFCTL_STATE_OPTION
))
527 blockpolicy
= PFRULE_RETURN
;
529 | SET REQUIREORDER yesno
{
530 if
(pf
->opts
& PF_OPT_VERBOSE
)
531 printf
("set require-order %s\n",
532 $3 == 1 ?
"yes" : "no");
535 | SET FINGERPRINTS STRING
{
536 if
(pf
->opts
& PF_OPT_VERBOSE
)
537 printf
("fingerprints %s\n", $3);
538 if
(check_rulestate
(PFCTL_STATE_OPTION
)) {
542 if
(pfctl_file_fingerprints
(pf
->dev
, pf
->opts
, $3)) {
543 yyerror("error loading fingerprints %s", $3);
549 | SET STATEPOLICY statelock
{
550 if
(pf
->opts
& PF_OPT_VERBOSE
)
553 printf
("set state-policy floating\n");
556 printf
("set state-policy if-bound\n");
559 printf
("set state-policy "
563 default_statelock
= $3;
566 if
(check_rulestate
(PFCTL_STATE_OPTION
)) {
570 if
(pfctl_set_debug
(pf
, $3) != 0) {
571 yyerror("error setting debuglevel %s", $3);
579 string : string STRING
{
580 if
(asprintf
(&$$
, "%s %s", $1, $2) == -1)
581 err
(1, "string: asprintf");
588 varset
: STRING
'=' string {
589 if
(pf
->opts
& PF_OPT_VERBOSE
)
590 printf
("%s = \"%s\"\n", $1, $3);
591 if
(symset
($1, $3, 0) == -1)
592 err
(1, "cannot store variable %s", $1);
598 anchorrule
: ANCHOR
string dir interface af proto fromto filter_opts
{
601 if
(check_rulestate
(PFCTL_STATE_FILTER
)) {
606 PREPARE_ANCHOR_RULE
(r
, $2);
611 if
(strlcpy
(r.match_tagname
, $8.match_tag
,
612 PF_TAG_NAME_SIZE
) >= PF_TAG_NAME_SIZE
) {
613 yyerror("tag too long, max %u chars",
614 PF_TAG_NAME_SIZE
- 1);
617 r.match_tag_not
= $8.match_tag_not
;
619 decide_address_family
($7.src.host
, &r.af
);
620 decide_address_family
($7.dst.host
, &r.af
);
622 expand_rule
(&r
, $4, NULL
, $6, $7.src_os
,
623 $7.src.host
, $7.src.port
, $7.dst.host
, $7.dst.port
,
626 | NATANCHOR
string interface af proto fromto
{
629 if
(check_rulestate
(PFCTL_STATE_NAT
)) {
634 PREPARE_ANCHOR_RULE
(r
, $2);
639 decide_address_family
($6.src.host
, &r.af
);
640 decide_address_family
($6.dst.host
, &r.af
);
642 expand_rule
(&r
, $3, NULL
, $5, $6.src_os
,
643 $6.src.host
, $6.src.port
, $6.dst.host
, $6.dst.port
,
646 | RDRANCHOR
string interface af proto fromto
{
649 if
(check_rulestate
(PFCTL_STATE_NAT
)) {
654 PREPARE_ANCHOR_RULE
(r
, $2);
659 decide_address_family
($6.src.host
, &r.af
);
660 decide_address_family
($6.dst.host
, &r.af
);
662 if
($6.src.port
!= NULL
) {
663 yyerror("source port parameter not supported"
667 if
($6.dst.port
!= NULL
) {
668 if
($6.dst.port
->next
!= NULL
) {
669 yyerror("destination port list "
670 "expansion not supported in "
673 } else if
($6.dst.port
->op
!= PF_OP_EQ
) {
674 yyerror("destination port operators"
675 " not supported in rdr-anchor");
678 r.dst.port
[0] = $6.dst.port
->port
[0];
679 r.dst.port
[1] = $6.dst.port
->port
[1];
680 r.dst.port_op
= $6.dst.port
->op
;
683 expand_rule
(&r
, $3, NULL
, $5, $6.src_os
,
684 $6.src.host
, $6.src.port
, $6.dst.host
, $6.dst.port
,
687 | BINATANCHOR
string interface af proto fromto
{
690 if
(check_rulestate
(PFCTL_STATE_NAT
)) {
695 PREPARE_ANCHOR_RULE
(r
, $2);
700 if
($5->next
!= NULL
) {
701 yyerror("proto list expansion"
702 " not supported in binat-anchor");
709 if
($6.src.host
!= NULL ||
$6.src.port
!= NULL ||
710 $6.dst.host
!= NULL ||
$6.dst.port
!= NULL
) {
711 yyerror("fromto parameter not supported"
716 decide_address_family
($6.src.host
, &r.af
);
717 decide_address_family
($6.dst.host
, &r.af
);
719 pfctl_add_rule
(pf
, &r
);
723 loadrule
: LOAD ANCHOR
string FROM
string {
725 struct loadanchors
*loadanchor
;
727 t
= strsep
(&$3, ":");
728 if
(*t
== '\0' ||
$3 == NULL ||
*$3 == '\0') {
729 yyerror("anchor '%s' invalid\n", $3);
733 if
(strlen
(t
) >= PF_ANCHOR_NAME_SIZE
) {
734 yyerror("anchorname %s too long, max %u\n",
735 t
, PF_ANCHOR_NAME_SIZE
- 1);
739 if
(strlen
($3) >= PF_RULESET_NAME_SIZE
) {
740 yyerror("rulesetname %s too long, max %u\n",
741 $3, PF_RULESET_NAME_SIZE
- 1);
746 loadanchor
= calloc
(1, sizeof
(struct loadanchors
));
747 if
(loadanchor
== NULL
)
748 err
(1, "loadrule: calloc");
749 if
((loadanchor
->anchorname
= strdup
(t
)) == NULL
)
750 err
(1, "loadrule: strdup");
751 if
((loadanchor
->rulesetname
= strdup
($3)) == NULL
)
752 err
(1, "loadrule: strdup");
753 if
((loadanchor
->filename
= strdup
($5)) == NULL
)
754 err
(1, "loadrule: strdup");
756 TAILQ_INSERT_TAIL
(&loadanchorshead
, loadanchor
,
759 free
(t
); /* not $3 */
763 scrubrule
: SCRUB dir logquick interface af proto fromto scrub_opts
767 if
(check_rulestate
(PFCTL_STATE_SCRUB
))
770 memset
(&r
, 0, sizeof
(r
));
777 yyerror("scrub rules do not support 'quick'");
783 r.rule_flag |
= PFRULE_NODF
;
785 r.rule_flag |
= PFRULE_RANDOMID
;
786 if
($8.reassemble_tcp
) {
787 if
(r.direction
!= PF_INOUT
) {
788 yyerror("reassemble tcp rules can not "
789 "specify direction");
792 r.rule_flag |
= PFRULE_REASSEMBLE_TCP
;
795 r.min_ttl
= $8.minttl
;
797 r.max_mss
= $8.maxmss
;
799 r.rule_flag |
= $8.fragcache
;
801 expand_rule
(&r
, $4, NULL
, $6, $7.src_os
,
802 $7.src.host
, $7.src.port
, $7.dst.host
, $7.dst.port
,
808 bzero
(&scrub_opts
, sizeof scrub_opts
);
813 bzero
(&scrub_opts
, sizeof scrub_opts
);
818 scrub_opts_l
: scrub_opts_l scrub_opt
823 if
(scrub_opts.nodf
) {
824 yyerror("no-df cannot be respecified");
830 if
(scrub_opts.marker
& SOM_MINTTL
) {
831 yyerror("min-ttl cannot be respecified");
835 yyerror("illegal min-ttl value %d", $2);
838 scrub_opts.marker |
= SOM_MINTTL
;
839 scrub_opts.minttl
= $2;
842 if
(scrub_opts.marker
& SOM_MAXMSS
) {
843 yyerror("max-mss cannot be respecified");
847 yyerror("illegal max-mss value %d", $2);
850 scrub_opts.marker |
= SOM_MAXMSS
;
851 scrub_opts.maxmss
= $2;
854 if
(scrub_opts.marker
& SOM_FRAGCACHE
) {
855 yyerror("fragcache cannot be respecified");
858 scrub_opts.marker |
= SOM_FRAGCACHE
;
859 scrub_opts.fragcache
= $1;
861 | REASSEMBLE STRING
{
862 if
(strcasecmp
($2, "tcp") != 0) {
867 if
(scrub_opts.reassemble_tcp
) {
868 yyerror("reassemble tcp cannot be respecified");
871 scrub_opts.reassemble_tcp
= 1;
874 if
(scrub_opts.randomid
) {
875 yyerror("random-id cannot be respecified");
878 scrub_opts.randomid
= 1;
882 fragcache
: FRAGMENT REASSEMBLE
{ $$
= 0; /* default */ }
883 | FRAGMENT FRAGCROP
{ $$
= PFRULE_FRAGCROP
; }
884 | FRAGMENT FRAGDROP
{ $$
= PFRULE_FRAGDROP
; }
887 antispoof
: ANTISPOOF logquick antispoof_ifspc af antispoof_opts
{
889 struct node_host
*h
= NULL
;
890 struct node_if
*i
, *j
;
892 if
(check_rulestate
(PFCTL_STATE_FILTER
))
895 for
(i
= $3; i
; i
= i
->next
) {
896 bzero
(&r
, sizeof
(r
));
903 if
(rule_label
(&r
, $5.label
))
905 j
= calloc
(1, sizeof
(struct node_if
));
907 err
(1, "antispoof: calloc");
908 if
(strlcpy
(j
->ifname
, i
->ifname
,
909 sizeof
(j
->ifname
)) >= sizeof
(j
->ifname
)) {
911 yyerror("interface name too long");
915 h
= ifa_lookup
(j
->ifname
, PFI_AFLAG_NETWORK
);
918 expand_rule
(&r
, j
, NULL
, NULL
, NULL
, h
,
919 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
921 if
((i
->ifa_flags
& IFF_LOOPBACK
) == 0) {
922 bzero
(&r
, sizeof
(r
));
929 if
(rule_label
(&r
, $5.label
))
931 h
= ifa_lookup
(i
->ifname
, 0);
933 expand_rule
(&r
, NULL
, NULL
,
934 NULL
, NULL
, h
, NULL
, NULL
,
935 NULL
, NULL
, NULL
, NULL
);
942 antispoof_ifspc
: FOR if_item
{ $$
= $2; }
943 | FOR
'{' antispoof_iflst
'}' { $$
= $3; }
946 antispoof_iflst
: if_item
{ $$
= $1; }
947 | antispoof_iflst comma if_item
{
954 antispoof_opts
: { bzero
(&antispoof_opts
, sizeof antispoof_opts
); }
956 { $$
= antispoof_opts
; }
958 bzero
(&antispoof_opts
, sizeof antispoof_opts
);
963 antispoof_opts_l
: antispoof_opts_l antispoof_opt
967 antispoof_opt
: label
{
968 if
(antispoof_opts.label
) {
969 yyerror("label cannot be redefined");
972 antispoof_opts.label
= $1;
976 not
: '!' { $$
= 1; }
977 |
/* empty */ { $$
= 0; }
980 tabledef
: TABLE
'<' STRING
'>' table_opts
{
981 struct node_host
*h
, *nh
;
982 struct node_tinit
*ti
, *nti
;
984 if
(strlen
($3) >= PF_TABLE_NAME_SIZE
) {
985 yyerror("table name too long, max %d chars",
986 PF_TABLE_NAME_SIZE
- 1);
990 if
(pf
->loadopt
& PFCTL_FLAG_TABLE
)
991 if
(process_tabledef
($3, &$5)) {
996 for
(ti
= SIMPLEQ_FIRST
(&$5.init_nodes
);
997 ti
!= SIMPLEQ_END
(&$5.init_nodes
); ti
= nti
) {
1000 for
(h
= ti
->host
; h
!= NULL
; h
= nh
) {
1004 nti
= SIMPLEQ_NEXT
(ti
, entries
);
1011 bzero
(&table_opts
, sizeof table_opts
);
1012 SIMPLEQ_INIT
(&table_opts.init_nodes
);
1015 { $$
= table_opts
; }
1018 bzero
(&table_opts
, sizeof table_opts
);
1019 SIMPLEQ_INIT
(&table_opts.init_nodes
);
1024 table_opts_l
: table_opts_l table_opt
1028 table_opt
: STRING
{
1029 if
(!strcmp
($1, "const"))
1030 table_opts.flags |
= PFR_TFLAG_CONST
;
1031 else if
(!strcmp
($1, "persist"))
1032 table_opts.flags |
= PFR_TFLAG_PERSIST
;
1039 |
'{' '}' { table_opts.init_addr
= 1; }
1040 |
'{' host_list
'}' {
1041 struct node_host
*n
;
1042 struct node_tinit
*ti
;
1044 for
(n
= $2; n
!= NULL
; n
= n
->next
) {
1045 switch
(n
->addr.type
) {
1046 case PF_ADDR_ADDRMASK
:
1048 case PF_ADDR_DYNIFTL
:
1049 yyerror("dynamic addresses are not "
1050 "permitted inside tables");
1053 yyerror("tables cannot contain tables");
1055 case PF_ADDR_NOROUTE
:
1056 yyerror("\"no-route\" is not permitted "
1060 yyerror("unknown address type %d",
1065 if
(!(ti
= calloc
(1, sizeof
(*ti
))))
1066 err
(1, "table_opt: calloc");
1068 SIMPLEQ_INSERT_TAIL
(&table_opts.init_nodes
, ti
,
1070 table_opts.init_addr
= 1;
1073 struct node_tinit
*ti
;
1075 if
(!(ti
= calloc
(1, sizeof
(*ti
))))
1076 err
(1, "table_opt: calloc");
1078 SIMPLEQ_INSERT_TAIL
(&table_opts.init_nodes
, ti
,
1080 table_opts.init_addr
= 1;
1084 altqif
: ALTQ interface queue_opts QUEUE qassign
{
1087 if
(check_rulestate
(PFCTL_STATE_QUEUE
))
1090 memset
(&a
, 0, sizeof
(a
));
1091 if
($3.scheduler.qtype
== ALTQT_NONE
) {
1092 yyerror("no scheduler specified!");
1095 a.scheduler
= $3.scheduler.qtype
;
1096 a.qlimit
= $3.qlimit
;
1097 a.tbrsize
= $3.tbrsize
;
1099 yyerror("no child queues specified");
1102 if
(expand_altq
(&a
, $2, $5, $3.queue_bwspec
,
1108 queuespec
: QUEUE STRING interface queue_opts qassign
{
1111 if
(check_rulestate
(PFCTL_STATE_QUEUE
)) {
1116 memset
(&a
, 0, sizeof
(a
));
1118 if
(strlcpy
(a.qname
, $2, sizeof
(a.qname
)) >=
1120 yyerror("queue name too long (max "
1121 "%d chars)", PF_QNAME_SIZE
-1);
1127 yyerror("cannot specify tbrsize for queue");
1130 if
($4.priority
> 255) {
1131 yyerror("priority out of range: max 255");
1134 a.priority
= $4.priority
;
1135 a.qlimit
= $4.qlimit
;
1136 a.scheduler
= $4.scheduler.qtype
;
1137 if
(expand_queue
(&a
, $3, $5, $4.queue_bwspec
,
1139 yyerror("errors in queue definition");
1146 bzero
(&queue_opts
, sizeof queue_opts
);
1147 queue_opts.priority
= DEFAULT_PRIORITY
;
1148 queue_opts.qlimit
= DEFAULT_QLIMIT
;
1149 queue_opts.scheduler.qtype
= ALTQT_NONE
;
1150 queue_opts.queue_bwspec.bw_percent
= 100;
1153 { $$
= queue_opts
; }
1155 bzero
(&queue_opts
, sizeof queue_opts
);
1156 queue_opts.priority
= DEFAULT_PRIORITY
;
1157 queue_opts.qlimit
= DEFAULT_QLIMIT
;
1158 queue_opts.scheduler.qtype
= ALTQT_NONE
;
1159 queue_opts.queue_bwspec.bw_percent
= 100;
1164 queue_opts_l
: queue_opts_l queue_opt
1168 queue_opt
: BANDWIDTH bandwidth
{
1169 if
(queue_opts.marker
& QOM_BWSPEC
) {
1170 yyerror("bandwidth cannot be respecified");
1173 queue_opts.marker |
= QOM_BWSPEC
;
1174 queue_opts.queue_bwspec
= $2;
1177 if
(queue_opts.marker
& QOM_PRIORITY
) {
1178 yyerror("priority cannot be respecified");
1182 yyerror("priority out of range: max 255");
1185 queue_opts.marker |
= QOM_PRIORITY
;
1186 queue_opts.priority
= $2;
1189 if
(queue_opts.marker
& QOM_QLIMIT
) {
1190 yyerror("qlimit cannot be respecified");
1194 yyerror("qlimit out of range: max 65535");
1197 queue_opts.marker |
= QOM_QLIMIT
;
1198 queue_opts.qlimit
= $2;
1201 if
(queue_opts.marker
& QOM_SCHEDULER
) {
1202 yyerror("scheduler cannot be respecified");
1205 queue_opts.marker |
= QOM_SCHEDULER
;
1206 queue_opts.scheduler
= $1;
1209 if
(queue_opts.marker
& QOM_TBRSIZE
) {
1210 yyerror("tbrsize cannot be respecified");
1214 yyerror("tbrsize too big: max 65535");
1217 queue_opts.marker |
= QOM_TBRSIZE
;
1218 queue_opts.tbrsize
= $2;
1222 bandwidth
: STRING
{
1228 bps
= strtod
($1, &cp
);
1230 if
(!strcmp
(cp
, "b"))
1232 else if
(!strcmp
(cp
, "Kb"))
1234 else if
(!strcmp
(cp
, "Mb"))
1236 else if
(!strcmp
(cp
, "Gb"))
1237 bps
*= 1000 * 1000 * 1000;
1238 else if
(!strcmp
(cp
, "%")) {
1239 if
(bps
< 0 || bps
> 100) {
1240 yyerror("bandwidth spec "
1245 $$.bw_percent
= bps
;
1248 yyerror("unknown unit %s", cp
);
1254 $$.bw_absolute
= (u_int32_t
)bps
;
1259 $$.qtype
= ALTQT_CBQ
;
1260 $$.data.cbq_opts.flags
= 0;
1262 | CBQ
'(' cbqflags_list
')' {
1263 $$.qtype
= ALTQT_CBQ
;
1264 $$.data.cbq_opts.flags
= $3;
1267 $$.qtype
= ALTQT_PRIQ
;
1268 $$.data.priq_opts.flags
= 0;
1270 | PRIQ
'(' priqflags_list
')' {
1271 $$.qtype
= ALTQT_PRIQ
;
1272 $$.data.priq_opts.flags
= $3;
1275 $$.qtype
= ALTQT_HFSC
;
1276 bzero
(&$$.data.hfsc_opts
,
1277 sizeof
(struct node_hfsc_opts
));
1279 | HFSC
'(' hfsc_opts
')' {
1280 $$.qtype
= ALTQT_HFSC
;
1281 $$.data.hfsc_opts
= $3;
1285 cbqflags_list
: cbqflags_item
{ $$ |
= $1; }
1286 | cbqflags_list comma cbqflags_item
{ $$ |
= $3; }
1289 cbqflags_item
: STRING
{
1290 if
(!strcmp
($1, "default"))
1291 $$
= CBQCLF_DEFCLASS
;
1292 else if
(!strcmp
($1, "borrow"))
1294 else if
(!strcmp
($1, "red"))
1296 else if
(!strcmp
($1, "ecn"))
1297 $$
= CBQCLF_RED|CBQCLF_ECN
;
1298 else if
(!strcmp
($1, "rio"))
1301 yyerror("unknown cbq flag \"%s\"", $1);
1309 priqflags_list
: priqflags_item
{ $$ |
= $1; }
1310 | priqflags_list comma priqflags_item
{ $$ |
= $3; }
1313 priqflags_item
: STRING
{
1314 if
(!strcmp
($1, "default"))
1315 $$
= PRCF_DEFAULTCLASS
;
1316 else if
(!strcmp
($1, "red"))
1318 else if
(!strcmp
($1, "ecn"))
1319 $$
= PRCF_RED|PRCF_ECN
;
1320 else if
(!strcmp
($1, "rio"))
1323 yyerror("unknown priq flag \"%s\"", $1);
1333 sizeof
(struct node_hfsc_opts
));
1340 hfscopts_list
: hfscopts_item
1341 | hfscopts_list comma hfscopts_item
1344 hfscopts_item
: LINKSHARE bandwidth
{
1345 if
(hfsc_opts.linkshare.used
) {
1346 yyerror("linkshare already specified");
1349 hfsc_opts.linkshare.m2
= $2;
1350 hfsc_opts.linkshare.used
= 1;
1352 | LINKSHARE
'(' bandwidth number bandwidth
')' {
1353 if
(hfsc_opts.linkshare.used
) {
1354 yyerror("linkshare already specified");
1357 hfsc_opts.linkshare.m1
= $3;
1358 hfsc_opts.linkshare.d
= $4;
1359 hfsc_opts.linkshare.m2
= $5;
1360 hfsc_opts.linkshare.used
= 1;
1362 | REALTIME bandwidth
{
1363 if
(hfsc_opts.realtime.used
) {
1364 yyerror("realtime already specified");
1367 hfsc_opts.realtime.m2
= $2;
1368 hfsc_opts.realtime.used
= 1;
1370 | REALTIME
'(' bandwidth number bandwidth
')' {
1371 if
(hfsc_opts.realtime.used
) {
1372 yyerror("realtime already specified");
1375 hfsc_opts.realtime.m1
= $3;
1376 hfsc_opts.realtime.d
= $4;
1377 hfsc_opts.realtime.m2
= $5;
1378 hfsc_opts.realtime.used
= 1;
1380 | UPPERLIMIT bandwidth
{
1381 if
(hfsc_opts.upperlimit.used
) {
1382 yyerror("upperlimit already specified");
1385 hfsc_opts.upperlimit.m2
= $2;
1386 hfsc_opts.upperlimit.used
= 1;
1388 | UPPERLIMIT
'(' bandwidth number bandwidth
')' {
1389 if
(hfsc_opts.upperlimit.used
) {
1390 yyerror("upperlimit already specified");
1393 hfsc_opts.upperlimit.m1
= $3;
1394 hfsc_opts.upperlimit.d
= $4;
1395 hfsc_opts.upperlimit.m2
= $5;
1396 hfsc_opts.upperlimit.used
= 1;
1399 if
(!strcmp
($1, "default"))
1400 hfsc_opts.flags |
= HFCF_DEFAULTCLASS
;
1401 else if
(!strcmp
($1, "red"))
1402 hfsc_opts.flags |
= HFCF_RED
;
1403 else if
(!strcmp
($1, "ecn"))
1404 hfsc_opts.flags |
= HFCF_RED|HFCF_ECN
;
1405 else if
(!strcmp
($1, "rio"))
1406 hfsc_opts.flags |
= HFCF_RIO
;
1408 yyerror("unknown hfsc flag \"%s\"", $1);
1416 qassign
: /* empty */ { $$
= NULL
; }
1417 | qassign_item
{ $$
= $1; }
1418 |
'{' qassign_list
'}' { $$
= $2; }
1421 qassign_list
: qassign_item
{ $$
= $1; }
1422 | qassign_list comma qassign_item
{
1423 $1->tail
->next
= $3;
1429 qassign_item
: STRING
{
1430 $$
= calloc
(1, sizeof
(struct node_queue
));
1432 err
(1, "qassign_item: calloc");
1433 if
(strlcpy
($$
->queue
, $1, sizeof
($$
->queue
)) >=
1434 sizeof
($$
->queue
)) {
1435 yyerror("queue name '%s' too long (max "
1436 "%d chars)", $1, sizeof
($$
->queue
)-1);
1447 pfrule
: action dir logquick interface route af proto fromto
1451 struct node_state_opt
*o
;
1452 struct node_proto
*proto
;
1456 if
(check_rulestate
(PFCTL_STATE_FILTER
))
1459 memset
(&r
, 0, sizeof
(r
));
1463 case PFRULE_RETURNRST
:
1464 r.rule_flag |
= PFRULE_RETURNRST
;
1465 r.return_ttl
= $1.w
;
1467 case PFRULE_RETURNICMP
:
1468 r.rule_flag |
= PFRULE_RETURNICMP
;
1469 r.return_icmp
= $1.w
;
1470 r.return_icmp6
= $1.w2
;
1473 r.rule_flag |
= PFRULE_RETURN
;
1474 r.return_icmp
= $1.w
;
1475 r.return_icmp6
= $1.w2
;
1484 if
(strlcpy
(r.tagname
, $9.tag
,
1485 PF_TAG_NAME_SIZE
) >= PF_TAG_NAME_SIZE
) {
1486 yyerror("tag too long, max %u chars",
1487 PF_TAG_NAME_SIZE
- 1);
1491 if
(strlcpy
(r.match_tagname
, $9.match_tag
,
1492 PF_TAG_NAME_SIZE
) >= PF_TAG_NAME_SIZE
) {
1493 yyerror("tag too long, max %u chars",
1494 PF_TAG_NAME_SIZE
- 1);
1497 r.match_tag_not
= $9.match_tag_not
;
1498 r.flags
= $9.flags.b1
;
1499 r.flagset
= $9.flags.b2
;
1500 if
(rule_label
(&r
, $9.label
))
1503 if
($9.flags.b1 ||
$9.flags.b2 ||
$8.src_os
) {
1504 for
(proto
= $7; proto
!= NULL
&&
1505 proto
->proto
!= IPPROTO_TCP
;
1506 proto
= proto
->next
)
1508 if
(proto
== NULL
&& $7 != NULL
) {
1509 if
($9.flags.b1 ||
$9.flags.b2
)
1511 "flags only apply to tcp");
1514 "OS fingerprinting only "
1519 if
(($9.flags.b1
& parse_flags
("S")) == 0 &&
1521 yyerror("OS fingerprinting requires "
1522 "the SYN TCP flag (flags S/SA)");
1529 r.keep_state
= $9.keep.action
;
1530 o
= $9.keep.options
;
1532 struct node_state_opt
*p
= o
;
1535 case PF_STATE_OPT_MAX
:
1537 yyerror("state option 'max' "
1538 "multiple definitions");
1541 r.max_states
= o
->data.max_states
;
1543 case PF_STATE_OPT_NOSYNC
:
1544 if
(r.rule_flag
& PFRULE_NOSYNC
) {
1545 yyerror("state option 'sync' "
1546 "multiple definitions");
1549 r.rule_flag |
= PFRULE_NOSYNC
;
1551 case PF_STATE_OPT_SRCTRACK
:
1553 yyerror("state option "
1555 "multiple definitions");
1558 srctrack
= o
->data.src_track
;
1560 case PF_STATE_OPT_MAX_SRC_STATES
:
1561 if
(r.max_src_states
) {
1562 yyerror("state option "
1564 "multiple definitions");
1567 if
(o
->data.max_src_nodes
== 0) {
1568 yyerror("'max-src-states' must "
1573 o
->data.max_src_states
;
1574 r.rule_flag |
= PFRULE_SRCTRACK
;
1576 case PF_STATE_OPT_MAX_SRC_NODES
:
1577 if
(r.max_src_nodes
) {
1578 yyerror("state option "
1580 "multiple definitions");
1583 if
(o
->data.max_src_nodes
== 0) {
1584 yyerror("'max-src-nodes' must "
1589 o
->data.max_src_nodes
;
1590 r.rule_flag |
= PFRULE_SRCTRACK |
1591 PFRULE_RULESRCTRACK
;
1593 case PF_STATE_OPT_STATELOCK
:
1595 yyerror("state locking option: "
1596 "multiple definitions");
1600 r.rule_flag |
= o
->data.statelock
;
1602 case PF_STATE_OPT_TIMEOUT
:
1603 if
(r.timeout
[o
->data.timeout.number
]) {
1604 yyerror("state timeout %s "
1605 "multiple definitions",
1606 pf_timeouts
[o
->data.
1607 timeout.number
].name
);
1610 r.timeout
[o
->data.timeout.number
] =
1611 o
->data.timeout.seconds
;
1617 if
(srctrack
== PF_SRCTRACK_GLOBAL
&&
1619 yyerror("'max-src-nodes' is "
1620 "incompatible with "
1621 "'source-track global'");
1624 r.rule_flag |
= PFRULE_SRCTRACK
;
1625 if
(srctrack
== PF_SRCTRACK_RULE
)
1626 r.rule_flag |
= PFRULE_RULESRCTRACK
;
1628 if
(r.keep_state
&& !statelock
)
1629 r.rule_flag |
= default_statelock
;
1632 r.rule_flag |
= PFRULE_FRAGMENT
;
1633 r.allow_opts
= $9.allowopts
;
1635 decide_address_family
($8.src.host
, &r.af
);
1636 decide_address_family
($8.dst.host
, &r.af
);
1640 yyerror("direction must be explicit "
1641 "with rules that specify routing");
1645 r.rpool.opts
= $5.pool_opts
;
1647 memcpy
(&r.rpool.key
, $5.key
,
1648 sizeof
(struct pf_poolhashkey
));
1650 if
(r.rt
&& r.rt
!= PF_FASTROUTE
) {
1651 decide_address_family
($5.host
, &r.af
);
1652 remove_invalid_hosts
(&$5.host
, &r.af
);
1653 if
($5.host
== NULL
) {
1654 yyerror("no routing address with "
1655 "matching address family found.");
1658 if
((r.rpool.opts
& PF_POOL_TYPEMASK
) ==
1659 PF_POOL_NONE
&& ($5.host
->next
!= NULL ||
1660 $5.host
->addr.type
== PF_ADDR_TABLE ||
1661 DYNIF_MULTIADDR
($5.host
->addr
)))
1662 r.rpool.opts |
= PF_POOL_ROUNDROBIN
;
1663 if
((r.rpool.opts
& PF_POOL_TYPEMASK
) !=
1664 PF_POOL_ROUNDROBIN
&&
1665 disallow_table
($5.host
, "tables are only "
1666 "supported in round-robin routing pools"))
1668 if
((r.rpool.opts
& PF_POOL_TYPEMASK
) !=
1669 PF_POOL_ROUNDROBIN
&&
1670 disallow_alias
($5.host
, "interface (%s) "
1671 "is only supported in round-robin "
1674 if
($5.host
->next
!= NULL
) {
1675 if
((r.rpool.opts
& PF_POOL_TYPEMASK
) !=
1676 PF_POOL_ROUNDROBIN
) {
1677 yyerror("r.rpool.opts must "
1678 "be PF_POOL_ROUNDROBIN");
1683 if
($9.queues.qname
!= NULL
) {
1684 if
(strlcpy
(r.qname
, $9.queues.qname
,
1685 sizeof
(r.qname
)) >= sizeof
(r.qname
)) {
1686 yyerror("rule qname too long (max "
1687 "%d chars)", sizeof
(r.qname
)-1);
1690 free
($9.queues.qname
);
1692 if
($9.queues.pqname
!= NULL
) {
1693 if
(strlcpy
(r.pqname
, $9.queues.pqname
,
1694 sizeof
(r.pqname
)) >= sizeof
(r.pqname
)) {
1695 yyerror("rule pqname too long (max "
1696 "%d chars)", sizeof
(r.pqname
)-1);
1699 free
($9.queues.pqname
);
1702 expand_rule
(&r
, $4, $5.host
, $7, $8.src_os
,
1703 $8.src.host
, $8.src.port
, $8.dst.host
, $8.dst.port
,
1704 $9.uid
, $9.gid
, $9.icmpspec
);
1708 filter_opts
: { bzero
(&filter_opts
, sizeof filter_opts
); }
1710 { $$
= filter_opts
; }
1712 bzero
(&filter_opts
, sizeof filter_opts
);
1717 filter_opts_l
: filter_opts_l filter_opt
1721 filter_opt
: USER uids
{
1722 if
(filter_opts.uid
)
1723 $2->tail
->next
= filter_opts.uid
;
1724 filter_opts.uid
= $2;
1727 if
(filter_opts.gid
)
1728 $2->tail
->next
= filter_opts.gid
;
1729 filter_opts.gid
= $2;
1732 if
(filter_opts.marker
& FOM_FLAGS
) {
1733 yyerror("flags cannot be redefined");
1736 filter_opts.marker |
= FOM_FLAGS
;
1737 filter_opts.flags.b1 |
= $1.b1
;
1738 filter_opts.flags.b2 |
= $1.b2
;
1739 filter_opts.flags.w |
= $1.w
;
1740 filter_opts.flags.w2 |
= $1.w2
;
1743 if
(filter_opts.marker
& FOM_ICMP
) {
1744 yyerror("icmp-type cannot be redefined");
1747 filter_opts.marker |
= FOM_ICMP
;
1748 filter_opts.icmpspec
= $1;
1751 if
(filter_opts.marker
& FOM_TOS
) {
1752 yyerror("tos cannot be redefined");
1755 filter_opts.marker |
= FOM_TOS
;
1756 filter_opts.tos
= $1;
1759 if
(filter_opts.marker
& FOM_KEEP
) {
1760 yyerror("modulate or keep cannot be redefined");
1763 filter_opts.marker |
= FOM_KEEP
;
1764 filter_opts.keep.action
= $1.action
;
1765 filter_opts.keep.options
= $1.options
;
1768 filter_opts.fragment
= 1;
1771 filter_opts.allowopts
= 1;
1774 if
(filter_opts.label
) {
1775 yyerror("label cannot be redefined");
1778 filter_opts.label
= $1;
1781 if
(filter_opts.queues.qname
) {
1782 yyerror("queue cannot be redefined");
1785 filter_opts.queues
= $1;
1788 filter_opts.tag
= $2;
1790 | not TAGGED
string {
1791 filter_opts.match_tag
= $3;
1792 filter_opts.match_tag_not
= $1;
1796 action
: PASS
{ $$.b1
= PF_PASS
; $$.b2
= $$.w
= 0; }
1797 | BLOCK blockspec
{ $$
= $2; $$.b1
= PF_DROP
; }
1800 blockspec
: /* empty */ {
1801 $$.b2
= blockpolicy
;
1802 $$.w
= returnicmpdefault
;
1803 $$.w2
= returnicmp6default
;
1806 $$.b2
= PFRULE_DROP
;
1811 $$.b2
= PFRULE_RETURNRST
;
1815 | RETURNRST
'(' TTL number
')' {
1817 yyerror("illegal ttl value %d", $4);
1820 $$.b2
= PFRULE_RETURNRST
;
1825 $$.b2
= PFRULE_RETURNICMP
;
1826 $$.w
= returnicmpdefault
;
1827 $$.w2
= returnicmp6default
;
1830 $$.b2
= PFRULE_RETURNICMP
;
1831 $$.w
= returnicmpdefault
;
1832 $$.w2
= returnicmp6default
;
1834 | RETURNICMP
'(' STRING
')' {
1835 $$.b2
= PFRULE_RETURNICMP
;
1836 if
(!($$.w
= parseicmpspec
($3, AF_INET
))) {
1841 $$.w2
= returnicmp6default
;
1843 | RETURNICMP6
'(' STRING
')' {
1844 $$.b2
= PFRULE_RETURNICMP
;
1845 $$.w
= returnicmpdefault
;
1846 if
(!($$.w2
= parseicmpspec
($3, AF_INET6
))) {
1852 | RETURNICMP
'(' STRING comma STRING
')' {
1853 $$.b2
= PFRULE_RETURNICMP
;
1854 if
(!($$.w
= parseicmpspec
($3, AF_INET
)) ||
1855 !($$.w2
= parseicmpspec
($5, AF_INET6
))) {
1864 $$.b2
= PFRULE_RETURN
;
1865 $$.w
= returnicmpdefault
;
1866 $$.w2
= returnicmp6default
;
1870 dir
: /* empty */ { $$
= 0; }
1871 | IN
{ $$
= PF_IN
; }
1872 | OUT
{ $$
= PF_OUT
; }
1875 logquick
: /* empty */ { $$.log
= 0; $$.quick
= 0; }
1876 | log
{ $$.log
= $1; $$.quick
= 0; }
1877 | QUICK
{ $$.log
= 0; $$.quick
= 1; }
1878 | log QUICK
{ $$.log
= $1; $$.quick
= 1; }
1879 | QUICK log
{ $$.log
= $2; $$.quick
= 1; }
1882 log
: LOG
{ $$
= 1; }
1883 | LOGALL
{ $$
= 2; }
1886 interface
: /* empty */ { $$
= NULL
; }
1887 | ON if_item_not
{ $$
= $2; }
1888 | ON
'{' if_list
'}' { $$
= $3; }
1891 if_list
: if_item_not
{ $$
= $1; }
1892 | if_list comma if_item_not
{
1893 $1->tail
->next
= $3;
1899 if_item_not
: not if_item
{ $$
= $2; $$
->not
= $1; }
1903 struct node_host
*n
;
1905 if
((n
= ifa_exists
($1, 1)) == NULL
) {
1906 yyerror("unknown interface %s", $1);
1910 $$
= calloc
(1, sizeof
(struct node_if
));
1912 err
(1, "if_item: calloc");
1913 if
(strlcpy
($$
->ifname
, $1, sizeof
($$
->ifname
)) >=
1914 sizeof
($$
->ifname
)) {
1917 yyerror("interface name too long");
1921 $$
->ifa_flags
= n
->ifa_flags
;
1928 af
: /* empty */ { $$
= 0; }
1929 | INET
{ $$
= AF_INET
; }
1930 | INET6
{ $$
= AF_INET6
; }
1933 proto
: /* empty */ { $$
= NULL
; }
1934 | PROTO proto_item
{ $$
= $2; }
1935 | PROTO
'{' proto_list
'}' { $$
= $3; }
1938 proto_list
: proto_item
{ $$
= $1; }
1939 | proto_list comma proto_item
{
1940 $1->tail
->next
= $3;
1946 proto_item
: STRING
{
1950 if
(atoul
($1, &ulval
) == 0) {
1952 yyerror("protocol outside range");
1956 pr
= (u_int8_t
)ulval
;
1960 p
= getprotobyname
($1);
1962 yyerror("unknown protocol %s", $1);
1970 yyerror("proto 0 cannot be used");
1973 $$
= calloc
(1, sizeof
(struct node_proto
));
1975 err
(1, "proto_item: calloc");
1996 os
: /* empty */ { $$
= NULL
; }
1997 | OS xos
{ $$
= $2; }
1998 | OS
'{' os_list
'}' { $$
= $3; }
2002 $$
= calloc
(1, sizeof
(struct node_os
));
2004 err
(1, "os: calloc");
2010 os_list
: xos
{ $$
= $1; }
2011 | os_list comma xos
{
2012 $1->tail
->next
= $3;
2018 from
: /* empty */ {
2036 ipportspec
: ipspec
{
2040 | ipspec PORT portspec
{
2050 ipspec
: ANY
{ $$
= NULL
; }
2051 | xhost
{ $$
= $1; }
2052 |
'{' host_list
'}' { $$
= $2; }
2055 host_list
: xhost
{ $$
= $1; }
2056 | host_list comma xhost
{
2059 else if
($1 == NULL
)
2062 $1->tail
->next
= $3;
2063 $1->tail
= $3->tail
;
2070 struct node_host
*n
;
2072 for
(n
= $2; n
!= NULL
; n
= n
->next
)
2077 $$
= calloc
(1, sizeof
(struct node_host
));
2079 err
(1, "xhost: calloc");
2080 $$
->addr.type
= PF_ADDR_NOROUTE
;
2087 if
(($$
= host
($1)) == NULL
) {
2088 /* error. "any" is handled elsewhere */
2090 yyerror("could not parse host specification");
2096 | STRING
'/' number
{
2099 if
(asprintf
(&buf
, "%s/%u", $1, $3) == -1)
2100 err
(1, "host: asprintf");
2102 if
(($$
= host
(buf
)) == NULL
) {
2103 /* error. "any" is handled elsewhere */
2105 yyerror("could not parse host specification");
2111 | dynaddr
'/' number
{
2112 struct node_host
*n
;
2115 for
(n
= $1; n
!= NULL
; n
= n
->next
)
2119 if
(strlen
($2) >= PF_TABLE_NAME_SIZE
) {
2120 yyerror("table name '%s' too long", $2);
2124 $$
= calloc
(1, sizeof
(struct node_host
));
2126 err
(1, "host: calloc");
2127 $$
->addr.type
= PF_ADDR_TABLE
;
2128 if
(strlcpy
($$
->addr.v.tblname
, $2,
2129 sizeof
($$
->addr.v.tblname
)) >=
2130 sizeof
($$
->addr.v.tblname
))
2131 errx
(1, "host: strlcpy");
2141 if
(atoul
($1, &ulval
) == -1) {
2142 yyerror("%s is not a number", $1);
2151 dynaddr
: '(' STRING
')' {
2156 while
((p
= strrchr
($2, ':')) != NULL
) {
2157 if
(!strcmp
(p
+1, "network"))
2158 flags |
= PFI_AFLAG_NETWORK
;
2159 else if
(!strcmp
(p
+1, "broadcast"))
2160 flags |
= PFI_AFLAG_BROADCAST
;
2161 else if
(!strcmp
(p
+1, "peer"))
2162 flags |
= PFI_AFLAG_PEER
;
2163 else if
(!strcmp
(p
+1, "0"))
2164 flags |
= PFI_AFLAG_NOALIAS
;
2166 yyerror("interface %s has bad modifier",
2173 if
(flags
& (flags
- 1) & PFI_AFLAG_MODEMASK
) {
2175 yyerror("illegal combination of "
2176 "interface modifiers");
2179 if
(ifa_exists
($2, 1) == NULL
&& strcmp
($2, "self")) {
2180 yyerror("interface %s does not exist", $2);
2184 $$
= calloc
(1, sizeof
(struct node_host
));
2186 err
(1, "address: calloc");
2188 set_ipmask
($$
, 128);
2189 $$
->addr.type
= PF_ADDR_DYNIFTL
;
2190 $$
->addr.iflags
= flags
;
2191 if
(strlcpy
($$
->addr.v.ifname
, $2,
2192 sizeof
($$
->addr.v.ifname
)) >=
2193 sizeof
($$
->addr.v.ifname
)) {
2196 yyerror("interface name too long");
2205 portspec
: port_item
{ $$
= $1; }
2206 |
'{' port_list
'}' { $$
= $2; }
2209 port_list
: port_item
{ $$
= $1; }
2210 | port_list comma port_item
{
2211 $1->tail
->next
= $3;
2218 $$
= calloc
(1, sizeof
(struct node_port
));
2220 err
(1, "port_item: calloc");
2232 yyerror("':' cannot be used with an other "
2236 $$
= calloc
(1, sizeof
(struct node_port
));
2238 err
(1, "port_item: calloc");
2245 | port PORTBINARY port
{
2247 yyerror("':' cannot be used with an other "
2251 $$
= calloc
(1, sizeof
(struct node_port
));
2253 err
(1, "port_item: calloc");
2263 char *p
= strchr
($1, ':');
2264 struct servent
*s
= NULL
;
2268 if
(atoul
($1, &ulval
) == 0) {
2269 if
(ulval
> 65535) {
2271 yyerror("illegal port value %d",
2275 $$.a
= htons
(ulval
);
2277 s
= getservbyname
($1, "tcp");
2279 s
= getservbyname
($1, "udp");
2281 yyerror("unknown port %s", $1);
2293 if
((port
[0] = getservice
($1)) == -1 ||
2294 (port
[1] = getservice
(p
)) == -1) {
2306 uids
: uid_item
{ $$
= $1; }
2307 |
'{' uid_list
'}' { $$
= $2; }
2310 uid_list
: uid_item
{ $$
= $1; }
2311 | uid_list comma uid_item
{
2312 $1->tail
->next
= $3;
2319 $$
= calloc
(1, sizeof
(struct node_uid
));
2321 err
(1, "uid_item: calloc");
2329 if
($2 == UID_MAX
&& $1 != PF_OP_EQ
&& $1 != PF_OP_NE
) {
2330 yyerror("user unknown requires operator = or "
2334 $$
= calloc
(1, sizeof
(struct node_uid
));
2336 err
(1, "uid_item: calloc");
2343 | uid PORTBINARY uid
{
2344 if
($1 == UID_MAX ||
$3 == UID_MAX
) {
2345 yyerror("user unknown requires operator = or "
2349 $$
= calloc
(1, sizeof
(struct node_uid
));
2351 err
(1, "uid_item: calloc");
2363 if
(atoul
($1, &ulval
) == -1) {
2364 if
(!strcmp
($1, "unknown"))
2369 if
((pw
= getpwnam
($1)) == NULL
) {
2370 yyerror("unknown user %s", $1);
2377 if
(ulval
>= UID_MAX
) {
2379 yyerror("illegal uid value %lu", ulval
);
2388 gids
: gid_item
{ $$
= $1; }
2389 |
'{' gid_list
'}' { $$
= $2; }
2392 gid_list
: gid_item
{ $$
= $1; }
2393 | gid_list comma gid_item
{
2394 $1->tail
->next
= $3;
2401 $$
= calloc
(1, sizeof
(struct node_gid
));
2403 err
(1, "gid_item: calloc");
2411 if
($2 == GID_MAX
&& $1 != PF_OP_EQ
&& $1 != PF_OP_NE
) {
2412 yyerror("group unknown requires operator = or "
2416 $$
= calloc
(1, sizeof
(struct node_gid
));
2418 err
(1, "gid_item: calloc");
2425 | gid PORTBINARY gid
{
2426 if
($1 == GID_MAX ||
$3 == GID_MAX
) {
2427 yyerror("group unknown requires operator = or "
2431 $$
= calloc
(1, sizeof
(struct node_gid
));
2433 err
(1, "gid_item: calloc");
2445 if
(atoul
($1, &ulval
) == -1) {
2446 if
(!strcmp
($1, "unknown"))
2451 if
((grp
= getgrnam
($1)) == NULL
) {
2452 yyerror("unknown group %s", $1);
2459 if
(ulval
>= GID_MAX
) {
2460 yyerror("illegal gid value %lu", ulval
);
2473 if
((f
= parse_flags
($1)) < 0) {
2474 yyerror("bad flags %s", $1);
2483 flags
: FLAGS flag
'/' flag
{ $$.b1
= $2.b1
; $$.b2
= $4.b1
; }
2484 | FLAGS
'/' flag
{ $$.b1
= 0; $$.b2
= $3.b1
; }
2487 icmpspec
: ICMPTYPE icmp_item
{ $$
= $2; }
2488 | ICMPTYPE
'{' icmp_list
'}' { $$
= $3; }
2489 | ICMP6TYPE icmp6_item
{ $$
= $2; }
2490 | ICMP6TYPE
'{' icmp6_list
'}' { $$
= $3; }
2493 icmp_list
: icmp_item
{ $$
= $1; }
2494 | icmp_list comma icmp_item
{
2495 $1->tail
->next
= $3;
2501 icmp6_list
: icmp6_item
{ $$
= $1; }
2502 | icmp6_list comma icmp6_item
{
2503 $1->tail
->next
= $3;
2509 icmp_item
: icmptype
{
2510 $$
= calloc
(1, sizeof
(struct node_icmp
));
2512 err
(1, "icmp_item: calloc");
2515 $$
->proto
= IPPROTO_ICMP
;
2519 | icmptype CODE STRING
{
2520 const struct icmpcodeent
*p
;
2523 if
(atoul
($3, &ulval
) == 0) {
2526 yyerror("illegal icmp-code %d", ulval
);
2530 if
((p
= geticmpcodebyname
($1-1, $3,
2531 AF_INET
)) == NULL
) {
2532 yyerror("unknown icmp-code %s", $3);
2539 $$
= calloc
(1, sizeof
(struct node_icmp
));
2541 err
(1, "icmp_item: calloc");
2543 $$
->code
= ulval
+ 1;
2544 $$
->proto
= IPPROTO_ICMP
;
2550 icmp6_item
: icmp6type
{
2551 $$
= calloc
(1, sizeof
(struct node_icmp
));
2553 err
(1, "icmp_item: calloc");
2556 $$
->proto
= IPPROTO_ICMPV6
;
2560 | icmp6type CODE STRING
{
2561 const struct icmpcodeent
*p
;
2564 if
(atoul
($3, &ulval
) == 0) {
2566 yyerror("illegal icmp6-code %ld",
2572 if
((p
= geticmpcodebyname
($1-1, $3,
2573 AF_INET6
)) == NULL
) {
2574 yyerror("unknown icmp6-code %s", $3);
2581 $$
= calloc
(1, sizeof
(struct node_icmp
));
2583 err
(1, "icmp_item: calloc");
2585 $$
->code
= ulval
+ 1;
2586 $$
->proto
= IPPROTO_ICMPV6
;
2593 const struct icmptypeent
*p
;
2596 if
(atoul
($1, &ulval
) == 0) {
2598 yyerror("illegal icmp-type %d", ulval
);
2604 if
((p
= geticmptypebyname
($1, AF_INET
)) ==
2606 yyerror("unknown icmp-type %s", $1);
2616 icmp6type
: STRING
{
2617 const struct icmptypeent
*p
;
2620 if
(atoul
($1, &ulval
) == 0) {
2622 yyerror("illegal icmp6-type %d", ulval
);
2628 if
((p
= geticmptypebyname
($1, AF_INET6
)) ==
2630 yyerror("unknown icmp6-type %s", $1);
2641 if
(!strcmp
($2, "lowdelay"))
2642 $$
= IPTOS_LOWDELAY
;
2643 else if
(!strcmp
($2, "throughput"))
2644 $$
= IPTOS_THROUGHPUT
;
2645 else if
(!strcmp
($2, "reliability"))
2646 $$
= IPTOS_RELIABILITY
;
2647 else if
($2[0] == '0' && $2[1] == 'x')
2648 $$
= strtoul
($2, NULL
, 16);
2650 $$
= strtoul
($2, NULL
, 10);
2651 if
(!$$ || $$
> 255) {
2652 yyerror("illegal tos value %s", $2);
2660 sourcetrack
: SOURCETRACK
{ $$
= PF_SRCTRACK
; }
2661 | SOURCETRACK GLOBAL
{ $$
= PF_SRCTRACK_GLOBAL
; }
2662 | SOURCETRACK RULE
{ $$
= PF_SRCTRACK_RULE
; }
2665 statelock
: IFBOUND
{
2666 $$
= PFRULE_IFBOUND
;
2669 $$
= PFRULE_GRBOUND
;
2676 keep
: KEEP STATE state_opt_spec
{
2677 $$.action
= PF_STATE_NORMAL
;
2680 | MODULATE STATE state_opt_spec
{
2681 $$.action
= PF_STATE_MODULATE
;
2684 | SYNPROXY STATE state_opt_spec
{
2685 $$.action
= PF_STATE_SYNPROXY
;
2690 state_opt_spec
: '(' state_opt_list
')' { $$
= $2; }
2691 |
/* empty */ { $$
= NULL
; }
2694 state_opt_list
: state_opt_item
{ $$
= $1; }
2695 | state_opt_list comma state_opt_item
{
2696 $1->tail
->next
= $3;
2702 state_opt_item
: MAXIMUM number
{
2703 $$
= calloc
(1, sizeof
(struct node_state_opt
));
2705 err
(1, "state_opt_item: calloc");
2706 $$
->type
= PF_STATE_OPT_MAX
;
2707 $$
->data.max_states
= $2;
2712 $$
= calloc
(1, sizeof
(struct node_state_opt
));
2714 err
(1, "state_opt_item: calloc");
2715 $$
->type
= PF_STATE_OPT_NOSYNC
;
2719 | MAXSRCSTATES number
{
2720 $$
= calloc
(1, sizeof
(struct node_state_opt
));
2722 err
(1, "state_opt_item: calloc");
2723 $$
->type
= PF_STATE_OPT_MAX_SRC_STATES
;
2724 $$
->data.max_src_states
= $2;
2728 | MAXSRCNODES number
{
2729 $$
= calloc
(1, sizeof
(struct node_state_opt
));
2731 err
(1, "state_opt_item: calloc");
2732 $$
->type
= PF_STATE_OPT_MAX_SRC_NODES
;
2733 $$
->data.max_src_nodes
= $2;
2738 $$
= calloc
(1, sizeof
(struct node_state_opt
));
2740 err
(1, "state_opt_item: calloc");
2741 $$
->type
= PF_STATE_OPT_SRCTRACK
;
2742 $$
->data.src_track
= $1;
2747 $$
= calloc
(1, sizeof
(struct node_state_opt
));
2749 err
(1, "state_opt_item: calloc");
2750 $$
->type
= PF_STATE_OPT_STATELOCK
;
2751 $$
->data.statelock
= $1;
2758 for
(i
= 0; pf_timeouts
[i
].name
&&
2759 strcmp
(pf_timeouts
[i
].name
, $1); ++i
)
2761 if
(!pf_timeouts
[i
].name
) {
2762 yyerror("illegal timeout name %s", $1);
2766 if
(strchr
(pf_timeouts
[i
].name
, '.') == NULL
) {
2767 yyerror("illegal state timeout %s", $1);
2772 $$
= calloc
(1, sizeof
(struct node_state_opt
));
2774 err
(1, "state_opt_item: calloc");
2775 $$
->type
= PF_STATE_OPT_TIMEOUT
;
2776 $$
->data.timeout.number
= pf_timeouts
[i
].timeout
;
2777 $$
->data.timeout.seconds
= $2;
2783 label
: LABEL STRING
{
2788 qname
: QUEUE STRING
{
2791 | QUEUE
'(' STRING
')' {
2794 | QUEUE
'(' STRING comma STRING
')' {
2800 no
: /* empty */ { $$
= 0; }
2805 char *p
= strchr
($1, ':');
2808 if
(($$.a
= getservice
($1)) == -1) {
2813 } else if
(!strcmp
(p
+1, "*")) {
2815 if
(($$.a
= getservice
($1)) == -1) {
2823 if
(($$.a
= getservice
($1)) == -1 ||
2824 ($$.b
= getservice
(p
)) == -1) {
2836 redirspec
: host
{ $$
= $1; }
2837 |
'{' redir_host_list
'}' { $$
= $2; }
2840 redir_host_list
: host
{ $$
= $1; }
2841 | redir_host_list comma host
{
2842 $1->tail
->next
= $3;
2843 $1->tail
= $3->tail
;
2848 redirpool
: /* empty */ { $$
= NULL
; }
2850 $$
= calloc
(1, sizeof
(struct redirection
));
2852 err
(1, "redirection: calloc");
2854 $$
->rport.a
= $$
->rport.b
= $$
->rport.t
= 0;
2856 | ARROW redirspec PORT rport
{
2857 $$
= calloc
(1, sizeof
(struct redirection
));
2859 err
(1, "redirection: calloc");
2865 hashkey
: /* empty */
2867 $$
= calloc
(1, sizeof
(struct pf_poolhashkey
));
2869 err
(1, "hashkey: calloc");
2870 $$
->key32
[0] = arc4random
();
2871 $$
->key32
[1] = arc4random
();
2872 $$
->key32
[2] = arc4random
();
2873 $$
->key32
[3] = arc4random
();
2877 if
(!strncmp
($1, "0x", 2)) {
2878 if
(strlen
($1) != 34) {
2880 yyerror("hex key must be 128 bits "
2881 "(32 hex digits) long");
2884 $$
= calloc
(1, sizeof
(struct pf_poolhashkey
));
2886 err
(1, "hashkey: calloc");
2888 if
(sscanf
($1, "0x%8x%8x%8x%8x",
2889 &$$
->key32
[0], &$$
->key32
[1],
2890 &$$
->key32
[2], &$$
->key32
[3]) != 4) {
2893 yyerror("invalid hex key");
2899 $$
= calloc
(1, sizeof
(struct pf_poolhashkey
));
2901 err
(1, "hashkey: calloc");
2903 MD5Update
(&context
, (unsigned char *)$1,
2905 MD5Final
((unsigned char *)$$
, &context
);
2906 $$
->key32
[0] = htonl
($$
->key32
[0]);
2907 $$
->key32
[1] = htonl
($$
->key32
[1]);
2908 $$
->key32
[2] = htonl
($$
->key32
[2]);
2909 $$
->key32
[3] = htonl
($$
->key32
[3]);
2915 pool_opts
: { bzero
(&pool_opts
, sizeof pool_opts
); }
2919 bzero
(&pool_opts
, sizeof pool_opts
);
2924 pool_opts_l
: pool_opts_l pool_opt
2928 pool_opt
: BITMASK
{
2929 if
(pool_opts.type
) {
2930 yyerror("pool type cannot be redefined");
2933 pool_opts.type
= PF_POOL_BITMASK
;
2936 if
(pool_opts.type
) {
2937 yyerror("pool type cannot be redefined");
2940 pool_opts.type
= PF_POOL_RANDOM
;
2942 | SOURCEHASH hashkey
{
2943 if
(pool_opts.type
) {
2944 yyerror("pool type cannot be redefined");
2947 pool_opts.type
= PF_POOL_SRCHASH
;
2951 if
(pool_opts.type
) {
2952 yyerror("pool type cannot be redefined");
2955 pool_opts.type
= PF_POOL_ROUNDROBIN
;
2958 if
(pool_opts.staticport
) {
2959 yyerror("static-port cannot be redefined");
2962 pool_opts.staticport
= 1;
2965 if
(filter_opts.marker
& POM_STICKYADDRESS
) {
2966 yyerror("sticky-address cannot be redefined");
2969 pool_opts.marker |
= POM_STICKYADDRESS
;
2970 pool_opts.opts |
= PF_POOL_STICKYADDR
;
2974 redirection
: /* empty */ { $$
= NULL
; }
2976 $$
= calloc
(1, sizeof
(struct redirection
));
2978 err
(1, "redirection: calloc");
2980 $$
->rport.a
= $$
->rport.b
= $$
->rport.t
= 0;
2982 | ARROW host PORT rport
{
2983 $$
= calloc
(1, sizeof
(struct redirection
));
2985 err
(1, "redirection: calloc");
2991 natpass
: /* empty */ { $$
= 0; }
2995 nataction
: no NAT natpass
{
3013 natrule
: nataction interface af proto fromto tag redirpool pool_opts
3017 if
(check_rulestate
(PFCTL_STATE_NAT
))
3020 memset
(&r
, 0, sizeof
(r
));
3027 if
($5.src.host
&& $5.src.host
->af
&&
3028 !$5.src.host
->ifindex
)
3029 r.af
= $5.src.host
->af
;
3030 else if
($5.dst.host
&& $5.dst.host
->af
&&
3031 !$5.dst.host
->ifindex
)
3032 r.af
= $5.dst.host
->af
;
3036 if
(strlcpy
(r.tagname
, $6, PF_TAG_NAME_SIZE
) >=
3038 yyerror("tag too long, max %u chars",
3039 PF_TAG_NAME_SIZE
- 1);
3043 if
(r.action
== PF_NONAT || r.action
== PF_NORDR
) {
3045 yyerror("translation rule with 'no' "
3046 "does not need '->'");
3050 if
($7 == NULL ||
$7->host
== NULL
) {
3051 yyerror("translation rule requires '-> "
3055 if
(!r.af
&& ! $7->host
->ifindex
)
3056 r.af
= $7->host
->af
;
3058 remove_invalid_hosts
(&$7->host
, &r.af
);
3059 if
(invalid_redirect
($7->host
, r.af
))
3061 if
(check_netmask
($7->host
, r.af
))
3064 r.rpool.proxy_port
[0] = ntohs
($7->rport.a
);
3068 if
(!$7->rport.b
&& $7->rport.t
&&
3069 $5.dst.port
!= NULL
) {
3070 r.rpool.proxy_port
[1] =
3071 ntohs
($7->rport.a
) +
3073 $5.dst.port
->port
[1]) -
3075 $5.dst.port
->port
[0]));
3077 r.rpool.proxy_port
[1] =
3081 r.rpool.proxy_port
[1] =
3083 if
(!r.rpool.proxy_port
[0] &&
3084 !r.rpool.proxy_port
[1]) {
3085 r.rpool.proxy_port
[0] =
3086 PF_NAT_PROXY_PORT_LOW
;
3087 r.rpool.proxy_port
[1] =
3088 PF_NAT_PROXY_PORT_HIGH
;
3089 } else if
(!r.rpool.proxy_port
[1])
3090 r.rpool.proxy_port
[1] =
3091 r.rpool.proxy_port
[0];
3097 r.rpool.opts
= $8.type
;
3098 if
((r.rpool.opts
& PF_POOL_TYPEMASK
) ==
3099 PF_POOL_NONE
&& ($7->host
->next
!= NULL ||
3100 $7->host
->addr.type
== PF_ADDR_TABLE ||
3101 DYNIF_MULTIADDR
($7->host
->addr
)))
3102 r.rpool.opts
= PF_POOL_ROUNDROBIN
;
3103 if
((r.rpool.opts
& PF_POOL_TYPEMASK
) !=
3104 PF_POOL_ROUNDROBIN
&&
3105 disallow_table
($7->host
, "tables are only "
3106 "supported in round-robin redirection "
3109 if
((r.rpool.opts
& PF_POOL_TYPEMASK
) !=
3110 PF_POOL_ROUNDROBIN
&&
3111 disallow_alias
($7->host
, "interface (%s) "
3112 "is only supported in round-robin "
3113 "redirection pools"))
3115 if
($7->host
->next
!= NULL
) {
3116 if
((r.rpool.opts
& PF_POOL_TYPEMASK
) !=
3117 PF_POOL_ROUNDROBIN
) {
3118 yyerror("only round-robin "
3119 "valid for multiple "
3120 "redirection addresses");
3127 memcpy
(&r.rpool.key
, $8.key
,
3128 sizeof
(struct pf_poolhashkey
));
3131 r.rpool.opts |
= $8.opts
;
3133 if
($8.staticport
) {
3134 if
(r.action
!= PF_NAT
) {
3135 yyerror("the 'static-port' option is "
3136 "only valid with nat rules");
3139 if
(r.rpool.proxy_port
[0] !=
3140 PF_NAT_PROXY_PORT_LOW
&&
3141 r.rpool.proxy_port
[1] !=
3142 PF_NAT_PROXY_PORT_HIGH
) {
3143 yyerror("the 'static-port' option can't"
3144 " be used when specifying a port"
3148 r.rpool.proxy_port
[0] = 0;
3149 r.rpool.proxy_port
[1] = 0;
3152 expand_rule
(&r
, $2, $7 == NULL ? NULL
: $7->host
, $4,
3153 $5.src_os
, $5.src.host
, $5.src.port
, $5.dst.host
,
3154 $5.dst.port
, 0, 0, 0);
3159 binatrule
: no BINAT natpass interface af proto FROM host TO ipspec tag
3162 struct pf_rule binat
;
3163 struct pf_pooladdr
*pa
;
3165 if
(check_rulestate
(PFCTL_STATE_NAT
))
3168 memset
(&binat
, 0, sizeof
(binat
));
3171 binat.action
= PF_NOBINAT
;
3173 binat.action
= PF_BINAT
;
3176 if
(!binat.af
&& $8 != NULL
&& $8->af
)
3178 if
(!binat.af
&& $10 != NULL
&& $10->af
)
3180 if
(!binat.af
&& $12 != NULL
&& $12->host
)
3181 binat.af
= $12->host
->af
;
3183 yyerror("address family (inet/inet6) "
3189 memcpy
(binat.ifname
, $4->ifname
,
3190 sizeof
(binat.ifname
));
3191 binat.ifnot
= $4->not
;
3195 if
(strlcpy
(binat.tagname
, $11,
3196 PF_TAG_NAME_SIZE
) >= PF_TAG_NAME_SIZE
) {
3197 yyerror("tag too long, max %u chars",
3198 PF_TAG_NAME_SIZE
- 1);
3203 binat.proto
= $6->proto
;
3207 if
($8 != NULL
&& disallow_table
($8, "invalid use of "
3208 "table <%s> as the source address of a binat rule"))
3210 if
($8 != NULL
&& disallow_alias
($8, "invalid use of "
3211 "interface (%s) as the source address of a binat "
3214 if
($12 != NULL
&& $12->host
!= NULL
&& disallow_table
(
3215 $12->host
, "invalid use of table <%s> as the "
3216 "redirect address of a binat rule"))
3218 if
($12 != NULL
&& $12->host
!= NULL
&& disallow_alias
(
3219 $12->host
, "invalid use of interface (%s) as the "
3220 "redirect address of a binat rule"))
3225 yyerror("multiple binat ip addresses");
3228 if
($8->addr.type
== PF_ADDR_DYNIFTL
)
3230 if
($8->af
!= binat.af
) {
3231 yyerror("binat ip versions must match");
3234 if
(check_netmask
($8, binat.af
))
3236 memcpy
(&binat.src.addr
, &$8->addr
,
3237 sizeof
(binat.src.addr
));
3242 yyerror("multiple binat ip addresses");
3245 if
($10->af
!= binat.af
&& $10->af
) {
3246 yyerror("binat ip versions must match");
3249 if
(check_netmask
($10, binat.af
))
3251 memcpy
(&binat.dst.addr
, &$10->addr
,
3252 sizeof
(binat.dst.addr
));
3253 binat.dst.not
= $10->not
;
3257 if
(binat.action
== PF_NOBINAT
) {
3259 yyerror("'no binat' rule does not need"
3264 if
($12 == NULL ||
$12->host
== NULL
) {
3265 yyerror("'binat' rule requires"
3270 remove_invalid_hosts
(&$12->host
, &binat.af
);
3271 if
(invalid_redirect
($12->host
, binat.af
))
3273 if
($12->host
->next
!= NULL
) {
3274 yyerror("binat rule must redirect to "
3275 "a single address");
3278 if
(check_netmask
($12->host
, binat.af
))
3281 if
(!PF_AZERO
(&binat.src.addr.v.a.mask
,
3283 !PF_AEQ
(&binat.src.addr.v.a.mask
,
3284 &$12->host
->addr.v.a.mask
, binat.af
)) {
3285 yyerror("'binat' source mask and "
3286 "redirect mask must be the same");
3290 TAILQ_INIT
(&binat.rpool.list
);
3291 pa
= calloc
(1, sizeof
(struct pf_pooladdr
));
3293 err
(1, "binat: calloc");
3294 pa
->addr
= $12->host
->addr
;
3296 TAILQ_INSERT_TAIL
(&binat.rpool.list
,
3302 pfctl_add_rule
(pf
, &binat
);
3306 tag
: /* empty */ { $$
= NULL
; }
3307 | TAG STRING
{ $$
= $2; }
3310 route_host
: STRING
{
3311 $$
= calloc
(1, sizeof
(struct node_host
));
3313 err
(1, "route_host: calloc");
3315 if
(ifa_exists
($$
->ifname
, 0) == NULL
) {
3316 yyerror("routeto: unknown interface %s",
3322 set_ipmask
($$
, 128);
3326 |
'(' STRING host
')' {
3329 if
(ifa_exists
($$
->ifname
, 0) == NULL
) {
3330 yyerror("routeto: unknown interface %s",
3337 route_host_list
: route_host
{ $$
= $1; }
3338 | route_host_list comma route_host
{
3341 if
($1->af
!= $3->af
) {
3342 yyerror("all pool addresses must be in the "
3343 "same address family");
3346 $1->tail
->next
= $3;
3347 $1->tail
= $3->tail
;
3352 routespec
: route_host
{ $$
= $1; }
3353 |
'{' route_host_list
'}' { $$
= $2; }
3356 route
: /* empty */ {
3363 $$.rt
= PF_FASTROUTE
;
3366 | ROUTETO routespec pool_opts
{
3369 $$.pool_opts
= $3.type |
$3.opts
;
3373 | REPLYTO routespec pool_opts
{
3376 $$.pool_opts
= $3.type |
$3.opts
;
3380 | DUPTO routespec pool_opts
{
3383 $$.pool_opts
= $3.type |
$3.opts
;
3389 timeout_spec
: STRING number
3391 if
(check_rulestate
(PFCTL_STATE_OPTION
)) {
3395 if
(pfctl_set_timeout
(pf
, $1, $2, 0) != 0) {
3396 yyerror("unknown timeout %s", $1);
3404 timeout_list
: timeout_list comma timeout_spec
3408 limit_spec
: STRING number
3410 if
(check_rulestate
(PFCTL_STATE_OPTION
)) {
3414 if
(pfctl_set_limit
(pf
, $1, $2) != 0) {
3415 yyerror("unable to set limit %s %u", $1, $2);
3423 limit_list
: limit_list comma limit_spec
3431 yesno
: NO
{ $$
= 0; }
3433 if
(!strcmp
($1, "yes"))
3443 unaryop
: '=' { $$
= PF_OP_EQ
; }
3444 |
'!' '=' { $$
= PF_OP_NE
; }
3445 |
'<' '=' { $$
= PF_OP_LE
; }
3446 |
'<' { $$
= PF_OP_LT
; }
3447 |
'>' '=' { $$
= PF_OP_GE
; }
3448 |
'>' { $$
= PF_OP_GT
; }
3454 yyerror(const char *fmt
, ...
)
3460 fprintf
(stderr
, "%s:%d: ", infile
, yylval.lineno
);
3461 vfprintf
(stderr
, fmt
, ap
);
3462 fprintf
(stderr
, "\n");
3468 disallow_table
(struct node_host
*h
, const char *fmt
)
3470 for
(; h
!= NULL
; h
= h
->next
)
3471 if
(h
->addr.type
== PF_ADDR_TABLE
) {
3472 yyerror(fmt
, h
->addr.v.tblname
);
3479 disallow_alias
(struct node_host
*h
, const char *fmt
)
3481 for
(; h
!= NULL
; h
= h
->next
)
3482 if
(DYNIF_MULTIADDR
(h
->addr
)) {
3483 yyerror(fmt
, h
->addr.v.tblname
);
3490 rule_consistent
(struct pf_rule
*r
)
3494 switch
(r
->action
) {
3498 problems
= filter_consistent
(r
);
3502 problems
= nat_consistent
(r
);
3506 problems
= rdr_consistent
(r
);
3517 filter_consistent
(struct pf_rule
*r
)
3521 if
(r
->proto
!= IPPROTO_TCP
&& r
->proto
!= IPPROTO_UDP
&&
3522 (r
->src.port_op || r
->dst.port_op
)) {
3523 yyerror("port only applies to tcp/udp");
3526 if
(r
->proto
!= IPPROTO_ICMP
&& r
->proto
!= IPPROTO_ICMPV6
&&
3527 (r
->type || r
->code
)) {
3528 yyerror("icmp-type/code only applies to icmp");
3531 if
(!r
->af
&& (r
->type || r
->code
)) {
3532 yyerror("must indicate address family with icmp-type/code");
3535 if
((r
->proto
== IPPROTO_ICMP
&& r
->af
== AF_INET6
) ||
3536 (r
->proto
== IPPROTO_ICMPV6
&& r
->af
== AF_INET
)) {
3537 yyerror("proto %s doesn't match address family %s",
3538 r
->proto
== IPPROTO_ICMP ?
"icmp" : "icmp6",
3539 r
->af
== AF_INET ?
"inet" : "inet6");
3542 if
(r
->allow_opts
&& r
->action
!= PF_PASS
) {
3543 yyerror("allow-opts can only be specified for pass rules");
3546 if
(r
->rule_flag
& PFRULE_FRAGMENT
&& (r
->src.port_op ||
3547 r
->dst.port_op || r
->flagset || r
->type || r
->code
)) {
3548 yyerror("fragments can be filtered only on IP header fields");
3551 if
(r
->rule_flag
& PFRULE_RETURNRST
&& r
->proto
!= IPPROTO_TCP
) {
3552 yyerror("return-rst can only be applied to TCP rules");
3555 if
(r
->max_src_nodes
&& !(r
->rule_flag
& PFRULE_RULESRCTRACK
)) {
3556 yyerror("max-src-nodes requires 'source-track rule'");
3559 if
(r
->action
== PF_DROP
&& r
->keep_state
) {
3560 yyerror("keep state on block rules doesn't make sense");
3563 if
((r
->tagname
[0] || r
->match_tagname
[0]) && !r
->keep_state
&&
3564 r
->action
== PF_PASS
&& !r
->anchorname
[0]) {
3565 yyerror("tags cannot be used without keep state");
3572 nat_consistent
(struct pf_rule
*r __unused
)
3574 return
(0); /* yeah! */
3578 rdr_consistent
(struct pf_rule
*r
)
3582 if
(r
->proto
!= IPPROTO_TCP
&& r
->proto
!= IPPROTO_UDP
) {
3583 if
(r
->src.port_op
) {
3584 yyerror("src port only applies to tcp/udp");
3587 if
(r
->dst.port_op
) {
3588 yyerror("dst port only applies to tcp/udp");
3591 if
(r
->rpool.proxy_port
[0]) {
3592 yyerror("rpool port only applies to tcp/udp");
3596 if
(r
->dst.port_op
&&
3597 r
->dst.port_op
!= PF_OP_EQ
&& r
->dst.port_op
!= PF_OP_RRG
) {
3598 yyerror("invalid port operator for rdr destination port");
3605 process_tabledef
(char *name
, struct table_opts
*opts
)
3607 struct pfr_buffer ab
;
3608 struct node_tinit
*ti
;
3610 bzero
(&ab
, sizeof
(ab
));
3611 ab.pfrb_type
= PFRB_ADDRS
;
3612 SIMPLEQ_FOREACH
(ti
, &opts
->init_nodes
, entries
) {
3614 if
(pfr_buf_load
(&ab
, ti
->file
, 0, append_addr
)) {
3616 yyerror("cannot load \"%s\": %s",
3617 ti
->file
, strerror
(errno
));
3619 yyerror("file \"%s\" contains bad data",
3624 if
(append_addr_host
(&ab
, ti
->host
, 0, 0)) {
3625 yyerror("cannot create address buffer: %s",
3630 if
(pf
->opts
& PF_OPT_VERBOSE
)
3631 print_tabledef
(name
, opts
->flags
, opts
->init_addr
,
3633 if
(!(pf
->opts
& PF_OPT_NOACTION
) &&
3634 pfctl_define_table
(name
, opts
->flags
, opts
->init_addr
,
3635 pf
->anchor
, pf
->ruleset
, &ab
, pf
->tticket
)) {
3636 yyerror("cannot define table %s: %s", name
,
3637 pfr_strerror
(errno
));
3653 /* macro gore, but you should've seen the prior indentation nightmare... */
3655 #define FREE_LIST(T,r) \
3658 while
(node
!= NULL
) { \
3660 node
= node
->next
; \
3665 #define LOOP_THROUGH(T,n,r,C) \
3669 r
= calloc
(1, sizeof
(T
)); \
3671 err
(1, "LOOP: calloc"); \
3675 while
(n
!= NULL
) { \
3684 expand_label_str
(char *label
, size_t len
, const char *srch
, const char *repl
)
3689 if
((tmp
= calloc
(1, len
)) == NULL
)
3690 err
(1, "expand_label_str: calloc");
3692 while
((q
= strstr
(p
, srch
)) != NULL
) {
3694 if
((strlcat
(tmp
, p
, len
) >= len
) ||
3695 (strlcat
(tmp
, repl
, len
) >= len
))
3696 errx
(1, "expand_label: label too long");
3700 if
(strlcat
(tmp
, p
, len
) >= len
)
3701 errx
(1, "expand_label: label too long");
3702 strlcpy
(label
, tmp
, len
); /* always fits */
3707 expand_label_if
(const char *name
, char *label
, size_t len
, const char *ifname
)
3709 if
(strstr
(label
, name
) != NULL
) {
3711 expand_label_str
(label
, len
, name
, "any");
3713 expand_label_str
(label
, len
, name
, ifname
);
3718 expand_label_addr
(const char *name
, char *label
, size_t len
, sa_family_t af
,
3719 struct node_host
*h
)
3721 char tmp
[64], tmp_not
[66];
3723 if
(strstr
(label
, name
) != NULL
) {
3724 switch
(h
->addr.type
) {
3725 case PF_ADDR_DYNIFTL
:
3726 snprintf
(tmp
, sizeof
(tmp
), "(%s)", h
->addr.v.ifname
);
3729 snprintf
(tmp
, sizeof
(tmp
), "<%s>", h
->addr.v.tblname
);
3731 case PF_ADDR_NOROUTE
:
3732 snprintf
(tmp
, sizeof
(tmp
), "no-route");
3734 case PF_ADDR_ADDRMASK
:
3735 if
(!af ||
(PF_AZERO
(&h
->addr.v.a.addr
, af
) &&
3736 PF_AZERO
(&h
->addr.v.a.mask
, af
)))
3737 snprintf
(tmp
, sizeof
(tmp
), "any");
3742 if
(inet_ntop
(af
, &h
->addr.v.a.addr
, a
,
3744 snprintf
(tmp
, sizeof
(tmp
), "?");
3746 bits
= unmask
(&h
->addr.v.a.mask
, af
);
3747 if
((af
== AF_INET
&& bits
< 32) ||
3748 (af
== AF_INET6
&& bits
< 128))
3749 snprintf
(tmp
, sizeof
(tmp
),
3752 snprintf
(tmp
, sizeof
(tmp
),
3758 snprintf
(tmp
, sizeof
(tmp
), "?");
3763 snprintf
(tmp_not
, sizeof
(tmp_not
), "! %s", tmp
);
3764 expand_label_str
(label
, len
, name
, tmp_not
);
3766 expand_label_str
(label
, len
, name
, tmp
);
3771 expand_label_port
(const char *name
, char *label
, size_t len
,
3772 struct node_port
*port
)
3774 char a1
[6], a2
[6], op
[13] = "";
3776 if
(strstr
(label
, name
) != NULL
) {
3777 snprintf
(a1
, sizeof
(a1
), "%u", ntohs
(port
->port
[0]));
3778 snprintf
(a2
, sizeof
(a2
), "%u", ntohs
(port
->port
[1]));
3781 else if
(port
->op
== PF_OP_IRG
)
3782 snprintf
(op
, sizeof
(op
), "%s><%s", a1
, a2
);
3783 else if
(port
->op
== PF_OP_XRG
)
3784 snprintf
(op
, sizeof
(op
), "%s<>%s", a1
, a2
);
3785 else if
(port
->op
== PF_OP_EQ
)
3786 snprintf
(op
, sizeof
(op
), "%s", a1
);
3787 else if
(port
->op
== PF_OP_NE
)
3788 snprintf
(op
, sizeof
(op
), "!=%s", a1
);
3789 else if
(port
->op
== PF_OP_LT
)
3790 snprintf
(op
, sizeof
(op
), "<%s", a1
);
3791 else if
(port
->op
== PF_OP_LE
)
3792 snprintf
(op
, sizeof
(op
), "<=%s", a1
);
3793 else if
(port
->op
== PF_OP_GT
)
3794 snprintf
(op
, sizeof
(op
), ">%s", a1
);
3795 else if
(port
->op
== PF_OP_GE
)
3796 snprintf
(op
, sizeof
(op
), ">=%s", a1
);
3797 expand_label_str
(label
, len
, name
, op
);
3802 expand_label_proto
(const char *name
, char *label
, size_t len
, u_int8_t proto
)
3804 struct protoent
*pe
;
3807 if
(strstr
(label
, name
) != NULL
) {
3808 pe
= getprotobynumber
(proto
);
3810 expand_label_str
(label
, len
, name
, pe
->p_name
);
3812 snprintf
(n
, sizeof
(n
), "%u", proto
);
3813 expand_label_str
(label
, len
, name
, n
);
3819 expand_label_nr
(const char *name
, char *label
, size_t len
)
3823 if
(strstr
(label
, name
) != NULL
) {
3824 snprintf
(n
, sizeof
(n
), "%u", pf
->rule_nr
);
3825 expand_label_str
(label
, len
, name
, n
);
3830 expand_label
(char *label
, size_t len
, const char *ifname
, sa_family_t af
,
3831 struct node_host
*src_host
, struct node_port
*src_port
,
3832 struct node_host
*dst_host
, struct node_port
*dst_port
,
3835 expand_label_if
("$if", label
, len
, ifname
);
3836 expand_label_addr
("$srcaddr", label
, len
, af
, src_host
);
3837 expand_label_addr
("$dstaddr", label
, len
, af
, dst_host
);
3838 expand_label_port
("$srcport", label
, len
, src_port
);
3839 expand_label_port
("$dstport", label
, len
, dst_port
);
3840 expand_label_proto
("$proto", label
, len
, proto
);
3841 expand_label_nr
("$nr", label
, len
);
3845 expand_altq
(struct pf_altq
*a
, struct node_if
*interfaces
,
3846 struct node_queue
*nqueues
, struct node_queue_bw bwspec
,
3847 struct node_queue_opt
*opts
)
3849 struct pf_altq pa
, pb
;
3850 char qname
[PF_QNAME_SIZE
];
3851 struct node_queue
*n
;
3852 struct node_queue_bw bw
;
3855 if
((pf
->loadopt
& PFCTL_FLAG_ALTQ
) == 0) {
3856 FREE_LIST
(struct node_if
, interfaces
);
3857 FREE_LIST
(struct node_queue
, nqueues
);
3861 LOOP_THROUGH
(struct node_if
, interface
, interfaces
,
3862 memcpy
(&pa
, a
, sizeof
(struct pf_altq
));
3863 if
(strlcpy
(pa.ifname
, interface
->ifname
,
3864 sizeof
(pa.ifname
)) >= sizeof
(pa.ifname
))
3865 errx
(1, "expand_altq: strlcpy");
3867 if
(interface
->not
) {
3868 yyerror("altq on ! <interface> is not supported");
3871 if
(eval_pfaltq
(pf
, &pa
, &bwspec
, opts
))
3874 if
(pfctl_add_altq
(pf
, &pa
))
3877 if
(pf
->opts
& PF_OPT_VERBOSE
) {
3878 print_altq
(&pf
->paltq
->altq
, 0,
3880 if
(nqueues
&& nqueues
->tail
) {
3882 LOOP_THROUGH
(struct node_queue
, queue
,
3892 if
(pa.scheduler
== ALTQT_CBQ ||
3893 pa.scheduler
== ALTQT_HFSC
) {
3894 /* now create a root queue */
3895 memset
(&pb
, 0, sizeof
(struct pf_altq
));
3896 if
(strlcpy
(qname
, "root_", sizeof
(qname
)) >=
3898 errx
(1, "expand_altq: strlcpy");
3899 if
(strlcat
(qname
, interface
->ifname
,
3900 sizeof
(qname
)) >= sizeof
(qname
))
3901 errx
(1, "expand_altq: strlcat");
3902 if
(strlcpy
(pb.qname
, qname
,
3903 sizeof
(pb.qname
)) >= sizeof
(pb.qname
))
3904 errx
(1, "expand_altq: strlcpy");
3905 if
(strlcpy
(pb.ifname
, interface
->ifname
,
3906 sizeof
(pb.ifname
)) >= sizeof
(pb.ifname
))
3907 errx
(1, "expand_altq: strlcpy");
3908 pb.qlimit
= pa.qlimit
;
3909 pb.scheduler
= pa.scheduler
;
3910 bw.bw_absolute
= pa.ifbandwidth
;
3912 if
(eval_pfqueue
(pf
, &pb
, &bw
, opts
))
3915 if
(pfctl_add_altq
(pf
, &pb
))
3919 LOOP_THROUGH
(struct node_queue
, queue
, nqueues
,
3920 n
= calloc
(1, sizeof
(struct node_queue
));
3922 err
(1, "expand_altq: calloc");
3923 if
(pa.scheduler
== ALTQT_CBQ ||
3924 pa.scheduler
== ALTQT_HFSC
)
3925 if
(strlcpy
(n
->parent
, qname
,
3926 sizeof
(n
->parent
)) >=
3928 errx
(1, "expand_altq: strlcpy");
3929 if
(strlcpy
(n
->queue
, queue
->queue
,
3930 sizeof
(n
->queue
)) >= sizeof
(n
->queue
))
3931 errx
(1, "expand_altq: strlcpy");
3932 if
(strlcpy
(n
->ifname
, interface
->ifname
,
3933 sizeof
(n
->ifname
)) >= sizeof
(n
->ifname
))
3934 errx
(1, "expand_altq: strlcpy");
3935 n
->scheduler
= pa.scheduler
;
3941 queues
->tail
->next
= n
;
3947 FREE_LIST
(struct node_if
, interfaces
);
3948 FREE_LIST
(struct node_queue
, nqueues
);
3954 expand_queue
(struct pf_altq
*a
, struct node_if
*interfaces
,
3955 struct node_queue
*nqueues
, struct node_queue_bw bwspec
,
3956 struct node_queue_opt
*opts
)
3958 struct node_queue
*n
, *nq
;
3963 if
((pf
->loadopt
& PFCTL_FLAG_ALTQ
) == 0) {
3964 FREE_LIST
(struct node_queue
, nqueues
);
3968 if
(queues
== NULL
) {
3969 yyerror("queue %s has no parent", a
->qname
);
3970 FREE_LIST
(struct node_queue
, nqueues
);
3974 LOOP_THROUGH
(struct node_if
, interface
, interfaces
,
3975 LOOP_THROUGH
(struct node_queue
, tqueue
, queues
,
3976 if
(!strncmp
(a
->qname
, tqueue
->queue
, PF_QNAME_SIZE
) &&
3977 (interface
->ifname
[0] == 0 ||
3978 (!interface
->not
&& !strncmp
(interface
->ifname
,
3979 tqueue
->ifname
, IFNAMSIZ
)) ||
3980 (interface
->not
&& strncmp
(interface
->ifname
,
3981 tqueue
->ifname
, IFNAMSIZ
)))) {
3982 /* found ourself in queues */
3985 memcpy
(&pa
, a
, sizeof
(struct pf_altq
));
3987 if
(pa.scheduler
!= ALTQT_NONE
&&
3988 pa.scheduler
!= tqueue
->scheduler
) {
3989 yyerror("exactly one scheduler type "
3990 "per interface allowed");
3993 pa.scheduler
= tqueue
->scheduler
;
3995 /* scheduler dependent error checking */
3996 switch
(pa.scheduler
) {
3998 if
(nqueues
!= NULL
) {
3999 yyerror("priq queues cannot "
4000 "have child queues");
4003 if
(bwspec.bw_absolute
> 0 ||
4004 bwspec.bw_percent
< 100) {
4005 yyerror("priq doesn't take "
4014 if
(strlcpy
(pa.ifname
, tqueue
->ifname
,
4015 sizeof
(pa.ifname
)) >= sizeof
(pa.ifname
))
4016 errx
(1, "expand_queue: strlcpy");
4017 if
(strlcpy
(pa.parent
, tqueue
->parent
,
4018 sizeof
(pa.parent
)) >= sizeof
(pa.parent
))
4019 errx
(1, "expand_queue: strlcpy");
4021 if
(eval_pfqueue
(pf
, &pa
, &bwspec
, opts
))
4024 if
(pfctl_add_altq
(pf
, &pa
))
4027 for
(nq
= nqueues
; nq
!= NULL
; nq
= nq
->next
) {
4028 if
(!strcmp
(a
->qname
, nq
->queue
)) {
4029 yyerror("queue cannot have "
4035 sizeof
(struct node_queue
));
4037 err
(1, "expand_queue: calloc");
4038 if
(strlcpy
(n
->parent
, a
->qname
,
4039 sizeof
(n
->parent
)) >=
4041 errx
(1, "expand_queue strlcpy");
4042 if
(strlcpy
(n
->queue
, nq
->queue
,
4043 sizeof
(n
->queue
)) >=
4045 errx
(1, "expand_queue strlcpy");
4046 if
(strlcpy
(n
->ifname
, tqueue
->ifname
,
4047 sizeof
(n
->ifname
)) >=
4049 errx
(1, "expand_queue strlcpy");
4050 n
->scheduler
= tqueue
->scheduler
;
4056 queues
->tail
->next
= n
;
4060 if
((pf
->opts
& PF_OPT_VERBOSE
) && (
4061 (found
== 1 && interface
->ifname
[0] == 0) ||
4062 (found
> 0 && interface
->ifname
[0] != 0))) {
4063 print_queue
(&pf
->paltq
->altq
, 0,
4064 &bwspec
, interface
->ifname
[0] != 0,
4066 if
(nqueues
&& nqueues
->tail
) {
4068 LOOP_THROUGH
(struct node_queue
,
4081 FREE_LIST
(struct node_queue
, nqueues
);
4082 FREE_LIST
(struct node_if
, interfaces
);
4085 yyerror("queue %s has no parent", a
->qname
);
4096 expand_rule
(struct pf_rule
*r
,
4097 struct node_if
*interfaces
, struct node_host
*rpool_hosts
,
4098 struct node_proto
*protos
, struct node_os
*src_oses
,
4099 struct node_host
*src_hosts
, struct node_port
*src_ports
,
4100 struct node_host
*dst_hosts
, struct node_port
*dst_ports
,
4101 struct node_uid
*uids
, struct node_gid
*gids
, struct node_icmp
*icmp_types
)
4103 sa_family_t af
= r
->af
;
4104 int added
= 0, error = 0;
4105 char ifname
[IF_NAMESIZE
];
4106 char label
[PF_RULE_LABEL_SIZE
];
4107 char tagname
[PF_TAG_NAME_SIZE
];
4108 char match_tagname
[PF_TAG_NAME_SIZE
];
4109 struct pf_pooladdr
*pa
;
4110 struct node_host
*h
;
4111 u_int8_t flags
, flagset
, keep_state
;
4113 if
(strlcpy
(label
, r
->label
, sizeof
(label
)) >= sizeof
(label
))
4114 errx
(1, "expand_rule: strlcpy");
4115 if
(strlcpy
(tagname
, r
->tagname
, sizeof
(tagname
)) >= sizeof
(tagname
))
4116 errx
(1, "expand_rule: strlcpy");
4117 if
(strlcpy
(match_tagname
, r
->match_tagname
, sizeof
(match_tagname
)) >=
4118 sizeof
(match_tagname
))
4119 errx
(1, "expand_rule: strlcpy");
4121 flagset
= r
->flagset
;
4122 keep_state
= r
->keep_state
;
4124 LOOP_THROUGH
(struct node_if
, interface
, interfaces
,
4125 LOOP_THROUGH
(struct node_proto
, proto
, protos
,
4126 LOOP_THROUGH
(struct node_icmp
, icmp_type
, icmp_types
,
4127 LOOP_THROUGH
(struct node_host
, src_host
, src_hosts
,
4128 LOOP_THROUGH
(struct node_port
, src_port
, src_ports
,
4129 LOOP_THROUGH
(struct node_os
, src_os
, src_oses
,
4130 LOOP_THROUGH
(struct node_host
, dst_host
, dst_hosts
,
4131 LOOP_THROUGH
(struct node_port
, dst_port
, dst_ports
,
4132 LOOP_THROUGH
(struct node_uid
, uid
, uids
,
4133 LOOP_THROUGH
(struct node_gid
, gid
, gids
,
4136 /* for link-local IPv6 address, interface must match up */
4137 if
((r
->af
&& src_host
->af
&& r
->af
!= src_host
->af
) ||
4138 (r
->af
&& dst_host
->af
&& r
->af
!= dst_host
->af
) ||
4139 (src_host
->af
&& dst_host
->af
&&
4140 src_host
->af
!= dst_host
->af
) ||
4141 (src_host
->ifindex
&& dst_host
->ifindex
&&
4142 src_host
->ifindex
!= dst_host
->ifindex
) ||
4143 (src_host
->ifindex
&& *interface
->ifname
&&
4144 src_host
->ifindex
!= if_nametoindex
(interface
->ifname
)) ||
4145 (dst_host
->ifindex
&& *interface
->ifname
&&
4146 dst_host
->ifindex
!= if_nametoindex
(interface
->ifname
)))
4148 if
(!r
->af
&& src_host
->af
)
4149 r
->af
= src_host
->af
;
4150 else if
(!r
->af
&& dst_host
->af
)
4151 r
->af
= dst_host
->af
;
4153 if
(*interface
->ifname
)
4154 memcpy
(r
->ifname
, interface
->ifname
, sizeof
(r
->ifname
));
4155 else if
(if_indextoname
(src_host
->ifindex
, ifname
))
4156 memcpy
(r
->ifname
, ifname
, sizeof
(r
->ifname
));
4157 else if
(if_indextoname
(dst_host
->ifindex
, ifname
))
4158 memcpy
(r
->ifname
, ifname
, sizeof
(r
->ifname
));
4160 memset
(r
->ifname
, '\0', sizeof
(r
->ifname
));
4162 if
(strlcpy
(r
->label
, label
, sizeof
(r
->label
)) >=
4164 errx
(1, "expand_rule: strlcpy");
4165 if
(strlcpy
(r
->tagname
, tagname
, sizeof
(r
->tagname
)) >=
4167 errx
(1, "expand_rule: strlcpy");
4168 if
(strlcpy
(r
->match_tagname
, match_tagname
,
4169 sizeof
(r
->match_tagname
)) >= sizeof
(r
->match_tagname
))
4170 errx
(1, "expand_rule: strlcpy");
4171 expand_label
(r
->label
, PF_RULE_LABEL_SIZE
, r
->ifname
, r
->af
,
4172 src_host
, src_port
, dst_host
, dst_port
, proto
->proto
);
4173 expand_label
(r
->tagname
, PF_TAG_NAME_SIZE
, r
->ifname
, r
->af
,
4174 src_host
, src_port
, dst_host
, dst_port
, proto
->proto
);
4175 expand_label
(r
->match_tagname
, PF_TAG_NAME_SIZE
, r
->ifname
,
4176 r
->af
, src_host
, src_port
, dst_host
, dst_port
,
4179 error += check_netmask
(src_host
, r
->af
);
4180 error += check_netmask
(dst_host
, r
->af
);
4182 r
->ifnot
= interface
->not
;
4183 r
->proto
= proto
->proto
;
4184 r
->src.addr
= src_host
->addr
;
4185 r
->src.not
= src_host
->not
;
4186 r
->src.port
[0] = src_port
->port
[0];
4187 r
->src.port
[1] = src_port
->port
[1];
4188 r
->src.port_op
= src_port
->op
;
4189 r
->dst.addr
= dst_host
->addr
;
4190 r
->dst.not
= dst_host
->not
;
4191 r
->dst.port
[0] = dst_port
->port
[0];
4192 r
->dst.port
[1] = dst_port
->port
[1];
4193 r
->dst.port_op
= dst_port
->op
;
4194 r
->uid.op
= uid
->op
;
4195 r
->uid.uid
[0] = uid
->uid
[0];
4196 r
->uid.uid
[1] = uid
->uid
[1];
4197 r
->gid.op
= gid
->op
;
4198 r
->gid.gid
[0] = gid
->gid
[0];
4199 r
->gid.gid
[1] = gid
->gid
[1];
4200 r
->type
= icmp_type
->type
;
4201 r
->code
= icmp_type
->code
;
4203 if
((keep_state
== PF_STATE_MODULATE ||
4204 keep_state
== PF_STATE_SYNPROXY
) &&
4205 r
->proto
&& r
->proto
!= IPPROTO_TCP
)
4206 r
->keep_state
= PF_STATE_NORMAL
;
4208 r
->keep_state
= keep_state
;
4210 if
(r
->proto
&& r
->proto
!= IPPROTO_TCP
) {
4215 r
->flagset
= flagset
;
4217 if
(icmp_type
->proto
&& r
->proto
!= icmp_type
->proto
) {
4218 yyerror("icmp-type mismatch");
4222 if
(src_os
&& src_os
->os
) {
4223 r
->os_fingerprint
= pfctl_get_fingerprint
(src_os
->os
);
4224 if
((pf
->opts
& PF_OPT_VERBOSE2
) &&
4225 r
->os_fingerprint
== PF_OSFP_NOMATCH
)
4227 "warning: unknown '%s' OS fingerprint\n",
4230 r
->os_fingerprint
= PF_OSFP_ANY
;
4233 TAILQ_INIT
(&r
->rpool.list
);
4234 for
(h
= rpool_hosts
; h
!= NULL
; h
= h
->next
) {
4235 pa
= calloc
(1, sizeof
(struct pf_pooladdr
));
4237 err
(1, "expand_rule: calloc");
4239 if
(h
->ifname
!= NULL
) {
4240 if
(strlcpy
(pa
->ifname
, h
->ifname
,
4241 sizeof
(pa
->ifname
)) >=
4243 errx
(1, "expand_rule: strlcpy");
4246 TAILQ_INSERT_TAIL
(&r
->rpool.list
, pa
, entries
);
4249 if
(rule_consistent
(r
) < 0 ||
error)
4250 yyerror("skipping rule due to errors");
4252 r
->nr
= pf
->rule_nr
++;
4253 pfctl_add_rule
(pf
, r
);
4259 FREE_LIST
(struct node_if
, interfaces
);
4260 FREE_LIST
(struct node_proto
, protos
);
4261 FREE_LIST
(struct node_host
, src_hosts
);
4262 FREE_LIST
(struct node_port
, src_ports
);
4263 FREE_LIST
(struct node_os
, src_oses
);
4264 FREE_LIST
(struct node_host
, dst_hosts
);
4265 FREE_LIST
(struct node_port
, dst_ports
);
4266 FREE_LIST
(struct node_uid
, uids
);
4267 FREE_LIST
(struct node_gid
, gids
);
4268 FREE_LIST
(struct node_icmp
, icmp_types
);
4269 FREE_LIST
(struct node_host
, rpool_hosts
);
4272 yyerror("rule expands to no valid combination");
4279 check_rulestate
(int desired_state
)
4281 if
(require_order
&& (rulestate
> desired_state
)) {
4282 yyerror("Rules must be in order: options, normalization, "
4283 "queueing, translation, filtering");
4286 rulestate
= desired_state
;
4291 kw_cmp
(const void *k
, const void *e
)
4293 return
(strcmp
(k
, ((const struct keywords
*)e
)->k_name
));
4299 /* this has to be sorted always */
4300 static const struct keywords keywords
[] = {
4302 { "allow-opts", ALLOWOPTS
},
4304 { "anchor", ANCHOR
},
4305 { "antispoof", ANTISPOOF
},
4307 { "bandwidth", BANDWIDTH
},
4309 { "binat-anchor", BINATANCHOR
},
4310 { "bitmask", BITMASK
},
4312 { "block-policy", BLOCKPOLICY
},
4315 { "crop", FRAGCROP
},
4318 { "drop-ovl", FRAGDROP
},
4320 { "fastroute", FASTROUTE
},
4321 { "file", FILENAME
},
4322 { "fingerprints", FINGERPRINTS
},
4324 { "floating", FLOATING
},
4326 { "fragment", FRAGMENT
},
4328 { "global", GLOBAL
},
4330 { "group-bound", GRBOUND
},
4332 { "hostid", HOSTID
},
4333 { "icmp-type", ICMPTYPE
},
4334 { "icmp6-type", ICMP6TYPE
},
4335 { "if-bound", IFBOUND
},
4342 { "linkshare", LINKSHARE
},
4345 { "log-all", LOGALL
},
4346 { "loginterface", LOGINTERFACE
},
4348 { "max-mss", MAXMSS
},
4349 { "max-src-nodes", MAXSRCNODES
},
4350 { "max-src-states", MAXSRCSTATES
},
4351 { "min-ttl", MINTTL
},
4352 { "modulate", MODULATE
},
4354 { "nat-anchor", NATANCHOR
},
4357 { "no-route", NOROUTE
},
4358 { "no-sync", NOSYNC
},
4360 { "optimization", OPTIMIZATION
},
4365 { "priority", PRIORITY
},
4368 { "qlimit", QLIMIT
},
4371 { "random", RANDOM
},
4372 { "random-id", RANDOMID
},
4374 { "rdr-anchor", RDRANCHOR
},
4375 { "realtime", REALTIME
},
4376 { "reassemble", REASSEMBLE
},
4377 { "reply-to", REPLYTO
},
4378 { "require-order", REQUIREORDER
},
4379 { "return", RETURN
},
4380 { "return-icmp", RETURNICMP
},
4381 { "return-icmp6", RETURNICMP6
},
4382 { "return-rst", RETURNRST
},
4383 { "round-robin", ROUNDROBIN
},
4384 { "route-to", ROUTETO
},
4388 { "source-hash", SOURCEHASH
},
4389 { "source-track", SOURCETRACK
},
4391 { "state-policy", STATEPOLICY
},
4392 { "static-port", STATICPORT
},
4393 { "sticky-address", STICKYADDRESS
},
4394 { "synproxy", SYNPROXY
},
4397 { "tagged", TAGGED
},
4398 { "tbrsize", TBRSIZE
},
4399 { "timeout", TIMEOUT
},
4403 { "upperlimit", UPPERLIMIT
},
4406 const struct keywords
*p
;
4408 p
= bsearch
(s
, keywords
, sizeof
(keywords
)/sizeof
(keywords
[0]),
4409 sizeof
(keywords
[0]), kw_cmp
);
4413 fprintf
(stderr
, "%s: %d\n", s
, p
->k_val
);
4417 fprintf
(stderr
, "string: %s\n", s
);
4422 #define MAXPUSHBACK 128
4426 char pushback_buffer
[MAXPUSHBACK
];
4427 int pushback_index
= 0;
4435 /* Read character from the parsebuffer instead of input. */
4436 if
(parseindex
>= 0) {
4437 c
= parsebuf
[parseindex
++];
4446 return
(pushback_buffer
[--pushback_index
]);
4448 while
((c
= getc
(f
)) == '\\') {
4452 yyerror("whitespace after \\");
4456 yylval.lineno
= lineno
;
4459 if
(c
== '\t' || c
== ' ') {
4460 /* Compress blanks to a single space. */
4463 } while
(c
== '\t' || c
== ' ');
4478 if
(parseindex
>= 0)
4481 if
(pushback_index
< MAXPUSHBACK
-1)
4482 return
(pushback_buffer
[pushback_index
++] = c
);
4495 /* skip to either EOF or the first real EOL */
4518 while
((c
= lgetc
(fin
)) == ' ')
4521 yylval.lineno
= lineno
;
4523 while
((c
= lgetc
(fin
)) != '\n' && c
!= EOF
)
4525 if
(c
== '$' && parsebuf
== NULL
) {
4527 if
((c
= lgetc
(fin
)) == EOF
)
4530 if
(p
+ 1 >= buf
+ sizeof
(buf
) - 1) {
4531 yyerror("string too long");
4534 if
(isalnum
(c
) || c
== '_') {
4544 yyerror("macro '%s' not defined", buf
);
4557 if
((c
= lgetc
(fin
)) == EOF
)
4567 if
(p
+ 1 >= buf
+ sizeof
(buf
) - 1) {
4568 yyerror("string too long");
4573 yylval.v.
string = strdup
(buf
);
4574 if
(yylval.v.
string == NULL
)
4575 err
(1, "yylex: strdup");
4580 yylval.v.i
= PF_OP_XRG
;
4581 return
(PORTBINARY
);
4588 yylval.v.i
= PF_OP_IRG
;
4589 return
(PORTBINARY
);
4601 #define allowed_in_string(x) \
4602 (isalnum
(x
) ||
(ispunct
(x
) && x
!= '(' && x
!= ')' && \
4603 x
!= '{' && x
!= '}' && x
!= '<' && x
!= '>' && \
4604 x
!= '!' && x
!= '=' && x
!= '/' && x
!= '#' && \
4607 if
(isalnum
(c
) || c
== ':' || c
== '_') {
4610 if
((unsigned)(p
-buf
) >= sizeof
(buf
)) {
4611 yyerror("string too long");
4614 } while
((c
= lgetc
(fin
)) != EOF
&& (allowed_in_string
(c
)));
4617 if
((token
= lookup
(buf
)) == STRING
)
4618 if
((yylval.v.
string = strdup
(buf
)) == NULL
)
4619 err
(1, "yylex: strdup");
4623 yylval.lineno
= lineno
;
4632 parse_rules
(FILE *input
, struct pfctl
*xpf
)
4634 struct sym
*sym
, *next
;
4640 rulestate
= PFCTL_STATE_NONE
;
4641 returnicmpdefault
= (ICMP_UNREACH
<< 8) | ICMP_UNREACH_PORT
;
4642 returnicmp6default
=
4643 (ICMP6_DST_UNREACH
<< 8) | ICMP6_DST_UNREACH_NOPORT
;
4644 blockpolicy
= PFRULE_DROP
;
4649 /* Free macros and check which have not been used. */
4650 for
(sym
= TAILQ_FIRST
(&symhead
); sym
!= NULL
; sym
= next
) {
4651 next
= TAILQ_NEXT
(sym
, entries
);
4652 if
((pf
->opts
& PF_OPT_VERBOSE2
) && !sym
->used
)
4653 fprintf
(stderr
, "warning: macro '%s' not "
4654 "used\n", sym
->nam
);
4657 TAILQ_REMOVE
(&symhead
, sym
, entries
);
4661 return
(errors ?
-1 : 0);
4665 * Over-designed efficiency is a French and German concept, so how about
4666 * we wait until they discover this ugliness and make it all fancy.
4669 symset
(const char *nam
, const char *val
, int persist
)
4673 for
(sym
= TAILQ_FIRST
(&symhead
); sym
&& strcmp
(nam
, sym
->nam
);
4674 sym
= TAILQ_NEXT
(sym
, entries
))
4678 if
(sym
->persist
== 1)
4683 TAILQ_REMOVE
(&symhead
, sym
, entries
);
4687 if
((sym
= calloc
(1, sizeof
(*sym
))) == NULL
)
4690 sym
->nam
= strdup
(nam
);
4691 if
(sym
->nam
== NULL
) {
4695 sym
->val
= strdup
(val
);
4696 if
(sym
->val
== NULL
) {
4702 sym
->persist
= persist
;
4703 TAILQ_INSERT_TAIL
(&symhead
, sym
, entries
);
4708 pfctl_cmdline_symset
(char *s
)
4713 if
((val
= strrchr
(s
, '=')) == NULL
)
4716 if
((sym
= malloc
(strlen
(s
) - strlen
(val
) + 1)) == NULL
)
4717 err
(1, "pfctl_cmdline_symset: malloc");
4719 strlcpy
(sym
, s
, strlen
(s
) - strlen
(val
) + 1);
4721 ret
= symset
(sym
, val
+ 1, 1);
4728 symget
(const char *nam
)
4732 TAILQ_FOREACH
(sym
, &symhead
, entries
)
4733 if
(strcmp
(nam
, sym
->nam
) == 0) {
4741 decide_address_family
(struct node_host
*n
, sa_family_t
*af
)
4743 sa_family_t target_af
= 0;
4745 while
(!*af
&& n
!= NULL
) {
4749 if
(target_af
!= n
->af
)
4754 if
(!*af
&& target_af
)
4759 remove_invalid_hosts
(struct node_host
**nh
, sa_family_t
*af
)
4761 struct node_host
*n
= *nh
, *prev
= NULL
;
4764 if
(*af
&& n
->af
&& n
->af
!= *af
) {
4765 /* unlink and free n */
4766 struct node_host
*next
= n
->next
;
4768 /* adjust tail pointer */
4769 if
(n
== (*nh
)->tail
)
4771 /* adjust previous node's next pointer */
4777 if
(n
->ifname
!= NULL
)
4791 invalid_redirect
(struct node_host
*nh
, sa_family_t af
)
4794 struct node_host
*n
;
4796 /* tables and dyniftl are ok without an address family */
4797 for
(n
= nh
; n
!= NULL
; n
= n
->next
) {
4798 if
(n
->addr.type
!= PF_ADDR_TABLE
&&
4799 n
->addr.type
!= PF_ADDR_DYNIFTL
) {
4800 yyerror("address family not given and "
4801 "translation address expands to multiple "
4802 "address families");
4808 yyerror("no translation address with matching address family "
4816 atoul
(char *s
, u_long
*ulvalp
)
4822 ulval
= strtoul
(s
, &ep
, 0);
4823 if
(s
[0] == '\0' ||
*ep
!= '\0')
4825 if
(errno
== ERANGE
&& ulval
== ULONG_MAX
)
4837 if
(atoul
(n
, &ulval
) == 0) {
4838 if
(ulval
> 65535) {
4839 yyerror("illegal port value %d", ulval
);
4842 return
(htons
(ulval
));
4844 s
= getservbyname
(n
, "tcp");
4846 s
= getservbyname
(n
, "udp");
4848 yyerror("unknown port %s", n
);
4856 rule_label
(struct pf_rule
*r
, char *s
)
4859 if
(strlcpy
(r
->label
, s
, sizeof
(r
->label
)) >=
4861 yyerror("rule label too long (max %d chars)",
4862 sizeof
(r
->label
)-1);
4870 parseicmpspec
(char *w
, sa_family_t af
)
4872 const struct icmpcodeent
*p
;
4877 icmptype
= returnicmpdefault
>> 8;
4879 icmptype
= returnicmp6default
>> 8;
4881 if
(atoul
(w
, &ulval
) == -1) {
4882 if
((p
= geticmpcodebyname
(icmptype
, w
, af
)) == NULL
) {
4883 yyerror("unknown icmp code %s", w
);
4889 yyerror("invalid icmp code %ld", ulval
);
4892 return
(icmptype
<< 8 | ulval
);
4896 pfctl_load_anchors
(int dev
, int opts
, struct pfr_buffer
*trans
)
4898 struct loadanchors
*la
;
4900 TAILQ_FOREACH
(la
, &loadanchorshead
, entries
) {
4901 if
(opts
& PF_OPT_VERBOSE
)
4902 fprintf
(stderr
, "\nLoading anchor %s:%s from %s\n",
4903 la
->anchorname
, la
->rulesetname
, la
->filename
);
4904 if
(pfctl_rules
(dev
, la
->filename
, opts
, la
->anchorname
,
4905 la
->rulesetname
, trans
) == -1)