xref: /csrg-svn/sys/netiso/tp_cons.c (revision 36398)
1*36398Ssklower /***********************************************************
2*36398Ssklower 		Copyright IBM Corporation 1987
3*36398Ssklower 
4*36398Ssklower                       All Rights Reserved
5*36398Ssklower 
6*36398Ssklower Permission to use, copy, modify, and distribute this software and its
7*36398Ssklower documentation for any purpose and without fee is hereby granted,
8*36398Ssklower provided that the above copyright notice appear in all copies and that
9*36398Ssklower both that copyright notice and this permission notice appear in
10*36398Ssklower supporting documentation, and that the name of IBM not be
11*36398Ssklower used in advertising or publicity pertaining to distribution of the
12*36398Ssklower software without specific, written prior permission.
13*36398Ssklower 
14*36398Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15*36398Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16*36398Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17*36398Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18*36398Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19*36398Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20*36398Ssklower SOFTWARE.
21*36398Ssklower 
22*36398Ssklower ******************************************************************/
23*36398Ssklower 
24*36398Ssklower /*
25*36398Ssklower  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
26*36398Ssklower  */
27*36398Ssklower /*
28*36398Ssklower  * ARGO TP
29*36398Ssklower  * $Header: tp_cons.c,v 5.6 88/11/18 17:27:13 nhall Exp $
30*36398Ssklower  * $Source: /usr/argo/sys/netiso/RCS/tp_cons.c,v $
31*36398Ssklower  *
32*36398Ssklower  * Here is where you find the iso-dependent code.  We've tried
33*36398Ssklower  * keep all net-level and (primarily) address-family-dependent stuff
34*36398Ssklower  * out of the tp source, and everthing here is reached indirectly
35*36398Ssklower  * through a switch table (struct nl_protosw *) tpcb->tp_nlproto
36*36398Ssklower  * (see tp_pcb.c).
37*36398Ssklower  * The routines here are:
38*36398Ssklower  *		tpcons_mtu: figure out what size tpdu to use
39*36398Ssklower  *		tpcons_input: pullup and call tp_input w/ correct arguments
40*36398Ssklower  *		tpcons_output_dg: package a pkt for cons given 2 addresses & some data
41*36398Ssklower  *		tpcons_output: package a pkt for cons given an isopcb & some data
42*36398Ssklower  *		cons_chan_to_tpcb: find a tpcb based on the channel #
43*36398Ssklower  */
44*36398Ssklower 
45*36398Ssklower #ifndef lint
46*36398Ssklower static char *rcsid = "$Header: tp_cons.c,v 5.6 88/11/18 17:27:13 nhall Exp $";
47*36398Ssklower #endif lint
48*36398Ssklower 
49*36398Ssklower #include "argoxtwentyfive.h"
50*36398Ssklower 
51*36398Ssklower #ifdef ISO
52*36398Ssklower #if NARGOXTWENTYFIVE > 0
53*36398Ssklower 
54*36398Ssklower #include "types.h"
55*36398Ssklower #include "socket.h"
56*36398Ssklower #include "domain.h"
57*36398Ssklower #include "mbuf.h"
58*36398Ssklower #include "errno.h"
59*36398Ssklower #include "time.h"
60*36398Ssklower #include "../net/if.h"
61*36398Ssklower 
62*36398Ssklower #include "../netiso/tp_param.h"
63*36398Ssklower #include "../netiso/argo_debug.h"
64*36398Ssklower #include "../netiso/tp_stat.h"
65*36398Ssklower #include "../netiso/tp_pcb.h"
66*36398Ssklower #include "../netiso/tp_trace.h"
67*36398Ssklower #include "../netiso/tp_stat.h"
68*36398Ssklower #include "../netiso/tp_tpdu.h"
69*36398Ssklower #include "../net/route.h"
70*36398Ssklower #include "../netiso/iso.h"
71*36398Ssklower #include "../netiso/iso_pcb.h"
72*36398Ssklower #include "../netiso/cons.h"
73*36398Ssklower #include "../netiso/tp_seq.h"
74*36398Ssklower 
75*36398Ssklower int tpcons_output();
76*36398Ssklower 
77*36398Ssklower /*
78*36398Ssklower  * CALLED FROM:
79*36398Ssklower  *  tp_input() on incoming CR, CC, and pr_usrreq() for PRU_CONNECT
80*36398Ssklower  * FUNCTION, ARGUMENTS, SIDE EFFECTS and RETURN VALUE:
81*36398Ssklower  *  version of the previous procedure for X.25
82*36398Ssklower  */
83*36398Ssklower 
84*36398Ssklower void
85*36398Ssklower tpcons_mtu(so, isop, size, negot)
86*36398Ssklower 	struct socket *so;
87*36398Ssklower 	struct isopcb *isop;
88*36398Ssklower 	int *size;
89*36398Ssklower 	u_char *negot;
90*36398Ssklower {
91*36398Ssklower 	register struct ifnet *ifp;
92*36398Ssklower 	register int i=0;
93*36398Ssklower 	int windowsize = so->so_rcv.sb_hiwat;
94*36398Ssklower 	struct ifnet	*iso_routeifp();
95*36398Ssklower 
96*36398Ssklower 	IFTRACE(D_CONN)
97*36398Ssklower 		tptrace(TPPTmisc, "ENTER GET MTU: size negot ",*size, *negot, 0, 0);
98*36398Ssklower 	ENDTRACE
99*36398Ssklower 
100*36398Ssklower 
101*36398Ssklower 	*size = 1 << *negot;
102*36398Ssklower 	if ((ifp = iso_routeifp(&isop->isop_faddr)) == (struct ifnet *)0)
103*36398Ssklower 		return;
104*36398Ssklower 
105*36398Ssklower 	if( *size > windowsize ) {
106*36398Ssklower 		*size = windowsize;
107*36398Ssklower 		i++;
108*36398Ssklower 	}
109*36398Ssklower 
110*36398Ssklower 	if(*size > ifp->if_mtu) {
111*36398Ssklower 		*size = ifp->if_mtu ;
112*36398Ssklower 		i++;
113*36398Ssklower 	}
114*36398Ssklower 	if(i) {
115*36398Ssklower 		/* size was changed by this routine - have to transform it to
116*36398Ssklower 		 * the log2 of size
117*36398Ssklower 		 */
118*36398Ssklower 		for(i=TP_MIN_TPDUSIZE; (i<TP_MAX_TPDUSIZE && ((1<<i)<*size)) ; i++)
119*36398Ssklower 			;
120*36398Ssklower 		/* are we on the same LAN? if so, negotiate one tpdu size larger,
121*36398Ssklower 		 * and actually send the real mtu size
122*36398Ssklower 		 */
123*36398Ssklower 		/* PHASE2: replace with iso_on_localnet(&isop->isop_faddr);
124*36398Ssklower 		 */
125*36398Ssklower 		if ( !iso_netmatch(&isop->isop_laddr, &isop->isop_faddr) ) {
126*36398Ssklower 			i--;
127*36398Ssklower 			*size = 1<<i;
128*36398Ssklower 		}
129*36398Ssklower 		*negot = i;
130*36398Ssklower 	}
131*36398Ssklower 
132*36398Ssklower 	IFDEBUG(D_CONN)
133*36398Ssklower 		printf("GET MTU RETURNS: ifp %s size 0x%x negot 0x%x\n",
134*36398Ssklower 		ifp->if_name,	*size, *negot);
135*36398Ssklower 	ENDDEBUG
136*36398Ssklower 	IFTRACE(D_CONN)
137*36398Ssklower 		tptrace(TPPTmisc, "EXIT GET MTU: tpcb size negot ",
138*36398Ssklower 		*size, *negot, 0, 0);
139*36398Ssklower 	ENDTRACE
140*36398Ssklower }
141*36398Ssklower 
142*36398Ssklower /*
143*36398Ssklower  * CALLED FROM:
144*36398Ssklower  * 	cons
145*36398Ssklower  * FUNCTION and ARGUMENTS:
146*36398Ssklower  * THIS MAYBE BELONGS IN SOME OTHER PLACE??? but i think not -
147*36398Ssklower  */
148*36398Ssklower ProtoHook
149*36398Ssklower tpcons_ctlinput(cmd, siso, isop)
150*36398Ssklower 	int cmd;
151*36398Ssklower 	struct sockaddr_iso *siso;
152*36398Ssklower 	struct isopcb *isop;
153*36398Ssklower {
154*36398Ssklower 	switch (cmd) {
155*36398Ssklower 
156*36398Ssklower 	case PRC_CONS_SEND_DONE:
157*36398Ssklower 		if( isop->isop_socket ) { /* tp 0 only */
158*36398Ssklower 			register struct tp_pcb *tpcb =
159*36398Ssklower 				(struct tp_pcb *)isop->isop_socket->so_tpcb;
160*36398Ssklower 			struct 	tp_event 		E;
161*36398Ssklower 			int 					error = 0;
162*36398Ssklower 
163*36398Ssklower 			if( tpcb->tp_class == TP_CLASS_0 ) {
164*36398Ssklower 				/* only if class is exactly class zero, not
165*36398Ssklower 				 * still in class negotiation
166*36398Ssklower 				 */
167*36398Ssklower 				/* fake an ack */
168*36398Ssklower 				register SeqNum	seq =  SEQ_ADD(tpcb, tpcb->tp_snduna, 1);
169*36398Ssklower 
170*36398Ssklower 				IFTRACE(D_DATA)
171*36398Ssklower 					tptrace(TPPTmisc, "FAKE ACK seq cdt 1",
172*36398Ssklower 						seq, 0,0,0);
173*36398Ssklower 				ENDTRACE
174*36398Ssklower 				IFDEBUG(D_DATA)
175*36398Ssklower 					printf("FAKE ACK seq 0x%x cdt 1\n", seq );
176*36398Ssklower 				ENDDEBUG
177*36398Ssklower 				E.ATTR(AK_TPDU).e_cdt = 1;
178*36398Ssklower 				E.ATTR(AK_TPDU).e_seq = seq;
179*36398Ssklower 				E.ATTR(AK_TPDU).e_subseq = 0;
180*36398Ssklower 				E.ATTR(AK_TPDU).e_fcc_present = 0;
181*36398Ssklower 				error =  DoEvent(AK_TPDU);
182*36398Ssklower 				if( error ) {
183*36398Ssklower 					tpcb->tp_sock->so_error = error;
184*36398Ssklower 				}
185*36398Ssklower 			} /* else ignore it */
186*36398Ssklower 		}
187*36398Ssklower 		break;
188*36398Ssklower 	case PRC_ROUTEDEAD:
189*36398Ssklower 		if( isop->isop_socket ) { /* tp 0 only */
190*36398Ssklower 			tpiso_reset(isop);
191*36398Ssklower 			break;
192*36398Ssklower 		} /* else drop through */
193*36398Ssklower 	default:
194*36398Ssklower 		(void) tpclnp_ctlinput(cmd, siso);
195*36398Ssklower 		break;
196*36398Ssklower 	}
197*36398Ssklower 	return 0;
198*36398Ssklower }
199*36398Ssklower 
200*36398Ssklower /*
201*36398Ssklower  * CALLED FROM:
202*36398Ssklower  * 	cons's intr routine
203*36398Ssklower  * FUNCTION and ARGUMENTS:
204*36398Ssklower  * Take a packet (m) from cons, pullup m as required by tp,
205*36398Ssklower  *  ignore the socket argument, and call tp_input.
206*36398Ssklower  * No return value.
207*36398Ssklower  */
208*36398Ssklower ProtoHook
209*36398Ssklower tpcons_input(m, faddr, laddr, so, channel)
210*36398Ssklower 	struct mbuf 		*m;
211*36398Ssklower 	struct sockaddr_iso	*faddr, *laddr;
212*36398Ssklower 	struct socket 		*so; /* not used */
213*36398Ssklower 	int					channel;
214*36398Ssklower {
215*36398Ssklower 	if( m == MNULL)
216*36398Ssklower 		return 0;
217*36398Ssklower 
218*36398Ssklower 	m = (struct mbuf *)tp_inputprep(m);
219*36398Ssklower 
220*36398Ssklower 	IFDEBUG(D_TPINPUT)
221*36398Ssklower 		printf("tpcons_input before tp_input(m 0x%x)\n", m);
222*36398Ssklower 		dump_buf( m, 12+ m->m_len);
223*36398Ssklower 	ENDDEBUG
224*36398Ssklower 	tp_input(m, faddr, laddr, channel, tpcons_output);
225*36398Ssklower 	return 0;
226*36398Ssklower }
227*36398Ssklower 
228*36398Ssklower 
229*36398Ssklower /*
230*36398Ssklower  * CALLED FROM:
231*36398Ssklower  *  tp_emit()
232*36398Ssklower  * FUNCTION and ARGUMENTS:
233*36398Ssklower  *  Take a packet(m0) from tp and package it so that cons will accept it.
234*36398Ssklower  *  This means filling in a few of the fields.
235*36398Ssklower  *  inp is the isopcb structure; datalen is the length of the data in the
236*36398Ssklower  *  mbuf string m0.
237*36398Ssklower  * RETURN VALUE:
238*36398Ssklower  *  whatever (E*) is returned form the net layer output routine.
239*36398Ssklower  */
240*36398Ssklower 
241*36398Ssklower int
242*36398Ssklower tpcons_output(isop, m0, datalen, nochksum)
243*36398Ssklower 	struct isopcb		*isop;
244*36398Ssklower 	struct mbuf 		*m0;
245*36398Ssklower 	int 				datalen;
246*36398Ssklower 	int					nochksum;
247*36398Ssklower {
248*36398Ssklower 	struct tp_pcb 		*tpcb;
249*36398Ssklower 	int					error;
250*36398Ssklower 
251*36398Ssklower 	IFDEBUG(D_EMIT)
252*36398Ssklower 		printf(
253*36398Ssklower 		"tpcons_output(isop 0x%x, m 0x%x, len 0x%x socket 0x%x\n",
254*36398Ssklower 			isop, m0, datalen, isop->isop_socket);
255*36398Ssklower 	ENDDEBUG
256*36398Ssklower 	if(m0 == MNULL)
257*36398Ssklower 		return 0;
258*36398Ssklower 	ASSERT(m0->m_len > 0);
259*36398Ssklower 	tpcb = (struct tp_pcb *)isop->isop_socket->so_tpcb;
260*36398Ssklower 
261*36398Ssklower 	/* check is for class EQUAL to 4: if still in negotiation stage,
262*36398Ssklower 	 * cannot send as dgm
263*36398Ssklower 	 */
264*36398Ssklower 	error = cons_output(isop, m0,  datalen, (tpcb->tp_class == TP_CLASS_4));
265*36398Ssklower 	IncStat(ts_tpdu_sent);
266*36398Ssklower 
267*36398Ssklower 	IFTRACE(D_EMIT)
268*36398Ssklower 		tptrace( TPPTmisc,
269*36398Ssklower 		"tpcons_output( isop  m isdgm cons_output returns",
270*36398Ssklower 			isop, m0, (tpcb->tp_class == TP_CLASS_4), error );
271*36398Ssklower 	ENDTRACE
272*36398Ssklower 	return error;
273*36398Ssklower }
274*36398Ssklower 
275*36398Ssklower /*
276*36398Ssklower  * CALLED FROM:
277*36398Ssklower  *  tp_error_emit()
278*36398Ssklower  * FUNCTION and ARGUMENTS:
279*36398Ssklower  *  This is a copy of tpcons_output that takes the addresses
280*36398Ssklower  *  instead of a pcb.  It's used by the tp_error_emit, when we
281*36398Ssklower  *  don't have an iso_pcb with which to call the normal output rtn.
282*36398Ssklower  * RETURN VALUE:
283*36398Ssklower  *  ENOBUFS or
284*36398Ssklower  *  whatever (E*) is returned form the net layer output routine.
285*36398Ssklower  */
286*36398Ssklower 
287*36398Ssklower int
288*36398Ssklower tpcons_output_dg(laddr, faddr, m0, datalen, ro, nochksum)
289*36398Ssklower 	struct iso_addr		*laddr, *faddr;
290*36398Ssklower 	struct mbuf 		*m0;
291*36398Ssklower 	int 				datalen;
292*36398Ssklower 	struct route 		*ro;
293*36398Ssklower 	int					nochksum;
294*36398Ssklower {
295*36398Ssklower 	IFDEBUG(D_TPISO)
296*36398Ssklower 		printf("PANIC: tpcons_output_dg  datalen 0x%x m0 0x%x\n", datalen, m0);
297*36398Ssklower 	ENDDEBUG
298*36398Ssklower 
299*36398Ssklower 	return 0;
300*36398Ssklower }
301*36398Ssklower 
302*36398Ssklower struct tp_pcb *
303*36398Ssklower cons_chan_to_tpcb(chan)
304*36398Ssklower 	int chan;
305*36398Ssklower {
306*36398Ssklower 	extern struct isopcb *cons_chan_to_pcb ();
307*36398Ssklower #ifdef ARGO_DEBUG
308*36398Ssklower 	struct isopcb *isop = cons_chan_to_pcb (chan, -1);
309*36398Ssklower #else ARGO_DEBUG
310*36398Ssklower 	struct isopcb *isop = cons_chan_to_pcb (chan);
311*36398Ssklower #endif ARGO_DEBUG
312*36398Ssklower 
313*36398Ssklower 	IFTRACE(D_CONN)
314*36398Ssklower 		tptrace(TPPTmisc, "vc->tpcb(chan) socket",
315*36398Ssklower 			chan, isop->isop_socket, 0, 0);
316*36398Ssklower 	ENDTRACE
317*36398Ssklower 	IFDEBUG(D_CONN)
318*36398Ssklower 		printf("vc->tpcb(0x%x) socket 0x%x, *ISOP dump:",
319*36398Ssklower 			chan, isop->isop_socket);
320*36398Ssklower 		dump_buf( isop, 32);
321*36398Ssklower 	ENDDEBUG
322*36398Ssklower 	if( isop->isop_socket == (struct socket *)0 )
323*36398Ssklower 		return (struct tp_pcb *) 0;
324*36398Ssklower 	else {
325*36398Ssklower 		return (struct tp_pcb *)(isop->isop_socket->so_tpcb);
326*36398Ssklower }
327*36398Ssklower }
328*36398Ssklower #endif NARGOXTWENTYFIVE
329*36398Ssklower #endif ISO
330