]>
Commit | Line | Data |
---|---|---|
1c79356b A |
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 | } |