1 /* $NetBSD: cltp_usrreq.c,v 1.23 2003/09/30 00:01:18 christos Exp $ */
2
3 /*
4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
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.
18 *
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.
30 *
31 * @(#)cltp_usrreq.c 8.1 (Berkeley) 6/10/93
32 */
33
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: cltp_usrreq.c,v 1.23 2003/09/30 00:01:18 christos Exp $");
36
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
48 #include <net/if.h>
49 #include <net/route.h>
50
51 #include <netiso/argo_debug.h>
52 #include <netiso/iso.h>
53 #include <netiso/iso_pcb.h>
54 #include <netiso/iso_var.h>
55 #include <netiso/clnp.h>
56 #include <netiso/cltp_var.h>
57 #include <netiso/tp_param.h>
58 #include <netiso/tp_var.h>
59
60 #include <machine/stdarg.h>
61 #endif
62
63
64 /*
65 * CLTP protocol implementation.
66 * Per ISO 8602, December, 1987.
67 */
68 void
69 cltp_init()
70 {
71
72 cltb.isop_next = cltb.isop_prev = &cltb;
73 }
74
75 int cltp_cksum = 1;
76 struct isopcb cltb;
77 struct cltpstat cltpstat;
78
79
80 /* ARGUSED */
81 void
82 #if __STDC__
83 cltp_input(struct mbuf *m0, ...)
84 #else
85 cltp_input(m0, va_alist)
86 struct mbuf *m0;
87 va_dcl
88 #endif
89 {
90 struct sockaddr *srcsa, *dstsa;
91 u_int cons_channel;
92 struct isopcb *isop;
93 struct mbuf *m = m0;
94 struct mbuf *m_src = 0;
95 u_char *up = mtod(m, u_char *);
96 struct sockaddr_iso *src;
97 int len, hdrlen = *up + 1, dlen = 0;
98 u_char *uplim = up + hdrlen;
99 caddr_t dtsap = NULL;
100 va_list ap;
101
102 va_start(ap, m0);
103 srcsa = va_arg(ap, struct sockaddr *);
104 dstsa = va_arg(ap, struct sockaddr *);
105 cons_channel = va_arg(ap, int);
106 va_end(ap);
107 src = satosiso(srcsa);
108
109 for (len = 0; m; m = m->m_next)
110 len += m->m_len;
111 up += 2; /* skip header */
112 while (up < uplim)
113 switch (*up) { /* process options */
114 case CLTPOVAL_SRC:
115 src->siso_tlen = up[1];
116 src->siso_len = up[1] + TSEL(src) - (caddr_t) src;
117 if (src->siso_len < sizeof(*src))
118 src->siso_len = sizeof(*src);
119 else if (src->siso_len > sizeof(*src)) {
120 MGET(m_src, M_DONTWAIT, MT_SONAME);
121 if (m_src == 0)
122 goto bad;
123 m_src->m_len = src->siso_len;
124 src = mtod(m_src, struct sockaddr_iso *);
125 bcopy((caddr_t) srcsa, (caddr_t) src, srcsa->sa_len);
126 }
127 bcopy((caddr_t) up + 2, TSEL(src), up[1]);
128 up += 2 + src->siso_tlen;
129 continue;
130
131 case CLTPOVAL_DST:
132 dtsap = 2 + (caddr_t) up;
133 dlen = up[1];
134 up += 2 + dlen;
135 continue;
136
137 case CLTPOVAL_CSM:
138 if (iso_check_csum(m0, len)) {
139 cltpstat.cltps_badsum++;
140 goto bad;
141 }
142 up += 4;
143 continue;
144
145 default:
146 printf("clts: unknown option (%x)\n", up[0]);
147 cltpstat.cltps_hdrops++;
148 goto bad;
149 }
150 if (dlen == 0 || src->siso_tlen == 0)
151 goto bad;
152 for (isop = cltb.isop_next;; isop = isop->isop_next) {
153 if (isop == &cltb) {
154 cltpstat.cltps_noport++;
155 goto bad;
156 }
157 if (isop->isop_laddr &&
158 bcmp(TSEL(isop->isop_laddr), dtsap, dlen) == 0)
159 break;
160 }
161 m = m0;
162 m->m_len -= hdrlen;
163 m->m_data += hdrlen;
164 if (sbappendaddr(&isop->isop_socket->so_rcv, sisotosa(src), m,
165 (struct mbuf *) 0) == 0)
166 goto bad;
167 cltpstat.cltps_ipackets++;
168 sorwakeup(isop->isop_socket);
169 m0 = 0;
170 bad:
171 if (src != satosiso(srcsa))
172 m_freem(m_src);
173 if (m0)
174 m_freem(m0);
175 }
176
177 /*
178 * Notify a cltp user of an asynchronous error;
179 * just wake up so that he can collect error status.
180 */
181 void
182 cltp_notify(isop)
183 struct isopcb *isop;
184 {
185
186 sorwakeup(isop->isop_socket);
187 sowwakeup(isop->isop_socket);
188 }
189
190 void
191 cltp_ctlinput(cmd, sa, dummy)
192 int cmd;
193 struct sockaddr *sa;
194 void *dummy;
195 {
196 extern u_char inetctlerrmap[];
197 struct sockaddr_iso *siso;
198
199 if ((unsigned)cmd >= PRC_NCMDS)
200 return;
201 if (sa->sa_family != AF_ISO && sa->sa_family != AF_CCITT)
202 return;
203 siso = satosiso(sa);
204 if (siso == 0 || siso->siso_nlen == 0)
205 return;
206
207 switch (cmd) {
208 case PRC_ROUTEDEAD:
209 case PRC_REDIRECT_NET:
210 case PRC_REDIRECT_HOST:
211 case PRC_REDIRECT_TOSNET:
212 case PRC_REDIRECT_TOSHOST:
213 iso_pcbnotify(&cltb, siso,
214 (int) inetctlerrmap[cmd], iso_rtchange);
215 break;
216
217 default:
218 if (inetctlerrmap[cmd] == 0)
219 return; /* XXX */
220 iso_pcbnotify(&cltb, siso, (int) inetctlerrmap[cmd],
221 cltp_notify);
222 }
223 }
224
225 int
226 #if __STDC__
227 cltp_output(struct mbuf *m, ...)
228 #else
229 cltp_output(m, va_alist)
230 struct mbuf *m;
231 va_dcl
232 #endif
233 {
234 struct isopcb *isop;
235 int len;
236 struct sockaddr_iso *siso;
237 int hdrlen, error = 0, docsum;
238 u_char *up;
239 va_list ap;
240
241 va_start(ap, m);
242 isop = va_arg(ap, struct isopcb *);
243 va_end(ap);
244
245 if (isop->isop_laddr == 0 || isop->isop_faddr == 0) {
246 error = ENOTCONN;
247 goto bad;
248 }
249 /*
250 * Calculate data length and get a mbuf for CLTP header.
251 */
252 hdrlen = 2 + 2 + isop->isop_laddr->siso_tlen
253 + 2 + isop->isop_faddr->siso_tlen;
254 docsum = /* isop->isop_flags & CLNP_NO_CKSUM */ cltp_cksum;
255 if (docsum)
256 hdrlen += 4;
257 M_PREPEND(m, hdrlen, M_WAIT);
258 len = m->m_pkthdr.len;
259 /*
260 * Fill in mbuf with extended CLTP header
261 */
262 up = mtod(m, u_char *);
263 up[0] = hdrlen - 1;
264 up[1] = UD_TPDU_type;
265 up[2] = CLTPOVAL_SRC;
266 up[3] = (siso = isop->isop_laddr)->siso_tlen;
267 up += 4;
268 bcopy(TSEL(siso), (caddr_t) up, siso->siso_tlen);
269 up += siso->siso_tlen;
270 up[0] = CLTPOVAL_DST;
271 up[1] = (siso = isop->isop_faddr)->siso_tlen;
272 up += 2;
273 bcopy(TSEL(siso), (caddr_t) up, siso->siso_tlen);
274 /*
275 * Stuff checksum and output datagram.
276 */
277 if (docsum) {
278 up += siso->siso_tlen;
279 up[0] = CLTPOVAL_CSM;
280 up[1] = 2;
281 iso_gen_csum(m, 2 + up - mtod(m, u_char *), len);
282 }
283 cltpstat.cltps_opackets++;
284 return (tpclnp_output(m, len, isop, !docsum));
285 bad:
286 m_freem(m);
287 return (error);
288 }
289
290 u_long cltp_sendspace = 9216; /* really max datagram size */
291 u_long cltp_recvspace = 40 * (1024 + sizeof(struct sockaddr_iso));
292 /* 40 1K datagrams */
293
294
295 /* ARGSUSED */
296 int
297 cltp_usrreq(so, req, m, nam, control, p)
298 struct socket *so;
299 int req;
300 struct mbuf *m, *nam, *control;
301 struct proc *p;
302 {
303 struct isopcb *isop;
304 int s;
305 int error = 0;
306
307 if (req == PRU_CONTROL)
308 return (iso_control(so, (long)m, (caddr_t)nam,
309 (struct ifnet *)control, p));
310
311 if (req == PRU_PURGEIF) {
312 iso_purgeif((struct ifnet *)control);
313 return (0);
314 }
315
316 s = splsoftnet();
317 isop = sotoisopcb(so);
318 #ifdef DIAGNOSTIC
319 if (req != PRU_SEND && req != PRU_SENDOOB && control)
320 panic("cltp_usrreq: unexpected control mbuf");
321 #endif
322 if (isop == 0 && req != PRU_ATTACH) {
323 error = EINVAL;
324 goto release;
325 }
326
327 switch (req) {
328
329 case PRU_ATTACH:
330 if (isop != 0) {
331 error = EISCONN;
332 break;
333 }
334 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
335 error = soreserve(so, cltp_sendspace, cltp_recvspace);
336 if (error)
337 break;
338 }
339 error = iso_pcballoc(so, &cltb);
340 if (error)
341 break;
342 break;
343
344 case PRU_DETACH:
345 iso_pcbdetach(isop);
346 break;
347
348 case PRU_BIND:
349 error = iso_pcbbind(isop, nam, p);
350 break;
351
352 case PRU_LISTEN:
353 error = EOPNOTSUPP;
354 break;
355
356 case PRU_CONNECT:
357 error = iso_pcbconnect(isop, nam);
358 if (error)
359 break;
360 soisconnected(so);
361 break;
362
363 case PRU_CONNECT2:
364 error = EOPNOTSUPP;
365 break;
366
367 case PRU_DISCONNECT:
368 soisdisconnected(so);
369 iso_pcbdisconnect(isop);
370 break;
371
372 case PRU_SHUTDOWN:
373 socantsendmore(so);
374 break;
375
376 case PRU_RCVD:
377 error = EOPNOTSUPP;
378 break;
379
380 case PRU_SEND:
381 if (control && control->m_len) {
382 m_freem(control);
383 m_freem(m);
384 error = EINVAL;
385 break;
386 }
387 if (nam) {
388 if ((so->so_state & SS_ISCONNECTED) != 0) {
389 error = EISCONN;
390 goto die;
391 }
392 error = iso_pcbconnect(isop, nam);
393 if (error) {
394 die:
395 m_freem(m);
396 break;
397 }
398 } else {
399 if ((so->so_state & SS_ISCONNECTED) == 0) {
400 error = ENOTCONN;
401 goto die;
402 }
403 }
404 error = cltp_output(m, isop);
405 if (nam)
406 iso_pcbdisconnect(isop);
407 break;
408
409 case PRU_SENSE:
410 /*
411 * stat: don't bother with a blocksize.
412 */
413 splx(s);
414 return (0);
415
416 case PRU_RCVOOB:
417 error = EOPNOTSUPP;
418 break;
419
420 case PRU_SENDOOB:
421 m_freem(control);
422 m_freem(m);
423 error = EOPNOTSUPP;
424 break;
425
426 case PRU_SOCKADDR:
427 iso_getnetaddr(isop, nam, TP_LOCAL);
428 break;
429
430 case PRU_PEERADDR:
431 iso_getnetaddr(isop, nam, TP_FOREIGN);
432 break;
433
434 default:
435 panic("cltp_usrreq");
436 }
437
438 release:
439 splx(s);
440 return (error);
441 }
Cache object: 94973cef7a9628d1e4daab1002c39c9f
|