diff --git a/freebsd/netinet/in_pcb.c b/freebsd/netinet/in_pcb.c index 37d65330..22730aed 100644 --- a/freebsd/netinet/in_pcb.c +++ b/freebsd/netinet/in_pcb.c @@ -1126,7 +1126,10 @@ if (lport == 0) ifp_sin.sin_len = sizeof(ifp_sin); ifa = ifa_ifwithnet((struct sockaddr *)&ifp_sin, 0, RT_ALL_FIBS); if (ifa == NULL) { - return (EADDRNOTAVAIL); + ifp_sin.sin_addr.s_addr = faddr.s_addr; + ifa = ifa_ifwithnet((struct sockaddr *)&ifp_sin, 0, RT_ALL_FIBS); + if ( ifa == NULL ) + return (EADDRNOTAVAIL); } ifp = ifa->ifa_ifp; while (lport == 0) { diff --git a/freebsd/netinet/tcp_usrreq.c b/freebsd/netinet/tcp_usrreq.c index b33efedc..57c7bc18 100644 --- a/freebsd/netinet/tcp_usrreq.c +++ b/freebsd/netinet/tcp_usrreq.c @@ -1321,14 +1321,22 @@ tcp_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td) error = EADDRINUSE; goto out; } + + // inp->inp_lport != lport means in_pcbconnect_setup selected new port to inp->inp_lport. + // inp will inhash. + if (in_pcbinshash(inp) != 0) { + inp->inp_laddr.s_addr = INADDR_ANY; + inp->inp_lport = 0; + return (EAGAIN); + } } - - if (in_pcbinshash(inp) != 0) { - inp->inp_laddr.s_addr = INADDR_ANY; - inp->inp_lport = 0; - return (EAGAIN); + else + { + // app call bind() and connect(), lport is set when bind, and the inp is inhashed in bind() function. + // in_pcbconnect_setup() update inp->inp_faddr/inp->inp_fport, so inp should be rehashed. + in_pcbrehash(inp); } - + if (anonport) { inp->inp_flags |= INP_ANONPORT; }