Small update. I renamed the 'msb' argument ('most significant bits') to 'part' to improve readability. In Community 15562:4, '15562' is part 0 and the '4' is part 1. Same type of logic might be useful down the road for Large Communities which would have 3 parts.
- Job diff --git usr.sbin/bgpctl/parser.c usr.sbin/bgpctl/parser.c index 85300d1cd32..c9d63f9ade3 100644 --- usr.sbin/bgpctl/parser.c +++ usr.sbin/bgpctl/parser.c @@ -413,7 +413,7 @@ int parse_addr(const char *, struct bgpd_addr *); int parse_asnum(const char *, size_t, u_int32_t *); int parse_number(const char *, struct parse_result *, enum token_type); -int getcommunity(const char *); +int getcommunity(const char *, int); int parse_community(const char *, struct parse_result *); u_int getlargecommunity(const char *); int parse_largecommunity(const char *, struct parse_result *); @@ -927,7 +927,7 @@ parse_number(const char *word, struct parse_result *r, enum token_type type) } int -getcommunity(const char *s) +getcommunity(const char *s, int part) { const char *errstr; u_int16_t uval; @@ -935,6 +935,9 @@ getcommunity(const char *s) if (strcmp(s, "*") == 0) return (COMMUNITY_ANY); + if (part == 0 && strcmp(s, "WELLKNOWN") == 0) + return (COMMUNITY_WELLKNOWN); + uval = strtonum(s, 0, USHRT_MAX, &errstr); if (errstr) errx(1, "Community is %s: %s", errstr, s); @@ -978,8 +981,8 @@ parse_community(const char *word, struct parse_result *r) } *p++ = 0; - as = getcommunity(word); - type = getcommunity(p); + as = getcommunity(word, 0); + type = getcommunity(p, 1); done: if (as == 0) { @@ -994,10 +997,6 @@ done: case COMMUNITY_BLACKHOLE: /* valid */ break; - default: - /* unknown */ - fprintf(stderr, "Unknown well-known community\n"); - return (0); } if ((fs = calloc(1, sizeof(struct filter_set))) == NULL) diff --git usr.sbin/bgpd/parse.y usr.sbin/bgpd/parse.y index f0c96051e17..ec4ed956b60 100644 --- usr.sbin/bgpd/parse.y +++ usr.sbin/bgpd/parse.y @@ -146,7 +146,7 @@ void copy_filterset(struct filter_set_head *, void merge_filter_lists(struct filter_head *, struct filter_head *); struct filter_rule *get_rule(enum action_types); -int getcommunity(char *); +int getcommunity(char *, int); int parsecommunity(struct filter_community *, char *); int64_t getlargecommunity(char *); int parselargecommunity(struct filter_largecommunity *, char *); @@ -2963,11 +2963,13 @@ symget(const char *nam) } int -getcommunity(char *s) +getcommunity(char *s, int part) { int val; const char *errstr; + if (part == 0 && strcmp(s, "WELLKNOWN") == 0) + return (COMMUNITY_WELLKNOWN); if (strcmp(s, "*") == 0) return (COMMUNITY_ANY); if (strcmp(s, "neighbor-as") == 0) @@ -3017,15 +3019,11 @@ parsecommunity(struct filter_community *c, char *s) } *p++ = 0; - if ((i = getcommunity(s)) == COMMUNITY_ERROR) + if ((i = getcommunity(s, 0)) == COMMUNITY_ERROR) return (-1); - if (i == COMMUNITY_WELLKNOWN) { - yyerror("Bad community AS number"); - return (-1); - } as = i; - if ((i = getcommunity(p)) == COMMUNITY_ERROR) + if ((i = getcommunity(p, 1)) == COMMUNITY_ERROR) return (-1); c->as = as; c->type = i;