Lines 609-621
out:
Link Here
|
609 |
/* |
609 |
/* |
610 |
* Accept a connection. Essentially all the work is done at higher levels; |
610 |
* Accept a connection. Essentially all the work is done at higher levels; |
611 |
* just return the address of the peer, storing through addr. |
611 |
* just return the address of the peer, storing through addr. |
612 |
* |
|
|
613 |
* The rationale for acquiring the tcbinfo lock here is somewhat complicated, |
614 |
* and is described in detail in the commit log entry for r175612. Acquiring |
615 |
* it delays an accept(2) racing with sonewconn(), which inserts the socket |
616 |
* before the inpcb address/port fields are initialized. A better fix would |
617 |
* prevent the socket from being placed in the listen queue until all fields |
618 |
* are fully initialized. |
619 |
*/ |
612 |
*/ |
620 |
static int |
613 |
static int |
621 |
tcp_usr_accept(struct socket *so, struct sockaddr **nam) |
614 |
tcp_usr_accept(struct socket *so, struct sockaddr **nam) |
Lines 632-638
tcp_usr_accept(struct socket *so, struct sockaddr **nam)
Link Here
|
632 |
|
625 |
|
633 |
inp = sotoinpcb(so); |
626 |
inp = sotoinpcb(so); |
634 |
KASSERT(inp != NULL, ("tcp_usr_accept: inp == NULL")); |
627 |
KASSERT(inp != NULL, ("tcp_usr_accept: inp == NULL")); |
635 |
INP_INFO_RLOCK(&V_tcbinfo); |
|
|
636 |
INP_WLOCK(inp); |
628 |
INP_WLOCK(inp); |
637 |
if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) { |
629 |
if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) { |
638 |
error = ECONNABORTED; |
630 |
error = ECONNABORTED; |
Lines 652-658
tcp_usr_accept(struct socket *so, struct sockaddr **nam)
Link Here
|
652 |
out: |
644 |
out: |
653 |
TCPDEBUG2(PRU_ACCEPT); |
645 |
TCPDEBUG2(PRU_ACCEPT); |
654 |
INP_WUNLOCK(inp); |
646 |
INP_WUNLOCK(inp); |
655 |
INP_INFO_RUNLOCK(&V_tcbinfo); |
|
|
656 |
if (error == 0) |
647 |
if (error == 0) |
657 |
*nam = in_sockaddr(port, &addr); |
648 |
*nam = in_sockaddr(port, &addr); |
658 |
return error; |
649 |
return error; |