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