xref: /csrg-svn/sys/netiso/tp_subr2.c (revision 36414)
1*36414Ssklower /***********************************************************
2*36414Ssklower 		Copyright IBM Corporation 1987
3*36414Ssklower 
4*36414Ssklower                       All Rights Reserved
5*36414Ssklower 
6*36414Ssklower Permission to use, copy, modify, and distribute this software and its
7*36414Ssklower documentation for any purpose and without fee is hereby granted,
8*36414Ssklower provided that the above copyright notice appear in all copies and that
9*36414Ssklower both that copyright notice and this permission notice appear in
10*36414Ssklower supporting documentation, and that the name of IBM not be
11*36414Ssklower used in advertising or publicity pertaining to distribution of the
12*36414Ssklower software without specific, written prior permission.
13*36414Ssklower 
14*36414Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15*36414Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16*36414Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17*36414Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18*36414Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19*36414Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20*36414Ssklower SOFTWARE.
21*36414Ssklower 
22*36414Ssklower ******************************************************************/
23*36414Ssklower 
24*36414Ssklower /*
25*36414Ssklower  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
26*36414Ssklower  */
27*36414Ssklower /*
28*36414Ssklower  * ARGO TP
29*36414Ssklower  *
30*36414Ssklower  * $Header: tp_subr2.c,v 5.5 88/11/18 17:28:55 nhall Exp $
31*36414Ssklower  * $Source: /usr/argo/sys/netiso/RCS/tp_subr2.c,v $
32*36414Ssklower  *
33*36414Ssklower  * Some auxiliary routines:
34*36414Ssklower  * 		tp_protocol_error: required by xebec- called when a combo of state,
35*36414Ssklower  *			event, predicate isn't covered for by the transition file.
36*36414Ssklower  *		tp_indicate: gives indications(signals) to the user process
37*36414Ssklower  *		tp_getoptions: initializes variables that are affected by the options
38*36414Ssklower  *          chosen.
39*36414Ssklower  */
40*36414Ssklower 
41*36414Ssklower #ifndef lint
42*36414Ssklower static char *rcsid = "$Header: tp_subr2.c,v 5.5 88/11/18 17:28:55 nhall Exp $";
43*36414Ssklower #endif lint
44*36414Ssklower 
45*36414Ssklower #include "argoxtwentyfive.h"
46*36414Ssklower 
47*36414Ssklower /* this def'n is to cause the expansion of this macro in the
48*36414Ssklower  * routine tp_local_credit :
49*36414Ssklower  */
50*36414Ssklower #define LOCAL_CREDIT_EXPAND
51*36414Ssklower 
52*36414Ssklower #include "param.h"
53*36414Ssklower #include "mbuf.h"
54*36414Ssklower #include "socket.h"
55*36414Ssklower #include "socketvar.h"
56*36414Ssklower #include "domain.h"
57*36414Ssklower #include "protosw.h"
58*36414Ssklower #include "errno.h"
59*36414Ssklower #include "types.h"
60*36414Ssklower #include "time.h"
61*36414Ssklower #include "kernel.h"
62*36414Ssklower #undef MNULL
63*36414Ssklower #include "../netiso/tp_ip.h"
64*36414Ssklower #include "../netiso/tp_param.h"
65*36414Ssklower #include "../netiso/tp_timer.h"
66*36414Ssklower #include "../netiso/tp_stat.h"
67*36414Ssklower #include "../netiso/argo_debug.h"
68*36414Ssklower #include "../netiso/tp_tpdu.h"
69*36414Ssklower #include "../netiso/iso.h"
70*36414Ssklower #include "../netiso/iso_errno.h"
71*36414Ssklower #include "../netiso/tp_pcb.h"
72*36414Ssklower #include "../netiso/tp_seq.h"
73*36414Ssklower #include "../netiso/tp_trace.h"
74*36414Ssklower #include "../netiso/iso_pcb.h"
75*36414Ssklower #include "../netiso/tp_user.h"
76*36414Ssklower #include "../netiso/cons.h"
77*36414Ssklower 
78*36414Ssklower /*
79*36414Ssklower  * NAME: 	tp_local_credit()
80*36414Ssklower  *
81*36414Ssklower  * CALLED FROM:
82*36414Ssklower  *  tp_emit(), tp_usrreq()
83*36414Ssklower  *
84*36414Ssklower  * FUNCTION and ARGUMENTS:
85*36414Ssklower  *	Computes the local credit and stashes it in tpcb->tp_lcredit.
86*36414Ssklower  *  It's a macro in the production system rather than a procdure.
87*36414Ssklower  *
88*36414Ssklower  * RETURNS:
89*36414Ssklower  *
90*36414Ssklower  * SIDE EFFECTS:
91*36414Ssklower  *
92*36414Ssklower  * NOTES:
93*36414Ssklower  *  This doesn't actually get called in a production system -
94*36414Ssklower  *  the macro gets expanded instead in place of calls to this proc.
95*36414Ssklower  *  But for debugging, we call this and that allows us to add
96*36414Ssklower  *  debugging messages easily here.
97*36414Ssklower  */
98*36414Ssklower void
99*36414Ssklower tp_local_credit(tpcb)
100*36414Ssklower 	struct tp_pcb *tpcb;
101*36414Ssklower {
102*36414Ssklower 	LOCAL_CREDIT(tpcb);
103*36414Ssklower 	IFDEBUG(D_CREDIT)
104*36414Ssklower 		printf("ref 0x%x lcdt 0x%x l_tpdusize 0x%x decbit 0x%x\n",
105*36414Ssklower 			tpcb->tp_refp - tp_ref,
106*36414Ssklower 			tpcb->tp_lcredit,
107*36414Ssklower 			tpcb->tp_l_tpdusize,
108*36414Ssklower 			tpcb->tp_decbit,
109*36414Ssklower 			tpcb->tp_cong_win
110*36414Ssklower 			);
111*36414Ssklower 	ENDDEBUG
112*36414Ssklower 	IFTRACE(D_CREDIT)
113*36414Ssklower 		tptraceTPCB(TPPTmisc,
114*36414Ssklower 			"lcdt tpdusz \n",
115*36414Ssklower 			 tpcb->tp_lcredit, tpcb->tp_l_tpdusize, 0, 0);
116*36414Ssklower 	ENDTRACE
117*36414Ssklower }
118*36414Ssklower 
119*36414Ssklower /*
120*36414Ssklower  * NAME:  tp_protocol_error()
121*36414Ssklower  *
122*36414Ssklower  * CALLED FROM:
123*36414Ssklower  *  tp_driver(), when it doesn't know what to do with
124*36414Ssklower  * 	a combo of event, state, predicate
125*36414Ssklower  *
126*36414Ssklower  * FUNCTION and ARGUMENTS:
127*36414Ssklower  *  print error mesg
128*36414Ssklower  *
129*36414Ssklower  * RETURN VALUE:
130*36414Ssklower  *  EIO - always
131*36414Ssklower  *
132*36414Ssklower  * SIDE EFFECTS:
133*36414Ssklower  *
134*36414Ssklower  * NOTES:
135*36414Ssklower  */
136*36414Ssklower int
137*36414Ssklower tp_protocol_error(e,tpcb)
138*36414Ssklower 	struct tp_event	*e;
139*36414Ssklower 	struct tp_pcb	*tpcb;
140*36414Ssklower {
141*36414Ssklower 	printf("TP PROTOCOL ERROR! tpcb 0x%x event 0x%x, state 0x%x\n",
142*36414Ssklower 		tpcb, e->ev_number, tpcb->tp_state);
143*36414Ssklower 	IFTRACE(D_DRIVER)
144*36414Ssklower 		tptraceTPCB(TPPTmisc, "PROTOCOL ERROR tpcb event state",
145*36414Ssklower 			tpcb, e->ev_number, tpcb->tp_state, 0 );
146*36414Ssklower 	ENDTRACE
147*36414Ssklower 	return EIO; /* for lack of anything better */
148*36414Ssklower }
149*36414Ssklower 
150*36414Ssklower 
151*36414Ssklower /* Not used at the moment */
152*36414Ssklower ProtoHook
153*36414Ssklower tp_drain()
154*36414Ssklower {
155*36414Ssklower 	return 0;
156*36414Ssklower }
157*36414Ssklower 
158*36414Ssklower 
159*36414Ssklower /*
160*36414Ssklower  * NAME: tp_indicate()
161*36414Ssklower  *
162*36414Ssklower  * CALLED FROM:
163*36414Ssklower  * 	tp.trans when XPD arrive, when a connection is being disconnected by
164*36414Ssklower  *  the arrival of a DR or ER, and when a connection times out.
165*36414Ssklower  *
166*36414Ssklower  * FUNCTION and ARGUMENTS:
167*36414Ssklower  *  (ind) is the type of indication : T_DISCONNECT, T_XPD
168*36414Ssklower  *  (error) is an E* value that will be put in the socket structure
169*36414Ssklower  *  to be passed along to the user later.
170*36414Ssklower  * 	Gives a SIGURG to the user process or group indicated by the socket
171*36414Ssklower  * 	attached to the tpcb.
172*36414Ssklower  *
173*36414Ssklower  * RETURNS:  Rien
174*36414Ssklower  *
175*36414Ssklower  * SIDE EFFECTS:
176*36414Ssklower  *
177*36414Ssklower  * NOTES:
178*36414Ssklower  */
179*36414Ssklower void
180*36414Ssklower tp_indicate(ind, tpcb, error)
181*36414Ssklower 	int				ind;
182*36414Ssklower 	u_short			error;
183*36414Ssklower 	register struct tp_pcb	*tpcb;
184*36414Ssklower {
185*36414Ssklower 	register struct socket *so = tpcb->tp_sock;
186*36414Ssklower 	IFTRACE(D_INDICATION)
187*36414Ssklower 		tptraceTPCB(TPPTindicate, ind, *(int *)(tpcb->tp_lsuffix),
188*36414Ssklower 			*(int *)(tpcb->tp_fsuffix), error,so->so_pgrp);
189*36414Ssklower 	ENDTRACE
190*36414Ssklower 	IFDEBUG(D_INDICATION)
191*36414Ssklower 		u_char *ls, *fs;
192*36414Ssklower 		ls = tpcb->tp_lsuffix,
193*36414Ssklower 		fs = tpcb->tp_fsuffix,
194*36414Ssklower 
195*36414Ssklower 		printf(
196*36414Ssklower "indicate 0x%x lsuf 0x%02x%02x fsuf 0x%02x%02x err 0x%x prgp 0x%x noind 0x%x ref 0x%x\n",
197*36414Ssklower 		ind,
198*36414Ssklower 		*ls, *(ls+1), *fs, *(fs+1),
199*36414Ssklower 		error,so->so_pgrp,
200*36414Ssklower 		tpcb->tp_no_disc_indications,
201*36414Ssklower 		tpcb->tp_lref);
202*36414Ssklower 	ENDDEBUG
203*36414Ssklower 
204*36414Ssklower 	so->so_error = error;
205*36414Ssklower 
206*36414Ssklower 	if (ind == T_DISCONNECT)  {
207*36414Ssklower 		if ( tpcb->tp_no_disc_indications )
208*36414Ssklower 			return;
209*36414Ssklower 	}
210*36414Ssklower 	IFTRACE(D_INDICATION)
211*36414Ssklower 		tptraceTPCB(TPPTmisc, "doing sohasoutofband(so)", so,0,0,0);
212*36414Ssklower 	ENDTRACE
213*36414Ssklower 	sohasoutofband(so);
214*36414Ssklower }
215*36414Ssklower 
216*36414Ssklower /*
217*36414Ssklower  * NAME : tp_getoptions()
218*36414Ssklower  *
219*36414Ssklower  * CALLED FROM:
220*36414Ssklower  * 	tp.trans whenever we go into OPEN state
221*36414Ssklower  *
222*36414Ssklower  * FUNCTION and ARGUMENTS:
223*36414Ssklower  *  sets the proper flags and values in the tpcb, to control
224*36414Ssklower  *  the appropriate actions for the given class, options,
225*36414Ssklower  *  sequence space, etc, etc.
226*36414Ssklower  *
227*36414Ssklower  * RETURNS: Nada
228*36414Ssklower  *
229*36414Ssklower  * SIDE EFFECTS:
230*36414Ssklower  *
231*36414Ssklower  * NOTES:
232*36414Ssklower  */
233*36414Ssklower void
234*36414Ssklower tp_getoptions(tpcb)
235*36414Ssklower struct tp_pcb *tpcb;
236*36414Ssklower {
237*36414Ssklower 	tpcb->tp_seqmask =
238*36414Ssklower 		tpcb->tp_xtd_format ?	TP_XTD_FMT_MASK :	TP_NML_FMT_MASK ;
239*36414Ssklower 	tpcb->tp_seqbit =
240*36414Ssklower 		tpcb->tp_xtd_format ?	TP_XTD_FMT_BIT :	TP_NML_FMT_BIT ;
241*36414Ssklower 	tpcb->tp_seqhalf = tpcb->tp_seqbit >> 1;
242*36414Ssklower 	tpcb->tp_dt_ticks =
243*36414Ssklower 		MAX(tpcb->tp_dt_ticks, (tpcb->tp_peer_acktime + 2));
244*36414Ssklower 
245*36414Ssklower }
246*36414Ssklower 
247*36414Ssklower /*
248*36414Ssklower  * NAME:  tp_recycle_tsuffix()
249*36414Ssklower  *
250*36414Ssklower  * CALLED FROM:
251*36414Ssklower  *  Called when a ref is frozen.
252*36414Ssklower  *
253*36414Ssklower  * FUNCTION and ARGUMENTS:
254*36414Ssklower  *  allows the suffix to be reused.
255*36414Ssklower  *
256*36414Ssklower  * RETURNS: zilch
257*36414Ssklower  *
258*36414Ssklower  * SIDE EFFECTS:
259*36414Ssklower  *
260*36414Ssklower  * NOTES:
261*36414Ssklower  */
262*36414Ssklower void
263*36414Ssklower tp_recycle_tsuffix(tpcb)
264*36414Ssklower 	struct tp_pcb	*tpcb;
265*36414Ssklower {
266*36414Ssklower 	bzero( tpcb->tp_lsuffix, sizeof( tpcb->tp_lsuffix));
267*36414Ssklower 	bzero( tpcb->tp_fsuffix, sizeof( tpcb->tp_fsuffix));
268*36414Ssklower 	tpcb->tp_fsuffixlen = tpcb->tp_lsuffixlen = 0;
269*36414Ssklower 
270*36414Ssklower 	(tpcb->tp_nlproto->nlp_recycle_suffix)(tpcb->tp_npcb);
271*36414Ssklower }
272*36414Ssklower 
273*36414Ssklower /*
274*36414Ssklower  * NAME: tp_quench()
275*36414Ssklower  *
276*36414Ssklower  * CALLED FROM:
277*36414Ssklower  *  tp{af}_quench() when ICMP source quench or similar thing arrives.
278*36414Ssklower  *
279*36414Ssklower  * FUNCTION and ARGUMENTS:
280*36414Ssklower  *  Drop the congestion window back to 1.
281*36414Ssklower  *  Congestion window scheme:
282*36414Ssklower  *  Initial value is 1.  ("slow start" as Nagle, et. al. call it)
283*36414Ssklower  *  For each good ack that arrives, the congestion window is increased
284*36414Ssklower  *  by 1 (up to max size of logical infinity, which is to say,
285*36414Ssklower  *	it doesn't wrap around).
286*36414Ssklower  *  Source quench causes it to drop back to 1.
287*36414Ssklower  *  tp_send() uses the smaller of (regular window, congestion window).
288*36414Ssklower  *  One retransmission strategy option is to have any retransmission
289*36414Ssklower  *	cause reset the congestion window back  to 1.
290*36414Ssklower  *
291*36414Ssklower  *	(cmd) is either PRC_QUENCH: source quench, or
292*36414Ssklower  *		PRC_QUENCH2: dest. quench (dec bit)
293*36414Ssklower  *
294*36414Ssklower  * RETURNS:
295*36414Ssklower  *
296*36414Ssklower  * SIDE EFFECTS:
297*36414Ssklower  *
298*36414Ssklower  * NOTES:
299*36414Ssklower  */
300*36414Ssklower void
301*36414Ssklower tp_quench( tpcb, cmd )
302*36414Ssklower 	struct tp_pcb *tpcb;
303*36414Ssklower 	int cmd;
304*36414Ssklower {
305*36414Ssklower 	IFDEBUG(D_QUENCH)
306*36414Ssklower 		printf("tp_quench tpcb 0x%x ref 0x%x sufx 0x%x\n",
307*36414Ssklower 			tpcb, tpcb->tp_lref, *(int *)(tpcb->tp_lsuffix));
308*36414Ssklower 		printf("cong_win 0x%x decbit 0x%x \n",
309*36414Ssklower 			tpcb->tp_cong_win, tpcb->tp_decbit);
310*36414Ssklower 	ENDDEBUG
311*36414Ssklower 	switch(cmd) {
312*36414Ssklower 		case PRC_QUENCH:
313*36414Ssklower 			tpcb->tp_cong_win = 1;
314*36414Ssklower 			IncStat(ts_quench);
315*36414Ssklower 			break;
316*36414Ssklower 		case PRC_QUENCH2:
317*36414Ssklower 			tpcb->tp_cong_win = 1; /* might as well quench source also */
318*36414Ssklower 			tpcb->tp_decbit = TP_DECBIT_CLEAR_COUNT;
319*36414Ssklower 			IncStat(ts_rcvdecbit);
320*36414Ssklower 			break;
321*36414Ssklower 	}
322*36414Ssklower }
323*36414Ssklower 
324*36414Ssklower 
325*36414Ssklower /*
326*36414Ssklower  * NAME:	tp_netcmd()
327*36414Ssklower  *
328*36414Ssklower  * CALLED FROM:
329*36414Ssklower  *
330*36414Ssklower  * FUNCTION and ARGUMENTS:
331*36414Ssklower  *
332*36414Ssklower  * RETURNS:
333*36414Ssklower  *
334*36414Ssklower  * SIDE EFFECTS:
335*36414Ssklower  *
336*36414Ssklower  * NOTES:
337*36414Ssklower  */
338*36414Ssklower tp_netcmd( tpcb, cmd )
339*36414Ssklower 	struct tp_pcb *tpcb;
340*36414Ssklower 	int cmd;
341*36414Ssklower {
342*36414Ssklower #if NARGOXTWENTYFIVE > 0
343*36414Ssklower 	switch (cmd) {
344*36414Ssklower 
345*36414Ssklower 	case CONN_CLOSE:
346*36414Ssklower 	case CONN_REFUSE:
347*36414Ssklower 		cons_netcmd( cmd, tpcb->tp_npcb, 0, tpcb->tp_class == TP_CLASS_4);
348*36414Ssklower 		/* TODO: can this last param be replaced by
349*36414Ssklower 	 	*	tpcb->tp_netserv != ISO_CONS?)
350*36414Ssklower 		*/
351*36414Ssklower 		break;
352*36414Ssklower 
353*36414Ssklower 	default:
354*36414Ssklower 		printf("tp_netcmd(0x%x, 0x%x) NOT IMPLEMENTED\n", tpcb, cmd);
355*36414Ssklower 		break;
356*36414Ssklower 	}
357*36414Ssklower #else NARGOXTWENTYFIVE
358*36414Ssklower 	printf("tp_netcmd(): X25 NOT CONFIGURED!!\n");
359*36414Ssklower #endif NARGOXTWENTYFIVE > 0
360*36414Ssklower }
361*36414Ssklower /*
362*36414Ssklower  * CALLED FROM:
363*36414Ssklower  *  tp_ctloutput() and tp_emit()
364*36414Ssklower  * FUNCTION and ARGUMENTS:
365*36414Ssklower  * 	Convert a class mask to the highest numeric value it represents.
366*36414Ssklower  */
367*36414Ssklower 
368*36414Ssklower int
369*36414Ssklower tp_mask_to_num(x)
370*36414Ssklower 	u_char x;
371*36414Ssklower {
372*36414Ssklower 	register int j;
373*36414Ssklower 
374*36414Ssklower 	for(j = 4; j>=0 ;j--) {
375*36414Ssklower 		if(x & (1<<j))
376*36414Ssklower 			break;
377*36414Ssklower 	}
378*36414Ssklower 	ASSERT( (j == 4) || (j == 0) ); /* for now */
379*36414Ssklower 	if( (j != 4) && (j != 0) ) {
380*36414Ssklower 		printf("ASSERTION ERROR: tp_mask_to_num: x 0x%x j %d\n",
381*36414Ssklower 			x, j);
382*36414Ssklower 	}
383*36414Ssklower 	IFTRACE(D_TPINPUT)
384*36414Ssklower 		tptrace(TPPTmisc, "tp_mask_to_num(x) returns j", x, j, 0, 0);
385*36414Ssklower 	ENDTRACE
386*36414Ssklower 	IFDEBUG(D_TPINPUT)
387*36414Ssklower 		printf("tp_mask_to_num(0x%x) returns 0x%x\n", x, j);
388*36414Ssklower 	ENDDEBUG
389*36414Ssklower 	return j;
390*36414Ssklower }
391*36414Ssklower 
392*36414Ssklower static
393*36414Ssklower copyQOSparms(src, dst)
394*36414Ssklower 	struct tp_conn_param *src, *dst;
395*36414Ssklower {
396*36414Ssklower 	/* copy all but the bits stuff at the end */
397*36414Ssklower #define COPYSIZE (12 * sizeof(short))
398*36414Ssklower 
399*36414Ssklower 	bcopy( src, dst, COPYSIZE);
400*36414Ssklower 	dst->p_tpdusize = src->p_tpdusize;
401*36414Ssklower 	dst->p_ack_strat = src->p_ack_strat;
402*36414Ssklower 	dst->p_rx_strat = src->p_rx_strat;
403*36414Ssklower #undef COPYSIZE
404*36414Ssklower }
405*36414Ssklower 
406*36414Ssklower /*
407*36414Ssklower  * CALLED FROM:
408*36414Ssklower  *  tp_usrreq on PRU_CONNECT and tp_input on receipt of CR
409*36414Ssklower  *
410*36414Ssklower  * FUNCTION and ARGUMENTS:
411*36414Ssklower  * 	route directly to x.25 if the address is type 37 - GROT.
412*36414Ssklower  *  furthermore, let TP0 handle only type-37 addresses
413*36414Ssklower  *
414*36414Ssklower  *	Since this assumes that its address argument is in a mbuf, the
415*36414Ssklower  *	parameter was changed to reflect this assumtion. This also
416*36414Ssklower  *	implies that an mbuf must be allocated when this is
417*36414Ssklower  *	called from tp_input
418*36414Ssklower  *
419*36414Ssklower  * RETURNS:
420*36414Ssklower  *	errno value	 :
421*36414Ssklower  *	EAFNOSUPPORT if can't find an nl_protosw for x.25 (really could panic)
422*36414Ssklower  *	ECONNREFUSED if trying to run TP0 with non-type 37 address
423*36414Ssklower  *  possibly other E* returned from cons_netcmd()
424*36414Ssklower  * NOTE:
425*36414Ssklower  *  Would like to eliminate as much of this as possible --
426*36414Ssklower  *  only one set of defaults (let the user set the parms according
427*36414Ssklower  *  to parameters provided in the directory service).
428*36414Ssklower  *  Left here for now 'cause we don't yet have a clean way to handle
429*36414Ssklower  *  it on the passive end.
430*36414Ssklower  */
431*36414Ssklower int
432*36414Ssklower tp_route_to( m, tpcb, channel)
433*36414Ssklower 	struct mbuf					*m;
434*36414Ssklower 	register struct tp_pcb		*tpcb;
435*36414Ssklower 	u_int 						channel;
436*36414Ssklower {
437*36414Ssklower 	register struct sockaddr_iso *siso;	/* NOTE: this may be a sockaddr_in */
438*36414Ssklower 	extern struct tp_conn_param tp_conn_param[];
439*36414Ssklower 	int error = 0;
440*36414Ssklower 	int	vc_to_kill = 0; /* kludge */
441*36414Ssklower 
442*36414Ssklower 	siso = mtod(m, struct sockaddr_iso *);
443*36414Ssklower 	IFTRACE(D_CONN)
444*36414Ssklower 		tptraceTPCB(TPPTmisc,
445*36414Ssklower 		"route_to: so  afi netservice class",
446*36414Ssklower 		tpcb->tp_sock, siso->siso_addr.isoa_afi, tpcb->tp_netservice,
447*36414Ssklower 			tpcb->tp_class);
448*36414Ssklower 	ENDTRACE
449*36414Ssklower 	IFDEBUG(D_CONN)
450*36414Ssklower 		printf("tp_route_to( m x%x, channel 0x%x, tpcb 0x%x netserv 0x%x)\n",
451*36414Ssklower 			m, channel, tpcb, tpcb->tp_netservice);
452*36414Ssklower 		printf("m->mlen x%x, m->m_data:\n", m->m_len);
453*36414Ssklower 		dump_buf(mtod(m, caddr_t), m->m_len);
454*36414Ssklower 	ENDDEBUG
455*36414Ssklower 	if( siso->siso_family != tpcb->tp_domain ) {
456*36414Ssklower 		error = EAFNOSUPPORT;
457*36414Ssklower 		goto done;
458*36414Ssklower 	}
459*36414Ssklower 	{
460*36414Ssklower 		register int save_netservice = tpcb->tp_netservice;
461*36414Ssklower 
462*36414Ssklower 		switch(tpcb->tp_netservice) {
463*36414Ssklower 		case ISO_COSNS:
464*36414Ssklower 		case ISO_CLNS:
465*36414Ssklower 			/* This is a kludge but seems necessary so the passive end
466*36414Ssklower 			 * can get long enough timers. sigh.
467*36414Ssklower 			 */
468*36414Ssklower 			if( siso->siso_addr.osinet_idi[1] == (u_char)IDI_OSINET ) {
469*36414Ssklower 				if( tpcb->tp_dont_change_params == 0) {
470*36414Ssklower 					copyQOSparms( &tp_conn_param[ISO_COSNS],
471*36414Ssklower 							&tpcb->_tp_param);
472*36414Ssklower 				}
473*36414Ssklower 				tpcb->tp_flags |= TPF_NLQOS_PDN;
474*36414Ssklower 			}
475*36414Ssklower 			/* drop through to IN_CLNS*/
476*36414Ssklower 		case IN_CLNS:
477*36414Ssklower 			if( (tpcb->tp_class & TP_CLASS_4)==0 ) {
478*36414Ssklower 				error = EPROTOTYPE;
479*36414Ssklower 				break;
480*36414Ssklower 			}
481*36414Ssklower 			tpcb->tp_class = TP_CLASS_4;  /* IGNORE dont_change_parms */
482*36414Ssklower 			break;
483*36414Ssklower 
484*36414Ssklower 		case ISO_CONS:
485*36414Ssklower #if NARGOXTWENTYFIVE > 0
486*36414Ssklower 			tpcb->tp_flags |= TPF_NLQOS_PDN;
487*36414Ssklower 			if( tpcb->tp_dont_change_params == 0 ) {
488*36414Ssklower 				copyQOSparms( &tp_conn_param[ISO_CONS],
489*36414Ssklower 							&tpcb->_tp_param);
490*36414Ssklower 			}
491*36414Ssklower 			/*
492*36414Ssklower 			 * for use over x.25 really need a small receive window,
493*36414Ssklower 			 * need to start slowly, need small max negotiable tpdu size,
494*36414Ssklower 			 * and need to use the congestion window to the max
495*36414Ssklower 			 * IGNORES tp_dont_change_params for these!
496*36414Ssklower 			 */
497*36414Ssklower 			if( tpcb->tp_sock->so_snd.sb_hiwat > 512 ) {
498*36414Ssklower 				(void) soreserve(tpcb->tp_sock, 512, 512 );/* GAG */
499*36414Ssklower 			}
500*36414Ssklower 			tpcb->tp_rx_strat =  TPRX_USE_CW;
501*36414Ssklower 
502*36414Ssklower 			if( (tpcb->tp_nlproto != &nl_protosw[ISO_CONS]) ) {
503*36414Ssklower 				/* if the listener was restricting us to clns,
504*36414Ssklower 				 * ( we never get here if the listener isn't af_iso )
505*36414Ssklower 				 * refuse the connection :
506*36414Ssklower 				 * but we don't have a way to restrict thus - it's
507*36414Ssklower 				 * utterly permissive.
508*36414Ssklower 					if(channel)  {
509*36414Ssklower 						(void) cons_netcmd(CONN_REFUSE, tpcb->tp_npcb,
510*36414Ssklower 								channel, tpcb->tp_class == TP_CLASS_4);
511*36414Ssklower 						error = EPFNOSUPPORT;
512*36414Ssklower 						goto done;
513*36414Ssklower 					}
514*36414Ssklower 				 */
515*36414Ssklower 				IFDEBUG(D_CONN)
516*36414Ssklower 					printf(
517*36414Ssklower 					"tp_route_to( CHANGING nlproto old 0x%x new 0x%x)\n",
518*36414Ssklower 							tpcb->tp_nlproto , &nl_protosw[ISO_CONS]);
519*36414Ssklower 				ENDDEBUG
520*36414Ssklower 				tpcb->tp_nlproto = &nl_protosw[ISO_CONS];
521*36414Ssklower 			}
522*36414Ssklower 			/* Now we've got the right nl_protosw.
523*36414Ssklower 			 * If we already have a channel (we were called from tp_input())
524*36414Ssklower 			 * tell cons that we'll hang onto this channel.
525*36414Ssklower 			 * If we don't already have one (we were called from usrreq())
526*36414Ssklower 			 * -and if it's TP0 open a net connection and wait for it to finish.
527*36414Ssklower 			 */
528*36414Ssklower 			if( channel ) {
529*36414Ssklower 				error = cons_netcmd( CONN_CONFIRM, tpcb->tp_npcb,
530*36414Ssklower 								channel, tpcb->tp_class == TP_CLASS_4);
531*36414Ssklower 				vc_to_kill ++;
532*36414Ssklower 			} else if( tpcb->tp_class != TP_CLASS_4 /* class 4 only */) {
533*36414Ssklower 				/* better open vc if any possibility of ending up
534*36414Ssklower 				 * in non-multiplexing class
535*36414Ssklower 				 */
536*36414Ssklower 				error = cons_openvc(tpcb->tp_npcb, siso, tpcb->tp_sock);
537*36414Ssklower 				vc_to_kill ++;
538*36414Ssklower 			}
539*36414Ssklower 			/* class 4 doesn't need to open a vc now - may use one already
540*36414Ssklower 			 * opened or may open one only when it sends a pkt.
541*36414Ssklower 			 */
542*36414Ssklower #else NARGOXTWENTYFIVE > 0
543*36414Ssklower 			error = ECONNREFUSED;
544*36414Ssklower #endif NARGOXTWENTYFIVE > 0
545*36414Ssklower 			break;
546*36414Ssklower 		default:
547*36414Ssklower 			error = EPROTOTYPE;
548*36414Ssklower 		}
549*36414Ssklower 
550*36414Ssklower 		ASSERT( save_netservice == tpcb->tp_netservice);
551*36414Ssklower 	}
552*36414Ssklower 	if( error )
553*36414Ssklower 		goto done;
554*36414Ssklower 	IFDEBUG(D_CONN)
555*36414Ssklower 		printf("tp_route_to  calling nlp_pcbconn, netserv %d\n",
556*36414Ssklower 			tpcb->tp_netservice);
557*36414Ssklower 	ENDDEBUG
558*36414Ssklower 	error = (tpcb->tp_nlproto->nlp_pcbconn)(tpcb->tp_sock->so_pcb, m);
559*36414Ssklower 
560*36414Ssklower 	if( error && vc_to_kill ) {
561*36414Ssklower 		tp_netcmd( tpcb, CONN_CLOSE);
562*36414Ssklower 		goto done;
563*36414Ssklower 	}
564*36414Ssklower 
565*36414Ssklower 	/* PHASE 2: replace iso_netmatch with iso_on_localnet(foreign addr) */
566*36414Ssklower 	if( iso_netmatch(
567*36414Ssklower 		&(((struct isopcb *)(tpcb->tp_sock->so_pcb))->isop_laddr),
568*36414Ssklower 		&(((struct isopcb *)(tpcb->tp_sock->so_pcb))->isop_faddr)
569*36414Ssklower 					 )) {
570*36414Ssklower 		tpcb->tp_flags |= TPF_PEER_ON_SAMENET;
571*36414Ssklower 	}
572*36414Ssklower 
573*36414Ssklower 	{	/* start with the global rtt, rtv stats */
574*36414Ssklower 		register int i =
575*36414Ssklower 		   (int) tpcb->tp_flags & (TPF_PEER_ON_SAMENET | TPF_NLQOS_PDN);
576*36414Ssklower 
577*36414Ssklower 		tpcb->tp_rtt = tp_stat.ts_rtt[i];
578*36414Ssklower 		tpcb->tp_rtv = tp_stat.ts_rtv[i];
579*36414Ssklower 	}
580*36414Ssklower done:
581*36414Ssklower 	IFDEBUG(D_CONN)
582*36414Ssklower 		printf("tp_route_to  returns 0x%x\n", error);
583*36414Ssklower 	ENDDEBUG
584*36414Ssklower 	IFTRACE(D_CONN)
585*36414Ssklower 		tptraceTPCB(TPPTmisc, "route_to: returns: error netserv class", error,
586*36414Ssklower 			tpcb->tp_netservice, tpcb->tp_class, 0);
587*36414Ssklower 	ENDTRACE
588*36414Ssklower 	return error;
589*36414Ssklower }
590*36414Ssklower 
591*36414Ssklower #ifdef TP_PERF_MEAS
592*36414Ssklower /*
593*36414Ssklower  * CALLED FROM:
594*36414Ssklower  *  tp_ctloutput() when the user sets TPOPT_PERF_MEAS on
595*36414Ssklower  *  and tp_newsocket() when a new connection is made from
596*36414Ssklower  *  a listening socket with tp_perf_on == true.
597*36414Ssklower  * FUNCTION and ARGUMENTS:
598*36414Ssklower  *  (tpcb) is the usual; this procedure gets a clear cluster mbuf for
599*36414Ssklower  *  a tp_pmeas structure, and makes tpcb->tp_p_meas point to it.
600*36414Ssklower  * RETURN VALUE:
601*36414Ssklower  *  ENOBUFS if it cannot get a cluster mbuf.
602*36414Ssklower  */
603*36414Ssklower 
604*36414Ssklower int
605*36414Ssklower tp_setup_perf(tpcb)
606*36414Ssklower 	register struct tp_pcb *tpcb;
607*36414Ssklower {
608*36414Ssklower 	register struct mbuf *q;
609*36414Ssklower 
610*36414Ssklower 	if( tpcb->tp_p_meas == (struct tp_pmeas *)0 ) {
611*36414Ssklower 
612*36414Ssklower 		/* allocate a cluster for all the stats */
613*36414Ssklower 		MGET(q, M_DONTWAIT, TPMT_PERF); /* something we don't otherwise use */
614*36414Ssklower 		if (q == 0)
615*36414Ssklower 			return ENOBUFS;
616*36414Ssklower 		q->m_act = MNULL;
617*36414Ssklower 		MCLGET(q);	/* for the tp_pmeas struct */
618*36414Ssklower 		if(q->m_len == 0) {
619*36414Ssklower 			m_free(q);
620*36414Ssklower 			return ENOBUFS;
621*36414Ssklower 		} else {
622*36414Ssklower 			/* point into the cluster */
623*36414Ssklower 			tpcb->tp_p_meas = mtod(q, struct tp_pmeas *);
624*36414Ssklower 			/* get rid of the original little mbuf */
625*36414Ssklower 			q->m_off = 0; q->m_len = 0;
626*36414Ssklower 			m_free(q);
627*36414Ssklower 			bzero( (caddr_t)tpcb->tp_p_meas, sizeof (struct tp_pmeas) );
628*36414Ssklower 			IFDEBUG(D_PERF_MEAS)
629*36414Ssklower 				printf(
630*36414Ssklower 				"tpcb 0x%x so 0x%x ref 0x%x tp_p_meas 0x%x tp_perf_on 0x%x\n",
631*36414Ssklower 					tpcb, tpcb->tp_sock, tpcb->tp_lref,
632*36414Ssklower 					tpcb->tp_p_meas, tpcb->tp_perf_on);
633*36414Ssklower 			ENDDEBUG
634*36414Ssklower 			tpcb->tp_perf_on = 1;
635*36414Ssklower 		}
636*36414Ssklower 	}
637*36414Ssklower 	return 0;
638*36414Ssklower }
639*36414Ssklower #endif TP_PERF_MEAS
640*36414Ssklower 
641*36414Ssklower #ifdef ARGO_DEBUG
642*36414Ssklower dump_addr (addr)
643*36414Ssklower 	register struct sockaddr *addr;
644*36414Ssklower {
645*36414Ssklower 	switch( addr->sa_family ) {
646*36414Ssklower 		case AF_INET:
647*36414Ssklower 			dump_inaddr(addr);
648*36414Ssklower 			break;
649*36414Ssklower 		case AF_ISO:
650*36414Ssklower 			dump_isoaddr(addr);
651*36414Ssklower 			break;
652*36414Ssklower 		default:
653*36414Ssklower 			printf("BAD AF: 0x%x\n", addr->sa_family);
654*36414Ssklower 			break;
655*36414Ssklower 	}
656*36414Ssklower }
657*36414Ssklower 
658*36414Ssklower #endif ARGO_DEBUG
659*36414Ssklower 
660