Change so_pcb invariants in netnatm, such that netnatm sockets always have

pcb's allocated:

- Universally ensure (and assert) that so_pcb is not NULL, removing lots
  of checks and error cases.  Don't free the pcb without clearing the
  so_pcb pointer.

- Don't try to free the socket in pru_detach(), since the caller will
  immediately free the socket.

- Do retain the sotryfree() in pru_abort() for now, although eventually
  the caller will do it unconditionally.
This commit is contained in:
Robert Watson 2006-03-17 18:25:57 +00:00
parent fad8387468
commit 23801379f0

View File

@ -2,7 +2,7 @@
/*-
*
* Copyright (c) 1996 Charles D. Cranor and Washington University.
* Copyright (c) 2005 Robert N. M. Watson
* Copyright (c) 2005-2006 Robert N. M. Watson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -94,7 +94,6 @@ natm_usr_attach(struct socket *so, int proto, d_thread_t *p)
int error = 0;
npcb = (struct natmpcb *)so->so_pcb;
KASSERT(npcb == NULL, ("natm_usr_attach: so_pcb != NULL"));
if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
@ -116,27 +115,14 @@ static int
natm_usr_detach(struct socket *so)
{
struct natmpcb *npcb;
int error = 0;
NATM_LOCK();
npcb = (struct natmpcb *)so->so_pcb;
if (npcb == NULL) {
/* XXXRW: Does this case ever actually happen? */
error = EINVAL;
goto out;
}
/*
* we turn on 'drain' *before* we sofree.
*/
KASSERT(npcb != NULL, ("natm_usr_detach: npcb == NULL"));
npcb_free(npcb, NPCB_DESTROY); /* drain */
ACCEPT_LOCK();
SOCK_LOCK(so);
so->so_pcb = NULL;
sotryfree(so);
out:
NATM_UNLOCK();
return (error);
return (0);
}
static int
@ -151,11 +137,7 @@ natm_usr_connect(struct socket *so, struct sockaddr *nam, d_thread_t *p)
NATM_LOCK();
npcb = (struct natmpcb *)so->so_pcb;
if (npcb == NULL) {
/* XXXRW: Does this case ever actually happen? */
error = EINVAL;
goto out;
}
KASSERT(npcb != NULL, ("natm_usr_connect: npcb == NULL"));
/*
* validate nam and npcb
@ -212,18 +194,14 @@ natm_usr_connect(struct socket *so, struct sockaddr *nam, d_thread_t *p)
if (ifp->if_ioctl == NULL ||
ifp->if_ioctl(ifp, SIOCATMOPENVCC, (caddr_t)&op) != 0) {
IFF_UNLOCKGIANT(ifp);
NATM_LOCK();
npcb_free(npcb, NPCB_REMOVE);
error = EIO;
goto out;
}
IFF_UNLOCKGIANT(ifp);
NATM_LOCK();
soisconnected(so);
out:
NATM_UNLOCK();
return (error);
}
@ -237,11 +215,7 @@ natm_usr_disconnect(struct socket *so)
NATM_LOCK();
npcb = (struct natmpcb *)so->so_pcb;
if (npcb == NULL) {
/* XXXRW: Does this case ever actually happen? */
error = EINVAL;
goto out;
}
KASSERT(npcb != NULL, ("natm_usr_disconnect: npcb == NULL"));
if ((npcb->npcb_flags & NPCB_CONNECTED) == 0) {
printf("natm: disconnected check\n");
@ -263,7 +237,6 @@ natm_usr_disconnect(struct socket *so)
}
NATM_LOCK();
npcb_free(npcb, NPCB_REMOVE);
soisdisconnected(so);
out:
@ -289,11 +262,7 @@ natm_usr_send(struct socket *so, int flags, struct mbuf *m,
NATM_LOCK();
npcb = (struct natmpcb *)so->so_pcb;
if (npcb == NULL) {
/* XXXRW: Does this case ever actually happen? */
error = EINVAL;
goto out;
}
KASSERT(npcb != NULL, ("natm_usr_send: npcb == NULL"));
if (control && control->m_len) {
m_freem(control);
@ -330,11 +299,7 @@ natm_usr_peeraddr(struct socket *so, struct sockaddr **nam)
NATM_LOCK();
npcb = (struct natmpcb *)so->so_pcb;
if (npcb == NULL) {
/* XXXRW: Does this case ever actually happen? */
NATM_UNLOCK();
return (EINVAL);
}
KASSERT(npcb != NULL, ("natm_usr_peeraddr: npcb == NULL"));
snatm = &ssnatm;
bzero(snatm, sizeof(*snatm));
@ -356,13 +321,8 @@ natm_usr_control(struct socket *so, u_long cmd, caddr_t arg,
struct natmpcb *npcb;
int error;
/*
* XXXRW: Does this case ever actually happen? And does it even matter
* given that npcb is unused?
*/
npcb = (struct natmpcb *)so->so_pcb;
if (npcb == NULL)
return (EINVAL);
KASSERT(npcb != NULL, ("natm_usr_control: npcb == NULL"));
if (ifp == NULL || ifp->if_ioctl == NULL)
return (EOPNOTSUPP);
@ -376,7 +336,11 @@ natm_usr_control(struct socket *so, u_long cmd, caddr_t arg,
static int
natm_usr_abort(struct socket *so)
{
return (natm_usr_shutdown(so));
natm_usr_shutdown(so);
ACCEPT_LOCK();
SOCK_LOCK(so);
sotryfree(so);
return (0);
}
static int