summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/bgpd/bgpd.h44
-rw-r--r--usr.sbin/bgpd/control.c10
-rw-r--r--usr.sbin/bgpd/parse.y241
-rw-r--r--usr.sbin/bgpd/printconf.c186
-rw-r--r--usr.sbin/bgpd/rde.c37
-rw-r--r--usr.sbin/bgpd/rde.h43
-rw-r--r--usr.sbin/bgpd/rde_attr.c189
-rw-r--r--usr.sbin/bgpd/rde_filter.c296
-rw-r--r--usr.sbin/bgpd/rde_update.c32
9 files changed, 452 insertions, 626 deletions
diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h
index 1792de03f7b..8acea21297b 100644
--- a/usr.sbin/bgpd/bgpd.h
+++ b/usr.sbin/bgpd/bgpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.h,v 1.354 2018/11/14 14:03:36 claudio Exp $ */
+/* $OpenBSD: bgpd.h,v 1.355 2018/11/28 08:32:26 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -50,6 +50,7 @@
#define READ_BUF_SIZE 65535
#define RT_BUF_SIZE 16384
#define MAX_RTSOCK_BUF (2 * 1024 * 1024)
+#define MAX_COMM_MATCH 3
#define BGPD_OPT_VERBOSE 0x0001
#define BGPD_OPT_VERBOSE2 0x0002
@@ -427,12 +428,8 @@ enum imsg_type {
IMSG_CTL_SHOW_NEXTHOP,
IMSG_CTL_SHOW_INTERFACE,
IMSG_CTL_SHOW_RIB,
- IMSG_CTL_SHOW_RIB_AS,
IMSG_CTL_SHOW_RIB_PREFIX,
IMSG_CTL_SHOW_RIB_ATTR,
- IMSG_CTL_SHOW_RIB_COMMUNITY,
- IMSG_CTL_SHOW_RIB_EXTCOMMUNITY,
- IMSG_CTL_SHOW_RIB_LARGECOMMUNITY,
IMSG_CTL_SHOW_NETWORK,
IMSG_CTL_SHOW_RIB_MEM,
IMSG_CTL_SHOW_RIB_HASH,
@@ -741,14 +738,13 @@ struct filter_ovs {
};
struct filter_community {
- int as;
- int type;
-};
-
-struct filter_largecommunity {
- int64_t as;
- int64_t ld1;
- int64_t ld2;
+ u_int8_t type;
+ u_int8_t dflag1; /* one of set, any, local-as, neighbor-as */
+ u_int8_t dflag2;
+ u_int8_t dflag3;
+ u_int32_t data1;
+ u_int32_t data2;
+ u_int32_t data3;
};
struct filter_extcommunity {
@@ -779,7 +775,6 @@ struct ctl_show_rib_request {
struct filter_as as;
struct filter_community community;
struct filter_extcommunity extcommunity;
- struct filter_largecommunity large_community;
u_int32_t peerid;
u_int32_t flags;
u_int8_t validation_state;
@@ -829,11 +824,16 @@ struct filter_peers {
};
/* special community type */
-#define COMMUNITY_ERROR -1
-#define COMMUNITY_ANY -2
-#define COMMUNITY_NEIGHBOR_AS -3
-#define COMMUNITY_LOCAL_AS -4
-#define COMMUNITY_UNSET -5
+#define COMMUNITY_TYPE_NONE 0
+#define COMMUNITY_TYPE_BASIC 1
+#define COMMUNITY_TYPE_EXT 2
+#define COMMUNITY_TYPE_LARGE 3
+
+#define COMMUNITY_ANY 1
+#define COMMUNITY_NEIGHBOR_AS 2
+#define COMMUNITY_LOCAL_AS 3
+
+/* wellknown community definitions */
#define COMMUNITY_WELLKNOWN 0xffff
#define COMMUNITY_GRACEFUL_SHUTDOWN 0x0000 /* RFC 8326 */
#define COMMUNITY_BLACKHOLE 0x029A /* RFC 7999 */
@@ -928,8 +928,7 @@ struct filter_match {
struct filter_nexthop nexthop;
struct filter_as as;
struct filter_aslen aslen;
- struct filter_community community;
- struct filter_largecommunity large_community;
+ struct filter_community community[MAX_COMM_MATCH];
struct filter_extcommunity ext_community;
struct filter_prefixset prefixset;
struct filter_originset originset;
@@ -969,8 +968,6 @@ enum action_types {
ACTION_SET_NEXTHOP_SELF,
ACTION_SET_COMMUNITY,
ACTION_DEL_COMMUNITY,
- ACTION_DEL_LARGE_COMMUNITY,
- ACTION_SET_LARGE_COMMUNITY,
ACTION_SET_EXT_COMMUNITY,
ACTION_DEL_EXT_COMMUNITY,
ACTION_PFTABLE,
@@ -991,7 +988,6 @@ struct filter_set {
struct bgpd_addr nexthop;
struct nexthop *nh;
struct filter_community community;
- struct filter_largecommunity large_community;
struct filter_extcommunity ext_community;
char pftable[PFTABLE_LEN];
char rtlabel[RTLABEL_LEN];
diff --git a/usr.sbin/bgpd/control.c b/usr.sbin/bgpd/control.c
index 633a6344180..3ba8ed1c86d 100644
--- a/usr.sbin/bgpd/control.c
+++ b/usr.sbin/bgpd/control.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: control.c,v 1.90 2017/08/11 16:02:53 claudio Exp $ */
+/* $OpenBSD: control.c,v 1.91 2018/11/28 08:32:27 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -248,12 +248,8 @@ control_dispatch_msg(struct pollfd *pfd, u_int *ctl_cnt)
case IMSG_CTL_SHOW_NEXTHOP:
case IMSG_CTL_SHOW_INTERFACE:
case IMSG_CTL_SHOW_RIB:
- case IMSG_CTL_SHOW_RIB_AS:
case IMSG_CTL_SHOW_RIB_PREFIX:
case IMSG_CTL_SHOW_RIB_MEM:
- case IMSG_CTL_SHOW_RIB_COMMUNITY:
- case IMSG_CTL_SHOW_RIB_EXTCOMMUNITY:
- case IMSG_CTL_SHOW_RIB_LARGECOMMUNITY:
case IMSG_CTL_SHOW_NETWORK:
case IMSG_CTL_SHOW_TERSE:
case IMSG_CTL_SHOW_TIMER:
@@ -421,7 +417,6 @@ control_dispatch_msg(struct pollfd *pfd, u_int *ctl_cnt)
IMSG_HEADER_SIZE);
break;
case IMSG_CTL_SHOW_RIB:
- case IMSG_CTL_SHOW_RIB_AS:
case IMSG_CTL_SHOW_RIB_PREFIX:
if (imsg.hdr.len == IMSG_HEADER_SIZE +
sizeof(struct ctl_show_rib_request)) {
@@ -471,9 +466,6 @@ control_dispatch_msg(struct pollfd *pfd, u_int *ctl_cnt)
"wrong length");
break;
case IMSG_CTL_SHOW_RIB_MEM:
- case IMSG_CTL_SHOW_RIB_COMMUNITY:
- case IMSG_CTL_SHOW_RIB_EXTCOMMUNITY:
- case IMSG_CTL_SHOW_RIB_LARGECOMMUNITY:
case IMSG_CTL_SHOW_NETWORK:
c->ibuf.pid = imsg.hdr.pid;
imsg_ctl_rde(imsg.hdr.type, imsg.hdr.pid,
diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y
index 41ef8411ce6..fecf647da96 100644
--- a/usr.sbin/bgpd/parse.y
+++ b/usr.sbin/bgpd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.363 2018/11/18 09:36:23 claudio Exp $ */
+/* $OpenBSD: parse.y,v 1.364 2018/11/28 08:32:27 claudio Exp $ */
/*
* Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -153,9 +153,7 @@ int merge_filterset(struct filter_set_head *, struct filter_set *);
void merge_filter_lists(struct filter_head *, struct filter_head *);
struct filter_rule *get_rule(enum action_types);
-int64_t getcommunity(char *, int);
-int parsecommunity(struct filter_community *, char *);
-int parselargecommunity(struct filter_largecommunity *, char *);
+int parsecommunity(struct filter_community *, int, char *);
int parsesubtype(char *, int *, int *);
int parseextvalue(char *, u_int32_t *);
int parseextcommunity(struct filter_extcommunity *, char *,
@@ -232,7 +230,7 @@ typedef struct {
%type <v.addr> address
%type <v.prefix> prefix addrspec
%type <v.prefixset_item> prefixset_item
-%type <v.u8> action quick direction delete
+%type <v.u8> action quick direction delete community
%type <v.filter_rib> filter_rib_h filter_rib_l filter_rib
%type <v.filter_peers> filter_peer filter_peer_l filter_peer_h
%type <v.filter_match> filter_match filter_elm filter_match_h
@@ -2085,13 +2083,9 @@ filter_as : as4number_any {
filter_match_h : /* empty */ {
bzero(&$$, sizeof($$));
- $$.m.community.as = COMMUNITY_UNSET;
- $$.m.large_community.as = COMMUNITY_UNSET;
}
| {
bzero(&fmopts, sizeof(fmopts));
- fmopts.m.community.as = COMMUNITY_UNSET;
- fmopts.m.large_community.as = COMMUNITY_UNSET;
}
filter_match {
memcpy(&$$, &fmopts, sizeof($$));
@@ -2146,25 +2140,20 @@ filter_elm : filter_prefix_h {
fmopts.m.aslen.type = ASLEN_SEQ;
fmopts.m.aslen.aslen = $2;
}
- | COMMUNITY STRING {
- if (fmopts.m.community.as != COMMUNITY_UNSET) {
- yyerror("\"community\" already specified");
- free($2);
- YYERROR;
+ | community STRING {
+ int i;
+ for (i = 0; i < MAX_COMM_MATCH; i++) {
+ if (fmopts.m.community[i].type ==
+ COMMUNITY_TYPE_NONE)
+ break;
}
- if (parsecommunity(&fmopts.m.community, $2) == -1) {
+ if (i >= MAX_COMM_MATCH) {
+ yyerror("too many \"community\" filters "
+ "specified");
free($2);
YYERROR;
}
- free($2);
- }
- | LARGECOMMUNITY STRING {
- if (fmopts.m.large_community.as != COMMUNITY_UNSET) {
- yyerror("\"large-community\" already specified");
- free($2);
- YYERROR;
- }
- if (parselargecommunity(&fmopts.m.large_community, $2) == -1) {
+ if (parsecommunity(&fmopts.m.community[i], $1, $2) == -1) {
free($2);
YYERROR;
}
@@ -2405,6 +2394,10 @@ filter_set_l : filter_set_l comma filter_set_opt {
}
;
+community : COMMUNITY { $$ = COMMUNITY_TYPE_BASIC; }
+ | LARGECOMMUNITY { $$ = COMMUNITY_TYPE_LARGE; }
+ ;
+
delete : /* empty */ { $$ = 0; }
| DELETE { $$ = 1; }
;
@@ -2637,7 +2630,7 @@ filter_set_opt : LOCALPREF NUMBER {
}
free($2);
}
- | COMMUNITY delete STRING {
+ | community delete STRING {
if (($$ = calloc(1, sizeof(struct filter_set))) == NULL)
fatal(NULL);
if ($2)
@@ -2645,30 +2638,8 @@ filter_set_opt : LOCALPREF NUMBER {
else
$$->type = ACTION_SET_COMMUNITY;
- if (parsecommunity(&$$->action.community, $3) == -1) {
- free($3);
- free($$);
- YYERROR;
- }
- free($3);
- /* Don't allow setting of any match */
- if (!$2 && ($$->action.community.as == COMMUNITY_ANY ||
- $$->action.community.type == COMMUNITY_ANY)) {
- yyerror("'*' is not allowed in set community");
- free($$);
- YYERROR;
- }
- }
- | LARGECOMMUNITY delete STRING {
- if (($$ = calloc(1, sizeof(struct filter_set))) == NULL)
- fatal(NULL);
- if ($2)
- $$->type = ACTION_DEL_LARGE_COMMUNITY;
- else
- $$->type = ACTION_SET_LARGE_COMMUNITY;
-
- if (parselargecommunity(&$$->action.large_community,
- $3) == -1) {
+ if (parsecommunity(&$$->action.community, $1, $3) ==
+ -1) {
free($3);
free($$);
YYERROR;
@@ -2676,9 +2647,9 @@ filter_set_opt : LOCALPREF NUMBER {
free($3);
/* Don't allow setting of any match */
if (!$2 &&
- ($$->action.large_community.as == COMMUNITY_ANY ||
- $$->action.large_community.ld1 == COMMUNITY_ANY ||
- $$->action.large_community.ld2 == COMMUNITY_ANY)) {
+ ($$->action.community.dflag1 == COMMUNITY_ANY ||
+ $$->action.community.dflag2 == COMMUNITY_ANY ||
+ $$->action.community.dflag3 == COMMUNITY_ANY)) {
yyerror("'*' is not allowed in set community");
free($$);
YYERROR;
@@ -3470,60 +3441,105 @@ symget(const char *nam)
return (NULL);
}
-int64_t
-getcommunity(char *s, int large)
+static int
+getcommunity(char *s, int large, u_int32_t *val, u_int8_t *flag)
{
int64_t max = USHRT_MAX;
- u_int val;
const char *errstr;
- if (strcmp(s, "*") == 0)
- return (COMMUNITY_ANY);
- if (strcmp(s, "neighbor-as") == 0)
- return (COMMUNITY_NEIGHBOR_AS);
- if (strcmp(s, "local-as") == 0)
- return (COMMUNITY_LOCAL_AS);
+ *flag = 0;
+ *val = 0;
+ if (strcmp(s, "*") == 0) {
+ *flag = COMMUNITY_ANY;
+ return 0;
+ } else if (strcmp(s, "neighbor-as") == 0) {
+ *flag = COMMUNITY_NEIGHBOR_AS;
+ return 0;
+ } else if (strcmp(s, "local-as") == 0) {
+ *flag = COMMUNITY_LOCAL_AS;
+ return 0;
+ }
if (large)
max = UINT_MAX;
- val = strtonum(s, 0, max, &errstr);
+ *val = strtonum(s, 0, max, &errstr);
if (errstr) {
yyerror("Community %s is %s (max: %llu)", s, errstr, max);
- return (COMMUNITY_ERROR);
+ return -1;
}
- return (val);
+ return 0;
+}
+
+static void
+setcommunity(struct filter_community *c, u_int32_t as, u_int32_t data,
+ u_int8_t asflag, u_int8_t dataflag)
+{
+ memset(c, 0, sizeof(*c));
+ c->type = COMMUNITY_TYPE_BASIC;
+ c->dflag1 = asflag;
+ c->dflag2 = dataflag;
+ c->data1 = as;
+ c->data2 = data;
}
+static int
+parselargecommunity(struct filter_community *c, char *s)
+{
+ char *p, *q;
+
+ if ((p = strchr(s, ':')) == NULL) {
+ yyerror("Bad community syntax");
+ return (-1);
+ }
+ *p++ = 0;
+
+ if ((q = strchr(p, ':')) == NULL) {
+ yyerror("Bad community syntax");
+ return (-1);
+ }
+ *q++ = 0;
+
+ if (getcommunity(s, 1, &c->data1, &c->dflag1) == -1 ||
+ getcommunity(p, 1, &c->data2, &c->dflag2) == -1 ||
+ getcommunity(q, 1, &c->data3, &c->dflag3) == -1)
+ return (-1);
+ c->type = COMMUNITY_TYPE_LARGE;
+ return (0);
+}
int
-parsecommunity(struct filter_community *c, char *s)
+parsecommunity(struct filter_community *c, int type, char *s)
{
char *p;
- int i, as;
+ u_int32_t as, data;
+ u_int8_t asflag, dataflag;
+
+ if (type == COMMUNITY_TYPE_LARGE)
+ return parselargecommunity(c, s);
/* Well-known communities */
if (strcasecmp(s, "GRACEFUL_SHUTDOWN") == 0) {
- c->as = COMMUNITY_WELLKNOWN;
- c->type = COMMUNITY_GRACEFUL_SHUTDOWN;
+ setcommunity(c, COMMUNITY_WELLKNOWN,
+ COMMUNITY_GRACEFUL_SHUTDOWN, 0, 0);
return (0);
} else if (strcasecmp(s, "NO_EXPORT") == 0) {
- c->as = COMMUNITY_WELLKNOWN;
- c->type = COMMUNITY_NO_EXPORT;
+ setcommunity(c, COMMUNITY_WELLKNOWN,
+ COMMUNITY_NO_EXPORT, 0, 0);
return (0);
} else if (strcasecmp(s, "NO_ADVERTISE") == 0) {
- c->as = COMMUNITY_WELLKNOWN;
- c->type = COMMUNITY_NO_ADVERTISE;
+ setcommunity(c, COMMUNITY_WELLKNOWN,
+ COMMUNITY_NO_ADVERTISE, 0, 0);
return (0);
} else if (strcasecmp(s, "NO_EXPORT_SUBCONFED") == 0) {
- c->as = COMMUNITY_WELLKNOWN;
- c->type = COMMUNITY_NO_EXPSUBCONFED;
+ setcommunity(c, COMMUNITY_WELLKNOWN,
+ COMMUNITY_NO_EXPSUBCONFED, 0, 0);
return (0);
} else if (strcasecmp(s, "NO_PEER") == 0) {
- c->as = COMMUNITY_WELLKNOWN;
- c->type = COMMUNITY_NO_PEER;
+ setcommunity(c, COMMUNITY_WELLKNOWN,
+ COMMUNITY_NO_PEER, 0, 0);
return (0);
} else if (strcasecmp(s, "BLACKHOLE") == 0) {
- c->as = COMMUNITY_WELLKNOWN;
- c->type = COMMUNITY_BLACKHOLE;
+ setcommunity(c, COMMUNITY_WELLKNOWN,
+ COMMUNITY_BLACKHOLE, 0, 0);
return (0);
}
@@ -3533,49 +3549,10 @@ parsecommunity(struct filter_community *c, char *s)
}
*p++ = 0;
- if ((i = getcommunity(s, 0)) == COMMUNITY_ERROR)
- return (-1);
- as = i;
-
- if ((i = getcommunity(p, 0)) == COMMUNITY_ERROR)
- return (-1);
- c->as = as;
- c->type = i;
-
- return (0);
-}
-
-int
-parselargecommunity(struct filter_largecommunity *c, char *s)
-{
- char *p, *q;
- int64_t as, ld1, ld2;
-
- if ((p = strchr(s, ':')) == NULL) {
- yyerror("Bad community syntax");
- return (-1);
- }
- *p++ = 0;
-
- if ((q = strchr(p, ':')) == NULL) {
- yyerror("Bad community syntax");
- return (-1);
- }
- *q++ = 0;
-
- if ((as = getcommunity(s, 1)) == COMMUNITY_ERROR)
- return (-1);
-
- if ((ld1 = getcommunity(p, 1)) == COMMUNITY_ERROR)
+ if (getcommunity(s, 0, &as, &asflag) == -1 ||
+ getcommunity(p, 0, &data, &dataflag) == -1)
return (-1);
-
- if ((ld2 = getcommunity(q, 1)) == COMMUNITY_ERROR)
- return (-1);
-
- c->as = as;
- c->ld1 = ld1;
- c->ld2 = ld2;
-
+ setcommunity(c, as, data, asflag, dataflag);
return (0);
}
@@ -4218,10 +4195,6 @@ merge_filterset(struct filter_set_head *sh, struct filter_set *s)
yyerror("community is already set");
else if (s->type == ACTION_DEL_COMMUNITY)
yyerror("community will already be deleted");
- else if (s->type == ACTION_SET_LARGE_COMMUNITY)
- yyerror("large-community is already set");
- else if (s->type == ACTION_DEL_LARGE_COMMUNITY)
- yyerror("large-community will already be deleted");
else if (s->type == ACTION_SET_EXT_COMMUNITY)
yyerror("ext-community is already set");
else if (s->type == ACTION_DEL_EXT_COMMUNITY)
@@ -4243,21 +4216,9 @@ merge_filterset(struct filter_set_head *sh, struct filter_set *s)
switch (s->type) {
case ACTION_SET_COMMUNITY:
case ACTION_DEL_COMMUNITY:
- if (s->action.community.as <
- t->action.community.as ||
- (s->action.community.as ==
- t->action.community.as &&
- s->action.community.type <
- t->action.community.type)) {
- TAILQ_INSERT_BEFORE(t, s, entry);
- return (0);
- }
- break;
- case ACTION_SET_LARGE_COMMUNITY:
- case ACTION_DEL_LARGE_COMMUNITY:
- if (memcmp(&s->action.large_community,
- &t->action.large_community,
- sizeof(s->action.large_community)) < 0) {
+ if (memcmp(&s->action.community,
+ &t->action.community,
+ sizeof(s->action.community)) < 0) {
TAILQ_INSERT_BEFORE(t, s, entry);
return (0);
}
@@ -4321,8 +4282,6 @@ get_rule(enum action_types type)
r->quick = 0;
r->dir = out ? DIR_OUT : DIR_IN;
r->action = ACTION_NONE;
- r->match.community.as = COMMUNITY_UNSET;
- r->match.large_community.as = COMMUNITY_UNSET;
TAILQ_INIT(&r->set);
if (curpeer == curgroup) {
/* group */
diff --git a/usr.sbin/bgpd/printconf.c b/usr.sbin/bgpd/printconf.c
index e9dfebdffa4..3f7fcaa6266 100644
--- a/usr.sbin/bgpd/printconf.c
+++ b/usr.sbin/bgpd/printconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: printconf.c,v 1.123 2018/09/29 08:11:11 claudio Exp $ */
+/* $OpenBSD: printconf.c,v 1.124 2018/11/28 08:32:27 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -30,7 +30,8 @@
#include "log.h"
void print_prefix(struct filter_prefix *p);
-void print_community(int, int);
+const char *community_type(struct filter_community *c);
+void print_community(struct filter_community *c);
void print_largecommunity(int64_t, int64_t, int64_t);
void print_extcommunity(struct filter_extcommunity *);
void print_origin(u_int8_t);
@@ -104,61 +105,100 @@ print_prefix(struct filter_prefix *p)
}
}
-void
-print_community(int as, int type)
+const char *
+community_type(struct filter_community *c)
{
- if (as == COMMUNITY_ANY)
- printf("*:");
- else if (as == COMMUNITY_NEIGHBOR_AS)
- printf("neighbor-as:");
- else if (as == COMMUNITY_LOCAL_AS)
- printf("local-as:");
- else
- printf("%u:", (unsigned int)as);
-
- if (type == COMMUNITY_ANY)
- printf("* ");
- else if (type == COMMUNITY_NEIGHBOR_AS)
- printf("neighbor-as ");
- else if (type == COMMUNITY_LOCAL_AS)
- printf("local-as");
- else
- printf("%d ", type);
+ switch (c->type) {
+ case COMMUNITY_TYPE_BASIC:
+ return "community";
+ case COMMUNITY_TYPE_LARGE:
+ return "large-community";
+ default:
+ return "???";
+ }
}
void
-print_largecommunity(int64_t as, int64_t ld1, int64_t ld2)
+print_community(struct filter_community *c)
{
- if (as == COMMUNITY_ANY)
- printf("*:");
- else if (as == COMMUNITY_NEIGHBOR_AS)
- printf("neighbor-as:");
- else if (as == COMMUNITY_LOCAL_AS)
- printf("local-as:");
- else
- printf("%lld:", as);
-
- if (ld1 == COMMUNITY_ANY)
- printf("*:");
- else if (ld1 == COMMUNITY_NEIGHBOR_AS)
- printf("neighbor-as:");
- else if (ld1 == COMMUNITY_LOCAL_AS)
- printf("local-as:");
- else
- printf("%lld:", ld1);
-
- if (ld2 == COMMUNITY_ANY)
- printf("* ");
- else if (ld2 == COMMUNITY_NEIGHBOR_AS)
- printf("neighbor-as ");
- else if (ld2 == COMMUNITY_LOCAL_AS)
- printf("local-as ");
- else
- printf("%lld ", ld2);
-
+ switch (c->type) {
+ case COMMUNITY_TYPE_BASIC:
+ switch (c->dflag1) {
+ case COMMUNITY_ANY:
+ printf("*:");
+ break;
+ case COMMUNITY_NEIGHBOR_AS:
+ printf("neighbor-as:");
+ break;
+ case COMMUNITY_LOCAL_AS:
+ printf("local-as:");
+ break;
+ default:
+ printf("%u:", c->data1);
+ break;
+ }
+ switch (c->dflag2) {
+ case COMMUNITY_ANY:
+ printf("* ");
+ break;
+ case COMMUNITY_NEIGHBOR_AS:
+ printf("neighbor-as ");
+ break;
+ case COMMUNITY_LOCAL_AS:
+ printf("local-as ");
+ break;
+ default:
+ printf("%u ", c->data2);
+ break;
+ }
+ break;
+ case COMMUNITY_TYPE_LARGE:
+ switch (c->dflag1) {
+ case COMMUNITY_ANY:
+ printf("*:");
+ break;
+ case COMMUNITY_NEIGHBOR_AS:
+ printf("neighbor-as:");
+ break;
+ case COMMUNITY_LOCAL_AS:
+ printf("local-as:");
+ break;
+ default:
+ printf("%u:", c->data1);
+ break;
+ }
+ switch (c->dflag2) {
+ case COMMUNITY_ANY:
+ printf("*:");
+ break;
+ case COMMUNITY_NEIGHBOR_AS:
+ printf("neighbor-as:");
+ break;
+ case COMMUNITY_LOCAL_AS:
+ printf("local-as:");
+ break;
+ default:
+ printf("%u:", c->data2);
+ break;
+ }
+ switch (c->dflag3) {
+ case COMMUNITY_ANY:
+ printf("* ");
+ break;
+ case COMMUNITY_NEIGHBOR_AS:
+ printf("neighbor-as ");
+ break;
+ case COMMUNITY_LOCAL_AS:
+ printf("local-as ");
+ break;
+ default:
+ printf("%u ", c->data3);
+ break;
+ }
+ break;
+ }
}
-
void
print_extcommunity(struct filter_extcommunity *c)
{
@@ -263,30 +303,13 @@ print_set(struct filter_set_head *set)
printf("prepend-neighbor %u ", s->action.prepend);
break;
case ACTION_DEL_COMMUNITY:
- printf("community delete ");
- print_community(s->action.community.as,
- s->action.community.type);
- printf(" ");
+ printf("%s delete ",
+ community_type(&s->action.community));
+ print_community(&s->action.community);
break;
case ACTION_SET_COMMUNITY:
- printf("community ");
- print_community(s->action.community.as,
- s->action.community.type);
- printf(" ");
- break;
- case ACTION_DEL_LARGE_COMMUNITY:
- printf("large-community delete ");
- print_largecommunity(s->action.large_community.as,
- s->action.large_community.ld1,
- s->action.large_community.ld2);
- printf(" ");
- break;
- case ACTION_SET_LARGE_COMMUNITY:
- printf("large-community ");
- print_largecommunity(s->action.large_community.as,
- s->action.large_community.ld1,
- s->action.large_community.ld2);
- printf(" ");
+ printf("%s ", community_type(&s->action.community));
+ print_community(&s->action.community);
break;
case ACTION_PFTABLE:
printf("pftable %s ", s->action.pftable);
@@ -715,7 +738,8 @@ void print_as(struct filter_rule *r)
void
print_rule(struct peer *peer_l, struct filter_rule *r)
{
- struct peer *p;
+ struct peer *p;
+ int i;
if (r->action == ACTION_ALLOW)
printf("allow ");
@@ -817,21 +841,17 @@ print_rule(struct peer *peer_l, struct filter_rule *r)
"max-as-len" : "max-as-seq", r->match.aslen.aslen);
}
- if (r->match.community.as != COMMUNITY_UNSET) {
- printf("community ");
- print_community(r->match.community.as,
- r->match.community.type);
+ for (i = 0; i < MAX_COMM_MATCH; i++) {
+ struct filter_community *c = &r->match.community[i];
+ if (c->type != COMMUNITY_TYPE_NONE) {
+ printf("%s ", community_type(c));
+ print_community(c);
+ }
}
if (r->match.ext_community.flags & EXT_COMMUNITY_FLAG_VALID) {
printf("ext-community ");
print_extcommunity(&r->match.ext_community);
}
- if (r->match.large_community.as != COMMUNITY_UNSET) {
- printf("large-community ");
- print_largecommunity(r->match.large_community.as,
- r->match.large_community.ld1,
- r->match.large_community.ld2);
- }
print_set(&r->set);
diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c
index 26b06cfa6ed..2692890b0ce 100644
--- a/usr.sbin/bgpd/rde.c
+++ b/usr.sbin/bgpd/rde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.449 2018/11/10 11:19:01 denis Exp $ */
+/* $OpenBSD: rde.c,v 1.450 2018/11/28 08:32:27 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -583,10 +583,6 @@ badnetdel:
break;
case IMSG_CTL_SHOW_NETWORK:
case IMSG_CTL_SHOW_RIB:
- case IMSG_CTL_SHOW_RIB_AS:
- case IMSG_CTL_SHOW_RIB_COMMUNITY:
- case IMSG_CTL_SHOW_RIB_EXTCOMMUNITY:
- case IMSG_CTL_SHOW_RIB_LARGECOMMUNITY:
case IMSG_CTL_SHOW_RIB_PREFIX:
if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(req)) {
log_warnx("rde_dispatch: wrong imsg len");
@@ -2224,21 +2220,24 @@ rde_dump_filter(struct prefix *p, struct ctl_show_rib_request *req)
if ((req->flags & F_CTL_INVALID) &&
(asp->flags & F_ATTR_PARSE_ERR) == 0)
return;
- if (req->type == IMSG_CTL_SHOW_RIB_AS &&
- !aspath_match(asp->aspath->data, asp->aspath->len,
- &req->as, 0))
+ if (req->as.type != AS_UNDEF && !aspath_match(asp->aspath->data,
+ asp->aspath->len, &req->as, 0))
return;
- if (req->type == IMSG_CTL_SHOW_RIB_COMMUNITY &&
- !community_match(asp, req->community.as,
- req->community.type))
- return;
- if (req->type == IMSG_CTL_SHOW_RIB_EXTCOMMUNITY &&
+ switch (req->community.type) {
+ case COMMUNITY_TYPE_NONE:
+ break;
+ case COMMUNITY_TYPE_BASIC:
+ if (!community_match(asp, &req->community, NULL))
+ return;
+ break;
+ case COMMUNITY_TYPE_LARGE:
+ if (!community_large_match(asp, &req->community, NULL))
+ return;
+ break;
+ }
+ if (req->extcommunity.flags == EXT_COMMUNITY_FLAG_VALID &&
!community_ext_match(asp, &req->extcommunity, 0))
return;
- if (req->type == IMSG_CTL_SHOW_RIB_LARGECOMMUNITY &&
- !community_large_match(asp, req->large_community.as,
- req->large_community.ld1, req->large_community.ld2))
- return;
if (!ovs_match(p, req->flags))
return;
rde_dump_rib_as(p, asp, req->pid, req->flags);
@@ -2334,10 +2333,6 @@ rde_dump_ctx_new(struct ctl_show_rib_request *req, pid_t pid,
goto nomem;
break;
case IMSG_CTL_SHOW_RIB:
- case IMSG_CTL_SHOW_RIB_AS:
- case IMSG_CTL_SHOW_RIB_COMMUNITY:
- case IMSG_CTL_SHOW_RIB_EXTCOMMUNITY:
- case IMSG_CTL_SHOW_RIB_LARGECOMMUNITY:
if (rib_dump_new(rid, ctx->req.aid, CTL_MSG_HIGH_MARK, ctx,
rde_dump_upcall, rde_dump_done, rde_dump_throttled) == -1)
goto nomem;
diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h
index f98c23243ee..0ee5964de04 100644
--- a/usr.sbin/bgpd/rde.h
+++ b/usr.sbin/bgpd/rde.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.h,v 1.202 2018/11/04 12:34:54 claudio Exp $ */
+/* $OpenBSD: rde.h,v 1.203 2018/11/28 08:32:27 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and
@@ -361,25 +361,28 @@ int aspath_loopfree(struct aspath *, u_int32_t);
int aspath_compare(struct aspath *, struct aspath *);
u_char *aspath_prepend(struct aspath *, u_int32_t, int, u_int16_t *);
int aspath_lenmatch(struct aspath *, enum aslen_spec, u_int);
-int community_match(struct rde_aspath *, int, int);
-int community_set(struct rde_aspath *, int, int);
-void community_delete(struct rde_aspath *, int, int);
-int community_large_match(struct rde_aspath *, int64_t, int64_t,
- int64_t);
-int community_large_set(struct rde_aspath *, int64_t, int64_t,
- int64_t);
-void community_large_delete(struct rde_aspath *, int64_t,
- int64_t, int64_t);
-int community_ext_match(struct rde_aspath *,
- struct filter_extcommunity *, u_int16_t);
-int community_ext_set(struct rde_aspath *,
- struct filter_extcommunity *, u_int16_t);
-void community_ext_delete(struct rde_aspath *,
- struct filter_extcommunity *, u_int16_t);
-int community_ext_conv(struct filter_extcommunity *, u_int16_t,
- u_int64_t *);
-u_char *community_ext_delete_non_trans(u_char *, u_int16_t,
- u_int16_t *);
+
+int community_match(struct rde_aspath *, struct filter_community *,
+ struct rde_peer *);
+int community_set(struct rde_aspath *, struct filter_community *,
+ struct rde_peer *);
+void community_delete(struct rde_aspath *, struct filter_community *,
+ struct rde_peer *);
+int community_large_match(struct rde_aspath *, struct filter_community *,
+ struct rde_peer *);
+int community_large_set(struct rde_aspath *, struct filter_community *,
+ struct rde_peer *);
+void community_large_delete(struct rde_aspath *, struct filter_community *,
+ struct rde_peer *);
+int community_ext_match(struct rde_aspath *,
+ struct filter_extcommunity *, u_int16_t);
+int community_ext_set(struct rde_aspath *,
+ struct filter_extcommunity *, u_int16_t);
+void community_ext_delete(struct rde_aspath *,
+ struct filter_extcommunity *, u_int16_t);
+int community_ext_conv(struct filter_extcommunity *, u_int16_t,
+ u_int64_t *);
+u_char *community_ext_delete_non_trans(u_char *, u_int16_t, u_int16_t *);
/* rde_decide.c */
void prefix_evaluate(struct prefix *, struct rib_entry *);
diff --git a/usr.sbin/bgpd/rde_attr.c b/usr.sbin/bgpd/rde_attr.c
index 21b4fbf5f61..897c3a370ca 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.112 2018/10/10 06:21:47 deraadt Exp $ */
+/* $OpenBSD: rde_attr.c,v 1.113 2018/11/28 08:32:27 claudio Exp $ */
/*
* Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
@@ -995,18 +995,65 @@ aspath_lenmatch(struct aspath *a, enum aslen_spec type, u_int aslen)
int community_ext_matchone(struct filter_extcommunity *, u_int16_t, u_int64_t);
+static int
+community_extract(struct filter_community *fc, struct rde_peer *peer,
+ int field, int large, u_int32_t *value)
+{
+ u_int32_t data;
+ u_int8_t flag;
+ switch (field) {
+ case 1:
+ flag = fc->dflag1;
+ data = fc->data1;
+ break;
+ case 2:
+ flag = fc->dflag2;
+ data = fc->data2;
+ break;
+ case 3:
+ flag = fc->dflag3;
+ data = fc->data3;
+ break;
+ default:
+ fatalx("%s: unknown field %d", __func__, field);
+ }
+
+ switch (flag) {
+ case COMMUNITY_NEIGHBOR_AS:
+ if (peer == NULL)
+ return -1;
+ *value = peer->conf.remote_as;
+ case COMMUNITY_LOCAL_AS:
+ if (peer == NULL)
+ return -1;
+ *value = peer->conf.local_as;
+ default:
+ *value = data;
+ }
+ if (!large && *value > USHRT_MAX)
+ return -1;
+ return 0;
+}
+
int
-community_match(struct rde_aspath *asp, int as, int type)
+community_match(struct rde_aspath *asp, struct filter_community *fc,
+ struct rde_peer *peer)
{
struct attr *a;
u_int8_t *p;
- u_int16_t eas, etype, len;
+ u_int32_t as, type, eas, etype;
+ u_int16_t len;
a = attr_optget(asp, ATTR_COMMUNITIES);
if (a == NULL)
/* no communities, no match */
return (0);
+ if (community_extract(fc, peer, 1, 0, &as) == -1 ||
+ community_extract(fc, peer, 2, 0, &type) == -1)
+ /* can't match community */
+ return (0);
+
p = a->data;
for (len = a->len / 4; len > 0; len--) {
eas = *p++;
@@ -1015,21 +1062,29 @@ community_match(struct rde_aspath *asp, int as, int type)
etype = *p++;
etype <<= 8;
etype |= *p++;
- if ((as == COMMUNITY_ANY || (u_int16_t)as == eas) &&
- (type == COMMUNITY_ANY || (u_int16_t)type == etype))
+ if ((fc->dflag1 == COMMUNITY_ANY || as == eas) &&
+ (fc->dflag2 == COMMUNITY_ANY || type == etype))
return (1);
}
return (0);
}
int
-community_set(struct rde_aspath *asp, int as, int type)
+community_set(struct rde_aspath *asp, struct filter_community *fc,
+ struct rde_peer *peer)
{
struct attr *attr;
u_int8_t *p = NULL;
unsigned int i, ncommunities = 0;
+ u_int32_t as, type;
u_int8_t f = ATTR_OPTIONAL|ATTR_TRANSITIVE;
+ if (fc->dflag1 == COMMUNITY_ANY || fc->dflag2 == COMMUNITY_ANY ||
+ community_extract(fc, peer, 1, 0, &as) == -1 ||
+ community_extract(fc, peer, 2, 0, &type) == -1)
+ /* bad community */
+ return (0);
+
attr = attr_optget(asp, ATTR_COMMUNITIES);
if (attr != NULL) {
p = attr->data;
@@ -1070,12 +1125,13 @@ community_set(struct rde_aspath *asp, int as, int type)
}
void
-community_delete(struct rde_aspath *asp, int as, int type)
+community_delete(struct rde_aspath *asp, struct filter_community *fc,
+ struct rde_peer *peer)
{
struct attr *attr;
u_int8_t *p, *n;
u_int16_t l, len = 0;
- u_int16_t eas, etype;
+ u_int32_t as, type, eas, etype;
u_int8_t f;
attr = attr_optget(asp, ATTR_COMMUNITIES);
@@ -1083,6 +1139,11 @@ community_delete(struct rde_aspath *asp, int as, int type)
/* no attr nothing to do */
return;
+ if (community_extract(fc, peer, 1, 0, &as) == -1 ||
+ community_extract(fc, peer, 2, 0, &type) == -1)
+ /* bad community, nothing to do */
+ return;
+
p = attr->data;
for (l = 0; l < attr->len; l += 4) {
eas = *p++;
@@ -1092,8 +1153,8 @@ community_delete(struct rde_aspath *asp, int as, int type)
etype <<= 8;
etype |= *p++;
- if ((as == COMMUNITY_ANY || (u_int16_t)as == eas) &&
- (type == COMMUNITY_ANY || (u_int16_t)type == etype))
+ if ((fc->dflag1 == COMMUNITY_ANY || as == eas) &&
+ (fc->dflag2 == COMMUNITY_ANY || type == etype))
/* match */
continue;
len += 4;
@@ -1116,8 +1177,8 @@ community_delete(struct rde_aspath *asp, int as, int type)
etype <<= 8;
etype |= *p++;
- if ((as == COMMUNITY_ANY || (u_int16_t)as == eas) &&
- (type == COMMUNITY_ANY || (u_int16_t)type == etype))
+ if ((fc->dflag1 == COMMUNITY_ANY || as == eas) &&
+ (fc->dflag2 == COMMUNITY_ANY || type == etype))
/* match */
continue;
n[l++] = eas >> 8;
@@ -1382,46 +1443,66 @@ struct wire_largecommunity {
};
int
-community_large_match(struct rde_aspath *asp, int64_t as, int64_t ld1,
- int64_t ld2)
+community_large_match(struct rde_aspath *asp, struct filter_community *fc,
+ struct rde_peer *peer)
{
- struct wire_largecommunity *bar;
+ struct wire_largecommunity *wlc;
struct attr *a;
u_int8_t *p;
u_int16_t len;
- u_int32_t eas, eld1, eld2;
+ u_int32_t as, ld1, ld2;
a = attr_optget(asp, ATTR_LARGE_COMMUNITIES);
if (a == NULL)
/* no communities, no match */
return (0);
+ if (community_extract(fc, peer, 1, 1, &as) == -1 ||
+ community_extract(fc, peer, 2, 1, &ld1) == -1 ||
+ community_extract(fc, peer, 3, 1, &ld2) == -1)
+ /* can't match community */
+ return (0);
+
+ as = htonl(as);
+ ld1 = htonl(ld1);
+ ld2 = htonl(ld2);
+
p = a->data;
for (len = a->len / 12; len > 0; len--) {
- bar = (struct wire_largecommunity *)p;
+ wlc = (struct wire_largecommunity *)p;
p += 12;
- eas = betoh32(bar->as);
- eld1 = betoh32(bar->ld1);
- eld2 = betoh32(bar->ld2);
- if ((as == COMMUNITY_ANY || as == eas) &&
- (ld1 == COMMUNITY_ANY || ld1 == eld1) &&
- (ld2 == COMMUNITY_ANY || ld2 == eld2))
+ if ((fc->dflag1 == COMMUNITY_ANY || as == wlc->as) &&
+ (fc->dflag2 == COMMUNITY_ANY || ld1 == wlc->ld1) &&
+ (fc->dflag3 == COMMUNITY_ANY || ld2 == wlc->ld2))
return (1);
}
return (0);
}
int
-community_large_set(struct rde_aspath *asp, int64_t as, int64_t ld1,
- int64_t ld2)
+community_large_set(struct rde_aspath *asp, struct filter_community *fc,
+ struct rde_peer *peer)
{
- struct wire_largecommunity *bar;
+ struct wire_largecommunity *wlc;
struct attr *attr;
u_int8_t *p = NULL;
unsigned int i, ncommunities = 0;
+ u_int32_t as, ld1, ld2;
u_int8_t f = ATTR_OPTIONAL|ATTR_TRANSITIVE;
+ if (fc->dflag1 == COMMUNITY_ANY || fc->dflag2 == COMMUNITY_ANY ||
+ fc->dflag3 == COMMUNITY_ANY ||
+ community_extract(fc, peer, 1, 1, &as) == -1 ||
+ community_extract(fc, peer, 2, 1, &ld1) == -1 ||
+ community_extract(fc, peer, 3, 1, &ld2) == -1)
+ /* can't match community */
+ return (0);
+
+ as = htonl(as);
+ ld1 = htonl(ld1);
+ ld2 = htonl(ld2);
+
attr = attr_optget(asp, ATTR_LARGE_COMMUNITIES);
if (attr != NULL) {
p = attr->data;
@@ -1430,9 +1511,8 @@ community_large_set(struct rde_aspath *asp, int64_t as, int64_t ld1,
/* first check if the community is not already set */
for (i = 0; i < ncommunities; i++) {
- bar = (struct wire_largecommunity *)p;
- if (bar->as == htobe32(as) && bar->ld1 == htobe32(ld1) &&
- bar->ld2 == htobe32(ld2))
+ wlc = (struct wire_largecommunity *)p;
+ if (wlc->as == as && wlc->ld1 == ld1 && wlc->ld2 == ld2)
/* already present, nothing todo */
return (1);
p += 12;
@@ -1445,10 +1525,10 @@ community_large_set(struct rde_aspath *asp, int64_t as, int64_t ld1,
if ((p = reallocarray(NULL, ncommunities, 12)) == NULL)
fatal("community_set");
- bar = (struct wire_largecommunity *)p;
- bar->as = htobe32(as);
- bar->ld1 = htobe32(ld1);
- bar->ld2 = htobe32(ld2);
+ wlc = (struct wire_largecommunity *)p;
+ wlc->as = as;
+ wlc->ld1 = ld1;
+ wlc->ld2 = ld2;
if (attr != NULL) {
memcpy(p + 12, attr->data, attr->len);
@@ -1463,14 +1543,14 @@ community_large_set(struct rde_aspath *asp, int64_t as, int64_t ld1,
}
void
-community_large_delete(struct rde_aspath *asp, int64_t as, int64_t ld1,
- int64_t ld2)
+community_large_delete(struct rde_aspath *asp, struct filter_community *fc,
+ struct rde_peer *peer)
{
- struct wire_largecommunity *bar;
+ struct wire_largecommunity *wlc;
struct attr *attr;
u_int8_t *p, *n;
u_int16_t l = 0, len = 0;
- u_int32_t eas, eld1, eld2;
+ u_int32_t as, ld1, ld2;
u_int8_t f;
attr = attr_optget(asp, ATTR_LARGE_COMMUNITIES);
@@ -1478,17 +1558,24 @@ community_large_delete(struct rde_aspath *asp, int64_t as, int64_t ld1,
/* no attr nothing to do */
return;
+ if (community_extract(fc, peer, 1, 1, &as) == -1 ||
+ community_extract(fc, peer, 2, 1, &ld1) == -1 ||
+ community_extract(fc, peer, 3, 1, &ld2) == -1)
+ /* can't match community */
+ return;
+
+ as = htonl(as);
+ ld1 = htonl(ld1);
+ ld2 = htonl(ld2);
+
p = attr->data;
for (len = 0; l < attr->len; l += 12) {
- bar = (struct wire_largecommunity *)p;
+ wlc = (struct wire_largecommunity *)p;
p += 12;
- eas = betoh32(bar->as);
- eld1 = betoh32(bar->ld1);
- eld2 = betoh32(bar->ld2);
- if ((as == COMMUNITY_ANY || as == eas) &&
- (ld1 == COMMUNITY_ANY || ld1 == eld1) &&
- (ld2 == COMMUNITY_ANY || ld2 == eld2))
+ if ((fc->dflag1 == COMMUNITY_ANY || as == wlc->as) &&
+ (fc->dflag2 == COMMUNITY_ANY || ld1 == wlc->ld1) &&
+ (fc->dflag3 == COMMUNITY_ANY || ld2 == wlc->ld2))
/* match */
continue;
len += 12;
@@ -1504,18 +1591,15 @@ community_large_delete(struct rde_aspath *asp, int64_t as, int64_t ld1,
p = attr->data;
for (l = 0; l < len && p < attr->data + attr->len; ) {
- bar = (struct wire_largecommunity *)p;
+ wlc = (struct wire_largecommunity *)p;
p += 12;
- eas = betoh32(bar->as);
- eld1 = betoh32(bar->ld1);
- eld2 = betoh32(bar->ld2);
- if ((as == COMMUNITY_ANY || as == eas) &&
- (ld1 == COMMUNITY_ANY || ld1 == eld1) &&
- (ld2 == COMMUNITY_ANY || ld2 == eld2))
+ if ((fc->dflag1 == COMMUNITY_ANY || as == wlc->as) &&
+ (fc->dflag2 == COMMUNITY_ANY || ld1 == wlc->ld1) &&
+ (fc->dflag3 == COMMUNITY_ANY || ld2 == wlc->ld2))
/* match */
continue;
- memcpy(n + l, bar, sizeof(*bar));
+ memcpy(n + l, wlc, sizeof(*wlc));
l += 12;
}
@@ -1526,7 +1610,6 @@ community_large_delete(struct rde_aspath *asp, int64_t as, int64_t ld1,
free(n);
}
-
u_char *
community_ext_delete_non_trans(u_char *data, u_int16_t len, u_int16_t *newlen)
{
diff --git a/usr.sbin/bgpd/rde_filter.c b/usr.sbin/bgpd/rde_filter.c
index 79d2bd1728c..d731bed35cc 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.113 2018/11/14 14:03:36 claudio Exp $ */
+/* $OpenBSD: rde_filter.c,v 1.114 2018/11/28 08:32:27 claudio Exp $ */
/*
* Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
@@ -40,8 +40,6 @@ rde_apply_set(struct filter_set_head *sh, struct filterstate *state,
{
struct filter_set *set;
u_char *np;
- int as, type;
- int64_t las, ld1, ld2;
u_int32_t prep_as;
u_int16_t nl;
u_int8_t prepend;
@@ -142,172 +140,28 @@ rde_apply_set(struct filter_set_head *sh, struct filterstate *state,
&state->nexthop, &state->nhflags);
break;
case ACTION_SET_COMMUNITY:
- switch (set->action.community.as) {
- case COMMUNITY_ERROR:
- case COMMUNITY_ANY:
- fatalx("%s: bad community string", __func__);
- case COMMUNITY_NEIGHBOR_AS:
- as = peer->conf.remote_as;
- break;
- case COMMUNITY_LOCAL_AS:
- as = peer->conf.local_as;
- break;
- default:
- as = set->action.community.as;
- break;
- }
-
switch (set->action.community.type) {
- case COMMUNITY_ERROR:
- case COMMUNITY_ANY:
- fatalx("%s: bad community string", __func__);
- case COMMUNITY_NEIGHBOR_AS:
- type = peer->conf.remote_as;
- break;
- case COMMUNITY_LOCAL_AS:
- type = peer->conf.local_as;
+ case COMMUNITY_TYPE_BASIC:
+ community_set(&state->aspath,
+ &set->action.community, peer);
break;
- default:
- type = set->action.community.type;
+ case COMMUNITY_TYPE_LARGE:
+ community_large_set(&state->aspath,
+ &set->action.community, peer);
break;
}
-
- community_set(&state->aspath, as, type);
break;
case ACTION_DEL_COMMUNITY:
- switch (set->action.community.as) {
- case COMMUNITY_ERROR:
- fatalx("%s: bad community string", __func__);
- case COMMUNITY_NEIGHBOR_AS:
- as = peer->conf.remote_as;
- break;
- case COMMUNITY_LOCAL_AS:
- as = peer->conf.local_as;
- break;
- case COMMUNITY_ANY:
- default:
- as = set->action.community.as;
- break;
- }
-
switch (set->action.community.type) {
- case COMMUNITY_ERROR:
- fatalx("%s: bad community string", __func__);
- case COMMUNITY_NEIGHBOR_AS:
- type = peer->conf.remote_as;
- break;
- case COMMUNITY_LOCAL_AS:
- type = peer->conf.local_as;
- break;
- case COMMUNITY_ANY:
- default:
- type = set->action.community.type;
- break;
- }
-
- community_delete(&state->aspath, as, type);
- break;
- case ACTION_SET_LARGE_COMMUNITY:
- switch (set->action.large_community.as) {
- case COMMUNITY_ERROR:
- fatalx("%s: bad large community string",
- __func__);
- case COMMUNITY_NEIGHBOR_AS:
- las = peer->conf.remote_as;
- break;
- case COMMUNITY_LOCAL_AS:
- las = peer->conf.local_as;
- break;
- case COMMUNITY_ANY:
- default:
- las = set->action.large_community.as;
- break;
- }
-
- switch (set->action.large_community.ld1) {
- case COMMUNITY_ERROR:
- fatalx("%s: bad large community string",
- __func__);
- case COMMUNITY_NEIGHBOR_AS:
- ld1 = peer->conf.remote_as;
- break;
- case COMMUNITY_LOCAL_AS:
- ld1 = peer->conf.local_as;
+ case COMMUNITY_TYPE_BASIC:
+ community_delete(&state->aspath,
+ &set->action.community, peer);
break;
- case COMMUNITY_ANY:
- default:
- ld1 = set->action.large_community.ld1;
+ case COMMUNITY_TYPE_LARGE:
+ community_large_delete(&state->aspath,
+ &set->action.community, peer);
break;
}
-
- switch (set->action.large_community.ld2) {
- case COMMUNITY_ERROR:
- fatalx("%s: bad large community string",
- __func__);
- case COMMUNITY_NEIGHBOR_AS:
- ld2 = peer->conf.remote_as;
- break;
- case COMMUNITY_LOCAL_AS:
- ld2 = peer->conf.local_as;
- break;
- case COMMUNITY_ANY:
- default:
- ld2 = set->action.large_community.ld2;
- break;
- }
-
- community_large_set(&state->aspath, las, ld1, ld2);
- break;
- case ACTION_DEL_LARGE_COMMUNITY:
- switch (set->action.large_community.as) {
- case COMMUNITY_ERROR:
- fatalx("%s: bad large community string",
- __func__);
- case COMMUNITY_NEIGHBOR_AS:
- las = peer->conf.remote_as;
- break;
- case COMMUNITY_LOCAL_AS:
- las = peer->conf.local_as;
- break;
- case COMMUNITY_ANY:
- default:
- las = set->action.large_community.as;
- break;
- }
-
- switch (set->action.large_community.ld1) {
- case COMMUNITY_ERROR:
- fatalx("%s: bad large community string",
- __func__);
- case COMMUNITY_NEIGHBOR_AS:
- ld1 = peer->conf.remote_as;
- break;
- case COMMUNITY_LOCAL_AS:
- ld1 = peer->conf.local_as;
- break;
- case COMMUNITY_ANY:
- default:
- ld1 = set->action.large_community.ld1;
- break;
- }
-
- switch (set->action.large_community.ld2) {
- case COMMUNITY_ERROR:
- fatalx("%s: bad large community string",
- __func__);
- case COMMUNITY_NEIGHBOR_AS:
- ld2 = peer->conf.remote_as;
- break;
- case COMMUNITY_LOCAL_AS:
- ld2 = peer->conf.local_as;
- break;
- case COMMUNITY_ANY:
- default:
- ld2 = set->action.large_community.ld2;
- break;
- }
-
- community_large_delete(&state->aspath, las, ld1, ld2);
break;
case ACTION_PFTABLE:
/* convert pftable name to an id */
@@ -348,9 +202,8 @@ int
rde_filter_match(struct filter_rule *f, struct rde_peer *peer,
struct filterstate *state, struct prefix *p)
{
- int cas, type;
- int64_t las, ld1, ld2;
- struct rde_aspath *asp = NULL;
+ struct rde_aspath *asp = NULL;
+ int i;
if (state != NULL)
asp = &state->aspath;
@@ -376,89 +229,28 @@ rde_filter_match(struct filter_rule *f, struct rde_peer *peer,
f->match.aslen.aslen) == 0)
return (0);
- if (asp != NULL && f->match.community.as != COMMUNITY_UNSET) {
- switch (f->match.community.as) {
- case COMMUNITY_ERROR:
- fatalx("rde_filter_match bad community string");
- case COMMUNITY_NEIGHBOR_AS:
- cas = peer->conf.remote_as;
- break;
- case COMMUNITY_LOCAL_AS:
- cas = peer->conf.local_as;
- break;
- default:
- cas = f->match.community.as;
- break;
- }
-
- switch (f->match.community.type) {
- case COMMUNITY_ERROR:
- fatalx("rde_filter_match bad community string");
- case COMMUNITY_NEIGHBOR_AS:
- type = peer->conf.remote_as;
+ for (i = 0; asp != NULL && i < MAX_COMM_MATCH; i++) {
+ switch (f->match.community[i].type) {
+ case COMMUNITY_TYPE_NONE:
+ i = MAX_COMM_MATCH;
break;
- case COMMUNITY_LOCAL_AS:
- type = peer->conf.local_as;
+ case COMMUNITY_TYPE_BASIC:
+ if (community_match(asp, &f->match.community[i],
+ peer) == 0)
+ return (0);
break;
- default:
- type = f->match.community.type;
+ case COMMUNITY_TYPE_LARGE:
+ if (community_large_match(asp, &f->match.community[i],
+ peer) == 0)
+ return (0);
break;
}
-
- if (community_match(asp, cas, type) == 0)
- return (0);
}
if (asp != NULL &&
(f->match.ext_community.flags & EXT_COMMUNITY_FLAG_VALID))
if (community_ext_match(asp, &f->match.ext_community,
peer->conf.remote_as) == 0)
return (0);
- if (asp != NULL && f->match.large_community.as != COMMUNITY_UNSET) {
- switch (f->match.large_community.as) {
- case COMMUNITY_ERROR:
- fatalx("rde_filter_match bad community string");
- case COMMUNITY_NEIGHBOR_AS:
- las = peer->conf.remote_as;
- break;
- case COMMUNITY_LOCAL_AS:
- las = peer->conf.local_as;
- break;
- default:
- las = f->match.large_community.as;
- break;
- }
-
- switch (f->match.large_community.ld1) {
- case COMMUNITY_ERROR:
- fatalx("rde_filter_match bad community string");
- case COMMUNITY_NEIGHBOR_AS:
- ld1 = peer->conf.remote_as;
- break;
- case COMMUNITY_LOCAL_AS:
- ld1 = peer->conf.local_as;
- break;
- default:
- ld1 = f->match.large_community.ld1;
- break;
- }
-
- switch (f->match.large_community.ld2) {
- case COMMUNITY_ERROR:
- fatalx("rde_filter_match bad community string");
- case COMMUNITY_NEIGHBOR_AS:
- ld2 = peer->conf.remote_as;
- break;
- case COMMUNITY_LOCAL_AS:
- ld2 = peer->conf.local_as;
- break;
- default:
- ld2 = f->match.large_community.ld2;
- break;
- }
-
- if (community_large_match(asp, las, ld1, ld2) == 0)
- return (0);
- }
if (state != NULL && f->match.nexthop.flags != 0) {
struct bgpd_addr *nexthop, *cmpaddr;
@@ -744,11 +536,8 @@ filterset_cmp(struct filter_set *a, struct filter_set *b)
if (a->type == ACTION_SET_COMMUNITY ||
a->type == ACTION_DEL_COMMUNITY) { /* a->type == b->type */
- /* compare community */
- if (a->action.community.as - b->action.community.as != 0)
- return (a->action.community.as -
- b->action.community.as);
- return (a->action.community.type - b->action.community.type);
+ return (memcmp(&a->action.community, &b->action.community,
+ sizeof(a->action.community)));
}
if (a->type == ACTION_SET_EXT_COMMUNITY ||
@@ -757,21 +546,6 @@ filterset_cmp(struct filter_set *a, struct filter_set *b)
&b->action.ext_community, sizeof(a->action.ext_community)));
}
- if (a->type == ACTION_SET_LARGE_COMMUNITY ||
- a->type == ACTION_DEL_LARGE_COMMUNITY) { /* a->type == b->type */
- /* compare community */
- if (a->action.large_community.as -
- b->action.large_community.as != 0)
- return (a->action.large_community.as -
- b->action.large_community.as);
- if (a->action.large_community.ld1 -
- b->action.large_community.ld1 != 0)
- return (a->action.large_community.ld1 -
- b->action.large_community.ld1);
- return (a->action.large_community.ld2 -
- b->action.large_community.ld2);
- }
-
if (a->type == ACTION_SET_NEXTHOP && b->type == ACTION_SET_NEXTHOP) {
/*
* This is the only interesting case, all others are considered
@@ -845,14 +619,6 @@ filterset_equal(struct filter_set_head *ah, struct filter_set_head *bh)
sizeof(a->action.community)) == 0)
continue;
break;
- case ACTION_DEL_LARGE_COMMUNITY:
- case ACTION_SET_LARGE_COMMUNITY:
- if (a->type == b->type &&
- memcmp(&a->action.large_community,
- &b->action.large_community,
- sizeof(a->action.large_community)) == 0)
- continue;
- break;
case ACTION_PFTABLE:
case ACTION_PFTABLE_ID:
if (b->type == ACTION_PFTABLE)
@@ -936,10 +702,6 @@ filterset_name(enum action_types type)
return ("community");
case ACTION_DEL_COMMUNITY:
return ("community delete");
- case ACTION_SET_LARGE_COMMUNITY:
- return ("large-community");
- case ACTION_DEL_LARGE_COMMUNITY:
- return ("large-community delete");
case ACTION_PFTABLE:
case ACTION_PFTABLE_ID:
return ("pftable");
diff --git a/usr.sbin/bgpd/rde_update.c b/usr.sbin/bgpd/rde_update.c
index a20922782b1..8157342058e 100644
--- a/usr.sbin/bgpd/rde_update.c
+++ b/usr.sbin/bgpd/rde_update.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_update.c,v 1.103 2018/11/04 12:34:54 claudio Exp $ */
+/* $OpenBSD: rde_update.c,v 1.104 2018/11/28 08:32:27 claudio Exp $ */
/*
* Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
@@ -66,6 +66,22 @@ RB_GENERATE(uptree_attr, update_attr, entry, up_attr_cmp)
SIPHASH_KEY uptree_key;
+static struct filter_community comm_no_advertise = {
+ .type = COMMUNITY_TYPE_BASIC,
+ .data1 = COMMUNITY_WELLKNOWN,
+ .data2 = COMMUNITY_NO_ADVERTISE
+};
+static struct filter_community comm_no_export = {
+ .type = COMMUNITY_TYPE_BASIC,
+ .data1 = COMMUNITY_WELLKNOWN,
+ .data2 = COMMUNITY_NO_EXPORT
+};
+static struct filter_community comm_no_expsubconfed = {
+ .type = COMMUNITY_TYPE_BASIC,
+ .data1 = COMMUNITY_WELLKNOWN,
+ .data2 = COMMUNITY_NO_EXPSUBCONFED
+};
+
void
up_init(struct rde_peer *peer)
{
@@ -329,14 +345,14 @@ up_test_update(struct rde_peer *peer, struct prefix *p)
}
/* well known communities */
- if (community_match(asp, COMMUNITY_WELLKNOWN, COMMUNITY_NO_ADVERTISE))
- return (0);
- if (peer->conf.ebgp && community_match(asp, COMMUNITY_WELLKNOWN,
- COMMUNITY_NO_EXPORT))
- return (0);
- if (peer->conf.ebgp && community_match(asp, COMMUNITY_WELLKNOWN,
- COMMUNITY_NO_EXPSUBCONFED))
+ if (community_match(asp, &comm_no_advertise, NULL))
return (0);
+ if (peer->conf.ebgp) {
+ if (community_match(asp, &comm_no_export, NULL))
+ return (0);
+ if (community_match(asp, &comm_no_expsubconfed, NULL))
+ return (0);
+ }
/*
* Don't send messages back to originator