1 /* $NetBSD: cltp_usrreq.c,v 1.39 2009/03/18 17:06:52 cegger Exp $ */
4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * @(#)cltp_usrreq.c 8.1 (Berkeley) 6/10/93
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: cltp_usrreq.c,v 1.39 2009/03/18 17:06:52 cegger Exp $");
37 #ifndef CLTPOVAL_SRC /* XXX -- till files gets changed */
38 #include <sys/param.h>
39 #include <sys/malloc.h>
41 #include <sys/protosw.h>
42 #include <sys/socket.h>
43 #include <sys/socketvar.h>
44 #include <sys/errno.h>
46 #include <sys/systm.h>
50 #include <net/route.h>
52 #include <netiso/argo_debug.h>
53 #include <netiso/iso.h>
54 #include <netiso/iso_pcb.h>
55 #include <netiso/iso_var.h>
56 #include <netiso/clnp.h>
57 #include <netiso/cltp_var.h>
58 #include <netiso/tp_param.h>
59 #include <netiso/tp_var.h>
61 #include <machine/stdarg.h>
66 * CLTP protocol implementation.
67 * Per ISO 8602, December, 1987.
73 cltb
.isop_next
= cltb
.isop_prev
= &cltb
;
78 struct cltpstat cltpstat
;
83 cltp_input(struct mbuf
*m0
, ...)
85 struct sockaddr
*srcsa
, *dstsa
;
89 struct mbuf
*m_src
= 0;
90 u_char
*up
= mtod(m
, u_char
*);
91 struct sockaddr_iso
*src
;
92 int len
, hdrlen
= *up
+ 1, dlen
= 0;
93 u_char
*uplim
= up
+ hdrlen
;
98 srcsa
= va_arg(ap
, struct sockaddr
*);
99 dstsa
= va_arg(ap
, struct sockaddr
*);
100 cons_channel
= va_arg(ap
, int);
102 src
= satosiso(srcsa
);
104 for (len
= 0; m
; m
= m
->m_next
)
106 up
+= 2; /* skip header */
108 switch (*up
) { /* process options */
110 src
->siso_tlen
= up
[1];
111 src
->siso_len
= up
[1] +
112 ((const char *)TSEL(src
) - (const char *)src
);
113 if (src
->siso_len
< sizeof(*src
))
114 src
->siso_len
= sizeof(*src
);
115 else if (src
->siso_len
> sizeof(*src
)) {
116 MGET(m_src
, M_DONTWAIT
, MT_SONAME
);
119 m_src
->m_len
= src
->siso_len
;
120 src
= mtod(m_src
, struct sockaddr_iso
*);
121 memcpy((void *) src
, (void *) srcsa
, srcsa
->sa_len
);
123 memcpy(WRITABLE_TSEL(src
), (char *)up
+ 2, up
[1]);
124 up
+= 2 + src
->siso_tlen
;
128 dtsap
= 2 + (char *)up
;
134 if (iso_check_csum(m0
, len
)) {
135 cltpstat
.cltps_badsum
++;
142 printf("clts: unknown option (%x)\n", up
[0]);
143 cltpstat
.cltps_hdrops
++;
146 if (dlen
== 0 || src
->siso_tlen
== 0)
148 for (isop
= cltb
.isop_next
;; isop
= isop
->isop_next
) {
150 cltpstat
.cltps_noport
++;
153 if (isop
->isop_laddr
&&
154 memcmp(TSEL(isop
->isop_laddr
), dtsap
, dlen
) == 0)
160 if (sbappendaddr(&isop
->isop_socket
->so_rcv
, sisotosa(src
), m
,
161 (struct mbuf
*) 0) == 0)
163 cltpstat
.cltps_ipackets
++;
164 sorwakeup(isop
->isop_socket
);
167 if (src
!= satosiso(srcsa
))
174 * Notify a cltp user of an asynchronous error;
175 * just wake up so that he can collect error status.
178 cltp_notify(struct isopcb
*isop
)
181 sorwakeup(isop
->isop_socket
);
182 sowwakeup(isop
->isop_socket
);
188 const struct sockaddr
*sa
,
191 const struct sockaddr_iso
*siso
;
193 if ((unsigned)cmd
>= PRC_NCMDS
)
195 if (sa
->sa_family
!= AF_ISO
&& sa
->sa_family
!= AF_CCITT
)
197 siso
= satocsiso(sa
);
198 if (siso
== 0 || siso
->siso_nlen
== 0)
203 case PRC_REDIRECT_NET
:
204 case PRC_REDIRECT_HOST
:
205 case PRC_REDIRECT_TOSNET
:
206 case PRC_REDIRECT_TOSHOST
:
207 iso_pcbnotify(&cltb
, siso
,
208 (int) isoctlerrmap
[cmd
], iso_rtchange
);
212 if (isoctlerrmap
[cmd
] == 0)
214 iso_pcbnotify(&cltb
, siso
, (int) isoctlerrmap
[cmd
],
220 cltp_output(struct mbuf
*m
, ...)
224 struct sockaddr_iso
*siso
;
225 int hdrlen
, error
= 0, docsum
;
230 isop
= va_arg(ap
, struct isopcb
*);
233 if (isop
->isop_laddr
== 0 || isop
->isop_faddr
== 0) {
238 * Calculate data length and get a mbuf for CLTP header.
240 hdrlen
= 2 + 2 + isop
->isop_laddr
->siso_tlen
241 + 2 + isop
->isop_faddr
->siso_tlen
;
242 docsum
= /* isop->isop_flags & CLNP_NO_CKSUM */ cltp_cksum
;
245 M_PREPEND(m
, hdrlen
, M_WAIT
);
246 len
= m
->m_pkthdr
.len
;
248 * Fill in mbuf with extended CLTP header
250 up
= mtod(m
, u_char
*);
252 up
[1] = UD_TPDU_type
;
253 up
[2] = CLTPOVAL_SRC
;
254 up
[3] = (siso
= isop
->isop_laddr
)->siso_tlen
;
256 memcpy((void *) up
, TSEL(siso
), siso
->siso_tlen
);
257 up
+= siso
->siso_tlen
;
258 up
[0] = CLTPOVAL_DST
;
259 up
[1] = (siso
= isop
->isop_faddr
)->siso_tlen
;
261 memcpy((void *) up
, TSEL(siso
), siso
->siso_tlen
);
263 * Stuff checksum and output datagram.
266 up
+= siso
->siso_tlen
;
267 up
[0] = CLTPOVAL_CSM
;
269 iso_gen_csum(m
, 2 + up
- mtod(m
, u_char
*), len
);
271 cltpstat
.cltps_opackets
++;
272 return (tpclnp_output(m
, len
, isop
, !docsum
));
278 u_long cltp_sendspace
= 9216; /* really max datagram size */
279 u_long cltp_recvspace
= 40 * (1024 + sizeof(struct sockaddr_iso
));
280 /* 40 1K datagrams */
285 cltp_usrreq(struct socket
*so
, int req
, struct mbuf
*m
, struct mbuf
*nam
, struct mbuf
*control
, struct lwp
*l
)
291 if (req
== PRU_CONTROL
)
292 return (iso_control(so
, (long)m
, (void *)nam
,
293 (struct ifnet
*)control
, l
));
295 if (req
== PRU_PURGEIF
) {
296 mutex_enter(softnet_lock
);
297 iso_purgeif((struct ifnet
*)control
);
298 mutex_exit(softnet_lock
);
303 isop
= sotoisopcb(so
);
305 if (req
!= PRU_SEND
&& req
!= PRU_SENDOOB
&& control
)
306 panic("cltp_usrreq: unexpected control mbuf");
308 if (isop
== 0 && req
!= PRU_ATTACH
) {
321 if (so
->so_snd
.sb_hiwat
== 0 || so
->so_rcv
.sb_hiwat
== 0) {
322 error
= soreserve(so
, cltp_sendspace
, cltp_recvspace
);
326 error
= iso_pcballoc(so
, &cltb
);
336 error
= iso_pcbbind(isop
, nam
, l
);
344 error
= iso_pcbconnect(isop
, nam
, l
);
355 soisdisconnected(so
);
356 iso_pcbdisconnect(isop
);
368 if (control
&& control
->m_len
) {
375 if ((so
->so_state
& SS_ISCONNECTED
) != 0) {
379 error
= iso_pcbconnect(isop
, nam
, l
);
386 if ((so
->so_state
& SS_ISCONNECTED
) == 0) {
391 error
= cltp_output(m
, isop
);
393 iso_pcbdisconnect(isop
);
398 * stat: don't bother with a blocksize.
414 iso_getnetaddr(isop
, nam
, TP_LOCAL
);
418 iso_getnetaddr(isop
, nam
, TP_FOREIGN
);
422 panic("cltp_usrreq");