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