Break out in_pcbdetach() into two functions:
- in_pcbdetach(), which removes the link between an inpcb and its socket. - in_pcbfree(), which frees a detached pcb. Unlike the previous in_pcbdetach(), neither of these functions will attempt to conditionally free the socket, as they are responsible only for managing in_pcb memory. Mirror these changes into in6_pcbdetach() by breaking it into in6_pcbdetach() and in6_pcbfree(). While here, eliminate undesired checks for NULL inpcb pointers in sockets, as we will now have as an invariant that sockets will always have valid so_pcb pointers. MFC after: 3 months
This commit is contained in:
parent
0154484bef
commit
4c7c478d0f
@ -676,16 +676,30 @@ in_pcbdisconnect(struct inpcb *inp)
|
||||
#ifdef IPSEC
|
||||
ipsec_pcbdisconn(inp->inp_sp);
|
||||
#endif
|
||||
if (inp->inp_socket->so_state & SS_NOFDREF)
|
||||
in_pcbdetach(inp);
|
||||
}
|
||||
|
||||
/*
|
||||
* In the old world order, in_pcbdetach() served two functions: to detach the
|
||||
* pcb from the socket/potentially free the socket, and to free the pcb
|
||||
* itself. In the new world order, the protocol code is responsible for
|
||||
* managing the relationship with the socket, and this code simply frees the
|
||||
* pcb.
|
||||
*/
|
||||
void
|
||||
in_pcbdetach(struct inpcb *inp)
|
||||
{
|
||||
struct socket *so = inp->inp_socket;
|
||||
|
||||
KASSERT(inp->inp_socket != NULL, ("in_pcbdetach: inp_socket == NULL"));
|
||||
inp->inp_socket->so_pcb = NULL;
|
||||
inp->inp_socket = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
in_pcbfree(struct inpcb *inp)
|
||||
{
|
||||
struct inpcbinfo *ipi = inp->inp_pcbinfo;
|
||||
|
||||
KASSERT(inp->inp_socket == NULL, ("in_pcbfree: inp_socket != NULL"));
|
||||
INP_INFO_WLOCK_ASSERT(ipi);
|
||||
INP_LOCK_ASSERT(inp);
|
||||
|
||||
@ -694,12 +708,6 @@ in_pcbdetach(struct inpcb *inp)
|
||||
#endif /*IPSEC*/
|
||||
inp->inp_gencnt = ++ipi->ipi_gencnt;
|
||||
in_pcbremlists(inp);
|
||||
if (so) {
|
||||
ACCEPT_LOCK();
|
||||
SOCK_LOCK(so);
|
||||
so->so_pcb = NULL;
|
||||
sotryfree(so);
|
||||
}
|
||||
if (inp->inp_options)
|
||||
(void)m_free(inp->inp_options);
|
||||
ip_freemoptions(inp->inp_moptions);
|
||||
@ -744,10 +752,7 @@ in_setsockaddr(struct socket *so, struct sockaddr **nam,
|
||||
|
||||
INP_INFO_RLOCK(pcbinfo);
|
||||
inp = sotoinpcb(so);
|
||||
if (!inp) {
|
||||
INP_INFO_RUNLOCK(pcbinfo);
|
||||
return ECONNRESET;
|
||||
}
|
||||
KASSERT(inp != NULL, ("in_setsockaddr: so_pcb == NULL"));
|
||||
INP_LOCK(inp);
|
||||
port = inp->inp_lport;
|
||||
addr = inp->inp_laddr;
|
||||
@ -771,10 +776,7 @@ in_setpeeraddr(struct socket *so, struct sockaddr **nam,
|
||||
|
||||
INP_INFO_RLOCK(pcbinfo);
|
||||
inp = sotoinpcb(so);
|
||||
if (!inp) {
|
||||
INP_INFO_RUNLOCK(pcbinfo);
|
||||
return ECONNRESET;
|
||||
}
|
||||
KASSERT(inp != NULL, ("in_setpeeraddr: so_pcb == NULL"));
|
||||
INP_LOCK(inp);
|
||||
port = inp->inp_fport;
|
||||
addr = inp->inp_faddr;
|
||||
@ -1169,7 +1171,8 @@ in_pcbsosetlabel(struct socket *so)
|
||||
#ifdef MAC
|
||||
struct inpcb *inp;
|
||||
|
||||
inp = (struct inpcb *)so->so_pcb;
|
||||
inp = sotoinpcb(so);
|
||||
KASSERT(inp != NULL, ("in_pcbsosetlabel: so->so_pcb == NULL"));
|
||||
INP_LOCK(inp);
|
||||
SOCK_LOCK(so);
|
||||
mac_inpcb_sosetlabel(so, inp);
|
||||
|
@ -352,6 +352,7 @@ int in_pcbconnect_setup(struct inpcb *, struct sockaddr *, in_addr_t *,
|
||||
struct ucred *);
|
||||
void in_pcbdetach(struct inpcb *);
|
||||
void in_pcbdisconnect(struct inpcb *);
|
||||
void in_pcbfree(struct inpcb *);
|
||||
int in_pcbinshash(struct inpcb *);
|
||||
struct inpcb *
|
||||
in_pcblookup_local(struct inpcbinfo *,
|
||||
|
@ -422,17 +422,23 @@ in6_pcbdisconnect(inp)
|
||||
#ifdef IPSEC
|
||||
ipsec_pcbdisconn(inp->inp_sp);
|
||||
#endif
|
||||
if (inp->inp_socket->so_state & SS_NOFDREF)
|
||||
in6_pcbdetach(inp);
|
||||
}
|
||||
|
||||
void
|
||||
in6_pcbdetach(inp)
|
||||
struct inpcb *inp;
|
||||
in6_pcbdetach(struct inpcb *inp)
|
||||
{
|
||||
|
||||
KASSERT(inp->inp_socket != NULL, ("in6_pcbdetach: inp_socket == NULL"));
|
||||
inp->inp_socket->so_pcb = NULL;
|
||||
inp->inp_socket = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
in6_pcbfree(struct inpcb *inp)
|
||||
{
|
||||
struct socket *so = inp->inp_socket;
|
||||
struct inpcbinfo *ipi = inp->inp_pcbinfo;
|
||||
|
||||
KASSERT(inp->inp_socket == NULL, ("in6_pcbfree: inp_socket != NULL"));
|
||||
INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
|
||||
INP_LOCK_ASSERT(inp);
|
||||
|
||||
@ -442,14 +448,6 @@ in6_pcbdetach(inp)
|
||||
#endif /* IPSEC */
|
||||
inp->inp_gencnt = ++ipi->ipi_gencnt;
|
||||
in_pcbremlists(inp);
|
||||
|
||||
if (so) {
|
||||
ACCEPT_LOCK();
|
||||
SOCK_LOCK(so);
|
||||
so->so_pcb = NULL;
|
||||
sotryfree(so);
|
||||
}
|
||||
|
||||
ip6_freepcbopts(inp->in6p_outputopts);
|
||||
ip6_freemoptions(inp->in6p_moptions);
|
||||
/* Check and free IPv4 related resources in case of mapped addr */
|
||||
|
@ -76,6 +76,7 @@ int in6_pcbbind __P((struct inpcb *, struct sockaddr *, struct ucred *));
|
||||
int in6_pcbconnect __P((struct inpcb *, struct sockaddr *, struct ucred *));
|
||||
void in6_pcbdetach __P((struct inpcb *));
|
||||
void in6_pcbdisconnect __P((struct inpcb *));
|
||||
void in6_pcbfree __P((struct inpcb *));
|
||||
int in6_pcbladdr __P((struct inpcb *, struct sockaddr *,
|
||||
struct in6_addr **));
|
||||
struct inpcb *
|
||||
|
Loading…
x
Reference in New Issue
Block a user