diff options
author | 2006-02-09 21:05:09 +0000 | |
---|---|---|
committer | 2006-02-09 21:05:09 +0000 | |
commit | aaa4f5df6530f0afa16fd1246cbbc555a65dd08c (patch) | |
tree | a2aab4db46e05f8bec3a61b7b3661fb3e517fa26 | |
parent | When comparing community type, cast to u_int16_t. The same is done for the (diff) | |
download | wireguard-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.h | 4 | ||||
-rw-r--r-- | usr.sbin/bgpd/parse.y | 32 | ||||
-rw-r--r-- | usr.sbin/bgpd/printconf.c | 6 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde.h | 3 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_attr.c | 64 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_filter.c | 30 |
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, |