]> git.saurik.com Git - apple/xnu.git/blob - bsd/netiso/cltp_usrreq.c
xnu-123.5.tar.gz
[apple/xnu.git] / bsd / netiso / cltp_usrreq.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /*
23 * Copyright (c) 1989, 1993
24 * The Regents of the University of California. All rights reserved.
25 *
26 * Redistribution and use in source and binary forms, with or without
27 * modification, are permitted provided that the following conditions
28 * are met:
29 * 1. Redistributions of source code must retain the above copyright
30 * notice, this list of conditions and the following disclaimer.
31 * 2. Redistributions in binary form must reproduce the above copyright
32 * notice, this list of conditions and the following disclaimer in the
33 * documentation and/or other materials provided with the distribution.
34 * 3. All advertising materials mentioning features or use of this software
35 * must display the following acknowledgement:
36 * This product includes software developed by the University of
37 * California, Berkeley and its contributors.
38 * 4. Neither the name of the University nor the names of its contributors
39 * may be used to endorse or promote products derived from this software
40 * without specific prior written permission.
41 *
42 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
43 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
46 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52 * SUCH DAMAGE.
53 *
54 * @(#)cltp_usrreq.c 8.1 (Berkeley) 6/10/93
55 */
56
57 #ifndef CLTPOVAL_SRC /* XXX -- till files gets changed */
58 #include <sys/param.h>
59 #include <sys/malloc.h>
60 #include <sys/mbuf.h>
61 #include <sys/protosw.h>
62 #include <sys/socket.h>
63 #include <sys/socketvar.h>
64 #include <sys/errno.h>
65 #include <sys/stat.h>
66
67 #include <net/if.h>
68 #include <net/route.h>
69
70 #include <netiso/argo_debug.h>
71 #include <netiso/iso.h>
72 #include <netiso/iso_pcb.h>
73 #include <netiso/iso_var.h>
74 #include <netiso/clnp.h>
75 #include <netiso/cltp_var.h>
76 #endif
77
78 /*
79 * CLTP protocol implementation.
80 * Per ISO 8602, December, 1987.
81 */
82 cltp_init()
83 {
84
85 cltb.isop_next = cltb.isop_prev = &cltb;
86 }
87
88 int cltp_cksum = 1;
89
90
91 /* ARGUSED */
92 cltp_input(m0, srcsa, dstsa, cons_channel, output)
93 struct mbuf *m0;
94 struct sockaddr *srcsa, *dstsa;
95 u_int cons_channel;
96 int (*output)();
97 {
98 register struct isopcb *isop;
99 register struct mbuf *m = m0;
100 register u_char *up = mtod(m, u_char *);
101 register struct sockaddr_iso *src = (struct sockaddr_iso *)srcsa;
102 int len, hdrlen = *up + 1, dlen = 0;
103 u_char *uplim = up + hdrlen;
104 caddr_t dtsap;
105
106 for (len = 0; m; m = m->m_next)
107 len += m->m_len;
108 up += 2; /* skip header */
109 while (up < uplim) switch (*up) { /* process options */
110 case CLTPOVAL_SRC:
111 src->siso_tlen = up[1];
112 src->siso_len = up[1] + TSEL(src) - (caddr_t)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, M_DONTWAIT, MT_SONAME);
117 if (m == 0)
118 goto bad;
119 m->m_len = src->siso_len;
120 src = mtod(m, struct sockaddr_iso *);
121 bcopy((caddr_t)srcsa, (caddr_t)src, srcsa->sa_len);
122 }
123 bcopy((caddr_t)up + 2, TSEL(src), up[1]);
124 up += 2 + src->siso_tlen;
125 continue;
126
127 case CLTPOVAL_DST:
128 dtsap = 2 + (caddr_t)up;
129 dlen = up[1];
130 up += 2 + dlen;
131 continue;
132
133 case CLTPOVAL_CSM:
134 if (iso_check_csum(m0, len)) {
135 cltpstat.cltps_badsum++;
136 goto bad;
137 }
138 up += 4;
139 continue;
140
141 default:
142 printf("clts: unknown option (%x)\n", up[0]);
143 cltpstat.cltps_hdrops++;
144 goto bad;
145 }
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;
152 }
153 if (isop->isop_laddr &&
154 bcmp(TSEL(isop->isop_laddr), dtsap, dlen) == 0)
155 break;
156 }
157 m = m0;
158 m->m_len -= hdrlen;
159 m->m_data += hdrlen;
160 if (sbappendaddr(&isop->isop_socket->so_rcv, (struct sockaddr *)src,
161 m, (struct mbuf *)0) == 0)
162 goto bad;
163 cltpstat.cltps_ipackets++;
164 sorwakeup(isop->isop_socket);
165 m0 = 0;
166 bad:
167 if (src != (struct sockaddr_iso *)srcsa)
168 m_freem(dtom(src));
169 if (m0)
170 m_freem(m0);
171 return 0;
172 }
173
174 /*
175 * Notify a cltp user of an asynchronous error;
176 * just wake up so that he can collect error status.
177 */
178 cltp_notify(isop)
179 register struct isopcb *isop;
180 {
181
182 sorwakeup(isop->isop_socket);
183 sowwakeup(isop->isop_socket);
184 }
185
186 cltp_ctlinput(cmd, sa)
187 int cmd;
188 struct sockaddr *sa;
189 {
190 extern u_char inetctlerrmap[];
191 struct sockaddr_iso *siso;
192 int iso_rtchange();
193
194 if ((unsigned)cmd > PRC_NCMDS)
195 return;
196 if (sa->sa_family != AF_ISO && sa->sa_family != AF_CCITT)
197 return;
198 siso = (struct sockaddr_iso *)sa;
199 if (siso == 0 || siso->siso_nlen == 0)
200 return;
201
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)inetctlerrmap[cmd], iso_rtchange);
210 break;
211
212 default:
213 if (inetctlerrmap[cmd] == 0)
214 return; /* XXX */
215 iso_pcbnotify(&cltb, siso, (int)inetctlerrmap[cmd],
216 cltp_notify);
217 }
218 }
219
220 cltp_output(isop, m)
221 register struct isopcb *isop;
222 register struct mbuf *m;
223 {
224 register int len;
225 register struct sockaddr_iso *siso;
226 int hdrlen, error = 0, docsum;
227 register u_char *up;
228
229 if (isop->isop_laddr == 0 || isop->isop_faddr == 0) {
230 error = ENOTCONN;
231 goto bad;
232 }
233 /*
234 * Calculate data length and get a mbuf for CLTP header.
235 */
236 hdrlen = 2 + 2 + isop->isop_laddr->siso_tlen
237 + 2 + isop->isop_faddr->siso_tlen;
238 if (docsum = /*isop->isop_flags & CLNP_NO_CKSUM*/ cltp_cksum)
239 hdrlen += 4;
240 M_PREPEND(m, hdrlen, M_WAIT);
241 len = m->m_pkthdr.len;
242 /*
243 * Fill in mbuf with extended CLTP header
244 */
245 up = mtod(m, u_char *);
246 up[0] = hdrlen - 1;
247 up[1] = UD_TPDU_type;
248 up[2] = CLTPOVAL_SRC;
249 up[3] = (siso = isop->isop_laddr)->siso_tlen;
250 up += 4;
251 bcopy(TSEL(siso), (caddr_t)up, siso->siso_tlen);
252 up += siso->siso_tlen;
253 up[0] = CLTPOVAL_DST;
254 up[1] = (siso = isop->isop_faddr)->siso_tlen;
255 up += 2;
256 bcopy(TSEL(siso), (caddr_t)up, siso->siso_tlen);
257 /*
258 * Stuff checksum and output datagram.
259 */
260 if (docsum) {
261 up += siso->siso_tlen;
262 up[0] = CLTPOVAL_CSM;
263 up[1] = 2;
264 iso_gen_csum(m, 2 + up - mtod(m, u_char *), len);
265 }
266 cltpstat.cltps_opackets++;
267 return (tpclnp_output(isop, m, len, !docsum));
268 bad:
269 m_freem(m);
270 return (error);
271 }
272
273 u_long cltp_sendspace = 9216; /* really max datagram size */
274 u_long cltp_recvspace = 40 * (1024 + sizeof(struct sockaddr_iso));
275 /* 40 1K datagrams */
276
277
278 /*ARGSUSED*/
279 cltp_usrreq(so, req, m, nam, control)
280 struct socket *so;
281 int req;
282 struct mbuf *m, *nam, *control;
283 {
284 register struct isopcb *isop = sotoisopcb(so);
285 int s, error = 0;
286
287 if (req == PRU_CONTROL)
288 return (iso_control(so, (int)m, (caddr_t)nam,
289 (struct ifnet *)control));
290 if ((isop == NULL && req != PRU_ATTACH) ||
291 (control && control->m_len)) {
292 error = EINVAL;
293 goto release;
294 }
295 switch (req) {
296
297 case PRU_ATTACH:
298 if (isop != NULL) {
299 error = EINVAL;
300 break;
301 }
302 error = iso_pcballoc(so, &cltb);
303 if (error)
304 break;
305 error = soreserve(so, cltp_sendspace, cltp_recvspace);
306 if (error)
307 break;
308 break;
309
310 case PRU_DETACH:
311 iso_pcbdetach(isop);
312 break;
313
314 case PRU_BIND:
315 error = iso_pcbbind(isop, nam);
316 break;
317
318 case PRU_LISTEN:
319 error = EOPNOTSUPP;
320 break;
321
322 case PRU_CONNECT:
323 if (isop->isop_faddr) {
324 error = EISCONN;
325 break;
326 }
327 error = iso_pcbconnect(isop, nam);
328 if (error == 0)
329 soisconnected(so);
330 break;
331
332 case PRU_CONNECT2:
333 error = EOPNOTSUPP;
334 break;
335
336 case PRU_ACCEPT:
337 error = EOPNOTSUPP;
338 break;
339
340 case PRU_DISCONNECT:
341 if (isop->isop_faddr == 0) {
342 error = ENOTCONN;
343 break;
344 }
345 iso_pcbdisconnect(isop);
346 so->so_state &= ~SS_ISCONNECTED; /* XXX */
347 break;
348
349 case PRU_SHUTDOWN:
350 socantsendmore(so);
351 break;
352
353 case PRU_SEND:
354 if (nam) {
355 if (isop->isop_faddr) {
356 error = EISCONN;
357 break;
358 }
359 /*
360 * Must block input while temporarily connected.
361 */
362 s = splnet();
363 error = iso_pcbconnect(isop, nam);
364 if (error) {
365 splx(s);
366 break;
367 }
368 } else {
369 if (isop->isop_faddr == 0) {
370 error = ENOTCONN;
371 break;
372 }
373 }
374 error = cltp_output(isop, m);
375 m = 0;
376 if (nam) {
377 iso_pcbdisconnect(isop);
378 splx(s);
379 }
380 break;
381
382 case PRU_ABORT:
383 soisdisconnected(so);
384 iso_pcbdetach(isop);
385 break;
386
387 case PRU_SOCKADDR:
388 if (isop->isop_laddr)
389 bcopy((caddr_t)isop->isop_laddr, mtod(m, caddr_t),
390 nam->m_len = isop->isop_laddr->siso_len);
391 break;
392
393 case PRU_PEERADDR:
394 if (isop->isop_faddr)
395 bcopy((caddr_t)isop->isop_faddr, mtod(m, caddr_t),
396 nam->m_len = isop->isop_faddr->siso_len);
397 break;
398
399 case PRU_SENSE:
400 /*
401 * stat: don't bother with a blocksize.
402 */
403 return (0);
404
405 case PRU_SENDOOB:
406 case PRU_FASTTIMO:
407 case PRU_SLOWTIMO:
408 case PRU_PROTORCV:
409 case PRU_PROTOSEND:
410 error = EOPNOTSUPP;
411 break;
412
413 case PRU_RCVD:
414 case PRU_RCVOOB:
415 return (EOPNOTSUPP); /* do not free mbuf's */
416
417 default:
418 panic("cltp_usrreq");
419 }
420 release:
421 if (control != NULL)
422 m_freem(control);
423 if (m != NULL)
424 m_freem(m);
425 return (error);
426 }