xref: /csrg-svn/sys/netiso/cltp_usrreq.c (revision 39925)
139540Ssklower /*
239540Ssklower  * Copyright (c) 1989 Regents of the University of California.
339540Ssklower  * All rights reserved.
439540Ssklower  *
539540Ssklower  * Redistribution and use in source and binary forms are permitted
639540Ssklower  * provided that the above copyright notice and this paragraph are
739540Ssklower  * duplicated in all such forms and that any documentation,
839540Ssklower  * advertising materials, and other materials related to such
939540Ssklower  * distribution and use acknowledge that the software was developed
1039540Ssklower  * by the University of California, Berkeley.  The name of the
1139540Ssklower  * University may not be used to endorse or promote products derived
1239540Ssklower  * from this software without specific prior written permission.
1339540Ssklower  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1439540Ssklower  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1539540Ssklower  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1639540Ssklower  *
17*39925Ssklower  *	@(#)cltp_usrreq.c	7.2 (Berkeley) 01/16/90
1839540Ssklower  */
1939540Ssklower 
2039540Ssklower #ifndef CLTPOVAL_SRC /* XXX -- till files gets changed */
2139540Ssklower #include "param.h"
2239540Ssklower #include "user.h"
2339540Ssklower #include "malloc.h"
2439540Ssklower #include "mbuf.h"
2539540Ssklower #include "protosw.h"
2639540Ssklower #include "socket.h"
2739540Ssklower #include "socketvar.h"
2839540Ssklower #include "errno.h"
2939540Ssklower #include "stat.h"
3039540Ssklower 
3139540Ssklower #include "../net/if.h"
3239540Ssklower #include "../net/route.h"
3339540Ssklower 
3439540Ssklower #include "argo_debug.h"
3539540Ssklower #include "iso.h"
3639540Ssklower #include "iso_pcb.h"
3739540Ssklower #include "iso_var.h"
3839540Ssklower #include "clnp.h"
3939540Ssklower #include "cltp_var.h"
4039540Ssklower #endif
4139540Ssklower 
4239540Ssklower /*
4339540Ssklower  * CLTP protocol implementation.
4439540Ssklower  * Per ISO 8602, December, 1987.
4539540Ssklower  */
4639540Ssklower cltp_init()
4739540Ssklower {
4839540Ssklower 
4939540Ssklower 	cltb.isop_next = cltb.isop_prev = &cltb;
5039540Ssklower }
5139540Ssklower 
5239540Ssklower int cltp_cksum = 1;
5339540Ssklower 
5439540Ssklower 
5539540Ssklower /* ARGUSED */
5639540Ssklower cltp_input(m0, srcsa, dstsa, cons_channel, output)
5739540Ssklower 	struct mbuf *m0;
5839540Ssklower 	struct sockaddr *srcsa, *dstsa;
5939540Ssklower 	u_int cons_channel;
6039540Ssklower 	int (*output)();
6139540Ssklower {
6239540Ssklower 	register struct isopcb *isop;
6339540Ssklower 	register struct mbuf *m = m0;
6439540Ssklower 	register u_char *up = mtod(m, u_char *);
6539540Ssklower 	register struct sockaddr_iso *src = (struct sockaddr_iso *)srcsa;
6639540Ssklower 	int len, hdrlen = *up + 1, dlen = 0;
6739540Ssklower 	u_char *uplim = up + hdrlen;
6839540Ssklower 	caddr_t dtsap;
6939540Ssklower 
7039540Ssklower 	for (len = 0; m; m = m->m_next)
7139540Ssklower 		len += m->m_len;
7239540Ssklower 	up += 2; /* skip header */
7339540Ssklower 	while (up < uplim) switch (*up) { /* process options */
7439540Ssklower 	case CLTPOVAL_SRC:
7539540Ssklower 		src->siso_tlen = up[1];
7639540Ssklower 		src->siso_len = up[1] + TSEL(src) - (caddr_t)src;
7739540Ssklower 		if (src->siso_len < sizeof(*src))
7839540Ssklower 			src->siso_len = sizeof(*src);
7939540Ssklower 		else if (src->siso_len > sizeof(*src)) {
8039540Ssklower 			MGET(m, M_DONTWAIT, MT_SONAME);
8139540Ssklower 			if (m == 0)
8239540Ssklower 				goto bad;
8339540Ssklower 			m->m_len = src->siso_len;
8439540Ssklower 			src = mtod(m, struct sockaddr_iso *);
8539540Ssklower 			bcopy((caddr_t)srcsa, (caddr_t)src, srcsa->sa_len);
8639540Ssklower 		}
8739540Ssklower 		bcopy((caddr_t)up + 2, TSEL(src), up[1]);
8839540Ssklower 		up += 2 + src->siso_tlen;
8939540Ssklower 		continue;
9039540Ssklower 
9139540Ssklower 	case CLTPOVAL_DST:
9239540Ssklower 		dtsap = 2 + (caddr_t)up;
9339540Ssklower 		dlen = up[1];
9439540Ssklower 		up += 2 + dlen;
9539540Ssklower 		continue;
9639540Ssklower 
9739540Ssklower 	case CLTPOVAL_CSM:
98*39925Ssklower 		if (iso_check_csum(m0, len)) {
99*39925Ssklower 			cltpstat.cltps_badsum++;
10039540Ssklower 			goto bad;
101*39925Ssklower 		}
10239540Ssklower 		up += 4;
103*39925Ssklower 		continue;
10439540Ssklower 
10539540Ssklower 	default:
10639540Ssklower 		printf("clts: unknown option (%x)\n", up[0]);
107*39925Ssklower 		cltpstat.cltps_hdrops++;
10839540Ssklower 		goto bad;
10939540Ssklower 	}
11039540Ssklower 	if (dlen == 0 || src->siso_tlen == 0)
11139540Ssklower 		goto bad;
11239540Ssklower 	for (isop = cltb.isop_next;; isop = isop->isop_next) {
113*39925Ssklower 		if (isop == &cltb) {
114*39925Ssklower 			cltpstat.cltps_noport++;
11539540Ssklower 			goto bad;
116*39925Ssklower 		}
11739540Ssklower 		if (isop->isop_laddr &&
11839540Ssklower 		    bcmp(TSEL(isop->isop_laddr), dtsap, dlen) == 0)
11939540Ssklower 			break;
12039540Ssklower 	}
12139540Ssklower 	m = m0;
122*39925Ssklower 	m->m_len -= hdrlen;
123*39925Ssklower 	m->m_data += hdrlen;
12439540Ssklower 	if (sbappendaddr(&isop->isop_socket->so_rcv, (struct sockaddr *)src,
12539540Ssklower 	    m, (struct mbuf *)0) == 0)
12639540Ssklower 		goto bad;
127*39925Ssklower 	cltpstat.cltps_ipackets++;
12839540Ssklower 	sorwakeup(isop->isop_socket);
12939540Ssklower 	m0 = 0;
13039540Ssklower bad:
13139540Ssklower 	if (src != (struct sockaddr_iso *)srcsa)
13239540Ssklower 		m_freem(dtom(src));
13339540Ssklower 	if (m0)
13439540Ssklower 		m_freem(m0);
135*39925Ssklower 	return 0;
13639540Ssklower }
13739540Ssklower 
13839540Ssklower /*
13939540Ssklower  * Notify a cltp user of an asynchronous error;
14039540Ssklower  * just wake up so that he can collect error status.
14139540Ssklower  */
14239540Ssklower cltp_notify(isop)
14339540Ssklower 	register struct isopcb *isop;
14439540Ssklower {
14539540Ssklower 
14639540Ssklower 	sorwakeup(isop->isop_socket);
14739540Ssklower 	sowwakeup(isop->isop_socket);
14839540Ssklower }
14939540Ssklower 
15039540Ssklower cltp_ctlinput(cmd, sa)
15139540Ssklower 	int cmd;
15239540Ssklower 	struct sockaddr *sa;
15339540Ssklower {
15439540Ssklower 	extern u_char inetctlerrmap[];
15539540Ssklower 	struct sockaddr_iso *siso;
15639540Ssklower 	int iso_rtchange();
15739540Ssklower 
15839540Ssklower 	if ((unsigned)cmd > PRC_NCMDS)
15939540Ssklower 		return;
16039540Ssklower 	if (sa->sa_family != AF_ISO && sa->sa_family != AF_CCITT)
16139540Ssklower 		return;
16239540Ssklower 	siso = (struct sockaddr_iso *)sa;
16339540Ssklower 	if (siso == 0 || siso->siso_nlen == 0)
16439540Ssklower 		return;
16539540Ssklower 
16639540Ssklower 	switch (cmd) {
16739540Ssklower 	case PRC_ROUTEDEAD:
16839540Ssklower 	case PRC_REDIRECT_NET:
16939540Ssklower 	case PRC_REDIRECT_HOST:
17039540Ssklower 	case PRC_REDIRECT_TOSNET:
17139540Ssklower 	case PRC_REDIRECT_TOSHOST:
17239540Ssklower 		iso_pcbnotify(&cltb, siso,
17339540Ssklower 				(int)inetctlerrmap[cmd], iso_rtchange);
17439540Ssklower 		break;
17539540Ssklower 
17639540Ssklower 	default:
17739540Ssklower 		if (inetctlerrmap[cmd] == 0)
17839540Ssklower 			return;		/* XXX */
17939540Ssklower 		iso_pcbnotify(&cltb, siso, (int)inetctlerrmap[cmd],
18039540Ssklower 			cltp_notify);
18139540Ssklower 	}
18239540Ssklower }
18339540Ssklower 
18439540Ssklower cltp_output(isop, m)
18539540Ssklower 	register struct isopcb *isop;
18639540Ssklower 	register struct mbuf *m;
18739540Ssklower {
18839540Ssklower 	register int len;
18939540Ssklower 	register struct sockaddr_iso *siso;
19039540Ssklower 	int hdrlen, error = 0, docsum;
19139540Ssklower 	register u_char *up;
19239540Ssklower 
19339540Ssklower 	if (isop->isop_laddr == 0 || isop->isop_faddr == 0) {
19439540Ssklower 		error = ENOTCONN;
19539540Ssklower 		goto bad;
19639540Ssklower 	}
19739540Ssklower 	/*
19839540Ssklower 	 * Calculate data length and get a mbuf for CLTP header.
19939540Ssklower 	 */
20039540Ssklower 	hdrlen = 2 + 2 + isop->isop_laddr->siso_tlen
20139540Ssklower 		   + 2 + isop->isop_faddr->siso_tlen;
20239540Ssklower 	if (docsum = /*isop->isop_flags & CLNP_NO_CKSUM*/ cltp_cksum)
20339540Ssklower 		hdrlen += 4;
20439540Ssklower 	M_PREPEND(m, hdrlen, M_WAIT);
20539540Ssklower 	len = m->m_pkthdr.len;
20639540Ssklower 	/*
20739540Ssklower 	 * Fill in mbuf with extended CLTP header
20839540Ssklower 	 */
20939540Ssklower 	up = mtod(m, u_char *);
210*39925Ssklower 	up[0] = hdrlen - 1;
211*39925Ssklower 	up[1] = UD_TPDU_type;
212*39925Ssklower 	up[2] = CLTPOVAL_SRC;
21339540Ssklower 	up[3] = (siso = isop->isop_laddr)->siso_tlen;
21439540Ssklower 	up += 4;
21539540Ssklower 	bcopy(TSEL(siso), (caddr_t)up, siso->siso_tlen);
21639540Ssklower 	up += siso->siso_tlen;
217*39925Ssklower 	up[0] = CLTPOVAL_DST;
21839540Ssklower 	up[1] = (siso = isop->isop_faddr)->siso_tlen;
21939540Ssklower 	up += 2;
22039540Ssklower 	bcopy(TSEL(siso), (caddr_t)up, siso->siso_tlen);
22139540Ssklower 	/*
22239540Ssklower 	 * Stuff checksum and output datagram.
22339540Ssklower 	 */
22439540Ssklower 	if (docsum) {
22539540Ssklower 		up += siso->siso_tlen;
22639540Ssklower 		up[0] = CLTPOVAL_CSM;
22739540Ssklower 		up[1] = 2;
228*39925Ssklower 		iso_gen_csum(m, 2 + up - mtod(m, u_char *), len);
22939540Ssklower 	}
230*39925Ssklower 	cltpstat.cltps_opackets++;
23139540Ssklower 	return (tpclnp_output(isop, m, len, !docsum));
23239540Ssklower bad:
23339540Ssklower 	m_freem(m);
23439540Ssklower 	return (error);
23539540Ssklower }
23639540Ssklower 
23739540Ssklower #ifndef TP_LOCAL
23839540Ssklower /* XXXX should go in iso.h maybe? from tp_param.h, in any case */
23939540Ssklower #define		TP_LOCAL				22
24039540Ssklower #define		TP_FOREIGN				33
24139540Ssklower #endif
24239540Ssklower 
24339540Ssklower u_long	cltp_sendspace = 9216;		/* really max datagram size */
24439540Ssklower u_long	cltp_recvspace = 40 * (1024 + sizeof(struct sockaddr_iso));
24539540Ssklower 					/* 40 1K datagrams */
24639540Ssklower 
24739540Ssklower 
24839540Ssklower /*ARGSUSED*/
24939540Ssklower cltp_usrreq(so, req, m, nam, rights, control)
25039540Ssklower 	struct socket *so;
25139540Ssklower 	int req;
25239540Ssklower 	struct mbuf *m, *nam, *rights, *control;
25339540Ssklower {
25439540Ssklower 	struct isopcb *isop = sotoisopcb(so);
25539540Ssklower 	int s, error = 0;
25639540Ssklower 
25739540Ssklower 	if (req == PRU_CONTROL)
25839540Ssklower 		return (iso_control(so, (int)m, (caddr_t)nam,
25939540Ssklower 			(struct ifnet *)rights));
26039540Ssklower 	if (rights && rights->m_len) {
26139540Ssklower 		error = EINVAL;
26239540Ssklower 		goto release;
26339540Ssklower 	}
26439540Ssklower 	if (isop == NULL && req != PRU_ATTACH) {
26539540Ssklower 		error = EINVAL;
26639540Ssklower 		goto release;
26739540Ssklower 	}
26839540Ssklower 	switch (req) {
26939540Ssklower 
27039540Ssklower 	case PRU_ATTACH:
27139540Ssklower 		if (isop != NULL) {
27239540Ssklower 			error = EINVAL;
27339540Ssklower 			break;
27439540Ssklower 		}
27539540Ssklower 		error = iso_pcballoc(so, &cltb);
27639540Ssklower 		if (error)
27739540Ssklower 			break;
27839540Ssklower 		error = soreserve(so, cltp_sendspace, cltp_recvspace);
27939540Ssklower 		if (error)
28039540Ssklower 			break;
28139540Ssklower 		break;
28239540Ssklower 
28339540Ssklower 	case PRU_DETACH:
28439540Ssklower 		iso_pcbdetach(isop);
28539540Ssklower 		break;
28639540Ssklower 
28739540Ssklower 	case PRU_BIND:
28839540Ssklower 		error = iso_pcbbind(isop, nam);
28939540Ssklower 		break;
29039540Ssklower 
29139540Ssklower 	case PRU_LISTEN:
29239540Ssklower 		error = EOPNOTSUPP;
29339540Ssklower 		break;
29439540Ssklower 
29539540Ssklower 	case PRU_CONNECT:
29639540Ssklower 		if (isop->isop_faddr) {
29739540Ssklower 			error = EISCONN;
29839540Ssklower 			break;
29939540Ssklower 		}
30039540Ssklower 		error = iso_pcbconnect(isop, nam);
30139540Ssklower 		if (error == 0)
30239540Ssklower 			soisconnected(so);
30339540Ssklower 		break;
30439540Ssklower 
30539540Ssklower 	case PRU_CONNECT2:
30639540Ssklower 		error = EOPNOTSUPP;
30739540Ssklower 		break;
30839540Ssklower 
30939540Ssklower 	case PRU_ACCEPT:
31039540Ssklower 		error = EOPNOTSUPP;
31139540Ssklower 		break;
31239540Ssklower 
31339540Ssklower 	case PRU_DISCONNECT:
31439540Ssklower 		if (isop->isop_faddr == 0) {
31539540Ssklower 			error = ENOTCONN;
31639540Ssklower 			break;
31739540Ssklower 		}
31839540Ssklower 		iso_pcbdisconnect(isop);
31939540Ssklower 		so->so_state &= ~SS_ISCONNECTED;		/* XXX */
32039540Ssklower 		break;
32139540Ssklower 
32239540Ssklower 	case PRU_SHUTDOWN:
32339540Ssklower 		socantsendmore(so);
32439540Ssklower 		break;
32539540Ssklower 
32639540Ssklower 	case PRU_SEND:
32739540Ssklower 		if (nam) {
32839540Ssklower 			if (isop->isop_faddr) {
32939540Ssklower 				error = EISCONN;
33039540Ssklower 				break;
33139540Ssklower 			}
33239540Ssklower 			/*
33339540Ssklower 			 * Must block input while temporarily connected.
33439540Ssklower 			 */
33539540Ssklower 			s = splnet();
33639540Ssklower 			error = iso_pcbconnect(isop, nam);
33739540Ssklower 			if (error) {
33839540Ssklower 				splx(s);
33939540Ssklower 				break;
34039540Ssklower 			}
34139540Ssklower 		} else {
34239540Ssklower 			if (isop->isop_faddr == 0) {
34339540Ssklower 				error = ENOTCONN;
34439540Ssklower 				break;
34539540Ssklower 			}
34639540Ssklower 		}
34739540Ssklower 		error = cltp_output(isop, m);
34839540Ssklower 		m = 0;
34939540Ssklower 		if (nam) {
35039540Ssklower 			iso_pcbdisconnect(isop);
35139540Ssklower 			splx(s);
35239540Ssklower 		}
35339540Ssklower 		break;
35439540Ssklower 
35539540Ssklower 	case PRU_ABORT:
35639540Ssklower 		soisdisconnected(so);
35739540Ssklower 		iso_pcbdetach(isop);
35839540Ssklower 		break;
35939540Ssklower 
36039540Ssklower 	case PRU_SOCKADDR:
36139540Ssklower 		iso_getnetaddr(isop, nam, TP_LOCAL);
36239540Ssklower 		break;
36339540Ssklower 
36439540Ssklower 	case PRU_PEERADDR:
36539540Ssklower 		iso_getnetaddr(isop, nam, TP_FOREIGN);
36639540Ssklower 		break;
36739540Ssklower 
36839540Ssklower 	case PRU_SENSE:
36939540Ssklower 		/*
37039540Ssklower 		 * stat: don't bother with a blocksize.
37139540Ssklower 		 */
37239540Ssklower 		return (0);
37339540Ssklower 
37439540Ssklower 	case PRU_SENDOOB:
37539540Ssklower 	case PRU_FASTTIMO:
37639540Ssklower 	case PRU_SLOWTIMO:
37739540Ssklower 	case PRU_PROTORCV:
37839540Ssklower 	case PRU_PROTOSEND:
37939540Ssklower 		error =  EOPNOTSUPP;
38039540Ssklower 		break;
38139540Ssklower 
38239540Ssklower 	case PRU_RCVD:
38339540Ssklower 	case PRU_RCVOOB:
38439540Ssklower 		return (EOPNOTSUPP);	/* do not free mbuf's */
38539540Ssklower 
38639540Ssklower 	default:
38739540Ssklower 		panic("cltp_usrreq");
38839540Ssklower 	}
38939540Ssklower release:
39039540Ssklower 	if (m != NULL)
39139540Ssklower 		m_freem(m);
39239540Ssklower 	return (error);
39339540Ssklower }
394