diff --git a/lib/routemap.h b/lib/routemap.h index b166de1e09..8c00e8104c 100644 --- a/lib/routemap.h +++ b/lib/routemap.h @@ -194,7 +194,15 @@ extern int route_map_delete_set(struct route_map_index *index, /* Install rule command to the match list. */ extern void route_map_install_match(struct route_map_rule_cmd *cmd); -/* Install rule command to the set list. */ +/* + * Install rule command to the set list. + * + * When installing a particular item, Allow a difference of handling + * of bad cli inputted(return NULL) -vs- this particular daemon cannot use + * this form of the command(return a pointer and handle it appropriately + * in the apply command). See 'set metric' command + * as it is handled in ripd/ripngd and ospfd. + */ extern void route_map_install_set(struct route_map_rule_cmd *cmd); /* Lookup route map by name. */ diff --git a/ospfd/ospf_routemap.c b/ospfd/ospf_routemap.c index 547e1e8f53..f47e2b6f1e 100644 --- a/ospfd/ospf_routemap.c +++ b/ospfd/ospf_routemap.c @@ -336,6 +336,10 @@ static struct route_map_rule_cmd route_match_tag_cmd = { route_map_rule_tag_free, }; +struct ospf_metric { + bool used; + u_int32_t metric; +}; /* `set metric METRIC' */ /* Set metric to attribute. */ @@ -343,7 +347,7 @@ static route_map_result_t route_set_metric(void *rule, struct prefix *prefix, route_map_object_t type, void *object) { - u_int32_t *metric; + struct ospf_metric *metric; struct external_info *ei; if (type == RMAP_OSPF) { @@ -352,7 +356,8 @@ static route_map_result_t route_set_metric(void *rule, struct prefix *prefix, ei = object; /* Set metric out value. */ - ei->route_map_set.metric = *metric; + if (metric->used) + ei->route_map_set.metric = metric->metric; } return RMAP_OKAY; } @@ -360,7 +365,10 @@ static route_map_result_t route_set_metric(void *rule, struct prefix *prefix, /* set metric compilation. */ static void *route_set_metric_compile(const char *arg) { - u_int32_t *metric; + struct ospf_metric *metric; + + metric = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(u_int32_t)); + metric->used = false; /* OSPF doesn't support the +/- in set metric <+/-metric> check @@ -373,11 +381,12 @@ static void *route_set_metric_compile(const char *arg) if (strmatch(arg, "+rtt") || strmatch(arg, "-rtt")) zlog_warn( "OSPF does not support 'set metric +rtt / -rtt'"); - return NULL; + + return metric; } } - metric = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(u_int32_t)); - *metric = strtoul(arg, NULL, 10); + metric->metric = strtoul(arg, NULL, 10); + metric->used = true; return metric; } diff --git a/ripd/rip_routemap.c b/ripd/rip_routemap.c index 7255df5e67..7d39023b38 100644 --- a/ripd/rip_routemap.c +++ b/ripd/rip_routemap.c @@ -36,8 +36,8 @@ struct rip_metric_modifier { enum { metric_increment, metric_decrement, metric_absolute } type; - - u_char metric; + bool used; + u_int8_t metric; }; /* Hook function for updating route_map assignment. */ @@ -365,6 +365,9 @@ static route_map_result_t route_set_metric(void *rule, struct prefix *prefix, mod = rule; rinfo = object; + if (!mod->used) + return RMAP_OKAY; + if (mod->type == metric_increment) rinfo->metric_out += mod->metric; else if (mod->type == metric_decrement) @@ -387,43 +390,49 @@ static void *route_set_metric_compile(const char *arg) { int len; const char *pnt; - int type; long metric; char *endptr = NULL; struct rip_metric_modifier *mod; + mod = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, + sizeof(struct rip_metric_modifier)); + mod->used = false; + len = strlen(arg); pnt = arg; if (len == 0) - return NULL; + return mod; /* Examine first character. */ if (arg[0] == '+') { - type = metric_increment; + mod->type = metric_increment; pnt++; } else if (arg[0] == '-') { - type = metric_decrement; + mod->type = metric_decrement; pnt++; } else - type = metric_absolute; + mod->type = metric_absolute; /* Check beginning with digit string. */ if (*pnt < '0' || *pnt > '9') - return NULL; + return mod; /* Convert string to integer. */ metric = strtol(pnt, &endptr, 10); - if (metric == LONG_MAX || *endptr != '\0') - return NULL; - if (metric < 0 || metric > RIP_METRIC_INFINITY) - return NULL; + if (*endptr != '\0' || mod->metric < 0) { + metric = 0; + return mod; + } + if (metric > RIP_METRIC_INFINITY) { + zlog_info("%s: Metric specified: %ld is greater than RIP_METRIC_INFINITY, using INFINITY instead", + __PRETTY_FUNCTION__, metric); + mod->metric = RIP_METRIC_INFINITY; + } else + mod->metric = metric; - mod = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, - sizeof(struct rip_metric_modifier)); - mod->type = type; - mod->metric = metric; + mod->used = true; return mod; } diff --git a/ripngd/ripng_routemap.c b/ripngd/ripng_routemap.c index 3080801fb3..e518585c74 100644 --- a/ripngd/ripng_routemap.c +++ b/ripngd/ripng_routemap.c @@ -32,8 +32,8 @@ struct rip_metric_modifier { enum { metric_increment, metric_decrement, metric_absolute } type; - - u_char metric; + bool used; + u_int8_t metric; }; /* `match metric METRIC' */ @@ -168,6 +168,9 @@ static route_map_result_t route_set_metric(void *rule, struct prefix *prefix, mod = rule; rinfo = object; + if (!mod->used) + return RMAP_OKAY; + if (mod->type == metric_increment) rinfo->metric_out += mod->metric; else if (mod->type == metric_decrement) @@ -190,7 +193,6 @@ static void *route_set_metric_compile(const char *arg) { int len; const char *pnt; - int type; long metric; char *endptr = NULL; struct rip_metric_modifier *mod; @@ -198,38 +200,42 @@ static void *route_set_metric_compile(const char *arg) len = strlen(arg); pnt = arg; + mod = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, + sizeof(struct rip_metric_modifier)); + mod->used = false; + if (len == 0) - return NULL; + return mod; /* Examine first character. */ if (arg[0] == '+') { - type = metric_increment; + mod->type = metric_increment; pnt++; } else if (arg[0] == '-') { - type = metric_decrement; + mod->type = metric_decrement; pnt++; } else - type = metric_absolute; + mod->type = metric_absolute; /* Check beginning with digit string. */ if (*pnt < '0' || *pnt > '9') - return NULL; + return mod; /* Convert string to integer. */ metric = strtol(pnt, &endptr, 10); - if (metric == LONG_MAX || *endptr != '\0') - return NULL; - /* Commented out by Hasso Tepper, to avoid problems in vtysh. */ - /* if (metric < 0 || metric > RIPNG_METRIC_INFINITY) */ - if (metric < 0) - return NULL; + if (*endptr != '\0' || metric < 0) + return mod; - mod = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, - sizeof(struct rip_metric_modifier)); - mod->type = type; - mod->metric = metric; + if (metric > RIPNG_METRIC_INFINITY) { + zlog_info("%s: Metric specified: %ld is being converted into METRIC_INFINITY", + __PRETTY_FUNCTION__, + metric); + mod->metric = RIPNG_METRIC_INFINITY; + } else + mod->metric = metric; + mod->used = true; return mod; }