* Initiate connection to peer. * Create a template for use in transmissions on this connection. * Enter SYN_SENT state, and mark socket as connecting. * Start keep-alive timer, and seed output sequence space. * Send initial segment on connection. */
| 573 | * Send initial segment on connection. |
| 574 | */ |
| 575 | static int |
| 576 | tcp_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td) |
| 577 | { |
| 578 | struct epoch_tracker et; |
| 579 | int error = 0; |
| 580 | struct inpcb *inp; |
| 581 | struct tcpcb *tp = NULL; |
| 582 | struct sockaddr_in *sinp; |
| 583 | |
| 584 | sinp = (struct sockaddr_in *)nam; |
| 585 | if (nam->sa_len != sizeof (*sinp)) |
| 586 | return (EINVAL); |
| 587 | /* |
| 588 | * Must disallow TCP ``connections'' to multicast addresses. |
| 589 | */ |
| 590 | if (sinp->sin_family == AF_INET |
| 591 | && IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) |
| 592 | return (EAFNOSUPPORT); |
| 593 | if ((sinp->sin_family == AF_INET) && |
| 594 | (ntohl(sinp->sin_addr.s_addr) == INADDR_BROADCAST)) |
| 595 | return (EACCES); |
| 596 | if ((error = prison_remote_ip4(td->td_ucred, &sinp->sin_addr)) != 0) |
| 597 | return (error); |
| 598 | |
| 599 | TCPDEBUG0; |
| 600 | inp = sotoinpcb(so); |
| 601 | KASSERT(inp != NULL, ("tcp_usr_connect: inp == NULL")); |
| 602 | INP_WLOCK(inp); |
| 603 | if (inp->inp_flags & INP_TIMEWAIT) { |
| 604 | error = EADDRINUSE; |
| 605 | goto out; |
| 606 | } |
| 607 | if (inp->inp_flags & INP_DROPPED) { |
| 608 | error = ECONNREFUSED; |
| 609 | goto out; |
| 610 | } |
| 611 | tp = intotcpcb(inp); |
| 612 | TCPDEBUG1(); |
| 613 | NET_EPOCH_ENTER(et); |
| 614 | if ((error = tcp_connect(tp, nam, td)) != 0) |
| 615 | goto out_in_epoch; |
| 616 | #ifdef TCP_OFFLOAD |
| 617 | if (registered_toedevs > 0 && |
| 618 | (so->so_options & SO_NO_OFFLOAD) == 0 && |
| 619 | (error = tcp_offload_connect(so, nam)) == 0) |
| 620 | goto out_in_epoch; |
| 621 | #endif |
| 622 | tcp_timer_activate(tp, TT_KEEP, TP_KEEPINIT(tp)); |
| 623 | error = tp->t_fb->tfb_tcp_output(tp); |
| 624 | out_in_epoch: |
| 625 | NET_EPOCH_EXIT(et); |
| 626 | out: |
| 627 | TCPDEBUG2(PRU_CONNECT); |
| 628 | TCP_PROBE2(debug__user, tp, PRU_CONNECT); |
| 629 | INP_WUNLOCK(inp); |
| 630 | return (error); |
| 631 | } |
| 632 | #endif /* INET */ |
nothing calls this directly
no test coverage detected