diff options
author | Peter Hessler <phessler@cvs.openbsd.org> | 2016-10-14 16:05:37 +0000 |
---|---|---|
committer | Peter Hessler <phessler@cvs.openbsd.org> | 2016-10-14 16:05:37 +0000 |
commit | 01b441ff7f82f081c867c730843a20ced322c69a (patch) | |
tree | ca0453d28e3be1dd47c8ca80ee1921b62665f03a /usr.sbin/bgpctl | |
parent | ab11fdd7396c99faa03965917bfae604b99150fb (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.8 | 7 | ||||
-rw-r--r-- | usr.sbin/bgpctl/bgpctl.c | 50 | ||||
-rw-r--r-- | usr.sbin/bgpctl/parser.c | 85 | ||||
-rw-r--r-- | usr.sbin/bgpctl/parser.h | 3 |
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; |