|
|
1.1 root 1: /*
2: * Copyright (c) 1989 Regents of the University of California.
3: * All rights reserved.
4: *
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.
19: *
20: * @(#)cltp_usrreq.c 7.5 (Berkeley) 6/28/90
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: */
49: cltp_init()
50: {
51:
52: cltb.isop_next = cltb.isop_prev = &cltb;
53: }
54:
55: int cltp_cksum = 1;
56:
57:
58: /* ARGUSED */
59: cltp_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:
101: if (iso_check_csum(m0, len)) {
102: cltpstat.cltps_badsum++;
103: goto bad;
104: }
105: up += 4;
106: continue;
107:
108: default:
109: printf("clts: unknown option (%x)\n", up[0]);
110: cltpstat.cltps_hdrops++;
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) {
116: if (isop == &cltb) {
117: cltpstat.cltps_noport++;
118: goto bad;
119: }
120: if (isop->isop_laddr &&
121: bcmp(TSEL(isop->isop_laddr), dtsap, dlen) == 0)
122: break;
123: }
124: m = m0;
125: m->m_len -= hdrlen;
126: m->m_data += hdrlen;
127: if (sbappendaddr(&isop->isop_socket->so_rcv, (struct sockaddr *)src,
128: m, (struct mbuf *)0) == 0)
129: goto bad;
130: cltpstat.cltps_ipackets++;
131: sorwakeup(isop->isop_socket);
132: m0 = 0;
133: bad:
134: if (src != (struct sockaddr_iso *)srcsa)
135: m_freem(dtom(src));
136: if (m0)
137: m_freem(m0);
138: return 0;
139: }
140:
141: /*
142: * Notify a cltp user of an asynchronous error;
143: * just wake up so that he can collect error status.
144: */
145: cltp_notify(isop)
146: register struct isopcb *isop;
147: {
148:
149: sorwakeup(isop->isop_socket);
150: sowwakeup(isop->isop_socket);
151: }
152:
153: cltp_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:
187: cltp_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 *);
213: up[0] = hdrlen - 1;
214: up[1] = UD_TPDU_type;
215: up[2] = CLTPOVAL_SRC;
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;
220: up[0] = CLTPOVAL_DST;
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;
231: iso_gen_csum(m, 2 + up - mtod(m, u_char *), len);
232: }
233: cltpstat.cltps_opackets++;
234: return (tpclnp_output(isop, m, len, !docsum));
235: bad:
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:
246: u_long cltp_sendspace = 9216; /* really max datagram size */
247: u_long cltp_recvspace = 40 * (1024 + sizeof(struct sockaddr_iso));
248: /* 40 1K datagrams */
249:
250:
251: /*ARGSUSED*/
252: cltp_usrreq(so, req, m, nam, control)
253: struct socket *so;
254: int req;
255: struct mbuf *m, *nam, *control;
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,
262: (struct ifnet *)control));
263: if ((isop == NULL && req != PRU_ATTACH) ||
264: (control && control->m_len)) {
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: }
389: release:
390: if (control != NULL)
391: m_freem(control);
392: if (m != NULL)
393: m_freem(m);
394: return (error);
395: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.