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