summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenning Brauer <henning@cvs.openbsd.org>2004-12-10 22:13:27 +0000
committerHenning Brauer <henning@cvs.openbsd.org>2004-12-10 22:13:27 +0000
commit3c92a3c63a57c0f35ca1a461f262a39d2b92e443 (patch)
tree306d6f9e47e9d9078dda54a5ceafc5ff71a28214
parent12c009627283dd670ebdb223b04a23b49fb2e1b0 (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.y20
-rw-r--r--sbin/pfctl/pf_print_state.c5
-rw-r--r--sys/net/pf.c45
-rw-r--r--sys/net/pf_ioctl.c48
-rw-r--r--sys/net/pfvar.h10
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,