Procotol control block locking for netatalk DDP.
This commit is contained in:
parent
d0f3949724
commit
9183ed533a
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2004 Robert N. M. Watson
|
||||
* Copyright (c) 1990,1994 Regents of The University of Michigan.
|
||||
* All Rights Reserved. See COPYRIGHT.
|
||||
*
|
||||
@ -24,11 +25,13 @@
|
||||
#include <netatalk/at_var.h>
|
||||
#include <netatalk/ddp.h>
|
||||
#include <netatalk/ddp_var.h>
|
||||
#include <netatalk/ddp_pcb.h>
|
||||
#include <netatalk/at_extern.h>
|
||||
|
||||
static volatile int ddp_forward = 1;
|
||||
static volatile int ddp_firewall = 0;
|
||||
static struct ddpstat ddpstat;
|
||||
|
||||
static struct route forwro;
|
||||
|
||||
static void ddp_input(struct mbuf *, struct ifnet *, struct elaphdr *, int);
|
||||
@ -360,17 +363,16 @@ ddp_input(m, ifp, elh, phase)
|
||||
* Search for ddp protocol control blocks that match these
|
||||
* addresses.
|
||||
*/
|
||||
DDP_LIST_SLOCK();
|
||||
if ((ddp = ddp_search(&from, &to, aa)) == NULL) {
|
||||
m_freem(m);
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef MAC
|
||||
SOCK_LOCK(ddp->ddp_socket);
|
||||
if (mac_check_socket_deliver(ddp->ddp_socket, m) != 0) {
|
||||
SOCK_UNLOCK(ddp->ddp_socket);
|
||||
m_freem(m);
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
SOCK_UNLOCK(ddp->ddp_socket);
|
||||
#endif
|
||||
@ -384,13 +386,17 @@ ddp_input(m, ifp, elh, phase)
|
||||
* If the socket is full (or similar error) dump the packet.
|
||||
*/
|
||||
ddpstat.ddps_nosockspace++;
|
||||
m_freem(m);
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
* And wake up whatever might be waiting for it
|
||||
*/
|
||||
sorwakeup(ddp->ddp_socket);
|
||||
m = NULL;
|
||||
out:
|
||||
DDP_LIST_SUNLOCK();
|
||||
if (m != NULL)
|
||||
m_freem(m);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2004 Robert N. M. Watson
|
||||
* Copyright (c) 1990,1994 Regents of The University of Michigan.
|
||||
* All Rights Reserved. See COPYRIGHT.
|
||||
*
|
||||
@ -22,12 +23,18 @@
|
||||
#include <netatalk/ddp_pcb.h>
|
||||
#include <netatalk/at_extern.h>
|
||||
|
||||
struct mtx ddp_list_mtx;
|
||||
static struct ddpcb *ddp_ports[ ATPORT_LAST ];
|
||||
struct ddpcb *ddpcb_list = NULL;
|
||||
struct ddpcb *ddpcb_list = NULL;
|
||||
|
||||
void
|
||||
at_sockaddr(struct ddpcb *ddp, struct sockaddr **addr)
|
||||
{
|
||||
|
||||
/*
|
||||
* Prevent modification of ddp during copy of addr.
|
||||
*/
|
||||
DDP_LOCK_ASSERT(ddp);
|
||||
*addr = sodupsockaddr((struct sockaddr *)&ddp->ddp_lsat, M_NOWAIT);
|
||||
}
|
||||
|
||||
@ -38,6 +45,12 @@ at_pcbsetaddr(struct ddpcb *ddp, struct sockaddr *addr, struct thread *td)
|
||||
struct at_ifaddr *aa;
|
||||
struct ddpcb *ddpp;
|
||||
|
||||
/*
|
||||
* We read and write both the ddp passed in, and also ddp_ports.
|
||||
*/
|
||||
DDP_LIST_XLOCK_ASSERT();
|
||||
DDP_LOCK_ASSERT(ddp);
|
||||
|
||||
if (ddp->ddp_lsat.sat_port != ATADDR_ANYPORT) { /* shouldn't be bound */
|
||||
return (EINVAL);
|
||||
}
|
||||
@ -134,6 +147,9 @@ at_pcbconnect(struct ddpcb *ddp, struct sockaddr *addr, struct thread *td)
|
||||
struct ifnet *ifp;
|
||||
u_short hintnet = 0, net;
|
||||
|
||||
DDP_LIST_XLOCK_ASSERT();
|
||||
DDP_LOCK_ASSERT(ddp);
|
||||
|
||||
if (sat->sat_family != AF_APPLETALK) {
|
||||
return (EAFNOSUPPORT);
|
||||
}
|
||||
@ -222,6 +238,9 @@ at_pcbconnect(struct ddpcb *ddp, struct sockaddr *addr, struct thread *td)
|
||||
void
|
||||
at_pcbdisconnect(struct ddpcb *ddp)
|
||||
{
|
||||
|
||||
DDP_LOCK_ASSERT(ddp);
|
||||
|
||||
ddp->ddp_fsat.sat_addr.s_net = ATADDR_ANYNET;
|
||||
ddp->ddp_fsat.sat_addr.s_node = ATADDR_ANYNODE;
|
||||
ddp->ddp_fsat.sat_port = ATADDR_ANYPORT;
|
||||
@ -232,9 +251,15 @@ at_pcballoc(struct socket *so)
|
||||
{
|
||||
struct ddpcb *ddp;
|
||||
|
||||
MALLOC(ddp, struct ddpcb *, sizeof *ddp, M_PCB, M_WAITOK | M_ZERO);
|
||||
DDP_LIST_XLOCK_ASSERT();
|
||||
|
||||
MALLOC(ddp, struct ddpcb *, sizeof *ddp, M_PCB, M_NOWAIT | M_ZERO);
|
||||
DDP_LOCK_INIT(ddp);
|
||||
ddp->ddp_lsat.sat_port = ATADDR_ANYPORT;
|
||||
|
||||
ddp->ddp_socket = so;
|
||||
so->so_pcb = (caddr_t)ddp;
|
||||
|
||||
ddp->ddp_next = ddpcb_list;
|
||||
ddp->ddp_prev = NULL;
|
||||
ddp->ddp_pprev = NULL;
|
||||
@ -243,15 +268,19 @@ at_pcballoc(struct socket *so)
|
||||
ddpcb_list->ddp_prev = ddp;
|
||||
}
|
||||
ddpcb_list = ddp;
|
||||
|
||||
ddp->ddp_socket = so;
|
||||
so->so_pcb = (caddr_t)ddp;
|
||||
return (0);
|
||||
return(0);
|
||||
}
|
||||
|
||||
void
|
||||
at_pcbdetach(struct socket *so, struct ddpcb *ddp)
|
||||
{
|
||||
|
||||
/*
|
||||
* We modify ddp, ddp_ports, and the global list.
|
||||
*/
|
||||
DDP_LIST_XLOCK_ASSERT();
|
||||
DDP_LOCK_ASSERT(ddp);
|
||||
|
||||
soisdisconnected(so);
|
||||
SOCK_LOCK(so);
|
||||
so->so_pcb = NULL;
|
||||
@ -282,6 +311,8 @@ at_pcbdetach(struct socket *so, struct ddpcb *ddp)
|
||||
if (ddp->ddp_next) {
|
||||
ddp->ddp_next->ddp_prev = ddp->ddp_prev;
|
||||
}
|
||||
DDP_UNLOCK(ddp);
|
||||
DDP_LOCK_DESTROY(ddp);
|
||||
FREE(ddp, M_PCB);
|
||||
}
|
||||
|
||||
@ -297,6 +328,8 @@ ddp_search(struct sockaddr_at *from, struct sockaddr_at *to,
|
||||
{
|
||||
struct ddpcb *ddp;
|
||||
|
||||
DDP_LIST_SLOCK_ASSERT();
|
||||
|
||||
/*
|
||||
* Check for bad ports.
|
||||
*/
|
||||
@ -309,11 +342,13 @@ ddp_search(struct sockaddr_at *from, struct sockaddr_at *to,
|
||||
* the interface?
|
||||
*/
|
||||
for (ddp = ddp_ports[ to->sat_port - 1 ]; ddp; ddp = ddp->ddp_pnext) {
|
||||
DDP_LOCK(ddp);
|
||||
/* XXX should we handle 0.YY? */
|
||||
|
||||
/* XXXX.YY to socket on destination interface */
|
||||
if (to->sat_addr.s_net == ddp->ddp_lsat.sat_addr.s_net &&
|
||||
to->sat_addr.s_node == ddp->ddp_lsat.sat_addr.s_node) {
|
||||
DDP_UNLOCK(ddp);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -321,6 +356,7 @@ ddp_search(struct sockaddr_at *from, struct sockaddr_at *to,
|
||||
if (to->sat_addr.s_node == ATADDR_BCAST && (to->sat_addr.s_net == 0 ||
|
||||
to->sat_addr.s_net == ddp->ddp_lsat.sat_addr.s_net) &&
|
||||
ddp->ddp_lsat.sat_addr.s_net == AA_SAT(aa)->sat_addr.s_net) {
|
||||
DDP_UNLOCK(ddp);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -331,8 +367,10 @@ ddp_search(struct sockaddr_at *from, struct sockaddr_at *to,
|
||||
ntohs(aa->aa_firstnet) &&
|
||||
ntohs(ddp->ddp_lsat.sat_addr.s_net) <=
|
||||
ntohs(aa->aa_lastnet)) {
|
||||
DDP_UNLOCK(ddp);
|
||||
break;
|
||||
}
|
||||
DDP_UNLOCK(ddp);
|
||||
}
|
||||
return (ddp);
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2004 Robert N. M. Watson
|
||||
* Copyright (c) 1990,1994 Regents of The University of Michigan.
|
||||
* All Rights Reserved. See COPYRIGHT.
|
||||
*
|
||||
@ -17,4 +18,23 @@ int at_pcbsetaddr(struct ddpcb *ddp, struct sockaddr *addr,
|
||||
struct thread *td);
|
||||
void at_sockaddr(struct ddpcb *ddp, struct sockaddr **addr);
|
||||
|
||||
/* Lock macros for per-pcb locks. */
|
||||
#define DDP_LOCK_INIT(ddp) mtx_init(&(ddp)->ddp_mtx, "ddp_mtx", \
|
||||
NULL, MTX_DEF)
|
||||
#define DDP_LOCK_DESTROY(ddp) mtx_destroy(&(ddp)->ddp_mtx)
|
||||
#define DDP_LOCK(ddp) mtx_lock(&(ddp)->ddp_mtx)
|
||||
#define DDP_UNLOCK(ddp) mtx_unlock(&(ddp)->ddp_mtx)
|
||||
#define DDP_LOCK_ASSERT(ddp) mtx_assert(&(ddp)->ddp_mtx, MA_OWNED)
|
||||
|
||||
/* Lock macros for global pcb list lock. */
|
||||
#define DDP_LIST_LOCK_INIT() mtx_init(&ddp_list_mtx, "ddp_list_mtx", \
|
||||
NULL, MTX_DEF)
|
||||
#define DDP_LIST_LOCK_DESTROY() mtx_destroy(&ddp_list_mtx)
|
||||
#define DDP_LIST_XLOCK() mtx_lock(&ddp_list_mtx)
|
||||
#define DDP_LIST_XUNLOCK() mtx_unlock(&ddp_list_mtx)
|
||||
#define DDP_LIST_XLOCK_ASSERT() mtx_assert(&ddp_list_mtx, MA_OWNED)
|
||||
#define DDP_LIST_SLOCK() mtx_lock(&ddp_list_mtx)
|
||||
#define DDP_LIST_SUNLOCK() mtx_unlock(&ddp_list_mtx)
|
||||
#define DDP_LIST_SLOCK_ASSERT() mtx_assert(&ddp_list_mtx, MA_OWNED)
|
||||
|
||||
#endif
|
||||
|
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2004 Robert N. M. Watson
|
||||
* Copyright (c) 1990,1994 Regents of The University of Michigan.
|
||||
* All Rights Reserved. See COPYRIGHT.
|
||||
*
|
||||
@ -33,17 +34,22 @@ ddp_attach(struct socket *so, int proto, struct thread *td)
|
||||
struct ddpcb *ddp;
|
||||
int error = 0;
|
||||
|
||||
|
||||
ddp = sotoddpcb(so);
|
||||
if (ddp != NULL) {
|
||||
return (EINVAL);
|
||||
}
|
||||
if (ddp != NULL)
|
||||
return (EINVAL);
|
||||
|
||||
/*
|
||||
* Allocate socket buffer space first so that it's present
|
||||
* before first use.
|
||||
*/
|
||||
error = soreserve(so, ddp_sendspace, ddp_recvspace);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
DDP_LIST_XLOCK();
|
||||
error = at_pcballoc(so);
|
||||
if (error) {
|
||||
return (error);
|
||||
}
|
||||
return (soreserve(so, ddp_sendspace, ddp_recvspace));
|
||||
DDP_LIST_XUNLOCK();
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -52,10 +58,13 @@ ddp_detach(struct socket *so)
|
||||
struct ddpcb *ddp;
|
||||
|
||||
ddp = sotoddpcb(so);
|
||||
if (ddp == NULL) {
|
||||
if (ddp == NULL)
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
DDP_LIST_XLOCK();
|
||||
DDP_LOCK(ddp);
|
||||
at_pcbdetach(so, ddp);
|
||||
DDP_LIST_XUNLOCK();
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -69,7 +78,11 @@ ddp_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
|
||||
if (ddp == NULL) {
|
||||
return (EINVAL);
|
||||
}
|
||||
DDP_LIST_XLOCK();
|
||||
DDP_LOCK(ddp);
|
||||
error = at_pcbsetaddr(ddp, nam, td);
|
||||
DDP_UNLOCK(ddp);
|
||||
DDP_LIST_XUNLOCK();
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -84,11 +97,17 @@ ddp_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
DDP_LIST_XLOCK();
|
||||
DDP_LOCK(ddp);
|
||||
if (ddp->ddp_fsat.sat_port != ATADDR_ANYPORT) {
|
||||
DDP_UNLOCK(ddp);
|
||||
DDP_LIST_XUNLOCK();
|
||||
return (EISCONN);
|
||||
}
|
||||
|
||||
error = at_pcbconnect(ddp, nam, td);
|
||||
error = at_pcbconnect( ddp, nam, td );
|
||||
DDP_UNLOCK(ddp);
|
||||
DDP_LIST_XUNLOCK();
|
||||
if (error == 0)
|
||||
soisconnected(so);
|
||||
return (error);
|
||||
@ -104,12 +123,15 @@ ddp_disconnect(struct socket *so)
|
||||
if (ddp == NULL) {
|
||||
return (EINVAL);
|
||||
}
|
||||
DDP_LOCK(ddp);
|
||||
if (ddp->ddp_fsat.sat_addr.s_node == ATADDR_ANYNODE) {
|
||||
DDP_UNLOCK(ddp);
|
||||
return (ENOTCONN);
|
||||
}
|
||||
|
||||
at_pcbdisconnect(ddp);
|
||||
ddp->ddp_fsat.sat_addr.s_node = ATADDR_ANYNODE;
|
||||
DDP_UNLOCK(ddp);
|
||||
soisdisconnected(so);
|
||||
return (0);
|
||||
}
|
||||
@ -144,23 +166,28 @@ ddp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
|
||||
}
|
||||
|
||||
if (addr != NULL) {
|
||||
DDP_LIST_XLOCK();
|
||||
DDP_LOCK(ddp);
|
||||
if (ddp->ddp_fsat.sat_port != ATADDR_ANYPORT) {
|
||||
return (EISCONN);
|
||||
error = EISCONN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
error = at_pcbconnect(ddp, addr, td);
|
||||
if (error) {
|
||||
return (error);
|
||||
if (error == 0) {
|
||||
error = ddp_output(m, so);
|
||||
at_pcbdisconnect(ddp);
|
||||
}
|
||||
out:
|
||||
DDP_UNLOCK(ddp);
|
||||
DDP_LIST_XUNLOCK();
|
||||
} else {
|
||||
if (ddp->ddp_fsat.sat_port == ATADDR_ANYPORT) {
|
||||
return (ENOTCONN);
|
||||
}
|
||||
}
|
||||
|
||||
error = ddp_output(m, so);
|
||||
if (addr != NULL) {
|
||||
at_pcbdisconnect(ddp);
|
||||
DDP_LOCK(ddp);
|
||||
if (ddp->ddp_fsat.sat_port == ATADDR_ANYPORT)
|
||||
error = ENOTCONN;
|
||||
else
|
||||
error = ddp_output(m, so);
|
||||
DDP_UNLOCK(ddp);
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
@ -174,20 +201,23 @@ ddp_abort(struct socket *so)
|
||||
if (ddp == NULL) {
|
||||
return (EINVAL);
|
||||
}
|
||||
DDP_LIST_XLOCK();
|
||||
DDP_LOCK(ddp);
|
||||
at_pcbdetach(so, ddp);
|
||||
DDP_LIST_XUNLOCK();
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
ddp_init(void)
|
||||
{
|
||||
|
||||
atintrq1.ifq_maxlen = IFQ_MAXLEN;
|
||||
atintrq2.ifq_maxlen = IFQ_MAXLEN;
|
||||
aarpintrq.ifq_maxlen = IFQ_MAXLEN;
|
||||
mtx_init(&atintrq1.ifq_mtx, "at1_inq", NULL, MTX_DEF);
|
||||
mtx_init(&atintrq2.ifq_mtx, "at2_inq", NULL, MTX_DEF);
|
||||
mtx_init(&aarpintrq.ifq_mtx, "aarp_inq", NULL, MTX_DEF);
|
||||
DDP_LIST_LOCK_INIT();
|
||||
netisr_register(NETISR_ATALK1, at1intr, &atintrq1, 0);
|
||||
netisr_register(NETISR_ATALK2, at2intr, &atintrq2, 0);
|
||||
netisr_register(NETISR_AARP, aarpintr, &aarpintrq, 0);
|
||||
@ -202,6 +232,7 @@ ddp_clean(void)
|
||||
for (ddp = ddpcb_list; ddp != NULL; ddp = ddp->ddp_next) {
|
||||
at_pcbdetach(ddp->ddp_socket, ddp);
|
||||
}
|
||||
DDP_LIST_LOCK_DESTROY();
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -220,7 +251,9 @@ at_setsockaddr(struct socket *so, struct sockaddr **nam)
|
||||
if (ddp == NULL) {
|
||||
return (EINVAL);
|
||||
}
|
||||
DDP_LOCK(ddp);
|
||||
at_sockaddr(ddp, nam);
|
||||
DDP_UNLOCK(ddp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@ struct ddpcb {
|
||||
struct socket *ddp_socket;
|
||||
struct ddpcb *ddp_prev, *ddp_next;
|
||||
struct ddpcb *ddp_pprev, *ddp_pnext;
|
||||
struct mtx ddp_mtx;
|
||||
};
|
||||
|
||||
#define sotoddpcb(so) ((struct ddpcb *)(so)->so_pcb)
|
||||
@ -34,5 +35,6 @@ struct ddpstat {
|
||||
extern int ddp_cksum;
|
||||
extern struct ddpcb *ddpcb_list;
|
||||
extern struct pr_usrreqs ddp_usrreqs;
|
||||
extern struct mtx ddp_list_mtx;
|
||||
#endif
|
||||
#endif /* _NETATALK_DDP_VAR_H_ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user