cltp_usrreq.c made separate file in conf/files
[unix-history] / usr / src / sys / netiso / cltp_usrreq.c
CommitLineData
cb94d50b
KS
1/*
2 * Copyright (c) 1989 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16 *
3483a811 17 * @(#)cltp_usrreq.c 7.3 (Berkeley) %G%
cb94d50b
KS
18 */
19
20#ifndef CLTPOVAL_SRC /* XXX -- till files gets changed */
21#include "param.h"
22#include "user.h"
23#include "malloc.h"
24#include "mbuf.h"
25#include "protosw.h"
26#include "socket.h"
27#include "socketvar.h"
28#include "errno.h"
29#include "stat.h"
30
31#include "../net/if.h"
32#include "../net/route.h"
33
34#include "argo_debug.h"
35#include "iso.h"
36#include "iso_pcb.h"
37#include "iso_var.h"
38#include "clnp.h"
39#include "cltp_var.h"
40#endif
41
42/*
43 * CLTP protocol implementation.
44 * Per ISO 8602, December, 1987.
45 */
46cltp_init()
47{
48
49 cltb.isop_next = cltb.isop_prev = &cltb;
50}
51
52int cltp_cksum = 1;
53
54
55/* ARGUSED */
56cltp_input(m0, srcsa, dstsa, cons_channel, output)
57 struct mbuf *m0;
58 struct sockaddr *srcsa, *dstsa;
59 u_int cons_channel;
60 int (*output)();
61{
62 register struct isopcb *isop;
63 register struct mbuf *m = m0;
64 register u_char *up = mtod(m, u_char *);
65 register struct sockaddr_iso *src = (struct sockaddr_iso *)srcsa;
66 int len, hdrlen = *up + 1, dlen = 0;
67 u_char *uplim = up + hdrlen;
68 caddr_t dtsap;
69
70 for (len = 0; m; m = m->m_next)
71 len += m->m_len;
72 up += 2; /* skip header */
73 while (up < uplim) switch (*up) { /* process options */
74 case CLTPOVAL_SRC:
75 src->siso_tlen = up[1];
76 src->siso_len = up[1] + TSEL(src) - (caddr_t)src;
77 if (src->siso_len < sizeof(*src))
78 src->siso_len = sizeof(*src);
79 else if (src->siso_len > sizeof(*src)) {
80 MGET(m, M_DONTWAIT, MT_SONAME);
81 if (m == 0)
82 goto bad;
83 m->m_len = src->siso_len;
84 src = mtod(m, struct sockaddr_iso *);
85 bcopy((caddr_t)srcsa, (caddr_t)src, srcsa->sa_len);
86 }
87 bcopy((caddr_t)up + 2, TSEL(src), up[1]);
88 up += 2 + src->siso_tlen;
89 continue;
90
91 case CLTPOVAL_DST:
92 dtsap = 2 + (caddr_t)up;
93 dlen = up[1];
94 up += 2 + dlen;
95 continue;
96
97 case CLTPOVAL_CSM:
c6f34efd
KS
98 if (iso_check_csum(m0, len)) {
99 cltpstat.cltps_badsum++;
cb94d50b 100 goto bad;
c6f34efd 101 }
cb94d50b 102 up += 4;
c6f34efd 103 continue;
cb94d50b
KS
104
105 default:
106 printf("clts: unknown option (%x)\n", up[0]);
c6f34efd 107 cltpstat.cltps_hdrops++;
cb94d50b
KS
108 goto bad;
109 }
110 if (dlen == 0 || src->siso_tlen == 0)
111 goto bad;
112 for (isop = cltb.isop_next;; isop = isop->isop_next) {
c6f34efd
KS
113 if (isop == &cltb) {
114 cltpstat.cltps_noport++;
cb94d50b 115 goto bad;
c6f34efd 116 }
cb94d50b
KS
117 if (isop->isop_laddr &&
118 bcmp(TSEL(isop->isop_laddr), dtsap, dlen) == 0)
119 break;
120 }
121 m = m0;
c6f34efd
KS
122 m->m_len -= hdrlen;
123 m->m_data += hdrlen;
cb94d50b
KS
124 if (sbappendaddr(&isop->isop_socket->so_rcv, (struct sockaddr *)src,
125 m, (struct mbuf *)0) == 0)
126 goto bad;
c6f34efd 127 cltpstat.cltps_ipackets++;
cb94d50b
KS
128 sorwakeup(isop->isop_socket);
129 m0 = 0;
130bad:
131 if (src != (struct sockaddr_iso *)srcsa)
132 m_freem(dtom(src));
133 if (m0)
134 m_freem(m0);
c6f34efd 135 return 0;
cb94d50b
KS
136}
137
138/*
139 * Notify a cltp user of an asynchronous error;
140 * just wake up so that he can collect error status.
141 */
142cltp_notify(isop)
143 register struct isopcb *isop;
144{
145
146 sorwakeup(isop->isop_socket);
147 sowwakeup(isop->isop_socket);
148}
149
150cltp_ctlinput(cmd, sa)
151 int cmd;
152 struct sockaddr *sa;
153{
154 extern u_char inetctlerrmap[];
155 struct sockaddr_iso *siso;
156 int iso_rtchange();
157
158 if ((unsigned)cmd > PRC_NCMDS)
159 return;
160 if (sa->sa_family != AF_ISO && sa->sa_family != AF_CCITT)
161 return;
162 siso = (struct sockaddr_iso *)sa;
163 if (siso == 0 || siso->siso_nlen == 0)
164 return;
165
166 switch (cmd) {
167 case PRC_ROUTEDEAD:
168 case PRC_REDIRECT_NET:
169 case PRC_REDIRECT_HOST:
170 case PRC_REDIRECT_TOSNET:
171 case PRC_REDIRECT_TOSHOST:
172 iso_pcbnotify(&cltb, siso,
173 (int)inetctlerrmap[cmd], iso_rtchange);
174 break;
175
176 default:
177 if (inetctlerrmap[cmd] == 0)
178 return; /* XXX */
179 iso_pcbnotify(&cltb, siso, (int)inetctlerrmap[cmd],
180 cltp_notify);
181 }
182}
183
184cltp_output(isop, m)
185 register struct isopcb *isop;
186 register struct mbuf *m;
187{
188 register int len;
189 register struct sockaddr_iso *siso;
190 int hdrlen, error = 0, docsum;
191 register u_char *up;
192
193 if (isop->isop_laddr == 0 || isop->isop_faddr == 0) {
194 error = ENOTCONN;
195 goto bad;
196 }
197 /*
198 * Calculate data length and get a mbuf for CLTP header.
199 */
200 hdrlen = 2 + 2 + isop->isop_laddr->siso_tlen
201 + 2 + isop->isop_faddr->siso_tlen;
202 if (docsum = /*isop->isop_flags & CLNP_NO_CKSUM*/ cltp_cksum)
203 hdrlen += 4;
204 M_PREPEND(m, hdrlen, M_WAIT);
205 len = m->m_pkthdr.len;
206 /*
207 * Fill in mbuf with extended CLTP header
208 */
209 up = mtod(m, u_char *);
c6f34efd
KS
210 up[0] = hdrlen - 1;
211 up[1] = UD_TPDU_type;
212 up[2] = CLTPOVAL_SRC;
cb94d50b
KS
213 up[3] = (siso = isop->isop_laddr)->siso_tlen;
214 up += 4;
215 bcopy(TSEL(siso), (caddr_t)up, siso->siso_tlen);
216 up += siso->siso_tlen;
c6f34efd 217 up[0] = CLTPOVAL_DST;
cb94d50b
KS
218 up[1] = (siso = isop->isop_faddr)->siso_tlen;
219 up += 2;
220 bcopy(TSEL(siso), (caddr_t)up, siso->siso_tlen);
221 /*
222 * Stuff checksum and output datagram.
223 */
224 if (docsum) {
225 up += siso->siso_tlen;
226 up[0] = CLTPOVAL_CSM;
227 up[1] = 2;
c6f34efd 228 iso_gen_csum(m, 2 + up - mtod(m, u_char *), len);
cb94d50b 229 }
c6f34efd 230 cltpstat.cltps_opackets++;
cb94d50b
KS
231 return (tpclnp_output(isop, m, len, !docsum));
232bad:
233 m_freem(m);
234 return (error);
235}
236
237#ifndef TP_LOCAL
238/* XXXX should go in iso.h maybe? from tp_param.h, in any case */
239#define TP_LOCAL 22
240#define TP_FOREIGN 33
241#endif
242
243u_long cltp_sendspace = 9216; /* really max datagram size */
244u_long cltp_recvspace = 40 * (1024 + sizeof(struct sockaddr_iso));
245 /* 40 1K datagrams */
246
247
248/*ARGSUSED*/
3483a811 249cltp_usrreq(so, req, m, nam, control)
cb94d50b
KS
250 struct socket *so;
251 int req;
3483a811 252 struct mbuf *m, *nam, *control;
cb94d50b
KS
253{
254 struct isopcb *isop = sotoisopcb(so);
255 int s, error = 0;
256
257 if (req == PRU_CONTROL)
258 return (iso_control(so, (int)m, (caddr_t)nam,
3483a811 259 (struct ifnet *)control));
cb94d50b
KS
260 if (isop == NULL && req != PRU_ATTACH) {
261 error = EINVAL;
262 goto release;
263 }
264 switch (req) {
265
266 case PRU_ATTACH:
267 if (isop != NULL) {
268 error = EINVAL;
269 break;
270 }
271 error = iso_pcballoc(so, &cltb);
272 if (error)
273 break;
274 error = soreserve(so, cltp_sendspace, cltp_recvspace);
275 if (error)
276 break;
277 break;
278
279 case PRU_DETACH:
280 iso_pcbdetach(isop);
281 break;
282
283 case PRU_BIND:
284 error = iso_pcbbind(isop, nam);
285 break;
286
287 case PRU_LISTEN:
288 error = EOPNOTSUPP;
289 break;
290
291 case PRU_CONNECT:
292 if (isop->isop_faddr) {
293 error = EISCONN;
294 break;
295 }
296 error = iso_pcbconnect(isop, nam);
297 if (error == 0)
298 soisconnected(so);
299 break;
300
301 case PRU_CONNECT2:
302 error = EOPNOTSUPP;
303 break;
304
305 case PRU_ACCEPT:
306 error = EOPNOTSUPP;
307 break;
308
309 case PRU_DISCONNECT:
310 if (isop->isop_faddr == 0) {
311 error = ENOTCONN;
312 break;
313 }
314 iso_pcbdisconnect(isop);
315 so->so_state &= ~SS_ISCONNECTED; /* XXX */
316 break;
317
318 case PRU_SHUTDOWN:
319 socantsendmore(so);
320 break;
321
322 case PRU_SEND:
323 if (nam) {
324 if (isop->isop_faddr) {
325 error = EISCONN;
326 break;
327 }
328 /*
329 * Must block input while temporarily connected.
330 */
331 s = splnet();
332 error = iso_pcbconnect(isop, nam);
333 if (error) {
334 splx(s);
335 break;
336 }
337 } else {
338 if (isop->isop_faddr == 0) {
339 error = ENOTCONN;
340 break;
341 }
342 }
343 error = cltp_output(isop, m);
344 m = 0;
345 if (nam) {
346 iso_pcbdisconnect(isop);
347 splx(s);
348 }
349 break;
350
351 case PRU_ABORT:
352 soisdisconnected(so);
353 iso_pcbdetach(isop);
354 break;
355
356 case PRU_SOCKADDR:
357 iso_getnetaddr(isop, nam, TP_LOCAL);
358 break;
359
360 case PRU_PEERADDR:
361 iso_getnetaddr(isop, nam, TP_FOREIGN);
362 break;
363
364 case PRU_SENSE:
365 /*
366 * stat: don't bother with a blocksize.
367 */
368 return (0);
369
370 case PRU_SENDOOB:
371 case PRU_FASTTIMO:
372 case PRU_SLOWTIMO:
373 case PRU_PROTORCV:
374 case PRU_PROTOSEND:
375 error = EOPNOTSUPP;
376 break;
377
378 case PRU_RCVD:
379 case PRU_RCVOOB:
380 return (EOPNOTSUPP); /* do not free mbuf's */
381
382 default:
383 panic("cltp_usrreq");
384 }
385release:
386 if (m != NULL)
387 m_freem(m);
388 return (error);
389}