Index: sys/kern/vfs_export.c =================================================================== --- sys/kern/vfs_export.c +++ sys/kern/vfs_export.c @@ -65,7 +65,7 @@ #if defined(INET) || defined(INET6) static struct radix_node_head *vfs_create_addrlist_af( - struct radix_node_head **prnh, int off); + struct radix_node_head **prnh, int off, int salen); #endif static void vfs_free_addrlist(struct netexport *nep); static int vfs_free_netcred(struct radix_node *rn, void *w); @@ -108,7 +108,7 @@ struct radix_node *rn; struct sockaddr *saddr, *smask = NULL; #if defined(INET6) || defined(INET) - int off; + int off, salen; #endif int error; @@ -181,16 +181,18 @@ #ifdef INET case AF_INET: if ((rnh = nep->ne4) == NULL) { + salen = sizeof(struct sockaddr_in); off = offsetof(struct sockaddr_in, sin_addr) << 3; - rnh = vfs_create_addrlist_af(&nep->ne4, off); + rnh = vfs_create_addrlist_af(&nep->ne4, off, salen); } break; #endif #ifdef INET6 case AF_INET6: if ((rnh = nep->ne6) == NULL) { + salen = sizeof(struct sockaddr_in6); off = offsetof(struct sockaddr_in6, sin6_addr) << 3; - rnh = vfs_create_addrlist_af(&nep->ne6, off); + rnh = vfs_create_addrlist_af(&nep->ne6, off, salen); } break; #endif @@ -245,10 +247,10 @@ #if defined(INET) || defined(INET6) static struct radix_node_head * -vfs_create_addrlist_af(struct radix_node_head **prnh, int off) +vfs_create_addrlist_af(struct radix_node_head **prnh, int off, int salen) { - if (rn_inithead((void **)prnh, off) == 0) + if (rn_inithead((void **)prnh, off, salen) == 0) return (NULL); RADIX_NODE_HEAD_LOCK_INIT(*prnh); return (*prnh); Index: sys/net/radix.h =================================================================== --- sys/net/radix.h +++ sys/net/radix.h @@ -65,7 +65,8 @@ struct radix_node *rn_Dupedkey; } rn_leaf; struct { /* node only data: */ - int rn_Off; /* where to start compare */ + int16_t rn_Off; /* where to start compare */ + int16_t rn_Salen; /* total length of sockaddr */ struct radix_node *rn_L;/* progeny */ struct radix_node *rn_R;/* progeny */ } rn_node; @@ -81,6 +82,7 @@ #define rn_key rn_u.rn_leaf.rn_Key #define rn_mask rn_u.rn_leaf.rn_Mask #define rn_offset rn_u.rn_node.rn_Off +#define rn_salen rn_u.rn_node.rn_Salen #define rn_left rn_u.rn_node.rn_L #define rn_right rn_u.rn_node.rn_R @@ -148,7 +150,7 @@ }; void rn_inithead_internal(struct radix_head *rh, struct radix_node *base_nodes, - int off); + int off, int salen); #ifndef _KERNEL #define R_Malloc(p, t, n) (p = (t) malloc((unsigned int)(n))) @@ -173,7 +175,7 @@ #define RADIX_NODE_HEAD_WLOCK_ASSERT(rnh) rm_assert(&(rnh)->rnh_lock, RA_WLOCKED) #endif /* _KERNEL */ -int rn_inithead(void **, int); +int rn_inithead(void **, int, int); int rn_detachhead(void **); int rn_refines(void *, void *); struct radix_node *rn_addroute(void *, void *, struct radix_head *, Index: sys/net/radix.c =================================================================== --- sys/net/radix.c +++ sys/net/radix.c @@ -84,7 +84,7 @@ rn_new_radix_mask(struct radix_node *tt, struct radix_mask *next); static int rn_satisfies_leaf(char *trial, struct radix_node *leaf, - int skip); + int skip, int salen); /* * The data structure for the keys is a radix tree with one way @@ -255,11 +255,11 @@ } static int -rn_satisfies_leaf(char *trial, struct radix_node *leaf, int skip) +rn_satisfies_leaf(char *trial, struct radix_node *leaf, int skip, int salen) { char *cp = trial, *cp2 = leaf->rn_key, *cp3 = leaf->rn_mask; char *cplim; - int length = min(LEN(cp), LEN(cp2)); + int length = min(salen, LEN(cp2) - skip); if (cp3 == NULL) cp3 = rn_ones; @@ -283,7 +283,12 @@ caddr_t cp = v, cp2; caddr_t cplim; struct radix_node *saved_t, *top = t; - int off = t->rn_offset, vlen = LEN(cp), matched_off; +#ifndef RADIX_ALLOW_VARIABLE_KEY_LENGTH + int salen = t->rn_salen; +#else + int salen = LEN(cp); +#endif + int off = t->rn_offset, vlen = salen, matched_off; int test, b, rn_bit; /* @@ -344,7 +349,7 @@ if (t->rn_flags & RNF_NORMAL) { if (rn_bit <= t->rn_bit) return (t); - } else if (rn_satisfies_leaf(v, t, matched_off)) + } else if (rn_satisfies_leaf(v, t, matched_off, salen)) return (t); t = saved_t; /* start searching up the tree */ @@ -367,7 +372,7 @@ x = rn_search_m(v, t, m->rm_mask); while (x && x->rn_mask != m->rm_mask) x = x->rn_dupedkey; - if (x && rn_satisfies_leaf(v, x, off)) + if (x && rn_satisfies_leaf(v, x, off, salen)) return (x); } m = m->rm_mklist; @@ -1111,7 +1116,8 @@ * bits starting at 'off'. */ void -rn_inithead_internal(struct radix_head *rh, struct radix_node *base_nodes, int off) +rn_inithead_internal(struct radix_head *rh, struct radix_node *base_nodes, + int off, int salen) { struct radix_node *t, *tt, *ttt; @@ -1119,6 +1125,7 @@ ttt = base_nodes + 2; t->rn_right = ttt; t->rn_parent = t; + t->rn_salen = salen; tt = t->rn_left; /* ... which in turn is base_nodes */ tt->rn_flags = t->rn_flags = RNF_ROOT | RNF_ACTIVE; tt->rn_bit = -1 - off; @@ -1142,7 +1149,7 @@ /* Functions used by 'struct radix_node_head' users */ int -rn_inithead(void **head, int off) +rn_inithead(void **head, int off, int salen) { struct radix_node_head *rnh; struct radix_mask_head *rmh; @@ -1164,8 +1171,8 @@ } /* Init trees */ - rn_inithead_internal(&rnh->rh, rnh->rnh_nodes, off); - rn_inithead_internal(&rmh->head, rmh->mask_nodes, 0); + rn_inithead_internal(&rnh->rh, rnh->rnh_nodes, off, salen); + rn_inithead_internal(&rmh->head, rmh->mask_nodes, 0, 0); *head = rnh; rnh->rh.rnh_masks = rmh; Index: sys/net/route.h =================================================================== --- sys/net/route.h +++ sys/net/route.h @@ -455,7 +455,7 @@ void rt_newmaddrmsg(int, struct ifmultiaddr *); int rt_setgate(struct rtentry *, struct sockaddr *, struct sockaddr *); void rt_maskedcopy(struct sockaddr *, struct sockaddr *, struct sockaddr *); -struct rib_head *rt_table_init(int); +struct rib_head *rt_table_init(int, int, int, u_int); void rt_table_destroy(struct rib_head *); u_int rt_tables_get_gen(int table, int fam); Index: sys/net/route.c =================================================================== --- sys/net/route.c +++ sys/net/route.c @@ -345,7 +345,7 @@ #endif struct rib_head * -rt_table_init(int offset) +rt_table_init(int offset, int salen, int family, u_int fibnum) { struct rib_head *rh; @@ -353,8 +353,8 @@ /* TODO: These details should be hidded inside radix.c */ /* Init masks tree */ - rn_inithead_internal(&rh->head, rh->rnh_nodes, offset); - rn_inithead_internal(&rh->rmhead.head, rh->rmhead.mask_nodes, 0); + rn_inithead_internal(&rh->head, rh->rnh_nodes, offset, salen); + rn_inithead_internal(&rh->rmhead.head, rh->rmhead.mask_nodes, 0, 0); rh->head.rnh_masks = &rh->rmhead; /* Init locks */ Index: sys/net/route_var.h =================================================================== --- sys/net/route_var.h +++ sys/net/route_var.h @@ -60,6 +60,12 @@ struct rib_head *rt_tables_get_rnh(int fib, int family); +#ifndef container_of +#define container_of(ptr, type, member) \ + ((type *) ((uint8_t *)(ptr) - offsetof(type, member))) +#endif +#define RNTORT(p) ((struct rtentry *)(p)) + /* rte<>nhop translation */ static inline uint16_t fib_rte_to_nh_flags(int rt_flags) Index: sys/netinet/in_fib.c =================================================================== --- sys/netinet/in_fib.c +++ sys/netinet/in_fib.c @@ -65,7 +65,7 @@ static void fib4_rte_to_nh_extended(struct rtentry *rte, struct in_addr dst, uint32_t flags, struct nhop4_extended *pnh4); -#define RNTORT(p) ((struct rtentry *)(p)) +#define FIB4_LOOKUP_KEY(a) (void *)(container_of(a, struct sockaddr_in, sin_addr)) static void fib4_rte_to_nh_basic(struct rtentry *rte, struct in_addr dst, @@ -134,7 +134,6 @@ RIB_RLOCK_TRACKER; struct rib_head *rh; struct radix_node *rn; - struct sockaddr_in sin; struct rtentry *rte; KASSERT((fibnum < rt_numfibs), ("fib4_lookup_nh_basic: bad fibnum")); @@ -142,13 +141,8 @@ if (rh == NULL) return (ENOENT); - /* Prepare lookup key */ - memset(&sin, 0, sizeof(sin)); - sin.sin_len = sizeof(struct sockaddr_in); - sin.sin_addr = dst; - RIB_RLOCK(rh); - rn = rh->rnh_matchaddr((void *)&sin, &rh->head); + rn = rh->rnh_matchaddr(FIB4_LOOKUP_KEY(&dst), &rh->head); if (rn != NULL && ((rn->rn_flags & RNF_ROOT) == 0)) { rte = RNTORT(rn); /* Ensure route & ifp is UP */ @@ -183,7 +177,6 @@ RIB_RLOCK_TRACKER; struct rib_head *rh; struct radix_node *rn; - struct sockaddr_in sin; struct rtentry *rte; KASSERT((fibnum < rt_numfibs), ("fib4_lookup_nh_ext: bad fibnum")); @@ -191,13 +184,8 @@ if (rh == NULL) return (ENOENT); - /* Prepare lookup key */ - memset(&sin, 0, sizeof(sin)); - sin.sin_len = sizeof(struct sockaddr_in); - sin.sin_addr = dst; - RIB_RLOCK(rh); - rn = rh->rnh_matchaddr((void *)&sin, &rh->head); + rn = rh->rnh_matchaddr(FIB4_LOOKUP_KEY(&dst), &rh->head); if (rn != NULL && ((rn->rn_flags & RNF_ROOT) == 0)) { rte = RNTORT(rn); #ifdef RADIX_MPATH Index: sys/netinet/in_rmx.c =================================================================== --- sys/netinet/in_rmx.c +++ sys/netinet/in_rmx.c @@ -49,7 +49,7 @@ #include #include -extern int in_inithead(void **head, int off); +extern int in_inithead(void **head, int off, u_int fibnum); #ifdef VIMAGE extern int in_detachhead(void **head, int off); #endif @@ -116,11 +116,11 @@ * Initialize our routing tree. */ int -in_inithead(void **head, int off) +in_inithead(void **head, int off, u_int fibnum) { struct rib_head *rh; - rh = rt_table_init(32); + rh = rt_table_init(32, sizeof(struct sockaddr_in), AF_INET, fibnum); if (rh == NULL) return (0); Index: sys/netinet6/in6_fib.c =================================================================== --- sys/netinet6/in6_fib.c +++ sys/netinet6/in6_fib.c @@ -73,8 +73,9 @@ static void fib6_rte_to_nh_basic(struct rtentry *rte, const struct in6_addr *dst, uint32_t flags, struct nhop6_basic *pnh6); static struct ifnet *fib6_get_ifaifp(struct rtentry *rte); -#define RNTORT(p) ((struct rtentry *)(p)) +#define FIB6_LOOKUP_KEY(a) (void *)(container_of(a, struct sockaddr_in6, sin6_addr)) + /* * Gets real interface for the @rte. * Returns rt_ifp for !IFF_LOOPBACK routers. @@ -174,7 +175,7 @@ RIB_RLOCK_TRACKER; struct rib_head *rh; struct radix_node *rn; - struct sockaddr_in6 sin6; + struct in6_addr addr6; struct rtentry *rte; KASSERT((fibnum < rt_numfibs), ("fib6_lookup_nh_basic: bad fibnum")); @@ -183,20 +184,18 @@ return (ENOENT); /* Prepare lookup key */ - memset(&sin6, 0, sizeof(sin6)); - sin6.sin6_addr = *dst; - sin6.sin6_len = sizeof(struct sockaddr_in6); + addr6 = *dst; /* Assume scopeid is valid and embed it directly */ if (IN6_IS_SCOPE_LINKLOCAL(dst)) - sin6.sin6_addr.s6_addr16[1] = htons(scopeid & 0xffff); + addr6.s6_addr16[1] = htons(scopeid & 0xffff); RIB_RLOCK(rh); - rn = rh->rnh_matchaddr((void *)&sin6, &rh->head); + rn = rh->rnh_matchaddr(FIB6_LOOKUP_KEY(&addr6), &rh->head); if (rn != NULL && ((rn->rn_flags & RNF_ROOT) == 0)) { rte = RNTORT(rn); /* Ensure route & ifp is UP */ if (RT_LINK_IS_UP(rte->rt_ifp)) { - fib6_rte_to_nh_basic(rte, &sin6.sin6_addr, flags, pnh6); + fib6_rte_to_nh_basic(rte, &addr6, flags, pnh6); RIB_RUNLOCK(rh); return (0); } @@ -224,7 +223,7 @@ RIB_RLOCK_TRACKER; struct rib_head *rh; struct radix_node *rn; - struct sockaddr_in6 sin6; + struct in6_addr addr6; struct rtentry *rte; KASSERT((fibnum < rt_numfibs), ("fib6_lookup_nh_ext: bad fibnum")); @@ -233,15 +232,13 @@ return (ENOENT); /* Prepare lookup key */ - memset(&sin6, 0, sizeof(sin6)); - sin6.sin6_len = sizeof(struct sockaddr_in6); - sin6.sin6_addr = *dst; + addr6 = *dst; /* Assume scopeid is valid and embed it directly */ if (IN6_IS_SCOPE_LINKLOCAL(dst)) - sin6.sin6_addr.s6_addr16[1] = htons(scopeid & 0xffff); + addr6.s6_addr16[1] = htons(scopeid & 0xffff); RIB_RLOCK(rh); - rn = rh->rnh_matchaddr((void *)&sin6, &rh->head); + rn = rh->rnh_matchaddr(FIB6_LOOKUP_KEY(&addr6), &rh->head); if (rn != NULL && ((rn->rn_flags & RNF_ROOT) == 0)) { rte = RNTORT(rn); #ifdef RADIX_MPATH @@ -253,7 +250,7 @@ #endif /* Ensure route & ifp is UP */ if (RT_LINK_IS_UP(rte->rt_ifp)) { - fib6_rte_to_nh_extended(rte, &sin6.sin6_addr, flags, + fib6_rte_to_nh_extended(rte, &addr6, flags, pnh6); if ((flags & NHR_REF) != 0) { /* TODO: Do lwref on egress ifp's */ Index: sys/netinet6/in6_rmx.c =================================================================== --- sys/netinet6/in6_rmx.c +++ sys/netinet6/in6_rmx.c @@ -96,7 +96,7 @@ #include #include -extern int in6_inithead(void **head, int off); +extern int in6_inithead(void **head, int off, u_int fibnum); #ifdef VIMAGE extern int in6_detachhead(void **head, int off); #endif @@ -157,11 +157,12 @@ */ int -in6_inithead(void **head, int off) +in6_inithead(void **head, int off, u_int fibnum) { struct rib_head *rh; - rh = rt_table_init(offsetof(struct sockaddr_in6, sin6_addr) << 3); + rh = rt_table_init(offsetof(struct sockaddr_in6, sin6_addr) << 3, + sizeof(struct sockaddr_in6), AF_INET6, fibnum); if (rh == NULL) return (0); Index: sys/netpfil/ipfw/ip_fw_table_algo.c =================================================================== --- sys/netpfil/ipfw/ip_fw_table_algo.c +++ sys/netpfil/ipfw/ip_fw_table_algo.c @@ -440,9 +440,9 @@ { struct radix_cfg *cfg; - if (!rn_inithead(&ti->state, OFF_LEN_INET)) + if (!rn_inithead(&ti->state, OFF_LEN_INET, KEY_LEN_INET)) return (ENOMEM); - if (!rn_inithead(&ti->xstate, OFF_LEN_INET6)) { + if (!rn_inithead(&ti->xstate, OFF_LEN_INET6, KEY_LEN_INET6)) { rn_detachhead(&ti->state); return (ENOMEM); } Index: sys/netpfil/pf/pf_table.c =================================================================== --- sys/netpfil/pf/pf_table.c +++ sys/netpfil/pf/pf_table.c @@ -1954,9 +1954,11 @@ } if (!rn_inithead((void **)&kt->pfrkt_ip4, - offsetof(struct sockaddr_in, sin_addr) * 8) || + offsetof(struct sockaddr_in, sin_addr) * 8, + sizeof(struct sockaddr_in)) || !rn_inithead((void **)&kt->pfrkt_ip6, - offsetof(struct sockaddr_in6, sin6_addr) * 8)) { + offsetof(struct sockaddr_in6, sin6_addr) * 8, + sizeof(struct sockaddr_in6))) { pfr_destroy_ktable(kt, 0); return (NULL); }