This is basically a rewrite of in6_ifpprefix() in a more generic fashion. The idea is to get rid of rt_ifp. I'm also introducing if_isconnected() because I want to use it in ARP.
ok? Index: netinet6/in6.c =================================================================== RCS file: /cvs/src/sys/netinet6/in6.c,v retrieving revision 1.178 diff -u -p -r1.178 in6.c --- netinet6/in6.c 2 Nov 2015 15:05:23 -0000 1.178 +++ netinet6/in6.c 12 Nov 2015 10:33:30 -0000 @@ -61,7 +61,6 @@ * @(#)in.c 8.2 (Berkeley) 11/15/93 */ -#include "bridge.h" #include "carp.h" #include <sys/param.h> @@ -84,9 +83,6 @@ #include <netinet/in.h> #include <netinet/if_ether.h> -#if NBRIDGE > 0 -#include <net/if_bridge.h> -#endif #include <netinet6/in6_var.h> #include <netinet/ip6.h> @@ -1448,44 +1444,6 @@ in6ifa_ifpwithaddr(struct ifnet *ifp, st } return (ifatoia6(ifa)); -} - -/* - * Check whether an interface has a prefix by looking up the cloning route. - */ -int -in6_ifpprefix(const struct ifnet *ifp, const struct in6_addr *addr) -{ - struct sockaddr_in6 dst; - struct rtentry *rt; - u_int tableid = ifp->if_rdomain; - - bzero(&dst, sizeof(dst)); - dst.sin6_len = sizeof(struct sockaddr_in6); - dst.sin6_family = AF_INET6; - dst.sin6_addr = *addr; - rt = rtalloc(sin6tosa(&dst), 0, tableid); - - if (rt == NULL) - return (0); - if ((rt->rt_flags & (RTF_CLONING | RTF_CLONED)) == 0 || - (rt->rt_ifp != ifp && -#if NBRIDGE > 0 - !SAME_BRIDGE(rt->rt_ifp->if_bridgeport, ifp->if_bridgeport) && -#endif -#if NCARP > 0 - (ifp->if_type != IFT_CARP || rt->rt_ifp != ifp->if_carpdev) && - (rt->rt_ifp->if_type != IFT_CARP || rt->rt_ifp->if_carpdev != ifp)&& - (ifp->if_type != IFT_CARP || rt->rt_ifp->if_type != IFT_CARP || - rt->rt_ifp->if_carpdev != ifp->if_carpdev) && -#endif - 1)) { - rtfree(rt); - return (0); - } - - rtfree(rt); - return (1); } /* Index: netinet6/in6_var.h =================================================================== RCS file: /cvs/src/sys/netinet6/in6_var.h,v retrieving revision 1.57 diff -u -p -r1.57 in6_var.h --- netinet6/in6_var.h 5 Oct 2015 01:22:34 -0000 1.57 +++ netinet6/in6_var.h 12 Nov 2015 10:14:21 -0000 @@ -506,7 +506,6 @@ void *in6_domifattach(struct ifnet *); void in6_domifdetach(struct ifnet *, void *); struct in6_ifaddr *in6ifa_ifpforlinklocal(struct ifnet *, int); struct in6_ifaddr *in6ifa_ifpwithaddr(struct ifnet *, struct in6_addr *); -int in6_ifpprefix(const struct ifnet *, const struct in6_addr *); int in6_addr2scopeid(unsigned int, struct in6_addr *); int in6_matchlen(struct in6_addr *, struct in6_addr *); int in6_are_prefix_equal(struct in6_addr *, struct in6_addr *, int); Index: netinet6/nd6_nbr.c =================================================================== RCS file: /cvs/src/sys/netinet6/nd6_nbr.c,v retrieving revision 1.99 diff -u -p -r1.99 nd6_nbr.c --- netinet6/nd6_nbr.c 2 Nov 2015 15:05:23 -0000 1.99 +++ netinet6/nd6_nbr.c 12 Nov 2015 10:36:56 -0000 @@ -81,6 +81,8 @@ void nd6_dad_ns_output(struct dadq *, st void nd6_dad_ns_input(struct ifaddr *); void nd6_dad_duplicated(struct dadq *); +int nd6_isneighbor(const struct ifnet *, const struct in6_addr *); + static int dad_maxtry = 15; /* max # of *tries* to transmit DAD packet */ /* @@ -149,7 +151,7 @@ nd6_ns_input(struct mbuf *m, int off, in /* * Make sure the source address is from a neighbor's address. */ - if (!in6_ifpprefix(ifp, &saddr6)) { + if (!nd6_isneighbor(ifp, &saddr6)) { nd6log((LOG_INFO, "nd6_ns_input: " "NS packet from non-neighbor\n")); goto bad; @@ -684,7 +686,7 @@ nd6_na_input(struct mbuf *m, int off, in /* * Make sure the source address is from a neighbor's address. */ - if (!in6_ifpprefix(ifp, &saddr6)) { + if (!nd6_isneighbor(ifp, &saddr6)) { nd6log((LOG_INFO, "nd6_na_input: " "ND packet from non-neighbor\n")); goto bad; @@ -1405,4 +1407,28 @@ nd6_dad_ns_input(struct ifaddr *ifa) if (dp) dp->dad_ns_icount++; } +} + +/* + * Check whether ``addr'' is a neighbor address connected to ``ifp''. + */ +int +nd6_isneighbor(const struct ifnet *ifp, const struct in6_addr *addr) +{ + struct rtentry *rt; + struct sockaddr_in6 sin6; + unsigned int tableid = ifp->if_rdomain; + int rv = 0; + + memset(&sin6, 0, sizeof(sin6)); + sin6.sin6_len = sizeof(struct sockaddr_in6); + sin6.sin6_family = AF_INET6; + sin6.sin6_addr = *addr; + rt = rtalloc(sin6tosa(&sin6), 0, tableid); + + if (rtisvalid(rt) && ISSET(rt->rt_flags, RTF_CLONING|RTF_CLONED)) + rv = if_isconnected(ifp, rt->rt_ifidx); + + rtfree(rt); + return (rv); } Index: net/if.c =================================================================== RCS file: /cvs/src/sys/net/if.c,v retrieving revision 1.405 diff -u -p -r1.405 if.c --- net/if.c 11 Nov 2015 10:23:23 -0000 1.405 +++ net/if.c 12 Nov 2015 10:34:37 -0000 @@ -945,6 +945,36 @@ if_detach(struct ifnet *ifp) } /* + * Returns true if ``ifp0'' is connected to the interface with index ``ifidx''. + */ +int +if_isconnected(const struct ifnet *ifp0, unsigned int ifidx) +{ + struct ifnet *ifp; + int connected = 0; + + ifp = if_get(ifidx); + if (ifp == NULL) + return (0); + + if (ifp0->if_index == ifp->if_index) + connected = 1; + +#if NBRIDGE > 0 + if (SAME_BRIDGE(ifp0->if_bridgeport, ifp->if_bridgeport)) + connected = 1; +#endif +#if NCARP > 0 + if ((ifp0->if_type == IFT_CARP && ifp0->if_carpdev == ifp) || + (ifp->if_type == IFT_CARP && ifp->if_carpdev == ifp0)) + connected = 1; +#endif + + if_put(ifp); + return (connected); +} + +/* * Create a clone network interface. */ int Index: net/if_var.h =================================================================== RCS file: /cvs/src/sys/net/if_var.h,v retrieving revision 1.52 diff -u -p -r1.52 if_var.h --- net/if_var.h 11 Nov 2015 10:23:23 -0000 1.52 +++ net/if_var.h 12 Nov 2015 10:31:29 -0000 @@ -426,6 +426,8 @@ struct ifaddr *ifa_ifwithnet(struct sock struct ifaddr *ifaof_ifpforaddr(struct sockaddr *, struct ifnet *); void ifafree(struct ifaddr *); +int if_isconnected(const struct ifnet *, unsigned int); + void if_clone_attach(struct if_clone *); void if_clone_detach(struct if_clone *);