diff options
author | Henning Brauer <henning@cvs.openbsd.org> | 2004-12-10 22:13:27 +0000 |
---|---|---|
committer | Henning Brauer <henning@cvs.openbsd.org> | 2004-12-10 22:13:27 +0000 |
commit | 3c92a3c63a57c0f35ca1a461f262a39d2b92e443 (patch) | |
tree | 306d6f9e47e9d9078dda54a5ceafc5ff71a28214 | |
parent | 12c009627283dd670ebdb223b04a23b49fb2e1b0 (diff) |
allow pf to filter on route labels
pass in from route dtag keep state queue reallyslow
tested by Gabriel Kihlman <gk@stacken.kth.se> and
Michael Knudsen <e@molioner.dk> and ryan
ok ryan
-rw-r--r-- | sbin/pfctl/parse.y | 20 | ||||
-rw-r--r-- | sbin/pfctl/pf_print_state.c | 5 | ||||
-rw-r--r-- | sys/net/pf.c | 45 | ||||
-rw-r--r-- | sys/net/pf_ioctl.c | 48 | ||||
-rw-r--r-- | sys/net/pfvar.h | 10 |
5 files changed, 120 insertions, 8 deletions
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y index 7b9da3f0026..ddce9fa4012 100644 --- a/sbin/pfctl/parse.y +++ b/sbin/pfctl/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.468 2004/12/08 01:27:23 mcbride Exp $ */ +/* $OpenBSD: parse.y,v 1.469 2004/12/10 22:13:26 henning Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -406,7 +406,7 @@ typedef struct { %token LOAD %token STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE %token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH -%token TAGGED TAG IFBOUND GRBOUND FLOATING STATEPOLICY +%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 @@ -2255,6 +2255,21 @@ host : STRING { $$->next = NULL; $$->tail = $$; } + | ROUTE STRING { + $$ = calloc(1, sizeof(struct node_host)); + if ($$ == NULL) + 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); + YYERROR; + } + $$->next = NULL; + $$->tail = $$; + } ; number : STRING { @@ -4545,6 +4560,7 @@ lookup(char *s) { "return-icmp6", RETURNICMP6}, { "return-rst", RETURNRST}, { "round-robin", ROUNDROBIN}, + { "route", ROUTE}, { "route-to", ROUTETO}, { "rule", RULE}, { "scrub", SCRUB}, diff --git a/sbin/pfctl/pf_print_state.c b/sbin/pfctl/pf_print_state.c index b7cf5ca9ac5..a41e9e5f887 100644 --- a/sbin/pfctl/pf_print_state.c +++ b/sbin/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 @@ -96,6 +96,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/sys/net/pf.c b/sys/net/pf.c index 887b9405263..d08a19f09ec 100644 --- a/sys/net/pf.c +++ b/sys/net/pf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf.c,v 1.471 2004/12/07 18:02:03 mcbride Exp $ */ +/* $OpenBSD: pf.c,v 1.472 2004/12/10 22:13:25 henning Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -5118,6 +5118,49 @@ pf_routable(struct pf_addr *addr, sa_family_t af) return (0); } +int +pf_rtlabel_match(struct pf_addr *addr, sa_family_t af, struct pf_addr_wrap *aw) +{ + struct sockaddr_in *dst; +#ifdef INET6 + struct sockaddr_in6 *dst6; + struct route_in6 ro; +#else + struct route ro; +#endif + int ret = 0; + + bzero(&ro, sizeof(ro)); + switch (af) { + case AF_INET: + dst = satosin(&ro.ro_dst); + dst->sin_family = AF_INET; + dst->sin_len = sizeof(*dst); + dst->sin_addr = addr->v4; + break; +#ifdef INET6 + case AF_INET6: + dst6 = (struct sockaddr_in6 *)&ro.ro_dst; + dst6->sin6_family = AF_INET6; + dst6->sin6_len = sizeof(*dst6); + dst6->sin6_addr = addr->v6; + break; +#endif /* INET6 */ + default: + return (0); + } + + rtalloc_noclone((struct route *)&ro, NO_CLONING); + + if (ro.ro_rt != NULL) { + if (ro.ro_rt->rt_labelid == aw->v.rtlabel) + ret = 1; + RTFREE(ro.ro_rt); + } + + return (ret); +} + #ifdef INET void pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp, diff --git a/sys/net/pf_ioctl.c b/sys/net/pf_ioctl.c index cbfbdb1992e..3003f0482b6 100644 --- a/sys/net/pf_ioctl.c +++ b/sys/net/pf_ioctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_ioctl.c,v 1.135 2004/12/07 18:02:04 mcbride Exp $ */ +/* $OpenBSD: pf_ioctl.c,v 1.136 2004/12/10 22:13:26 henning Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -121,6 +121,9 @@ TAILQ_HEAD(pf_tags, pf_tagname) pf_tags = TAILQ_HEAD_INITIALIZER(pf_tags), static u_int16_t tagname2tag(struct pf_tags *, char *); static void tag2tagname(struct pf_tags *, u_int16_t, char *); static void tag_unref(struct pf_tags *, u_int16_t); +int pf_rtlabel_add(struct pf_addr_wrap *); +void pf_rtlabel_remove(struct pf_addr_wrap *); +void pf_rtlabel_copyout(struct pf_addr_wrap *); #define DPFPRINTF(n, x) if (pf_status.debug >= (n)) printf x @@ -593,6 +596,8 @@ pf_rm_rule(struct pf_rulequeue *rulequeue, struct pf_rule *rule) pf_qid_unref(rule->pqid); pf_qid_unref(rule->qid); #endif + pf_rtlabel_remove(&rule->src.addr); + pf_rtlabel_remove(&rule->dst.addr); pfi_dynaddr_remove(&rule->src.addr); pfi_dynaddr_remove(&rule->dst.addr); if (rulequeue == NULL) { @@ -702,6 +707,37 @@ pf_tag_unref(u_int16_t tag) return (tag_unref(&pf_tags, tag)); } +int +pf_rtlabel_add(struct pf_addr_wrap *a) +{ + if (a->type == PF_ADDR_RTLABEL && + (a->v.rtlabel = rtlabel_name2id(a->v.rtlabelname)) == 0) + return (-1); + return (0); +} + +void +pf_rtlabel_remove(struct pf_addr_wrap *a) +{ + if (a->type == PF_ADDR_RTLABEL) + rtlabel_unref(a->v.rtlabel); +} + +void +pf_rtlabel_copyout(struct pf_addr_wrap *a) +{ + const char *name; + + if (a->type == PF_ADDR_RTLABEL && a->v.rtlabel) { + if ((name = rtlabel_id2name(a->v.rtlabel)) == NULL) + strlcpy(a->v.rtlabelname, "?", + sizeof(a->v.rtlabelname)); + else + strlcpy(a->v.rtlabelname, name, + sizeof(a->v.rtlabelname)); + } +} + #ifdef ALTQ u_int32_t pf_qname2qid(char *qname) @@ -1168,6 +1204,9 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) error = EBUSY; if (rule->rt && !rule->direction) error = EINVAL; + if (pf_rtlabel_add(&rule->src.addr) || + pf_rtlabel_add(&rule->dst.addr)) + error = EBUSY; if (pfi_dynaddr_setup(&rule->src.addr, rule->af)) error = EINVAL; if (pfi_dynaddr_setup(&rule->dst.addr, rule->af)) @@ -1273,6 +1312,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) pfi_dynaddr_copyout(&pr->rule.dst.addr); pf_tbladdr_copyout(&pr->rule.src.addr); pf_tbladdr_copyout(&pr->rule.dst.addr); + pf_rtlabel_copyout(&pr->rule.src.addr); + pf_rtlabel_copyout(&pr->rule.dst.addr); for (i = 0; i < PF_SKIP_COUNT; ++i) if (rule->skip[i].ptr == NULL) pr->rule.skip[i].nr = -1; @@ -1384,9 +1425,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) if ((newrule->match_tag = pf_tagname2tag( newrule->match_tagname)) == 0) error = EBUSY; - if (newrule->rt && !newrule->direction) error = EINVAL; + if (pf_rtlabel_add(&newrule->src.addr) || + pf_rtlabel_add(&newrule->dst.addr)) + error = EBUSY; if (pfi_dynaddr_setup(&newrule->src.addr, newrule->af)) error = EINVAL; if (pfi_dynaddr_setup(&newrule->dst.addr, newrule->af)) @@ -2058,6 +2101,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) bcopy(pa, &pp->addr, sizeof(struct pf_pooladdr)); pfi_dynaddr_copyout(&pp->addr.addr); pf_tbladdr_copyout(&pp->addr.addr); + pf_rtlabel_copyout(&pp->addr.addr); break; } diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index 32718dda6c8..60cc689ebc1 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pfvar.h,v 1.208 2004/12/07 10:33:41 dhartmei Exp $ */ +/* $OpenBSD: pfvar.h,v 1.209 2004/12/10 22:13:26 henning Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -39,6 +39,7 @@ #include <sys/tree.h> #include <net/radix.h> +#include <net/route.h> #include <netinet/ip_ipsp.h> #include <netinet/tcp_fsm.h> @@ -77,7 +78,7 @@ enum { PF_LIMIT_STATES, PF_LIMIT_SRC_NODES, PF_LIMIT_FRAGS, PF_LIMIT_MAX }; enum { PF_POOL_NONE, PF_POOL_BITMASK, PF_POOL_RANDOM, PF_POOL_SRCHASH, PF_POOL_ROUNDROBIN }; enum { PF_ADDR_ADDRMASK, PF_ADDR_NOROUTE, PF_ADDR_DYNIFTL, - PF_ADDR_TABLE }; + PF_ADDR_TABLE, PF_ADDR_RTLABEL }; #define PF_POOL_TYPEMASK 0x0f #define PF_POOL_STICKYADDR 0x20 #define PF_WSCALE_FLAG 0x80 @@ -114,6 +115,8 @@ struct pf_addr_wrap { } a; char ifname[IFNAMSIZ]; char tblname[PF_TABLE_NAME_SIZE]; + char rtlabelname[RTLABEL_LEN]; + u_int32_t rtlabel; } v; union { struct pfi_dynaddr *dyn; @@ -279,6 +282,8 @@ struct pfi_dynaddr { ( \ (((aw)->type == PF_ADDR_NOROUTE && \ pf_routable((x), (af))) || \ + ((aw)->type == PF_ADDR_RTLABEL && \ + !pf_rtlabel_match((x), (af), (aw))) || \ ((aw)->type == PF_ADDR_TABLE && \ !pfr_match_addr((aw)->p.tbl, (x), (af))) || \ ((aw)->type == PF_ADDR_DYNIFTL && \ @@ -1428,6 +1433,7 @@ u_int32_t pf_state_expires(const struct pf_state *); void pf_purge_expired_fragments(void); int pf_routable(struct pf_addr *addr, sa_family_t af); +int pf_rtlabel_match(struct pf_addr *, sa_family_t, struct pf_addr_wrap *); void pfr_initialize(void); int pfr_match_addr(struct pfr_ktable *, struct pf_addr *, sa_family_t); void pfr_update_stats(struct pfr_ktable *, struct pf_addr *, sa_family_t, |