xref: /csrg-svn/sys/netiso/tp_cons.c (revision 37469)
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 $
3136398Ssklower  *
3236398Ssklower  * Here is where you find the iso-dependent code.  We've tried
3336398Ssklower  * keep all net-level and (primarily) address-family-dependent stuff
3436398Ssklower  * out of the tp source, and everthing here is reached indirectly
3536398Ssklower  * through a switch table (struct nl_protosw *) tpcb->tp_nlproto
3636398Ssklower  * (see tp_pcb.c).
3736398Ssklower  * The routines here are:
3836398Ssklower  *		tpcons_mtu: figure out what size tpdu to use
3936398Ssklower  *		tpcons_input: pullup and call tp_input w/ correct arguments
4036398Ssklower  *		tpcons_output_dg: package a pkt for cons given 2 addresses & some data
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 #include "argoxtwentyfive.h"
5036398Ssklower 
5136398Ssklower #ifdef ISO
5236398Ssklower #if NARGOXTWENTYFIVE > 0
5336398Ssklower 
54*37469Ssklower #include "param.h"
5536398Ssklower #include "socket.h"
5636398Ssklower #include "domain.h"
5736398Ssklower #include "mbuf.h"
5836398Ssklower #include "errno.h"
5936398Ssklower #include "time.h"
6036398Ssklower #include "../net/if.h"
6136398Ssklower 
62*37469Ssklower #include "tp_param.h"
63*37469Ssklower #include "argo_debug.h"
64*37469Ssklower #include "tp_stat.h"
65*37469Ssklower #include "tp_pcb.h"
66*37469Ssklower #include "tp_trace.h"
67*37469Ssklower #include "tp_stat.h"
68*37469Ssklower #include "tp_tpdu.h"
6936398Ssklower #include "../net/route.h"
70*37469Ssklower #include "iso.h"
71*37469Ssklower #include "iso_pcb.h"
72*37469Ssklower #include "cons.h"
73*37469Ssklower #include "tp_seq.h"
7436398Ssklower 
7536398Ssklower int tpcons_output();
7636398Ssklower 
7736398Ssklower /*
7836398Ssklower  * CALLED FROM:
7936398Ssklower  *  tp_input() on incoming CR, CC, and pr_usrreq() for PRU_CONNECT
8036398Ssklower  * FUNCTION, ARGUMENTS, SIDE EFFECTS and RETURN VALUE:
8136398Ssklower  *  version of the previous procedure for X.25
8236398Ssklower  */
8336398Ssklower 
8436398Ssklower void
8536398Ssklower tpcons_mtu(so, isop, size, negot)
8636398Ssklower 	struct socket *so;
8736398Ssklower 	struct isopcb *isop;
8836398Ssklower 	int *size;
8936398Ssklower 	u_char *negot;
9036398Ssklower {
9136398Ssklower 	register struct ifnet *ifp;
9236398Ssklower 	register int i=0;
9336398Ssklower 	int windowsize = so->so_rcv.sb_hiwat;
9436398Ssklower 	struct ifnet	*iso_routeifp();
9536398Ssklower 
9636398Ssklower 	IFTRACE(D_CONN)
9736398Ssklower 		tptrace(TPPTmisc, "ENTER GET MTU: size negot ",*size, *negot, 0, 0);
9836398Ssklower 	ENDTRACE
9936398Ssklower 
10036398Ssklower 
10136398Ssklower 	*size = 1 << *negot;
10236398Ssklower 	if ((ifp = iso_routeifp(&isop->isop_faddr)) == (struct ifnet *)0)
10336398Ssklower 		return;
10436398Ssklower 
10536398Ssklower 	if( *size > windowsize ) {
10636398Ssklower 		*size = windowsize;
10736398Ssklower 		i++;
10836398Ssklower 	}
10936398Ssklower 
11036398Ssklower 	if(*size > ifp->if_mtu) {
11136398Ssklower 		*size = ifp->if_mtu ;
11236398Ssklower 		i++;
11336398Ssklower 	}
11436398Ssklower 	if(i) {
11536398Ssklower 		/* size was changed by this routine - have to transform it to
11636398Ssklower 		 * the log2 of size
11736398Ssklower 		 */
11836398Ssklower 		for(i=TP_MIN_TPDUSIZE; (i<TP_MAX_TPDUSIZE && ((1<<i)<*size)) ; i++)
11936398Ssklower 			;
12036398Ssklower 		/* are we on the same LAN? if so, negotiate one tpdu size larger,
12136398Ssklower 		 * and actually send the real mtu size
12236398Ssklower 		 */
12336398Ssklower 		/* PHASE2: replace with iso_on_localnet(&isop->isop_faddr);
12436398Ssklower 		 */
12536398Ssklower 		if ( !iso_netmatch(&isop->isop_laddr, &isop->isop_faddr) ) {
12636398Ssklower 			i--;
12736398Ssklower 			*size = 1<<i;
12836398Ssklower 		}
12936398Ssklower 		*negot = i;
13036398Ssklower 	}
13136398Ssklower 
13236398Ssklower 	IFDEBUG(D_CONN)
13336398Ssklower 		printf("GET MTU RETURNS: ifp %s size 0x%x negot 0x%x\n",
13436398Ssklower 		ifp->if_name,	*size, *negot);
13536398Ssklower 	ENDDEBUG
13636398Ssklower 	IFTRACE(D_CONN)
13736398Ssklower 		tptrace(TPPTmisc, "EXIT GET MTU: tpcb size negot ",
13836398Ssklower 		*size, *negot, 0, 0);
13936398Ssklower 	ENDTRACE
14036398Ssklower }
14136398Ssklower 
14236398Ssklower /*
14336398Ssklower  * CALLED FROM:
14436398Ssklower  * 	cons
14536398Ssklower  * FUNCTION and ARGUMENTS:
14636398Ssklower  * THIS MAYBE BELONGS IN SOME OTHER PLACE??? but i think not -
14736398Ssklower  */
14836398Ssklower ProtoHook
14936398Ssklower tpcons_ctlinput(cmd, siso, isop)
15036398Ssklower 	int cmd;
15136398Ssklower 	struct sockaddr_iso *siso;
15236398Ssklower 	struct isopcb *isop;
15336398Ssklower {
15436398Ssklower 	switch (cmd) {
15536398Ssklower 
15636398Ssklower 	case PRC_CONS_SEND_DONE:
15736398Ssklower 		if( isop->isop_socket ) { /* tp 0 only */
15836398Ssklower 			register struct tp_pcb *tpcb =
15936398Ssklower 				(struct tp_pcb *)isop->isop_socket->so_tpcb;
16036398Ssklower 			struct 	tp_event 		E;
16136398Ssklower 			int 					error = 0;
16236398Ssklower 
16336398Ssklower 			if( tpcb->tp_class == TP_CLASS_0 ) {
16436398Ssklower 				/* only if class is exactly class zero, not
16536398Ssklower 				 * still in class negotiation
16636398Ssklower 				 */
16736398Ssklower 				/* fake an ack */
16836398Ssklower 				register SeqNum	seq =  SEQ_ADD(tpcb, tpcb->tp_snduna, 1);
16936398Ssklower 
17036398Ssklower 				IFTRACE(D_DATA)
17136398Ssklower 					tptrace(TPPTmisc, "FAKE ACK seq cdt 1",
17236398Ssklower 						seq, 0,0,0);
17336398Ssklower 				ENDTRACE
17436398Ssklower 				IFDEBUG(D_DATA)
17536398Ssklower 					printf("FAKE ACK seq 0x%x cdt 1\n", seq );
17636398Ssklower 				ENDDEBUG
17736398Ssklower 				E.ATTR(AK_TPDU).e_cdt = 1;
17836398Ssklower 				E.ATTR(AK_TPDU).e_seq = seq;
17936398Ssklower 				E.ATTR(AK_TPDU).e_subseq = 0;
18036398Ssklower 				E.ATTR(AK_TPDU).e_fcc_present = 0;
18136398Ssklower 				error =  DoEvent(AK_TPDU);
18236398Ssklower 				if( error ) {
18336398Ssklower 					tpcb->tp_sock->so_error = error;
18436398Ssklower 				}
18536398Ssklower 			} /* else ignore it */
18636398Ssklower 		}
18736398Ssklower 		break;
18836398Ssklower 	case PRC_ROUTEDEAD:
18936398Ssklower 		if( isop->isop_socket ) { /* tp 0 only */
19036398Ssklower 			tpiso_reset(isop);
19136398Ssklower 			break;
19236398Ssklower 		} /* else drop through */
19336398Ssklower 	default:
19436398Ssklower 		(void) tpclnp_ctlinput(cmd, siso);
19536398Ssklower 		break;
19636398Ssklower 	}
19736398Ssklower 	return 0;
19836398Ssklower }
19936398Ssklower 
20036398Ssklower /*
20136398Ssklower  * CALLED FROM:
20236398Ssklower  * 	cons's intr routine
20336398Ssklower  * FUNCTION and ARGUMENTS:
20436398Ssklower  * Take a packet (m) from cons, pullup m as required by tp,
20536398Ssklower  *  ignore the socket argument, and call tp_input.
20636398Ssklower  * No return value.
20736398Ssklower  */
20836398Ssklower ProtoHook
20936398Ssklower tpcons_input(m, faddr, laddr, so, channel)
21036398Ssklower 	struct mbuf 		*m;
21136398Ssklower 	struct sockaddr_iso	*faddr, *laddr;
21236398Ssklower 	struct socket 		*so; /* not used */
21336398Ssklower 	int					channel;
21436398Ssklower {
21536398Ssklower 	if( m == MNULL)
21636398Ssklower 		return 0;
21736398Ssklower 
21836398Ssklower 	m = (struct mbuf *)tp_inputprep(m);
21936398Ssklower 
22036398Ssklower 	IFDEBUG(D_TPINPUT)
22136398Ssklower 		printf("tpcons_input before tp_input(m 0x%x)\n", m);
22236398Ssklower 		dump_buf( m, 12+ m->m_len);
22336398Ssklower 	ENDDEBUG
22436398Ssklower 	tp_input(m, faddr, laddr, channel, tpcons_output);
22536398Ssklower 	return 0;
22636398Ssklower }
22736398Ssklower 
22836398Ssklower 
22936398Ssklower /*
23036398Ssklower  * CALLED FROM:
23136398Ssklower  *  tp_emit()
23236398Ssklower  * FUNCTION and ARGUMENTS:
23336398Ssklower  *  Take a packet(m0) from tp and package it so that cons will accept it.
23436398Ssklower  *  This means filling in a few of the fields.
23536398Ssklower  *  inp is the isopcb structure; datalen is the length of the data in the
23636398Ssklower  *  mbuf string m0.
23736398Ssklower  * RETURN VALUE:
23836398Ssklower  *  whatever (E*) is returned form the net layer output routine.
23936398Ssklower  */
24036398Ssklower 
24136398Ssklower int
24236398Ssklower tpcons_output(isop, m0, datalen, nochksum)
24336398Ssklower 	struct isopcb		*isop;
24436398Ssklower 	struct mbuf 		*m0;
24536398Ssklower 	int 				datalen;
24636398Ssklower 	int					nochksum;
24736398Ssklower {
24836398Ssklower 	struct tp_pcb 		*tpcb;
24936398Ssklower 	int					error;
25036398Ssklower 
25136398Ssklower 	IFDEBUG(D_EMIT)
25236398Ssklower 		printf(
25336398Ssklower 		"tpcons_output(isop 0x%x, m 0x%x, len 0x%x socket 0x%x\n",
25436398Ssklower 			isop, m0, datalen, isop->isop_socket);
25536398Ssklower 	ENDDEBUG
25636398Ssklower 	if(m0 == MNULL)
25736398Ssklower 		return 0;
25836398Ssklower 	ASSERT(m0->m_len > 0);
25936398Ssklower 	tpcb = (struct tp_pcb *)isop->isop_socket->so_tpcb;
26036398Ssklower 
26136398Ssklower 	/* check is for class EQUAL to 4: if still in negotiation stage,
26236398Ssklower 	 * cannot send as dgm
26336398Ssklower 	 */
26436398Ssklower 	error = cons_output(isop, m0,  datalen, (tpcb->tp_class == TP_CLASS_4));
26536398Ssklower 	IncStat(ts_tpdu_sent);
26636398Ssklower 
26736398Ssklower 	IFTRACE(D_EMIT)
26836398Ssklower 		tptrace( TPPTmisc,
26936398Ssklower 		"tpcons_output( isop  m isdgm cons_output returns",
27036398Ssklower 			isop, m0, (tpcb->tp_class == TP_CLASS_4), error );
27136398Ssklower 	ENDTRACE
27236398Ssklower 	return error;
27336398Ssklower }
27436398Ssklower 
27536398Ssklower /*
27636398Ssklower  * CALLED FROM:
27736398Ssklower  *  tp_error_emit()
27836398Ssklower  * FUNCTION and ARGUMENTS:
27936398Ssklower  *  This is a copy of tpcons_output that takes the addresses
28036398Ssklower  *  instead of a pcb.  It's used by the tp_error_emit, when we
28136398Ssklower  *  don't have an iso_pcb with which to call the normal output rtn.
28236398Ssklower  * RETURN VALUE:
28336398Ssklower  *  ENOBUFS or
28436398Ssklower  *  whatever (E*) is returned form the net layer output routine.
28536398Ssklower  */
28636398Ssklower 
28736398Ssklower int
28836398Ssklower tpcons_output_dg(laddr, faddr, m0, datalen, ro, nochksum)
28936398Ssklower 	struct iso_addr		*laddr, *faddr;
29036398Ssklower 	struct mbuf 		*m0;
29136398Ssklower 	int 				datalen;
29236398Ssklower 	struct route 		*ro;
29336398Ssklower 	int					nochksum;
29436398Ssklower {
29536398Ssklower 	IFDEBUG(D_TPISO)
29636398Ssklower 		printf("PANIC: tpcons_output_dg  datalen 0x%x m0 0x%x\n", datalen, m0);
29736398Ssklower 	ENDDEBUG
29836398Ssklower 
29936398Ssklower 	return 0;
30036398Ssklower }
30136398Ssklower 
30236398Ssklower struct tp_pcb *
30336398Ssklower cons_chan_to_tpcb(chan)
30436398Ssklower 	int chan;
30536398Ssklower {
30636398Ssklower 	extern struct isopcb *cons_chan_to_pcb ();
30736398Ssklower #ifdef ARGO_DEBUG
30836398Ssklower 	struct isopcb *isop = cons_chan_to_pcb (chan, -1);
30936398Ssklower #else ARGO_DEBUG
31036398Ssklower 	struct isopcb *isop = cons_chan_to_pcb (chan);
31136398Ssklower #endif ARGO_DEBUG
31236398Ssklower 
31336398Ssklower 	IFTRACE(D_CONN)
31436398Ssklower 		tptrace(TPPTmisc, "vc->tpcb(chan) socket",
31536398Ssklower 			chan, isop->isop_socket, 0, 0);
31636398Ssklower 	ENDTRACE
31736398Ssklower 	IFDEBUG(D_CONN)
31836398Ssklower 		printf("vc->tpcb(0x%x) socket 0x%x, *ISOP dump:",
31936398Ssklower 			chan, isop->isop_socket);
32036398Ssklower 		dump_buf( isop, 32);
32136398Ssklower 	ENDDEBUG
32236398Ssklower 	if( isop->isop_socket == (struct socket *)0 )
32336398Ssklower 		return (struct tp_pcb *) 0;
32436398Ssklower 	else {
32536398Ssklower 		return (struct tp_pcb *)(isop->isop_socket->so_tpcb);
32636398Ssklower }
32736398Ssklower }
32836398Ssklower #endif NARGOXTWENTYFIVE
32936398Ssklower #endif ISO
330