From owner-svn-src-stable@FreeBSD.ORG Sun Aug 30 22:36:47 2009 Return-Path: Delivered-To: svn-src-stable@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 69259106568F; Sun, 30 Aug 2009 22:36:47 +0000 (UTC) (envelope-from qingli@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 3C0E98FC1C; Sun, 30 Aug 2009 22:36:47 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n7UMal8T008294; Sun, 30 Aug 2009 22:36:47 GMT (envelope-from qingli@svn.freebsd.org) Received: (from qingli@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n7UMalEU008292; Sun, 30 Aug 2009 22:36:47 GMT (envelope-from qingli@svn.freebsd.org) Message-Id: <200908302236.n7UMalEU008292@svn.freebsd.org> From: Qing Li Date: Sun, 30 Aug 2009 22:36:47 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r196671 - in stable/8/sys: . amd64/include/xen cddl/contrib/opensolaris contrib/dev/acpica contrib/pf dev/xen/xenpci netinet6 X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 30 Aug 2009 22:36:47 -0000 Author: qingli Date: Sun Aug 30 22:36:46 2009 New Revision: 196671 URL: http://svn.freebsd.org/changeset/base/196671 Log: MFC r196569 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 Approved by: re Modified: stable/8/sys/ (props changed) stable/8/sys/amd64/include/xen/ (props changed) stable/8/sys/cddl/contrib/opensolaris/ (props changed) stable/8/sys/contrib/dev/acpica/ (props changed) stable/8/sys/contrib/pf/ (props changed) stable/8/sys/dev/xen/xenpci/ (props changed) stable/8/sys/netinet6/ip6_input.c Modified: stable/8/sys/netinet6/ip6_input.c ============================================================================== --- stable/8/sys/netinet6/ip6_input.c Sun Aug 30 22:35:20 2009 (r196670) +++ stable/8/sys/netinet6/ip6_input.c Sun Aug 30 22:36:46 2009 (r196671) @@ -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; } }