summaryrefslogtreecommitdiff
path: root/pimd/pim_rp.c
diff options
context:
space:
mode:
Diffstat (limited to 'pimd/pim_rp.c')
-rw-r--r--pimd/pim_rp.c48
1 files changed, 35 insertions, 13 deletions
diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c
index a31fec036f..3e3b6dddb5 100644
--- a/pimd/pim_rp.c
+++ b/pimd/pim_rp.c
@@ -124,7 +124,7 @@ void pim_rp_init(struct pim_instance *pim)
}
rp_info->group.family = AF_INET;
rp_info->rp.rpf_addr.family = AF_INET;
- rp_info->rp.rpf_addr.prefixlen = IPV4_MAX_PREFIXLEN;
+ rp_info->rp.rpf_addr.prefixlen = IPV4_MAX_BITLEN;
rp_info->rp.rpf_addr.u.prefix4.s_addr = INADDR_NONE;
listnode_add(pim->rp_list, rp_info);
@@ -139,11 +139,12 @@ void pim_rp_init(struct pim_instance *pim)
void pim_rp_free(struct pim_instance *pim)
{
- if (pim->rp_list)
- list_delete(&pim->rp_list);
if (pim->rp_table)
route_table_finish(pim->rp_table);
pim->rp_table = NULL;
+
+ if (pim->rp_list)
+ list_delete(&pim->rp_list);
}
/*
@@ -204,6 +205,26 @@ static struct rp_info *pim_rp_find_exact(struct pim_instance *pim,
}
/*
+ * XXX: long-term issue: we don't actually have a good "ip address-list"
+ * implementation. ("access-list XYZ" is the closest but honestly it's
+ * kinda garbage.)
+ *
+ * So it's using a prefix-list to match an address here, which causes very
+ * unexpected results for the user since prefix-lists by default only match
+ * when the prefix length is an exact match too. i.e. you'd have to add the
+ * "le 32" and do "ip prefix-list foo permit 10.0.0.0/24 le 32"
+ *
+ * To avoid this pitfall, this code uses "address_mode = true" for the prefix
+ * list match (this is the only user for that.)
+ *
+ * In the long run, we need to add a "ip address-list", but that's a wholly
+ * separate bag of worms, and existing configs using ip prefix-list would
+ * drop into the UX pitfall.
+ */
+
+#include "lib/plist_int.h"
+
+/*
* Given a group, return the rp_info for that group
*/
struct rp_info *pim_rp_find_match_group(struct pim_instance *pim,
@@ -213,7 +234,8 @@ struct rp_info *pim_rp_find_match_group(struct pim_instance *pim,
struct rp_info *best = NULL;
struct rp_info *rp_info;
struct prefix_list *plist;
- const struct prefix *p, *bp;
+ const struct prefix *bp;
+ const struct prefix_list_entry *entry;
struct route_node *rn;
bp = NULL;
@@ -221,19 +243,19 @@ struct rp_info *pim_rp_find_match_group(struct pim_instance *pim,
if (rp_info->plist) {
plist = prefix_list_lookup(AFI_IP, rp_info->plist);
- if (prefix_list_apply_which_prefix(plist, &p, group)
- == PREFIX_DENY)
+ if (prefix_list_apply_ext(plist, &entry, group, true)
+ == PREFIX_DENY || !entry)
continue;
if (!best) {
best = rp_info;
- bp = p;
+ bp = &entry->prefix;
continue;
}
- if (bp && bp->prefixlen < p->prefixlen) {
+ if (bp && bp->prefixlen < entry->prefix.prefixlen) {
best = rp_info;
- bp = p;
+ bp = &entry->prefix;
}
}
}
@@ -417,7 +439,7 @@ int pim_rp_new(struct pim_instance *pim, struct in_addr rp_addr,
rp_info = XCALLOC(MTYPE_PIM_RP, sizeof(*rp_info));
rp_info->rp.rpf_addr.family = AF_INET;
- rp_info->rp.rpf_addr.prefixlen = IPV4_MAX_PREFIXLEN;
+ rp_info->rp.rpf_addr.prefixlen = IPV4_MAX_BITLEN;
rp_info->rp.rpf_addr.u.prefix4 = rp_addr;
prefix_copy(&rp_info->group, &group);
rp_info->rp_src = rp_src_flag;
@@ -1036,7 +1058,7 @@ int pim_rp_i_am_rp(struct pim_instance *pim, struct in_addr group)
memset(&g, 0, sizeof(g));
g.family = AF_INET;
- g.prefixlen = 32;
+ g.prefixlen = IPV4_MAX_BITLEN;
g.u.prefix4 = group;
rp_info = pim_rp_find_match_group(pim, &g);
@@ -1059,7 +1081,7 @@ struct pim_rpf *pim_rp_g(struct pim_instance *pim, struct in_addr group)
memset(&g, 0, sizeof(g));
g.family = AF_INET;
- g.prefixlen = 32;
+ g.prefixlen = IPV4_MAX_BITLEN;
g.u.prefix4 = group;
rp_info = pim_rp_find_match_group(pim, &g);
@@ -1103,7 +1125,7 @@ int pim_rp_set_upstream_addr(struct pim_instance *pim, struct in_addr *up,
memset(&g, 0, sizeof(g));
g.family = AF_INET;
- g.prefixlen = 32;
+ g.prefixlen = IPV4_MAX_BITLEN;
g.u.prefix4 = group;
rp_info = pim_rp_find_match_group(pim, &g);