X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/43866e378188c25dd1e2208016ab3cbeb086ae6c..55e303ae13a4cf49d70f2294092726f2fffb9ef2:/bsd/netinet/in_pcb.c diff --git a/bsd/netinet/in_pcb.c b/bsd/netinet/in_pcb.c index 3e1a98d30..ef52ab61f 100644 --- a/bsd/netinet/in_pcb.c +++ b/bsd/netinet/in_pcb.c @@ -105,6 +105,8 @@ extern int ipsec_bypass; #endif +extern u_long route_generation; + #define DBG_FNC_PCB_LOOKUP NETDBG_CODE(DBG_NETTCP, (6 << 8)) #define DBG_FNC_PCB_HLOOKUP NETDBG_CODE(DBG_NETTCP, ((6 << 8) | 1)) @@ -451,12 +453,16 @@ 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 != + (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)) { + inp->inp_socket->so_options & SO_DONTROUTE || + ro->ro_rt->generation_id != route_generation)) { rtfree(ro->ro_rt); ro->ro_rt = (struct rtentry *)0; } @@ -464,6 +470,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 = @@ -557,6 +564,7 @@ in_pcbconnect(inp, nam, p) return (error); } inp->inp_laddr = ifaddr->sin_addr; + inp->inp_flags |= INP_INADDR_ANY; } inp->inp_faddr = sin->sin_addr; inp->inp_fport = sin->sin_port; @@ -614,8 +622,10 @@ in_pcbdetach(inp) rt->rt_gateway, rt_mask(rt), rt->rt_flags, (struct rtentry **)0); } - else + else { rtfree(rt); + inp->inp_route.ro_rt = 0; + } } ip_freemoptions(inp->inp_moptions); inp->inp_vflag = 0; @@ -1115,7 +1125,7 @@ in_pcbremlists(inp) LIST_REMOVE(inp, inp_hash); LIST_REMOVE(inp, inp_portlist); - if (LIST_FIRST(&phd->phd_pcblist) == NULL) { + if (phd != NULL && (LIST_FIRST(&phd->phd_pcblist) == NULL)) { LIST_REMOVE(phd, phd_hash); FREE(phd, M_PCB); }