From 3bec29ac951ab9b3a49fa874b9862bb5404088c1 Mon Sep 17 00:00:00 2001 From: Don Slice Date: Wed, 28 Jun 2017 14:53:27 -0400 Subject: [PATCH] lib/ospf/eigrp: enable ospf and eigrp to use more specific network statements Issue reported that a configuration commonly used on other routing implementations fails in frr. If under ospf, "network 172.16.1.1/32 area 0" or under eigrp, "network 172.16.1.1/32" is entered, the appropriate interfaces are not included in the routing protocol. This was because the code was calling prefix_match, which did not match if the network statement had a longer mask than the interface being matched. This fix takes away that restriction by creating a "lib/prefix_match_network_statement" function which doesn't care about the mask of the interface. Manual testing shows both ospf and eigrp now can be defined with more specific network statements. Signed-off-by: Don Slice --- eigrpd/eigrp_network.c | 2 +- lib/prefix.c | 25 +++++++++++++++++++++++++ lib/prefix.h | 1 + ospfd/ospfd.c | 2 +- 4 files changed, 28 insertions(+), 2 deletions(-) diff --git a/eigrpd/eigrp_network.c b/eigrpd/eigrp_network.c index cfed11a9eb..c4e0b8435c 100644 --- a/eigrpd/eigrp_network.c +++ b/eigrpd/eigrp_network.c @@ -262,7 +262,7 @@ static int eigrp_network_match_iface(const struct connected *co, const struct prefix *net) { /* new approach: more elegant and conceptually clean */ - return prefix_match(net, CONNECTED_PREFIX (co)); + return prefix_match_network_statement(net, CONNECTED_PREFIX (co)); } static void diff --git a/lib/prefix.c b/lib/prefix.c index 9c228cf954..4131f37fbd 100644 --- a/lib/prefix.c +++ b/lib/prefix.c @@ -292,6 +292,31 @@ prefix_match (const struct prefix *n, const struct prefix *p) return 1; } +/* If n includes p then return 1 else return 0. Prefix mask is not considered */ +int +prefix_match_network_statement (const struct prefix *n, const struct prefix *p) +{ + int offset; + int shift; + const u_char *np, *pp; + + /* Set both prefix's head pointer. */ + np = (const u_char *)&n->u.prefix; + pp = (const u_char *)&p->u.prefix; + + offset = n->prefixlen / PNBBY; + shift = n->prefixlen % PNBBY; + + if (shift) + if (maskbit[shift] & (np[offset] ^ pp[offset])) + return 0; + + while (offset--) + if (np[offset] != pp[offset]) + return 0; + return 1; +} + /* Copy prefix from src to dest. */ void prefix_copy (struct prefix *dest, const struct prefix *src) diff --git a/lib/prefix.h b/lib/prefix.h index 35dfddd9d3..24144e80a3 100644 --- a/lib/prefix.h +++ b/lib/prefix.h @@ -279,6 +279,7 @@ extern int str2prefix (const char *, struct prefix *); extern const char *prefix2str (union prefixconstptr, char *, int); extern int prefix_match (const struct prefix *, const struct prefix *); +extern int prefix_match_network_statement (const struct prefix *, const struct prefix *); extern int prefix_same (const struct prefix *, const struct prefix *); extern int prefix_cmp (const struct prefix *, const struct prefix *); extern int prefix_common_bits (const struct prefix *, const struct prefix *); diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index 27cedc8705..aeb7600d69 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -1116,7 +1116,7 @@ static int ospf_network_match_iface(const struct connected *co, const struct prefix *net) { /* new approach: more elegant and conceptually clean */ - return prefix_match(net, CONNECTED_PREFIX(co)); + return prefix_match_network_statement(net, CONNECTED_PREFIX(co)); } static void -- 2.39.5