2007-03-04 08:59:00 +03:00
|
|
|
/* $NetBSD: cltp_usrreq.c,v 1.32 2007/03/04 06:03:31 christos Exp $ */
|
1994-06-29 10:39:25 +04:00
|
|
|
|
1993-04-09 16:00:07 +04:00
|
|
|
/*
|
1994-05-13 10:08:03 +04:00
|
|
|
* Copyright (c) 1989, 1993
|
|
|
|
* The Regents of the University of California. All rights reserved.
|
1993-04-09 16:00:07 +04:00
|
|
|
*
|
|
|
|
* 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.
|
2003-08-07 20:26:28 +04:00
|
|
|
* 3. Neither the name of the University nor the names of its contributors
|
1993-04-09 16:00:07 +04:00
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
|
|
|
*
|
1994-06-29 10:39:25 +04:00
|
|
|
* @(#)cltp_usrreq.c 8.1 (Berkeley) 6/10/93
|
1993-04-09 16:00:07 +04:00
|
|
|
*/
|
|
|
|
|
2001-11-13 03:56:55 +03:00
|
|
|
#include <sys/cdefs.h>
|
2007-03-04 08:59:00 +03:00
|
|
|
__KERNEL_RCSID(0, "$NetBSD: cltp_usrreq.c,v 1.32 2007/03/04 06:03:31 christos Exp $");
|
2001-11-13 03:56:55 +03:00
|
|
|
|
1996-02-14 01:07:57 +03:00
|
|
|
#ifndef CLTPOVAL_SRC /* XXX -- till files gets changed */
|
1993-12-18 03:40:47 +03:00
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/malloc.h>
|
|
|
|
#include <sys/mbuf.h>
|
|
|
|
#include <sys/protosw.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/socketvar.h>
|
|
|
|
#include <sys/errno.h>
|
|
|
|
#include <sys/stat.h>
|
1996-02-14 01:07:57 +03:00
|
|
|
#include <sys/systm.h>
|
2005-12-11 15:16:03 +03:00
|
|
|
#include <sys/proc.h>
|
1993-04-09 16:00:07 +04:00
|
|
|
|
1993-12-18 03:40:47 +03:00
|
|
|
#include <net/if.h>
|
|
|
|
#include <net/route.h>
|
1993-04-09 16:00:07 +04:00
|
|
|
|
1993-12-18 03:40:47 +03:00
|
|
|
#include <netiso/argo_debug.h>
|
|
|
|
#include <netiso/iso.h>
|
|
|
|
#include <netiso/iso_pcb.h>
|
|
|
|
#include <netiso/iso_var.h>
|
|
|
|
#include <netiso/clnp.h>
|
|
|
|
#include <netiso/cltp_var.h>
|
1996-02-14 01:07:57 +03:00
|
|
|
#include <netiso/tp_param.h>
|
|
|
|
#include <netiso/tp_var.h>
|
|
|
|
|
|
|
|
#include <machine/stdarg.h>
|
1993-04-09 16:00:07 +04:00
|
|
|
#endif
|
|
|
|
|
1996-02-14 01:07:57 +03:00
|
|
|
|
1993-04-09 16:00:07 +04:00
|
|
|
/*
|
|
|
|
* CLTP protocol implementation.
|
|
|
|
* Per ISO 8602, December, 1987.
|
|
|
|
*/
|
1994-05-13 10:08:03 +04:00
|
|
|
void
|
1993-04-09 16:00:07 +04:00
|
|
|
cltp_init()
|
|
|
|
{
|
|
|
|
|
|
|
|
cltb.isop_next = cltb.isop_prev = &cltb;
|
|
|
|
}
|
|
|
|
|
2002-05-13 01:30:35 +04:00
|
|
|
int cltp_cksum = 1;
|
|
|
|
struct isopcb cltb;
|
|
|
|
struct cltpstat cltpstat;
|
1993-04-09 16:00:07 +04:00
|
|
|
|
|
|
|
|
|
|
|
/* ARGUSED */
|
1994-05-13 10:08:03 +04:00
|
|
|
void
|
1996-02-14 01:07:57 +03:00
|
|
|
cltp_input(struct mbuf *m0, ...)
|
1993-04-09 16:00:07 +04:00
|
|
|
{
|
1996-02-14 01:07:57 +03:00
|
|
|
struct sockaddr *srcsa, *dstsa;
|
|
|
|
u_int cons_channel;
|
2000-03-30 16:51:13 +04:00
|
|
|
struct isopcb *isop;
|
|
|
|
struct mbuf *m = m0;
|
1997-06-24 06:25:59 +04:00
|
|
|
struct mbuf *m_src = 0;
|
2000-03-30 16:51:13 +04:00
|
|
|
u_char *up = mtod(m, u_char *);
|
|
|
|
struct sockaddr_iso *src;
|
1996-02-14 01:07:57 +03:00
|
|
|
int len, hdrlen = *up + 1, dlen = 0;
|
|
|
|
u_char *uplim = up + hdrlen;
|
2007-03-04 08:59:00 +03:00
|
|
|
void * dtsap = NULL;
|
1996-02-14 01:07:57 +03:00
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
va_start(ap, m0);
|
|
|
|
srcsa = va_arg(ap, struct sockaddr *);
|
|
|
|
dstsa = va_arg(ap, struct sockaddr *);
|
|
|
|
cons_channel = va_arg(ap, int);
|
|
|
|
va_end(ap);
|
|
|
|
src = satosiso(srcsa);
|
1993-04-09 16:00:07 +04:00
|
|
|
|
|
|
|
for (len = 0; m; m = m->m_next)
|
|
|
|
len += m->m_len;
|
1996-02-14 01:07:57 +03:00
|
|
|
up += 2; /* skip header */
|
|
|
|
while (up < uplim)
|
|
|
|
switch (*up) { /* process options */
|
|
|
|
case CLTPOVAL_SRC:
|
|
|
|
src->siso_tlen = up[1];
|
KNF: de-__P, bzero -> memset, bcmp -> memcmp. Remove extraneous
parentheses in return statements.
Cosmetic: don't open-code TAILQ_FOREACH().
Cosmetic: change types of variables to avoid oodles of casts: in
in6_src.c, avoid casts by changing several route_in6 pointers
to struct route pointers. Remove unnecessary casts to caddr_t
elsewhere.
Pave the way for eliminating address family-specific route caches:
soon, struct route will not embed a sockaddr, but it will hold
a reference to an external sockaddr, instead. We will set the
destination sockaddr using rtcache_setdst(). (I created a stub
for it, but it isn't used anywhere, yet.) rtcache_free() will
free the sockaddr. I have extracted from rtcache_free() a helper
subroutine, rtcache_clear(). rtcache_clear() will "forget" a
cached route, but it will not forget the destination by releasing
the sockaddr. I use rtcache_clear() instead of rtcache_free()
in rtcache_update(), because rtcache_update() is not supposed
to forget the destination.
Constify:
1 Introduce const accessor for route->ro_dst, rtcache_getdst().
2 Constify the 'dst' argument to ifnet->if_output(). This
led me to constify a lot of code called by output routines.
3 Constify the sockaddr argument to protosw->pr_ctlinput. This
led me to constify a lot of code called by ctlinput routines.
4 Introduce const macros for converting from a generic sockaddr
to family-specific sockaddrs, e.g., sockaddr_in: satocsin6,
satocsin, et cetera.
2007-02-18 01:34:07 +03:00
|
|
|
src->siso_len = up[1] +
|
|
|
|
((const char *)TSEL(src) - (const char *)src);
|
1996-02-14 01:07:57 +03:00
|
|
|
if (src->siso_len < sizeof(*src))
|
|
|
|
src->siso_len = sizeof(*src);
|
|
|
|
else if (src->siso_len > sizeof(*src)) {
|
1997-06-24 06:25:59 +04:00
|
|
|
MGET(m_src, M_DONTWAIT, MT_SONAME);
|
|
|
|
if (m_src == 0)
|
1996-02-14 01:07:57 +03:00
|
|
|
goto bad;
|
1997-06-24 06:25:59 +04:00
|
|
|
m_src->m_len = src->siso_len;
|
|
|
|
src = mtod(m_src, struct sockaddr_iso *);
|
2007-03-04 08:59:00 +03:00
|
|
|
bcopy((void *) srcsa, (void *) src, srcsa->sa_len);
|
1996-02-14 01:07:57 +03:00
|
|
|
}
|
2007-03-04 08:59:00 +03:00
|
|
|
memcpy(WRITABLE_TSEL(src), (char *)up + 2, up[1]);
|
1996-02-14 01:07:57 +03:00
|
|
|
up += 2 + src->siso_tlen;
|
|
|
|
continue;
|
|
|
|
|
|
|
|
case CLTPOVAL_DST:
|
2007-03-04 08:59:00 +03:00
|
|
|
dtsap = 2 + (char *)up;
|
1996-02-14 01:07:57 +03:00
|
|
|
dlen = up[1];
|
|
|
|
up += 2 + dlen;
|
|
|
|
continue;
|
|
|
|
|
|
|
|
case CLTPOVAL_CSM:
|
|
|
|
if (iso_check_csum(m0, len)) {
|
|
|
|
cltpstat.cltps_badsum++;
|
1993-04-09 16:00:07 +04:00
|
|
|
goto bad;
|
1996-02-14 01:07:57 +03:00
|
|
|
}
|
|
|
|
up += 4;
|
|
|
|
continue;
|
|
|
|
|
|
|
|
default:
|
1996-10-13 06:03:00 +04:00
|
|
|
printf("clts: unknown option (%x)\n", up[0]);
|
1996-02-14 01:07:57 +03:00
|
|
|
cltpstat.cltps_hdrops++;
|
1993-04-09 16:00:07 +04:00
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
if (dlen == 0 || src->siso_tlen == 0)
|
|
|
|
goto bad;
|
|
|
|
for (isop = cltb.isop_next;; isop = isop->isop_next) {
|
|
|
|
if (isop == &cltb) {
|
|
|
|
cltpstat.cltps_noport++;
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
if (isop->isop_laddr &&
|
|
|
|
bcmp(TSEL(isop->isop_laddr), dtsap, dlen) == 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
m = m0;
|
|
|
|
m->m_len -= hdrlen;
|
|
|
|
m->m_data += hdrlen;
|
1995-06-13 11:13:14 +04:00
|
|
|
if (sbappendaddr(&isop->isop_socket->so_rcv, sisotosa(src), m,
|
1996-02-14 01:07:57 +03:00
|
|
|
(struct mbuf *) 0) == 0)
|
1993-04-09 16:00:07 +04:00
|
|
|
goto bad;
|
|
|
|
cltpstat.cltps_ipackets++;
|
|
|
|
sorwakeup(isop->isop_socket);
|
|
|
|
m0 = 0;
|
|
|
|
bad:
|
1995-06-13 11:13:14 +04:00
|
|
|
if (src != satosiso(srcsa))
|
1997-06-24 06:25:59 +04:00
|
|
|
m_freem(m_src);
|
1993-04-09 16:00:07 +04:00
|
|
|
if (m0)
|
|
|
|
m_freem(m0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Notify a cltp user of an asynchronous error;
|
|
|
|
* just wake up so that he can collect error status.
|
|
|
|
*/
|
1996-02-14 01:07:57 +03:00
|
|
|
void
|
1993-04-09 16:00:07 +04:00
|
|
|
cltp_notify(isop)
|
2000-03-30 16:51:13 +04:00
|
|
|
struct isopcb *isop;
|
1993-04-09 16:00:07 +04:00
|
|
|
{
|
|
|
|
|
|
|
|
sorwakeup(isop->isop_socket);
|
|
|
|
sowwakeup(isop->isop_socket);
|
|
|
|
}
|
|
|
|
|
1994-05-13 10:08:03 +04:00
|
|
|
void
|
2006-10-12 05:30:41 +04:00
|
|
|
cltp_ctlinput(
|
|
|
|
int cmd,
|
KNF: de-__P, bzero -> memset, bcmp -> memcmp. Remove extraneous
parentheses in return statements.
Cosmetic: don't open-code TAILQ_FOREACH().
Cosmetic: change types of variables to avoid oodles of casts: in
in6_src.c, avoid casts by changing several route_in6 pointers
to struct route pointers. Remove unnecessary casts to caddr_t
elsewhere.
Pave the way for eliminating address family-specific route caches:
soon, struct route will not embed a sockaddr, but it will hold
a reference to an external sockaddr, instead. We will set the
destination sockaddr using rtcache_setdst(). (I created a stub
for it, but it isn't used anywhere, yet.) rtcache_free() will
free the sockaddr. I have extracted from rtcache_free() a helper
subroutine, rtcache_clear(). rtcache_clear() will "forget" a
cached route, but it will not forget the destination by releasing
the sockaddr. I use rtcache_clear() instead of rtcache_free()
in rtcache_update(), because rtcache_update() is not supposed
to forget the destination.
Constify:
1 Introduce const accessor for route->ro_dst, rtcache_getdst().
2 Constify the 'dst' argument to ifnet->if_output(). This
led me to constify a lot of code called by output routines.
3 Constify the sockaddr argument to protosw->pr_ctlinput. This
led me to constify a lot of code called by ctlinput routines.
4 Introduce const macros for converting from a generic sockaddr
to family-specific sockaddrs, e.g., sockaddr_in: satocsin6,
satocsin, et cetera.
2007-02-18 01:34:07 +03:00
|
|
|
const struct sockaddr *sa,
|
2006-11-16 04:32:37 +03:00
|
|
|
void *dummy)
|
1993-04-09 16:00:07 +04:00
|
|
|
{
|
KNF: de-__P, bzero -> memset, bcmp -> memcmp. Remove extraneous
parentheses in return statements.
Cosmetic: don't open-code TAILQ_FOREACH().
Cosmetic: change types of variables to avoid oodles of casts: in
in6_src.c, avoid casts by changing several route_in6 pointers
to struct route pointers. Remove unnecessary casts to caddr_t
elsewhere.
Pave the way for eliminating address family-specific route caches:
soon, struct route will not embed a sockaddr, but it will hold
a reference to an external sockaddr, instead. We will set the
destination sockaddr using rtcache_setdst(). (I created a stub
for it, but it isn't used anywhere, yet.) rtcache_free() will
free the sockaddr. I have extracted from rtcache_free() a helper
subroutine, rtcache_clear(). rtcache_clear() will "forget" a
cached route, but it will not forget the destination by releasing
the sockaddr. I use rtcache_clear() instead of rtcache_free()
in rtcache_update(), because rtcache_update() is not supposed
to forget the destination.
Constify:
1 Introduce const accessor for route->ro_dst, rtcache_getdst().
2 Constify the 'dst' argument to ifnet->if_output(). This
led me to constify a lot of code called by output routines.
3 Constify the sockaddr argument to protosw->pr_ctlinput. This
led me to constify a lot of code called by ctlinput routines.
4 Introduce const macros for converting from a generic sockaddr
to family-specific sockaddrs, e.g., sockaddr_in: satocsin6,
satocsin, et cetera.
2007-02-18 01:34:07 +03:00
|
|
|
const struct sockaddr_iso *siso;
|
1993-04-09 16:00:07 +04:00
|
|
|
|
2003-09-30 04:01:18 +04:00
|
|
|
if ((unsigned)cmd >= PRC_NCMDS)
|
1993-04-09 16:00:07 +04:00
|
|
|
return;
|
|
|
|
if (sa->sa_family != AF_ISO && sa->sa_family != AF_CCITT)
|
|
|
|
return;
|
KNF: de-__P, bzero -> memset, bcmp -> memcmp. Remove extraneous
parentheses in return statements.
Cosmetic: don't open-code TAILQ_FOREACH().
Cosmetic: change types of variables to avoid oodles of casts: in
in6_src.c, avoid casts by changing several route_in6 pointers
to struct route pointers. Remove unnecessary casts to caddr_t
elsewhere.
Pave the way for eliminating address family-specific route caches:
soon, struct route will not embed a sockaddr, but it will hold
a reference to an external sockaddr, instead. We will set the
destination sockaddr using rtcache_setdst(). (I created a stub
for it, but it isn't used anywhere, yet.) rtcache_free() will
free the sockaddr. I have extracted from rtcache_free() a helper
subroutine, rtcache_clear(). rtcache_clear() will "forget" a
cached route, but it will not forget the destination by releasing
the sockaddr. I use rtcache_clear() instead of rtcache_free()
in rtcache_update(), because rtcache_update() is not supposed
to forget the destination.
Constify:
1 Introduce const accessor for route->ro_dst, rtcache_getdst().
2 Constify the 'dst' argument to ifnet->if_output(). This
led me to constify a lot of code called by output routines.
3 Constify the sockaddr argument to protosw->pr_ctlinput. This
led me to constify a lot of code called by ctlinput routines.
4 Introduce const macros for converting from a generic sockaddr
to family-specific sockaddrs, e.g., sockaddr_in: satocsin6,
satocsin, et cetera.
2007-02-18 01:34:07 +03:00
|
|
|
siso = satocsiso(sa);
|
1993-04-09 16:00:07 +04:00
|
|
|
if (siso == 0 || siso->siso_nlen == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
switch (cmd) {
|
|
|
|
case PRC_ROUTEDEAD:
|
|
|
|
case PRC_REDIRECT_NET:
|
|
|
|
case PRC_REDIRECT_HOST:
|
|
|
|
case PRC_REDIRECT_TOSNET:
|
|
|
|
case PRC_REDIRECT_TOSHOST:
|
|
|
|
iso_pcbnotify(&cltb, siso,
|
2004-04-19 09:16:45 +04:00
|
|
|
(int) isoctlerrmap[cmd], iso_rtchange);
|
1993-04-09 16:00:07 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2004-04-19 09:16:45 +04:00
|
|
|
if (isoctlerrmap[cmd] == 0)
|
1996-02-14 01:07:57 +03:00
|
|
|
return; /* XXX */
|
2004-04-19 09:16:45 +04:00
|
|
|
iso_pcbnotify(&cltb, siso, (int) isoctlerrmap[cmd],
|
1996-02-14 01:07:57 +03:00
|
|
|
cltp_notify);
|
1993-04-09 16:00:07 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1996-02-14 01:07:57 +03:00
|
|
|
int
|
|
|
|
cltp_output(struct mbuf *m, ...)
|
1993-04-09 16:00:07 +04:00
|
|
|
{
|
2000-03-30 16:51:13 +04:00
|
|
|
struct isopcb *isop;
|
|
|
|
int len;
|
|
|
|
struct sockaddr_iso *siso;
|
1996-02-14 01:07:57 +03:00
|
|
|
int hdrlen, error = 0, docsum;
|
2000-03-30 16:51:13 +04:00
|
|
|
u_char *up;
|
1996-02-14 01:07:57 +03:00
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
va_start(ap, m);
|
|
|
|
isop = va_arg(ap, struct isopcb *);
|
|
|
|
va_end(ap);
|
1993-04-09 16:00:07 +04:00
|
|
|
|
|
|
|
if (isop->isop_laddr == 0 || isop->isop_faddr == 0) {
|
|
|
|
error = ENOTCONN;
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Calculate data length and get a mbuf for CLTP header.
|
|
|
|
*/
|
|
|
|
hdrlen = 2 + 2 + isop->isop_laddr->siso_tlen
|
1996-02-14 01:07:57 +03:00
|
|
|
+ 2 + isop->isop_faddr->siso_tlen;
|
|
|
|
docsum = /* isop->isop_flags & CLNP_NO_CKSUM */ cltp_cksum;
|
|
|
|
if (docsum)
|
1993-04-09 16:00:07 +04:00
|
|
|
hdrlen += 4;
|
|
|
|
M_PREPEND(m, hdrlen, M_WAIT);
|
|
|
|
len = m->m_pkthdr.len;
|
|
|
|
/*
|
|
|
|
* Fill in mbuf with extended CLTP header
|
|
|
|
*/
|
|
|
|
up = mtod(m, u_char *);
|
|
|
|
up[0] = hdrlen - 1;
|
|
|
|
up[1] = UD_TPDU_type;
|
|
|
|
up[2] = CLTPOVAL_SRC;
|
|
|
|
up[3] = (siso = isop->isop_laddr)->siso_tlen;
|
|
|
|
up += 4;
|
2007-03-04 08:59:00 +03:00
|
|
|
bcopy(TSEL(siso), (void *) up, siso->siso_tlen);
|
1993-04-09 16:00:07 +04:00
|
|
|
up += siso->siso_tlen;
|
|
|
|
up[0] = CLTPOVAL_DST;
|
|
|
|
up[1] = (siso = isop->isop_faddr)->siso_tlen;
|
|
|
|
up += 2;
|
2007-03-04 08:59:00 +03:00
|
|
|
bcopy(TSEL(siso), (void *) up, siso->siso_tlen);
|
1993-04-09 16:00:07 +04:00
|
|
|
/*
|
|
|
|
* Stuff checksum and output datagram.
|
|
|
|
*/
|
|
|
|
if (docsum) {
|
|
|
|
up += siso->siso_tlen;
|
|
|
|
up[0] = CLTPOVAL_CSM;
|
|
|
|
up[1] = 2;
|
|
|
|
iso_gen_csum(m, 2 + up - mtod(m, u_char *), len);
|
|
|
|
}
|
|
|
|
cltpstat.cltps_opackets++;
|
1996-02-14 01:07:57 +03:00
|
|
|
return (tpclnp_output(m, len, isop, !docsum));
|
1993-04-09 16:00:07 +04:00
|
|
|
bad:
|
|
|
|
m_freem(m);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
1996-02-14 01:07:57 +03:00
|
|
|
u_long cltp_sendspace = 9216; /* really max datagram size */
|
|
|
|
u_long cltp_recvspace = 40 * (1024 + sizeof(struct sockaddr_iso));
|
|
|
|
/* 40 1K datagrams */
|
1993-04-09 16:00:07 +04:00
|
|
|
|
|
|
|
|
1996-02-14 01:07:57 +03:00
|
|
|
/* ARGSUSED */
|
|
|
|
int
|
2005-12-11 15:16:03 +03:00
|
|
|
cltp_usrreq(so, req, m, nam, control, l)
|
1996-05-22 17:54:55 +04:00
|
|
|
struct socket *so;
|
|
|
|
int req;
|
|
|
|
struct mbuf *m, *nam, *control;
|
2005-12-11 15:16:03 +03:00
|
|
|
struct lwp *l;
|
1993-04-09 16:00:07 +04:00
|
|
|
{
|
2000-03-30 16:51:13 +04:00
|
|
|
struct isopcb *isop;
|
1996-09-08 18:28:08 +04:00
|
|
|
int s;
|
|
|
|
int error = 0;
|
1993-04-09 16:00:07 +04:00
|
|
|
|
|
|
|
if (req == PRU_CONTROL)
|
2007-03-04 08:59:00 +03:00
|
|
|
return (iso_control(so, (long)m, (void *)nam,
|
2005-12-11 15:16:03 +03:00
|
|
|
(struct ifnet *)control, l));
|
1996-09-08 18:28:08 +04:00
|
|
|
|
2000-02-03 02:28:08 +03:00
|
|
|
if (req == PRU_PURGEIF) {
|
|
|
|
iso_purgeif((struct ifnet *)control);
|
2000-02-02 01:52:04 +03:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
1996-09-08 18:28:08 +04:00
|
|
|
s = splsoftnet();
|
|
|
|
isop = sotoisopcb(so);
|
|
|
|
#ifdef DIAGNOSTIC
|
|
|
|
if (req != PRU_SEND && req != PRU_SENDOOB && control)
|
|
|
|
panic("cltp_usrreq: unexpected control mbuf");
|
|
|
|
#endif
|
|
|
|
if (isop == 0 && req != PRU_ATTACH) {
|
1993-04-09 16:00:07 +04:00
|
|
|
error = EINVAL;
|
|
|
|
goto release;
|
|
|
|
}
|
1996-09-08 18:28:08 +04:00
|
|
|
|
1993-04-09 16:00:07 +04:00
|
|
|
switch (req) {
|
|
|
|
|
|
|
|
case PRU_ATTACH:
|
1996-09-08 18:28:08 +04:00
|
|
|
if (isop != 0) {
|
|
|
|
error = EISCONN;
|
1993-04-09 16:00:07 +04:00
|
|
|
break;
|
|
|
|
}
|
1996-09-08 18:28:08 +04:00
|
|
|
if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
|
|
|
|
error = soreserve(so, cltp_sendspace, cltp_recvspace);
|
|
|
|
if (error)
|
|
|
|
break;
|
|
|
|
}
|
1993-04-09 16:00:07 +04:00
|
|
|
error = iso_pcballoc(so, &cltb);
|
|
|
|
if (error)
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PRU_DETACH:
|
|
|
|
iso_pcbdetach(isop);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PRU_BIND:
|
2006-07-24 02:06:03 +04:00
|
|
|
error = iso_pcbbind(isop, nam, l);
|
1993-04-09 16:00:07 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PRU_LISTEN:
|
|
|
|
error = EOPNOTSUPP;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PRU_CONNECT:
|
2006-07-24 02:06:03 +04:00
|
|
|
error = iso_pcbconnect(isop, nam, l);
|
1996-09-08 18:28:08 +04:00
|
|
|
if (error)
|
|
|
|
break;
|
|
|
|
soisconnected(so);
|
1993-04-09 16:00:07 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PRU_CONNECT2:
|
|
|
|
error = EOPNOTSUPP;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PRU_DISCONNECT:
|
1996-09-08 18:28:08 +04:00
|
|
|
soisdisconnected(so);
|
1993-04-09 16:00:07 +04:00
|
|
|
iso_pcbdisconnect(isop);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PRU_SHUTDOWN:
|
|
|
|
socantsendmore(so);
|
|
|
|
break;
|
|
|
|
|
1996-09-08 18:28:08 +04:00
|
|
|
case PRU_RCVD:
|
|
|
|
error = EOPNOTSUPP;
|
|
|
|
break;
|
|
|
|
|
1993-04-09 16:00:07 +04:00
|
|
|
case PRU_SEND:
|
1996-09-08 18:28:08 +04:00
|
|
|
if (control && control->m_len) {
|
|
|
|
m_freem(control);
|
|
|
|
m_freem(m);
|
|
|
|
error = EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
1993-04-09 16:00:07 +04:00
|
|
|
if (nam) {
|
1996-09-08 18:28:08 +04:00
|
|
|
if ((so->so_state & SS_ISCONNECTED) != 0) {
|
1993-04-09 16:00:07 +04:00
|
|
|
error = EISCONN;
|
1996-09-08 18:28:08 +04:00
|
|
|
goto die;
|
1993-04-09 16:00:07 +04:00
|
|
|
}
|
2006-07-24 02:06:03 +04:00
|
|
|
error = iso_pcbconnect(isop, nam, l);
|
1993-04-09 16:00:07 +04:00
|
|
|
if (error) {
|
1996-09-08 18:28:08 +04:00
|
|
|
die:
|
|
|
|
m_freem(m);
|
1993-04-09 16:00:07 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
1996-09-08 18:28:08 +04:00
|
|
|
if ((so->so_state & SS_ISCONNECTED) == 0) {
|
1993-04-09 16:00:07 +04:00
|
|
|
error = ENOTCONN;
|
1996-09-08 18:28:08 +04:00
|
|
|
goto die;
|
1993-04-09 16:00:07 +04:00
|
|
|
}
|
|
|
|
}
|
1996-02-14 01:07:57 +03:00
|
|
|
error = cltp_output(m, isop);
|
1996-09-08 18:28:08 +04:00
|
|
|
if (nam)
|
1993-04-09 16:00:07 +04:00
|
|
|
iso_pcbdisconnect(isop);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PRU_SENSE:
|
|
|
|
/*
|
|
|
|
* stat: don't bother with a blocksize.
|
|
|
|
*/
|
1996-09-08 18:28:08 +04:00
|
|
|
splx(s);
|
1993-04-09 16:00:07 +04:00
|
|
|
return (0);
|
|
|
|
|
1996-09-08 18:28:08 +04:00
|
|
|
case PRU_RCVOOB:
|
|
|
|
error = EOPNOTSUPP;
|
|
|
|
break;
|
|
|
|
|
1993-04-09 16:00:07 +04:00
|
|
|
case PRU_SENDOOB:
|
1996-09-08 18:28:08 +04:00
|
|
|
m_freem(control);
|
|
|
|
m_freem(m);
|
1996-02-14 01:07:57 +03:00
|
|
|
error = EOPNOTSUPP;
|
1993-04-09 16:00:07 +04:00
|
|
|
break;
|
|
|
|
|
1996-09-08 18:28:08 +04:00
|
|
|
case PRU_SOCKADDR:
|
|
|
|
iso_getnetaddr(isop, nam, TP_LOCAL);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PRU_PEERADDR:
|
|
|
|
iso_getnetaddr(isop, nam, TP_FOREIGN);
|
|
|
|
break;
|
1993-04-09 16:00:07 +04:00
|
|
|
|
|
|
|
default:
|
|
|
|
panic("cltp_usrreq");
|
|
|
|
}
|
1996-09-08 18:28:08 +04:00
|
|
|
|
1993-04-09 16:00:07 +04:00
|
|
|
release:
|
1996-09-08 18:28:08 +04:00
|
|
|
splx(s);
|
1993-04-09 16:00:07 +04:00
|
|
|
return (error);
|
|
|
|
}
|