summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorclaudio <claudio@openbsd.org>2006-02-09 21:05:09 +0000
committerclaudio <claudio@openbsd.org>2006-02-09 21:05:09 +0000
commitaaa4f5df6530f0afa16fd1246cbbc555a65dd08c (patch)
treea2aab4db46e05f8bec3a61b7b3661fb3e517fa26
parentWhen comparing community type, cast to u_int16_t. The same is done for the (diff)
downloadwireguard-openbsd-aaa4f5df6530f0afa16fd1246cbbc555a65dd08c.tar.xz
wireguard-openbsd-aaa4f5df6530f0afa16fd1246cbbc555a65dd08c.zip
Implement "set community delete 65001:*" and friends. This will remove
communities from the path attributes. Useful to make sure that the ones you set later are set by a (evil) peer. OK henning@
-rw-r--r--usr.sbin/bgpd/bgpd.h4
-rw-r--r--usr.sbin/bgpd/parse.y32
-rw-r--r--usr.sbin/bgpd/printconf.c6
-rw-r--r--usr.sbin/bgpd/rde.h3
-rw-r--r--usr.sbin/bgpd/rde_attr.c64
-rw-r--r--usr.sbin/bgpd/rde_filter.c30
6 files changed, 123 insertions, 16 deletions
diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h
index 4e91db8ae32..7967d837e34 100644
--- a/usr.sbin/bgpd/bgpd.h
+++ b/usr.sbin/bgpd/bgpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.h,v 1.190 2006/02/02 14:06:05 claudio Exp $ */
+/* $OpenBSD: bgpd.h,v 1.191 2006/02/09 21:05:09 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -589,6 +589,7 @@ enum action_types {
ACTION_SET_NEXTHOP_BLACKHOLE,
ACTION_SET_NEXTHOP_NOMODIFY,
ACTION_SET_COMMUNITY,
+ ACTION_DEL_COMMUNITY,
ACTION_PFTABLE,
ACTION_PFTABLE_ID,
ACTION_RTLABEL,
@@ -609,6 +610,7 @@ static const char * const filterset_names[] = {
"nexthop",
"nexthop",
"community",
+ "community delete",
"pftable",
"pftable",
"rtlabel",
diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y
index 504b650e0d2..aa3f8bf1fb0 100644
--- a/usr.sbin/bgpd/parse.y
+++ b/usr.sbin/bgpd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.179 2006/02/02 14:06:05 claudio Exp $ */
+/* $OpenBSD: parse.y,v 1.180 2006/02/09 21:05:09 claudio Exp $ */
/*
* Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -158,7 +158,7 @@ typedef struct {
%token QUICK
%token FROM TO ANY
%token CONNECTED STATIC
-%token PREFIX PREFIXLEN SOURCEAS TRANSITAS COMMUNITY
+%token PREFIX PREFIXLEN SOURCEAS TRANSITAS COMMUNITY DELETE
%token SET LOCALPREF MED METRIC NEXTHOP REJECT BLACKHOLE NOMODIFY
%token PREPEND_SELF PREPEND_PEER PFTABLE WEIGHT RTLABEL
%token ERROR
@@ -170,7 +170,7 @@ typedef struct {
%type <v.string> string
%type <v.addr> address
%type <v.prefix> prefix addrspec
-%type <v.u8> action quick direction
+%type <v.u8> action quick direction delete
%type <v.filter_peers> filter_peer filter_peer_l filter_peer_h
%type <v.filter_match> filter_match filter_elm filter_match_h
%type <v.filter_as> filter_as filter_as_l filter_as_h
@@ -1236,6 +1236,10 @@ filter_set_l : filter_set_l comma filter_set_opt {
}
;
+delete : /* empty */ { $$ = 0; }
+ | DELETE { $$ = 1; }
+ ;
+
filter_set_opt : LOCALPREF number {
if (($$ = calloc(1, sizeof(struct filter_set))) == NULL)
fatal(NULL);
@@ -1419,20 +1423,26 @@ filter_set_opt : LOCALPREF number {
}
free($2);
}
- | COMMUNITY STRING {
+ | COMMUNITY delete STRING {
if (($$ = calloc(1, sizeof(struct filter_set))) == NULL)
fatal(NULL);
- $$->type = ACTION_SET_COMMUNITY;
- if (parsecommunity($2, &$$->action.community.as,
+ if ($2)
+ $$->type = ACTION_DEL_COMMUNITY;
+ else
+ $$->type = ACTION_SET_COMMUNITY;
+
+ if (parsecommunity($3, &$$->action.community.as,
&$$->action.community.type) == -1) {
- free($2);
+ free($3);
+ free($$);
YYERROR;
}
- free($2);
+ free($3);
/* Don't allow setting of any match */
- if ($$->action.community.as == COMMUNITY_ANY ||
- $$->action.community.type == COMMUNITY_ANY) {
+ if (!$2 && ($$->action.community.as == COMMUNITY_ANY ||
+ $$->action.community.type == COMMUNITY_ANY)) {
yyerror("'*' is not allowed in set community");
+ free($$);
YYERROR;
}
/* Don't allow setting of unknown well-known types */
@@ -1447,6 +1457,7 @@ filter_set_opt : LOCALPREF number {
default:
/* unknown */
yyerror("Invalid well-known community");
+ free($$);
YYERROR;
break;
}
@@ -1516,6 +1527,7 @@ lookup(char *s)
{ "community", COMMUNITY},
{ "compare", COMPARE},
{ "connected", CONNECTED},
+ { "delete", DELETE},
{ "deny", DENY},
{ "depend", DEPEND},
{ "descr", DESCR},
diff --git a/usr.sbin/bgpd/printconf.c b/usr.sbin/bgpd/printconf.c
index 47c4a5fce11..2fddffe3f29 100644
--- a/usr.sbin/bgpd/printconf.c
+++ b/usr.sbin/bgpd/printconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: printconf.c,v 1.51 2006/02/02 14:06:05 claudio Exp $ */
+/* $OpenBSD: printconf.c,v 1.52 2006/02/09 21:05:09 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -120,6 +120,10 @@ print_set(struct filter_set_head *set)
case ACTION_SET_PREPEND_PEER:
printf("prepend-neighbor %u ", s->action.prepend);
break;
+ case ACTION_DEL_COMMUNITY:
+ printf("community delete %u:%u ",
+ s->action.community.as, s->action.community.type);
+ break;
case ACTION_SET_COMMUNITY:
printf("community %u:%u ", s->action.community.as,
s->action.community.type);
diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h
index 749be49c67f..87471be8474 100644
--- a/usr.sbin/bgpd/rde.h
+++ b/usr.sbin/bgpd/rde.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.h,v 1.88 2006/02/02 14:06:05 claudio Exp $ */
+/* $OpenBSD: rde.h,v 1.89 2006/02/09 21:05:09 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and
@@ -291,6 +291,7 @@ struct aspath *aspath_prepend(struct aspath *, u_int16_t, int);
int aspath_match(struct aspath *, enum as_spec, u_int16_t);
int community_match(void *, u_int16_t, int, int);
int community_set(struct rde_aspath *, int, int);
+void community_delete(struct rde_aspath *, int, int);
/* rde_rib.c */
void path_init(u_int32_t);
diff --git a/usr.sbin/bgpd/rde_attr.c b/usr.sbin/bgpd/rde_attr.c
index 60a5869a47b..715f3c0ecff 100644
--- a/usr.sbin/bgpd/rde_attr.c
+++ b/usr.sbin/bgpd/rde_attr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_attr.c,v 1.62 2006/02/09 20:54:56 claudio Exp $ */
+/* $OpenBSD: rde_attr.c,v 1.63 2006/02/09 21:05:09 claudio Exp $ */
/*
* Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
@@ -739,7 +739,6 @@ community_set(struct rde_aspath *asp, int as, int type)
u_int8_t t = ATTR_COMMUNITIES;
attr = attr_optget(asp, ATTR_COMMUNITIES);
-
if (attr != NULL) {
p = attr->data;
ncommunities = attr->len >> 2; /* divide by four */
@@ -778,3 +777,64 @@ community_set(struct rde_aspath *asp, int as, int type)
return (1);
}
+void
+community_delete(struct rde_aspath *asp, int as, int type)
+{
+ struct attr *attr;
+ u_int8_t *p, *n;
+ u_int16_t l, len = 0;
+ u_int16_t eas, etype;
+ u_int8_t f, t;
+
+ attr = attr_optget(asp, ATTR_COMMUNITIES);
+ if (attr == NULL)
+ /* no attr nothing to do */
+ return;
+
+ p = attr->data;
+ for (l = 0; l < attr->len; l += 4) {
+ eas = *p++;
+ eas <<= 8;
+ eas |= *p++;
+ etype = *p++;
+ etype <<= 8;
+ etype |= *p++;
+
+ if (as != COMMUNITY_ANY && (u_int16_t)as != eas &&
+ type != COMMUNITY_ANY && (u_int16_t)type != etype)
+ len += 4;
+ }
+
+ if (len == 0) {
+ attr_free(asp, attr);
+ return;
+ }
+
+ if ((n = malloc(len)) == NULL)
+ fatal("community_delete");
+
+ p = attr->data;
+ for (l = 0; l < len && p < attr->data + attr->len; ) {
+ eas = *p++;
+ eas <<= 8;
+ eas |= *p++;
+ etype = *p++;
+ etype <<= 8;
+ etype |= *p++;
+
+ if (as != COMMUNITY_ANY && (u_int16_t)as != eas &&
+ type != COMMUNITY_ANY && (u_int16_t)type != etype) {
+ n[l++] = eas >> 8;
+ n[l++] = eas & 0xff;
+ n[l++] = etype >> 8;
+ n[l++] = etype & 0xff;
+ }
+ }
+
+ f = attr->flags;
+ t = attr->type;
+
+ attr_free(asp, attr);
+ attr_optadd(asp, f, t, n, len);
+}
+
diff --git a/usr.sbin/bgpd/rde_filter.c b/usr.sbin/bgpd/rde_filter.c
index fa3d1c53b7d..dbd78508aee 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.45 2006/02/03 19:33:14 claudio Exp $ */
+/* $OpenBSD: rde_filter.c,v 1.46 2006/02/09 21:05:09 claudio Exp $ */
/*
* Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
@@ -190,6 +190,33 @@ rde_apply_set(struct rde_aspath *asp, struct filter_set_head *sh,
community_set(asp, as, type);
break;
+ case ACTION_DEL_COMMUNITY:
+ switch (set->action.community.as) {
+ case COMMUNITY_ERROR:
+ fatalx("rde_apply_set bad community string");
+ case COMMUNITY_NEIGHBOR_AS:
+ as = peer->conf.remote_as;
+ break;
+ case COMMUNITY_ANY:
+ default:
+ as = set->action.community.as;
+ break;
+ }
+
+ switch (set->action.community.type) {
+ case COMMUNITY_ERROR:
+ fatalx("rde_apply_set bad community string");
+ case COMMUNITY_NEIGHBOR_AS:
+ type = peer->conf.remote_as;
+ break;
+ case COMMUNITY_ANY:
+ default:
+ type = set->action.community.type;
+ break;
+ }
+
+ community_delete(asp, as, type);
+ break;
case ACTION_PFTABLE:
/* convert pftable name to an id */
set->action.id = pftable_name2id(set->action.pftable);
@@ -488,6 +515,7 @@ filterset_equal(struct filter_set_head *ah, struct filter_set_head *bh)
if (a->type == b->type)
continue;
break;
+ case ACTION_DEL_COMMUNITY:
case ACTION_SET_COMMUNITY:
if (a->type == b->type &&
memcmp(&a->action.community, &b->action.community,