xref: /csrg-svn/sys/netiso/tp_cons.c (revision 63222)
149268Sbostic /*-
2*63222Sbostic  * Copyright (c) 1991, 1993
3*63222Sbostic  *	The Regents of the University of California.  All rights reserved.
449268Sbostic  *
549268Sbostic  * %sccs.include.redist.c%
649268Sbostic  *
7*63222Sbostic  *	@(#)tp_cons.c	8.1 (Berkeley) 06/10/93
849268Sbostic  */
949268Sbostic 
1036398Ssklower /***********************************************************
1136398Ssklower 		Copyright IBM Corporation 1987
1236398Ssklower 
1336398Ssklower                       All Rights Reserved
1436398Ssklower 
1536398Ssklower Permission to use, copy, modify, and distribute this software and its
1636398Ssklower documentation for any purpose and without fee is hereby granted,
1736398Ssklower provided that the above copyright notice appear in all copies and that
1836398Ssklower both that copyright notice and this permission notice appear in
1936398Ssklower supporting documentation, and that the name of IBM not be
2036398Ssklower used in advertising or publicity pertaining to distribution of the
2136398Ssklower software without specific, written prior permission.
2236398Ssklower 
2336398Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
2436398Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
2536398Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
2636398Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
2736398Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
2836398Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2936398Ssklower SOFTWARE.
3036398Ssklower 
3136398Ssklower ******************************************************************/
3236398Ssklower 
3336398Ssklower /*
3436398Ssklower  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
3536398Ssklower  */
3636398Ssklower /*
3736398Ssklower  * ARGO TP
3836398Ssklower  * $Header: tp_cons.c,v 5.6 88/11/18 17:27:13 nhall Exp $
3936398Ssklower  * $Source: /usr/argo/sys/netiso/RCS/tp_cons.c,v $
4036398Ssklower  *
4145900Ssklower  * Here is where you find the iso- and cons-dependent code.  We've tried
4236398Ssklower  * keep all net-level and (primarily) address-family-dependent stuff
4336398Ssklower  * out of the tp source, and everthing here is reached indirectly
4436398Ssklower  * through a switch table (struct nl_protosw *) tpcb->tp_nlproto
4536398Ssklower  * (see tp_pcb.c).
4636398Ssklower  * The routines here are:
4749268Sbostic  *	tpcons_input: pullup and call tp_input w/ correct arguments
4849268Sbostic  *	tpcons_output: package a pkt for cons given an isopcb & some data
4949268Sbostic  *	cons_chan_to_tpcb: find a tpcb based on the channel #
5036398Ssklower  */
5136398Ssklower 
5236398Ssklower #ifdef ISO
5345900Ssklower #ifdef TPCONS
5436398Ssklower 
5556533Sbostic #include <sys/param.h>
5656533Sbostic #include <sys/socket.h>
5756533Sbostic #include <sys/domain.h>
5856533Sbostic #include <sys/mbuf.h>
5956533Sbostic #include <sys/errno.h>
6056533Sbostic #include <sys/time.h>
6145900Ssklower 
6256533Sbostic #include <net/if.h>
6356533Sbostic #include <net/route.h>
6436398Ssklower 
6556533Sbostic #include <netiso/tp_param.h>
6656533Sbostic #include <netiso/argo_debug.h>
6756533Sbostic #include <netiso/tp_stat.h>
6856533Sbostic #include <netiso/tp_pcb.h>
6956533Sbostic #include <netiso/tp_trace.h>
7056533Sbostic #include <netiso/tp_stat.h>
7156533Sbostic #include <netiso/tp_tpdu.h>
7256533Sbostic #include <netiso/iso.h>
7356533Sbostic #include <netiso/iso_errno.h>
7456533Sbostic #include <netiso/iso_pcb.h>
7556533Sbostic #include <netiso/cons.h>
7656533Sbostic #include <netiso/tp_seq.h>
7736398Ssklower 
7845900Ssklower #undef FALSE
7945900Ssklower #undef TRUE
8056533Sbostic #include <netccitt/x25.h>
8156533Sbostic #include <netccitt/pk.h>
8256533Sbostic #include <netccitt/pk_var.h>
8345900Ssklower 
8456533Sbostic #include <netiso/if_cons.c>
8536398Ssklower int tpcons_output();
8636398Ssklower 
8736398Ssklower /*
8836398Ssklower  * CALLED FROM:
8945900Ssklower  *  tp_route_to() for PRU_CONNECT
9045900Ssklower  * FUNCTION, ARGUMENTS, SIDE EFFECTS and RETURN VALUE:
9145900Ssklower  *  version of the previous procedure for X.25
9245900Ssklower  */
9345900Ssklower 
9445900Ssklower tpcons_pcbconnect(isop, nam)
9545900Ssklower struct isopcb *isop;
9645900Ssklower register struct mbuf *nam;
9745900Ssklower {
9845900Ssklower 	int error;
9945900Ssklower 	if (error = iso_pcbconnect(isop, nam))
10045900Ssklower 		return error;
10145900Ssklower 	if ((isop->isop_chan = (caddr_t) pk_attach((struct socket *)0)) == 0) {
10245900Ssklower 		IFDEBUG(D_CCONS)
10345900Ssklower 			printf("tpcons_pcbconnect: no pklcd; returns 0x%x\n", error);
10445900Ssklower 		ENDDEBUG
10545900Ssklower 		return ENOBUFS;
10645900Ssklower 	}
10745900Ssklower 	if (error = cons_connect(isop)) { /* if it doesn't work */
10845900Ssklower 		/* oh, dear, throw packet away */
10945900Ssklower 		pk_disconnect((struct pklcd *)isop->isop_chan);
11045900Ssklower 		isop->isop_chan = 0;
11149257Ssklower 	} else
11249257Ssklower 		isop->isop_refcnt = 1;
11349257Ssklower 	return error;
11445900Ssklower }
11545900Ssklower 
11645900Ssklower 
11745900Ssklower /*
11845900Ssklower  * CALLED FROM:
11936398Ssklower  * 	cons
12036398Ssklower  * FUNCTION and ARGUMENTS:
12136398Ssklower  * THIS MAYBE BELONGS IN SOME OTHER PLACE??? but i think not -
12236398Ssklower  */
12336398Ssklower ProtoHook
tpcons_ctlinput(cmd,siso,isop)12436398Ssklower tpcons_ctlinput(cmd, siso, isop)
12536398Ssklower 	int cmd;
12636398Ssklower 	struct sockaddr_iso *siso;
12736398Ssklower 	struct isopcb *isop;
12836398Ssklower {
12950648Ssklower 	register struct tp_pcb *tpcb = 0;
13050648Ssklower 
13150648Ssklower 	if (isop->isop_socket)
13250648Ssklower 		tpcb = (struct tp_pcb *)isop->isop_socket->so_pcb;
13336398Ssklower 	switch (cmd) {
13436398Ssklower 
13536398Ssklower 	case PRC_CONS_SEND_DONE:
13650648Ssklower 		if (tpcb) {
13736398Ssklower 			struct 	tp_event 		E;
13836398Ssklower 			int 					error = 0;
13936398Ssklower 
14050648Ssklower 			if (tpcb->tp_class == TP_CLASS_0) {
14136398Ssklower 				/* only if class is exactly class zero, not
14236398Ssklower 				 * still in class negotiation
14336398Ssklower 				 */
14436398Ssklower 				/* fake an ack */
14536398Ssklower 				register SeqNum	seq =  SEQ_ADD(tpcb, tpcb->tp_snduna, 1);
14636398Ssklower 
14736398Ssklower 				IFTRACE(D_DATA)
14836398Ssklower 					tptrace(TPPTmisc, "FAKE ACK seq cdt 1",
14936398Ssklower 						seq, 0,0,0);
15036398Ssklower 				ENDTRACE
15136398Ssklower 				IFDEBUG(D_DATA)
15236398Ssklower 					printf("FAKE ACK seq 0x%x cdt 1\n", seq );
15336398Ssklower 				ENDDEBUG
15436398Ssklower 				E.ATTR(AK_TPDU).e_cdt = 1;
15536398Ssklower 				E.ATTR(AK_TPDU).e_seq = seq;
15636398Ssklower 				E.ATTR(AK_TPDU).e_subseq = 0;
15736398Ssklower 				E.ATTR(AK_TPDU).e_fcc_present = 0;
15836398Ssklower 				error =  DoEvent(AK_TPDU);
15936398Ssklower 				if( error ) {
16036398Ssklower 					tpcb->tp_sock->so_error = error;
16136398Ssklower 				}
16236398Ssklower 			} /* else ignore it */
16350648Ssklower 		}
16436398Ssklower 		break;
16536398Ssklower 	case PRC_ROUTEDEAD:
16650648Ssklower 		if (tpcb && tpcb->tp_class == TP_CLASS_0) {
16736398Ssklower 			tpiso_reset(isop);
16836398Ssklower 			break;
16936398Ssklower 		} /* else drop through */
17036398Ssklower 	default:
17136398Ssklower 		(void) tpclnp_ctlinput(cmd, siso);
17236398Ssklower 		break;
17336398Ssklower 	}
17436398Ssklower 	return 0;
17536398Ssklower }
17636398Ssklower 
17736398Ssklower /*
17836398Ssklower  * CALLED FROM:
17936398Ssklower  * 	cons's intr routine
18036398Ssklower  * FUNCTION and ARGUMENTS:
18136398Ssklower  * Take a packet (m) from cons, pullup m as required by tp,
18236398Ssklower  *  ignore the socket argument, and call tp_input.
18336398Ssklower  * No return value.
18436398Ssklower  */
18536398Ssklower ProtoHook
tpcons_input(m,faddr,laddr,channel)18645900Ssklower tpcons_input(m, faddr, laddr, channel)
18736398Ssklower 	struct mbuf 		*m;
18836398Ssklower 	struct sockaddr_iso	*faddr, *laddr;
18945900Ssklower 	caddr_t				channel;
19036398Ssklower {
19136398Ssklower 	if( m == MNULL)
19236398Ssklower 		return 0;
19336398Ssklower 
19436398Ssklower 	m = (struct mbuf *)tp_inputprep(m);
19536398Ssklower 
19636398Ssklower 	IFDEBUG(D_TPINPUT)
19736398Ssklower 		printf("tpcons_input before tp_input(m 0x%x)\n", m);
19836398Ssklower 		dump_buf( m, 12+ m->m_len);
19936398Ssklower 	ENDDEBUG
20048743Ssklower 	tp_input(m, faddr, laddr, channel, tpcons_output, 0);
20136398Ssklower 	return 0;
20236398Ssklower }
20336398Ssklower 
20436398Ssklower 
20536398Ssklower /*
20636398Ssklower  * CALLED FROM:
20736398Ssklower  *  tp_emit()
20836398Ssklower  * FUNCTION and ARGUMENTS:
20936398Ssklower  *  Take a packet(m0) from tp and package it so that cons will accept it.
21036398Ssklower  *  This means filling in a few of the fields.
21136398Ssklower  *  inp is the isopcb structure; datalen is the length of the data in the
21236398Ssklower  *  mbuf string m0.
21336398Ssklower  * RETURN VALUE:
21436398Ssklower  *  whatever (E*) is returned form the net layer output routine.
21536398Ssklower  */
21636398Ssklower 
21736398Ssklower int
tpcons_output(isop,m0,datalen,nochksum)21836398Ssklower tpcons_output(isop, m0, datalen, nochksum)
21936398Ssklower 	struct isopcb		*isop;
22036398Ssklower 	struct mbuf 		*m0;
22136398Ssklower 	int 				datalen;
22236398Ssklower 	int					nochksum;
22336398Ssklower {
22445900Ssklower 	register	struct mbuf *m = m0;
22536398Ssklower 	int					error;
22636398Ssklower 
22736398Ssklower 	IFDEBUG(D_EMIT)
22836398Ssklower 		printf(
22936398Ssklower 		"tpcons_output(isop 0x%x, m 0x%x, len 0x%x socket 0x%x\n",
23036398Ssklower 			isop, m0, datalen, isop->isop_socket);
23136398Ssklower 	ENDDEBUG
23245900Ssklower 	if (m == MNULL)
23336398Ssklower 		return 0;
23449586Ssklower 	if ((m->m_flags & M_PKTHDR) == 0) {
23545900Ssklower 		MGETHDR(m, M_DONTWAIT, MT_DATA);
23645900Ssklower 		if (m == 0)
23745900Ssklower 			return ENOBUFS;
23845900Ssklower 		m->m_next = m0;
23945900Ssklower 	}
24045900Ssklower 	m->m_pkthdr.len = datalen;
24150648Ssklower 	if (isop->isop_chan == 0) {
24250648Ssklower 		/* got a restart maybe? */
24350648Ssklower 		if ((isop->isop_chan = (caddr_t) pk_attach((struct socket *)0)) == 0) {
24450648Ssklower 			IFDEBUG(D_CCONS)
24550648Ssklower 				printf("tpcons_output: no pklcd\n");
24650648Ssklower 			ENDDEBUG
24750648Ssklower 			error = ENOBUFS;
24850648Ssklower 		}
24950648Ssklower 		if (error = cons_connect(isop)) {
25050648Ssklower 			pk_disconnect((struct pklcd *)isop->isop_chan);
25150648Ssklower 			isop->isop_chan = 0;
25250648Ssklower 			IFDEBUG(D_CCONS)
25350648Ssklower 				printf("tpcons_output: can't reconnect\n");
25450648Ssklower 			ENDDEBUG
25550648Ssklower 		}
25650648Ssklower 	} else {
25750648Ssklower 		error = pk_send(isop->isop_chan, m);
25850648Ssklower 		IncStat(ts_tpdu_sent);
25950648Ssklower 	}
26036398Ssklower 	return error;
26136398Ssklower }
26236398Ssklower /*
26336398Ssklower  * CALLED FROM:
26436398Ssklower  *  tp_error_emit()
26536398Ssklower  * FUNCTION and ARGUMENTS:
26645900Ssklower  *  Take a packet(m0) from tp and package it so that cons will accept it.
26745900Ssklower  *  chan is the cons channel to use; datalen is the length of the data in the
26845900Ssklower  *  mbuf string m0.
26936398Ssklower  * RETURN VALUE:
27036398Ssklower  *  whatever (E*) is returned form the net layer output routine.
27136398Ssklower  */
27236398Ssklower 
27336398Ssklower int
tpcons_dg_output(chan,m0,datalen)27445900Ssklower tpcons_dg_output(chan, m0, datalen)
27545900Ssklower 	caddr_t				chan;
27636398Ssklower 	struct mbuf 		*m0;
27736398Ssklower 	int 				datalen;
27836398Ssklower {
27945900Ssklower 	return tpcons_output(((struct pklcd *)chan)->lcd_upnext, m0, datalen, 0);
28036398Ssklower }
28160359Sbostic #endif /* TPCONS */
28260359Sbostic #endif /* ISO */
283