summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/net/if_llatbl.c9
-rw-r--r--sys/netinet6/in6.c11
-rw-r--r--sys/netinet6/in6_src.c30
-rw-r--r--sys/netinet6/ip6_output.c15
4 files changed, 44 insertions, 21 deletions
diff --git a/sys/net/if_llatbl.c b/sys/net/if_llatbl.c
index b66d6e1..fb94f73 100644
--- a/sys/net/if_llatbl.c
+++ b/sys/net/if_llatbl.c
@@ -263,6 +263,15 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
__func__, dl->sdl_index);
return EINVAL;
}
+ if (ifp->if_flags & IFF_LOOPBACK) {
+ struct ifaddr *ia;
+ ia = ifa_ifwithaddr(dst);
+ if (ia != NULL) {
+ ifp = ia->ifa_ifp;
+ ifa_free(ia);
+ } else
+ return EINVAL;
+ }
switch (rtm->rtm_type) {
case RTM_ADD:
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index b0b2585..9521e8e 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -1201,8 +1201,8 @@ in6_purgeaddr(struct ifaddr *ifa)
bzero(&null_sdl, sizeof(null_sdl));
null_sdl.sdl_len = sizeof(null_sdl);
null_sdl.sdl_family = AF_LINK;
- null_sdl.sdl_type = V_loif->if_type;
- null_sdl.sdl_index = V_loif->if_index;
+ null_sdl.sdl_type = ia->ia_ifp->if_type;
+ null_sdl.sdl_index = ia->ia_ifp->if_index;
bzero(&info, sizeof(info));
info.rti_flags = ia->ia_flags | RTF_HOST | RTF_STATIC;
info.rti_info[RTAX_DST] = (struct sockaddr *)&ia->ia_addr;
@@ -1782,9 +1782,9 @@ in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia,
if (error == 0 && rt != NULL) {
RT_LOCK(rt);
((struct sockaddr_dl *)rt->rt_gateway)->sdl_type =
- rt->rt_ifp->if_type;
+ ifp->if_type;
((struct sockaddr_dl *)rt->rt_gateway)->sdl_index =
- rt->rt_ifp->if_index;
+ ifp->if_index;
RT_REMREF(rt);
RT_UNLOCK(rt);
} else if (error != 0)
@@ -2495,6 +2495,9 @@ in6_lltable_dump(struct lltable *llt, struct sysctl_req *wr)
} ndpc;
int i, error;
+ if (ifp->if_flags & IFF_LOOPBACK)
+ return 0;
+
LLTABLE_LOCK_ASSERT();
error = 0;
diff --git a/sys/netinet6/in6_src.c b/sys/netinet6/in6_src.c
index f087fae..8e82ef1 100644
--- a/sys/netinet6/in6_src.c
+++ b/sys/netinet6/in6_src.c
@@ -85,6 +85,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sx.h>
#include <net/if.h>
+#include <net/if_dl.h>
#include <net/route.h>
#include <net/if_llatbl.h>
#ifdef RADIX_MPATH
@@ -697,8 +698,25 @@ selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
if (error == EHOSTUNREACH)
V_ip6stat.ip6s_noroute++;
- if (retifp != NULL)
+ if (retifp != NULL) {
*retifp = ifp;
+
+ /*
+ * Adjust the "outgoing" interface. If we're going to loop
+ * the packet back to ourselves, the ifp would be the loopback
+ * interface. However, we'd rather know the interface associated
+ * to the destination address (which should probably be one of
+ * our own addresses.)
+ */
+ if (rt) {
+ if ((rt->rt_ifp->if_flags & IFF_LOOPBACK) &&
+ (rt->rt_gateway->sa_family == AF_LINK))
+ *retifp =
+ ifnet_byindex(((struct sockaddr_dl *)
+ rt->rt_gateway)->sdl_index);
+ }
+ }
+
if (retrt != NULL)
*retrt = rt; /* rt may be NULL */
@@ -750,16 +768,6 @@ in6_selectif(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
return (flags);
}
- /*
- * Adjust the "outgoing" interface. If we're going to loop the packet
- * back to ourselves, the ifp would be the loopback interface.
- * However, we'd rather know the interface associated to the
- * destination address (which should probably be one of our own
- * addresses.)
- */
- if (rt && rt->rt_ifa && rt->rt_ifa->ifa_ifp)
- *retifp = rt->rt_ifa->ifa_ifp;
-
if (ro == &sro && rt && rt == sro.ro_rt)
RTFREE(rt);
return (0);
diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c
index c48ac7b..9887564 100644
--- a/sys/netinet6/ip6_output.c
+++ b/sys/netinet6/ip6_output.c
@@ -602,15 +602,12 @@ again:
rt->rt_use++;
}
+
/*
* The outgoing interface must be in the zone of source and
- * destination addresses. We should use ia_ifp to support the
- * case of sending packets to an address of our own.
+ * destination addresses.
*/
- if (ia != NULL && ia->ia_ifp)
- origifp = ia->ia_ifp;
- else
- origifp = ifp;
+ origifp = ifp;
src0 = ip6->ip6_src;
if (in6_setscope(&src0, origifp, &zone))
@@ -634,6 +631,12 @@ again:
goto badscope;
}
+ /* We should use ia_ifp to support the case of
+ * sending packets to an address of our own.
+ */
+ if (ia != NULL && ia->ia_ifp)
+ ifp = ia->ia_ifp;
+
/* scope check is done. */
goto routefound;
OpenPOWER on IntegriCloud