diff options
author | mlaier <mlaier@FreeBSD.org> | 2005-05-03 16:55:20 +0000 |
---|---|---|
committer | mlaier <mlaier@FreeBSD.org> | 2005-05-03 16:55:20 +0000 |
commit | b28479dfe2b344764dddb58a31df37c21423cfde (patch) | |
tree | 7a2c1661f3b801f814c99be7e4339e2b5cfdb86f /contrib/pf/pfctl | |
parent | f9e60af5004dc157f222b733768010aa3d2e98d7 (diff) | |
download | FreeBSD-src-b28479dfe2b344764dddb58a31df37c21423cfde.zip FreeBSD-src-b28479dfe2b344764dddb58a31df37c21423cfde.tar.gz |
Resolve conflicts created during the import of pf 3.7 Some features are
missing and will be implemented in a second step. This is functional as is.
Tested by: freebsd-pf, pfsense.org
Obtained from: OpenBSD
Diffstat (limited to 'contrib/pf/pfctl')
-rw-r--r-- | contrib/pf/pfctl/parse.y | 644 | ||||
-rw-r--r-- | contrib/pf/pfctl/pf_print_state.c | 5 | ||||
-rw-r--r-- | contrib/pf/pfctl/pfctl.c | 722 | ||||
-rw-r--r-- | contrib/pf/pfctl/pfctl.h | 17 | ||||
-rw-r--r-- | contrib/pf/pfctl/pfctl_altq.c | 63 | ||||
-rw-r--r-- | contrib/pf/pfctl/pfctl_optimize.c | 7 | ||||
-rw-r--r-- | contrib/pf/pfctl/pfctl_parser.c | 213 | ||||
-rw-r--r-- | contrib/pf/pfctl/pfctl_parser.h | 61 | ||||
-rw-r--r-- | contrib/pf/pfctl/pfctl_qstats.c | 8 | ||||
-rw-r--r-- | contrib/pf/pfctl/pfctl_table.c | 36 |
10 files changed, 1127 insertions, 649 deletions
diff --git a/contrib/pf/pfctl/parse.y b/contrib/pf/pfctl/parse.y index 2c82bcd..a06a5de 100644 --- a/contrib/pf/pfctl/parse.y +++ b/contrib/pf/pfctl/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.449 2004/03/20 23:20:20 david Exp $ */ +/* $OpenBSD: parse.y,v 1.482 2005/03/07 13:20:03 henning Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$"); #include <errno.h> #include <string.h> #include <ctype.h> +#include <math.h> #include <err.h> #include <limits.h> #include <pwd.h> @@ -124,8 +125,10 @@ struct node_icmp { }; enum { PF_STATE_OPT_MAX, PF_STATE_OPT_NOSYNC, PF_STATE_OPT_SRCTRACK, - PF_STATE_OPT_MAX_SRC_STATES, PF_STATE_OPT_MAX_SRC_NODES, - PF_STATE_OPT_STATELOCK, PF_STATE_OPT_TIMEOUT }; + PF_STATE_OPT_MAX_SRC_STATES, PF_STATE_OPT_MAX_SRC_CONN, + PF_STATE_OPT_MAX_SRC_CONN_RATE, PF_STATE_OPT_MAX_SRC_NODES, + PF_STATE_OPT_OVERLOAD, PF_STATE_OPT_STATELOCK, + PF_STATE_OPT_TIMEOUT }; enum { PF_SRCTRACK_NONE, PF_SRCTRACK, PF_SRCTRACK_GLOBAL, PF_SRCTRACK_RULE }; @@ -134,6 +137,15 @@ struct node_state_opt { union { u_int32_t max_states; u_int32_t max_src_states; + u_int32_t max_src_conn; + struct { + u_int32_t limit; + u_int32_t seconds; + } max_src_conn_rate; + struct { + u_int8_t flush; + char tblname[PF_TABLE_NAME_SIZE]; + } overload; u_int32_t max_src_nodes; u_int8_t src_track; u_int32_t statelock; @@ -182,6 +194,7 @@ struct filter_opts { } flags; struct node_icmp *icmpspec; u_int32_t tos; + u_int32_t prob; struct { int action; struct node_state_opt *options; @@ -268,11 +281,13 @@ void expand_label(char *, size_t, const char *, u_int8_t, struct node_host *, void expand_rule(struct pf_rule *, struct node_if *, struct node_host *, struct node_proto *, struct node_os*, struct node_host *, struct node_port *, struct node_host *, struct node_port *, - struct node_uid *, struct node_gid *, struct node_icmp *); + struct node_uid *, struct node_gid *, struct node_icmp *, + const char *); int expand_altq(struct pf_altq *, struct node_if *, struct node_queue *, struct node_queue_bw bwspec, struct node_queue_opt *); int expand_queue(struct pf_altq *, struct node_if *, struct node_queue *, struct node_queue_bw, struct node_queue_opt *); +int expand_skip_interface(struct node_if *); int check_rulestate(int); int kw_cmp(const void *, const void *); @@ -309,7 +324,6 @@ TAILQ_HEAD(loadanchorshead, loadanchors) struct loadanchors { TAILQ_ENTRY(loadanchors) entries; char *anchorname; - char *rulesetname; char *filename; }; @@ -362,6 +376,10 @@ typedef struct { u_int8_t log; u_int8_t quick; } logquick; + struct { + int neg; + char *name; + } tagged; struct pf_poolhashkey *hashkey; struct node_queue *queue; struct node_queue_opt queue_options; @@ -378,18 +396,6 @@ typedef struct { int lineno; } YYSTYPE; -#define PREPARE_ANCHOR_RULE(r, a) \ - do { \ - memset(&(r), 0, sizeof(r)); \ - if (strlcpy(r.anchorname, (a), \ - sizeof(r.anchorname)) >= \ - sizeof(r.anchorname)) { \ - yyerror("anchor name '%s' too long", \ - (a)); \ - YYERROR; \ - } \ - } while (0) - #define DYNIF_MULTIADDR(addr) ((addr).type == PF_ADDR_DYNIFTL && \ (!((addr).iflags & PFI_AFLAG_NOALIAS) || \ !isdigit((addr).v.ifname[strlen((addr).v.ifname)-1]))) @@ -403,22 +409,24 @@ typedef struct { %token NOROUTE FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DROP TABLE %token REASSEMBLE FRAGDROP FRAGCROP ANCHOR NATANCHOR RDRANCHOR BINATANCHOR %token SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY RANDOMID -%token REQUIREORDER SYNPROXY FINGERPRINTS NOSYNC DEBUG HOSTID +%token REQUIREORDER SYNPROXY FINGERPRINTS NOSYNC DEBUG SKIP HOSTID %token ANTISPOOF FOR -%token BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT +%token BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT PROBABILITY %token ALTQ CBQ PRIQ HFSC BANDWIDTH TBRSIZE LINKSHARE REALTIME UPPERLIMIT %token QUEUE PRIORITY QLIMIT %token LOAD %token STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE -%token TAGGED TAG IFBOUND GRBOUND FLOATING STATEPOLICY +%token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH +%token TAGGED TAG IFBOUND GRBOUND FLOATING STATEPOLICY ROUTE %token <v.string> STRING %token <v.i> PORTBINARY %type <v.interface> interface if_list if_item_not if_item %type <v.number> number icmptype icmp6type uid gid %type <v.number> tos not yesno natpass -%type <v.i> no dir log af fragcache sourcetrack +%type <v.i> no dir log af fragcache sourcetrack flush %type <v.i> unaryop statelock -%type <v.b> action nataction flags flag blockspec +%type <v.b> action nataction scrubaction +%type <v.b> flags flag blockspec %type <v.range> port rport %type <v.hashkey> hashkey %type <v.proto> proto proto_list proto_item @@ -440,7 +448,7 @@ typedef struct { %type <v.keep_state> keep %type <v.state_opt> state_opt_spec state_opt_list state_opt_item %type <v.logquick> logquick -%type <v.interface> antispoof_ifspc antispoof_iflst +%type <v.interface> antispoof_ifspc antispoof_iflst antispoof_if %type <v.qassign> qname %type <v.queue> qassign qassign_list qassign_item %type <v.queue_options> scheduler @@ -454,6 +462,7 @@ typedef struct { %type <v.scrub_opts> scrub_opts scrub_opt scrub_opts_l %type <v.table_opts> table_opts table_opt table_opts_l %type <v.pool_opts> pool_opts pool_opt pool_opts_l +%type <v.tagged> tagged %% ruleset : /* empty */ @@ -494,11 +503,6 @@ option : SET OPTIMIZATION STRING { free($3); YYERROR; } - if ((ifa_exists($3, 0) == NULL) && strcmp($3, "none")) { - yyerror("interface %s doesn't exist", $3); - free($3); - YYERROR; - } if (pfctl_set_logif(pf, $3) != 0) { yyerror("error setting loginterface %s", $3); free($3); @@ -512,7 +516,7 @@ option : SET OPTIMIZATION STRING { YYERROR; } if (pfctl_set_hostid(pf, $3) != 0) { - yyerror("error setting loginterface %08x", $3); + yyerror("error setting hostid %08x", $3); YYERROR; } } @@ -538,15 +542,19 @@ option : SET OPTIMIZATION STRING { } | SET FINGERPRINTS STRING { if (pf->opts & PF_OPT_VERBOSE) - printf("fingerprints %s\n", $3); + printf("set fingerprints %s\n", $3); if (check_rulestate(PFCTL_STATE_OPTION)) { free($3); YYERROR; } - if (pfctl_file_fingerprints(pf->dev, pf->opts, $3)) { - yyerror("error loading fingerprints %s", $3); - free($3); - YYERROR; + if (!pf->anchor[0]) { + if (pfctl_file_fingerprints(pf->dev, + pf->opts, $3)) { + yyerror("error loading " + "fingerprints %s", $3); + free($3); + YYERROR; + } } free($3); } @@ -578,6 +586,12 @@ option : SET OPTIMIZATION STRING { } free($3); } + | SET SKIP interface { + if (expand_skip_interface($3) != 0) { + yyerror("error setting skip interface(s)"); + YYERROR; + } + } ; string : string STRING { @@ -607,9 +621,10 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts { YYERROR; } - PREPARE_ANCHOR_RULE(r, $2); + memset(&r, 0, sizeof(r)); r.direction = $3; r.af = $5; + r.prob = $8.prob; if ($8.match_tag) if (strlcpy(r.match_tagname, $8.match_tag, @@ -625,7 +640,8 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts { expand_rule(&r, $4, NULL, $6, $7.src_os, $7.src.host, $7.src.port, $7.dst.host, $7.dst.port, - 0, 0, 0); + 0, 0, 0, $2); + free($2); } | NATANCHOR string interface af proto fromto { struct pf_rule r; @@ -635,8 +651,7 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts { YYERROR; } - PREPARE_ANCHOR_RULE(r, $2); - free($2); + memset(&r, 0, sizeof(r)); r.action = PF_NAT; r.af = $4; @@ -645,7 +660,8 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts { expand_rule(&r, $3, NULL, $5, $6.src_os, $6.src.host, $6.src.port, $6.dst.host, $6.dst.port, - 0, 0, 0); + 0, 0, 0, $2); + free($2); } | RDRANCHOR string interface af proto fromto { struct pf_rule r; @@ -655,8 +671,7 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts { YYERROR; } - PREPARE_ANCHOR_RULE(r, $2); - free($2); + memset(&r, 0, sizeof(r)); r.action = PF_RDR; r.af = $4; @@ -686,7 +701,8 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts { expand_rule(&r, $3, NULL, $5, $6.src_os, $6.src.host, $6.src.port, $6.dst.host, $6.dst.port, - 0, 0, 0); + 0, 0, 0, $2); + free($2); } | BINATANCHOR string interface af proto fromto { struct pf_rule r; @@ -696,8 +712,7 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts { YYERROR; } - PREPARE_ANCHOR_RULE(r, $2); - free($2); + memset(&r, 0, sizeof(r)); r.action = PF_BINAT; r.af = $4; if ($5 != NULL) { @@ -720,39 +735,24 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts { decide_address_family($6.src.host, &r.af); decide_address_family($6.dst.host, &r.af); - pfctl_add_rule(pf, &r); + pfctl_add_rule(pf, &r, $2); + free($2); } ; loadrule : LOAD ANCHOR string FROM string { - char *t; struct loadanchors *loadanchor; - t = strsep(&$3, ":"); - if (*t == '\0' || $3 == NULL || *$3 == '\0') { - yyerror("anchor '%s' invalid\n", $3); - free(t); - YYERROR; - } - if (strlen(t) >= PF_ANCHOR_NAME_SIZE) { + if (strlen($3) >= MAXPATHLEN) { yyerror("anchorname %s too long, max %u\n", - t, PF_ANCHOR_NAME_SIZE - 1); - free(t); - YYERROR; - } - if (strlen($3) >= PF_RULESET_NAME_SIZE) { - yyerror("rulesetname %s too long, max %u\n", - $3, PF_RULESET_NAME_SIZE - 1); - free(t); + $3, MAXPATHLEN - 1); + free($3); YYERROR; } - loadanchor = calloc(1, sizeof(struct loadanchors)); if (loadanchor == NULL) err(1, "loadrule: calloc"); - if ((loadanchor->anchorname = strdup(t)) == NULL) - err(1, "loadrule: strdup"); - if ((loadanchor->rulesetname = strdup($3)) == NULL) + if ((loadanchor->anchorname = strdup($3)) == NULL) err(1, "loadrule: strdup"); if ((loadanchor->filename = strdup($5)) == NULL) err(1, "loadrule: strdup"); @@ -760,11 +760,20 @@ loadrule : LOAD ANCHOR string FROM string { TAILQ_INSERT_TAIL(&loadanchorshead, loadanchor, entries); - free(t); /* not $3 */ + free($3); free($5); }; -scrubrule : SCRUB dir logquick interface af proto fromto scrub_opts +scrubaction : no SCRUB { + $$.b2 = $$.w = 0; + if ($1) + $$.b1 = PF_NOSCRUB; + else + $$.b1 = PF_SCRUB; + } + ; + +scrubrule : scrubaction dir logquick interface af proto fromto scrub_opts { struct pf_rule r; @@ -773,7 +782,7 @@ scrubrule : SCRUB dir logquick interface af proto fromto scrub_opts memset(&r, 0, sizeof(r)); - r.action = PF_SCRUB; + r.action = $1.b1; r.direction = $2; r.log = $3.log; @@ -804,7 +813,7 @@ scrubrule : SCRUB dir logquick interface af proto fromto scrub_opts expand_rule(&r, $4, NULL, $6, $7.src_os, $7.src.host, $7.src.port, $7.dst.host, $7.dst.port, - NULL, NULL, NULL); + NULL, NULL, NULL, ""); } ; @@ -864,6 +873,8 @@ scrub_opt : NODF { } | REASSEMBLE STRING { if (strcasecmp($2, "tcp") != 0) { + yyerror("scrub reassemble supports only tcp, " + "not '%s'", $2); free($2); YYERROR; } @@ -890,7 +901,7 @@ fragcache : FRAGMENT REASSEMBLE { $$ = 0; /* default */ } antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts { struct pf_rule r; - struct node_host *h = NULL; + struct node_host *h = NULL, *hh; struct node_if *i, *j; if (check_rulestate(PFCTL_STATE_FILTER)) @@ -916,11 +927,35 @@ antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts { YYERROR; } j->not = 1; - h = ifa_lookup(j->ifname, PFI_AFLAG_NETWORK); + if (i->dynamic) { + h = calloc(1, sizeof(*h)); + if (h == NULL) + err(1, "address: calloc"); + h->addr.type = PF_ADDR_DYNIFTL; + set_ipmask(h, 128); + if (strlcpy(h->addr.v.ifname, i->ifname, + sizeof(h->addr.v.ifname)) >= + sizeof(h->addr.v.ifname)) { + free(h); + yyerror( + "interface name too long"); + YYERROR; + } + hh = malloc(sizeof(*hh)); + if (hh == NULL) + err(1, "address: malloc"); + bcopy(h, hh, sizeof(*hh)); + h->addr.iflags = PFI_AFLAG_NETWORK; + } else { + h = ifa_lookup(j->ifname, + PFI_AFLAG_NETWORK); + hh = NULL; + } if (h != NULL) expand_rule(&r, j, NULL, NULL, NULL, h, - NULL, NULL, NULL, NULL, NULL, NULL); + NULL, NULL, NULL, NULL, NULL, + NULL, ""); if ((i->ifa_flags & IFF_LOOPBACK) == 0) { bzero(&r, sizeof(r)); @@ -932,29 +967,40 @@ antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts { r.af = $4; if (rule_label(&r, $5.label)) YYERROR; - h = ifa_lookup(i->ifname, 0); + if (hh != NULL) + h = hh; + else + h = ifa_lookup(i->ifname, 0); if (h != NULL) expand_rule(&r, NULL, NULL, NULL, NULL, h, NULL, NULL, - NULL, NULL, NULL, NULL); - } + NULL, NULL, NULL, NULL, ""); + } else + free(hh); } free($5.label); } ; -antispoof_ifspc : FOR if_item { $$ = $2; } +antispoof_ifspc : FOR antispoof_if { $$ = $2; } | FOR '{' antispoof_iflst '}' { $$ = $3; } ; -antispoof_iflst : if_item { $$ = $1; } - | antispoof_iflst comma if_item { +antispoof_iflst : antispoof_if { $$ = $1; } + | antispoof_iflst comma antispoof_if { $1->tail->next = $3; $1->tail = $3; $$ = $1; } ; +antispoof_if : if_item { $$ = $1; } + | '(' if_item ')' { + $2->dynamic = 1; + $$ = $2; + } + ; + antispoof_opts : { bzero(&antispoof_opts, sizeof antispoof_opts); } antispoof_opts_l { $$ = antispoof_opts; } @@ -1035,6 +1081,7 @@ table_opt : STRING { else if (!strcmp($1, "persist")) table_opts.flags |= PFR_TFLAG_PERSIST; else { + yyerror("invalid table option '%s'", $1); free($1); YYERROR; } @@ -1353,14 +1400,15 @@ hfscopts_item : LINKSHARE bandwidth { hfsc_opts.linkshare.m2 = $2; hfsc_opts.linkshare.used = 1; } - | LINKSHARE '(' bandwidth number bandwidth ')' { + | LINKSHARE '(' bandwidth comma number comma bandwidth ')' + { if (hfsc_opts.linkshare.used) { yyerror("linkshare already specified"); YYERROR; } hfsc_opts.linkshare.m1 = $3; - hfsc_opts.linkshare.d = $4; - hfsc_opts.linkshare.m2 = $5; + hfsc_opts.linkshare.d = $5; + hfsc_opts.linkshare.m2 = $7; hfsc_opts.linkshare.used = 1; } | REALTIME bandwidth { @@ -1371,14 +1419,15 @@ hfscopts_item : LINKSHARE bandwidth { hfsc_opts.realtime.m2 = $2; hfsc_opts.realtime.used = 1; } - | REALTIME '(' bandwidth number bandwidth ')' { + | REALTIME '(' bandwidth comma number comma bandwidth ')' + { if (hfsc_opts.realtime.used) { yyerror("realtime already specified"); YYERROR; } hfsc_opts.realtime.m1 = $3; - hfsc_opts.realtime.d = $4; - hfsc_opts.realtime.m2 = $5; + hfsc_opts.realtime.d = $5; + hfsc_opts.realtime.m2 = $7; hfsc_opts.realtime.used = 1; } | UPPERLIMIT bandwidth { @@ -1389,14 +1438,15 @@ hfscopts_item : LINKSHARE bandwidth { hfsc_opts.upperlimit.m2 = $2; hfsc_opts.upperlimit.used = 1; } - | UPPERLIMIT '(' bandwidth number bandwidth ')' { + | UPPERLIMIT '(' bandwidth comma number comma bandwidth ')' + { if (hfsc_opts.upperlimit.used) { yyerror("upperlimit already specified"); YYERROR; } hfsc_opts.upperlimit.m1 = $3; - hfsc_opts.upperlimit.d = $4; - hfsc_opts.upperlimit.m2 = $5; + hfsc_opts.upperlimit.d = $5; + hfsc_opts.upperlimit.m2 = $7; hfsc_opts.upperlimit.used = 1; } | STRING { @@ -1482,6 +1532,7 @@ pfrule : action dir logquick interface route af proto fromto r.direction = $2; r.log = $3.log; r.quick = $3.quick; + r.prob = $9.prob; r.af = $6; if ($9.tag) @@ -1560,6 +1611,7 @@ pfrule : action dir logquick interface route af proto fromto YYERROR; } srctrack = o->data.src_track; + r.rule_flag |= PFRULE_SRCTRACK; break; case PF_STATE_OPT_MAX_SRC_STATES: if (r.max_src_states) { @@ -1568,7 +1620,7 @@ pfrule : action dir logquick interface route af proto fromto "multiple definitions"); YYERROR; } - if (o->data.max_src_nodes == 0) { + if (o->data.max_src_states == 0) { yyerror("'max-src-states' must " "be > 0"); YYERROR; @@ -1577,6 +1629,66 @@ pfrule : action dir logquick interface route af proto fromto o->data.max_src_states; r.rule_flag |= PFRULE_SRCTRACK; break; + case PF_STATE_OPT_OVERLOAD: + if (r.overload_tblname[0]) { + yyerror("multiple 'overload' " + "table definitions"); + YYERROR; + } + if (strlcpy(r.overload_tblname, + o->data.overload.tblname, + PF_TABLE_NAME_SIZE) >= + PF_TABLE_NAME_SIZE) { + yyerror("state option: " + "strlcpy"); + YYERROR; + } + r.flush = o->data.overload.flush; + break; + case PF_STATE_OPT_MAX_SRC_CONN: + if (r.max_src_conn) { + yyerror("state option " + "'max-src-conn' " + "multiple definitions"); + YYERROR; + } + if (o->data.max_src_conn == 0) { + yyerror("'max-src-conn' " + "must be > 0"); + YYERROR; + } + r.max_src_conn = + o->data.max_src_conn; + r.rule_flag |= PFRULE_SRCTRACK | + PFRULE_RULESRCTRACK; + break; + case PF_STATE_OPT_MAX_SRC_CONN_RATE: + if (r.max_src_conn_rate.limit) { + yyerror("state option " + "'max-src-conn-rate' " + "multiple definitions"); + YYERROR; + } + if (!o->data.max_src_conn_rate.limit || + !o->data.max_src_conn_rate.seconds) { + yyerror("'max-src-conn-rate' " + "values must be > 0"); + YYERROR; + } + if (o->data.max_src_conn_rate.limit > + PF_THRESHOLD_MAX) { + yyerror("'max-src-conn-rate' " + "maximum rate must be < %u", + PF_THRESHOLD_MAX); + YYERROR; + } + r.max_src_conn_rate.limit = + o->data.max_src_conn_rate.limit; + r.max_src_conn_rate.seconds = + o->data.max_src_conn_rate.seconds; + r.rule_flag |= PFRULE_SRCTRACK | + PFRULE_RULESRCTRACK; + break; case PF_STATE_OPT_MAX_SRC_NODES: if (r.max_src_nodes) { yyerror("state option " @@ -1617,7 +1729,7 @@ pfrule : action dir logquick interface route af proto fromto o = o->next; free(p); } - if (srctrack) { + if (r.rule_flag & PFRULE_SRCTRACK) { if (srctrack == PF_SRCTRACK_GLOBAL && r.max_src_nodes) { yyerror("'max-src-nodes' is " @@ -1625,6 +1737,24 @@ pfrule : action dir logquick interface route af proto fromto "'source-track global'"); YYERROR; } + if (srctrack == PF_SRCTRACK_GLOBAL && + r.max_src_conn) { + yyerror("'max-src-conn' is " + "incompatible with " + "'source-track global'"); + YYERROR; + } + if (srctrack == PF_SRCTRACK_GLOBAL && + r.max_src_conn_rate.seconds) { + yyerror("'max-src-conn-rate' is " + "incompatible with " + "'source-track global'"); + YYERROR; + } + if (r.timeout[PFTM_SRC_NODE] < + r.max_src_conn_rate.seconds) + r.timeout[PFTM_SRC_NODE] = + r.max_src_conn_rate.seconds; r.rule_flag |= PFRULE_SRCTRACK; if (srctrack == PF_SRCTRACK_RULE) r.rule_flag |= PFRULE_RULESRCTRACK; @@ -1705,7 +1835,7 @@ pfrule : action dir logquick interface route af proto fromto expand_rule(&r, $4, $5.host, $7, $8.src_os, $8.src.host, $8.src.port, $8.dst.host, $8.dst.port, - $9.uid, $9.gid, $9.icmpspec); + $9.uid, $9.gid, $9.icmpspec, ""); } ; @@ -1795,6 +1925,28 @@ filter_opt : USER uids { filter_opts.match_tag = $3; filter_opts.match_tag_not = $1; } + | PROBABILITY STRING { + char *e; + double p = strtod($2, &e); + + if (*e == '%') { + p *= 0.01; + e++; + } + if (*e) { + yyerror("invalid probability: %s", $2); + free($2); + YYERROR; + } + p = floor(p * (UINT_MAX+1.0) + 0.5); + if (p < 1.0 || p >= (UINT_MAX+1.0)) { + yyerror("invalid probability: %s", $2); + free($2); + YYERROR; + } + filter_opts.prob = (u_int32_t)p; + free($2); + } ; action : PASS { $$.b1 = PF_PASS; $$.b2 = $$.w = 0; } @@ -1906,13 +2058,6 @@ if_item_not : not if_item { $$ = $2; $$->not = $1; } if_item : STRING { struct node_host *n; - if ((n = ifa_exists($1, 1)) == NULL) { -#ifndef __FreeBSD__ - yyerror("unknown interface %s", $1); - free($1); - YYERROR; -#endif - } $$ = calloc(1, sizeof(struct node_if)); if ($$ == NULL) err(1, "if_item: calloc"); @@ -1923,13 +2068,11 @@ if_item : STRING { yyerror("interface name too long"); YYERROR; } + + if ((n = ifa_exists($1, 1)) != NULL) + $$->ifa_flags = n->ifa_flags; + free($1); -#ifdef __FreeBSD__ - if (n == NULL) - $$->ifa_flags = PF_IFA_FLAG_DYNAMIC; - else /* XXX ugly */ -#endif - $$->ifa_flags = n->ifa_flags; $$->not = 0; $$->next = NULL; $$->tail = $$; @@ -2144,6 +2287,26 @@ host : STRING { $$->next = NULL; $$->tail = $$; } + | ROUTE STRING { + $$ = calloc(1, sizeof(struct node_host)); + if ($$ == NULL) { + free($2); + err(1, "host: calloc"); + } + $$->addr.type = PF_ADDR_RTLABEL; + if (strlcpy($$->addr.v.rtlabelname, $2, + sizeof($$->addr.v.rtlabelname)) >= + sizeof($$->addr.v.rtlabelname)) { + yyerror("route label too long, max %u chars", + sizeof($$->addr.v.rtlabelname) - 1); + free($2); + free($$); + YYERROR; + } + $$->next = NULL; + $$->tail = $$; + free($2); + } ; number : STRING { @@ -2164,6 +2327,11 @@ dynaddr : '(' STRING ')' { char *p, *op; op = $2; + if (!isalpha(op[0])) { + yyerror("invalid interface name '%s'", op); + free(op); + YYERROR; + } while ((p = strrchr($2, ':')) != NULL) { if (!strcmp(p+1, "network")) flags |= PFI_AFLAG_NETWORK; @@ -2187,13 +2355,6 @@ dynaddr : '(' STRING ')' { "interface modifiers"); YYERROR; } - if (ifa_exists($2, 1) == NULL && strcmp($2, "self")) { -#ifndef __FreeBSD__ - yyerror("interface %s does not exist", $2); - free(op); - YYERROR; -#endif - } $$ = calloc(1, sizeof(struct node_host)); if ($$ == NULL) err(1, "address: calloc"); @@ -2281,7 +2442,7 @@ port : STRING { if (atoul($1, &ulval) == 0) { if (ulval > 65535) { free($1); - yyerror("illegal port value %d", + yyerror("illegal port value %lu", ulval); YYERROR; } @@ -2536,7 +2697,7 @@ icmp_item : icmptype { if (atoul($3, &ulval) == 0) { if (ulval > 255) { free($3); - yyerror("illegal icmp-code %d", ulval); + yyerror("illegal icmp-code %lu", ulval); YYERROR; } } else { @@ -2576,7 +2737,7 @@ icmp6_item : icmp6type { if (atoul($3, &ulval) == 0) { if (ulval > 255) { - yyerror("illegal icmp6-code %ld", + yyerror("illegal icmp6-code %lu", ulval); free($3); YYERROR; @@ -2608,7 +2769,7 @@ icmptype : STRING { if (atoul($1, &ulval) == 0) { if (ulval > 255) { - yyerror("illegal icmp-type %d", ulval); + yyerror("illegal icmp-type %lu", ulval); free($1); YYERROR; } @@ -2632,7 +2793,7 @@ icmp6type : STRING { if (atoul($1, &ulval) == 0) { if (ulval > 255) { - yyerror("illegal icmp6-type %d", ulval); + yyerror("illegal icmp6-type %lu", ulval); free($1); YYERROR; } @@ -2700,6 +2861,13 @@ keep : KEEP STATE state_opt_spec { } ; +flush : /* empty */ { $$ = 0; } + | FLUSH { $$ = PF_FLUSH; } + | FLUSH GLOBAL { + $$ = PF_FLUSH | PF_FLUSH_GLOBAL; + } + ; + state_opt_spec : '(' state_opt_list ')' { $$ = $2; } | /* empty */ { $$ = NULL; } ; @@ -2738,6 +2906,43 @@ state_opt_item : MAXIMUM number { $$->next = NULL; $$->tail = $$; } + | MAXSRCCONN number { + $$ = calloc(1, sizeof(struct node_state_opt)); + if ($$ == NULL) + err(1, "state_opt_item: calloc"); + $$->type = PF_STATE_OPT_MAX_SRC_CONN; + $$->data.max_src_conn = $2; + $$->next = NULL; + $$->tail = $$; + } + | MAXSRCCONNRATE number '/' number { + $$ = calloc(1, sizeof(struct node_state_opt)); + if ($$ == NULL) + err(1, "state_opt_item: calloc"); + $$->type = PF_STATE_OPT_MAX_SRC_CONN_RATE; + $$->data.max_src_conn_rate.limit = $2; + $$->data.max_src_conn_rate.seconds = $4; + $$->next = NULL; + $$->tail = $$; + } + | OVERLOAD '<' STRING '>' flush { + if (strlen($3) >= PF_TABLE_NAME_SIZE) { + yyerror("table name '%s' too long", $3); + free($3); + YYERROR; + } + $$ = calloc(1, sizeof(struct node_state_opt)); + if ($$ == NULL) + err(1, "state_opt_item: calloc"); + if (strlcpy($$->data.overload.tblname, $3, + PF_TABLE_NAME_SIZE) >= PF_TABLE_NAME_SIZE) + errx(1, "state_opt_item: strlcpy"); + free($3); + $$->type = PF_STATE_OPT_OVERLOAD; + $$->data.overload.flush = $5; + $$->next = NULL; + $$->tail = $$; + } | MAXSRCNODES number { $$ = calloc(1, sizeof(struct node_state_opt)); if ($$ == NULL) @@ -3023,7 +3228,7 @@ nataction : no NAT natpass { } ; -natrule : nataction interface af proto fromto tag redirpool pool_opts +natrule : nataction interface af proto fromto tag tagged redirpool pool_opts { struct pf_rule r; @@ -3053,46 +3258,55 @@ natrule : nataction interface af proto fromto tag redirpool pool_opts YYERROR; } + if ($7.name) + if (strlcpy(r.match_tagname, $7.name, + PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) { + yyerror("tag too long, max %u chars", + PF_TAG_NAME_SIZE - 1); + YYERROR; + } + r.match_tag_not = $7.neg; + if (r.action == PF_NONAT || r.action == PF_NORDR) { - if ($7 != NULL) { + if ($8 != NULL) { yyerror("translation rule with 'no' " "does not need '->'"); YYERROR; } } else { - if ($7 == NULL || $7->host == NULL) { + if ($8 == NULL || $8->host == NULL) { yyerror("translation rule requires '-> " "address'"); YYERROR; } - if (!r.af && ! $7->host->ifindex) - r.af = $7->host->af; + if (!r.af && ! $8->host->ifindex) + r.af = $8->host->af; - remove_invalid_hosts(&$7->host, &r.af); - if (invalid_redirect($7->host, r.af)) + remove_invalid_hosts(&$8->host, &r.af); + if (invalid_redirect($8->host, r.af)) YYERROR; - if (check_netmask($7->host, r.af)) + if (check_netmask($8->host, r.af)) YYERROR; - r.rpool.proxy_port[0] = ntohs($7->rport.a); + r.rpool.proxy_port[0] = ntohs($8->rport.a); switch (r.action) { case PF_RDR: - if (!$7->rport.b && $7->rport.t && + if (!$8->rport.b && $8->rport.t && $5.dst.port != NULL) { r.rpool.proxy_port[1] = - ntohs($7->rport.a) + + ntohs($8->rport.a) + (ntohs( $5.dst.port->port[1]) - ntohs( $5.dst.port->port[0])); } else r.rpool.proxy_port[1] = - ntohs($7->rport.b); + ntohs($8->rport.b); break; case PF_NAT: r.rpool.proxy_port[1] = - ntohs($7->rport.b); + ntohs($8->rport.b); if (!r.rpool.proxy_port[0] && !r.rpool.proxy_port[1]) { r.rpool.proxy_port[0] = @@ -3107,25 +3321,25 @@ natrule : nataction interface af proto fromto tag redirpool pool_opts break; } - r.rpool.opts = $8.type; + r.rpool.opts = $9.type; if ((r.rpool.opts & PF_POOL_TYPEMASK) == - PF_POOL_NONE && ($7->host->next != NULL || - $7->host->addr.type == PF_ADDR_TABLE || - DYNIF_MULTIADDR($7->host->addr))) + PF_POOL_NONE && ($8->host->next != NULL || + $8->host->addr.type == PF_ADDR_TABLE || + DYNIF_MULTIADDR($8->host->addr))) r.rpool.opts = PF_POOL_ROUNDROBIN; if ((r.rpool.opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN && - disallow_table($7->host, "tables are only " + disallow_table($8->host, "tables are only " "supported in round-robin redirection " "pools")) YYERROR; if ((r.rpool.opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN && - disallow_alias($7->host, "interface (%s) " + disallow_alias($8->host, "interface (%s) " "is only supported in round-robin " "redirection pools")) YYERROR; - if ($7->host->next != NULL) { + if ($8->host->next != NULL) { if ((r.rpool.opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN) { yyerror("only round-robin " @@ -3136,14 +3350,14 @@ natrule : nataction interface af proto fromto tag redirpool pool_opts } } - if ($8.key != NULL) - memcpy(&r.rpool.key, $8.key, + if ($9.key != NULL) + memcpy(&r.rpool.key, $9.key, sizeof(struct pf_poolhashkey)); - if ($8.opts) - r.rpool.opts |= $8.opts; + if ($9.opts) + r.rpool.opts |= $9.opts; - if ($8.staticport) { + if ($9.staticport) { if (r.action != PF_NAT) { yyerror("the 'static-port' option is " "only valid with nat rules"); @@ -3162,14 +3376,14 @@ natrule : nataction interface af proto fromto tag redirpool pool_opts r.rpool.proxy_port[1] = 0; } - expand_rule(&r, $2, $7 == NULL ? NULL : $7->host, $4, + expand_rule(&r, $2, $8 == NULL ? NULL : $8->host, $4, $5.src_os, $5.src.host, $5.src.port, $5.dst.host, - $5.dst.port, 0, 0, 0); - free($7); + $5.dst.port, 0, 0, 0, ""); + free($8); } ; -binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag +binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag tagged redirection { struct pf_rule binat; @@ -3190,8 +3404,9 @@ binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag binat.af = $8->af; if (!binat.af && $10 != NULL && $10->af) binat.af = $10->af; - if (!binat.af && $12 != NULL && $12->host) - binat.af = $12->host->af; + + if (!binat.af && $13 != NULL && $13->host) + binat.af = $13->host->af; if (!binat.af) { yyerror("address family (inet/inet6) " "undefined"); @@ -3204,6 +3419,7 @@ binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag binat.ifnot = $4->not; free($4); } + if ($11 != NULL) if (strlcpy(binat.tagname, $11, PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) { @@ -3211,6 +3427,14 @@ binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag PF_TAG_NAME_SIZE - 1); YYERROR; } + if ($12.name) + if (strlcpy(binat.match_tagname, $12.name, + PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) { + yyerror("tag too long, max %u chars", + PF_TAG_NAME_SIZE - 1); + YYERROR; + } + binat.match_tag_not = $12.neg; if ($6 != NULL) { binat.proto = $6->proto; @@ -3224,12 +3448,12 @@ binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag "interface (%s) as the source address of a binat " "rule")) YYERROR; - if ($12 != NULL && $12->host != NULL && disallow_table( - $12->host, "invalid use of table <%s> as the " + if ($13 != NULL && $13->host != NULL && disallow_table( + $13->host, "invalid use of table <%s> as the " "redirect address of a binat rule")) YYERROR; - if ($12 != NULL && $12->host != NULL && disallow_alias( - $12->host, "invalid use of interface (%s) as the " + if ($13 != NULL && $13->host != NULL && disallow_alias( + $13->host, "invalid use of interface (%s) as the " "redirect address of a binat rule")) YYERROR; @@ -3263,38 +3487,38 @@ binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag YYERROR; memcpy(&binat.dst.addr, &$10->addr, sizeof(binat.dst.addr)); - binat.dst.not = $10->not; + binat.dst.neg = $10->not; free($10); } if (binat.action == PF_NOBINAT) { - if ($12 != NULL) { + if ($13 != NULL) { yyerror("'no binat' rule does not need" " '->'"); YYERROR; } } else { - if ($12 == NULL || $12->host == NULL) { + if ($13 == NULL || $13->host == NULL) { yyerror("'binat' rule requires" " '-> address'"); YYERROR; } - remove_invalid_hosts(&$12->host, &binat.af); - if (invalid_redirect($12->host, binat.af)) + remove_invalid_hosts(&$13->host, &binat.af); + if (invalid_redirect($13->host, binat.af)) YYERROR; - if ($12->host->next != NULL) { + if ($13->host->next != NULL) { yyerror("binat rule must redirect to " "a single address"); YYERROR; } - if (check_netmask($12->host, binat.af)) + if (check_netmask($13->host, binat.af)) YYERROR; if (!PF_AZERO(&binat.src.addr.v.a.mask, binat.af) && !PF_AEQ(&binat.src.addr.v.a.mask, - &$12->host->addr.v.a.mask, binat.af)) { + &$13->host->addr.v.a.mask, binat.af)) { yyerror("'binat' source mask and " "redirect mask must be the same"); YYERROR; @@ -3304,15 +3528,15 @@ binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag pa = calloc(1, sizeof(struct pf_pooladdr)); if (pa == NULL) err(1, "binat: calloc"); - pa->addr = $12->host->addr; + pa->addr = $13->host->addr; pa->ifname[0] = 0; TAILQ_INSERT_TAIL(&binat.rpool.list, pa, entries); - free($12); + free($13); } - pfctl_add_rule(pf, &binat); + pfctl_add_rule(pf, &binat, ""); } ; @@ -3320,18 +3544,15 @@ tag : /* empty */ { $$ = NULL; } | TAG STRING { $$ = $2; } ; +tagged : /* empty */ { $$.neg = 0; $$.name = NULL; } + | not TAGGED string { $$.neg = $1; $$.name = $3; } + ; + route_host : STRING { $$ = calloc(1, sizeof(struct node_host)); if ($$ == NULL) err(1, "route_host: calloc"); $$->ifname = $1; - if (ifa_exists($$->ifname, 0) == NULL) { - yyerror("routeto: unknown interface %s", - $$->ifname); - free($1); - free($$); - YYERROR; - } set_ipmask($$, 128); $$->next = NULL; $$->tail = $$; @@ -3339,11 +3560,6 @@ route_host : STRING { | '(' STRING host ')' { $$ = $3; $$->ifname = $2; - if (ifa_exists($$->ifname, 0) == NULL) { - yyerror("routeto: unknown interface %s", - $$->ifname); - YYERROR; - } } ; @@ -3446,6 +3662,8 @@ yesno : NO { $$ = 0; } if (!strcmp($1, "yes")) $$ = 1; else { + yyerror("invalid value '%s', expected 'yes' " + "or 'no'", $1); free($1); YYERROR; } @@ -3509,6 +3727,7 @@ rule_consistent(struct pf_rule *r) case PF_PASS: case PF_DROP: case PF_SCRUB: + case PF_NOSCRUB: problems = filter_consistent(r); break; case PF_NAT: @@ -3546,6 +3765,12 @@ filter_consistent(struct pf_rule *r) yyerror("must indicate address family with icmp-type/code"); problems++; } + if (r->overload_tblname[0] && + r->max_src_conn == 0 && r->max_src_conn_rate.seconds == 0) { + yyerror("'overload' requires 'max-src-conn' " + "or 'max-src-conn-rate'"); + problems++; + } if ((r->proto == IPPROTO_ICMP && r->af == AF_INET6) || (r->proto == IPPROTO_ICMPV6 && r->af == AF_INET)) { yyerror("proto %s doesn't match address family %s", @@ -3575,7 +3800,7 @@ filter_consistent(struct pf_rule *r) problems++; } if ((r->tagname[0] || r->match_tagname[0]) && !r->keep_state && - r->action == PF_PASS && !r->anchorname[0]) { + r->action == PF_PASS) { yyerror("tags cannot be used without keep state"); problems++; } @@ -3646,7 +3871,7 @@ process_tabledef(char *name, struct table_opts *opts) &opts->init_nodes); if (!(pf->opts & PF_OPT_NOACTION) && pfctl_define_table(name, opts->flags, opts->init_addr, - pf->anchor, pf->ruleset, &ab, pf->tticket)) { + pf->anchor, &ab, pf->tticket)) { yyerror("cannot define table %s: %s", name, pfr_strerror(errno)); goto _error; @@ -4112,7 +4337,8 @@ expand_rule(struct pf_rule *r, struct node_proto *protos, struct node_os *src_oses, struct node_host *src_hosts, struct node_port *src_ports, struct node_host *dst_hosts, struct node_port *dst_ports, - struct node_uid *uids, struct node_gid *gids, struct node_icmp *icmp_types) + struct node_uid *uids, struct node_gid *gids, struct node_icmp *icmp_types, + const char *anchor_call) { sa_family_t af = r->af; int added = 0, error = 0; @@ -4165,11 +4391,12 @@ expand_rule(struct pf_rule *r, r->af = dst_host->af; if (*interface->ifname) - memcpy(r->ifname, interface->ifname, sizeof(r->ifname)); + strlcpy(r->ifname, interface->ifname, + sizeof(r->ifname)); else if (if_indextoname(src_host->ifindex, ifname)) - memcpy(r->ifname, ifname, sizeof(r->ifname)); + strlcpy(r->ifname, ifname, sizeof(r->ifname)); else if (if_indextoname(dst_host->ifindex, ifname)) - memcpy(r->ifname, ifname, sizeof(r->ifname)); + strlcpy(r->ifname, ifname, sizeof(r->ifname)); else memset(r->ifname, '\0', sizeof(r->ifname)); @@ -4196,12 +4423,12 @@ expand_rule(struct pf_rule *r, r->ifnot = interface->not; r->proto = proto->proto; r->src.addr = src_host->addr; - r->src.not = src_host->not; + r->src.neg = src_host->not; r->src.port[0] = src_port->port[0]; r->src.port[1] = src_port->port[1]; r->src.port_op = src_port->op; r->dst.addr = dst_host->addr; - r->dst.not = dst_host->not; + r->dst.neg = dst_host->not; r->dst.port[0] = dst_port->port[0]; r->dst.port[1] = dst_port->port[1]; r->dst.port_op = dst_port->op; @@ -4264,7 +4491,7 @@ expand_rule(struct pf_rule *r, yyerror("skipping rule due to errors"); else { r->nr = pf->rule_nr++; - pfctl_add_rule(pf, r); + pfctl_add_rule(pf, r, anchor_call); added++; } @@ -4286,6 +4513,42 @@ expand_rule(struct pf_rule *r, yyerror("rule expands to no valid combination"); } +int +expand_skip_interface(struct node_if *interfaces) +{ + int errs = 0; + + if (!interfaces || (!interfaces->next && !interfaces->not && + !strcmp(interfaces->ifname, "none"))) { + if (pf->opts & PF_OPT_VERBOSE) + printf("set skip on none\n"); + errs = pfctl_set_interface_flags(pf, "", PFI_IFLAG_SKIP, 0); + return (errs); + } + + if (pf->opts & PF_OPT_VERBOSE) + printf("set skip on {"); + LOOP_THROUGH(struct node_if, interface, interfaces, + if (pf->opts & PF_OPT_VERBOSE) + printf(" %s", interface->ifname); + if (interface->not) { + yyerror("skip on ! <interface> is not supported"); + errs++; + } else + errs += pfctl_set_interface_flags(pf, + interface->ifname, PFI_IFLAG_SKIP, 1); + ); + if (pf->opts & PF_OPT_VERBOSE) + printf(" }\n"); + + FREE_LIST(struct node_if, interfaces); + + if (errs) + return (1); + else + return (0); +} + #undef FREE_LIST #undef LOOP_THROUGH @@ -4336,6 +4599,7 @@ lookup(char *s) { "fingerprints", FINGERPRINTS}, { "flags", FLAGS}, { "floating", FLOATING}, + { "flush", FLUSH}, { "for", FOR}, { "fragment", FRAGMENT}, { "from", FROM}, @@ -4360,6 +4624,8 @@ lookup(char *s) { "loginterface", LOGINTERFACE}, { "max", MAXIMUM}, { "max-mss", MAXMSS}, + { "max-src-conn", MAXSRCCONN}, + { "max-src-conn-rate", MAXSRCCONNRATE}, { "max-src-nodes", MAXSRCNODES}, { "max-src-states", MAXSRCSTATES}, { "min-ttl", MINTTL}, @@ -4374,10 +4640,12 @@ lookup(char *s) { "optimization", OPTIMIZATION}, { "os", OS}, { "out", OUT}, + { "overload", OVERLOAD}, { "pass", PASS}, { "port", PORT}, { "priority", PRIORITY}, { "priq", PRIQ}, + { "probability", PROBABILITY}, { "proto", PROTO}, { "qlimit", QLIMIT}, { "queue", QUEUE}, @@ -4395,10 +4663,12 @@ lookup(char *s) { "return-icmp6", RETURNICMP6}, { "return-rst", RETURNRST}, { "round-robin", ROUNDROBIN}, + { "route", ROUTE}, { "route-to", ROUTETO}, { "rule", RULE}, { "scrub", SCRUB}, { "set", SET}, + { "skip", SKIP}, { "source-hash", SOURCEHASH}, { "source-track", SOURCETRACK}, { "state", STATE}, @@ -4850,7 +5120,7 @@ getservice(char *n) if (atoul(n, &ulval) == 0) { if (ulval > 65535) { - yyerror("illegal port value %d", ulval); + yyerror("illegal port value %lu", ulval); return (-1); } return (htons(ulval)); @@ -4900,7 +5170,7 @@ parseicmpspec(char *w, sa_family_t af) ulval = p->code; } if (ulval > 255) { - yyerror("invalid icmp code %ld", ulval); + yyerror("invalid icmp code %lu", ulval); return (0); } return (icmptype << 8 | ulval); @@ -4913,10 +5183,10 @@ pfctl_load_anchors(int dev, int opts, struct pfr_buffer *trans) TAILQ_FOREACH(la, &loadanchorshead, entries) { if (opts & PF_OPT_VERBOSE) - fprintf(stderr, "\nLoading anchor %s:%s from %s\n", - la->anchorname, la->rulesetname, la->filename); + fprintf(stderr, "\nLoading anchor %s from %s\n", + la->anchorname, la->filename); if (pfctl_rules(dev, la->filename, opts, la->anchorname, - la->rulesetname, trans) == -1) + trans) == -1) return (-1); } diff --git a/contrib/pf/pfctl/pf_print_state.c b/contrib/pf/pfctl/pf_print_state.c index 318bde7..1205547 100644 --- a/contrib/pf/pfctl/pf_print_state.c +++ b/contrib/pf/pfctl/pf_print_state.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_print_state.c,v 1.39 2004/02/10 17:48:08 henning Exp $ */ +/* $OpenBSD: pf_print_state.c,v 1.40 2004/12/10 22:13:26 henning Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -100,6 +100,9 @@ print_addr(struct pf_addr_wrap *addr, sa_family_t af, int verbose) case PF_ADDR_NOROUTE: printf("no-route"); return; + case PF_ADDR_RTLABEL: + printf("route \"%s\"", addr->v.rtlabelname); + return; default: printf("?"); return; diff --git a/contrib/pf/pfctl/pfctl.c b/contrib/pf/pfctl/pfctl.c index 6abbbec..bc4c96e 100644 --- a/contrib/pf/pfctl/pfctl.c +++ b/contrib/pf/pfctl/pfctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl.c,v 1.213 2004/03/20 09:31:42 david Exp $ */ +/* $OpenBSD: pfctl.c,v 1.234 2005/03/07 13:52:50 henning Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include <sys/types.h> #include <sys/ioctl.h> #include <sys/socket.h> +#include <sys/stat.h> #include <net/if.h> #include <netinet/in.h> @@ -65,23 +66,31 @@ void usage(void); int pfctl_enable(int, int); int pfctl_disable(int, int); int pfctl_clear_stats(int, int); -int pfctl_clear_rules(int, int, char *, char *); -int pfctl_clear_nat(int, int, char *, char *); +int pfctl_clear_interface_flags(int, int); +int pfctl_clear_rules(int, int, char *); +int pfctl_clear_nat(int, int, char *); int pfctl_clear_altq(int, int); int pfctl_clear_src_nodes(int, int); int pfctl_clear_states(int, const char *, int); int pfctl_kill_states(int, const char *, int); +void pfctl_init_options(struct pfctl *); +int pfctl_load_options(struct pfctl *); +int pfctl_load_limit(struct pfctl *, unsigned int, unsigned int); +int pfctl_load_timeout(struct pfctl *, unsigned int, unsigned int); +int pfctl_load_debug(struct pfctl *, unsigned int); +int pfctl_load_logif(struct pfctl *, char *); +int pfctl_load_hostid(struct pfctl *, unsigned int); int pfctl_get_pool(int, struct pf_pool *, u_int32_t, u_int32_t, int, - char *, char *); + char *); void pfctl_print_rule_counters(struct pf_rule *, int); -int pfctl_show_rules(int, int, int, char *, char *); -int pfctl_show_nat(int, int, char *, char *); +int pfctl_show_rules(int, int, int, char *); +int pfctl_show_nat(int, int, char *); int pfctl_show_src_nodes(int, int); int pfctl_show_states(int, const char *, int); int pfctl_show_status(int, int); int pfctl_show_timeouts(int, int); int pfctl_show_limits(int, int); -int pfctl_debug(int, u_int32_t, int); +void pfctl_debug(int, u_int32_t, int); int pfctl_clear_rule_counters(int, int); int pfctl_test_altqsupport(int, int); int pfctl_show_anchors(int, int, char *); @@ -128,6 +137,7 @@ static const struct pf_hint pf_hint_normal[] = { { "tcp.closing", 15 * 60 }, { "tcp.finwait", 45 }, { "tcp.closed", 90 }, + { "tcp.tsdiff", 30 }, { NULL, 0 } }; static const struct pf_hint pf_hint_satellite[] = { @@ -137,6 +147,7 @@ static const struct pf_hint pf_hint_satellite[] = { { "tcp.closing", 15 * 60 + 5 }, { "tcp.finwait", 45 + 5 }, { "tcp.closed", 90 + 5 }, + { "tcp.tsdiff", 60 }, { NULL, 0 } }; static const struct pf_hint pf_hint_conservative[] = { @@ -146,6 +157,7 @@ static const struct pf_hint pf_hint_conservative[] = { { "tcp.closing", 60 * 60 }, { "tcp.finwait", 10 * 60 }, { "tcp.closed", 3 * 60 }, + { "tcp.tsdiff", 60 }, { NULL, 0 } }; static const struct pf_hint pf_hint_aggressive[] = { @@ -155,6 +167,7 @@ static const struct pf_hint pf_hint_aggressive[] = { { "tcp.closing", 60 }, { "tcp.finwait", 30 }, { "tcp.closed", 30 }, + { "tcp.tsdiff", 10 }, { NULL, 0 } }; @@ -196,14 +209,14 @@ usage(void) { extern char *__progname; - fprintf(stderr, "usage: %s [-AdeghNnOqRrvz] ", __progname); - fprintf(stderr, "[-a anchor[:ruleset]] [-D macro=value]\n"); + fprintf(stderr, "usage: %s [-AdeghmNnOoqRrvz] ", __progname); + fprintf(stderr, "[-a anchor] [-D macro=value] [-F modifier]\n"); fprintf(stderr, " "); - fprintf(stderr, "[-F modifier] [-f file] [-i interface] "); - fprintf(stderr, "[-k host] [-p device]\n"); + fprintf(stderr, "[-f file] [-i interface] [-k host] "); + fprintf(stderr, "[-p device] [-s modifier]\n"); fprintf(stderr, " "); - fprintf(stderr, "[-s modifier] [-T command [address ...]] "); - fprintf(stderr, "[-t table] [-x level]\n"); + fprintf(stderr, "[-t table -T command [address ...]] "); + fprintf(stderr, "[-x level]\n"); exit(1); } @@ -260,42 +273,31 @@ pfctl_clear_stats(int dev, int opts) } int -pfctl_clear_rules(int dev, int opts, char *anchorname, char *rulesetname) +pfctl_clear_interface_flags(int dev, int opts) { - struct pfr_buffer t; + struct pfioc_iface pi; - if (*anchorname && !*rulesetname) { - struct pfioc_ruleset pr; - int mnr, nr, r; + if ((opts & PF_OPT_NOACTION) == 0) { + bzero(&pi, sizeof(pi)); + pi.pfiio_flags = PFI_IFLAG_SETABLE_MASK; - memset(&pr, 0, sizeof(pr)); - memcpy(pr.anchor, anchorname, sizeof(pr.anchor)); - if (ioctl(dev, DIOCGETRULESETS, &pr)) { - if (errno == EINVAL) - fprintf(stderr, "No rulesets in anchor '%s'.\n", - anchorname); - else - err(1, "DIOCGETRULESETS"); - return (-1); - } - mnr = pr.nr; - for (nr = mnr - 1; nr >= 0; --nr) { - pr.nr = nr; - if (ioctl(dev, DIOCGETRULESET, &pr)) - err(1, "DIOCGETRULESET"); - r = pfctl_clear_rules(dev, opts | PF_OPT_QUIET, - anchorname, pr.name); - if (r) - return (r); - } + if (ioctl(dev, DIOCCLRIFFLAG, &pi)) + err(1, "DIOCCLRIFFLAG"); if ((opts & PF_OPT_QUIET) == 0) - fprintf(stderr, "rules cleared\n"); - return (0); + fprintf(stderr, "pf: interface flags reset\n"); } + return (0); +} + +int +pfctl_clear_rules(int dev, int opts, char *anchorname) +{ + struct pfr_buffer t; + memset(&t, 0, sizeof(t)); t.pfrb_type = PFRB_TRANS; - if (pfctl_add_trans(&t, PF_RULESET_SCRUB, anchorname, rulesetname) || - pfctl_add_trans(&t, PF_RULESET_FILTER, anchorname, rulesetname) || + if (pfctl_add_trans(&t, PF_RULESET_SCRUB, anchorname) || + pfctl_add_trans(&t, PF_RULESET_FILTER, anchorname) || pfctl_trans(dev, &t, DIOCXBEGIN, 0) || pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) err(1, "pfctl_clear_rules"); @@ -305,43 +307,15 @@ pfctl_clear_rules(int dev, int opts, char *anchorname, char *rulesetname) } int -pfctl_clear_nat(int dev, int opts, char *anchorname, char *rulesetname) +pfctl_clear_nat(int dev, int opts, char *anchorname) { struct pfr_buffer t; - if (*anchorname && !*rulesetname) { - struct pfioc_ruleset pr; - int mnr, nr, r; - - memset(&pr, 0, sizeof(pr)); - memcpy(pr.anchor, anchorname, sizeof(pr.anchor)); - if (ioctl(dev, DIOCGETRULESETS, &pr)) { - if (errno == EINVAL) - fprintf(stderr, "No rulesets in anchor '%s'.\n", - anchorname); - else - err(1, "DIOCGETRULESETS"); - return (-1); - } - mnr = pr.nr; - for (nr = mnr - 1; nr >= 0; --nr) { - pr.nr = nr; - if (ioctl(dev, DIOCGETRULESET, &pr)) - err(1, "DIOCGETRULESET"); - r = pfctl_clear_nat(dev, opts | PF_OPT_QUIET, - anchorname, pr.name); - if (r) - return (r); - } - if ((opts & PF_OPT_QUIET) == 0) - fprintf(stderr, "nat cleared\n"); - return (0); - } memset(&t, 0, sizeof(t)); t.pfrb_type = PFRB_TRANS; - if (pfctl_add_trans(&t, PF_RULESET_NAT, anchorname, rulesetname) || - pfctl_add_trans(&t, PF_RULESET_BINAT, anchorname, rulesetname) || - pfctl_add_trans(&t, PF_RULESET_RDR, anchorname, rulesetname) || + if (pfctl_add_trans(&t, PF_RULESET_NAT, anchorname) || + pfctl_add_trans(&t, PF_RULESET_BINAT, anchorname) || + pfctl_add_trans(&t, PF_RULESET_RDR, anchorname) || pfctl_trans(dev, &t, DIOCXBEGIN, 0) || pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) err(1, "pfctl_clear_nat"); @@ -359,7 +333,7 @@ pfctl_clear_altq(int dev, int opts) return (-1); memset(&t, 0, sizeof(t)); t.pfrb_type = PFRB_TRANS; - if (pfctl_add_trans(&t, PF_RULESET_ALTQ, "", "") || + if (pfctl_add_trans(&t, PF_RULESET_ALTQ, "") || pfctl_trans(dev, &t, DIOCXBEGIN, 0) || pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) err(1, "pfctl_clear_altq"); @@ -503,7 +477,7 @@ pfctl_kill_states(int dev, const char *iface, int opts) int pfctl_get_pool(int dev, struct pf_pool *pool, u_int32_t nr, - u_int32_t ticket, int r_action, char *anchorname, char *rulesetname) + u_int32_t ticket, int r_action, char *anchorname) { struct pfioc_pooladdr pp; struct pf_pooladdr *pa; @@ -511,7 +485,6 @@ pfctl_get_pool(int dev, struct pf_pool *pool, u_int32_t nr, memset(&pp, 0, sizeof(pp)); memcpy(pp.anchor, anchorname, sizeof(pp.anchor)); - memcpy(pp.ruleset, rulesetname, sizeof(pp.ruleset)); pp.r_action = r_action; pp.r_num = nr; pp.ticket = ticket; @@ -589,45 +562,14 @@ pfctl_print_title(char *title) } int -pfctl_show_rules(int dev, int opts, int format, char *anchorname, - char *rulesetname) +pfctl_show_rules(int dev, int opts, int format, char *anchorname) { struct pfioc_rule pr; u_int32_t nr, mnr, header = 0; int rule_numbers = opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG); - if (*anchorname && !*rulesetname) { - struct pfioc_ruleset pr; - int r; - - memset(&pr, 0, sizeof(pr)); - memcpy(pr.anchor, anchorname, sizeof(pr.anchor)); - if (ioctl(dev, DIOCGETRULESETS, &pr)) { - if (errno == EINVAL) - fprintf(stderr, "No rulesets in anchor '%s'.\n", - anchorname); - else - err(1, "DIOCGETRULESETS"); - return (-1); - } - if (opts & PF_OPT_SHOWALL && pr.nr) - pfctl_print_title("FILTER RULES:"); - mnr = pr.nr; - for (nr = 0; nr < mnr; ++nr) { - pr.nr = nr; - if (ioctl(dev, DIOCGETRULESET, &pr)) - err(1, "DIOCGETRULESET"); - r = pfctl_show_rules(dev, opts, format, anchorname, - pr.name); - if (r) - return (r); - } - return (0); - } - memset(&pr, 0, sizeof(pr)); memcpy(pr.anchor, anchorname, sizeof(pr.anchor)); - memcpy(pr.ruleset, rulesetname, sizeof(pr.ruleset)); if (opts & PF_OPT_SHOWALL) { pr.rule.action = PF_PASS; if (ioctl(dev, DIOCGETRULES, &pr)) { @@ -656,7 +598,7 @@ pfctl_show_rules(int dev, int opts, int format, char *anchorname, } if (pfctl_get_pool(dev, &pr.rule.rpool, - nr, pr.ticket, PF_SCRUB, anchorname, rulesetname) != 0) + nr, pr.ticket, PF_SCRUB, anchorname) != 0) return (-1); switch (format) { @@ -672,7 +614,7 @@ pfctl_show_rules(int dev, int opts, int format, char *anchorname, default: if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL)) labels = 1; - print_rule(&pr.rule, rule_numbers); + print_rule(&pr.rule, pr.anchor_call, rule_numbers); pfctl_print_rule_counters(&pr.rule, opts); } pfctl_clear_pool(&pr.rule.rpool); @@ -691,7 +633,7 @@ pfctl_show_rules(int dev, int opts, int format, char *anchorname, } if (pfctl_get_pool(dev, &pr.rule.rpool, - nr, pr.ticket, PF_PASS, anchorname, rulesetname) != 0) + nr, pr.ticket, PF_PASS, anchorname) != 0) return (-1); switch (format) { @@ -707,7 +649,7 @@ pfctl_show_rules(int dev, int opts, int format, char *anchorname, default: if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL)) labels = 1; - print_rule(&pr.rule, rule_numbers); + print_rule(&pr.rule, pr.anchor_call, rule_numbers); pfctl_print_rule_counters(&pr.rule, opts); } pfctl_clear_pool(&pr.rule.rpool); @@ -716,42 +658,15 @@ pfctl_show_rules(int dev, int opts, int format, char *anchorname, } int -pfctl_show_nat(int dev, int opts, char *anchorname, char *rulesetname) +pfctl_show_nat(int dev, int opts, char *anchorname) { struct pfioc_rule pr; u_int32_t mnr, nr; static int nattype[3] = { PF_NAT, PF_RDR, PF_BINAT }; int i, dotitle = opts & PF_OPT_SHOWALL; - if (*anchorname && !*rulesetname) { - struct pfioc_ruleset pr; - int r; - - memset(&pr, 0, sizeof(pr)); - memcpy(pr.anchor, anchorname, sizeof(pr.anchor)); - if (ioctl(dev, DIOCGETRULESETS, &pr)) { - if (errno == EINVAL) - fprintf(stderr, "No rulesets in anchor '%s'.\n", - anchorname); - else - err(1, "DIOCGETRULESETS"); - return (-1); - } - mnr = pr.nr; - for (nr = 0; nr < mnr; ++nr) { - pr.nr = nr; - if (ioctl(dev, DIOCGETRULESET, &pr)) - err(1, "DIOCGETRULESET"); - r = pfctl_show_nat(dev, opts, anchorname, pr.name); - if (r) - return (r); - } - return (0); - } - memset(&pr, 0, sizeof(pr)); memcpy(pr.anchor, anchorname, sizeof(pr.anchor)); - memcpy(pr.ruleset, rulesetname, sizeof(pr.ruleset)); for (i = 0; i < 3; i++) { pr.rule.action = nattype[i]; if (ioctl(dev, DIOCGETRULES, &pr)) { @@ -766,14 +681,14 @@ pfctl_show_nat(int dev, int opts, char *anchorname, char *rulesetname) return (-1); } if (pfctl_get_pool(dev, &pr.rule.rpool, nr, - pr.ticket, nattype[i], anchorname, - rulesetname) != 0) + pr.ticket, nattype[i], anchorname) != 0) return (-1); if (dotitle) { pfctl_print_title("TRANSLATION RULES:"); dotitle = 0; } - print_rule(&pr.rule, opts & PF_OPT_VERBOSE2); + print_rule(&pr.rule, pr.anchor_call, + opts & PF_OPT_VERBOSE2); pfctl_print_rule_counters(&pr.rule, opts); pfctl_clear_pool(&pr.rule.rpool); } @@ -897,7 +812,8 @@ pfctl_show_timeouts(int dev, int opts) if (ioctl(dev, DIOCGETTIMEOUT, &pt)) err(1, "DIOCGETTIMEOUT"); printf("%-20s %10d", pf_timeouts[i].name, pt.seconds); - if (i >= PFTM_ADAPTIVE_START && i <= PFTM_ADAPTIVE_END) + if (pf_timeouts[i].timeout >= PFTM_ADAPTIVE_START && + pf_timeouts[i].timeout <= PFTM_ADAPTIVE_END) printf(" states"); else printf("s"); @@ -952,13 +868,14 @@ pfctl_add_pool(struct pfctl *pf, struct pf_pool *p, sa_family_t af) } int -pfctl_add_rule(struct pfctl *pf, struct pf_rule *r) +pfctl_add_rule(struct pfctl *pf, struct pf_rule *r, const char *anchor_call) { u_int8_t rs_num; struct pfioc_rule pr; switch (r->action) { case PF_SCRUB: + case PF_NOSCRUB: if ((loadopt & PFCTL_FLAG_FILTER) == 0) return (0); rs_num = PF_RULESET_SCRUB; @@ -988,28 +905,59 @@ pfctl_add_rule(struct pfctl *pf, struct pf_rule *r) rs_num = PF_RULESET_BINAT; break; default: - errx(1, "Invalid rule type"); + errx(1, "Invalid rule type %d", r->action); break; } + + if ((pf->opts & PF_OPT_OPTIMIZE) && rs_num == PF_RULESET_FILTER) { + /* + * We'll do an optimization post-pass before finally adding the + * rules. Then we'll disable the optimization flag and feed + * the rules right back into this function. + */ + struct pf_opt_rule *pfr; + struct pf_pooladdr *pa; + + if ((pfr = calloc(1, sizeof(*pfr))) == NULL) + err(1, "calloc"); + memcpy(&pfr->por_rule, r, sizeof(*r)); + if (strlcpy(pfr->por_anchor, anchor_call, + sizeof(pfr->por_anchor)) >= sizeof(pfr->por_anchor)) + errx(1, "pfctl_add_rule: strlcpy"); + TAILQ_INSERT_TAIL(&pf->opt_queue, pfr, por_entry); + + if (TAILQ_FIRST(&r->rpool.list) != NULL) { + TAILQ_INIT(&pfr->por_rule.rpool.list); + while ((pa = TAILQ_FIRST(&r->rpool.list)) != NULL) { + TAILQ_REMOVE(&r->rpool.list, pa, entries); + TAILQ_INSERT_TAIL(&pfr->por_rule.rpool.list, pa, + entries); + } + } else { + memset(&pfr->por_rule.rpool, 0, + sizeof(pfr->por_rule.rpool)); + + } + return (0); + } + if ((pf->opts & PF_OPT_NOACTION) == 0) { bzero(&pr, sizeof(pr)); if (strlcpy(pr.anchor, pf->anchor, sizeof(pr.anchor)) >= - sizeof(pr.anchor) || - strlcpy(pr.ruleset, pf->ruleset, sizeof(pr.ruleset)) >= - sizeof(pr.ruleset)) + sizeof(pr.anchor)) errx(1, "pfctl_add_rule: strlcpy"); if (pfctl_add_pool(pf, &r->rpool, r->af)) return (1); - pr.ticket = pfctl_get_ticket(pf->trans, rs_num, pf->anchor, - pf->ruleset); + pr.ticket = pfctl_get_ticket(pf->trans, rs_num, pf->anchor); pr.pool_ticket = pf->paddr.ticket; memcpy(&pr.rule, r, sizeof(pr.rule)); + strlcpy(pr.anchor_call, anchor_call, sizeof(pr.anchor_call)); if (ioctl(pf->dev, DIOCADDRULE, &pr)) err(1, "DIOCADDRULE"); } if (pf->opts & PF_OPT_VERBOSE) - print_rule(r, pf->opts & PF_OPT_VERBOSE2); + print_rule(r, anchor_call, pf->opts & PF_OPT_VERBOSE2); pfctl_clear_pool(&r->rpool); return (0); } @@ -1038,7 +986,7 @@ pfctl_add_altq(struct pfctl *pf, struct pf_altq *a) int pfctl_rules(int dev, char *filename, int opts, char *anchorname, - char *rulesetname, struct pfr_buffer *trans) + struct pfr_buffer *trans) { #define ERR(x) do { warn(x); goto _error; } while(0) #define ERRX(x) do { warnx(x); goto _error; } while(0) @@ -1064,15 +1012,13 @@ pfctl_rules(int dev, char *filename, int opts, char *anchorname, memset(&pf, 0, sizeof(pf)); memset(&trs, 0, sizeof(trs)); if (strlcpy(trs.pfrt_anchor, anchorname, - sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor) || - strlcpy(trs.pfrt_ruleset, rulesetname, - sizeof(trs.pfrt_ruleset)) >= sizeof(trs.pfrt_ruleset)) + sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor)) ERRX("pfctl_rules: strlcpy"); if (strcmp(filename, "-") == 0) { fin = stdin; infile = "stdin"; } else { - if ((fin = fopen(filename, "r")) == NULL) { + if ((fin = pfctl_fopen(filename, "r")) == NULL) { warn("%s", filename); return (1); } @@ -1087,43 +1033,37 @@ pfctl_rules(int dev, char *filename, int opts, char *anchorname, pf.trans = t; pf.rule_nr = 0; pf.anchor = anchorname; - pf.ruleset = rulesetname; + TAILQ_INIT(&pf.opt_queue); + pfctl_init_options(&pf); if ((opts & PF_OPT_NOACTION) == 0) { if ((pf.loadopt & PFCTL_FLAG_NAT) != 0) { - if (pfctl_add_trans(t, PF_RULESET_NAT, anchorname, - rulesetname) || - pfctl_add_trans(t, PF_RULESET_BINAT, anchorname, - rulesetname) || - pfctl_add_trans(t, PF_RULESET_RDR, anchorname, - rulesetname)) + if (pfctl_add_trans(t, PF_RULESET_NAT, anchorname) || + pfctl_add_trans(t, PF_RULESET_BINAT, anchorname) || + pfctl_add_trans(t, PF_RULESET_RDR, anchorname)) ERR("pfctl_rules"); } if (((altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ) != 0))) { - if (pfctl_add_trans(t, PF_RULESET_ALTQ, anchorname, - rulesetname)) + if (pfctl_add_trans(t, PF_RULESET_ALTQ, anchorname)) ERR("pfctl_rules"); } if ((pf.loadopt & PFCTL_FLAG_FILTER) != 0) { - if (pfctl_add_trans(t, PF_RULESET_SCRUB, anchorname, - rulesetname) || - pfctl_add_trans(t, PF_RULESET_FILTER, anchorname, - rulesetname)) + if (pfctl_add_trans(t, PF_RULESET_SCRUB, anchorname) || + pfctl_add_trans(t, PF_RULESET_FILTER, anchorname)) ERR("pfctl_rules"); } if (pf.loadopt & PFCTL_FLAG_TABLE) { - if (pfctl_add_trans(t, PF_RULESET_TABLE, anchorname, - rulesetname)) + if (pfctl_add_trans(t, PF_RULESET_TABLE, anchorname)) ERR("pfctl_rules"); } if (pfctl_trans(dev, t, DIOCXBEGIN, osize)) ERR("DIOCXBEGIN"); if (altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ)) pa.ticket = pfctl_get_ticket(t, PF_RULESET_ALTQ, - anchorname, rulesetname); + anchorname); if (pf.loadopt & PFCTL_FLAG_TABLE) pf.tticket = pfctl_get_ticket(t, PF_RULESET_TABLE, - anchorname, rulesetname); + anchorname); } if (parse_rules(fin, &pf) < 0) { if ((opts & PF_OPT_NOACTION) == 0) @@ -1132,20 +1072,32 @@ pfctl_rules(int dev, char *filename, int opts, char *anchorname, else goto _error; } + if (pf.opts & PF_OPT_OPTIMIZE) { + if (pfctl_optimize_rules(&pf)) + ERRX("Failed to optimize ruleset: pf rules not loaded"); + } + if ((altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ) != 0)) if (check_commit_altq(dev, opts) != 0) ERRX("errors in altq config"); - if (fin != stdin) + + if (fin != stdin) { fclose(fin); + fin = NULL; + } /* process "load anchor" directives */ - if (!anchorname[0] && !rulesetname[0]) + if (!anchorname[0]) if (pfctl_load_anchors(dev, opts, t) == -1) ERRX("load anchors"); - if (trans == NULL && (opts & PF_OPT_NOACTION) == 0) + if (trans == NULL && (opts & PF_OPT_NOACTION) == 0) { + if (!anchorname[0]) + if (pfctl_load_options(&pf)) + goto _error; if (pfctl_trans(dev, t, DIOCXCOMMIT, 0)) ERR("DIOCXCOMMIT"); + } return (0); _error: @@ -1154,38 +1106,118 @@ _error: if (pfctl_trans(dev, t, DIOCXROLLBACK, 0)) err(1, "DIOCXROLLBACK"); exit(1); - } else /* sub ruleset */ + } else { /* sub ruleset */ + if (fin != NULL && fin != stdin) + fclose(fin); return (-1); + } #undef ERR #undef ERRX } +FILE * +pfctl_fopen(const char *name, const char *mode) +{ + struct stat st; + FILE *fp; + + fp = fopen(name, mode); + if (fp == NULL) + return (NULL); + if (fstat(fileno(fp), &st)) { + fclose(fp); + return (NULL); + } + if (S_ISDIR(st.st_mode)) { + fclose(fp); + errno = EISDIR; + return (NULL); + } + return (fp); +} + +void +pfctl_init_options(struct pfctl *pf) +{ + pf->timeout[PFTM_TCP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL; + pf->timeout[PFTM_TCP_OPENING] = PFTM_TCP_OPENING_VAL; + pf->timeout[PFTM_TCP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL; + pf->timeout[PFTM_TCP_CLOSING] = PFTM_TCP_CLOSING_VAL; + pf->timeout[PFTM_TCP_FIN_WAIT] = PFTM_TCP_FIN_WAIT_VAL; + pf->timeout[PFTM_TCP_CLOSED] = PFTM_TCP_CLOSED_VAL; + pf->timeout[PFTM_UDP_FIRST_PACKET] = PFTM_UDP_FIRST_PACKET_VAL; + pf->timeout[PFTM_UDP_SINGLE] = PFTM_UDP_SINGLE_VAL; + pf->timeout[PFTM_UDP_MULTIPLE] = PFTM_UDP_MULTIPLE_VAL; + pf->timeout[PFTM_ICMP_FIRST_PACKET] = PFTM_ICMP_FIRST_PACKET_VAL; + pf->timeout[PFTM_ICMP_ERROR_REPLY] = PFTM_ICMP_ERROR_REPLY_VAL; + pf->timeout[PFTM_OTHER_FIRST_PACKET] = PFTM_OTHER_FIRST_PACKET_VAL; + pf->timeout[PFTM_OTHER_SINGLE] = PFTM_OTHER_SINGLE_VAL; + pf->timeout[PFTM_OTHER_MULTIPLE] = PFTM_OTHER_MULTIPLE_VAL; + pf->timeout[PFTM_FRAG] = PFTM_FRAG_VAL; + pf->timeout[PFTM_INTERVAL] = PFTM_INTERVAL_VAL; + pf->timeout[PFTM_SRC_NODE] = PFTM_SRC_NODE_VAL; + pf->timeout[PFTM_TS_DIFF] = PFTM_TS_DIFF_VAL; + + pf->limit[PF_LIMIT_STATES] = PFSTATE_HIWAT; + pf->limit[PF_LIMIT_FRAGS] = PFFRAG_FRENT_HIWAT; + pf->limit[PF_LIMIT_SRC_NODES] = PFSNODE_HIWAT; + + pf->debug = PF_DEBUG_URGENT; +} + int -pfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit) +pfctl_load_options(struct pfctl *pf) { - struct pfioc_limit pl; - int i; + int i, error = 0; if ((loadopt & PFCTL_FLAG_OPTION) == 0) return (0); - memset(&pl, 0, sizeof(pl)); + /* load limits */ + for (i = 0; i < PF_LIMIT_MAX; i++) { + if ((pf->opts & PF_OPT_MERGE) && !pf->limit_set[i]) + continue; + if (pfctl_load_limit(pf, i, pf->limit[i])) + error = 1; + } + + /* load timeouts */ + for (i = 0; i < PFTM_MAX; i++) { + if ((pf->opts & PF_OPT_MERGE) && !pf->timeout_set[i]) + continue; + if (pfctl_load_timeout(pf, i, pf->timeout[i])) + error = 1; + } + + /* load debug */ + if (!(pf->opts & PF_OPT_MERGE) || pf->debug_set) + if (pfctl_load_debug(pf, pf->debug)) + error = 1; + + /* load logif */ + if (!(pf->opts & PF_OPT_MERGE) || pf->ifname_set) + if (pfctl_load_logif(pf, pf->ifname)) + error = 1; + + /* load hostid */ + if (!(pf->opts & PF_OPT_MERGE) || pf->hostid_set) + if (pfctl_load_hostid(pf, pf->hostid)) + error = 1; + + return (error); +} + +int +pfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit) +{ + int i; + + for (i = 0; pf_limits[i].name; i++) { if (strcasecmp(opt, pf_limits[i].name) == 0) { - pl.index = pf_limits[i].index; - pl.limit = limit; - if ((pf->opts & PF_OPT_NOACTION) == 0) { - if (ioctl(pf->dev, DIOCSETLIMIT, &pl)) { - if (errno == EBUSY) { - warnx("Current pool " - "size exceeds requested " - "hard limit"); - return (1); - } else - err(1, "DIOCSETLIMIT"); - } - } + pf->limit[pf_limits[i].index] = limit; + pf->limit_set[pf_limits[i].index] = 1; break; } } @@ -1201,18 +1233,35 @@ pfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit) } int +pfctl_load_limit(struct pfctl *pf, unsigned int index, unsigned int limit) +{ + struct pfioc_limit pl; + + memset(&pl, 0, sizeof(pl)); + pl.index = index; + pl.limit = limit; + if (ioctl(pf->dev, DIOCSETLIMIT, &pl)) { + if (errno == EBUSY) + warnx("Current pool size exceeds requested hard limit"); + else + warnx("DIOCSETLIMIT"); + return (1); + } + return (0); +} + +int pfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet) { - struct pfioc_tm pt; int i; if ((loadopt & PFCTL_FLAG_OPTION) == 0) return (0); - memset(&pt, 0, sizeof(pt)); for (i = 0; pf_timeouts[i].name; i++) { if (strcasecmp(opt, pf_timeouts[i].name) == 0) { - pt.timeout = pf_timeouts[i].timeout; + pf->timeout[pf_timeouts[i].timeout] = seconds; + pf->timeout_set[pf_timeouts[i].timeout] = 1; break; } } @@ -1222,11 +1271,6 @@ pfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet) return (1); } - pt.seconds = seconds; - if ((pf->opts & PF_OPT_NOACTION) == 0) { - if (ioctl(pf->dev, DIOCSETTIMEOUT, &pt)) - err(1, "DIOCSETTIMEOUT"); - } if (pf->opts & PF_OPT_VERBOSE && ! quiet) printf("set timeout %s %d\n", opt, seconds); @@ -1235,6 +1279,21 @@ pfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet) } int +pfctl_load_timeout(struct pfctl *pf, unsigned int timeout, unsigned int seconds) +{ + struct pfioc_tm pt; + + memset(&pt, 0, sizeof(pt)); + pt.timeout = timeout; + pt.seconds = seconds; + if (ioctl(pf->dev, DIOCSETTIMEOUT, &pt)) { + warnx("DIOCSETTIMEOUT"); + return (1); + } + return (0); +} + +int pfctl_set_optimization(struct pfctl *pf, const char *opt) { const struct pf_hint *hint; @@ -1267,23 +1326,19 @@ pfctl_set_optimization(struct pfctl *pf, const char *opt) int pfctl_set_logif(struct pfctl *pf, char *ifname) { - struct pfioc_if pi; if ((loadopt & PFCTL_FLAG_OPTION) == 0) return (0); - memset(&pi, 0, sizeof(pi)); - if ((pf->opts & PF_OPT_NOACTION) == 0) { - if (!strcmp(ifname, "none")) - bzero(pi.ifname, sizeof(pi.ifname)); - else { - if (strlcpy(pi.ifname, ifname, - sizeof(pi.ifname)) >= sizeof(pi.ifname)) - errx(1, "pfctl_set_logif: strlcpy"); - } - if (ioctl(pf->dev, DIOCSETSTATUSIF, &pi)) - err(1, "DIOCSETSTATUSIF"); + if (!strcmp(ifname, "none")) { + free(pf->ifname); + pf->ifname = NULL; + } else { + pf->ifname = strdup(ifname); + if (!pf->ifname) + errx(1, "pfctl_set_logif: strdup"); } + pf->ifname_set = 1; if (pf->opts & PF_OPT_VERBOSE) printf("set loginterface %s\n", ifname); @@ -1292,6 +1347,24 @@ pfctl_set_logif(struct pfctl *pf, char *ifname) } int +pfctl_load_logif(struct pfctl *pf, char *ifname) +{ + struct pfioc_if pi; + + memset(&pi, 0, sizeof(pi)); + if (ifname && strlcpy(pi.ifname, ifname, + sizeof(pi.ifname)) >= sizeof(pi.ifname)) { + warnx("pfctl_set_logif: strlcpy"); + return (1); + } + if (ioctl(pf->dev, DIOCSETSTATUSIF, &pi)) { + warnx("DIOCSETSTATUSIF"); + return (1); + } + return (0); +} + +int pfctl_set_hostid(struct pfctl *pf, u_int32_t hostid) { if ((loadopt & PFCTL_FLAG_OPTION) == 0) @@ -1299,9 +1372,8 @@ pfctl_set_hostid(struct pfctl *pf, u_int32_t hostid) HTONL(hostid); - if ((pf->opts & PF_OPT_NOACTION) == 0) - if (ioctl(dev, DIOCSETHOSTID, &hostid)) - err(1, "DIOCSETHOSTID"); + pf->hostid = hostid; + pf->hostid_set = 1; if (pf->opts & PF_OPT_VERBOSE) printf("set hostid 0x%08x\n", ntohl(hostid)); @@ -1310,6 +1382,16 @@ pfctl_set_hostid(struct pfctl *pf, u_int32_t hostid) } int +pfctl_load_hostid(struct pfctl *pf, u_int32_t hostid) +{ + if (ioctl(dev, DIOCSETHOSTID, &hostid)) { + warnx("DIOCSETHOSTID"); + return (1); + } + return (0); +} + +int pfctl_set_debug(struct pfctl *pf, char *d) { u_int32_t level; @@ -1318,18 +1400,20 @@ pfctl_set_debug(struct pfctl *pf, char *d) return (0); if (!strcmp(d, "none")) - level = PF_DEBUG_NONE; + pf->debug = PF_DEBUG_NONE; else if (!strcmp(d, "urgent")) - level = PF_DEBUG_URGENT; + pf->debug = PF_DEBUG_URGENT; else if (!strcmp(d, "misc")) - level = PF_DEBUG_MISC; + pf->debug = PF_DEBUG_MISC; else if (!strcmp(d, "loud")) - level = PF_DEBUG_NOISY; + pf->debug = PF_DEBUG_NOISY; else { warnx("unknown debug level \"%s\"", d); return (-1); } + pf->debug_set = 1; + if ((pf->opts & PF_OPT_NOACTION) == 0) if (ioctl(dev, DIOCSETDEBUG, &level)) err(1, "DIOCSETDEBUG"); @@ -1341,6 +1425,44 @@ pfctl_set_debug(struct pfctl *pf, char *d) } int +pfctl_load_debug(struct pfctl *pf, unsigned int level) +{ + if (ioctl(pf->dev, DIOCSETDEBUG, &level)) { + warnx("DIOCSETDEBUG"); + return (1); + } + return (0); +} + +int +pfctl_set_interface_flags(struct pfctl *pf, char *ifname, int flags, int how) +{ + struct pfioc_iface pi; + + if ((loadopt & PFCTL_FLAG_OPTION) == 0) + return (0); + + bzero(&pi, sizeof(pi)); + + pi.pfiio_flags = flags; + + if (strlcpy(pi.pfiio_name, ifname, sizeof(pi.pfiio_name)) >= + sizeof(pi.pfiio_name)) + errx(1, "pfctl_set_interface_flags: strlcpy"); + + if ((pf->opts & PF_OPT_NOACTION) == 0) { + if (how == 0) { + if (ioctl(pf->dev, DIOCCLRIFFLAG, &pi)) + err(1, "DIOCCLRIFFLAG"); + } else { + if (ioctl(pf->dev, DIOCSETIFFLAG, &pi)) + err(1, "DIOCSETIFFLAG"); + } + } + return (0); +} + +void pfctl_debug(int dev, u_int32_t level, int opts) { if (ioctl(dev, DIOCSETDEBUG, &level)) @@ -1366,7 +1488,6 @@ pfctl_debug(int dev, u_int32_t level, int opts) } fprintf(stderr, "'\n"); } - return (0); } int @@ -1403,48 +1524,37 @@ pfctl_test_altqsupport(int dev, int opts) int pfctl_show_anchors(int dev, int opts, char *anchorname) { - u_int32_t nr, mnr; + struct pfioc_ruleset pr; + u_int32_t mnr, nr; - if (!*anchorname) { - struct pfioc_anchor pa; + memset(&pr, 0, sizeof(pr)); + memcpy(pr.path, anchorname, sizeof(pr.path)); + if (ioctl(dev, DIOCGETRULESETS, &pr)) { + if (errno == EINVAL) + fprintf(stderr, "Anchor '%s' not found.\n", + anchorname); + else + err(1, "DIOCGETRULESETS"); + return (-1); + } + mnr = pr.nr; + for (nr = 0; nr < mnr; ++nr) { + char sub[MAXPATHLEN]; - memset(&pa, 0, sizeof(pa)); - if (ioctl(dev, DIOCGETANCHORS, &pa)) { - warn("DIOCGETANCHORS"); - return (-1); - } - mnr = pa.nr; - for (nr = 0; nr < mnr; ++nr) { - pa.nr = nr; - if (ioctl(dev, DIOCGETANCHOR, &pa)) { - warn("DIOCGETANCHOR"); - return (-1); - } - if (!(opts & PF_OPT_VERBOSE) && - !strcmp(pa.name, PF_RESERVED_ANCHOR)) - continue; - printf(" %s\n", pa.name); + pr.nr = nr; + if (ioctl(dev, DIOCGETRULESET, &pr)) + err(1, "DIOCGETRULESET"); + if (!strcmp(pr.name, PF_RESERVED_ANCHOR)) + continue; + sub[0] = 0; + if (pr.path[0]) { + strlcat(sub, pr.path, sizeof(sub)); + strlcat(sub, "/", sizeof(sub)); } - } else { - struct pfioc_ruleset pr; - - memset(&pr, 0, sizeof(pr)); - memcpy(pr.anchor, anchorname, sizeof(pr.anchor)); - if (ioctl(dev, DIOCGETRULESETS, &pr)) { - if (errno == EINVAL) - fprintf(stderr, "No rulesets in anchor '%s'.\n", - anchorname); - else - err(1, "DIOCGETRULESETS"); + strlcat(sub, pr.name, sizeof(sub)); + printf(" %s\n", sub); + if (opts & PF_OPT_VERBOSE && pfctl_show_anchors(dev, opts, sub)) return (-1); - } - mnr = pr.nr; - for (nr = 0; nr < mnr; ++nr) { - pr.nr = nr; - if (ioctl(dev, DIOCGETRULESET, &pr)) - err(1, "DIOCGETRULESET"); - printf(" %s:%s\n", pr.anchor, pr.name); - } } return (0); } @@ -1466,14 +1576,13 @@ main(int argc, char *argv[]) int ch; int mode = O_RDONLY; int opts = 0; - char anchorname[PF_ANCHOR_NAME_SIZE]; - char rulesetname[PF_RULESET_NAME_SIZE]; + char anchorname[MAXPATHLEN]; if (argc < 2) usage(); while ((ch = getopt(argc, argv, - "a:AdD:eqf:F:ghi:k:nNOp:rRs:t:T:vx:z")) != -1) { + "a:AdD:eqf:F:ghi:k:mnNOop:rRs:t:T:vx:z")) != -1) { switch (ch) { case 'a': anchoropt = optarg; @@ -1514,6 +1623,9 @@ main(int argc, char *argv[]) state_kill[state_killers++] = optarg; mode = O_RDWR; break; + case 'm': + opts |= PF_OPT_MERGE; + break; case 'n': opts |= PF_OPT_NOACTION; break; @@ -1536,6 +1648,12 @@ main(int argc, char *argv[]) case 'R': loadopt |= PFCTL_FLAG_FILTER; break; + case 'o': + if (opts & PF_OPT_OPTIMIZE) + opts |= PF_OPT_OPTIMIZE_PROFILE; + else + opts |= PF_OPT_OPTIMIZE; + break; case 'O': loadopt |= PFCTL_FLAG_OPTION; break; @@ -1602,31 +1720,11 @@ main(int argc, char *argv[]) loadopt = ~0; memset(anchorname, 0, sizeof(anchorname)); - memset(rulesetname, 0, sizeof(rulesetname)); if (anchoropt != NULL) { - char *t; - - if ((t = strchr(anchoropt, ':')) == NULL) { - if (strlcpy(anchorname, anchoropt, - sizeof(anchorname)) >= sizeof(anchorname)) - errx(1, "anchor name '%s' too long", - anchoropt); - } else { - char *p; - - if ((p = strdup(anchoropt)) == NULL) - err(1, "anchoropt: strdup"); - t = strsep(&p, ":"); - if (*t == '\0' || *p == '\0') - errx(1, "anchor '%s' invalid", anchoropt); - if (strlcpy(anchorname, t, sizeof(anchorname)) >= - sizeof(anchorname)) - errx(1, "anchor name '%s' too long", t); - if (strlcpy(rulesetname, p, sizeof(rulesetname)) >= - sizeof(rulesetname)) - errx(1, "ruleset name '%s' too long", p); - free(t); /* not p */ - } + if (strlcpy(anchorname, anchoropt, + sizeof(anchorname)) >= sizeof(anchorname)) + errx(1, "anchor name '%s' too long", + anchoropt); loadopt &= PFCTL_FLAG_FILTER|PFCTL_FLAG_NAT|PFCTL_FLAG_TABLE; } @@ -1660,17 +1758,15 @@ main(int argc, char *argv[]) break; case 'r': pfctl_load_fingerprints(dev, opts); - pfctl_show_rules(dev, opts, 0, anchorname, - rulesetname); + pfctl_show_rules(dev, opts, 0, anchorname); break; case 'l': pfctl_load_fingerprints(dev, opts); - pfctl_show_rules(dev, opts, 1, anchorname, - rulesetname); + pfctl_show_rules(dev, opts, 1, anchorname); break; case 'n': pfctl_load_fingerprints(dev, opts); - pfctl_show_nat(dev, opts, anchorname, rulesetname); + pfctl_show_nat(dev, opts, anchorname); break; case 'q': pfctl_show_altq(dev, ifaceopt, opts, @@ -1695,21 +1791,20 @@ main(int argc, char *argv[]) opts |= PF_OPT_SHOWALL; pfctl_load_fingerprints(dev, opts); - pfctl_show_nat(dev, opts, anchorname, rulesetname); - pfctl_show_rules(dev, opts, 0, anchorname, - rulesetname); + pfctl_show_nat(dev, opts, anchorname); + pfctl_show_rules(dev, opts, 0, anchorname); pfctl_show_altq(dev, ifaceopt, opts, 0); pfctl_show_states(dev, ifaceopt, opts); pfctl_show_src_nodes(dev, opts); pfctl_show_status(dev, opts); - pfctl_show_rules(dev, opts, 1, anchorname, rulesetname); + pfctl_show_rules(dev, opts, 1, anchorname); pfctl_show_timeouts(dev, opts); pfctl_show_limits(dev, opts); - pfctl_show_tables(anchorname, rulesetname, opts); + pfctl_show_tables(anchorname, opts); pfctl_show_fingerprints(opts); break; case 'T': - pfctl_show_tables(anchorname, rulesetname, opts); + pfctl_show_tables(anchorname, opts); break; case 'o': pfctl_load_fingerprints(dev, opts); @@ -1724,10 +1819,10 @@ main(int argc, char *argv[]) if (clearopt != NULL) { switch (*clearopt) { case 'r': - pfctl_clear_rules(dev, opts, anchorname, rulesetname); + pfctl_clear_rules(dev, opts, anchorname); break; case 'n': - pfctl_clear_nat(dev, opts, anchorname, rulesetname); + pfctl_clear_nat(dev, opts, anchorname); break; case 'q': pfctl_clear_altq(dev, opts); @@ -1742,22 +1837,23 @@ main(int argc, char *argv[]) pfctl_clear_stats(dev, opts); break; case 'a': - pfctl_clear_rules(dev, opts, anchorname, rulesetname); - pfctl_clear_nat(dev, opts, anchorname, rulesetname); - pfctl_clear_tables(anchorname, rulesetname, opts); - if (!*anchorname && !*rulesetname) { + pfctl_clear_rules(dev, opts, anchorname); + pfctl_clear_nat(dev, opts, anchorname); + pfctl_clear_tables(anchorname, opts); + if (!*anchorname) { pfctl_clear_altq(dev, opts); pfctl_clear_states(dev, ifaceopt, opts); pfctl_clear_src_nodes(dev, opts); pfctl_clear_stats(dev, opts); pfctl_clear_fingerprints(dev, opts); + pfctl_clear_interface_flags(dev, opts); } break; case 'o': pfctl_clear_fingerprints(dev, opts); break; case 'T': - pfctl_clear_tables(anchorname, rulesetname, opts); + pfctl_clear_tables(anchorname, opts); break; } } @@ -1766,17 +1862,21 @@ main(int argc, char *argv[]) if (tblcmdopt != NULL) { error = pfctl_command_tables(argc, argv, tableopt, - tblcmdopt, rulesopt, anchorname, rulesetname, opts); + tblcmdopt, rulesopt, anchorname, opts); rulesopt = NULL; } - if (rulesopt != NULL) + if ((rulesopt != NULL) && (!*anchorname)) + if (pfctl_clear_interface_flags(dev, opts | PF_OPT_QUIET)) + error = 1; + + if (rulesopt != NULL && !(opts & (PF_OPT_MERGE|PF_OPT_NOACTION)) && + !anchorname[0] && (loadopt & PFCTL_FLAG_OPTION)) if (pfctl_file_fingerprints(dev, opts, PF_OSFP_FILE)) error = 1; if (rulesopt != NULL) { - if (pfctl_rules(dev, rulesopt, opts, anchorname, rulesetname, - NULL)) + if (pfctl_rules(dev, rulesopt, opts, anchorname, NULL)) error = 1; else if (!(opts & PF_OPT_NOACTION) && (loadopt & PFCTL_FLAG_TABLE)) diff --git a/contrib/pf/pfctl/pfctl.h b/contrib/pf/pfctl/pfctl.h index 2776f5e..94c6fc8 100644 --- a/contrib/pf/pfctl/pfctl.h +++ b/contrib/pf/pfctl/pfctl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl.h,v 1.33 2004/02/19 21:37:01 cedric Exp $ */ +/* $OpenBSD: pfctl.h,v 1.37 2005/01/05 18:23:10 mcbride Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -65,8 +65,6 @@ int pfr_get_astats(struct pfr_table *, struct pfr_astats *, int *, int); int pfr_clr_astats(struct pfr_table *, struct pfr_addr *, int, int *, int); int pfr_tst_addrs(struct pfr_table *, struct pfr_addr *, int, int *, int); int pfr_set_tflags(struct pfr_table *, int, int, int, int *, int *, int); -int pfr_ina_begin(struct pfr_table *, int *, int *, int); -int pfr_ina_commit(struct pfr_table *, int, int *, int *, int); int pfr_ina_define(struct pfr_table *, struct pfr_addr *, int, int *, int *, int, int); void pfr_buf_clear(struct pfr_buffer *); @@ -80,13 +78,14 @@ int pfi_get_ifaces(const char *, struct pfi_if *, int *, int); int pfi_clr_istats(const char *, int *, int); void pfctl_print_title(char *); -int pfctl_clear_tables(const char *, const char *, int); -int pfctl_show_tables(const char *, const char *, int); +int pfctl_clear_tables(const char *, int); +int pfctl_show_tables(const char *, int); int pfctl_command_tables(int, char *[], char *, const char *, char *, - const char *, const char *, int); + const char *, int); int pfctl_show_altq(int, const char *, int, int); void warn_namespace_collision(const char *); int pfctl_show_ifaces(const char *, int); +FILE *pfctl_fopen(const char *, const char *); #ifdef __FreeBSD__ extern int altqsupport; @@ -108,6 +107,8 @@ struct segment { double x, y, d, m; }; +extern int loadopt; + int check_commit_altq(int, int); void pfaltq_store(struct pf_altq *); void pfaltq_free(struct pf_altq *); @@ -121,9 +122,9 @@ void print_state(struct pf_state *, int); int unmask(struct pf_addr *, sa_family_t); int pfctl_cmdline_symset(char *); -int pfctl_add_trans(struct pfr_buffer *, int, const char *, const char *); +int pfctl_add_trans(struct pfr_buffer *, int, const char *); u_int32_t - pfctl_get_ticket(struct pfr_buffer *, int, const char *, const char *); + pfctl_get_ticket(struct pfr_buffer *, int, const char *); int pfctl_trans(int, struct pfr_buffer *, u_long, int); #endif /* _PFCTL_H_ */ diff --git a/contrib/pf/pfctl/pfctl_altq.c b/contrib/pf/pfctl/pfctl_altq.c index eeed648..384d1a2 100644 --- a/contrib/pf/pfctl/pfctl_altq.c +++ b/contrib/pf/pfctl/pfctl_altq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_altq.c,v 1.83 2004/03/14 21:51:44 dhartmei Exp $ */ +/* $OpenBSD: pfctl_altq.c,v 1.86 2005/02/28 14:04:51 henning Exp $ */ /* * Copyright (c) 2002 @@ -315,7 +315,8 @@ eval_pfqueue(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw, struct node_queue_opt *opts) { /* should be merged with expand_queue */ - struct pf_altq *if_pa, *parent; + struct pf_altq *if_pa, *parent, *altq; + u_int32_t bwsum; int error = 0; /* find the corresponding interface and copy fields used by queues */ @@ -347,22 +348,35 @@ eval_pfqueue(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw, pa->qlimit = DEFAULT_QLIMIT; if (pa->scheduler == ALTQT_CBQ || pa->scheduler == ALTQT_HFSC) { - if ((pa->bandwidth = eval_bwspec(bw, - parent == NULL ? 0 : parent->bandwidth)) == 0) { - fprintf(stderr, "bandwidth for %s invalid (%d / %d)\n", - pa->qname, bw->bw_absolute, bw->bw_percent); - return (1); - } + pa->bandwidth = eval_bwspec(bw, + parent == NULL ? 0 : parent->bandwidth); if (pa->bandwidth > pa->ifbandwidth) { fprintf(stderr, "bandwidth for %s higher than " "interface\n", pa->qname); return (1); } - if (parent != NULL && pa->bandwidth > parent->bandwidth) { - fprintf(stderr, "bandwidth for %s higher than parent\n", - pa->qname); - return (1); + /* check the sum of the child bandwidth is under parent's */ + if (parent != NULL) { + if (pa->bandwidth > parent->bandwidth) { + warnx("bandwidth for %s higher than parent", + pa->qname); + return (1); + } + bwsum = 0; + TAILQ_FOREACH(altq, &altqs, entries) { + if (strncmp(altq->ifname, pa->ifname, + IFNAMSIZ) == 0 && + altq->qname[0] != 0 && + strncmp(altq->parent, pa->parent, + PF_QNAME_SIZE) == 0) + bwsum += altq->bandwidth; + } + bwsum += pa->bandwidth; + if (bwsum > parent->bandwidth) { + warnx("the sum of the child bandwidth higher" + " than parent \"%s\"", parent->qname); + } } } @@ -706,7 +720,7 @@ eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa) * for the real-time service curve, the sum of the service curves * should not exceed 80% of the interface bandwidth. 20% is reserved * not to over-commit the actual interface bandwidth. - * for the link-sharing service curve, the sum of the child service + * for the linkshare service curve, the sum of the child service * curve should not exceed the parent service curve. * for the upper-limit service curve, the assigned bandwidth should * be smaller than the interface bandwidth, and the upper-limit should @@ -733,7 +747,7 @@ eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa) if (strncmp(altq->parent, pa->parent, PF_QNAME_SIZE) != 0) continue; - /* if the class has a link-sharing service curve, add it. */ + /* if the class has a linkshare service curve, add it. */ if (opts->lssc_m2 != 0 && altq->pq_u.hfsc_opts.lssc_m2 != 0) { sc.m1 = altq->pq_u.hfsc_opts.lssc_m1; sc.d = altq->pq_u.hfsc_opts.lssc_d; @@ -744,22 +758,35 @@ eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa) /* check the real-time service curve. reserve 20% of interface bw */ if (opts->rtsc_m2 != 0) { + /* add this queue to the sum */ + sc.m1 = opts->rtsc_m1; + sc.d = opts->rtsc_d; + sc.m2 = opts->rtsc_m2; + gsc_add_sc(&rtsc, &sc); + /* compare the sum with 80% of the interface */ sc.m1 = 0; sc.d = 0; sc.m2 = pa->ifbandwidth / 100 * 80; if (!is_gsc_under_sc(&rtsc, &sc)) { - warnx("real-time sc exceeds the interface bandwidth"); + warnx("real-time sc exceeds 80%% of the interface " + "bandwidth (%s)", rate2str((double)sc.m2)); goto err_ret; } } - /* check the link-sharing service curve. */ + /* check the linkshare service curve. */ if (opts->lssc_m2 != 0) { + /* add this queue to the child sum */ + sc.m1 = opts->lssc_m1; + sc.d = opts->lssc_d; + sc.m2 = opts->lssc_m2; + gsc_add_sc(&lssc, &sc); + /* compare the sum of the children with parent's sc */ sc.m1 = parent->pq_u.hfsc_opts.lssc_m1; sc.d = parent->pq_u.hfsc_opts.lssc_d; sc.m2 = parent->pq_u.hfsc_opts.lssc_m2; if (!is_gsc_under_sc(&lssc, &sc)) { - warnx("link-sharing sc exceeds parent's sc"); + warnx("linkshare sc exceeds parent's sc"); goto err_ret; } } @@ -1108,6 +1135,7 @@ getifspeed(char *ifname) if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) err(1, "socket"); + bzero(&ifr, sizeof(ifr)); if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >= sizeof(ifr.ifr_name)) errx(1, "getifspeed: strlcpy"); @@ -1130,6 +1158,7 @@ getifmtu(char *ifname) if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) err(1, "socket"); + bzero(&ifr, sizeof(ifr)); if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >= sizeof(ifr.ifr_name)) errx(1, "getifmtu: strlcpy"); diff --git a/contrib/pf/pfctl/pfctl_optimize.c b/contrib/pf/pfctl/pfctl_optimize.c index 6c6803e..111dc32 100644 --- a/contrib/pf/pfctl/pfctl_optimize.c +++ b/contrib/pf/pfctl/pfctl_optimize.c @@ -16,6 +16,9 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + #include <sys/types.h> #include <sys/ioctl.h> #include <sys/socket.h> @@ -815,7 +818,11 @@ block_feedback(struct pfctl *pf, struct superblock *block) break; } } +#ifdef __FreeBSD__ + if (por2 == NULL) +#else if (por2 == TAILQ_END(&block->sb_rules)) +#endif TAILQ_INSERT_TAIL(&block->sb_rules, por1, por_entry); } diff --git a/contrib/pf/pfctl/pfctl_parser.c b/contrib/pf/pfctl/pfctl_parser.c index c02f7da..2cf82b4 100644 --- a/contrib/pf/pfctl/pfctl_parser.c +++ b/contrib/pf/pfctl/pfctl_parser.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_parser.c,v 1.194 2004/03/15 15:25:44 dhartmei Exp $ */ +/* $OpenBSD: pfctl_parser.c,v 1.211 2004/12/07 10:33:41 dhartmei Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -37,6 +37,8 @@ __FBSDID("$FreeBSD$"); #include <sys/types.h> #include <sys/ioctl.h> #include <sys/socket.h> +#include <sys/param.h> +#include <sys/proc.h> #include <net/if.h> #include <netinet/in.h> #include <netinet/in_systm.h> @@ -66,6 +68,7 @@ void print_ugid (u_int8_t, unsigned, unsigned, const char *, unsigned); void print_flags (u_int8_t); void print_fromto(struct pf_rule_addr *, pf_osfp_t, struct pf_rule_addr *, u_int8_t, u_int8_t, int); +int ifa_skip_if(const char *filter, struct node_host *p); struct node_host *host_if(const char *, int); struct node_host *host_v4(const char *, int); @@ -186,6 +189,7 @@ const struct pf_timeout pf_timeouts[] = { { "tcp.closing", PFTM_TCP_CLOSING }, { "tcp.finwait", PFTM_TCP_FIN_WAIT }, { "tcp.closed", PFTM_TCP_CLOSED }, + { "tcp.tsdiff", PFTM_TS_DIFF }, { "udp.first", PFTM_UDP_FIRST_PACKET }, { "udp.single", PFTM_UDP_SINGLE }, { "udp.multiple", PFTM_UDP_MULTIPLE }, @@ -366,13 +370,13 @@ print_fromto(struct pf_rule_addr *src, pf_osfp_t osfp, struct pf_rule_addr *dst, PF_AZERO(&src->addr.v.a.mask, AF_INET6) && PF_AZERO(&dst->addr.v.a.addr, AF_INET6) && PF_AZERO(&dst->addr.v.a.mask, AF_INET6) && - !src->not && !dst->not && + !src->neg && !dst->neg && !src->port_op && !dst->port_op && osfp == PF_OSFP_ANY) printf(" all"); else { printf(" from "); - if (src->not) + if (src->neg) printf("! "); print_addr(&src->addr, af, verbose); if (src->port_op) @@ -384,7 +388,7 @@ print_fromto(struct pf_rule_addr *src, pf_osfp_t osfp, struct pf_rule_addr *dst, sizeof(buf))); printf(" to "); - if (dst->not) + if (dst->neg) printf("! "); print_addr(&dst->addr, af, verbose); if (dst->port_op) @@ -472,6 +476,7 @@ print_pool(struct pf_pool *pool, u_int16_t p1, u_int16_t p2, } const char *pf_reasons[PFRES_MAX+1] = PFRES_NAMES; +const char *pf_lcounters[LCNT_MAX+1] = LCNT_NAMES; const char *pf_fcounters[FCNT_MAX+1] = FCNT_NAMES; const char *pf_scounters[FCNT_MAX+1] = FCNT_NAMES; @@ -574,6 +579,22 @@ print_status(struct pf_status *s, int opts) else printf("%14s\n", ""); } + if (opts & PF_OPT_VERBOSE) { + printf("Limit Counters\n"); + for (i = 0; i < LCNT_MAX; i++) { + printf(" %-25s %14lld ", pf_lcounters[i], +#ifdef __FreeBSD__ + (unsigned long long)s->lcounters[i]); +#else + s->lcounters[i]); +#endif + if (runtime > 0) + printf("%14.1f/s\n", + (double)s->lcounters[i] / (double)runtime); + else + printf("%14s\n", ""); + } + } } void @@ -593,7 +614,9 @@ print_src_node(struct pf_src_node *sn, int opts) printf(" -> "); aw.v.a.addr = sn->raddr; print_addr(&aw, sn->af, opts & PF_OPT_VERBOSE2); - printf(" (%d states)\n", sn->states); + printf(" ( states %u, connections %u, rate %u.%u/%us )\n", sn->states, + sn->conn, sn->conn_rate.count / 1000, + (sn->conn_rate.count % 1000) / 100, sn->conn_rate.seconds); if (opts & PF_OPT_VERBOSE) { sec = sn->creation % 60; sn->creation /= 60; @@ -628,21 +651,22 @@ print_src_node(struct pf_src_node *sn, int opts) } void -print_rule(struct pf_rule *r, int verbose) +print_rule(struct pf_rule *r, const char *anchor_call, int verbose) { - static const char *actiontypes[] = { "pass", "block", "scrub", "nat", - "no nat", "binat", "no binat", "rdr", "no rdr" }; + static const char *actiontypes[] = { "pass", "block", "scrub", + "no scrub", "nat", "no nat", "binat", "no binat", "rdr", "no rdr" }; static const char *anchortypes[] = { "anchor", "anchor", "anchor", - "nat-anchor", "nat-anchor", "binat-anchor", "binat-anchor", - "rdr-anchor", "rdr-anchor" }; + "anchor", "nat-anchor", "nat-anchor", "binat-anchor", + "binat-anchor", "rdr-anchor", "rdr-anchor" }; int i, opts; if (verbose) printf("@%d ", r->nr); if (r->action > PF_NORDR) printf("action(%d)", r->action); - else if (r->anchorname[0]) - printf("%s %s", anchortypes[r->action], r->anchorname); + else if (anchor_call[0]) + printf("%s \"%s\"", anchortypes[r->action], + anchor_call); else { printf("%s", actiontypes[r->action]); if (r->natpass) @@ -782,6 +806,21 @@ print_rule(struct pf_rule *r, int verbose) printf(" modulate state"); else if (r->keep_state == PF_STATE_SYNPROXY) printf(" synproxy state"); + if (r->prob) { + char buf[20]; + + snprintf(buf, sizeof(buf), "%f", r->prob*100.0/(UINT_MAX+1.0)); + for (i = strlen(buf)-1; i > 0; i--) { + if (buf[i] == '0') + buf[i] = '\0'; + else { + if (buf[i] == '.') + buf[i] = '\0'; + break; + } + } + printf(" probability %s%%", buf); + } opts = 0; if (r->max_states || r->max_src_nodes || r->max_src_states) opts = 1; @@ -822,12 +861,35 @@ print_rule(struct pf_rule *r, int verbose) printf("max-src-states %u", r->max_src_states); opts = 0; } + if (r->max_src_conn) { + if (!opts) + printf(", "); + printf("max-src-conn %u", r->max_src_conn); + opts = 0; + } + if (r->max_src_conn_rate.limit) { + if (!opts) + printf(", "); + printf("max-src-conn-rate %u/%u", + r->max_src_conn_rate.limit, + r->max_src_conn_rate.seconds); + opts = 0; + } if (r->max_src_nodes) { if (!opts) printf(", "); printf("max-src-nodes %u", r->max_src_nodes); opts = 0; } + if (r->overload_tblname[0]) { + if (!opts) + printf(", "); + printf("overload <%s>", r->overload_tblname); + if (r->flush) + printf(" flush"); + if (r->flush & PF_FLUSH_GLOBAL) + printf(" global"); + } if (r->rule_flag & PFRULE_IFBOUND) { if (!opts) printf(", "); @@ -842,11 +904,17 @@ print_rule(struct pf_rule *r, int verbose) } for (i = 0; i < PFTM_MAX; ++i) if (r->timeout[i]) { + int j; + if (!opts) printf(", "); opts = 0; - printf("%s %u", pf_timeouts[i].name, - r->timeout[i]); + for (j = 0; j < sizeof(pf_timeouts) / + sizeof(pf_timeouts[0]); ++j) + if (pf_timeouts[j].timeout == i) + break; + printf("%s %u", j == PFTM_MAX ? "inv.timeout" : + pf_timeouts[j].name, r->timeout[i]); } printf(")"); } @@ -886,7 +954,7 @@ print_rule(struct pf_rule *r, int verbose) printf(" !"); printf(" tagged %s", r->match_tagname); } - if (!r->anchorname[0] && (r->action == PF_NAT || + if (!anchor_call[0] && (r->action == PF_NAT || r->action == PF_BINAT || r->action == PF_RDR)) { printf(" -> "); print_pool(&r->rpool, r->rpool.proxy_port[0], @@ -953,9 +1021,7 @@ set_ipmask(struct node_host *h, u_int8_t b) int i, j = 0; m = &h->addr.v.a.mask; - - for (i = 0; i < 4; i++) - m->addr32[i] = 0; + memset(m, 0, sizeof(*m)); while (b >= 32) { m->addr32[j++] = 0xffffffff; @@ -1007,8 +1073,6 @@ ifa_load(void) { struct ifaddrs *ifap, *ifa; struct node_host *n = NULL, *h = NULL; - struct pfr_buffer b; - struct pfi_if *p; if (getifaddrs(&ifap) < 0) err(1, "getifaddrs"); @@ -1084,43 +1148,6 @@ ifa_load(void) } } - /* add interface groups, including clonable and dynamic stuff */ - bzero(&b, sizeof(b)); - b.pfrb_type = PFRB_IFACES; - for (;;) { - if (pfr_buf_grow(&b, b.pfrb_size)) - err(1, "ifa_load: pfr_buf_grow"); - b.pfrb_size = b.pfrb_msize; - if (pfi_get_ifaces(NULL, b.pfrb_caddr, &b.pfrb_size, - PFI_FLAG_GROUP)) - err(1, "ifa_load: pfi_get_ifaces"); - if (b.pfrb_size <= b.pfrb_msize) - break; - } - PFRB_FOREACH(p, &b) { - n = calloc(1, sizeof(struct node_host)); - if (n == NULL) - err(1, "address: calloc"); - n->af = AF_LINK; - n->ifa_flags = PF_IFA_FLAG_GROUP; - if (p->pfif_flags & PFI_IFLAG_DYNAMIC) - n->ifa_flags |= PF_IFA_FLAG_DYNAMIC; - if (p->pfif_flags & PFI_IFLAG_CLONABLE) - n->ifa_flags |= PF_IFA_FLAG_CLONABLE; - if (!strcmp(p->pfif_name, "lo")) - n->ifa_flags |= IFF_LOOPBACK; - if ((n->ifname = strdup(p->pfif_name)) == NULL) - err(1, "ifa_load: strdup"); - n->next = NULL; - n->tail = n; - if (h == NULL) - h = n; - else { - h->tail->next = n; - h->tail = n; - } - } - iftab = h; freeifaddrs(ifap); } @@ -1129,12 +1156,7 @@ struct node_host * ifa_exists(const char *ifa_name, int group_ok) { struct node_host *n; - char *p, buf[IFNAMSIZ]; - int group; - group = !isdigit(ifa_name[strlen(ifa_name) - 1]); - if (group && !group_ok) - return (NULL); if (iftab == NULL) ifa_load(); @@ -1142,19 +1164,7 @@ ifa_exists(const char *ifa_name, int group_ok) if (n->af == AF_LINK && !strncmp(n->ifname, ifa_name, IFNAMSIZ)) return (n); } - if (!group) { - /* look for clonable and/or dynamic interface */ - strlcpy(buf, ifa_name, sizeof(buf)); - for (p = buf + strlen(buf) - 1; p > buf && isdigit(*p); p--) - *p = '\0'; - for (n = iftab; n != NULL; n = n->next) - if (n->af == AF_LINK && - !strncmp(n->ifname, buf, IFNAMSIZ)) - break; - if (n != NULL && n->ifa_flags & - (PF_IFA_FLAG_DYNAMIC | PF_IFA_FLAG_CLONABLE)) - return (n); /* XXX */ - } + return (NULL); } @@ -1162,19 +1172,17 @@ struct node_host * ifa_lookup(const char *ifa_name, int flags) { struct node_host *p = NULL, *h = NULL, *n = NULL; - int return_all = 0, got4 = 0, got6 = 0; + int got4 = 0, got6 = 0; const char *last_if = NULL; if (!strncmp(ifa_name, "self", IFNAMSIZ)) - return_all = 1; + ifa_name = NULL; if (iftab == NULL) ifa_load(); for (p = iftab; p; p = p->next) { - if (!((p->af == AF_INET || p->af == AF_INET6) && - (!strncmp(p->ifname, ifa_name, strlen(ifa_name)) || - return_all))) + if (ifa_skip_if(ifa_name, p)) continue; if ((flags & PFI_AFLAG_BROADCAST) && p->af != AF_INET) continue; @@ -1238,6 +1246,28 @@ ifa_lookup(const char *ifa_name, int flags) return (h); } +int +ifa_skip_if(const char *filter, struct node_host *p) +{ + int n; + + if (p->af != AF_INET && p->af != AF_INET6) + return (1); + if (filter == NULL || !*filter) + return (0); + if (!strcmp(p->ifname, filter)) + return (0); /* exact match */ + n = strlen(filter); + if (n < 1 || n >= IFNAMSIZ) + return (1); /* sanity check */ + if (filter[n-1] >= '0' && filter[n-1] <= '9') + return (1); /* only do exact match in that case */ + if (strncmp(p->ifname, filter, n)) + return (1); /* prefix doesn't match */ + return (p->ifname[n] < '0' || p->ifname[n] > '9'); +} + + struct node_host * host(const char *s) { @@ -1248,7 +1278,7 @@ host(const char *s) if ((p = strrchr(s, '/')) != NULL) { mask = strtol(p+1, &q, 0); if (!q || *q || mask > 128 || q == (p+1)) { - fprintf(stderr, "invalid netmask\n"); + fprintf(stderr, "invalid netmask '%s'\n", p); return (NULL); } if ((ps = malloc(strlen(s) - strlen(p) + 1)) == NULL) @@ -1402,7 +1432,7 @@ host_dns(const char *s, int v4mask, int v6mask) char *p, *ps; if ((ps = strdup(s)) == NULL) - err(1, "host_if: strdup"); + err(1, "host_dns: strdup"); if ((p = strrchr(ps, ':')) != NULL && !strcmp(p, ":0")) { noalias = 1; *p = '\0'; @@ -1411,8 +1441,10 @@ host_dns(const char *s, int v4mask, int v6mask) hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; /* DUMMY */ error = getaddrinfo(ps, NULL, &hints, &res0); - if (error) + if (error) { + free(ps); return (h); + } for (res = res0; res; res = res->ai_next) { if (res->ai_family != AF_INET && @@ -1536,33 +1568,28 @@ append_addr_host(struct pfr_buffer *b, struct node_host *n, int test, int not) } int -pfctl_add_trans(struct pfr_buffer *buf, int rs_num, const char *anchor, - const char *ruleset) +pfctl_add_trans(struct pfr_buffer *buf, int rs_num, const char *anchor) { struct pfioc_trans_e trans; bzero(&trans, sizeof(trans)); trans.rs_num = rs_num; if (strlcpy(trans.anchor, anchor, - sizeof(trans.anchor)) >= sizeof(trans.anchor) || - strlcpy(trans.ruleset, ruleset, - sizeof(trans.ruleset)) >= sizeof(trans.ruleset)) + sizeof(trans.anchor)) >= sizeof(trans.anchor)) errx(1, "pfctl_add_trans: strlcpy"); return pfr_buf_add(buf, &trans); } u_int32_t -pfctl_get_ticket(struct pfr_buffer *buf, int rs_num, const char *anchor, - const char *ruleset) +pfctl_get_ticket(struct pfr_buffer *buf, int rs_num, const char *anchor) { struct pfioc_trans_e *p; PFRB_FOREACH(p, buf) - if (rs_num == p->rs_num && !strcmp(anchor, p->anchor) && - !strcmp(ruleset, p->ruleset)) + if (rs_num == p->rs_num && !strcmp(anchor, p->anchor)) return (p->ticket); - errx(1, "pfr_get_ticket: assertion failed"); + errx(1, "pfctl_get_ticket: assertion failed"); } int diff --git a/contrib/pf/pfctl/pfctl_parser.h b/contrib/pf/pfctl/pfctl_parser.h index 0756cc8..1c075ef 100644 --- a/contrib/pf/pfctl/pfctl_parser.h +++ b/contrib/pf/pfctl/pfctl_parser.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_parser.h,v 1.74 2004/02/10 22:26:56 dhartmei Exp $ */ +/* $OpenBSD: pfctl_parser.h,v 1.80 2005/02/07 18:18:14 david Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -47,6 +47,9 @@ #define PF_OPT_DUMMYACTION 0x0100 #define PF_OPT_DEBUG 0x0200 #define PF_OPT_SHOWALL 0x0400 +#define PF_OPT_OPTIMIZE 0x0800 +#define PF_OPT_OPTIMIZE_PROFILE 0x1000 +#define PF_OPT_MERGE 0x2000 #define PF_TH_ALL 0xFF @@ -60,6 +63,11 @@ NULL \ } +struct pfr_buffer; /* forward definition */ +struct pf_opt_rule; +TAILQ_HEAD(pf_opt_queue, pf_opt_rule); + + struct pfctl { int dev; int opts; @@ -73,11 +81,26 @@ struct pfctl { struct pfr_buffer *trans; const char *anchor; const char *ruleset; + struct pf_opt_queue opt_queue; + + /* 'set foo' options */ + u_int32_t timeout[PFTM_MAX]; + u_int32_t limit[PF_LIMIT_MAX]; + u_int32_t debug; + u_int32_t hostid; + char *ifname; + + u_int8_t timeout_set[PFTM_MAX]; + u_int8_t limit_set[PF_LIMIT_MAX]; + u_int8_t debug_set; + u_int8_t hostid_set; + u_int8_t ifname_set; }; struct node_if { char ifname[IFNAMSIZ]; u_int8_t not; + u_int8_t dynamic; /* antispoof */ u_int ifa_flags; struct node_if *next; struct node_if *tail; @@ -166,11 +189,33 @@ struct node_tinit { /* table initializer */ char *file; }; -struct pfr_buffer; /* forward definition */ -int pfctl_rules(int, char *, int, char *, char *, struct pfr_buffer *); +/* optimizer created tables */ +struct pf_opt_tbl { + char pt_name[PF_TABLE_NAME_SIZE]; + int pt_rulecount; + int pt_generated; + struct node_tinithead pt_nodes; + struct pfr_buffer *pt_buf; +}; +#define PF_OPT_TABLE_PREFIX "__automatic_" + +/* optimizer pf_rule container */ +struct pf_opt_rule { + struct pf_rule por_rule; + struct pf_opt_tbl *por_src_tbl; + struct pf_opt_tbl *por_dst_tbl; + char por_anchor[MAXPATHLEN]; + u_int64_t por_profile_count; + TAILQ_ENTRY(pf_opt_rule) por_entry; + TAILQ_ENTRY(pf_opt_rule) por_skip_entry[PF_SKIP_COUNT]; +}; + + +int pfctl_rules(int, char *, int, char *, struct pfr_buffer *); +int pfctl_optimize_rules(struct pfctl *); -int pfctl_add_rule(struct pfctl *, struct pf_rule *); +int pfctl_add_rule(struct pfctl *, struct pf_rule *, const char *); int pfctl_add_altq(struct pfctl *, struct pf_altq *); int pfctl_add_pool(struct pfctl *, struct pf_pool *, sa_family_t); void pfctl_clear_pool(struct pf_pool *); @@ -181,6 +226,7 @@ int pfctl_set_limit(struct pfctl *, const char *, unsigned int); int pfctl_set_logif(struct pfctl *, char *); int pfctl_set_hostid(struct pfctl *, u_int32_t); int pfctl_set_debug(struct pfctl *, char *); +int pfctl_set_interface_flags(struct pfctl *, char *, int, int); int parse_rules(FILE *, struct pfctl *); int parse_flags(char *); @@ -188,7 +234,7 @@ int pfctl_load_anchors(int, int, struct pfr_buffer *); void print_pool(struct pf_pool *, u_int16_t, u_int16_t, sa_family_t, int); void print_src_node(struct pf_src_node *, int); -void print_rule(struct pf_rule *, int); +void print_rule(struct pf_rule *, const char *, int); void print_tabledef(const char *, int, int, struct node_tinithead *); void print_status(struct pf_status *, int); @@ -202,8 +248,8 @@ void print_altq(const struct pf_altq *, unsigned, struct node_queue_bw *, void print_queue(const struct pf_altq *, unsigned, struct node_queue_bw *, int, struct node_queue_opt *); -int pfctl_define_table(char *, int, int, const char *, const char *, - struct pfr_buffer *, u_int32_t); +int pfctl_define_table(char *, int, int, const char *, struct pfr_buffer *, + u_int32_t); void pfctl_clear_fingerprints(int, int); int pfctl_file_fingerprints(int, int, const char *); @@ -244,6 +290,7 @@ extern const struct pf_timeout pf_timeouts[]; void set_ipmask(struct node_host *, u_int8_t); int check_netmask(struct node_host *, sa_family_t); +int unmask(struct pf_addr *, sa_family_t); void ifa_load(void); struct node_host *ifa_exists(const char *, int); struct node_host *ifa_lookup(const char *, int); diff --git a/contrib/pf/pfctl/pfctl_qstats.c b/contrib/pf/pfctl/pfctl_qstats.c index a46603c..28535c2 100644 --- a/contrib/pf/pfctl/pfctl_qstats.c +++ b/contrib/pf/pfctl/pfctl_qstats.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_qstats.c,v 1.29 2004/03/15 15:25:44 dhartmei Exp $ */ +/* $OpenBSD: pfctl_qstats.c,v 1.30 2004/04/27 21:47:32 kjc Exp $ */ /* * Copyright (c) Henning Brauer <henning@openbsd.org> @@ -97,6 +97,8 @@ pfctl_show_altq(int dev, const char *iface, int opts, int verbose2) if ((nodes = pfctl_update_qstats(dev, &root)) < 0) return (-1); + if (nodes == 0) + printf("No queue in use\n"); for (node = root; node != NULL; node = node->next) { if (iface != NULL && strcmp(node->altq.ifname, iface)) continue; @@ -107,11 +109,11 @@ pfctl_show_altq(int dev, const char *iface, int opts, int verbose2) pfctl_print_altq_node(dev, node, 0, opts); } - while (verbose2) { + while (verbose2 && nodes > 0) { printf("\n"); fflush(stdout); sleep(STAT_INTERVAL); - if (pfctl_update_qstats(dev, &root) == -1) + if ((nodes = pfctl_update_qstats(dev, &root)) == -1) return (-1); for (node = root; node != NULL; node = node->next) { if (iface != NULL && strcmp(node->altq.ifname, iface)) diff --git a/contrib/pf/pfctl/pfctl_table.c b/contrib/pf/pfctl/pfctl_table.c index 7b838b0..ecdd7e2 100644 --- a/contrib/pf/pfctl/pfctl_table.c +++ b/contrib/pf/pfctl/pfctl_table.c @@ -1,5 +1,4 @@ -/* $OpenBSD: pfctl_table.c,v 1.59 2004/03/15 15:25:44 dhartmei Exp $ */ -/* add $OpenBSD: pfctl_table.c,v 1.61 2004/06/12 22:22:44 cedric Exp $ */ +/* $OpenBSD: pfctl_table.c,v 1.62 2004/12/22 17:17:55 dhartmei Exp $ */ /* * Copyright (c) 2002 Cedric Berger @@ -57,7 +56,7 @@ __FBSDID("$FreeBSD$"); extern void usage(void); static int pfctl_table(int, char *[], char *, const char *, char *, - const char *, const char *, int); + const char *, int); static void print_table(struct pfr_table *, int, int); static void print_tstats(struct pfr_tstats *, int); static int load_addr(struct pfr_buffer *, int, char *[], char *, int); @@ -106,31 +105,29 @@ static const char *istats_text[2][2][2] = { } while(0) int -pfctl_clear_tables(const char *anchor, const char *ruleset, int opts) +pfctl_clear_tables(const char *anchor, int opts) { - return pfctl_table(0, NULL, NULL, "-F", NULL, anchor, ruleset, opts); + return pfctl_table(0, NULL, NULL, "-F", NULL, anchor, opts); } int -pfctl_show_tables(const char *anchor, const char *ruleset, int opts) +pfctl_show_tables(const char *anchor, int opts) { - return pfctl_table(0, NULL, NULL, "-s", NULL, anchor, ruleset, opts); + return pfctl_table(0, NULL, NULL, "-s", NULL, anchor, opts); } int pfctl_command_tables(int argc, char *argv[], char *tname, - const char *command, char *file, const char *anchor, const char *ruleset, - int opts) + const char *command, char *file, const char *anchor, int opts) { if (tname == NULL || command == NULL) usage(); - return pfctl_table(argc, argv, tname, command, file, anchor, ruleset, - opts); + return pfctl_table(argc, argv, tname, command, file, anchor, opts); } int pfctl_table(int argc, char *argv[], char *tname, const char *command, - char *file, const char *anchor, const char *ruleset, int opts) + char *file, const char *anchor, int opts) { struct pfr_table table; struct pfr_buffer b, b2; @@ -155,9 +152,7 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command, errx(1, "pfctl_table: strlcpy"); } if (strlcpy(table.pfrt_anchor, anchor, - sizeof(table.pfrt_anchor)) >= sizeof(table.pfrt_anchor) || - strlcpy(table.pfrt_ruleset, ruleset, - sizeof(table.pfrt_ruleset)) >= sizeof(table.pfrt_ruleset)) + sizeof(table.pfrt_anchor)) >= sizeof(table.pfrt_anchor)) errx(1, "pfctl_table: strlcpy"); if (!strcmp(command, "-F")) { @@ -347,8 +342,6 @@ print_table(struct pfr_table *ta, int verbose, int debug) ta->pfrt_name); if (ta->pfrt_anchor[0]) printf("\t%s", ta->pfrt_anchor); - if (ta->pfrt_ruleset[0]) - printf(":%s", ta->pfrt_ruleset); puts(""); } else puts(ta->pfrt_name); @@ -466,16 +459,14 @@ radix_perror(void) int pfctl_define_table(char *name, int flags, int addrs, const char *anchor, - const char *ruleset, struct pfr_buffer *ab, u_int32_t ticket) + struct pfr_buffer *ab, u_int32_t ticket) { struct pfr_table tbl; bzero(&tbl, sizeof(tbl)); if (strlcpy(tbl.pfrt_name, name, sizeof(tbl.pfrt_name)) >= sizeof(tbl.pfrt_name) || strlcpy(tbl.pfrt_anchor, anchor, - sizeof(tbl.pfrt_anchor)) >= sizeof(tbl.pfrt_anchor) || - strlcpy(tbl.pfrt_ruleset, ruleset, sizeof(tbl.pfrt_ruleset)) >= - sizeof(tbl.pfrt_ruleset)) + sizeof(tbl.pfrt_anchor)) >= sizeof(tbl.pfrt_anchor)) errx(1, "pfctl_define_table: strlcpy"); tbl.pfrt_flags = flags; @@ -589,7 +580,8 @@ print_iface(struct pfi_if *p, int opts) oprintf(flags, PFI_IFLAG_GROUP, "group", &first, 0); oprintf(flags, PFI_IFLAG_CLONABLE, "clonable", &first, 0); oprintf(flags, PFI_IFLAG_DYNAMIC, "dynamic", &first, 0); - oprintf(flags, PFI_IFLAG_ATTACHED, "attached", &first, 1); + oprintf(flags, PFI_IFLAG_ATTACHED, "attached", &first, 0); + oprintf(flags, PFI_IFLAG_SKIP, "skipped", &first, 1); #ifdef __FreeBSD__ first = 1; oprintf(flags, PFI_IFLAG_PLACEHOLDER, "placeholder", &first, 1); |