diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2006-02-02 14:06:06 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2006-02-02 14:06:06 +0000 |
commit | 77d306336665df0202684ea013b56ccab67d48cb (patch) | |
tree | 652858e3d80d9536217068cbab5d9e8c1e7be628 | |
parent | e48d9cd4078b2e4ea1d1d65efef627a69574921f (diff) |
Implement new special community "neighbor-as". neighbor-as is expanded on
the fly to the remote AS of the current neighbor. This can be used to
simplify rulesets in a dramatic way -- going from a script based nightmare
down to a handfull rules. jajajaja henning@
-rw-r--r-- | usr.sbin/bgpd/bgpd.h | 3 | ||||
-rw-r--r-- | usr.sbin/bgpd/parse.y | 10 | ||||
-rw-r--r-- | usr.sbin/bgpd/printconf.c | 7 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde.c | 4 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde.h | 4 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_filter.c | 75 |
6 files changed, 82 insertions, 21 deletions
diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h index 60ad43caa99..4e91db8ae32 100644 --- a/usr.sbin/bgpd/bgpd.h +++ b/usr.sbin/bgpd/bgpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bgpd.h,v 1.189 2006/01/24 15:28:02 henning Exp $ */ +/* $OpenBSD: bgpd.h,v 1.190 2006/02/02 14:06:05 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -532,6 +532,7 @@ struct filter_peers { /* special community type */ #define COMMUNITY_ERROR -1 #define COMMUNITY_ANY -2 +#define COMMUNITY_NEIGHBOR_AS -3 #define COMMUNITY_WELLKNOWN 0xffff #define COMMUNITY_NO_EXPORT 0xff01 #define COMMUNITY_NO_ADVERTISE 0xff02 diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y index b0d61b5260e..504b650e0d2 100644 --- a/usr.sbin/bgpd/parse.y +++ b/usr.sbin/bgpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.178 2006/01/07 14:50:28 claudio Exp $ */ +/* $OpenBSD: parse.y,v 1.179 2006/02/02 14:06:05 claudio Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -1429,6 +1429,12 @@ filter_set_opt : LOCALPREF number { YYERROR; } free($2); + /* Don't allow setting of any match */ + if ($$->action.community.as == COMMUNITY_ANY || + $$->action.community.type == COMMUNITY_ANY) { + yyerror("'*' is not allowed in set community"); + YYERROR; + } /* Don't allow setting of unknown well-known types */ if ($$->action.community.as == COMMUNITY_WELLKNOWN) { switch ($$->action.community.type) { @@ -2013,6 +2019,8 @@ getcommunity(char *s) if (strcmp(s, "*") == 0) return (COMMUNITY_ANY); + if (strcmp(s, "neighbor-as") == 0) + return (COMMUNITY_NEIGHBOR_AS); if (atoul(s, &ulval) == -1) { yyerror("\"%s\" is not a number", s); return (COMMUNITY_ERROR); diff --git a/usr.sbin/bgpd/printconf.c b/usr.sbin/bgpd/printconf.c index e3857bbef38..47c4a5fce11 100644 --- a/usr.sbin/bgpd/printconf.c +++ b/usr.sbin/bgpd/printconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: printconf.c,v 1.50 2005/11/01 10:58:29 claudio Exp $ */ +/* $OpenBSD: printconf.c,v 1.51 2006/02/02 14:06:05 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -417,13 +417,18 @@ print_rule(struct peer *peer_l, struct filter_rule *r) } if (r->match.community.as != 0) { + printf("community "); if (r->match.community.as == COMMUNITY_ANY) printf("*:"); + else if (r->match.community.as == COMMUNITY_NEIGHBOR_AS) + printf("neighbor-as:"); else printf("%d:", r->match.community.as); if (r->match.community.type == COMMUNITY_ANY) printf("* "); + else if (r->match.community.type == COMMUNITY_NEIGHBOR_AS) + printf("neighbor-as "); else printf("%d ", r->match.community.type); } diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c index cfcd1150e0c..d2c0a558ec7 100644 --- a/usr.sbin/bgpd/rde.c +++ b/usr.sbin/bgpd/rde.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.c,v 1.198 2006/01/24 14:48:47 claudio Exp $ */ +/* $OpenBSD: rde.c,v 1.199 2006/02/02 14:06:05 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -2268,7 +2268,7 @@ network_add(struct network_config *nc, int flagstatic) else p = &peerdynamic; - rde_apply_set(asp, &nc->attrset, nc->prefix.af, p, DIR_IN); + rde_apply_set(asp, &nc->attrset, nc->prefix.af, p, p); path_update(p, asp, &nc->prefix, nc->prefixlen, F_ORIGINAL); path_update(p, asp, &nc->prefix, nc->prefixlen, F_LOCAL); diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h index 724bcdf54cc..749be49c67f 100644 --- a/usr.sbin/bgpd/rde.h +++ b/usr.sbin/bgpd/rde.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.h,v 1.87 2006/01/24 14:14:04 claudio Exp $ */ +/* $OpenBSD: rde.h,v 1.88 2006/02/02 14:06:05 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and @@ -370,7 +370,7 @@ enum filter_actions rde_filter(struct rde_aspath **, struct filter_head *, struct bgpd_addr *, u_int8_t, struct rde_peer *, enum directions); void rde_apply_set(struct rde_aspath *, struct filter_set_head *, - sa_family_t, struct rde_peer *, enum directions); + sa_family_t, struct rde_peer *, struct rde_peer *); int rde_filter_community(struct rde_aspath *, int, int); int rde_filter_equal(struct filter_head *, struct filter_head *, struct rde_peer *, enum directions); diff --git a/usr.sbin/bgpd/rde_filter.c b/usr.sbin/bgpd/rde_filter.c index 7e47f85084e..9917a2beec1 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.42 2006/01/24 14:14:04 claudio Exp $ */ +/* $OpenBSD: rde_filter.c,v 1.43 2006/02/02 14:06:05 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 bgpd_addr *, u_int8_t, struct rde_peer *); int filterset_equal(struct filter_set_head *, struct filter_set_head *); enum filter_actions @@ -49,13 +49,13 @@ rde_filter(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)) { + if (rde_filter_match(f, asp, prefix, prefixlen, peer)) { if (asp != NULL && new != NULL) { /* asp may get modified so create a copy */ if (*new == NULL) *new = path_copy(asp); rde_apply_set(*new, &f->set, prefix->af, - from, dir); + from, peer); } if (f->action != ACTION_NONE) action = f->action; @@ -68,11 +68,12 @@ rde_filter(struct rde_aspath **new, struct filter_head *rules, void rde_apply_set(struct rde_aspath *asp, struct filter_set_head *sh, - sa_family_t af, struct rde_peer *from, enum directions dir) + sa_family_t af, struct rde_peer *from, struct rde_peer *peer) { struct filter_set *set; struct aspath *new; - u_int16_t as; + int as, type; + u_int16_t prep_as; u_int8_t prepend; if (asp == NULL) @@ -146,9 +147,9 @@ rde_apply_set(struct rde_aspath *asp, struct filter_set_head *sh, case ACTION_SET_PREPEND_PEER: if (from == NULL) break; - as = from->conf.remote_as; + prep_as = from->conf.remote_as; prepend = set->action.prepend; - new = aspath_prepend(asp->aspath, as, prepend); + new = aspath_prepend(asp->aspath, prep_as, prepend); aspath_put(asp->aspath); asp->aspath = new; break; @@ -160,8 +161,31 @@ rde_apply_set(struct rde_aspath *asp, struct filter_set_head *sh, af); break; case ACTION_SET_COMMUNITY: - community_set(asp, set->action.community.as, - set->action.community.type); + switch (set->action.community.as) { + case COMMUNITY_ERROR: + case COMMUNITY_ANY: + fatalx("rde_apply_set bad community string"); + case COMMUNITY_NEIGHBOR_AS: + as = peer->conf.remote_as; + break; + default: + as = set->action.community.as; + break; + } + + switch (set->action.community.type) { + case COMMUNITY_ERROR: + case COMMUNITY_ANY: + fatalx("rde_apply_set bad community string"); + case COMMUNITY_NEIGHBOR_AS: + type = peer->conf.remote_as; + break; + default: + type = set->action.community.as; + break; + } + + community_set(asp, as, type); break; case ACTION_PFTABLE: /* convert pftable name to an id */ @@ -189,18 +213,41 @@ 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 bgpd_addr *prefix, u_int8_t plen, struct rde_peer *peer) { + int as, type; if (asp != NULL && f->match.as.type != AS_NONE) if (aspath_match(asp->aspath, f->match.as.type, f->match.as.as) == 0) return (0); - if (asp != NULL && f->match.community.as != 0) - if (rde_filter_community(asp, f->match.community.as, - f->match.community.type) == 0) + if (asp != NULL && f->match.community.as != 0) { + switch (f->match.community.as) { + case COMMUNITY_ERROR: + fatalx("rde_apply_set bad community string"); + case COMMUNITY_NEIGHBOR_AS: + as = peer->conf.remote_as; + break; + default: + as = f->match.community.as; + break; + } + + switch (f->match.community.type) { + case COMMUNITY_ERROR: + fatalx("rde_apply_set bad community string"); + case COMMUNITY_NEIGHBOR_AS: + type = peer->conf.remote_as; + break; + default: + type = f->match.community.as; + break; + } + + if (rde_filter_community(asp, as, type) == 0) return (0); + } if (f->match.prefix.addr.af != 0 && f->match.prefix.addr.af == prefix->af) { |