summaryrefslogtreecommitdiffstats
path: root/sys/netinet6/ip6_input.c
diff options
context:
space:
mode:
authorqingli <qingli@FreeBSD.org>2009-08-26 21:32:50 +0000
committerqingli <qingli@FreeBSD.org>2009-08-26 21:32:50 +0000
commit487e2c0d0063d49f54d59dd42d56ef49a5fb4c35 (patch)
treea7fc499b5e45b2aa0c5f9ccb59b33fabbaa9085a /sys/netinet6/ip6_input.c
parenta3275cab81f4d354b68eeb181d4ad4c9aac9ac3f (diff)
downloadFreeBSD-src-487e2c0d0063d49f54d59dd42d56ef49a5fb4c35.zip
FreeBSD-src-487e2c0d0063d49f54d59dd42d56ef49a5fb4c35.tar.gz
When multiple interfaces exist in the system, with each interface having
an IPv6 address assigned to it, and if an incoming packet received on one interface has a packet destination address that belongs to another interface, the routing table is consulted to determine how to reach this packet destination. Since the packet destination is an interface address, the route table will return a host route with the loopback interface as rt_ifp. The input code must recognize this fact, instead of using the loopback interface, the input code performs a search to find the right interface that owns the given IPv6 address. Reviewed by: bz, gnn, kmacy MFC after: immediately
Diffstat (limited to 'sys/netinet6/ip6_input.c')
-rw-r--r--sys/netinet6/ip6_input.c27
1 files changed, 25 insertions, 2 deletions
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
index 019d57f..4958d74 100644
--- a/sys/netinet6/ip6_input.c
+++ b/sys/netinet6/ip6_input.c
@@ -628,8 +628,27 @@ passin:
&rt6_key(rin6.ro_rt)->sin6_addr)
#endif
rin6.ro_rt->rt_ifp->if_type == IFT_LOOP) {
- struct in6_ifaddr *ia6 =
- (struct in6_ifaddr *)rin6.ro_rt->rt_ifa;
+ int free_ia6 = 0;
+ struct in6_ifaddr *ia6;
+
+ /*
+ * found the loopback route to the interface address
+ */
+ if (rin6.ro_rt->rt_gateway->sa_family == AF_LINK) {
+ struct sockaddr_in6 dest6;
+
+ bzero(&dest6, sizeof(dest6));
+ dest6.sin6_family = AF_INET6;
+ dest6.sin6_len = sizeof(dest6);
+ dest6.sin6_addr = ip6->ip6_dst;
+ ia6 = (struct in6_ifaddr *)
+ ifa_ifwithaddr((struct sockaddr *)&dest6);
+ if (ia6 == NULL)
+ goto bad;
+ free_ia6 = 1;
+ }
+ else
+ ia6 = (struct in6_ifaddr *)rin6.ro_rt->rt_ifa;
/*
* record address information into m_tag.
@@ -647,6 +666,8 @@ passin:
/* Count the packet in the ip address stats */
ia6->ia_ifa.if_ipackets++;
ia6->ia_ifa.if_ibytes += m->m_pkthdr.len;
+ if (ia6 != NULL && free_ia6 != 0)
+ ifa_free(&ia6->ia_ifa);
goto hbhcheck;
} else {
char ip6bufs[INET6_ADDRSTRLEN];
@@ -657,6 +678,8 @@ passin:
ip6_sprintf(ip6bufs, &ip6->ip6_src),
ip6_sprintf(ip6bufd, &ip6->ip6_dst)));
+ if (ia6 != NULL && free_ia6 != 0)
+ ifa_free(&ia6->ia_ifa);
goto bad;
}
}
OpenPOWER on IntegriCloud