Use sockaddr_in6 in new jail API. Remove in6_pcbladdr() and use in6_pcbconnect(). --- sys/netinet/tcp_usrreq.c (svn+ssh://svn.freebsd.org/base/head) (revision 261548) +++ sys/netinet/tcp_usrreq.c (working copy) @@ -549,7 +549,7 @@ tcp6_usr_connect(struct socket *so, struct sockadd inp->inp_vflag &= ~INP_IPV4; inp->inp_vflag |= INP_IPV6; inp->inp_inc.inc_flags |= INC_ISIPV6; - if ((error = prison_remote_ip6(td->td_ucred, &sin6p->sin6_addr)) != 0) + if ((error = prison_remote_ip6(td->td_ucred, sin6p)) != 0) goto out; if ((error = tcp6_connect(tp, nam, td)) != 0) goto out; @@ -655,12 +655,13 @@ out: static int tcp6_usr_accept(struct socket *so, struct sockaddr **nam) { + struct in6_addr addr6; + struct in_addr addr; struct inpcb *inp = NULL; - int error = 0; struct tcpcb *tp = NULL; - struct in_addr addr; - struct in6_addr addr6; + uint32_t zoneid = 0; in_port_t port = 0; + int error = 0; int v4 = 0; TCPDEBUG0; @@ -690,6 +691,7 @@ tcp6_usr_accept(struct socket *so, struct sockaddr } else { port = inp->inp_fport; addr6 = inp->in6p_faddr; + zoneid = inp->in6p_zoneid; } out: @@ -700,9 +702,9 @@ out: if (v4) *nam = in6_v4mapsin6_sockaddr(port, &addr); else - *nam = in6_sockaddr(port, &addr6); + *nam = in6_sockaddr(port, &addr6, zoneid); } - return error; + return (error); } #endif /* INET6 */ @@ -1160,10 +1162,7 @@ out: static int tcp6_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td) { - struct inpcb *inp = tp->t_inpcb, *oinp; - struct socket *so = inp->inp_socket; - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam; - struct in6_addr addr6; + struct inpcb *inp = tp->t_inpcb; int error; INP_WLOCK_ASSERT(inp); @@ -1174,39 +1173,9 @@ tcp6_connect(struct tcpcb *tp, struct sockaddr *na if (error) goto out; } - - /* - * Cannot simply call in_pcbconnect, because there might be an - * earlier incarnation of this same connection still in - * TIME_WAIT state, creating an ADDRINUSE error. - * in6_pcbladdr() also handles scope zone IDs. - * - * XXXRW: We wouldn't need to expose in6_pcblookup_hash_locked() - * outside of in6_pcb.c if there were an in6_pcbconnect_setup(). - */ - error = in6_pcbladdr(inp, nam, &addr6); - if (error) + error = in6_pcbconnect(inp, nam, td->td_ucred); + if (error != 0) goto out; - oinp = in6_pcblookup_hash_locked(inp->inp_pcbinfo, - &sin6->sin6_addr, sin6->sin6_port, - IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr) - ? &addr6 - : &inp->in6p_laddr, - inp->inp_lport, 0, NULL); - if (oinp) { - error = EADDRINUSE; - goto out; - } - if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) - inp->in6p_laddr = addr6; - inp->in6p_faddr = sin6->sin6_addr; - inp->inp_fport = sin6->sin6_port; - /* update flowinfo - draft-itojun-ipv6-flowlabel-api-00 */ - inp->inp_flow &= ~IPV6_FLOWLABEL_MASK; - if (inp->inp_flags & IN6P_AUTOFLOWLABEL) - inp->inp_flow |= - (htonl(ip6_randomflowlabel()) & IPV6_FLOWLABEL_MASK); - in_pcbrehash(inp); INP_HASH_WUNLOCK(&V_tcbinfo); /* Compute window scaling to request. */ @@ -1214,7 +1183,7 @@ tcp6_connect(struct tcpcb *tp, struct sockaddr *na (TCP_MAXWIN << tp->request_r_scale) < sb_max) tp->request_r_scale++; - soisconnecting(so); + soisconnecting(inp->inp_socket); TCPSTAT_INC(tcps_connattempt); tcp_state_change(tp, TCPS_SYN_SENT); tp->iss = tcp_new_isn(tp);