linux32_sys_ptrace() fixes.
[netbsd-mini2440.git] / sys / netiso / cltp_usrreq.c
bloba4123ef7d02feb960078029d6cb10b8935e9caf2
1 /* $NetBSD: cltp_usrreq.c,v 1.33 2008/04/24 11:38:38 ad Exp $ */
3 /*
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
9 * are met:
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
29 * SUCH DAMAGE.
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.33 2008/04/24 11:38:38 ad Exp $");
37 #ifndef CLTPOVAL_SRC /* XXX -- till files gets changed */
38 #include <sys/param.h>
39 #include <sys/malloc.h>
40 #include <sys/mbuf.h>
41 #include <sys/protosw.h>
42 #include <sys/socket.h>
43 #include <sys/socketvar.h>
44 #include <sys/errno.h>
45 #include <sys/stat.h>
46 #include <sys/systm.h>
47 #include <sys/proc.h>
49 #include <net/if.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>
62 #endif
66 * CLTP protocol implementation.
67 * Per ISO 8602, December, 1987.
69 void
70 cltp_init()
73 cltb.isop_next = cltb.isop_prev = &cltb;
76 int cltp_cksum = 1;
77 struct isopcb cltb;
78 struct cltpstat cltpstat;
81 /* ARGUSED */
82 void
83 cltp_input(struct mbuf *m0, ...)
85 struct sockaddr *srcsa, *dstsa;
86 u_int cons_channel;
87 struct isopcb *isop;
88 struct mbuf *m = m0;
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;
94 void * dtsap = NULL;
95 va_list ap;
97 va_start(ap, m0);
98 srcsa = va_arg(ap, struct sockaddr *);
99 dstsa = va_arg(ap, struct sockaddr *);
100 cons_channel = va_arg(ap, int);
101 va_end(ap);
102 src = satosiso(srcsa);
104 for (len = 0; m; m = m->m_next)
105 len += m->m_len;
106 up += 2; /* skip header */
107 while (up < uplim)
108 switch (*up) { /* process options */
109 case CLTPOVAL_SRC:
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);
117 if (m_src == 0)
118 goto bad;
119 m_src->m_len = src->siso_len;
120 src = mtod(m_src, struct sockaddr_iso *);
121 bcopy((void *) srcsa, (void *) src, srcsa->sa_len);
123 memcpy(WRITABLE_TSEL(src), (char *)up + 2, up[1]);
124 up += 2 + src->siso_tlen;
125 continue;
127 case CLTPOVAL_DST:
128 dtsap = 2 + (char *)up;
129 dlen = up[1];
130 up += 2 + dlen;
131 continue;
133 case CLTPOVAL_CSM:
134 if (iso_check_csum(m0, len)) {
135 cltpstat.cltps_badsum++;
136 goto bad;
138 up += 4;
139 continue;
141 default:
142 printf("clts: unknown option (%x)\n", up[0]);
143 cltpstat.cltps_hdrops++;
144 goto bad;
146 if (dlen == 0 || src->siso_tlen == 0)
147 goto bad;
148 for (isop = cltb.isop_next;; isop = isop->isop_next) {
149 if (isop == &cltb) {
150 cltpstat.cltps_noport++;
151 goto bad;
153 if (isop->isop_laddr &&
154 bcmp(TSEL(isop->isop_laddr), dtsap, dlen) == 0)
155 break;
157 m = m0;
158 m->m_len -= hdrlen;
159 m->m_data += hdrlen;
160 if (sbappendaddr(&isop->isop_socket->so_rcv, sisotosa(src), m,
161 (struct mbuf *) 0) == 0)
162 goto bad;
163 cltpstat.cltps_ipackets++;
164 sorwakeup(isop->isop_socket);
165 m0 = 0;
166 bad:
167 if (src != satosiso(srcsa))
168 m_freem(m_src);
169 if (m0)
170 m_freem(m0);
174 * Notify a cltp user of an asynchronous error;
175 * just wake up so that he can collect error status.
177 void
178 cltp_notify(isop)
179 struct isopcb *isop;
182 sorwakeup(isop->isop_socket);
183 sowwakeup(isop->isop_socket);
186 void
187 cltp_ctlinput(
188 int cmd,
189 const struct sockaddr *sa,
190 void *dummy)
192 const struct sockaddr_iso *siso;
194 if ((unsigned)cmd >= PRC_NCMDS)
195 return;
196 if (sa->sa_family != AF_ISO && sa->sa_family != AF_CCITT)
197 return;
198 siso = satocsiso(sa);
199 if (siso == 0 || siso->siso_nlen == 0)
200 return;
202 switch (cmd) {
203 case PRC_ROUTEDEAD:
204 case PRC_REDIRECT_NET:
205 case PRC_REDIRECT_HOST:
206 case PRC_REDIRECT_TOSNET:
207 case PRC_REDIRECT_TOSHOST:
208 iso_pcbnotify(&cltb, siso,
209 (int) isoctlerrmap[cmd], iso_rtchange);
210 break;
212 default:
213 if (isoctlerrmap[cmd] == 0)
214 return; /* XXX */
215 iso_pcbnotify(&cltb, siso, (int) isoctlerrmap[cmd],
216 cltp_notify);
221 cltp_output(struct mbuf *m, ...)
223 struct isopcb *isop;
224 int len;
225 struct sockaddr_iso *siso;
226 int hdrlen, error = 0, docsum;
227 u_char *up;
228 va_list ap;
230 va_start(ap, m);
231 isop = va_arg(ap, struct isopcb *);
232 va_end(ap);
234 if (isop->isop_laddr == 0 || isop->isop_faddr == 0) {
235 error = ENOTCONN;
236 goto bad;
239 * Calculate data length and get a mbuf for CLTP header.
241 hdrlen = 2 + 2 + isop->isop_laddr->siso_tlen
242 + 2 + isop->isop_faddr->siso_tlen;
243 docsum = /* isop->isop_flags & CLNP_NO_CKSUM */ cltp_cksum;
244 if (docsum)
245 hdrlen += 4;
246 M_PREPEND(m, hdrlen, M_WAIT);
247 len = m->m_pkthdr.len;
249 * Fill in mbuf with extended CLTP header
251 up = mtod(m, u_char *);
252 up[0] = hdrlen - 1;
253 up[1] = UD_TPDU_type;
254 up[2] = CLTPOVAL_SRC;
255 up[3] = (siso = isop->isop_laddr)->siso_tlen;
256 up += 4;
257 bcopy(TSEL(siso), (void *) up, siso->siso_tlen);
258 up += siso->siso_tlen;
259 up[0] = CLTPOVAL_DST;
260 up[1] = (siso = isop->isop_faddr)->siso_tlen;
261 up += 2;
262 bcopy(TSEL(siso), (void *) up, siso->siso_tlen);
264 * Stuff checksum and output datagram.
266 if (docsum) {
267 up += siso->siso_tlen;
268 up[0] = CLTPOVAL_CSM;
269 up[1] = 2;
270 iso_gen_csum(m, 2 + up - mtod(m, u_char *), len);
272 cltpstat.cltps_opackets++;
273 return (tpclnp_output(m, len, isop, !docsum));
274 bad:
275 m_freem(m);
276 return (error);
279 u_long cltp_sendspace = 9216; /* really max datagram size */
280 u_long cltp_recvspace = 40 * (1024 + sizeof(struct sockaddr_iso));
281 /* 40 1K datagrams */
284 /* ARGSUSED */
286 cltp_usrreq(so, req, m, nam, control, l)
287 struct socket *so;
288 int req;
289 struct mbuf *m, *nam, *control;
290 struct lwp *l;
292 struct isopcb *isop;
293 int s;
294 int error = 0;
296 if (req == PRU_CONTROL)
297 return (iso_control(so, (long)m, (void *)nam,
298 (struct ifnet *)control, l));
300 if (req == PRU_PURGEIF) {
301 mutex_enter(softnet_lock);
302 iso_purgeif((struct ifnet *)control);
303 mutex_exit(softnet_lock);
304 return (0);
307 s = splsoftnet();
308 isop = sotoisopcb(so);
309 #ifdef DIAGNOSTIC
310 if (req != PRU_SEND && req != PRU_SENDOOB && control)
311 panic("cltp_usrreq: unexpected control mbuf");
312 #endif
313 if (isop == 0 && req != PRU_ATTACH) {
314 error = EINVAL;
315 goto release;
318 switch (req) {
320 case PRU_ATTACH:
321 sosetlock(so);
322 if (isop != 0) {
323 error = EISCONN;
324 break;
326 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
327 error = soreserve(so, cltp_sendspace, cltp_recvspace);
328 if (error)
329 break;
331 error = iso_pcballoc(so, &cltb);
332 if (error)
333 break;
334 break;
336 case PRU_DETACH:
337 iso_pcbdetach(isop);
338 break;
340 case PRU_BIND:
341 error = iso_pcbbind(isop, nam, l);
342 break;
344 case PRU_LISTEN:
345 error = EOPNOTSUPP;
346 break;
348 case PRU_CONNECT:
349 error = iso_pcbconnect(isop, nam, l);
350 if (error)
351 break;
352 soisconnected(so);
353 break;
355 case PRU_CONNECT2:
356 error = EOPNOTSUPP;
357 break;
359 case PRU_DISCONNECT:
360 soisdisconnected(so);
361 iso_pcbdisconnect(isop);
362 break;
364 case PRU_SHUTDOWN:
365 socantsendmore(so);
366 break;
368 case PRU_RCVD:
369 error = EOPNOTSUPP;
370 break;
372 case PRU_SEND:
373 if (control && control->m_len) {
374 m_freem(control);
375 m_freem(m);
376 error = EINVAL;
377 break;
379 if (nam) {
380 if ((so->so_state & SS_ISCONNECTED) != 0) {
381 error = EISCONN;
382 goto die;
384 error = iso_pcbconnect(isop, nam, l);
385 if (error) {
386 die:
387 m_freem(m);
388 break;
390 } else {
391 if ((so->so_state & SS_ISCONNECTED) == 0) {
392 error = ENOTCONN;
393 goto die;
396 error = cltp_output(m, isop);
397 if (nam)
398 iso_pcbdisconnect(isop);
399 break;
401 case PRU_SENSE:
403 * stat: don't bother with a blocksize.
405 splx(s);
406 return (0);
408 case PRU_RCVOOB:
409 error = EOPNOTSUPP;
410 break;
412 case PRU_SENDOOB:
413 m_freem(control);
414 m_freem(m);
415 error = EOPNOTSUPP;
416 break;
418 case PRU_SOCKADDR:
419 iso_getnetaddr(isop, nam, TP_LOCAL);
420 break;
422 case PRU_PEERADDR:
423 iso_getnetaddr(isop, nam, TP_FOREIGN);
424 break;
426 default:
427 panic("cltp_usrreq");
430 release:
431 splx(s);
432 return (error);