diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index e8506c32385c..59aec2eaec1b 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -413,12 +413,15 @@ in_pcbladdr(inp, nam, plocal_sin) /* * 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. */ ro = &inp->inp_route; if (ro->ro_rt && - (satosin(&ro->ro_dst)->sin_addr.s_addr != - sin->sin_addr.s_addr || - inp->inp_socket->so_options & SO_DONTROUTE)) { + (ro->ro_dst.sa_family != AF_INET || + satosin(&ro->ro_dst)->sin_addr.s_addr != + sin->sin_addr.s_addr || + inp->inp_socket->so_options & SO_DONTROUTE)) { RTFREE(ro->ro_rt); ro->ro_rt = (struct rtentry *)0; } @@ -426,6 +429,7 @@ in_pcbladdr(inp, nam, plocal_sin) (ro->ro_rt == (struct rtentry *)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); ((struct sockaddr_in *) &ro->ro_dst)->sin_addr = diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index af06486163d6..1b9c28d6d60d 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -224,13 +224,17 @@ ip_output(m0, opt, ro, flags, imo) * 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_addr.s_addr != pkt_dst.s_addr)) { + dst->sin_family != AF_INET || + dst->sin_addr.s_addr != pkt_dst.s_addr)) { 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 = pkt_dst;