diff options
Diffstat (limited to 'usr.sbin/bgpctl')
-rw-r--r-- | usr.sbin/bgpctl/parser.c | 206 |
1 files changed, 65 insertions, 141 deletions
diff --git a/usr.sbin/bgpctl/parser.c b/usr.sbin/bgpctl/parser.c index 86079fc2fea..08c4da067e0 100644 --- a/usr.sbin/bgpctl/parser.c +++ b/usr.sbin/bgpctl/parser.c @@ -1,4 +1,4 @@ -/* $OpenBSD: parser.c,v 1.125 2023/04/15 10:36:59 claudio Exp $ */ +/* $OpenBSD: parser.c,v 1.126 2023/04/17 10:23:32 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -50,8 +50,7 @@ enum token_type { COMMUNICATION, COMMUNITY, EXTCOMMUNITY, - EXTCOM_SUBTYPE, - LARGE_COMMUNITY, + LRGCOMMUNITY, LOCALPREF, MED, NEXTHOP, @@ -96,19 +95,11 @@ static const struct token t_show_rib_as[]; 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_extcommunity[]; -static const struct token t_show_ext_subtype[]; -static const struct token t_show_largecommunity[]; static const struct token t_network[]; static const struct token t_bulk[]; 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_extcommunity[]; -static const struct token t_ext_subtype[]; -static const struct token t_largecommunity[]; static const struct token t_localpref[]; static const struct token t_med[]; static const struct token t_nexthop[]; @@ -173,14 +164,14 @@ static const struct token t_show_rib[] = { { ASTYPE, "as", AS_ALL, t_show_rib_as}, { KEYWORD, "avs", NONE, t_show_avs}, { FLAG, "best", F_CTL_BEST, t_show_rib}, - { KEYWORD, "community", NONE, t_show_community}, + { COMMUNITY, "community", NONE, t_show_rib}, { FLAG, "detail", F_CTL_DETAIL, t_show_rib}, { ASTYPE, "empty-as", AS_EMPTY, t_show_rib}, { FLAG, "error", F_CTL_INVALID, t_show_rib}, - { KEYWORD, "ext-community", NONE, t_show_extcommunity}, + { EXTCOMMUNITY, "ext-community", NONE, t_show_rib}, { FLAG, "in", F_CTL_ADJ_IN, t_show_rib}, { FLAG, "invalid", F_CTL_INELIGIBLE, t_show_rib}, - { KEYWORD, "large-community", NONE, t_show_largecommunity}, + { LRGCOMMUNITY, "large-community", NONE, t_show_rib}, { FLAG, "leaked", F_CTL_LEAKED, t_show_rib}, { KEYWORD, "memory", SHOW_RIB_MEM, NULL}, { KEYWORD, "neighbor", NONE, t_show_rib_neigh}, @@ -336,39 +327,6 @@ static const struct token t_show_ip[] = { { ENDTOKEN, "", NONE, NULL} }; -static const struct token t_show_community[] = { - { COMMUNITY, "", NONE, t_show_rib}, - { ENDTOKEN, "", NONE, NULL} -}; - -static const struct token t_show_extcommunity[] = { - { EXTCOM_SUBTYPE, "bdc", NONE, t_show_ext_subtype}, - { EXTCOM_SUBTYPE, "defgw", NONE, t_show_ext_subtype}, - { EXTCOM_SUBTYPE, "esi-lab", NONE, t_show_ext_subtype}, - { EXTCOM_SUBTYPE, "esi-rt", NONE, t_show_ext_subtype}, - { EXTCOM_SUBTYPE, "l2vid", NONE, t_show_ext_subtype}, - { EXTCOM_SUBTYPE, "mac-mob", NONE, t_show_ext_subtype}, - { EXTCOM_SUBTYPE, "odi", NONE, t_show_ext_subtype}, - { EXTCOM_SUBTYPE, "ori", NONE, t_show_ext_subtype}, - { EXTCOM_SUBTYPE, "ort", NONE, t_show_ext_subtype}, - { EXTCOM_SUBTYPE, "ovs", NONE, t_show_ext_subtype}, - { EXTCOM_SUBTYPE, "rt", NONE, t_show_ext_subtype}, - { EXTCOM_SUBTYPE, "soo", NONE, t_show_ext_subtype}, - { EXTCOM_SUBTYPE, "srcas", NONE, t_show_ext_subtype}, - { EXTCOM_SUBTYPE, "vrfri", NONE, t_show_ext_subtype}, - { ENDTOKEN, "", NONE, NULL} -}; - -static const struct token t_show_ext_subtype[] = { - { EXTCOMMUNITY, "", NONE, t_show_rib}, - { 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, "bulk", NONE, t_bulk}, @@ -403,9 +361,9 @@ static const struct token t_rd[] = { static const struct token t_set[] = { { NOTOKEN, "", NONE, NULL}, - { KEYWORD, "community", NONE, t_community}, - { KEYWORD, "ext-community", NONE, t_extcommunity}, - { KEYWORD, "large-community", NONE, t_largecommunity}, + { COMMUNITY, "community", NONE, t_set}, + { EXTCOMMUNITY, "ext-community", NONE, t_set}, + { LRGCOMMUNITY, "large-community", NONE, t_set}, { KEYWORD, "localpref", NONE, t_localpref}, { KEYWORD, "med", NONE, t_med}, { KEYWORD, "metric", NONE, t_med}, @@ -418,39 +376,6 @@ static const struct token t_set[] = { { ENDTOKEN, "", NONE, NULL} }; -static const struct token t_community[] = { - { COMMUNITY, "", NONE, t_set}, - { ENDTOKEN, "", NONE, NULL} -}; - -static const struct token t_extcommunity[] = { - { EXTCOM_SUBTYPE, "bdc", NONE, t_ext_subtype}, - { EXTCOM_SUBTYPE, "defgw", NONE, t_ext_subtype}, - { EXTCOM_SUBTYPE, "esi-lab", NONE, t_ext_subtype}, - { EXTCOM_SUBTYPE, "esi-rt", NONE, t_ext_subtype}, - { EXTCOM_SUBTYPE, "l2vid", NONE, t_ext_subtype}, - { EXTCOM_SUBTYPE, "mac-mob", NONE, t_ext_subtype}, - { EXTCOM_SUBTYPE, "odi", NONE, t_ext_subtype}, - { EXTCOM_SUBTYPE, "ori", NONE, t_ext_subtype}, - { EXTCOM_SUBTYPE, "ort", NONE, t_ext_subtype}, - { EXTCOM_SUBTYPE, "ovs", NONE, t_ext_subtype}, - { EXTCOM_SUBTYPE, "rt", NONE, t_ext_subtype}, - { EXTCOM_SUBTYPE, "soo", NONE, t_ext_subtype}, - { EXTCOM_SUBTYPE, "srcas", NONE, t_ext_subtype}, - { EXTCOM_SUBTYPE, "vrfri", NONE, t_ext_subtype}, - { ENDTOKEN, "", NONE, NULL} -}; - -static const struct token t_ext_subtype[] = { - { EXTCOMMUNITY, "", NONE, t_set}, - { 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} @@ -516,7 +441,8 @@ void show_valid_args(const struct token []); int parse_addr(const char *, struct bgpd_addr *); int parse_asnum(const char *, size_t, uint32_t *); int parse_number(const char *, struct parse_result *, enum token_type); -void parsecommunity(struct community *c, int type, char *s); +void parsecommunity(struct community *c, char *s); +void parselargecommunity(struct community *c, char *s); void parseextcommunity(struct community *c, const char *t, char *s); int parse_nexthop(const char *, struct parse_result *); @@ -566,7 +492,7 @@ match_token(int *argc, char **argv[], const struct token table[]) u_int i, match; const struct token *t = NULL; struct filter_set *fs; - const char *word = *argv[0]; + const char *word = (*argv)[0]; size_t wordlen = 0; match = 0; @@ -698,17 +624,11 @@ match_token(int *argc, char **argv[], const struct token table[]) } break; case COMMUNITY: - case LARGE_COMMUNITY: - if (word != NULL && wordlen > 0) { - int type = COMMUNITY_TYPE_BASIC; - char *p = strdup(word); - - if (p == NULL) - err(1, NULL); - if (table[i].type == LARGE_COMMUNITY) - type = COMMUNITY_TYPE_LARGE; - parsecommunity(&res.community, type, p); - free(p); + if (word != NULL && strncmp(word, table[i].keyword, + wordlen) == 0 && *argc > 1) { + parsecommunity(&res.community, (*argv)[1]); + *argc -= 1; + *argv += 1; if ((fs = calloc(1, sizeof(*fs))) == NULL) err(1, NULL); @@ -720,23 +640,30 @@ match_token(int *argc, char **argv[], const struct token table[]) t = &table[i]; } break; - case EXTCOM_SUBTYPE: + case LRGCOMMUNITY: if (word != NULL && strncmp(word, table[i].keyword, - wordlen) == 0) { - res.ext_comm_subtype = table[i].keyword; + wordlen) == 0 && *argc > 1) { + parselargecommunity(&res.community, (*argv)[1]); + *argc -= 1; + *argv += 1; + + if ((fs = calloc(1, sizeof(*fs))) == NULL) + err(1, NULL); + fs->type = ACTION_SET_COMMUNITY; + fs->action.community = res.community; + TAILQ_INSERT_TAIL(&res.set, fs, entry); + match++; t = &table[i]; } break; case EXTCOMMUNITY: - if (word != NULL && wordlen > 0) { - char *p = strdup(word); - - if (p == NULL) - err(1, NULL); + if (word != NULL && strncmp(word, table[i].keyword, + wordlen) == 0 && *argc > 2) { parseextcommunity(&res.community, - res.ext_comm_subtype, p); - free(p); + (*argv)[1], (*argv)[2]); + *argc -= 2; + *argv += 2; if ((fs = calloc(1, sizeof(*fs))) == NULL) err(1, NULL); @@ -875,7 +802,6 @@ show_valid_args(const struct token table[]) case KEYWORD: case FLAG: case ASTYPE: - case EXTCOM_SUBTYPE: fprintf(stderr, " %s\n", table[i].keyword); break; case ADDRESS: @@ -899,13 +825,16 @@ show_valid_args(const struct token table[]) fprintf(stderr, " <reason>\n"); break; case COMMUNITY: - fprintf(stderr, " <community>\n"); + fprintf(stderr, " %s <community>\n", + table[i].keyword); break; - case LARGE_COMMUNITY: - fprintf(stderr, " <large-community>\n"); + case LRGCOMMUNITY: + fprintf(stderr, " %s <large-community>\n", + table[i].keyword); break; case EXTCOMMUNITY: - fprintf(stderr, " <extended-community>\n"); + fprintf(stderr, " %s <extended-community>\n", + table[i].keyword); break; case RD: fprintf(stderr, " <route-distinguisher>\n"); @@ -1160,41 +1089,12 @@ setcommunity(struct community *c, uint32_t as, uint32_t data, c->data3 = 0; } -static void -parselargecommunity(struct community *c, char *s) -{ - char *p, *q; - uint32_t dflag1, dflag2, dflag3; - - if ((p = strchr(s, ':')) == NULL) - errx(1, "Bad community syntax"); - *p++ = 0; - - if ((q = strchr(p, ':')) == NULL) - errx(1, "Bad community syntax"); - *q++ = 0; - - getcommunity(s, 1, &c->data1, &dflag1); - getcommunity(p, 1, &c->data2, &dflag2); - getcommunity(q, 1, &c->data3, &dflag3); - - c->flags = COMMUNITY_TYPE_LARGE; - c->flags |= dflag1 << 8; - c->flags |= dflag2 << 16; - c->flags |= dflag3 << 24; -} - void -parsecommunity(struct community *c, int type, char *s) +parsecommunity(struct community *c, char *s) { char *p; uint32_t as, data, asflag, dataflag; - if (type == COMMUNITY_TYPE_LARGE) { - parselargecommunity(c, s); - return; - } - /* Well-known communities */ if (strcasecmp(s, "GRACEFUL_SHUTDOWN") == 0) { setcommunity(c, COMMUNITY_WELLKNOWN, @@ -1231,6 +1131,30 @@ parsecommunity(struct community *c, int type, char *s) setcommunity(c, as, data, asflag, dataflag); } +void +parselargecommunity(struct community *c, char *s) +{ + char *p, *q; + uint32_t dflag1, dflag2, dflag3; + + if ((p = strchr(s, ':')) == NULL) + errx(1, "Bad community syntax"); + *p++ = 0; + + if ((q = strchr(p, ':')) == NULL) + errx(1, "Bad community syntax"); + *q++ = 0; + + getcommunity(s, 1, &c->data1, &dflag1); + getcommunity(p, 1, &c->data2, &dflag2); + getcommunity(q, 1, &c->data3, &dflag3); + + c->flags = COMMUNITY_TYPE_LARGE; + c->flags |= dflag1 << 8; + c->flags |= dflag2 << 16; + c->flags |= dflag3 << 24; +} + static int parsesubtype(const char *name, int *type, int *subtype) { |