2005-01-07 01:45:51 +00:00
|
|
|
/*-
|
2007-01-08 22:30:39 +00:00
|
|
|
* Copyright (c) 2005-2006 Robert N. M. Watson
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
1997-05-09 08:04:59 +00:00
|
|
|
*
|
|
|
|
* Copyright (c) 1996 Charles D. Cranor and Washington University.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
|
|
* must display the following acknowledgement:
|
|
|
|
* This product includes software developed by Charles D. Cranor and
|
|
|
|
* Washington University.
|
|
|
|
* 4. The name of the author may not be used to endorse or promote products
|
|
|
|
* derived from this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
2007-01-08 22:30:39 +00:00
|
|
|
*
|
|
|
|
* $NetBSD: natm.c,v 1.5 1996/11/09 03:26:26 chuck Exp $
|
1997-05-09 08:04:59 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2006-04-23 16:33:56 +00:00
|
|
|
* natm.c: Native mode ATM access (both aal0 and aal5).
|
1997-05-09 08:04:59 +00:00
|
|
|
*/
|
|
|
|
|
2003-06-11 05:37:42 +00:00
|
|
|
#include <sys/cdefs.h>
|
|
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
|
1997-05-09 08:04:59 +00:00
|
|
|
#include <sys/param.h>
|
2002-04-30 01:54:54 +00:00
|
|
|
#include <sys/conf.h>
|
1997-05-09 08:04:59 +00:00
|
|
|
#include <sys/kernel.h>
|
2002-04-30 01:54:54 +00:00
|
|
|
#include <sys/lock.h>
|
1997-09-02 01:19:47 +00:00
|
|
|
#include <sys/malloc.h>
|
1997-05-09 08:04:59 +00:00
|
|
|
#include <sys/mbuf.h>
|
2002-04-30 01:54:54 +00:00
|
|
|
#include <sys/protosw.h>
|
|
|
|
#include <sys/signalvar.h>
|
1997-05-09 08:04:59 +00:00
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/socketvar.h>
|
2002-04-30 01:54:54 +00:00
|
|
|
#include <sys/sockio.h>
|
|
|
|
#include <sys/sx.h>
|
|
|
|
#include <sys/systm.h>
|
2003-08-06 13:46:15 +00:00
|
|
|
#include <sys/sysctl.h>
|
1997-05-09 08:04:59 +00:00
|
|
|
|
|
|
|
#include <net/if.h>
|
|
|
|
#include <net/if_atm.h>
|
|
|
|
#include <net/netisr.h>
|
|
|
|
|
|
|
|
#include <netinet/in.h>
|
|
|
|
|
|
|
|
#include <netnatm/natm.h>
|
|
|
|
|
2006-04-23 16:33:56 +00:00
|
|
|
static const u_long natm5_sendspace = 16*1024;
|
|
|
|
static const u_long natm5_recvspace = 16*1024;
|
1997-05-09 08:04:59 +00:00
|
|
|
|
2006-04-23 16:33:56 +00:00
|
|
|
static const u_long natm0_sendspace = 16*1024;
|
|
|
|
static const u_long natm0_recvspace = 16*1024;
|
1997-05-09 08:04:59 +00:00
|
|
|
|
2006-04-23 16:33:56 +00:00
|
|
|
/*
|
|
|
|
* netnatm global subsystem lock, protects all global data structures in
|
|
|
|
* netnatm.
|
|
|
|
*/
|
|
|
|
struct mtx natm_mtx;
|
Lock down netnatm and mark as MPSAFE:
- Introduce a subsystem mutex, natm_mtx, manipulated with accessor macros
NATM_LOCK_INIT(), NATM_LOCK(), NATM_UNLOCK(), NATM_LOCK_ASSERT(). It
protects the consistency of pcb-related data structures. Finer grained
locking is possible, but should be done in the context of specific
measurements (as very little work is done in netnatm -- most is in the
ATM device driver or socket layer, so there's probably not much
contention).
- Remove GIANT_REQUIRED, mark as NETISR_MPSAFE, remove
NET_NEEDS_GIANT("netnatm").
- Conditionally acquire Giant when entering network interfaces for
ifp->if_ioctl() using IFF_LOCKGIANT(ifp)/IFF_UNLOCKGIANT(ifp) in order
to coexist with non-MPSAFE atm ifnet drivers..
- De-spl.
MFC after: 2 weeks
Reviewed by: harti, bms (various versions)
2005-07-18 16:55:46 +00:00
|
|
|
|
1997-05-09 08:04:59 +00:00
|
|
|
/*
|
2006-04-23 16:33:56 +00:00
|
|
|
* User socket requests.
|
1997-05-09 08:04:59 +00:00
|
|
|
*/
|
2009-05-20 17:00:16 +00:00
|
|
|
static int natm_usr_attach(struct socket *, int, struct thread *);
|
2006-04-23 16:33:56 +00:00
|
|
|
static void natm_usr_detach(struct socket *);
|
|
|
|
static int natm_usr_connect(struct socket *, struct sockaddr *,
|
2009-05-20 17:00:16 +00:00
|
|
|
struct thread *);
|
2006-04-23 16:33:56 +00:00
|
|
|
static int natm_usr_disconnect(struct socket *);
|
|
|
|
static int natm_usr_shutdown(struct socket *);
|
|
|
|
static int natm_usr_send(struct socket *, int, struct mbuf *,
|
2009-05-20 17:00:16 +00:00
|
|
|
struct sockaddr *, struct mbuf *, struct thread *);
|
2006-04-23 16:33:56 +00:00
|
|
|
static int natm_usr_peeraddr(struct socket *, struct sockaddr **);
|
|
|
|
static int natm_usr_control(struct socket *, u_long, caddr_t,
|
2009-05-20 17:00:16 +00:00
|
|
|
struct ifnet *, struct thread *);
|
2006-04-23 16:33:56 +00:00
|
|
|
static void natm_usr_abort(struct socket *);
|
|
|
|
static int natm_usr_bind(struct socket *, struct sockaddr *,
|
2009-05-20 17:00:16 +00:00
|
|
|
struct thread *);
|
2006-04-23 16:33:56 +00:00
|
|
|
static int natm_usr_sockaddr(struct socket *, struct sockaddr **);
|
1997-05-09 08:04:59 +00:00
|
|
|
|
|
|
|
static int
|
2009-05-20 17:00:16 +00:00
|
|
|
natm_usr_attach(struct socket *so, int proto, struct thread *p)
|
1997-05-09 08:04:59 +00:00
|
|
|
{
|
2006-04-23 16:33:56 +00:00
|
|
|
struct natmpcb *npcb;
|
|
|
|
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) {
|
|
|
|
if (proto == PROTO_NATMAAL5)
|
|
|
|
error = soreserve(so, natm5_sendspace,
|
|
|
|
natm5_recvspace);
|
|
|
|
else
|
|
|
|
error = soreserve(so, natm0_sendspace,
|
|
|
|
natm0_recvspace);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
so->so_pcb = npcb = npcb_alloc(M_WAITOK);
|
|
|
|
npcb->npcb_socket = so;
|
|
|
|
return (error);
|
1997-05-09 08:04:59 +00:00
|
|
|
}
|
|
|
|
|
Chance protocol switch method pru_detach() so that it returns void
rather than an error. Detaches do not "fail", they other occur or
the protocol flags SS_PROTOREF to take ownership of the socket.
soclose() no longer looks at so_pcb to see if it's NULL, relying
entirely on the protocol to decide whether it's time to free the
socket or not using SS_PROTOREF. so_pcb is now entirely owned and
managed by the protocol code. Likewise, no longer test so_pcb in
other socket functions, such as soreceive(), which have no business
digging into protocol internals.
Protocol detach routines no longer try to free the socket on detach,
this is performed in the socket code if the protocol permits it.
In rts_detach(), no longer test for rp != NULL in detach, and
likewise in other protocols that don't permit a NULL so_pcb, reduce
the incidence of testing for it during detach.
netinet and netinet6 are not fully updated to this change, which
will be in an upcoming commit. In their current state they may leak
memory or panic.
MFC after: 3 months
2006-04-01 15:42:02 +00:00
|
|
|
static void
|
1997-05-09 08:04:59 +00:00
|
|
|
natm_usr_detach(struct socket *so)
|
|
|
|
{
|
2006-04-23 16:33:56 +00:00
|
|
|
struct natmpcb *npcb;
|
1997-05-09 08:04:59 +00:00
|
|
|
|
2006-04-23 16:33:56 +00:00
|
|
|
npcb = (struct natmpcb *)so->so_pcb;
|
|
|
|
KASSERT(npcb != NULL, ("natm_usr_detach: npcb == NULL"));
|
2006-04-23 16:04:07 +00:00
|
|
|
|
2006-04-23 16:33:56 +00:00
|
|
|
NATM_LOCK();
|
|
|
|
npcb_free(npcb, NPCB_DESTROY); /* drain */
|
|
|
|
so->so_pcb = NULL;
|
|
|
|
NATM_UNLOCK();
|
1997-05-09 08:04:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2009-05-20 17:00:16 +00:00
|
|
|
natm_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *p)
|
1997-05-09 08:04:59 +00:00
|
|
|
{
|
2006-04-23 16:33:56 +00:00
|
|
|
struct natmpcb *npcb;
|
|
|
|
struct sockaddr_natm *snatm;
|
|
|
|
struct atmio_openvcc op;
|
|
|
|
struct ifnet *ifp;
|
|
|
|
int error = 0;
|
|
|
|
int proto = so->so_proto->pr_protocol;
|
|
|
|
|
|
|
|
npcb = (struct natmpcb *)so->so_pcb;
|
|
|
|
KASSERT(npcb != NULL, ("natm_usr_connect: npcb == NULL"));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Validate nam and npcb.
|
|
|
|
*/
|
|
|
|
NATM_LOCK();
|
|
|
|
snatm = (struct sockaddr_natm *)nam;
|
|
|
|
if (snatm->snatm_len != sizeof(*snatm) ||
|
|
|
|
(npcb->npcb_flags & NPCB_FREE) == 0) {
|
|
|
|
NATM_UNLOCK();
|
|
|
|
return (EINVAL);
|
|
|
|
}
|
|
|
|
if (snatm->snatm_family != AF_NATM) {
|
|
|
|
NATM_UNLOCK();
|
|
|
|
return (EAFNOSUPPORT);
|
|
|
|
}
|
1997-05-09 08:04:59 +00:00
|
|
|
|
2006-04-23 16:33:56 +00:00
|
|
|
snatm->snatm_if[IFNAMSIZ - 1] = '\0'; /* XXX ensure null termination
|
2003-08-06 13:46:15 +00:00
|
|
|
since ifunit() uses strcmp */
|
1997-05-09 08:04:59 +00:00
|
|
|
|
2006-04-23 16:33:56 +00:00
|
|
|
/*
|
|
|
|
* Convert interface string to ifp, validate.
|
|
|
|
*/
|
|
|
|
ifp = ifunit(snatm->snatm_if);
|
|
|
|
if (ifp == NULL || (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
|
|
|
|
NATM_UNLOCK();
|
|
|
|
return (ENXIO);
|
|
|
|
}
|
|
|
|
if (ifp->if_output != atm_output) {
|
|
|
|
NATM_UNLOCK();
|
|
|
|
return (EAFNOSUPPORT);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Register us with the NATM PCB layer.
|
|
|
|
*/
|
|
|
|
if (npcb_add(npcb, ifp, snatm->snatm_vci, snatm->snatm_vpi) != npcb) {
|
|
|
|
NATM_UNLOCK();
|
|
|
|
return (EADDRINUSE);
|
|
|
|
}
|
1997-05-09 08:04:59 +00:00
|
|
|
|
2006-04-23 16:33:56 +00:00
|
|
|
/*
|
|
|
|
* Open the channel.
|
|
|
|
*
|
|
|
|
* XXXRW: Eventually desirable to hold mutex over ioctl?
|
|
|
|
*/
|
|
|
|
bzero(&op, sizeof(op));
|
|
|
|
op.rxhand = npcb;
|
|
|
|
op.param.flags = ATMIO_FLAG_PVC;
|
|
|
|
op.param.vpi = npcb->npcb_vpi;
|
|
|
|
op.param.vci = npcb->npcb_vci;
|
|
|
|
op.param.rmtu = op.param.tmtu = ifp->if_mtu;
|
|
|
|
op.param.aal = (proto == PROTO_NATMAAL5) ? ATMIO_AAL_5 : ATMIO_AAL_0;
|
|
|
|
op.param.traffic = ATMIO_TRAFFIC_UBR;
|
2006-04-23 16:25:30 +00:00
|
|
|
NATM_UNLOCK();
|
2006-04-23 16:33:56 +00:00
|
|
|
|
|
|
|
if (ifp->if_ioctl == NULL ||
|
2009-03-15 14:21:05 +00:00
|
|
|
ifp->if_ioctl(ifp, SIOCATMOPENVCC, (caddr_t)&op) != 0)
|
2006-04-23 16:33:56 +00:00
|
|
|
return (EIO);
|
|
|
|
soisconnected(so);
|
|
|
|
return (error);
|
1997-05-09 08:04:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
natm_usr_disconnect(struct socket *so)
|
|
|
|
{
|
2006-04-23 16:33:56 +00:00
|
|
|
struct natmpcb *npcb;
|
|
|
|
struct atmio_closevcc cl;
|
|
|
|
struct ifnet *ifp;
|
|
|
|
int error = 0;
|
1997-05-09 08:04:59 +00:00
|
|
|
|
2006-04-23 16:33:56 +00:00
|
|
|
npcb = (struct natmpcb *)so->so_pcb;
|
|
|
|
KASSERT(npcb != NULL, ("natm_usr_disconnect: npcb == NULL"));
|
1997-05-09 08:04:59 +00:00
|
|
|
|
2006-04-23 16:33:56 +00:00
|
|
|
NATM_LOCK();
|
|
|
|
if ((npcb->npcb_flags & NPCB_CONNECTED) == 0) {
|
|
|
|
NATM_UNLOCK();
|
|
|
|
printf("natm: disconnected check\n");
|
|
|
|
return (EIO);
|
|
|
|
}
|
|
|
|
ifp = npcb->npcb_ifp;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Disable rx.
|
|
|
|
*
|
|
|
|
* XXXRW: Eventually desirable to hold mutex over ioctl?
|
|
|
|
*/
|
|
|
|
cl.vpi = npcb->npcb_vpi;
|
|
|
|
cl.vci = npcb->npcb_vci;
|
2006-04-23 16:25:30 +00:00
|
|
|
NATM_UNLOCK();
|
2009-03-15 14:21:05 +00:00
|
|
|
if (ifp->if_ioctl != NULL)
|
2006-04-23 16:33:56 +00:00
|
|
|
ifp->if_ioctl(ifp, SIOCATMCLOSEVCC, (caddr_t)&cl);
|
|
|
|
soisdisconnected(so);
|
|
|
|
return (error);
|
1997-05-09 08:04:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
natm_usr_shutdown(struct socket *so)
|
|
|
|
{
|
2006-04-23 16:33:56 +00:00
|
|
|
|
|
|
|
socantsendmore(so);
|
|
|
|
return (0);
|
1997-05-09 08:04:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
1997-08-16 19:16:27 +00:00
|
|
|
natm_usr_send(struct socket *so, int flags, struct mbuf *m,
|
2009-05-20 17:00:16 +00:00
|
|
|
struct sockaddr *nam, struct mbuf *control, struct thread *p)
|
1997-05-09 08:04:59 +00:00
|
|
|
{
|
2006-04-23 16:33:56 +00:00
|
|
|
struct natmpcb *npcb;
|
|
|
|
struct atm_pseudohdr *aph;
|
|
|
|
int error = 0;
|
|
|
|
int proto = so->so_proto->pr_protocol;
|
1997-05-09 08:04:59 +00:00
|
|
|
|
2006-04-23 16:33:56 +00:00
|
|
|
npcb = (struct natmpcb *)so->so_pcb;
|
|
|
|
KASSERT(npcb != NULL, ("natm_usr_send: npcb == NULL"));
|
1997-05-09 08:04:59 +00:00
|
|
|
|
2006-04-23 16:33:56 +00:00
|
|
|
NATM_LOCK();
|
|
|
|
if (control && control->m_len) {
|
|
|
|
NATM_UNLOCK();
|
|
|
|
m_freem(control);
|
|
|
|
m_freem(m);
|
|
|
|
return (EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Send the data. We must put an atm_pseudohdr on first.
|
|
|
|
*/
|
2012-12-05 08:04:20 +00:00
|
|
|
M_PREPEND(m, sizeof(*aph), M_NOWAIT);
|
2006-04-23 16:33:56 +00:00
|
|
|
if (m == NULL) {
|
|
|
|
NATM_UNLOCK();
|
|
|
|
m_freem(control);
|
|
|
|
return (ENOBUFS);
|
|
|
|
}
|
|
|
|
aph = mtod(m, struct atm_pseudohdr *);
|
|
|
|
ATM_PH_VPI(aph) = npcb->npcb_vpi;
|
|
|
|
ATM_PH_SETVCI(aph, npcb->npcb_vci);
|
|
|
|
ATM_PH_FLAGS(aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0;
|
|
|
|
error = atm_output(npcb->npcb_ifp, m, NULL, NULL);
|
2006-04-23 16:25:30 +00:00
|
|
|
NATM_UNLOCK();
|
2006-04-23 16:33:56 +00:00
|
|
|
return (error);
|
1997-05-09 08:04:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
1997-08-16 19:16:27 +00:00
|
|
|
natm_usr_peeraddr(struct socket *so, struct sockaddr **nam)
|
1997-05-09 08:04:59 +00:00
|
|
|
{
|
2006-04-23 16:33:56 +00:00
|
|
|
struct natmpcb *npcb;
|
|
|
|
struct sockaddr_natm *snatm, ssnatm;
|
|
|
|
|
|
|
|
npcb = (struct natmpcb *)so->so_pcb;
|
|
|
|
KASSERT(npcb != NULL, ("natm_usr_peeraddr: npcb == NULL"));
|
|
|
|
|
|
|
|
NATM_LOCK();
|
|
|
|
snatm = &ssnatm;
|
|
|
|
bzero(snatm, sizeof(*snatm));
|
|
|
|
snatm->snatm_len = sizeof(*snatm);
|
|
|
|
snatm->snatm_family = AF_NATM;
|
|
|
|
strlcpy(snatm->snatm_if, npcb->npcb_ifp->if_xname,
|
|
|
|
sizeof(snatm->snatm_if));
|
|
|
|
snatm->snatm_vci = npcb->npcb_vci;
|
|
|
|
snatm->snatm_vpi = npcb->npcb_vpi;
|
|
|
|
NATM_UNLOCK();
|
|
|
|
*nam = sodupsockaddr((struct sockaddr *)snatm, M_WAITOK);
|
|
|
|
return (0);
|
1997-05-09 08:04:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
1998-06-07 17:13:14 +00:00
|
|
|
natm_usr_control(struct socket *so, u_long cmd, caddr_t arg,
|
2009-05-20 17:00:16 +00:00
|
|
|
struct ifnet *ifp, struct thread *p)
|
1997-05-09 08:04:59 +00:00
|
|
|
{
|
2006-04-23 16:33:56 +00:00
|
|
|
struct natmpcb *npcb;
|
1997-05-09 08:04:59 +00:00
|
|
|
|
2006-04-23 16:33:56 +00:00
|
|
|
npcb = (struct natmpcb *)so->so_pcb;
|
|
|
|
KASSERT(npcb != NULL, ("natm_usr_control: npcb == NULL"));
|
1997-05-09 08:04:59 +00:00
|
|
|
|
2006-04-23 16:33:56 +00:00
|
|
|
if (ifp == NULL || ifp->if_ioctl == NULL)
|
|
|
|
return (EOPNOTSUPP);
|
2009-03-15 14:21:05 +00:00
|
|
|
return ((*ifp->if_ioctl)(ifp, cmd, arg));
|
1997-05-09 08:04:59 +00:00
|
|
|
}
|
|
|
|
|
2006-04-01 15:15:05 +00:00
|
|
|
static void
|
1997-05-09 08:04:59 +00:00
|
|
|
natm_usr_abort(struct socket *so)
|
|
|
|
{
|
2006-04-23 16:33:56 +00:00
|
|
|
|
2006-07-21 17:11:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
natm_usr_close(struct socket *so)
|
|
|
|
{
|
|
|
|
|
1997-05-09 08:04:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2009-05-20 17:00:16 +00:00
|
|
|
natm_usr_bind(struct socket *so, struct sockaddr *nam, struct thread *p)
|
1997-05-09 08:04:59 +00:00
|
|
|
{
|
2006-04-23 16:33:56 +00:00
|
|
|
|
|
|
|
return (EOPNOTSUPP);
|
1997-05-09 08:04:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
1997-08-16 19:16:27 +00:00
|
|
|
natm_usr_sockaddr(struct socket *so, struct sockaddr **nam)
|
1997-05-09 08:04:59 +00:00
|
|
|
{
|
2006-04-23 16:33:56 +00:00
|
|
|
|
|
|
|
return (EOPNOTSUPP);
|
1997-05-09 08:04:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* xxx - should be const */
|
|
|
|
struct pr_usrreqs natm_usrreqs = {
|
2004-11-08 14:44:54 +00:00
|
|
|
.pru_abort = natm_usr_abort,
|
|
|
|
.pru_attach = natm_usr_attach,
|
|
|
|
.pru_bind = natm_usr_bind,
|
|
|
|
.pru_connect = natm_usr_connect,
|
|
|
|
.pru_control = natm_usr_control,
|
|
|
|
.pru_detach = natm_usr_detach,
|
|
|
|
.pru_disconnect = natm_usr_disconnect,
|
|
|
|
.pru_peeraddr = natm_usr_peeraddr,
|
|
|
|
.pru_send = natm_usr_send,
|
|
|
|
.pru_shutdown = natm_usr_shutdown,
|
|
|
|
.pru_sockaddr = natm_usr_sockaddr,
|
2006-07-21 17:11:15 +00:00
|
|
|
.pru_close = natm_usr_close,
|
1997-05-09 08:04:59 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
2005-07-19 13:36:39 +00:00
|
|
|
* natmintr: interrupt
|
1997-05-09 08:04:59 +00:00
|
|
|
*
|
2006-04-23 16:33:56 +00:00
|
|
|
* Note: we expect a socket pointer in rcvif rather than an interface
|
|
|
|
* pointer. We can get the interface pointer from the so's PCB if we really
|
|
|
|
* need it.
|
1997-05-09 08:04:59 +00:00
|
|
|
*/
|
|
|
|
void
|
2003-03-04 23:19:55 +00:00
|
|
|
natmintr(struct mbuf *m)
|
1997-05-09 08:04:59 +00:00
|
|
|
{
|
2003-08-06 13:46:15 +00:00
|
|
|
struct socket *so;
|
|
|
|
struct natmpcb *npcb;
|
1997-05-09 08:04:59 +00:00
|
|
|
|
|
|
|
#ifdef DIAGNOSTIC
|
2003-08-06 13:46:15 +00:00
|
|
|
M_ASSERTPKTHDR(m);
|
1997-05-09 08:04:59 +00:00
|
|
|
#endif
|
|
|
|
|
Lock down netnatm and mark as MPSAFE:
- Introduce a subsystem mutex, natm_mtx, manipulated with accessor macros
NATM_LOCK_INIT(), NATM_LOCK(), NATM_UNLOCK(), NATM_LOCK_ASSERT(). It
protects the consistency of pcb-related data structures. Finer grained
locking is possible, but should be done in the context of specific
measurements (as very little work is done in netnatm -- most is in the
ATM device driver or socket layer, so there's probably not much
contention).
- Remove GIANT_REQUIRED, mark as NETISR_MPSAFE, remove
NET_NEEDS_GIANT("netnatm").
- Conditionally acquire Giant when entering network interfaces for
ifp->if_ioctl() using IFF_LOCKGIANT(ifp)/IFF_UNLOCKGIANT(ifp) in order
to coexist with non-MPSAFE atm ifnet drivers..
- De-spl.
MFC after: 2 weeks
Reviewed by: harti, bms (various versions)
2005-07-18 16:55:46 +00:00
|
|
|
NATM_LOCK();
|
2003-08-06 13:46:15 +00:00
|
|
|
npcb = (struct natmpcb *)m->m_pkthdr.rcvif; /* XXX: overloaded */
|
|
|
|
so = npcb->npcb_socket;
|
1997-05-09 08:04:59 +00:00
|
|
|
|
2003-08-06 13:46:15 +00:00
|
|
|
npcb->npcb_inq--;
|
1997-05-09 08:04:59 +00:00
|
|
|
|
2003-08-06 13:46:15 +00:00
|
|
|
if (npcb->npcb_flags & NPCB_DRAIN) {
|
|
|
|
if (npcb->npcb_inq == 0)
|
2008-10-23 15:53:51 +00:00
|
|
|
free(npcb, M_PCB); /* done! */
|
Lock down netnatm and mark as MPSAFE:
- Introduce a subsystem mutex, natm_mtx, manipulated with accessor macros
NATM_LOCK_INIT(), NATM_LOCK(), NATM_UNLOCK(), NATM_LOCK_ASSERT(). It
protects the consistency of pcb-related data structures. Finer grained
locking is possible, but should be done in the context of specific
measurements (as very little work is done in netnatm -- most is in the
ATM device driver or socket layer, so there's probably not much
contention).
- Remove GIANT_REQUIRED, mark as NETISR_MPSAFE, remove
NET_NEEDS_GIANT("netnatm").
- Conditionally acquire Giant when entering network interfaces for
ifp->if_ioctl() using IFF_LOCKGIANT(ifp)/IFF_UNLOCKGIANT(ifp) in order
to coexist with non-MPSAFE atm ifnet drivers..
- De-spl.
MFC after: 2 weeks
Reviewed by: harti, bms (various versions)
2005-07-18 16:55:46 +00:00
|
|
|
NATM_UNLOCK();
|
|
|
|
m_freem(m);
|
2003-08-06 13:46:15 +00:00
|
|
|
return;
|
|
|
|
}
|
1997-05-09 08:04:59 +00:00
|
|
|
|
2003-08-06 13:46:15 +00:00
|
|
|
if (npcb->npcb_flags & NPCB_FREE) {
|
Lock down netnatm and mark as MPSAFE:
- Introduce a subsystem mutex, natm_mtx, manipulated with accessor macros
NATM_LOCK_INIT(), NATM_LOCK(), NATM_UNLOCK(), NATM_LOCK_ASSERT(). It
protects the consistency of pcb-related data structures. Finer grained
locking is possible, but should be done in the context of specific
measurements (as very little work is done in netnatm -- most is in the
ATM device driver or socket layer, so there's probably not much
contention).
- Remove GIANT_REQUIRED, mark as NETISR_MPSAFE, remove
NET_NEEDS_GIANT("netnatm").
- Conditionally acquire Giant when entering network interfaces for
ifp->if_ioctl() using IFF_LOCKGIANT(ifp)/IFF_UNLOCKGIANT(ifp) in order
to coexist with non-MPSAFE atm ifnet drivers..
- De-spl.
MFC after: 2 weeks
Reviewed by: harti, bms (various versions)
2005-07-18 16:55:46 +00:00
|
|
|
NATM_UNLOCK();
|
2003-08-06 13:46:15 +00:00
|
|
|
m_freem(m); /* drop */
|
|
|
|
return;
|
|
|
|
}
|
1997-05-09 08:04:59 +00:00
|
|
|
|
|
|
|
#ifdef NEED_TO_RESTORE_IFP
|
2003-08-06 13:46:15 +00:00
|
|
|
m->m_pkthdr.rcvif = npcb->npcb_ifp;
|
1997-05-09 08:04:59 +00:00
|
|
|
#else
|
|
|
|
#ifdef DIAGNOSTIC
|
2003-08-06 13:46:15 +00:00
|
|
|
m->m_pkthdr.rcvif = NULL; /* null it out to be safe */
|
1997-05-09 08:04:59 +00:00
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2003-08-06 14:34:38 +00:00
|
|
|
if (sbspace(&so->so_rcv) > m->m_pkthdr.len) {
|
1997-05-09 08:04:59 +00:00
|
|
|
#ifdef NATM_STAT
|
2003-08-06 13:46:15 +00:00
|
|
|
natm_sookcnt++;
|
|
|
|
natm_sookbytes += m->m_pkthdr.len;
|
1997-05-09 08:04:59 +00:00
|
|
|
#endif
|
2003-08-06 13:46:15 +00:00
|
|
|
sbappendrecord(&so->so_rcv, m);
|
|
|
|
sorwakeup(so);
|
Lock down netnatm and mark as MPSAFE:
- Introduce a subsystem mutex, natm_mtx, manipulated with accessor macros
NATM_LOCK_INIT(), NATM_LOCK(), NATM_UNLOCK(), NATM_LOCK_ASSERT(). It
protects the consistency of pcb-related data structures. Finer grained
locking is possible, but should be done in the context of specific
measurements (as very little work is done in netnatm -- most is in the
ATM device driver or socket layer, so there's probably not much
contention).
- Remove GIANT_REQUIRED, mark as NETISR_MPSAFE, remove
NET_NEEDS_GIANT("netnatm").
- Conditionally acquire Giant when entering network interfaces for
ifp->if_ioctl() using IFF_LOCKGIANT(ifp)/IFF_UNLOCKGIANT(ifp) in order
to coexist with non-MPSAFE atm ifnet drivers..
- De-spl.
MFC after: 2 weeks
Reviewed by: harti, bms (various versions)
2005-07-18 16:55:46 +00:00
|
|
|
NATM_UNLOCK();
|
2003-08-06 13:46:15 +00:00
|
|
|
} else {
|
1997-05-09 08:04:59 +00:00
|
|
|
#ifdef NATM_STAT
|
2003-08-06 13:46:15 +00:00
|
|
|
natm_sodropcnt++;
|
|
|
|
natm_sodropbytes += m->m_pkthdr.len;
|
1997-05-09 08:04:59 +00:00
|
|
|
#endif
|
Lock down netnatm and mark as MPSAFE:
- Introduce a subsystem mutex, natm_mtx, manipulated with accessor macros
NATM_LOCK_INIT(), NATM_LOCK(), NATM_UNLOCK(), NATM_LOCK_ASSERT(). It
protects the consistency of pcb-related data structures. Finer grained
locking is possible, but should be done in the context of specific
measurements (as very little work is done in netnatm -- most is in the
ATM device driver or socket layer, so there's probably not much
contention).
- Remove GIANT_REQUIRED, mark as NETISR_MPSAFE, remove
NET_NEEDS_GIANT("netnatm").
- Conditionally acquire Giant when entering network interfaces for
ifp->if_ioctl() using IFF_LOCKGIANT(ifp)/IFF_UNLOCKGIANT(ifp) in order
to coexist with non-MPSAFE atm ifnet drivers..
- De-spl.
MFC after: 2 weeks
Reviewed by: harti, bms (various versions)
2005-07-18 16:55:46 +00:00
|
|
|
NATM_UNLOCK();
|
2003-08-06 13:46:15 +00:00
|
|
|
m_freem(m);
|
|
|
|
}
|
1997-05-09 08:04:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* natm0_sysctl: not used, but here in case we want to add something
|
|
|
|
* later...
|
|
|
|
*/
|
2003-08-06 13:46:15 +00:00
|
|
|
int
|
|
|
|
natm0_sysctl(SYSCTL_HANDLER_ARGS)
|
1997-05-09 08:04:59 +00:00
|
|
|
{
|
2006-04-23 16:33:56 +00:00
|
|
|
|
2003-08-06 13:46:15 +00:00
|
|
|
/* All sysctl names at this level are terminal. */
|
|
|
|
return (ENOENT);
|
1997-05-09 08:04:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* natm5_sysctl: not used, but here in case we want to add something
|
|
|
|
* later...
|
|
|
|
*/
|
2003-08-06 13:46:15 +00:00
|
|
|
int
|
|
|
|
natm5_sysctl(SYSCTL_HANDLER_ARGS)
|
1997-05-09 08:04:59 +00:00
|
|
|
{
|
2006-04-23 16:33:56 +00:00
|
|
|
|
2003-08-06 13:46:15 +00:00
|
|
|
/* All sysctl names at this level are terminal. */
|
|
|
|
return (ENOENT);
|
1997-05-09 08:04:59 +00:00
|
|
|
}
|