| 486 | } |
| 487 | |
| 488 | void |
| 489 | tcp_twclose(struct tcptw *tw, int reuse) |
| 490 | { |
| 491 | struct socket *so; |
| 492 | struct inpcb *inp; |
| 493 | |
| 494 | /* |
| 495 | * At this point, we are in one of two situations: |
| 496 | * |
| 497 | * (1) We have no socket, just an inpcb<->twtcp pair. We can free |
| 498 | * all state. |
| 499 | * |
| 500 | * (2) We have a socket -- if we own a reference, release it and |
| 501 | * notify the socket layer. |
| 502 | */ |
| 503 | inp = tw->tw_inpcb; |
| 504 | KASSERT((inp->inp_flags & INP_TIMEWAIT), ("tcp_twclose: !timewait")); |
| 505 | KASSERT(intotw(inp) == tw, ("tcp_twclose: inp_ppcb != tw")); |
| 506 | NET_EPOCH_ASSERT(); |
| 507 | INP_WLOCK_ASSERT(inp); |
| 508 | |
| 509 | tcp_tw_2msl_stop(tw, reuse); |
| 510 | inp->inp_ppcb = NULL; |
| 511 | in_pcbdrop(inp); |
| 512 | |
| 513 | so = inp->inp_socket; |
| 514 | if (so != NULL) { |
| 515 | /* |
| 516 | * If there's a socket, handle two cases: first, we own a |
| 517 | * strong reference, which we will now release, or we don't |
| 518 | * in which case another reference exists (XXXRW: think |
| 519 | * about this more), and we don't need to take action. |
| 520 | */ |
| 521 | if (inp->inp_flags & INP_SOCKREF) { |
| 522 | inp->inp_flags &= ~INP_SOCKREF; |
| 523 | INP_WUNLOCK(inp); |
| 524 | SOCK_LOCK(so); |
| 525 | KASSERT(so->so_state & SS_PROTOREF, |
| 526 | ("tcp_twclose: INP_SOCKREF && !SS_PROTOREF")); |
| 527 | so->so_state &= ~SS_PROTOREF; |
| 528 | sofree(so); |
| 529 | } else { |
| 530 | /* |
| 531 | * If we don't own the only reference, the socket and |
| 532 | * inpcb need to be left around to be handled by |
| 533 | * tcp_usr_detach() later. |
| 534 | */ |
| 535 | INP_WUNLOCK(inp); |
| 536 | } |
| 537 | } else { |
| 538 | /* |
| 539 | * The socket has been already cleaned-up for us, only free the |
| 540 | * inpcb. |
| 541 | */ |
| 542 | in_pcbfree(inp); |
| 543 | } |
| 544 | TCPSTAT_INC(tcps_closed); |
| 545 | } |
no test coverage detected