summaryrefslogtreecommitdiff
path: root/usr.sbin/bgpctl
diff options
context:
space:
mode:
authorPeter Hessler <phessler@cvs.openbsd.org>2016-10-14 16:05:37 +0000
committerPeter Hessler <phessler@cvs.openbsd.org>2016-10-14 16:05:37 +0000
commit01b441ff7f82f081c867c730843a20ced322c69a (patch)
treeca0453d28e3be1dd47c8ca80ee1921b62665f03a /usr.sbin/bgpctl
parentab11fdd7396c99faa03965917bfae604b99150fb (diff)
Add support for draft-ietf-idr-large-community
Joint work with Job Snijders, many thanks! OK benno@ deraadt@
Diffstat (limited to 'usr.sbin/bgpctl')
-rw-r--r--usr.sbin/bgpctl/bgpctl.87
-rw-r--r--usr.sbin/bgpctl/bgpctl.c50
-rw-r--r--usr.sbin/bgpctl/parser.c85
-rw-r--r--usr.sbin/bgpctl/parser.h3
4 files changed, 140 insertions, 5 deletions
diff --git a/usr.sbin/bgpctl/bgpctl.8 b/usr.sbin/bgpctl/bgpctl.8
index 2dab042d685..7c3b7128925 100644
--- a/usr.sbin/bgpctl/bgpctl.8
+++ b/usr.sbin/bgpctl/bgpctl.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: bgpctl.8,v 1.69 2016/05/25 14:15:59 jmc Exp $
+.\" $OpenBSD: bgpctl.8,v 1.70 2016/10/14 16:05:35 phessler Exp $
.\"
.\" Copyright (c) 2003 Henning Brauer <henning@openbsd.org>
.\"
@@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: May 25 2016 $
+.Dd $Mdocdate: October 14 2016 $
.Dt BGPCTL 8
.Os
.Sh NAME
@@ -300,6 +300,9 @@ anywhere in the AS path.
.It Cm community Ar community
Show all entries with community
.Ar community .
+.It Cm large-community Ar large-community
+Show all entries with large-community
+.Ar large-community .
.It Cm empty-as
Show all entries that are internal routes with no AS's in the AS path.
.It Cm memory
diff --git a/usr.sbin/bgpctl/bgpctl.c b/usr.sbin/bgpctl/bgpctl.c
index b3361c4943b..91e2cbc70d2 100644
--- a/usr.sbin/bgpctl/bgpctl.c
+++ b/usr.sbin/bgpctl/bgpctl.c
@@ -1,7 +1,9 @@
-/* $OpenBSD: bgpctl.c,v 1.189 2016/10/14 09:40:54 phessler Exp $ */
+/* $OpenBSD: bgpctl.c,v 1.190 2016/10/14 16:05:35 phessler Exp $ */
/*
* Copyright (c) 2003 Henning Brauer <henning@openbsd.org>
+ * Copyright (c) 2016 Job Snijders <job@instituut.net>
+ * Copyright (c) 2016 Peter Hessler <phessler@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -82,6 +84,7 @@ void show_rib_brief(struct ctl_show_rib *, u_char *);
void show_rib_detail(struct ctl_show_rib *, u_char *, int);
void show_attr(void *, u_int16_t);
void show_community(u_char *, u_int16_t);
+void show_large_community(u_char *, u_int16_t);
void show_ext_community(u_char *, u_int16_t);
char *fmt_mem(int64_t);
int show_rib_memory_msg(struct imsg *);
@@ -254,6 +257,13 @@ main(int argc, char *argv[])
sizeof(res->community));
type = IMSG_CTL_SHOW_RIB_COMMUNITY;
}
+ if (res->large_community.as != COMMUNITY_UNSET &&
+ res->large_community.ld1 != COMMUNITY_UNSET &&
+ res->large_community.ld2 != COMMUNITY_UNSET) {
+ memcpy(&ribreq.large_community, &res->large_community,
+ sizeof(res->large_community));
+ type = IMSG_CTL_SHOW_RIB_LARGECOMMUNITY;
+ }
memcpy(&ribreq.neighbor, &neighbor, sizeof(ribreq.neighbor));
strlcpy(ribreq.rib, res->rib, sizeof(ribreq.rib));
ribreq.aid = res->aid;
@@ -275,6 +285,11 @@ main(int argc, char *argv[])
res->community.type != COMMUNITY_UNSET)
memcpy(&ribreq.community, &res->community,
sizeof(res->community));
+ if (res->large_community.as != COMMUNITY_UNSET &&
+ res->large_community.ld1 != COMMUNITY_UNSET &&
+ res->large_community.ld2 != COMMUNITY_UNSET)
+ memcpy(&ribreq.large_community, &res->large_community,
+ sizeof(res->large_community));
memcpy(&ribreq.neighbor, &neighbor, sizeof(ribreq.neighbor));
ribreq.aid = res->aid;
ribreq.flags = res->flags;
@@ -377,6 +392,11 @@ main(int argc, char *argv[])
res->community.type != COMMUNITY_UNSET)
memcpy(&ribreq.community, &res->community,
sizeof(res->community));
+ if (res->large_community.as != COMMUNITY_UNSET &&
+ res->large_community.ld1 != COMMUNITY_UNSET &&
+ res->large_community.ld2 != COMMUNITY_UNSET)
+ memcpy(&ribreq.large_community, &res->large_community,
+ sizeof(res->large_community));
memcpy(&ribreq.neighbor, &neighbor, sizeof(ribreq.neighbor));
ribreq.aid = res->aid;
ribreq.flags = res->flags;
@@ -1425,6 +1445,11 @@ show_attr(void *b, u_int16_t len)
show_community(data, alen);
printf("\n");
break;
+ case ATTR_LARGE_COMMUNITIES:
+ printf(" Large Communities: ");
+ show_large_community(data, alen);
+ printf("\n");
+ break;
case ATTR_AGGREGATOR:
memcpy(&as, data, sizeof(as));
memcpy(&id, data + sizeof(as), sizeof(id));
@@ -1520,6 +1545,29 @@ show_community(u_char *data, u_int16_t len)
}
void
+show_large_community(u_char *data, u_int16_t len)
+{
+ u_int32_t a, l1, l2;
+ u_int16_t i;
+
+ if (len % 12)
+ return;
+
+ for (i = 0; i < len; i += 12) {
+ memcpy(&a, data + i, sizeof(a));
+ memcpy(&l1, data + i + 4, sizeof(l1));
+ memcpy(&l2, data + i + 8, sizeof(l2));
+ a = ntohl(a);
+ l1 = ntohl(l1);
+ l2 = ntohl(l2);
+ printf("%u:%u:%u", a, l1, l2);
+
+ if (i + 12 < len)
+ printf(" ");
+ }
+}
+
+void
show_ext_community(u_char *data, u_int16_t len)
{
u_int64_t ext;
diff --git a/usr.sbin/bgpctl/parser.c b/usr.sbin/bgpctl/parser.c
index 72ddca08b36..4b65785a0a6 100644
--- a/usr.sbin/bgpctl/parser.c
+++ b/usr.sbin/bgpctl/parser.c
@@ -1,7 +1,9 @@
-/* $OpenBSD: parser.c,v 1.73 2015/10/11 19:53:57 sthen Exp $ */
+/* $OpenBSD: parser.c,v 1.74 2016/10/14 16:05:35 phessler Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
+ * Copyright (c) 2016 Job Snijders <job@instituut.net>
+ * Copyright (c) 2016 Peter Hessler <phessler@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -44,6 +46,7 @@ enum token_type {
PEERDESC,
RIBNAME,
COMMUNITY,
+ LARGE_COMMUNITY,
LOCALPREF,
MED,
NEXTHOP,
@@ -90,11 +93,13 @@ static const struct token t_show_mrt_as[];
static const struct token t_show_prefix[];
static const struct token t_show_ip[];
static const struct token t_show_community[];
+static const struct token t_show_largecommunity[];
static const struct token t_network[];
static const struct token t_network_show[];
static const struct token t_prefix[];
static const struct token t_set[];
static const struct token t_community[];
+static const struct token t_largecommunity[];
static const struct token t_localpref[];
static const struct token t_med[];
static const struct token t_nexthop[];
@@ -160,6 +165,7 @@ static const struct token t_show_rib[] = {
{ ASTYPE, "peer-as", AS_PEER, t_show_rib_as},
{ ASTYPE, "empty-as", AS_EMPTY, t_show_rib},
{ KEYWORD, "community", NONE, t_show_community},
+ { KEYWORD, "large-community", NONE, t_show_largecommunity},
{ FLAG, "best", F_CTL_ACTIVE, t_show_rib},
{ FLAG, "selected", F_CTL_ACTIVE, t_show_rib},
{ FLAG, "detail", F_CTL_DETAIL, t_show_rib},
@@ -275,6 +281,11 @@ static const struct token t_show_community[] = {
{ ENDTOKEN, "", NONE, NULL}
};
+static const struct token t_show_largecommunity[] = {
+ { LARGE_COMMUNITY, "", NONE, t_show_rib},
+ { ENDTOKEN, "", NONE, NULL}
+};
+
static const struct token t_network[] = {
{ KEYWORD, "add", NETWORK_ADD, t_prefix},
{ KEYWORD, "delete", NETWORK_REMOVE, t_prefix},
@@ -299,6 +310,7 @@ static const struct token t_network_show[] = {
static const struct token t_set[] = {
{ NOTOKEN, "", NONE, NULL},
{ KEYWORD, "community", NONE, t_community},
+ { KEYWORD, "large-community", NONE, t_largecommunity},
{ KEYWORD, "localpref", NONE, t_localpref},
{ KEYWORD, "med", NONE, t_med},
{ KEYWORD, "metric", NONE, t_med},
@@ -317,6 +329,11 @@ static const struct token t_community[] = {
{ ENDTOKEN, "", NONE, NULL}
};
+static const struct token t_largecommunity[] = {
+ { LARGE_COMMUNITY, "", NONE, t_set},
+ { ENDTOKEN, "", NONE, NULL}
+};
+
static const struct token t_localpref[] = {
{ LOCALPREF, "", NONE, t_set},
{ ENDTOKEN, "", NONE, NULL}
@@ -391,6 +408,8 @@ int parse_number(const char *, struct parse_result *,
enum token_type);
int getcommunity(const char *);
int parse_community(const char *, struct parse_result *);
+u_int getlargecommunity(const char *);
+int parse_largecommunity(const char *, struct parse_result *);
int parse_nexthop(const char *, struct parse_result *);
int bgpctl_getopt(int *, char **[], int);
@@ -403,6 +422,9 @@ parse(int argc, char *argv[])
bzero(&res, sizeof(res));
res.community.as = COMMUNITY_UNSET;
res.community.type = COMMUNITY_UNSET;
+ res.large_community.as = COMMUNITY_UNSET;
+ res.large_community.ld1 = COMMUNITY_UNSET;
+ res.large_community.ld2 = COMMUNITY_UNSET;
TAILQ_INIT(&res.set);
if ((res.irr_outdir = getcwd(NULL, 0)) == NULL) {
fprintf(stderr, "getcwd failed: %s\n", strerror(errno));
@@ -556,6 +578,13 @@ match_token(int *argc, char **argv[], const struct token table[])
t = &table[i];
}
break;
+ case LARGE_COMMUNITY:
+ if (word != NULL && wordlen > 0 &&
+ parse_largecommunity(word, &res)) {
+ match++;
+ t = &table[i];
+ }
+ break;
case LOCALPREF:
case MED:
case PREPNBR:
@@ -668,6 +697,9 @@ show_valid_args(const struct token table[])
case COMMUNITY:
fprintf(stderr, " <community>\n");
break;
+ case LARGE_COMMUNITY:
+ fprintf(stderr, " <large-community>\n");
+ break;
case LOCALPREF:
case MED:
case PREPNBR:
@@ -961,6 +993,57 @@ done:
return (1);
}
+u_int
+getlargecommunity(const char *s)
+{
+ const char *errstr;
+ u_int32_t uval;
+
+ if (strcmp(s, "*") == 0)
+ return (COMMUNITY_ANY);
+
+ uval = strtonum(s, 0, UINT_MAX, &errstr);
+ if (errstr)
+ errx(1, "Large Community is %s: %s", errstr, s);
+
+ return (uval);
+}
+
+int
+parse_largecommunity(const char *word, struct parse_result *r)
+{
+ struct filter_set *fs;
+ char *p = strdup(word);
+ char *array[3];
+ int64_t as, ld1, ld2;
+ int i = 0;
+
+ while (p != NULL) {
+ array[i++] = p;
+ p = strchr(p, ':');
+ if (p)
+ *p++ = 0;
+ }
+
+ as = getlargecommunity(array[0]);
+ ld1 = getlargecommunity(array[1]);
+ ld2 = getlargecommunity(array[2]);
+
+ if ((fs = calloc(1, sizeof(struct filter_set))) == NULL)
+ err(1, NULL);
+ fs->type = ACTION_SET_LARGE_COMMUNITY;
+ fs->action.large_community.as = as;
+ fs->action.large_community.ld1 = ld1;
+ fs->action.large_community.ld2 = ld2;
+
+ r->large_community.as = as;
+ r->large_community.ld1 = ld1;
+ r->large_community.ld2 = ld2;
+
+ TAILQ_INSERT_TAIL(&r->set, fs, entry);
+ return (1);
+}
+
int
parse_nexthop(const char *word, struct parse_result *r)
{
diff --git a/usr.sbin/bgpctl/parser.h b/usr.sbin/bgpctl/parser.h
index d0d0ab95a94..cc66a04a4fc 100644
--- a/usr.sbin/bgpctl/parser.h
+++ b/usr.sbin/bgpctl/parser.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: parser.h,v 1.27 2015/04/17 07:51:09 phessler Exp $ */
+/* $OpenBSD: parser.h,v 1.28 2016/10/14 16:05:35 phessler Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -63,6 +63,7 @@ struct parse_result {
struct filter_as as;
struct filter_set_head set;
struct filter_community community;
+ struct filter_largecommunity large_community;
char peerdesc[PEER_DESCR_LEN];
char rib[PEER_DESCR_LEN];
char *irr_outdir;