summaryrefslogtreecommitdiff
path: root/bgpd/bgp_clist.c
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd/bgp_clist.c')
-rw-r--r--bgpd/bgp_clist.c119
1 files changed, 30 insertions, 89 deletions
diff --git a/bgpd/bgp_clist.c b/bgpd/bgp_clist.c
index 247d758f8c..e17cce3ff6 100644
--- a/bgpd/bgp_clist.c
+++ b/bgpd/bgp_clist.c
@@ -654,86 +654,6 @@ static bool ecommunity_regexp_match(struct ecommunity *ecom, regex_t *reg)
return false;
}
-#if 0
-/* Delete community attribute using regular expression match. Return
- modified communites attribute. */
-static struct community *
-community_regexp_delete (struct community *com, regex_t * reg)
-{
- int i;
- uint32_t comval;
- /* Maximum is "65535:65535" + '\0'. */
- char c[12];
- const char *str;
-
- if (!com)
- return NULL;
-
- i = 0;
- while (i < com->size)
- {
- memcpy (&comval, com_nthval (com, i), sizeof(uint32_t));
- comval = ntohl (comval);
-
- switch (comval) {
- case COMMUNITY_INTERNET:
- str = "internet";
- break;
- case COMMUNITY_ACCEPT_OWN:
- str = "accept-own";
- break;
- case COMMUNITY_ROUTE_FILTER_TRANSLATED_v4:
- str = "route-filter-translated-v4";
- break;
- case COMMUNITY_ROUTE_FILTER_v4:
- str = "route-filter-v4";
- break;
- case COMMUNITY_ROUTE_FILTER_TRANSLATED_v6:
- str = "route-filter-translated-v6";
- break;
- case COMMUNITY_ROUTE_FILTER_v6:
- str = "route-filter-v6";
- break;
- case COMMUNITY_LLGR_STALE:
- str = "llgr-stale";
- break;
- case COMMUNITY_NO_LLGR:
- str = "no-llgr";
- break;
- case COMMUNITY_ACCEPT_OWN_NEXTHOP:
- str = "accept-own-nexthop";
- break;
- case COMMUNITY_BLACKHOLE:
- str = "blackhole";
- break;
- case COMMUNITY_NO_EXPORT:
- str = "no-export";
- break;
- case COMMUNITY_NO_ADVERTISE:
- str = "no-advertise";
- break;
- case COMMUNITY_LOCAL_AS:
- str = "local-AS";
- break;
- case COMMUNITY_NO_PEER:
- str = "no-peer";
- break;
- default:
- sprintf (c, "%d:%d", (comval >> 16) & 0xFFFF,
- comval & 0xFFFF);
- str = c;
- break;
- }
-
- if (regexec (reg, str, 0, NULL, 0) == 0)
- community_del_val (com, com_nthval (com, i));
- else
- i++;
- }
- return com;
-}
-#endif
-
/* When given community attribute matches to the community-list return
1 else return 0. */
bool community_list_match(struct community *com, struct community_list *list)
@@ -1110,11 +1030,14 @@ struct lcommunity *lcommunity_list_match_delete(struct lcommunity *lcom,
}
/* Helper to check if every octet do not exceed UINT_MAX */
-static bool lcommunity_list_valid(const char *community)
+bool lcommunity_list_valid(const char *community, int style)
{
int octets;
char **splits, **communities;
+ char *endptr;
int num, num_communities;
+ regex_t *regres;
+ int invalid = 0;
frrstr_split(community, " ", &communities, &num_communities);
@@ -1123,25 +1046,43 @@ static bool lcommunity_list_valid(const char *community)
frrstr_split(communities[j], ":", &splits, &num);
for (int i = 0; i < num; i++) {
- if (strtoul(splits[i], NULL, 10) > UINT_MAX)
- return false;
-
if (strlen(splits[i]) == 0)
- return false;
+ /* There is no digit to check */
+ invalid++;
+
+ if (style == LARGE_COMMUNITY_LIST_STANDARD) {
+ if (*splits[i] == '-')
+ /* Must not be negative */
+ invalid++;
+ else if (strtoul(splits[i], &endptr, 10)
+ > UINT_MAX)
+ /* Larger than 4 octets */
+ invalid++;
+ else if (*endptr)
+ /* Not all characters were digits */
+ invalid++;
+ } else {
+ regres = bgp_regcomp(communities[j]);
+ if (!regres)
+ /* malformed regex */
+ invalid++;
+ else
+ bgp_regex_free(regres);
+ }
octets++;
XFREE(MTYPE_TMP, splits[i]);
}
XFREE(MTYPE_TMP, splits);
- if (octets < 3)
- return false;
+ if (octets != 3)
+ invalid++;
XFREE(MTYPE_TMP, communities[j]);
}
XFREE(MTYPE_TMP, communities);
- return true;
+ return (invalid > 0) ? false : true;
}
/* Set lcommunity-list. */
@@ -1176,7 +1117,7 @@ int lcommunity_list_set(struct community_list_handler *ch, const char *name,
}
if (str) {
- if (!lcommunity_list_valid(str))
+ if (!lcommunity_list_valid(str, style))
return COMMUNITY_LIST_ERR_MALFORMED_VAL;
if (style == LARGE_COMMUNITY_LIST_STANDARD)