diff --git a/lib/prefix.h b/lib/prefix.h index 816a1517e1..5e03a7b4f5 100644 --- a/lib/prefix.h +++ b/lib/prefix.h @@ -585,6 +585,71 @@ static inline int is_default_host_route(const struct prefix *p) return 0; } +/* IPv6 scope values, usable for IPv4 too (cf. below) */ +/* clang-format off */ +enum { + /* 0: reserved */ + MCAST_SCOPE_IFACE = 0x1, + MCAST_SCOPE_LINK = 0x2, + MCAST_SCOPE_REALM = 0x3, + MCAST_SCOPE_ADMIN = 0x4, + MCAST_SCOPE_SITE = 0x5, + /* 6-7: unassigned */ + MCAST_SCOPE_ORG = 0x8, + /* 9-d: unassigned */ + MCAST_SCOPE_GLOBAL = 0xe, + /* f: reserved */ +}; +/* clang-format on */ + +static inline uint8_t ipv6_mcast_scope(const struct in6_addr *addr) +{ + return addr->s6_addr[1] & 0xf; +} + +static inline bool ipv6_mcast_nofwd(const struct in6_addr *addr) +{ + return (addr->s6_addr[1] & 0xf) <= MCAST_SCOPE_LINK; +} + +static inline bool ipv6_mcast_ssm(const struct in6_addr *addr) +{ + uint32_t bits = ntohl(addr->s6_addr32[0]); + + /* ff3x:0000::/32 */ + return (bits & 0xfff0ffff) == 0xff300000; +} + +static inline uint8_t ipv4_mcast_scope(const struct in_addr *addr) +{ + uint32_t bits = ntohl(addr->s_addr); + + /* 224.0.0.0/24 - link scope */ + if ((bits & 0xffffff00) == 0xe0000000) + return MCAST_SCOPE_LINK; + /* 239.0.0.0/8 - org scope */ + if ((bits & 0xff000000) == 0xef000000) + return MCAST_SCOPE_ORG; + + return MCAST_SCOPE_GLOBAL; +} + +static inline bool ipv4_mcast_nofwd(const struct in_addr *addr) +{ + uint32_t bits = ntohl(addr->s_addr); + + /* 224.0.0.0/24 */ + return (bits & 0xffffff00) == 0xe0000000; +} + +static inline bool ipv4_mcast_ssm(const struct in_addr *addr) +{ + uint32_t bits = ntohl(addr->s_addr); + + /* 232.0.0.0/8 */ + return (bits & 0xff000000) == 0xe8000000; +} + #ifdef _FRR_ATTRIBUTE_PRINTFRR #pragma FRR printfrr_ext "%pEA" (struct ethaddr *) diff --git a/pimd/pim_addr.h b/pimd/pim_addr.h index e422a2e2da..eca907da37 100644 --- a/pimd/pim_addr.h +++ b/pimd/pim_addr.h @@ -34,6 +34,8 @@ typedef struct in_addr pim_addr; #define PIM_MAX_BITLEN IPV4_MAX_BITLEN #define PIM_AF_NAME "ip" +#define PIM_ADDR_FUNCNAME(name) ipv4_##name + union pimprefixptr { prefixtype(pimprefixptr, struct prefix, p) prefixtype(pimprefixptr, struct prefix_ipv4, p4) @@ -53,6 +55,8 @@ typedef struct in6_addr pim_addr; #define PIM_MAX_BITLEN IPV6_MAX_BITLEN #define PIM_AF_NAME "ipv6" +#define PIM_ADDR_FUNCNAME(name) ipv6_##name + union pimprefixptr { prefixtype(pimprefixptr, struct prefix, p) prefixtype(pimprefixptr, struct prefix_ipv6, p6) @@ -101,6 +105,21 @@ static inline pim_addr pim_addr_from_prefix(union pimprefixconstptr in) return ret; } +static inline uint8_t pim_addr_scope(const pim_addr addr) +{ + return PIM_ADDR_FUNCNAME(mcast_scope)(&addr); +} + +static inline bool pim_addr_nofwd(const pim_addr addr) +{ + return PIM_ADDR_FUNCNAME(mcast_nofwd)(&addr); +} + +static inline bool pim_addr_ssm(const pim_addr addr) +{ + return PIM_ADDR_FUNCNAME(mcast_ssm)(&addr); +} + /* don't use this struct directly, use the pim_sgaddr typedef */ struct _pim_sgaddr { pim_addr grp; diff --git a/pimd/pim_ssm.c b/pimd/pim_ssm.c index 74310474d4..62d6eb8308 100644 --- a/pimd/pim_ssm.c +++ b/pimd/pim_ssm.c @@ -70,19 +70,9 @@ void pim_ssm_prefix_list_update(struct pim_instance *pim, static int pim_is_grp_standard_ssm(struct prefix *group) { - static int first = 1; - static struct prefix group_ssm; + pim_addr addr = pim_addr_from_prefix(group); - if (first) { - if (!str2prefix(PIM_SSM_STANDARD_RANGE, &group_ssm)) - flog_err(EC_LIB_DEVELOPMENT, - "%s: Failure to Read Group Address: %s", - __func__, PIM_SSM_STANDARD_RANGE); - - first = 0; - } - - return prefix_match(&group_ssm, group); + return pim_addr_ssm(addr); } int pim_is_grp_ssm(struct pim_instance *pim, pim_addr group_addr)