diff options
Diffstat (limited to 'sbin/pfctl')
-rw-r--r-- | sbin/pfctl/parse.y | 859 | ||||
-rw-r--r-- | sbin/pfctl/pfctl.c | 138 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_optimize.c | 36 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_parser.c | 26 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_parser.h | 4 |
5 files changed, 278 insertions, 785 deletions
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y index 318f447380b..45a4247f323 100644 --- a/sbin/pfctl/parse.y +++ b/sbin/pfctl/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.562 2009/07/28 13:26:52 claudio Exp $ */ +/* $OpenBSD: parse.y,v 1.563 2009/09/01 13:42:00 henning Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -202,6 +202,32 @@ struct node_qassign { char *pqname; }; +struct range { + int a; + int b; + int t; +}; +struct redirection { + struct node_host *host; + struct range rport; +}; + +struct pool_opts { + int marker; +#define POM_TYPE 0x01 +#define POM_STICKYADDRESS 0x02 + u_int8_t opts; + int type; + int staticport; + struct pf_poolhashkey *key; + +} pool_opts; + +struct redirspec { + struct redirection *rdr; + struct pool_opts pool_opts; +}; + struct filter_opts { int marker; #define FOM_FLAGS 0x0001 @@ -240,6 +266,8 @@ struct filter_opts { struct node_host *addr; u_int16_t port; } divert; + struct redirspec nat; + struct redirspec rdr; /* scrub opts */ int nodf; @@ -284,18 +312,6 @@ struct table_opts { struct node_tinithead init_nodes; } table_opts; -struct pool_opts { - int marker; -#define POM_TYPE 0x01 -#define POM_STICKYADDRESS 0x02 - u_int8_t opts; - int type; - int staticport; - struct pf_poolhashkey *key; - -} pool_opts; - - struct node_hfsc_opts hfsc_opts; struct node_state_opt *keep_state_defaults = NULL; @@ -303,9 +319,6 @@ int disallow_table(struct node_host *, const char *); int disallow_urpf_failed(struct node_host *, const char *); int disallow_alias(struct node_host *, const char *); int rule_consistent(struct pf_rule *, int); -int filter_consistent(struct pf_rule *, int); -int nat_consistent(struct pf_rule *); -int rdr_consistent(struct pf_rule *); int process_tabledef(char *, struct table_opts *); void expand_label_str(char *, size_t, const char *, const char *); void expand_label_if(const char *, char *, size_t, const char *); @@ -318,11 +331,13 @@ void expand_label_nr(const char *, char *, size_t); void expand_label(char *, size_t, const char *, u_int8_t, struct node_host *, struct node_port *, struct node_host *, struct node_port *, u_int8_t); +int apply_redirspec(struct pf_pool *, struct pf_rule *, + struct redirspec *, int, struct node_port *); 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 *, const char *); + struct redirspec *, struct redirspec *, 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 *, const char *); int expand_altq(struct pf_altq *, struct node_if *, struct node_queue *, struct node_queue_bw bwspec, struct node_queue_opt *); @@ -365,11 +380,7 @@ typedef struct { u_int16_t w; u_int16_t w2; } b; - struct range { - int a; - int b; - int t; - } range; + struct range range; struct node_if *interface; struct node_proto *proto; struct node_icmp *icmp; @@ -391,10 +402,7 @@ typedef struct { sa_family_t af; struct pf_poolhashkey *key; } route; - struct redirection { - struct node_host *host; - struct range rport; - } *redirection; + struct redirection *redirection; struct { int action; struct node_state_opt *options; @@ -436,7 +444,7 @@ int parseport(char *, struct range *r, int); %token PASS BLOCK MATCH SCRUB RETURN IN OS OUT LOG QUICK ON FROM TO FLAGS %token RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE -%token ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF +%token ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT NODF %token MINTTL ERROR ALLOWOPTS FASTROUTE FILENAME ROUTETO DUPTO REPLYTO NO LABEL %token NOROUTE URPFFAILED FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DROP TABLE %token REASSEMBLE FRAGDROP FRAGCROP ANCHOR NATANCHOR RDRANCHOR BINATANCHOR @@ -450,7 +458,7 @@ int parseport(char *, struct range *r, int); %token STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE %token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH SLOPPY PFLOW %token TAGGED TAG IFBOUND FLOATING STATEPOLICY STATEDEFAULTS ROUTE SETTOS -%token DIVERTTO DIVERTREPLY +%token DIVERTTO DIVERTREPLY NATTO RDRTO %token <v.string> STRING %token <v.number> NUMBER %token <v.i> PORTBINARY @@ -458,9 +466,9 @@ int parseport(char *, struct range *r, int); %type <v.number> number icmptype icmp6type uid gid %type <v.number> tos not yesno optnodf %type <v.probability> probability -%type <v.i> no dir af optimizer +%type <v.i> dir af optimizer %type <v.i> sourcetrack flush unaryop statelock -%type <v.b> action nataction natpasslog +%type <v.b> action %type <v.b> flags flag blockspec %type <v.range> portplain portstar portrange %type <v.hashkey> hashkey @@ -472,7 +480,7 @@ int parseport(char *, struct range *r, int); %type <v.number> reticmpspec reticmp6spec %type <v.fromto> fromto %type <v.peer> ipportspec from to -%type <v.host> ipspec toipspec xhost host dynaddr host_list +%type <v.host> ipspec xhost host dynaddr host_list %type <v.host> redir_host_list redirspec %type <v.host> route_host route_host_list routespec %type <v.os> os xos os_list @@ -480,8 +488,8 @@ int parseport(char *, struct range *r, int); %type <v.uid> uids uid_list uid_item %type <v.gid> gids gid_list gid_item %type <v.route> route -%type <v.redirection> redirection redirpool -%type <v.string> label stringall tag anchorname +%type <v.redirection> redirpool +%type <v.string> label stringall anchorname %type <v.string> string varstring numberstring %type <v.keep_state> keep %type <v.state_opt> state_opt_spec state_opt_list state_opt_item @@ -500,16 +508,12 @@ int parseport(char *, struct range *r, int); %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 -%type <v.rtableid> rtable %% ruleset : /* empty */ | ruleset include '\n' | ruleset '\n' | ruleset option '\n' - | ruleset natrule '\n' - | ruleset binatrule '\n' | ruleset pfrule '\n' | ruleset anchorrule '\n' | ruleset loadrule '\n' @@ -543,8 +547,6 @@ include : INCLUDE STRING { */ fakeanchor : fakeanchor '\n' | fakeanchor anchorrule '\n' - | fakeanchor binatrule '\n' - | fakeanchor natrule '\n' | fakeanchor pfrule '\n' | fakeanchor error '\n' ; @@ -892,111 +894,13 @@ anchorrule : ANCHOR anchorname dir quick interface af proto fromto decide_address_family($8.src.host, &r.af); decide_address_family($8.dst.host, &r.af); - expand_rule(&r, $5, NULL, $7, $8.src_os, + expand_rule(&r, $5, NULL, NULL, $7, $8.src_os, $8.src.host, $8.src.port, $8.dst.host, $8.dst.port, $9.uid, $9.gid, $9.icmpspec, pf->astack[pf->asd + 1] ? pf->alast->name : $2); free($2); pf->astack[pf->asd + 1] = NULL; } - | NATANCHOR string interface af proto fromto rtable { - struct pf_rule r; - - if (check_rulestate(PFCTL_STATE_NAT)) { - free($2); - YYERROR; - } - - memset(&r, 0, sizeof(r)); - r.action = PF_NAT; - r.af = $4; - r.rtableid = $7; - - decide_address_family($6.src.host, &r.af); - decide_address_family($6.dst.host, &r.af); - - expand_rule(&r, $3, NULL, $5, $6.src_os, - $6.src.host, $6.src.port, $6.dst.host, $6.dst.port, - 0, 0, 0, $2); - free($2); - } - | RDRANCHOR string interface af proto fromto rtable { - struct pf_rule r; - - if (check_rulestate(PFCTL_STATE_NAT)) { - free($2); - YYERROR; - } - - memset(&r, 0, sizeof(r)); - r.action = PF_RDR; - r.af = $4; - r.rtableid = $7; - - decide_address_family($6.src.host, &r.af); - decide_address_family($6.dst.host, &r.af); - - if ($6.src.port != NULL) { - yyerror("source port parameter not supported" - " in rdr-anchor"); - YYERROR; - } - if ($6.dst.port != NULL) { - if ($6.dst.port->next != NULL) { - yyerror("destination port list " - "expansion not supported in " - "rdr-anchor"); - YYERROR; - } else if ($6.dst.port->op != PF_OP_EQ) { - yyerror("destination port operators" - " not supported in rdr-anchor"); - YYERROR; - } - r.dst.port[0] = $6.dst.port->port[0]; - r.dst.port[1] = $6.dst.port->port[1]; - r.dst.port_op = $6.dst.port->op; - } - - expand_rule(&r, $3, NULL, $5, $6.src_os, - $6.src.host, $6.src.port, $6.dst.host, $6.dst.port, - 0, 0, 0, $2); - free($2); - } - | BINATANCHOR string interface af proto fromto rtable { - struct pf_rule r; - - if (check_rulestate(PFCTL_STATE_NAT)) { - free($2); - YYERROR; - } - - memset(&r, 0, sizeof(r)); - r.action = PF_BINAT; - r.af = $4; - r.rtableid = $7; - if ($5 != NULL) { - if ($5->next != NULL) { - yyerror("proto list expansion" - " not supported in binat-anchor"); - YYERROR; - } - r.proto = $5->proto; - free($5); - } - - if ($6.src.host != NULL || $6.src.port != NULL || - $6.dst.host != NULL || $6.dst.port != NULL) { - yyerror("fromto parameter not supported" - " in binat-anchor"); - YYERROR; - } - - decide_address_family($6.src.host, &r.af); - decide_address_family($6.dst.host, &r.af); - - pfctl_add_rule(pf, &r, $2); - free($2); - } ; loadrule : LOAD ANCHOR string FROM string { @@ -1159,9 +1063,9 @@ antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts { } if (h != NULL) - expand_rule(&r, j, NULL, NULL, NULL, h, - NULL, NULL, NULL, NULL, NULL, - NULL, ""); + expand_rule(&r, j, NULL, NULL, NULL, + NULL, h, NULL, NULL, NULL, NULL, + NULL, NULL, ""); if ((i->ifa_flags & IFF_LOOPBACK) == 0) { bzero(&r, sizeof(r)); @@ -1181,8 +1085,9 @@ antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts { 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, h, NULL, + NULL, NULL, NULL, NULL, + NULL, ""); } else free(hh); } @@ -2094,9 +1999,9 @@ pfrule : action dir logquick interface route af proto fromto YYERROR; } r.rt = $5.rt; - r.rpool.opts = $5.pool_opts; + r.rdr.opts = $5.pool_opts; if ($5.key != NULL) - memcpy(&r.rpool.key, $5.key, + memcpy(&r.rdr.key, $5.key, sizeof(struct pf_poolhashkey)); } if (r.rt && r.rt != PF_FASTROUTE) { @@ -2107,30 +2012,35 @@ pfrule : action dir logquick interface route af proto fromto "matching address family found."); YYERROR; } - if ((r.rpool.opts & PF_POOL_TYPEMASK) == + if ((r.rdr.opts & PF_POOL_TYPEMASK) == PF_POOL_NONE && ($5.host->next != NULL || $5.host->addr.type == PF_ADDR_TABLE || DYNIF_MULTIADDR($5.host->addr))) - r.rpool.opts |= PF_POOL_ROUNDROBIN; - if ((r.rpool.opts & PF_POOL_TYPEMASK) != + r.rdr.opts |= PF_POOL_ROUNDROBIN; + if ((r.rdr.opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN && disallow_table($5.host, "tables are only " "supported in round-robin routing pools")) YYERROR; - if ((r.rpool.opts & PF_POOL_TYPEMASK) != + if ((r.rdr.opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN && disallow_alias($5.host, "interface (%s) " "is only supported in round-robin " "routing pools")) YYERROR; if ($5.host->next != NULL) { - if ((r.rpool.opts & PF_POOL_TYPEMASK) != + if ((r.rdr.opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN) { yyerror("r.rpool.opts must " "be PF_POOL_ROUNDROBIN"); YYERROR; } } + /* fake redirspec */ + if (($9.rdr.rdr = calloc(1, + sizeof(*$9.rdr.rdr))) == NULL) + err(1, "$9.rdr.rdr"); + $9.rdr.rdr->host = $5.host; } if ($9.queues.qname != NULL) { if (strlcpy(r.qname, $9.queues.qname, @@ -2175,7 +2085,7 @@ pfrule : action dir logquick interface route af proto fromto } } - expand_rule(&r, $4, $5.host, $7, $8.src_os, + expand_rule(&r, $4, &$9.nat, &$9.rdr, $7, $8.src_os, $8.src.host, $8.src.port, $8.dst.host, $8.dst.port, $9.uid, $9.gid, $9.icmpspec, ""); } @@ -2317,6 +2227,24 @@ filter_opt : USER uids { filter_opts.marker |= FOM_SCRUB_TCP; filter_opts.marker |= $3.marker; } + | NATTO redirpool pool_opts { + if (filter_opts.nat.rdr) { + yyerror("cannot respecify nat-to"); + YYERROR; + } + filter_opts.nat.rdr = $2; + memcpy(&filter_opts.nat.pool_opts, &$3, + sizeof(filter_opts.nat.pool_opts)); + } + | RDRTO redirpool pool_opts { + if (filter_opts.rdr.rdr) { + yyerror("cannot respecify rdr-to"); + YYERROR; + } + filter_opts.rdr.rdr = $2; + memcpy(&filter_opts.rdr.pool_opts, &$3, + sizeof(filter_opts.rdr.pool_opts)); + } ; probability : STRING { @@ -2671,10 +2599,6 @@ ipspec : ANY { $$ = NULL; } | '{' optnl host_list '}' { $$ = $3; } ; -toipspec : TO ipspec { $$ = $2; } - | /* empty */ { $$ = NULL; } - ; - host_list : ipspec optnl { $$ = $1; } | host_list comma ipspec optnl { if ($3 == NULL) @@ -3561,10 +3485,6 @@ qname : QUEUE STRING { } ; -no : /* empty */ { $$ = 0; } - | NO { $$ = 1; } - ; - portstar : numberstring { if (parseport($1, &$$, PPORT_RANGE|PPORT_STAR) == -1) { free($1); @@ -3586,20 +3506,19 @@ redir_host_list : host optnl { $$ = $1; } } ; -redirpool : /* empty */ { $$ = NULL; } - | ARROW redirspec { +redirpool : redirspec { $$ = calloc(1, sizeof(struct redirection)); if ($$ == NULL) err(1, "redirection: calloc"); - $$->host = $2; + $$->host = $1; $$->rport.a = $$->rport.b = $$->rport.t = 0; } - | ARROW redirspec PORT portstar { + | redirspec PORT portstar { $$ = calloc(1, sizeof(struct redirection)); if ($$ == NULL) err(1, "redirection: calloc"); - $$->host = $2; - $$->rport = $4; + $$->host = $1; + $$->rport = $3; } ; @@ -3712,401 +3631,6 @@ pool_opt : BITMASK { } ; -redirection : /* empty */ { $$ = NULL; } - | ARROW host { - $$ = calloc(1, sizeof(struct redirection)); - if ($$ == NULL) - err(1, "redirection: calloc"); - $$->host = $2; - $$->rport.a = $$->rport.b = $$->rport.t = 0; - } - | ARROW host PORT portstar { - $$ = calloc(1, sizeof(struct redirection)); - if ($$ == NULL) - err(1, "redirection: calloc"); - $$->host = $2; - $$->rport = $4; - } - ; - -natpasslog : /* empty */ { $$.b1 = $$.b2 = 0; $$.w2 = 0; } - | PASS { $$.b1 = 1; $$.b2 = 0; $$.w2 = 0; } - | PASS log { $$.b1 = 1; $$.b2 = $2.log; $$.w2 = $2.logif; } - | log { $$.b1 = 0; $$.b2 = $1.log; $$.w2 = $1.logif; } - ; - -nataction : no NAT natpasslog { - if ($1 && $3.b1) { - yyerror("\"pass\" not valid with \"no\""); - YYERROR; - } - if ($1) - $$.b1 = PF_NONAT; - else - $$.b1 = PF_NAT; - $$.b2 = $3.b1; - $$.w = $3.b2; - $$.w2 = $3.w2; - } - | no RDR natpasslog { - if ($1 && $3.b1) { - yyerror("\"pass\" not valid with \"no\""); - YYERROR; - } - if ($1) - $$.b1 = PF_NORDR; - else - $$.b1 = PF_RDR; - $$.b2 = $3.b1; - $$.w = $3.b2; - $$.w2 = $3.w2; - } - ; - -natrule : nataction interface af proto fromto tag tagged rtable - redirpool pool_opts - { - struct pf_rule r; - - if (check_rulestate(PFCTL_STATE_NAT)) - YYERROR; - - memset(&r, 0, sizeof(r)); - - r.action = $1.b1; - r.natpass = $1.b2; - r.log = $1.w; - r.logif = $1.w2; - r.af = $3; - - if (!r.af) { - if ($5.src.host && $5.src.host->af && - !$5.src.host->ifindex) - r.af = $5.src.host->af; - else if ($5.dst.host && $5.dst.host->af && - !$5.dst.host->ifindex) - r.af = $5.dst.host->af; - } - - if ($6 != NULL) - if (strlcpy(r.tagname, $6, PF_TAG_NAME_SIZE) >= - PF_TAG_NAME_SIZE) { - yyerror("tag too long, max %u chars", - PF_TAG_NAME_SIZE - 1); - 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; - r.rtableid = $8; - - if (r.action == PF_NONAT || r.action == PF_NORDR) { - if ($9 != NULL) { - yyerror("translation rule with 'no' " - "does not need '->'"); - YYERROR; - } - } else { - if ($9 == NULL || $9->host == NULL) { - yyerror("translation rule requires '-> " - "address'"); - YYERROR; - } - if (!r.af && ! $9->host->ifindex) - r.af = $9->host->af; - - remove_invalid_hosts(&$9->host, &r.af); - if (invalid_redirect($9->host, r.af)) - YYERROR; - if (check_netmask($9->host, r.af)) - YYERROR; - - r.rpool.proxy_port[0] = ntohs($9->rport.a); - - switch (r.action) { - case PF_RDR: - if (!$9->rport.b && $9->rport.t && - $5.dst.port != NULL) { - r.rpool.proxy_port[1] = - ntohs($9->rport.a) + - (ntohs( - $5.dst.port->port[1]) - - ntohs( - $5.dst.port->port[0])); - } else - r.rpool.proxy_port[1] = - ntohs($9->rport.b); - break; - case PF_NAT: - r.rpool.proxy_port[1] = - ntohs($9->rport.b); - if (!r.rpool.proxy_port[0] && - !r.rpool.proxy_port[1]) { - r.rpool.proxy_port[0] = - PF_NAT_PROXY_PORT_LOW; - r.rpool.proxy_port[1] = - PF_NAT_PROXY_PORT_HIGH; - } else if (!r.rpool.proxy_port[1]) - r.rpool.proxy_port[1] = - r.rpool.proxy_port[0]; - break; - default: - break; - } - - r.rpool.opts = $10.type; - if ((r.rpool.opts & PF_POOL_TYPEMASK) == - PF_POOL_NONE && ($9->host->next != NULL || - $9->host->addr.type == PF_ADDR_TABLE || - DYNIF_MULTIADDR($9->host->addr))) - r.rpool.opts = PF_POOL_ROUNDROBIN; - if ((r.rpool.opts & PF_POOL_TYPEMASK) != - PF_POOL_ROUNDROBIN && - disallow_table($9->host, "tables are only " - "supported in round-robin redirection " - "pools")) - YYERROR; - if ((r.rpool.opts & PF_POOL_TYPEMASK) != - PF_POOL_ROUNDROBIN && - disallow_alias($9->host, "interface (%s) " - "is only supported in round-robin " - "redirection pools")) - YYERROR; - if ($9->host->next != NULL) { - if ((r.rpool.opts & PF_POOL_TYPEMASK) != - PF_POOL_ROUNDROBIN) { - yyerror("only round-robin " - "valid for multiple " - "redirection addresses"); - YYERROR; - } - } - } - - if ($10.key != NULL) - memcpy(&r.rpool.key, $10.key, - sizeof(struct pf_poolhashkey)); - - if ($10.opts) - r.rpool.opts |= $10.opts; - - if ($10.staticport) { - if (r.action != PF_NAT) { - yyerror("the 'static-port' option is " - "only valid with nat rules"); - YYERROR; - } - if (r.rpool.proxy_port[0] != - PF_NAT_PROXY_PORT_LOW && - r.rpool.proxy_port[1] != - PF_NAT_PROXY_PORT_HIGH) { - yyerror("the 'static-port' option can't" - " be used when specifying a port" - " range"); - YYERROR; - } - r.rpool.proxy_port[0] = 0; - r.rpool.proxy_port[1] = 0; - } - - expand_rule(&r, $2, $9 == NULL ? NULL : $9->host, $4, - $5.src_os, $5.src.host, $5.src.port, $5.dst.host, - $5.dst.port, 0, 0, 0, ""); - free($9); - } - ; - -binatrule : no BINAT natpasslog interface af proto FROM host toipspec tag - tagged rtable redirection - { - struct pf_rule binat; - struct pf_pooladdr *pa; - - if (check_rulestate(PFCTL_STATE_NAT)) - YYERROR; - if (disallow_urpf_failed($9, "\"urpf-failed\" is not " - "permitted as a binat destination")) - YYERROR; - - memset(&binat, 0, sizeof(binat)); - - if ($1 && $3.b1) { - yyerror("\"pass\" not valid with \"no\""); - YYERROR; - } - if ($1) - binat.action = PF_NOBINAT; - else - binat.action = PF_BINAT; - binat.natpass = $3.b1; - binat.log = $3.b2; - binat.logif = $3.w2; - binat.af = $5; - if (!binat.af && $8 != NULL && $8->af) - binat.af = $8->af; - if (!binat.af && $9 != NULL && $9->af) - binat.af = $9->af; - - if (!binat.af && $13 != NULL && $13->host) - binat.af = $13->host->af; - if (!binat.af) { - yyerror("address family (inet/inet6) " - "undefined"); - YYERROR; - } - - if ($4 != NULL) { - memcpy(binat.ifname, $4->ifname, - sizeof(binat.ifname)); - binat.ifnot = $4->not; - free($4); - } - - if ($10 != NULL) - if (strlcpy(binat.tagname, $10, - PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) { - yyerror("tag too long, max %u chars", - PF_TAG_NAME_SIZE - 1); - YYERROR; - } - if ($11.name) - if (strlcpy(binat.match_tagname, $11.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 = $11.neg; - binat.rtableid = $12; - - if ($6 != NULL) { - binat.proto = $6->proto; - free($6); - } - - if ($8 != NULL && disallow_table($8, "invalid use of " - "table <%s> as the source address of a binat rule")) - YYERROR; - if ($8 != NULL && disallow_alias($8, "invalid use of " - "interface (%s) as the source address of a binat " - "rule")) - YYERROR; - 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 ($13 != NULL && $13->host != NULL && disallow_alias( - $13->host, "invalid use of interface (%s) as the " - "redirect address of a binat rule")) - YYERROR; - - if ($8 != NULL) { - if ($8->next) { - yyerror("multiple binat ip addresses"); - YYERROR; - } - if ($8->addr.type == PF_ADDR_DYNIFTL) - $8->af = binat.af; - if ($8->af != binat.af) { - yyerror("binat ip versions must match"); - YYERROR; - } - if (check_netmask($8, binat.af)) - YYERROR; - memcpy(&binat.src.addr, &$8->addr, - sizeof(binat.src.addr)); - free($8); - } - if ($9 != NULL) { - if ($9->next) { - yyerror("multiple binat ip addresses"); - YYERROR; - } - if ($9->af != binat.af && $9->af) { - yyerror("binat ip versions must match"); - YYERROR; - } - if (check_netmask($9, binat.af)) - YYERROR; - memcpy(&binat.dst.addr, &$9->addr, - sizeof(binat.dst.addr)); - binat.dst.neg = $9->not; - free($9); - } - - if (binat.action == PF_NOBINAT) { - if ($13 != NULL) { - yyerror("'no binat' rule does not need" - " '->'"); - YYERROR; - } - } else { - if ($13 == NULL || $13->host == NULL) { - yyerror("'binat' rule requires" - " '-> address'"); - YYERROR; - } - - remove_invalid_hosts(&$13->host, &binat.af); - if (invalid_redirect($13->host, binat.af)) - YYERROR; - if ($13->host->next != NULL) { - yyerror("binat rule must redirect to " - "a single address"); - YYERROR; - } - 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, - &$13->host->addr.v.a.mask, binat.af)) { - yyerror("'binat' source mask and " - "redirect mask must be the same"); - YYERROR; - } - - TAILQ_INIT(&binat.rpool.list); - pa = calloc(1, sizeof(struct pf_pooladdr)); - if (pa == NULL) - err(1, "binat: calloc"); - pa->addr = $13->host->addr; - pa->ifname[0] = 0; - TAILQ_INSERT_TAIL(&binat.rpool.list, - pa, entries); - - free($13); - } - - pfctl_add_rule(pf, &binat, ""); - } - ; - -tag : /* empty */ { $$ = NULL; } - | TAG STRING { $$ = $2; } - ; - -tagged : /* empty */ { $$.neg = 0; $$.name = NULL; } - | not TAGGED string { $$.neg = $1; $$.name = $3; } - ; - -rtable : /* empty */ { $$ = -1; } - | RTABLE NUMBER { - if ($2 < 0 || $2 > RT_TABLEID_MAX) { - yyerror("invalid rtable id"); - YYERROR; - } - $$ = $2; - } - ; - route_host : STRING { $$ = calloc(1, sizeof(struct node_host)); if ($$ == NULL) @@ -4300,33 +3824,6 @@ rule_consistent(struct pf_rule *r, int anchor_call) { int problems = 0; - switch (r->action) { - case PF_PASS: - case PF_MATCH: - case PF_DROP: - problems = filter_consistent(r, anchor_call); - break; - case PF_NAT: - case PF_NONAT: - problems = nat_consistent(r); - break; - case PF_RDR: - case PF_NORDR: - problems = rdr_consistent(r); - break; - case PF_BINAT: - case PF_NOBINAT: - default: - break; - } - return (problems); -} - -int -filter_consistent(struct pf_rule *r, int anchor_call) -{ - int problems = 0; - if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP && (r->src.port_op || r->dst.port_op)) { yyerror("port only applies to tcp/udp"); @@ -4382,6 +3879,20 @@ filter_consistent(struct pf_rule *r, int anchor_call) "synproxy state or modulate state"); problems++; } + if ((!TAILQ_EMPTY(&r->nat.list) || !TAILQ_EMPTY(&r->rdr.list)) && + r->action != PF_MATCH && !r->keep_state) { + yyerror("nat-to and rdr-to require keep state"); + problems++; + } + if (!TAILQ_EMPTY(&r->nat.list) && r->direction != PF_OUT) { + yyerror("nat-to can only be used outbound"); + problems++; + } + if (!TAILQ_EMPTY(&r->rdr.list) && r->direction != PF_IN) { + yyerror("rdr-to can only be used inbound"); + problems++; + } + /* match rules rules */ if (r->action == PF_MATCH) { if (r->divert.port) { @@ -4398,39 +3909,6 @@ filter_consistent(struct pf_rule *r, int anchor_call) } int -nat_consistent(struct pf_rule *r) -{ - return (0); /* yeah! */ -} - -int -rdr_consistent(struct pf_rule *r) -{ - int problems = 0; - - if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP) { - if (r->src.port_op) { - yyerror("src port only applies to tcp/udp"); - problems++; - } - if (r->dst.port_op) { - yyerror("dst port only applies to tcp/udp"); - problems++; - } - if (r->rpool.proxy_port[0]) { - yyerror("rpool port only applies to tcp/udp"); - problems++; - } - } - if (r->dst.port_op && - r->dst.port_op != PF_OP_EQ && r->dst.port_op != PF_OP_RRG) { - yyerror("invalid port operator for rdr destination port"); - problems++; - } - return (-problems); -} - -int process_tabledef(char *name, struct table_opts *opts) { struct pfr_buffer ab; @@ -4924,9 +4402,108 @@ expand_queue(struct pf_altq *a, struct node_if *interfaces, return (0); } +int +apply_redirspec(struct pf_pool *rpool, struct pf_rule *r, struct redirspec *rs, + int isrdr, struct node_port *np) +{ + struct node_host *h; + struct pf_pooladdr *pa; + + if (!rs || !rs->rdr) + return (0); + + if (!r->af && ! rs->rdr->host->ifindex) + r->af = rs->rdr->host->af; + + remove_invalid_hosts(&rs->rdr->host, &r->af); + if (invalid_redirect(rs->rdr->host, r->af)) + return (1); + if (check_netmask(rs->rdr->host, r->af)) + return (1); + + rpool->proxy_port[0] = ntohs(rs->rdr->rport.a); + + if (isrdr) { + if (!rs->rdr->rport.b && rs->rdr->rport.t && np->port != NULL) { + rpool->proxy_port[1] = ntohs(rs->rdr->rport.a) + + (ntohs(np->port[1]) - ntohs(np->port[0])); + } else + rpool->proxy_port[1] = ntohs(rs->rdr->rport.b); + } else { + rpool->proxy_port[1] = ntohs(rs->rdr->rport.b); + if (!rpool->proxy_port[0] && !rpool->proxy_port[1]) { + rpool->proxy_port[0] = PF_NAT_PROXY_PORT_LOW; + rpool->proxy_port[1] = PF_NAT_PROXY_PORT_HIGH; + } else if (!rpool->proxy_port[1]) + rpool->proxy_port[1] = rpool->proxy_port[0]; + } + + rpool->opts = rs->pool_opts.type; + if ((rpool->opts & PF_POOL_TYPEMASK) == PF_POOL_NONE && + (rs->rdr->host->next != NULL || + rs->rdr->host->addr.type == PF_ADDR_TABLE || + DYNIF_MULTIADDR(rs->rdr->host->addr))) + rpool->opts = PF_POOL_ROUNDROBIN; + if ((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN && + disallow_table(rs->rdr->host, "tables are only supported in " + "round-robin redirection pools")) + return (1); + if ((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN && + disallow_alias(rs->rdr->host, "interface (%s) is only supported in " + "round-robin redirection pools")) + return (1); + if (rs->rdr->host->next != NULL) { + if ((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN) { + yyerror("only round-robin valid for multiple " + "redirection addresses"); + return (1); + } + } + + if (rs->pool_opts.key != NULL) + memcpy(&rpool->key, rs->pool_opts.key, + sizeof(struct pf_poolhashkey)); + + if (rs->pool_opts.opts) + rpool->opts |= rs->pool_opts.opts; + + if (rs->pool_opts.staticport) { + if (isrdr) { + yyerror("the 'static-port' option is only valid with " + "nat rules"); + return (1); + } + if (rpool->proxy_port[0] != PF_NAT_PROXY_PORT_LOW && + rpool->proxy_port[1] != PF_NAT_PROXY_PORT_HIGH) { + yyerror("the 'static-port' option can't be used when " + "specifying a port range"); + return (1); + } + rpool->proxy_port[0] = 0; + rpool->proxy_port[1] = 0; + } + + TAILQ_INIT(&rpool->list); + for (h = rs->rdr->host; h != NULL; h = h->next) { + if ((pa = calloc(1, sizeof(struct pf_pooladdr))) == NULL) + err(1, "expand_rule: calloc"); + pa->addr = h->addr; + if (h->ifname != NULL) { + if (strlcpy(pa->ifname, h->ifname, sizeof pa->ifname) >= + sizeof(pa->ifname)) + errx(1, "expand_rule: strlcpy"); + } else + pa->ifname[0] = 0; + TAILQ_INSERT_TAIL(&rpool->list, pa, entries); + } + + return (0); +} + + void -expand_rule(struct pf_rule *r, - struct node_if *interfaces, struct node_host *rpool_hosts, +expand_rule(struct pf_rule *r, struct node_if *interfaces, + struct redirspec *nat, struct redirspec *rdr, 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, @@ -4939,8 +4516,6 @@ expand_rule(struct pf_rule *r, char label[PF_RULE_LABEL_SIZE]; char tagname[PF_TAG_NAME_SIZE]; char match_tagname[PF_TAG_NAME_SIZE]; - struct pf_pooladdr *pa; - struct node_host *h; u_int8_t flags, flagset, keep_state; if (strlcpy(label, r->label, sizeof(label)) >= sizeof(label)) @@ -5064,21 +4639,8 @@ expand_rule(struct pf_rule *r, r->os_fingerprint = PF_OSFP_ANY; } - TAILQ_INIT(&r->rpool.list); - for (h = rpool_hosts; h != NULL; h = h->next) { - pa = calloc(1, sizeof(struct pf_pooladdr)); - if (pa == NULL) - err(1, "expand_rule: calloc"); - pa->addr = h->addr; - if (h->ifname != NULL) { - if (strlcpy(pa->ifname, h->ifname, - sizeof(pa->ifname)) >= - sizeof(pa->ifname)) - errx(1, "expand_rule: strlcpy"); - } else - pa->ifname[0] = 0; - TAILQ_INSERT_TAIL(&r->rpool.list, pa, entries); - } + error += apply_redirspec(&r->nat, r, nat, 0, dst_port); + error += apply_redirspec(&r->rdr, r, rdr, 1, dst_port); if (rule_consistent(r, anchor_call[0]) < 0 || error) yyerror("skipping rule due to errors"); @@ -5100,7 +4662,10 @@ expand_rule(struct pf_rule *r, FREE_LIST(struct node_uid, uids); FREE_LIST(struct node_gid, gids); FREE_LIST(struct node_icmp, icmp_types); - FREE_LIST(struct node_host, rpool_hosts); + if (nat && nat->rdr) + FREE_LIST(struct node_host, nat->rdr->host); + if (rdr && rdr->rdr) + FREE_LIST(struct node_host, rdr->rdr->host); if (!added) yyerror("rule expands to no valid combination"); @@ -5227,6 +4792,7 @@ lookup(char *s) { "modulate", MODULATE}, { "nat", NAT}, { "nat-anchor", NATANCHOR}, + { "nat-to", NATTO}, { "no", NO}, { "no-df", NODF}, { "no-route", NOROUTE}, @@ -5250,6 +4816,7 @@ lookup(char *s) { "random-id", RANDOMID}, { "rdr", RDR}, { "rdr-anchor", RDRANCHOR}, + { "rdr-to", RDRTO}, { "realtime", REALTIME}, { "reassemble", REASSEMBLE}, { "reply-to", REPLYTO}, @@ -5491,12 +5058,6 @@ top: } lungetc(next); break; - case '-': - next = lgetc(0); - if (next == '>') - return (ARROW); - lungetc(next); - break; } #define allowed_to_end_number(x) \ diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c index ef0d04a2f4b..984f29c0806 100644 --- a/sbin/pfctl/pfctl.c +++ b/sbin/pfctl/pfctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl.c,v 1.284 2009/08/21 05:27:57 ratchov Exp $ */ +/* $OpenBSD: pfctl.c,v 1.285 2009/09/01 13:42:00 henning Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -62,7 +62,6 @@ int pfctl_disable(int, int); int pfctl_clear_stats(int, int); 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); @@ -80,10 +79,9 @@ int pfctl_load_logif(struct pfctl *, char *); int pfctl_load_hostid(struct pfctl *, unsigned int); int pfctl_load_reassembly(struct pfctl *, u_int32_t); int pfctl_get_pool(int, struct pf_pool *, u_int32_t, u_int32_t, int, - char *); + char *, int); void pfctl_print_rule_counters(struct pf_rule *, int); int pfctl_show_rules(int, char *, int, enum pfctl_show, char *, int); -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); @@ -201,12 +199,12 @@ static const struct { }; static const char *clearopt_list[] = { - "nat", "queue", "rules", "Sources", + "queue", "rules", "Sources", "states", "info", "Tables", "osfp", "all", NULL }; static const char *showopt_list[] = { - "nat", "queue", "rules", "Anchors", "Sources", "states", "info", + "queue", "rules", "Anchors", "Sources", "states", "info", "Interfaces", "labels", "timeouts", "memory", "Tables", "osfp", "all", NULL }; @@ -321,24 +319,6 @@ pfctl_clear_rules(int dev, int opts, char *anchorname) } int -pfctl_clear_nat(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_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"); - if ((opts & PF_OPT_QUIET) == 0) - fprintf(stderr, "nat cleared\n"); - return (0); -} - -int pfctl_clear_altq(int dev, int opts) { struct pfr_buffer t; @@ -706,7 +686,7 @@ pfctl_id_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) + u_int32_t ticket, int r_action, char *anchorname, int which) { struct pfioc_pooladdr pp; struct pf_pooladdr *pa; @@ -717,6 +697,7 @@ pfctl_get_pool(int dev, struct pf_pool *pool, u_int32_t nr, pp.r_action = r_action; pp.r_num = nr; pp.ticket = ticket; + pp.which = which; if (ioctl(dev, DIOCGETADDRS, &pp)) { warn("DIOCGETADDRS"); return (-1); @@ -857,8 +838,11 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format, goto error; } - if (pfctl_get_pool(dev, &pr.rule.rpool, - nr, pr.ticket, PF_PASS, path) != 0) + if (pfctl_get_pool(dev, &pr.rule.rdr, + nr, pr.ticket, PF_PASS, path, PF_RDR) != 0) + goto error; + if (pfctl_get_pool(dev, &pr.rule.nat, + nr, pr.ticket, PF_PASS, path, PF_NAT) != 0) goto error; switch (format) { @@ -913,7 +897,8 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format, case PFCTL_SHOW_NOTHING: break; } - pfctl_clear_pool(&pr.rule.rpool); + pfctl_clear_pool(&pr.rule.rdr); + pfctl_clear_pool(&pr.rule.nat); } path[len] = '\0'; return (0); @@ -924,46 +909,6 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format, } int -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; - - memset(&pr, 0, sizeof(pr)); - memcpy(pr.anchor, anchorname, sizeof(pr.anchor)); - for (i = 0; i < 3; i++) { - pr.rule.action = nattype[i]; - if (ioctl(dev, DIOCGETRULES, &pr)) { - warn("DIOCGETRULES"); - return (-1); - } - mnr = pr.nr; - for (nr = 0; nr < mnr; ++nr) { - pr.nr = nr; - if (ioctl(dev, DIOCGETRULE, &pr)) { - warn("DIOCGETRULE"); - return (-1); - } - if (pfctl_get_pool(dev, &pr.rule.rpool, nr, - pr.ticket, nattype[i], anchorname) != 0) - return (-1); - if (dotitle) { - pfctl_print_title("TRANSLATION RULES:"); - dotitle = 0; - } - print_rule(&pr.rule, pr.anchor_call, - opts & PF_OPT_VERBOSE2); - printf("\n"); - pfctl_print_rule_counters(&pr.rule, opts); - pfctl_clear_pool(&pr.rule.rpool); - } - } - return (0); -} - -int pfctl_show_src_nodes(int dev, int opts) { struct pfioc_src_nodes psn; @@ -1120,22 +1065,16 @@ pfctl_show_limits(int dev, int opts) /* callbacks for rule/nat/rdr/addr */ int -pfctl_add_pool(struct pfctl *pf, struct pf_pool *p, sa_family_t af) +pfctl_add_pool(struct pfctl *pf, struct pf_pool *p, sa_family_t af, int which) { struct pf_pooladdr *pa; - if ((pf->opts & PF_OPT_NOACTION) == 0) { - if (ioctl(pf->dev, DIOCBEGINADDRS, &pf->paddr)) - err(1, "DIOCBEGINADDRS"); - } - pf->paddr.af = af; TAILQ_FOREACH(pa, &p->list, entries) { + pf->paddr.which = which; memcpy(&pf->paddr.addr, pa, sizeof(struct pf_pooladdr)); - if ((pf->opts & PF_OPT_NOACTION) == 0) { - if (ioctl(pf->dev, DIOCADDADDR, &pf->paddr)) - err(1, "DIOCADDADDR"); - } + if (ioctl(pf->dev, DIOCADDADDR, &pf->paddr)) + err(1, "DIOCADDADDR"); } return (0); } @@ -1181,8 +1120,10 @@ pfctl_add_rule(struct pfctl *pf, struct pf_rule *r, const char *anchor_call) if ((rule = calloc(1, sizeof(*rule))) == NULL) err(1, "calloc"); bcopy(r, rule, sizeof(*rule)); - TAILQ_INIT(&rule->rpool.list); - pfctl_move_pool(&r->rpool, &rule->rpool); + TAILQ_INIT(&rule->rdr.list); + pfctl_move_pool(&r->rdr, &rule->rdr); + TAILQ_INIT(&rule->nat.list); + pfctl_move_pool(&r->nat, &rule->nat); TAILQ_INSERT_TAIL(rs->rules[rs_num].active.ptr, rule, entries); return (0); @@ -1193,12 +1134,6 @@ pfctl_ruleset_trans(struct pfctl *pf, char *path, struct pf_anchor *a) { int osize = pf->trans->pfrb_size; - if ((pf->loadopt & PFCTL_FLAG_NAT) != 0) { - if (pfctl_add_trans(pf->trans, PF_RULESET_NAT, path) || - pfctl_add_trans(pf->trans, PF_RULESET_BINAT, path) || - pfctl_add_trans(pf->trans, PF_RULESET_RDR, path)) - return (1); - } if (a == pf->astack[0] && ((altqsupport && (pf->loadopt & PFCTL_FLAG_ALTQ) != 0))) { if (pfctl_add_trans(pf->trans, PF_RULESET_ALTQ, path)) @@ -1307,7 +1242,11 @@ pfctl_load_rule(struct pfctl *pf, char *path, struct pf_rule *r, int depth) name = ""; if ((pf->opts & PF_OPT_NOACTION) == 0) { - if (pfctl_add_pool(pf, &r->rpool, r->af)) + if (ioctl(pf->dev, DIOCBEGINADDRS, &pf->paddr)) + err(1, "DIOCBEGINADDRS"); + if (pfctl_add_pool(pf, &r->rdr, r->af, PF_RDR)) + return (1); + if (pfctl_add_pool(pf, &r->nat, r->af, PF_NAT)) return (1); pr.pool_ticket = pf->paddr.ticket; memcpy(&pr.rule, r, sizeof(pr.rule)); @@ -1324,7 +1263,8 @@ pfctl_load_rule(struct pfctl *pf, char *path, struct pf_rule *r, int depth) pf->opts & PF_OPT_VERBOSE2); } path[len] = '\0'; - pfctl_clear_pool(&r->rpool); + pfctl_clear_pool(&r->rdr); + pfctl_clear_pool(&r->nat); return (0); } @@ -1438,11 +1378,7 @@ pfctl_rules(int dev, char *filename, int opts, int optimize, goto _error; } - if ((pf.loadopt & PFCTL_FLAG_NAT && - (pfctl_load_ruleset(&pf, path, rs, PF_RULESET_NAT, 0) || - pfctl_load_ruleset(&pf, path, rs, PF_RULESET_RDR, 0) || - pfctl_load_ruleset(&pf, path, rs, PF_RULESET_BINAT, 0))) || - (pf.loadopt & PFCTL_FLAG_FILTER && + if ((pf.loadopt & PFCTL_FLAG_FILTER && pfctl_load_ruleset(&pf, path, rs, PF_RULESET_FILTER, 0))) { if ((opts & PF_OPT_NOACTION) == 0) ERRX("Unable to load rules into kernel"); @@ -2013,7 +1949,7 @@ main(int argc, char *argv[]) usage(); while ((ch = getopt(argc, argv, - "a:AdD:eqf:F:ghi:k:K:mnNOo:p:rRs:t:T:vx:z")) != -1) { + "a:AdD:eqf:F:ghi:k:K:mnOo:p:rRs:t:T:vx:z")) != -1) { switch (ch) { case 'a': anchoropt = optarg; @@ -2069,9 +2005,6 @@ main(int argc, char *argv[]) case 'n': opts |= PF_OPT_NOACTION; break; - case 'N': - loadopt |= PFCTL_FLAG_NAT; - break; case 'r': opts |= PF_OPT_USEDNS; break; @@ -2178,7 +2111,7 @@ main(int argc, char *argv[]) sizeof(anchorname)) >= sizeof(anchorname)) errx(1, "anchor name '%s' too long", anchoropt); - loadopt &= PFCTL_FLAG_FILTER|PFCTL_FLAG_NAT|PFCTL_FLAG_TABLE; + loadopt &= PFCTL_FLAG_FILTER|PFCTL_FLAG_TABLE; } if ((opts & PF_OPT_NOACTION) == 0) { @@ -2215,10 +2148,6 @@ main(int argc, char *argv[]) pfctl_show_rules(dev, path, opts, PFCTL_SHOW_LABELS, anchorname, 0); break; - case 'n': - pfctl_load_fingerprints(dev, opts); - pfctl_show_nat(dev, opts, anchorname); - break; case 'q': pfctl_show_altq(dev, ifaceopt, opts, opts & PF_OPT_VERBOSE2); @@ -2242,7 +2171,6 @@ main(int argc, char *argv[]) opts |= PF_OPT_SHOWALL; pfctl_load_fingerprints(dev, opts); - pfctl_show_nat(dev, opts, anchorname); pfctl_show_rules(dev, path, opts, 0, anchorname, 0); pfctl_show_altq(dev, ifaceopt, opts, 0); pfctl_show_states(dev, ifaceopt, opts); @@ -2280,9 +2208,6 @@ main(int argc, char *argv[]) case 'r': pfctl_clear_rules(dev, opts, anchorname); break; - case 'n': - pfctl_clear_nat(dev, opts, anchorname); - break; case 'q': pfctl_clear_altq(dev, opts); break; @@ -2297,7 +2222,6 @@ main(int argc, char *argv[]) break; case 'a': pfctl_clear_rules(dev, opts, anchorname); - pfctl_clear_nat(dev, opts, anchorname); pfctl_clear_tables(anchorname, opts); if (!*anchorname) { pfctl_clear_altq(dev, opts); diff --git a/sbin/pfctl/pfctl_optimize.c b/sbin/pfctl/pfctl_optimize.c index bbed611d2fe..88d44115331 100644 --- a/sbin/pfctl/pfctl_optimize.c +++ b/sbin/pfctl/pfctl_optimize.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_optimize.c,v 1.18 2008/05/07 06:23:30 markus Exp $ */ +/* $OpenBSD: pfctl_optimize.c,v 1.19 2009/09/01 13:42:00 henning Exp $ */ /* * Copyright (c) 2004 Mike Frantzen <frantzen@openbsd.org> @@ -134,7 +134,8 @@ struct pf_rule_field { PF_RULE_FIELD(return_ttl, BREAK), PF_RULE_FIELD(overload_tblname, BREAK), PF_RULE_FIELD(flush, BREAK), - PF_RULE_FIELD(rpool, BREAK), + PF_RULE_FIELD(rdr, BREAK), + PF_RULE_FIELD(nat, BREAK), PF_RULE_FIELD(logif, BREAK), /* @@ -287,12 +288,18 @@ pfctl_optimize_ruleset(struct pfctl *pf, struct pf_ruleset *rs) if ((por = calloc(1, sizeof(*por))) == NULL) err(1, "calloc"); memcpy(&por->por_rule, r, sizeof(*r)); - if (TAILQ_FIRST(&r->rpool.list) != NULL) { - TAILQ_INIT(&por->por_rule.rpool.list); - pfctl_move_pool(&r->rpool, &por->por_rule.rpool); + if (TAILQ_FIRST(&r->rdr.list) != NULL) { + TAILQ_INIT(&por->por_rule.rdr.list); + pfctl_move_pool(&r->rdr, &por->por_rule.rdr); } else - bzero(&por->por_rule.rpool, - sizeof(por->por_rule.rpool)); + bzero(&por->por_rule.rdr, + sizeof(por->por_rule.rdr)); + if (TAILQ_FIRST(&r->nat.list) != NULL) { + TAILQ_INIT(&por->por_rule.nat.list); + pfctl_move_pool(&r->nat, &por->por_rule.nat); + } else + bzero(&por->por_rule.nat, + sizeof(por->por_rule.nat)); TAILQ_INSERT_TAIL(&opt_queue, por, por_entry); @@ -322,8 +329,10 @@ pfctl_optimize_ruleset(struct pfctl *pf, struct pf_ruleset *rs) if ((r = calloc(1, sizeof(*r))) == NULL) err(1, "calloc"); memcpy(r, &por->por_rule, sizeof(*r)); - TAILQ_INIT(&r->rpool.list); - pfctl_move_pool(&por->por_rule.rpool, &r->rpool); + TAILQ_INIT(&r->rdr.list); + TAILQ_INIT(&r->nat.list); + pfctl_move_pool(&por->por_rule.rdr, &r->rdr); + pfctl_move_pool(&por->por_rule.nat, &r->nat); TAILQ_INSERT_TAIL( rs->rules[PF_RULESET_FILTER].active.ptr, r, entries); @@ -908,9 +917,12 @@ load_feedback_profile(struct pfctl *pf, struct superblocks *superblocks) memcpy(&por->por_rule, &pr.rule, sizeof(por->por_rule)); rs = pf_find_or_create_ruleset(pr.anchor_call); por->por_rule.anchor = rs->anchor; - if (TAILQ_EMPTY(&por->por_rule.rpool.list)) - memset(&por->por_rule.rpool, 0, - sizeof(por->por_rule.rpool)); + if (TAILQ_EMPTY(&por->por_rule.rdr.list)) + memset(&por->por_rule.rdr, 0, + sizeof(por->por_rule.rdr)); + if (TAILQ_EMPTY(&por->por_rule.nat.list)) + memset(&por->por_rule.nat, 0, + sizeof(por->por_rule.nat)); TAILQ_INSERT_TAIL(&queue, por, por_entry); /* XXX pfctl_get_pool(pf->dev, &pr.rule.rpool, nr, pr.ticket, diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c index b86759166b0..1f1d4899150 100644 --- a/sbin/pfctl/pfctl_parser.c +++ b/sbin/pfctl/pfctl_parser.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_parser.c,v 1.244 2009/04/15 05:07:02 david Exp $ */ +/* $OpenBSD: pfctl_parser.c,v 1.245 2009/09/01 13:42:00 henning Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -643,14 +643,6 @@ print_src_node(struct pf_src_node *sn, int opts) sn->packets[0] + sn->packets[1], sn->bytes[0] + sn->bytes[1]); switch (sn->ruletype) { - case PF_NAT: - if (sn->rule.nr != -1) - printf(", nat rule %u", sn->rule.nr); - break; - case PF_RDR: - if (sn->rule.nr != -1) - printf(", rdr rule %u", sn->rule.nr); - break; case PF_PASS: case PF_MATCH: if (sn->rule.nr != -1) @@ -772,7 +764,7 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose) printf(" fastroute"); if (r->rt != PF_FASTROUTE) { printf(" "); - print_pool(&r->rpool, 0, 0, r->af, PF_PASS); + print_pool(&r->rdr, 0, 0, r->af, PF_PASS); } } if (r->af) { @@ -1037,11 +1029,15 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose) printf(" port %u", ntohs(r->divert.port)); } } - 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], - r->rpool.proxy_port[1], r->af, r->action); + if (!anchor_call[0] && !TAILQ_EMPTY(&r->nat.list)) { + printf (" nat-to "); + print_pool(&r->nat, r->nat.proxy_port[0], + r->nat.proxy_port[1], r->af, PF_NAT); + } + if (!r->rt && !anchor_call[0] && !TAILQ_EMPTY(&r->rdr.list)) { + printf (" rdr-to "); + print_pool(&r->rdr, r->rdr.proxy_port[0], + r->rdr.proxy_port[1], r->af, PF_RDR); } } diff --git a/sbin/pfctl/pfctl_parser.h b/sbin/pfctl/pfctl_parser.h index 758c576b4c4..8b7eca95a2d 100644 --- a/sbin/pfctl/pfctl_parser.h +++ b/sbin/pfctl/pfctl_parser.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_parser.h,v 1.88 2009/04/06 12:05:55 henning Exp $ */ +/* $OpenBSD: pfctl_parser.h,v 1.89 2009/09/01 13:42:00 henning Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -194,7 +194,7 @@ int pfctl_optimize_ruleset(struct pfctl *, struct pf_ruleset *); 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); +int pfctl_add_pool(struct pfctl *, struct pf_pool *, sa_family_t, int); void pfctl_move_pool(struct pf_pool *, struct pf_pool *); void pfctl_clear_pool(struct pf_pool *); |