xref: /csrg-svn/sys/netiso/tp_cons.c (revision 45900)
136398Ssklower /***********************************************************
236398Ssklower 		Copyright IBM Corporation 1987
336398Ssklower 
436398Ssklower                       All Rights Reserved
536398Ssklower 
636398Ssklower Permission to use, copy, modify, and distribute this software and its
736398Ssklower documentation for any purpose and without fee is hereby granted,
836398Ssklower provided that the above copyright notice appear in all copies and that
936398Ssklower both that copyright notice and this permission notice appear in
1036398Ssklower supporting documentation, and that the name of IBM not be
1136398Ssklower used in advertising or publicity pertaining to distribution of the
1236398Ssklower software without specific, written prior permission.
1336398Ssklower 
1436398Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
1536398Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
1636398Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
1736398Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
1836398Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
1936398Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2036398Ssklower SOFTWARE.
2136398Ssklower 
2236398Ssklower ******************************************************************/
2336398Ssklower 
2436398Ssklower /*
2536398Ssklower  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
2636398Ssklower  */
2736398Ssklower /*
2836398Ssklower  * ARGO TP
2936398Ssklower  * $Header: tp_cons.c,v 5.6 88/11/18 17:27:13 nhall Exp $
3036398Ssklower  * $Source: /usr/argo/sys/netiso/RCS/tp_cons.c,v $
31*45900Ssklower  *	@(#)tp_cons.c	7.4 (Berkeley) 01/09/91 *
3236398Ssklower  *
33*45900Ssklower  * Here is where you find the iso- and cons-dependent code.  We've tried
3436398Ssklower  * keep all net-level and (primarily) address-family-dependent stuff
3536398Ssklower  * out of the tp source, and everthing here is reached indirectly
3636398Ssklower  * through a switch table (struct nl_protosw *) tpcb->tp_nlproto
3736398Ssklower  * (see tp_pcb.c).
3836398Ssklower  * The routines here are:
3936398Ssklower  *		tpcons_mtu: figure out what size tpdu to use
4036398Ssklower  *		tpcons_input: pullup and call tp_input w/ correct arguments
4136398Ssklower  *		tpcons_output: package a pkt for cons given an isopcb & some data
4236398Ssklower  *		cons_chan_to_tpcb: find a tpcb based on the channel #
4336398Ssklower  */
4436398Ssklower 
4536398Ssklower #ifndef lint
4636398Ssklower static char *rcsid = "$Header: tp_cons.c,v 5.6 88/11/18 17:27:13 nhall Exp $";
4736398Ssklower #endif lint
4836398Ssklower 
4936398Ssklower 
5036398Ssklower #ifdef ISO
51*45900Ssklower #ifdef TPCONS
5236398Ssklower 
5337469Ssklower #include "param.h"
5436398Ssklower #include "socket.h"
5536398Ssklower #include "domain.h"
5636398Ssklower #include "mbuf.h"
5736398Ssklower #include "errno.h"
5836398Ssklower #include "time.h"
59*45900Ssklower 
6036398Ssklower #include "../net/if.h"
61*45900Ssklower #include "../net/route.h"
6236398Ssklower 
6337469Ssklower #include "tp_param.h"
6437469Ssklower #include "argo_debug.h"
6537469Ssklower #include "tp_stat.h"
6637469Ssklower #include "tp_pcb.h"
6737469Ssklower #include "tp_trace.h"
6837469Ssklower #include "tp_stat.h"
6937469Ssklower #include "tp_tpdu.h"
7037469Ssklower #include "iso.h"
71*45900Ssklower #include "iso_errno.h"
7237469Ssklower #include "iso_pcb.h"
7337469Ssklower #include "cons.h"
7437469Ssklower #include "tp_seq.h"
7536398Ssklower 
76*45900Ssklower #undef FALSE
77*45900Ssklower #undef TRUE
78*45900Ssklower #include "../netccitt/x25.h"
79*45900Ssklower #include "../netccitt/pk.h"
80*45900Ssklower #include "../netccitt/pk_var.h"
81*45900Ssklower 
82*45900Ssklower #include "if_cons.c"
8336398Ssklower int tpcons_output();
8436398Ssklower 
8536398Ssklower /*
8636398Ssklower  * CALLED FROM:
87*45900Ssklower  *  tp_route_to() for PRU_CONNECT
88*45900Ssklower  * FUNCTION, ARGUMENTS, SIDE EFFECTS and RETURN VALUE:
89*45900Ssklower  *  version of the previous procedure for X.25
90*45900Ssklower  */
91*45900Ssklower 
92*45900Ssklower tpcons_pcbconnect(isop, nam)
93*45900Ssklower struct isopcb *isop;
94*45900Ssklower register struct mbuf *nam;
95*45900Ssklower {
96*45900Ssklower 	int error;
97*45900Ssklower 	if (error = iso_pcbconnect(isop, nam))
98*45900Ssklower 		return error;
99*45900Ssklower 	if ((isop->isop_chan = (caddr_t) pk_attach((struct socket *)0)) == 0) {
100*45900Ssklower 		IFDEBUG(D_CCONS)
101*45900Ssklower 			printf("tpcons_pcbconnect: no pklcd; returns 0x%x\n", error);
102*45900Ssklower 		ENDDEBUG
103*45900Ssklower 		return ENOBUFS;
104*45900Ssklower 	}
105*45900Ssklower 	if (error = cons_connect(isop)) { /* if it doesn't work */
106*45900Ssklower 		/* oh, dear, throw packet away */
107*45900Ssklower 		pk_disconnect((struct pklcd *)isop->isop_chan);
108*45900Ssklower 		isop->isop_chan = 0;
109*45900Ssklower 		return error;
110*45900Ssklower 	}
111*45900Ssklower }
112*45900Ssklower 
113*45900Ssklower 
114*45900Ssklower /*
115*45900Ssklower  * CALLED FROM:
11636398Ssklower  *  tp_input() on incoming CR, CC, and pr_usrreq() for PRU_CONNECT
11736398Ssklower  * FUNCTION, ARGUMENTS, SIDE EFFECTS and RETURN VALUE:
11836398Ssklower  *  version of the previous procedure for X.25
11936398Ssklower  */
12036398Ssklower 
12136398Ssklower void
12236398Ssklower tpcons_mtu(so, isop, size, negot)
12336398Ssklower 	struct socket *so;
12436398Ssklower 	struct isopcb *isop;
12536398Ssklower 	int *size;
12636398Ssklower 	u_char *negot;
12736398Ssklower {
12836398Ssklower 	register struct ifnet *ifp;
129*45900Ssklower 	register int i=0, isize;
13036398Ssklower 	int windowsize = so->so_rcv.sb_hiwat;
13136398Ssklower 
13236398Ssklower 	IFTRACE(D_CONN)
13336398Ssklower 		tptrace(TPPTmisc, "ENTER GET MTU: size negot ",*size, *negot, 0, 0);
13436398Ssklower 	ENDTRACE
13536398Ssklower 
136*45900Ssklower 	isize = *size = 1 << *negot;
137*45900Ssklower #ifdef ancient_history
13836398Ssklower 	if ((ifp = iso_routeifp(&isop->isop_faddr)) == (struct ifnet *)0)
13936398Ssklower 		return;
140*45900Ssklower #endif
14136398Ssklower 
142*45900Ssklower 	if (isize > windowsize) {
143*45900Ssklower 		isize = windowsize;
14436398Ssklower 		i++;
14536398Ssklower 	}
146*45900Ssklower 	if (isize > ifp->if_mtu) {
147*45900Ssklower 		isize = ifp->if_mtu;
14836398Ssklower 		i++;
14936398Ssklower 	}
150*45900Ssklower 	if (i) {
15136398Ssklower 		/* size was changed by this routine - have to transform it to
15236398Ssklower 		 * the log2 of size
15336398Ssklower 		 */
154*45900Ssklower 		for (i = TP_MIN_TPDUSIZE; i < TP_MAX_TPDUSIZE; i++) {
155*45900Ssklower 			if (isize <  (1 << (1 + i)))
156*45900Ssklower 				break;
15736398Ssklower 		}
15836398Ssklower 		*negot = i;
159*45900Ssklower 		*size = 1 << i;
16036398Ssklower 	}
16136398Ssklower 
16236398Ssklower 	IFDEBUG(D_CONN)
16336398Ssklower 		printf("GET MTU RETURNS: ifp %s size 0x%x negot 0x%x\n",
16436398Ssklower 		ifp->if_name,	*size, *negot);
16536398Ssklower 	ENDDEBUG
16636398Ssklower 	IFTRACE(D_CONN)
16736398Ssklower 		tptrace(TPPTmisc, "EXIT GET MTU: tpcb size negot ",
16836398Ssklower 		*size, *negot, 0, 0);
16936398Ssklower 	ENDTRACE
17036398Ssklower }
17136398Ssklower 
17236398Ssklower /*
17336398Ssklower  * CALLED FROM:
17436398Ssklower  * 	cons
17536398Ssklower  * FUNCTION and ARGUMENTS:
17636398Ssklower  * THIS MAYBE BELONGS IN SOME OTHER PLACE??? but i think not -
17736398Ssklower  */
17836398Ssklower ProtoHook
17936398Ssklower tpcons_ctlinput(cmd, siso, isop)
18036398Ssklower 	int cmd;
18136398Ssklower 	struct sockaddr_iso *siso;
18236398Ssklower 	struct isopcb *isop;
18336398Ssklower {
18436398Ssklower 	switch (cmd) {
18536398Ssklower 
18636398Ssklower 	case PRC_CONS_SEND_DONE:
18736398Ssklower 		if( isop->isop_socket ) { /* tp 0 only */
18836398Ssklower 			register struct tp_pcb *tpcb =
18936398Ssklower 				(struct tp_pcb *)isop->isop_socket->so_tpcb;
19036398Ssklower 			struct 	tp_event 		E;
19136398Ssklower 			int 					error = 0;
19236398Ssklower 
19336398Ssklower 			if( tpcb->tp_class == TP_CLASS_0 ) {
19436398Ssklower 				/* only if class is exactly class zero, not
19536398Ssklower 				 * still in class negotiation
19636398Ssklower 				 */
19736398Ssklower 				/* fake an ack */
19836398Ssklower 				register SeqNum	seq =  SEQ_ADD(tpcb, tpcb->tp_snduna, 1);
19936398Ssklower 
20036398Ssklower 				IFTRACE(D_DATA)
20136398Ssklower 					tptrace(TPPTmisc, "FAKE ACK seq cdt 1",
20236398Ssklower 						seq, 0,0,0);
20336398Ssklower 				ENDTRACE
20436398Ssklower 				IFDEBUG(D_DATA)
20536398Ssklower 					printf("FAKE ACK seq 0x%x cdt 1\n", seq );
20636398Ssklower 				ENDDEBUG
20736398Ssklower 				E.ATTR(AK_TPDU).e_cdt = 1;
20836398Ssklower 				E.ATTR(AK_TPDU).e_seq = seq;
20936398Ssklower 				E.ATTR(AK_TPDU).e_subseq = 0;
21036398Ssklower 				E.ATTR(AK_TPDU).e_fcc_present = 0;
21136398Ssklower 				error =  DoEvent(AK_TPDU);
21236398Ssklower 				if( error ) {
21336398Ssklower 					tpcb->tp_sock->so_error = error;
21436398Ssklower 				}
21536398Ssklower 			} /* else ignore it */
21636398Ssklower 		}
21736398Ssklower 		break;
21836398Ssklower 	case PRC_ROUTEDEAD:
21936398Ssklower 		if( isop->isop_socket ) { /* tp 0 only */
22036398Ssklower 			tpiso_reset(isop);
22136398Ssklower 			break;
22236398Ssklower 		} /* else drop through */
22336398Ssklower 	default:
22436398Ssklower 		(void) tpclnp_ctlinput(cmd, siso);
22536398Ssklower 		break;
22636398Ssklower 	}
22736398Ssklower 	return 0;
22836398Ssklower }
22936398Ssklower 
23036398Ssklower /*
23136398Ssklower  * CALLED FROM:
23236398Ssklower  * 	cons's intr routine
23336398Ssklower  * FUNCTION and ARGUMENTS:
23436398Ssklower  * Take a packet (m) from cons, pullup m as required by tp,
23536398Ssklower  *  ignore the socket argument, and call tp_input.
23636398Ssklower  * No return value.
23736398Ssklower  */
23836398Ssklower ProtoHook
239*45900Ssklower tpcons_input(m, faddr, laddr, channel)
24036398Ssklower 	struct mbuf 		*m;
24136398Ssklower 	struct sockaddr_iso	*faddr, *laddr;
242*45900Ssklower 	caddr_t				channel;
24336398Ssklower {
24436398Ssklower 	if( m == MNULL)
24536398Ssklower 		return 0;
24636398Ssklower 
24736398Ssklower 	m = (struct mbuf *)tp_inputprep(m);
24836398Ssklower 
24936398Ssklower 	IFDEBUG(D_TPINPUT)
25036398Ssklower 		printf("tpcons_input before tp_input(m 0x%x)\n", m);
25136398Ssklower 		dump_buf( m, 12+ m->m_len);
25236398Ssklower 	ENDDEBUG
25336398Ssklower 	tp_input(m, faddr, laddr, channel, tpcons_output);
25436398Ssklower 	return 0;
25536398Ssklower }
25636398Ssklower 
25736398Ssklower 
25836398Ssklower /*
25936398Ssklower  * CALLED FROM:
26036398Ssklower  *  tp_emit()
26136398Ssklower  * FUNCTION and ARGUMENTS:
26236398Ssklower  *  Take a packet(m0) from tp and package it so that cons will accept it.
26336398Ssklower  *  This means filling in a few of the fields.
26436398Ssklower  *  inp is the isopcb structure; datalen is the length of the data in the
26536398Ssklower  *  mbuf string m0.
26636398Ssklower  * RETURN VALUE:
26736398Ssklower  *  whatever (E*) is returned form the net layer output routine.
26836398Ssklower  */
26936398Ssklower 
27036398Ssklower int
27136398Ssklower tpcons_output(isop, m0, datalen, nochksum)
27236398Ssklower 	struct isopcb		*isop;
27336398Ssklower 	struct mbuf 		*m0;
27436398Ssklower 	int 				datalen;
27536398Ssklower 	int					nochksum;
27636398Ssklower {
277*45900Ssklower 	register	struct mbuf *m = m0;
27836398Ssklower 	int					error;
27936398Ssklower 
28036398Ssklower 	IFDEBUG(D_EMIT)
28136398Ssklower 		printf(
28236398Ssklower 		"tpcons_output(isop 0x%x, m 0x%x, len 0x%x socket 0x%x\n",
28336398Ssklower 			isop, m0, datalen, isop->isop_socket);
28436398Ssklower 	ENDDEBUG
285*45900Ssklower 	if (m == MNULL)
28636398Ssklower 		return 0;
287*45900Ssklower 	if (m->m_flags & M_PKTHDR == 0) {
288*45900Ssklower 		MGETHDR(m, M_DONTWAIT, MT_DATA);
289*45900Ssklower 		if (m == 0)
290*45900Ssklower 			return ENOBUFS;
291*45900Ssklower 		m->m_next = m0;
292*45900Ssklower 	}
293*45900Ssklower 	m->m_pkthdr.len = datalen;
294*45900Ssklower 	error = pk_send(isop->isop_chan, m);
29536398Ssklower 	IncStat(ts_tpdu_sent);
29636398Ssklower 
29736398Ssklower 	return error;
29836398Ssklower }
29936398Ssklower /*
30036398Ssklower  * CALLED FROM:
30136398Ssklower  *  tp_error_emit()
30236398Ssklower  * FUNCTION and ARGUMENTS:
303*45900Ssklower  *  Take a packet(m0) from tp and package it so that cons will accept it.
304*45900Ssklower  *  chan is the cons channel to use; datalen is the length of the data in the
305*45900Ssklower  *  mbuf string m0.
30636398Ssklower  * RETURN VALUE:
30736398Ssklower  *  whatever (E*) is returned form the net layer output routine.
30836398Ssklower  */
30936398Ssklower 
31036398Ssklower int
311*45900Ssklower tpcons_dg_output(chan, m0, datalen)
312*45900Ssklower 	caddr_t				chan;
31336398Ssklower 	struct mbuf 		*m0;
31436398Ssklower 	int 				datalen;
31536398Ssklower {
316*45900Ssklower 	return tpcons_output(((struct pklcd *)chan)->lcd_upnext, m0, datalen, 0);
31736398Ssklower }
318*45900Ssklower #endif TPCONS
31936398Ssklower #endif ISO
320