* Common subroutine to open a TCP connection to remote host specified * by struct sockaddr_in in mbuf *nam. Call in_pcbbind to assign a local * port number if needed. Call in_pcbconnect_setup to do the routing and * to choose a local host address (interface). If there is an existing * incarnation of the same connection in TIME-WAIT state and if the remote * host was sending CC options and
| 1587 | * Initialize connection parameters and enter SYN-SENT state. |
| 1588 | */ |
| 1589 | static int |
| 1590 | tcp_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td) |
| 1591 | { |
| 1592 | struct inpcb *inp = tp->t_inpcb, *oinp; |
| 1593 | struct socket *so = inp->inp_socket; |
| 1594 | struct in_addr laddr; |
| 1595 | u_short lport; |
| 1596 | int error; |
| 1597 | |
| 1598 | NET_EPOCH_ASSERT(); |
| 1599 | INP_WLOCK_ASSERT(inp); |
| 1600 | INP_HASH_WLOCK(&V_tcbinfo); |
| 1601 | |
| 1602 | #ifndef FSTACK |
| 1603 | if (V_tcp_require_unique_port && inp->inp_lport == 0) { |
| 1604 | error = in_pcbbind(inp, (struct sockaddr *)0, td->td_ucred); |
| 1605 | if (error) |
| 1606 | goto out; |
| 1607 | } |
| 1608 | |
| 1609 | /* |
| 1610 | * Cannot simply call in_pcbconnect, because there might be an |
| 1611 | * earlier incarnation of this same connection still in |
| 1612 | * TIME_WAIT state, creating an ADDRINUSE error. |
| 1613 | */ |
| 1614 | laddr = inp->inp_laddr; |
| 1615 | lport = inp->inp_lport; |
| 1616 | error = in_pcbconnect_setup(inp, nam, &laddr.s_addr, &lport, |
| 1617 | &inp->inp_faddr.s_addr, &inp->inp_fport, &oinp, td->td_ucred); |
| 1618 | if (error && oinp == NULL) |
| 1619 | goto out; |
| 1620 | if (oinp) { |
| 1621 | error = EADDRINUSE; |
| 1622 | goto out; |
| 1623 | } |
| 1624 | /* Handle initial bind if it hadn't been done in advance. */ |
| 1625 | if (inp->inp_lport == 0) { |
| 1626 | inp->inp_lport = lport; |
| 1627 | if (in_pcbinshash(inp) != 0) { |
| 1628 | inp->inp_lport = 0; |
| 1629 | error = EAGAIN; |
| 1630 | goto out; |
| 1631 | } |
| 1632 | } |
| 1633 | inp->inp_laddr = laddr; |
| 1634 | in_pcbrehash(inp); |
| 1635 | #else |
| 1636 | int anonport = 0; |
| 1637 | if (inp->inp_lport == 0) { |
| 1638 | anonport = 1; |
| 1639 | } |
| 1640 | |
| 1641 | laddr = inp->inp_laddr; |
| 1642 | lport = inp->inp_lport; |
| 1643 | error = in_pcbconnect_setup(inp, nam, &laddr.s_addr, &lport, |
| 1644 | &inp->inp_faddr.s_addr, &inp->inp_fport, &oinp, td->td_ucred); |
| 1645 | if (error && oinp == NULL) |
| 1646 | goto out; |
no test coverage detected