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