Index: sys/net/route.h =================================================================== --- sys/net/route.h +++ sys/net/route.h @@ -455,6 +455,14 @@ /* New API */ struct nhop_object *rib_lookup(uint32_t fibnum, const struct sockaddr *dst, uint32_t flags, uint32_t flowid); +void rt_get_inet_prefix_plen(const struct rtentry *rt, struct in_addr *paddr, + int *plen); +void rt_get_inet_prefix_pmask(const struct rtentry *rt, struct in_addr *paddr, + struct in_addr *pmask); +void rt_get_inet6_prefix_plen(const struct rtentry *rt, struct in6_addr *paddr, + int *plen); +void rt_get_inet6_prefix_pmask(const struct rtentry *rt, struct in6_addr *paddr, + struct in6_addr *pmask); #endif #endif Index: sys/net/route/route_ctl.c =================================================================== --- sys/net/route/route_ctl.c +++ sys/net/route/route_ctl.c @@ -236,6 +236,84 @@ return (weight); } +#ifdef INET +void +rt_get_inet_prefix_plen(const struct rtentry *rt, struct in_addr *paddr, int *plen) +{ + const struct sockaddr_in *dst; + + dst = (const struct sockaddr_in *)rt_key_const(rt); + KASSERT((dst->sin_family == AF_INET), + ("rt family is %d, not inet", dst->sin_family)); + *paddr = dst->sin_addr; + dst = (const struct sockaddr_in *)rt_mask_const(rt); + if (dst == NULL) + *plen = 32; + else + *plen = bitcount32(dst->sin_addr.s_addr); +} + +void +rt_get_inet_prefix_pmask(const struct rtentry *rt, struct in_addr *paddr, + struct in_addr *pmask) +{ + const struct sockaddr_in *dst; + + dst = (const struct sockaddr_in *)rt_key_const(rt); + KASSERT((dst->sin_family == AF_INET), + ("rt family is %d, not inet", dst->sin_family)); + *paddr = dst->sin_addr; + dst = (const struct sockaddr_in *)rt_mask_const(rt); + if (dst == NULL) + *pmask->s_addr = INADDR_BROADCAST; + else + *plen = bitcount32(dst->sin_addr.s_addr); +} +#endif + +#ifdef INET6 +static int +inet6_get_plen(const struct in6_addr *addr) +{ + + return (bitmask32(addr->s6_addr32[0]) + bitmask32(addr->s6_addr32[1]) + + bitmask32(addr->s6_addr32[2]) + bitmask32(addr->s6_addr32[3])); +} + +void +rt_get_inet6_prefix_plen(const struct rtentry *rt, struct in6_addr *paddr, int *plen) +{ + const struct sockaddr_in6 *dst; + + dst = (const struct sockaddr_in6 *)rt_key_const(rt); + KASSERT((dst->sin6_family == AF_INET6), + ("rt family is %d, not inet6", dst->sin6_family)); + *paddr = dst->sin6_addr; + dst = (const struct sockaddr_in6 *)rt_mask_const(rt); + if (dst == NULL) + *plen = 128; + else + *plen = inet6_get_plen(&dst->sin6_addr); +} + +void +rt_get_inet6_prefix_pmask(const struct rtentry *rt, struct in6_addr *paddr, + struct in6_addr *pmask) +{ + const struct sockaddr_in *dst; + + dst = (const struct sockaddr_in *)rt_key_const(rt); + KASSERT((dst->sin6_family == AF_INET), + ("rt family is %d, not inet", dst->sin_family)); + *paddr = dst->sin6_addr; + dst = (const struct sockaddr_in6 *)rt_mask_const(rt); + if (dst == NULL) + memset(pmask, 0xFF, sizeof(struct in6_addr)); + else + *plen = dst->sin6_addr; +} +#endif + static void rt_set_expire_info(struct rtentry *rt, const struct rt_addrinfo *info) {