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