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 *);