make sure to check address family on route cache. with IPv4 mapped

address we can see both AF_INET/INET6.
This commit is contained in:
itojun 2002-01-22 03:53:55 +00:00
parent d1f5dc17b6
commit ae1b9c29e9
3 changed files with 21 additions and 82 deletions

@ -1,4 +1,4 @@
/* $NetBSD: in_pcb.c,v 1.73 2001/11/13 00:32:36 lukem Exp $ */
/* $NetBSD: in_pcb.c,v 1.74 2002/01/22 03:53:55 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -102,7 +102,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: in_pcb.c,v 1.73 2001/11/13 00:32:36 lukem Exp $");
__KERNEL_RCSID(0, "$NetBSD: in_pcb.c,v 1.74 2002/01/22 03:53:55 itojun Exp $");
#include "opt_ipsec.h"
@ -397,78 +397,6 @@ in_pcbconnect(v, nam)
* destinations.
*/
if (in_nullhost(inp->inp_laddr)) {
#if 0
struct route *ro;
ia = (struct in_ifaddr *)0;
/*
* If route is known or can be allocated now,
* our src addr is taken from the i/f, else punt.
*/
ro = &inp->inp_route;
if (ro->ro_rt &&
(!in_hosteq(satosin(&ro->ro_dst)->sin_addr,
sin->sin_addr) ||
inp->inp_socket->so_options & SO_DONTROUTE)) {
RTFREE(ro->ro_rt);
ro->ro_rt = (struct rtentry *)0;
}
if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/
(ro->ro_rt == (struct rtentry *)0 ||
ro->ro_rt->rt_ifp == (struct ifnet *)0)) {
/* No route yet, so try to acquire one */
ro->ro_dst.sa_family = AF_INET;
ro->ro_dst.sa_len = sizeof(struct sockaddr_in);
satosin(&ro->ro_dst)->sin_addr = sin->sin_addr;
rtalloc(ro);
}
/*
* If we found a route, use the address
* corresponding to the outgoing interface
* unless it is the loopback (in case a route
* to our address on another net goes to loopback).
*
* XXX Is this still true? Do we care?
*/
if (ro->ro_rt && !(ro->ro_rt->rt_ifp->if_flags & IFF_LOOPBACK))
ia = ifatoia(ro->ro_rt->rt_ifa);
if (ia == NULL) {
u_int16_t fport = sin->sin_port;
sin->sin_port = 0;
ia = ifatoia(ifa_ifwithladdr(sintosa(sin)));
sin->sin_port = fport;
if (ia == 0) {
/* Find 1st non-loopback AF_INET address */
TAILQ_FOREACH(ia, &in_ifaddr, ia_list) {
if ((ia->ia_ifp->if_flags &
IFF_LOOPBACK) == 0)
break;
}
}
if (ia == NULL)
return (EADDRNOTAVAIL);
}
/*
* If the destination address is multicast and an outgoing
* interface has been set as a multicast option, use the
* address of that interface as our source address.
*/
if (IN_MULTICAST(sin->sin_addr.s_addr) &&
inp->inp_moptions != NULL) {
struct ip_moptions *imo;
struct ifnet *ifp;
imo = inp->inp_moptions;
if (imo->imo_multicast_ifp != NULL) {
ifp = imo->imo_multicast_ifp;
IFP_TO_IA(ifp, ia); /* XXX */
if (ia == 0)
return (EADDRNOTAVAIL);
}
}
ifaddr = satosin(&ia->ia_addr);
#else
int error;
ifaddr = in_selectsrc(sin, &inp->inp_route,
inp->inp_socket->so_options, inp->inp_moptions, &error);
@ -477,7 +405,6 @@ in_pcbconnect(v, nam)
error = EADDRNOTAVAIL;
return error;
}
#endif
}
if (in_pcblookup_connect(inp->inp_table, sin->sin_addr, sin->sin_port,
!in_nullhost(inp->inp_laddr) ? inp->inp_laddr : ifaddr->sin_addr,
@ -911,6 +838,7 @@ in_pcbrtentry(inp)
* No route yet, so try to acquire one.
*/
if (!in_nullhost(inp->inp_faddr)) {
bzero(&ro->ro_dst, sizeof(struct sockaddr_in));
ro->ro_dst.sa_family = AF_INET;
ro->ro_dst.sa_len = sizeof(ro->ro_dst);
satosin(&ro->ro_dst)->sin_addr = inp->inp_faddr;
@ -934,17 +862,21 @@ in_selectsrc(sin, ro, soopts, mopts, errorp)
/*
* If route is known or can be allocated now,
* our src addr is taken from the i/f, else punt.
* Note that we should check the address family of the cached
* destination, in case of sharing the cache with IPv6.
*/
if (ro->ro_rt &&
(!in_hosteq(satosin(&ro->ro_dst)->sin_addr, sin->sin_addr) ||
(ro->ro_dst.sa_family != AF_INET ||
!in_hosteq(satosin(&ro->ro_dst)->sin_addr, sin->sin_addr) ||
soopts & SO_DONTROUTE)) {
RTFREE(ro->ro_rt);
ro->ro_rt = (struct rtentry *)0;
}
if ((soopts & SO_DONTROUTE) == 0 && /*XXX*/
(ro->ro_rt == (struct rtentry *)0 ||
ro->ro_rt->rt_ifp == (struct ifnet *)0)) {
ro->ro_rt->rt_ifp == (struct ifnet *)0)) {
/* No route yet, so try to acquire one */
bzero(&ro->ro_dst, sizeof(struct sockaddr_in));
ro->ro_dst.sa_family = AF_INET;
ro->ro_dst.sa_len = sizeof(struct sockaddr_in);
satosin(&ro->ro_dst)->sin_addr = sin->sin_addr;

@ -1,4 +1,4 @@
/* $NetBSD: ip_output.c,v 1.91 2002/01/08 10:05:13 itojun Exp $ */
/* $NetBSD: ip_output.c,v 1.92 2002/01/22 03:53:55 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -102,7 +102,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ip_output.c,v 1.91 2002/01/08 10:05:13 itojun Exp $");
__KERNEL_RCSID(0, "$NetBSD: ip_output.c,v 1.92 2002/01/22 03:53:55 itojun Exp $");
#include "opt_pfil_hooks.h"
#include "opt_ipsec.h"
@ -235,13 +235,17 @@ ip_output(m0, va_alist)
* If there is a cached route,
* check that it is to the same destination
* and is still up. If not, free it and try again.
* The address family should also be checked in case of sharing the
* cache with IPv6.
*/
if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
dst->sin_family != AF_INET ||
!in_hosteq(dst->sin_addr, ip->ip_dst))) {
RTFREE(ro->ro_rt);
ro->ro_rt = (struct rtentry *)0;
}
if (ro->ro_rt == 0) {
bzero(dst, sizeof(*dst));
dst->sin_family = AF_INET;
dst->sin_len = sizeof(*dst);
dst->sin_addr = ip->ip_dst;

@ -1,4 +1,4 @@
/* $NetBSD: in6_src.c,v 1.9 2001/11/13 00:57:00 lukem Exp $ */
/* $NetBSD: in6_src.c,v 1.10 2002/01/22 03:53:56 itojun Exp $ */
/* $KAME: in6_src.c,v 1.36 2001/02/06 04:08:17 itojun Exp $ */
/*
@ -66,7 +66,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: in6_src.c,v 1.9 2001/11/13 00:57:00 lukem Exp $");
__KERNEL_RCSID(0, "$NetBSD: in6_src.c,v 1.10 2002/01/22 03:53:56 itojun Exp $");
#include "opt_inet.h"
@ -240,10 +240,13 @@ in6_selectsrc(dstsock, opts, mopts, ro, laddr, errorp)
/*
* If route is known or can be allocated now,
* our src addr is taken from the i/f, else punt.
* Note that we should check the address family of the
* cached destination, in case of sharing the cache with IPv4.
*/
if (ro) {
if (ro->ro_rt &&
!IN6_ARE_ADDR_EQUAL(&satosin6(&ro->ro_dst)->sin6_addr, dst)) {
(ro->ro_dst.sin6_family != AF_INET6 ||
!IN6_ARE_ADDR_EQUAL(&satosin6(&ro->ro_dst)->sin6_addr, dst))) {
RTFREE(ro->ro_rt);
ro->ro_rt = (struct rtentry *)0;
}