summaryrefslogtreecommitdiff
path: root/usr.sbin/bgpd
diff options
context:
space:
mode:
authorSebastian Benoit <benno@cvs.openbsd.org>2018-09-08 15:25:28 +0000
committerSebastian Benoit <benno@cvs.openbsd.org>2018-09-08 15:25:28 +0000
commit234f346a5dd7cc1405bab8d7c5a8ffdce3c7ebd0 (patch)
tree2bc883cb1c9dfbb6b3cdf8ff71dcd252df1ebf91 /usr.sbin/bgpd
parentcd1ddc73d5739787eff3eca032ba0b800166f07a (diff)
implement or-longer filter op for prefix-sets. Allows one two write rules like
deny from any prefix-set mynetworks or-longer ok claudio, feature discussed with job and deraadt
Diffstat (limited to 'usr.sbin/bgpd')
-rw-r--r--usr.sbin/bgpd/bgpd.conf.519
-rw-r--r--usr.sbin/bgpd/bgpd.h6
-rw-r--r--usr.sbin/bgpd/parse.y27
-rw-r--r--usr.sbin/bgpd/printconf.c4
-rw-r--r--usr.sbin/bgpd/rde.h8
-rw-r--r--usr.sbin/bgpd/rde_filter.c7
-rw-r--r--usr.sbin/bgpd/rde_trie.c23
7 files changed, 65 insertions, 29 deletions
diff --git a/usr.sbin/bgpd/bgpd.conf.5 b/usr.sbin/bgpd/bgpd.conf.5
index 29e97d37b91..d7fa470ed85 100644
--- a/usr.sbin/bgpd/bgpd.conf.5
+++ b/usr.sbin/bgpd/bgpd.conf.5
@@ -1,4 +1,4 @@
-.\" $OpenBSD: bgpd.conf.5,v 1.174 2018/09/07 10:59:16 claudio Exp $
+.\" $OpenBSD: bgpd.conf.5,v 1.175 2018/09/08 15:25:27 benno Exp $
.\"
.\" Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
.\" Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -16,7 +16,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: September 7 2018 $
+.Dd $Mdocdate: September 8 2018 $
.Dt BGPD.CONF 5
.Os
.Sh NAME
@@ -291,12 +291,6 @@ Log received and sent updates.
.Pq Ic inet Ns | Ns Ic inet6
.Ic priority Ar number Op Ic set ...\&
.Xc
-.\" NOT IMPLEMENTED. DO WE WANT THIS?
-.\" .It Xo
-.\" .Ic network prefix-set
-.\" .Ar name
-.\" .Op Ic set ...\&
-.\" .Xc
Announce the specified network as belonging to our AS.
If set to
.Ic connected ,
@@ -1447,11 +1441,18 @@ is a shorthand for:
.Ic prefix Ar address Ns Li / Ns Ar len Ic prexiflen Ic >= Ar len
.Ed
.Pp
-.It Ic prefix-set Ar name
+.It Ic prefix-set Ar name Op Ic or-longer
This rule applies only to
.Em UPDATES
that match the given prefix-set
.Ar name .
+With
+.Ic or-longer ,
+the
+.Em UPDATES
+will match any prefix in the prefix-set where
+.Bd -literal -offset indent
+.Ic address Ns Li / Ns Ar len Ic prexiflen Ic >= Ar len
.Pp
.It Ic quick
If an
diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h
index 4297a670d3a..0f4d1d088b4 100644
--- a/usr.sbin/bgpd/bgpd.h
+++ b/usr.sbin/bgpd/bgpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.h,v 1.336 2018/09/07 11:50:32 benno Exp $ */
+/* $OpenBSD: bgpd.h,v 1.337 2018/09/08 15:25:27 benno Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -353,7 +353,7 @@ enum network_type {
NETWORK_CONNECTED,
NETWORK_RTLABEL,
NETWORK_MRTCLONE,
- NETWORK_PRIORITY
+ NETWORK_PRIORITY,
};
struct network_config {
@@ -679,6 +679,8 @@ struct filter_aslen {
#define PREFIXSET_FLAG_FILTER 0x01
#define PREFIXSET_FLAG_DIRTY 0x02 /* prefix-set changed at reload */
+#define PREFIXSET_FLAG_OPS 0x04 /* indiv. prefixes have prefixlenops */
+#define PREFIXSET_FLAG_LONGER 0x08 /* filter all prefixes with or-longer */
struct filter_prefixset {
int flags;
diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y
index 21fb38b57ca..7a9abf303fb 100644
--- a/usr.sbin/bgpd/parse.y
+++ b/usr.sbin/bgpd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.340 2018/09/08 12:29:19 claudio Exp $ */
+/* $OpenBSD: parse.y,v 1.341 2018/09/08 15:25:27 benno Exp $ */
/*
* Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -2104,7 +2104,8 @@ filter_elm : filter_prefix_h {
}
fmopts.m.nexthop.flags = FILTER_NEXTHOP_NEIGHBOR;
}
- | PREFIXSET STRING {
+ | PREFIXSET STRING prefixlenop {
+ struct prefixset *ps;
if (fmopts.prefix_l != NULL) {
yyerror("\"prefix\" already specified, cannot "
"be used with \"prefix-set\" in the same "
@@ -2117,7 +2118,8 @@ filter_elm : filter_prefix_h {
free($2);
YYERROR;
}
- if ((find_prefixset($2, conf->prefixsets)) == NULL) {
+ if ((ps = find_prefixset($2, conf->prefixsets))
+ == NULL) {
yyerror("prefix-set not defined");
free($2);
YYERROR;
@@ -2129,6 +2131,25 @@ filter_elm : filter_prefix_h {
free($2);
YYERROR;
}
+ if (!($3.op == OP_NONE ||
+ ($3.op == OP_RANGE &&
+ $3.len_min == -1 && $3.len_max == -1))) {
+ yyerror("prefix-sets can only use option "
+ "or-longer");
+ free($2);
+ YYERROR;
+ }
+ if ($3.op == OP_RANGE && ps->sflags & PREFIXSET_FLAG_OPS) {
+ yyerror("prefix-set %s contains prefixlen "
+ "operators and cannot be used in with a "
+ "or-longer filter", ps->name);
+ free($2);
+ YYERROR;
+ }
+ if ($3.op == OP_RANGE && $3.len_min == -1 &&
+ $3.len_min == -1)
+ fmopts.m.prefixset.flags |=
+ PREFIXSET_FLAG_LONGER;
fmopts.m.prefixset.flags |= PREFIXSET_FLAG_FILTER;
fmopts.m.prefixset.ps = NULL;
free($2);
diff --git a/usr.sbin/bgpd/printconf.c b/usr.sbin/bgpd/printconf.c
index d8b7cdde791..361ebed7c28 100644
--- a/usr.sbin/bgpd/printconf.c
+++ b/usr.sbin/bgpd/printconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: printconf.c,v 1.113 2018/09/08 09:33:54 claudio Exp $ */
+/* $OpenBSD: printconf.c,v 1.114 2018/09/08 15:25:27 benno Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -685,6 +685,8 @@ print_rule(struct peer *peer_l, struct filter_rule *r)
if (r->match.prefixset.flags & PREFIXSET_FLAG_FILTER)
printf("prefix-set \"%s\" ", r->match.prefixset.name);
+ if (r->match.prefixset.flags & PREFIXSET_FLAG_LONGER)
+ printf("or-longer ");
if (r->match.nexthop.flags) {
if (r->match.nexthop.flags == FILTER_NEXTHOP_NEIGHBOR)
diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h
index c67e7cf660f..2d699c2481d 100644
--- a/usr.sbin/bgpd/rde.h
+++ b/usr.sbin/bgpd/rde.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.h,v 1.188 2018/09/07 10:49:22 claudio Exp $ */
+/* $OpenBSD: rde.h,v 1.189 2018/09/08 15:25:27 benno Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and
@@ -581,10 +581,10 @@ int up_dump_mp_reach(u_char *, u_int16_t *, struct rde_peer *,
u_int8_t);
/* rde_trie.c */
-int trie_add(struct trie_head *, struct bgpd_addr *, u_int8_t,
- u_int8_t, u_int8_t);
+int trie_add(struct trie_head *, struct bgpd_addr *, u_int8_t, u_int8_t,
+ u_int8_t);
void trie_free(struct trie_head *);
-int trie_match(struct trie_head *, struct bgpd_addr *, u_int8_t);
+int trie_match(struct trie_head *, struct bgpd_addr *, u_int8_t, int);
void trie_dump(struct trie_head *);
int trie_equal(struct trie_head *, struct trie_head *);
diff --git a/usr.sbin/bgpd/rde_filter.c b/usr.sbin/bgpd/rde_filter.c
index 4705cef5a55..04d7f13ab94 100644
--- a/usr.sbin/bgpd/rde_filter.c
+++ b/usr.sbin/bgpd/rde_filter.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_filter.c,v 1.104 2018/09/07 16:45:23 benno Exp $ */
+/* $OpenBSD: rde_filter.c,v 1.105 2018/09/08 15:25:27 benno Exp $ */
/*
* Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
@@ -478,7 +478,6 @@ rde_filter_match(struct filter_rule *f, struct rde_peer *peer,
}
/*
- * XXX must be second to last because we unconditionally return here.
* prefixset and prefix filter rules are mutual exclusive
*/
if (f->match.prefixset.flags != 0) {
@@ -487,9 +486,9 @@ rde_filter_match(struct filter_rule *f, struct rde_peer *peer,
pt_getaddr(p->re->prefix, prefix);
plen = p->re->prefix->prefixlen;
-
if (f->match.prefixset.ps == NULL ||
- !trie_match(&f->match.prefixset.ps->th, prefix, plen))
+ !trie_match(&f->match.prefixset.ps->th, prefix, plen,
+ (f->match.prefixset.flags & PREFIXSET_FLAG_LONGER)))
return (0);
} else if (f->match.prefix.addr.aid != 0)
return (rde_prefix_match(&f->match.prefix, p));
diff --git a/usr.sbin/bgpd/rde_trie.c b/usr.sbin/bgpd/rde_trie.c
index 31d9161bd0b..cbbc5060b97 100644
--- a/usr.sbin/bgpd/rde_trie.c
+++ b/usr.sbin/bgpd/rde_trie.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_trie.c,v 1.3 2018/09/07 20:26:30 claudio Exp $ */
+/* $OpenBSD: rde_trie.c,v 1.4 2018/09/08 15:25:27 benno Exp $ */
/*
* Copyright (c) 2018 Claudio Jeker <claudio@openbsd.org>
@@ -397,7 +397,8 @@ trie_free(struct trie_head *th)
}
static int
-trie_match_v4(struct trie_head *th, struct in_addr *prefix, u_int8_t plen)
+trie_match_v4(struct trie_head *th, struct in_addr *prefix, u_int8_t plen,
+ int orlonger)
{
struct tentry_v4 *n;
@@ -417,6 +418,10 @@ trie_match_v4(struct trie_head *th, struct in_addr *prefix, u_int8_t plen)
if (n->addr.s_addr != mp.s_addr)
break; /* off path, no match possible */
+ /* the match covers all larger prefixlens */
+ if (n->node && orlonger)
+ return 1;
+
/* plen is from 1 - 32 but the bitmask starts with 0 */
if (n->node && inet4isset(&n->plenmask, plen - 1))
return 1; /* prefixlen allowed, match */
@@ -433,7 +438,8 @@ trie_match_v4(struct trie_head *th, struct in_addr *prefix, u_int8_t plen)
}
static int
-trie_match_v6(struct trie_head *th, struct in6_addr *prefix, u_int8_t plen)
+trie_match_v6(struct trie_head *th, struct in6_addr *prefix, u_int8_t plen,
+ int orlonger)
{
struct tentry_v6 *n;
@@ -453,6 +459,10 @@ trie_match_v6(struct trie_head *th, struct in6_addr *prefix, u_int8_t plen)
if (memcmp(&n->addr, &mp, sizeof(mp)) != 0)
break; /* off path, no match possible */
+ /* the match covers all larger prefixlens */
+ if (n->node && orlonger)
+ return 1;
+
/* plen is from 1 - 128 but the bitmask starts with 0 */
if (n->node && inet6isset(&n->plenmask, plen - 1))
return 1; /* prefixlen allowed, match */
@@ -469,13 +479,14 @@ trie_match_v6(struct trie_head *th, struct in6_addr *prefix, u_int8_t plen)
/* find first matching element in the trie for prefix "prefix/plen" */
int
-trie_match(struct trie_head *th, struct bgpd_addr *prefix, u_int8_t plen)
+trie_match(struct trie_head *th, struct bgpd_addr *prefix, u_int8_t plen,
+ int orlonger)
{
switch (prefix->aid) {
case AID_INET:
- return trie_match_v4(th, &prefix->v4, plen);
+ return trie_match_v4(th, &prefix->v4, plen, orlonger);
case AID_INET6:
- return trie_match_v6(th, &prefix->v6, plen);
+ return trie_match_v6(th, &prefix->v6, plen, orlonger);
default:
/* anything else is no match */
return 0;