diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2012-11-13 09:47:21 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2012-11-13 09:47:21 +0000 |
commit | bb8c0be811b76c6ab88d9ab6f84dfd86fefb3dbb (patch) | |
tree | a8f0d48b7ce316fd0743d13e0b77734b4a78b42d | |
parent | 006fb6cf8bdb3bff5e028c1acaa88a19108a3c62 (diff) |
Allow filtering based on the NEXTHOP attribute. This allows to build rules
like: allow from any nexthop neighbor (to allow only prefixes that use the
routers IP address as nexthop). Lots of testing, input and OK florian@
-rw-r--r-- | usr.sbin/bgpd/bgpd.conf.5 | 17 | ||||
-rw-r--r-- | usr.sbin/bgpd/bgpd.h | 10 | ||||
-rw-r--r-- | usr.sbin/bgpd/parse.y | 22 | ||||
-rw-r--r-- | usr.sbin/bgpd/printconf.c | 9 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_filter.c | 37 |
5 files changed, 86 insertions, 9 deletions
diff --git a/usr.sbin/bgpd/bgpd.conf.5 b/usr.sbin/bgpd/bgpd.conf.5 index bc689c36ab7..10fcf658a39 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.121 2012/08/24 17:04:06 jmc Exp $ +.\" $OpenBSD: bgpd.conf.5,v 1.122 2012/11/13 09:47:20 claudio 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: August 24 2012 $ +.Dd $Mdocdate: November 13 2012 $ .Dt BGPD.CONF 5 .Os .Sh NAME @@ -1175,6 +1175,19 @@ is repeated more than .Ar len times. .Pp +.It Ic nexthop Ar address +This rule applies only to +.Em UPDATES +where the nexthop is equal to +.Ar address. +The +.Ar address +can be set to +.Em neighbor +in which case the nexthop is compared against the address of the neighbor. +Nexthop filtering is not supported on locally announced networks and one must +take into consideration previous rules overwriting nexthops. +.Pp .It Xo .Ic prefix .Ar address Ns Li / Ns Ar len diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h index 370b62ab320..a412a641531 100644 --- a/usr.sbin/bgpd/bgpd.h +++ b/usr.sbin/bgpd/bgpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bgpd.h,v 1.273 2012/09/18 10:10:00 claudio Exp $ */ +/* $OpenBSD: bgpd.h,v 1.274 2012/11/13 09:47:20 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -749,6 +749,13 @@ struct filter_prefix { u_int8_t len; }; +struct filter_nexthop { + struct bgpd_addr addr; + u_int8_t flags; +#define FILTER_NEXTHOP_ADDR 1 +#define FILTER_NEXTHOP_NEIGHBOR 2 +}; + struct filter_prefixlen { enum comp_ops op; u_int8_t aid; @@ -759,6 +766,7 @@ struct filter_prefixlen { struct filter_match { struct filter_prefix prefix; struct filter_prefixlen prefixlen; + struct filter_nexthop nexthop; struct filter_as as; struct filter_aslen aslen; struct filter_community community; diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y index 1099ef26833..460f016201a 100644 --- a/usr.sbin/bgpd/parse.y +++ b/usr.sbin/bgpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.264 2012/09/23 09:39:17 claudio Exp $ */ +/* $OpenBSD: parse.y,v 1.265 2012/11/13 09:47:20 claudio Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -1700,6 +1700,26 @@ filter_elm : filter_prefix_h { } fmopts.aid = AID_INET6; } + | NEXTHOP address { + if (fmopts.m.nexthop.flags) { + yyerror("nexthop already specified"); + YYERROR; + } + if (fmopts.aid && fmopts.aid != $2.aid) { + yyerror("nexthop address family doesn't match " + "rule address family"); + YYERROR; + } + fmopts.m.nexthop.addr = $2; + fmopts.m.nexthop.flags = FILTER_NEXTHOP_ADDR; + } + | NEXTHOP NEIGHBOR { + if (fmopts.m.nexthop.flags) { + yyerror("nexthop already specified"); + YYERROR; + } + fmopts.m.nexthop.flags = FILTER_NEXTHOP_NEIGHBOR; + } ; prefixlenop : unaryop NUMBER { diff --git a/usr.sbin/bgpd/printconf.c b/usr.sbin/bgpd/printconf.c index 803f83d9d34..ca1071872b9 100644 --- a/usr.sbin/bgpd/printconf.c +++ b/usr.sbin/bgpd/printconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: printconf.c,v 1.88 2012/09/23 09:39:18 claudio Exp $ */ +/* $OpenBSD: printconf.c,v 1.89 2012/11/13 09:47:20 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -561,6 +561,13 @@ print_rule(struct peer *peer_l, struct filter_rule *r) } } + if (r->match.nexthop.flags) { + if (r->match.nexthop.flags == FILTER_NEXTHOP_NEIGHBOR) + printf("nexthop neighbor "); + else + printf("nexthop %s ", log_addr(&r->match.nexthop.addr)); + } + if (r->match.as.type) { if (r->match.as.type == AS_ALL) printf("AS %s ", log_as(r->match.as.as)); diff --git a/usr.sbin/bgpd/rde_filter.c b/usr.sbin/bgpd/rde_filter.c index d2f630155c4..f38284de83f 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.67 2011/09/20 21:19:06 claudio Exp $ */ +/* $OpenBSD: rde_filter.c,v 1.68 2012/11/13 09:47:20 claudio Exp $ */ /* * Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> @@ -26,7 +26,7 @@ #include "rde.h" int rde_filter_match(struct filter_rule *, struct rde_aspath *, - struct bgpd_addr *, u_int8_t, struct rde_peer *); + struct bgpd_addr *, u_int8_t, struct rde_peer *, struct rde_peer *); int filterset_equal(struct filter_set_head *, struct filter_set_head *); enum filter_actions @@ -58,7 +58,7 @@ rde_filter(u_int16_t ribid, struct rde_aspath **new, struct filter_head *rules, if (f->peer.peerid != 0 && f->peer.peerid != peer->conf.id) continue; - if (rde_filter_match(f, asp, prefix, prefixlen, peer)) { + if (rde_filter_match(f, asp, prefix, prefixlen, peer, from)) { if (asp != NULL && new != NULL) { /* asp may get modified so create a copy */ if (*new == NULL) { @@ -267,7 +267,8 @@ rde_apply_set(struct rde_aspath *asp, struct filter_set_head *sh, int rde_filter_match(struct filter_rule *f, struct rde_aspath *asp, - struct bgpd_addr *prefix, u_int8_t plen, struct rde_peer *peer) + struct bgpd_addr *prefix, u_int8_t plen, struct rde_peer *peer, + struct rde_peer *from) { u_int32_t pas; int cas, type; @@ -384,6 +385,34 @@ rde_filter_match(struct filter_rule *f, struct rde_aspath *asp, } /* NOTREACHED */ } + if (f->match.nexthop.flags != 0) { + struct bgpd_addr *nexthop, *cmpaddr; + if (asp->nexthop == NULL) + /* no nexthop, skip */ + return (0); + nexthop = &asp->nexthop->exit_nexthop; + if (f->match.nexthop.flags == FILTER_NEXTHOP_ADDR) + cmpaddr = &f->match.nexthop.addr; + else + cmpaddr = &from->remote_addr; + if (cmpaddr->aid != nexthop->aid) + /* don't use IPv4 rules for IPv6 and vice versa */ + return (0); + + switch (cmpaddr->aid) { + case AID_INET: + if (cmpaddr->v4.s_addr != nexthop->v4.s_addr) + return (0); + break; + case AID_INET6: + if (memcmp(&cmpaddr->v6, &nexthop->v6, + sizeof(struct in6_addr))) + return (0); + break; + default: + fatalx("King Bula lost in address space"); + } + } /* matched somewhen or is anymatch rule */ return (1); |