summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2006-02-02 14:06:06 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2006-02-02 14:06:06 +0000
commit77d306336665df0202684ea013b56ccab67d48cb (patch)
tree652858e3d80d9536217068cbab5d9e8c1e7be628 /usr.sbin
parente48d9cd4078b2e4ea1d1d65efef627a69574921f (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@
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/bgpd/bgpd.h3
-rw-r--r--usr.sbin/bgpd/parse.y10
-rw-r--r--usr.sbin/bgpd/printconf.c7
-rw-r--r--usr.sbin/bgpd/rde.c4
-rw-r--r--usr.sbin/bgpd/rde.h4
-rw-r--r--usr.sbin/bgpd/rde_filter.c75
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) {