xref: /csrg-svn/sys/netiso/tp_subr2.c (revision 39197)
136414Ssklower /***********************************************************
236414Ssklower 		Copyright IBM Corporation 1987
336414Ssklower 
436414Ssklower                       All Rights Reserved
536414Ssklower 
636414Ssklower Permission to use, copy, modify, and distribute this software and its
736414Ssklower documentation for any purpose and without fee is hereby granted,
836414Ssklower provided that the above copyright notice appear in all copies and that
936414Ssklower both that copyright notice and this permission notice appear in
1036414Ssklower supporting documentation, and that the name of IBM not be
1136414Ssklower used in advertising or publicity pertaining to distribution of the
1236414Ssklower software without specific, written prior permission.
1336414Ssklower 
1436414Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
1536414Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
1636414Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
1736414Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
1836414Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
1936414Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2036414Ssklower SOFTWARE.
2136414Ssklower 
2236414Ssklower ******************************************************************/
2336414Ssklower 
2436414Ssklower /*
2536414Ssklower  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
2636414Ssklower  */
2736414Ssklower /*
2836414Ssklower  * ARGO TP
2936414Ssklower  *
3036414Ssklower  * $Header: tp_subr2.c,v 5.5 88/11/18 17:28:55 nhall Exp $
3136414Ssklower  * $Source: /usr/argo/sys/netiso/RCS/tp_subr2.c,v $
32*39197Ssklower  *	@(#)tp_subr2.c	7.4 (Berkeley) 09/22/89
3336414Ssklower  *
3436414Ssklower  * Some auxiliary routines:
3536414Ssklower  * 		tp_protocol_error: required by xebec- called when a combo of state,
3636414Ssklower  *			event, predicate isn't covered for by the transition file.
3736414Ssklower  *		tp_indicate: gives indications(signals) to the user process
3836414Ssklower  *		tp_getoptions: initializes variables that are affected by the options
3936414Ssklower  *          chosen.
4036414Ssklower  */
4136414Ssklower 
4236414Ssklower #ifndef lint
4336414Ssklower static char *rcsid = "$Header: tp_subr2.c,v 5.5 88/11/18 17:28:55 nhall Exp $";
4436414Ssklower #endif lint
4536414Ssklower 
4636414Ssklower #include "argoxtwentyfive.h"
4736414Ssklower 
4836414Ssklower /* this def'n is to cause the expansion of this macro in the
4936414Ssklower  * routine tp_local_credit :
5036414Ssklower  */
5136414Ssklower #define LOCAL_CREDIT_EXPAND
5236414Ssklower 
5336414Ssklower #include "param.h"
5436414Ssklower #include "mbuf.h"
5536414Ssklower #include "socket.h"
5636414Ssklower #include "socketvar.h"
5736414Ssklower #include "domain.h"
5836414Ssklower #include "protosw.h"
5936414Ssklower #include "errno.h"
6036414Ssklower #include "types.h"
6136414Ssklower #include "time.h"
6236414Ssklower #include "kernel.h"
6336414Ssklower #undef MNULL
6437469Ssklower #include "argo_debug.h"
6537469Ssklower #include "tp_param.h"
6637469Ssklower #include "tp_ip.h"
6737469Ssklower #include "iso.h"
6837469Ssklower #include "iso_errno.h"
6937469Ssklower #include "iso_pcb.h"
7037469Ssklower #include "tp_timer.h"
7137469Ssklower #include "tp_stat.h"
7237469Ssklower #include "tp_tpdu.h"
7337469Ssklower #include "tp_pcb.h"
7437469Ssklower #include "tp_seq.h"
7537469Ssklower #include "tp_trace.h"
7637469Ssklower #include "tp_user.h"
7737469Ssklower #include "cons.h"
7836414Ssklower 
7936414Ssklower /*
8036414Ssklower  * NAME: 	tp_local_credit()
8136414Ssklower  *
8236414Ssklower  * CALLED FROM:
8336414Ssklower  *  tp_emit(), tp_usrreq()
8436414Ssklower  *
8536414Ssklower  * FUNCTION and ARGUMENTS:
8636414Ssklower  *	Computes the local credit and stashes it in tpcb->tp_lcredit.
8736414Ssklower  *  It's a macro in the production system rather than a procdure.
8836414Ssklower  *
8936414Ssklower  * RETURNS:
9036414Ssklower  *
9136414Ssklower  * SIDE EFFECTS:
9236414Ssklower  *
9336414Ssklower  * NOTES:
9436414Ssklower  *  This doesn't actually get called in a production system -
9536414Ssklower  *  the macro gets expanded instead in place of calls to this proc.
9636414Ssklower  *  But for debugging, we call this and that allows us to add
9736414Ssklower  *  debugging messages easily here.
9836414Ssklower  */
9936414Ssklower void
10036414Ssklower tp_local_credit(tpcb)
10136414Ssklower 	struct tp_pcb *tpcb;
10236414Ssklower {
10336414Ssklower 	LOCAL_CREDIT(tpcb);
10436414Ssklower 	IFDEBUG(D_CREDIT)
10536414Ssklower 		printf("ref 0x%x lcdt 0x%x l_tpdusize 0x%x decbit 0x%x\n",
10636414Ssklower 			tpcb->tp_refp - tp_ref,
10736414Ssklower 			tpcb->tp_lcredit,
10836414Ssklower 			tpcb->tp_l_tpdusize,
10936414Ssklower 			tpcb->tp_decbit,
11036414Ssklower 			tpcb->tp_cong_win
11136414Ssklower 			);
11236414Ssklower 	ENDDEBUG
11336414Ssklower 	IFTRACE(D_CREDIT)
11436414Ssklower 		tptraceTPCB(TPPTmisc,
11536414Ssklower 			"lcdt tpdusz \n",
11636414Ssklower 			 tpcb->tp_lcredit, tpcb->tp_l_tpdusize, 0, 0);
11736414Ssklower 	ENDTRACE
11836414Ssklower }
11936414Ssklower 
12036414Ssklower /*
12136414Ssklower  * NAME:  tp_protocol_error()
12236414Ssklower  *
12336414Ssklower  * CALLED FROM:
12436414Ssklower  *  tp_driver(), when it doesn't know what to do with
12536414Ssklower  * 	a combo of event, state, predicate
12636414Ssklower  *
12736414Ssklower  * FUNCTION and ARGUMENTS:
12836414Ssklower  *  print error mesg
12936414Ssklower  *
13036414Ssklower  * RETURN VALUE:
13136414Ssklower  *  EIO - always
13236414Ssklower  *
13336414Ssklower  * SIDE EFFECTS:
13436414Ssklower  *
13536414Ssklower  * NOTES:
13636414Ssklower  */
13736414Ssklower int
13836414Ssklower tp_protocol_error(e,tpcb)
13936414Ssklower 	struct tp_event	*e;
14036414Ssklower 	struct tp_pcb	*tpcb;
14136414Ssklower {
14236414Ssklower 	printf("TP PROTOCOL ERROR! tpcb 0x%x event 0x%x, state 0x%x\n",
14336414Ssklower 		tpcb, e->ev_number, tpcb->tp_state);
14436414Ssklower 	IFTRACE(D_DRIVER)
14536414Ssklower 		tptraceTPCB(TPPTmisc, "PROTOCOL ERROR tpcb event state",
14636414Ssklower 			tpcb, e->ev_number, tpcb->tp_state, 0 );
14736414Ssklower 	ENDTRACE
14836414Ssklower 	return EIO; /* for lack of anything better */
14936414Ssklower }
15036414Ssklower 
15136414Ssklower 
15236414Ssklower /* Not used at the moment */
15336414Ssklower ProtoHook
15436414Ssklower tp_drain()
15536414Ssklower {
15636414Ssklower 	return 0;
15736414Ssklower }
15836414Ssklower 
15936414Ssklower 
16036414Ssklower /*
16136414Ssklower  * NAME: tp_indicate()
16236414Ssklower  *
16336414Ssklower  * CALLED FROM:
16436414Ssklower  * 	tp.trans when XPD arrive, when a connection is being disconnected by
16536414Ssklower  *  the arrival of a DR or ER, and when a connection times out.
16636414Ssklower  *
16736414Ssklower  * FUNCTION and ARGUMENTS:
16836414Ssklower  *  (ind) is the type of indication : T_DISCONNECT, T_XPD
16936414Ssklower  *  (error) is an E* value that will be put in the socket structure
17036414Ssklower  *  to be passed along to the user later.
17136414Ssklower  * 	Gives a SIGURG to the user process or group indicated by the socket
17236414Ssklower  * 	attached to the tpcb.
17336414Ssklower  *
17436414Ssklower  * RETURNS:  Rien
17536414Ssklower  *
17636414Ssklower  * SIDE EFFECTS:
17736414Ssklower  *
17836414Ssklower  * NOTES:
17936414Ssklower  */
18036414Ssklower void
18136414Ssklower tp_indicate(ind, tpcb, error)
18236414Ssklower 	int				ind;
18336414Ssklower 	u_short			error;
18436414Ssklower 	register struct tp_pcb	*tpcb;
18536414Ssklower {
18636414Ssklower 	register struct socket *so = tpcb->tp_sock;
18736414Ssklower 	IFTRACE(D_INDICATION)
188*39197Ssklower 		tptraceTPCB(TPPTindicate, ind, *(u_short *)(tpcb->tp_lsuffix),
189*39197Ssklower 			*(u_short *)(tpcb->tp_fsuffix), error,so->so_pgid);
19036414Ssklower 	ENDTRACE
19136414Ssklower 	IFDEBUG(D_INDICATION)
19237469Ssklower 		char *ls, *fs;
19336414Ssklower 		ls = tpcb->tp_lsuffix,
19436414Ssklower 		fs = tpcb->tp_fsuffix,
19536414Ssklower 
19636414Ssklower 		printf(
19737469Ssklower "indicate 0x%x lsuf 0x%02x%02x fsuf 0x%02x%02x err 0x%x  noind 0x%x ref 0x%x\n",
19836414Ssklower 		ind,
19936414Ssklower 		*ls, *(ls+1), *fs, *(fs+1),
20037469Ssklower 		error, /*so->so_pgrp,*/
20136414Ssklower 		tpcb->tp_no_disc_indications,
20236414Ssklower 		tpcb->tp_lref);
20336414Ssklower 	ENDDEBUG
20436414Ssklower 
20536414Ssklower 	so->so_error = error;
20636414Ssklower 
20736414Ssklower 	if (ind == T_DISCONNECT)  {
20836414Ssklower 		if ( tpcb->tp_no_disc_indications )
20936414Ssklower 			return;
21036414Ssklower 	}
21136414Ssklower 	IFTRACE(D_INDICATION)
21236414Ssklower 		tptraceTPCB(TPPTmisc, "doing sohasoutofband(so)", so,0,0,0);
21336414Ssklower 	ENDTRACE
21436414Ssklower 	sohasoutofband(so);
21536414Ssklower }
21636414Ssklower 
21736414Ssklower /*
21836414Ssklower  * NAME : tp_getoptions()
21936414Ssklower  *
22036414Ssklower  * CALLED FROM:
22136414Ssklower  * 	tp.trans whenever we go into OPEN state
22236414Ssklower  *
22336414Ssklower  * FUNCTION and ARGUMENTS:
22436414Ssklower  *  sets the proper flags and values in the tpcb, to control
22536414Ssklower  *  the appropriate actions for the given class, options,
22636414Ssklower  *  sequence space, etc, etc.
22736414Ssklower  *
22836414Ssklower  * RETURNS: Nada
22936414Ssklower  *
23036414Ssklower  * SIDE EFFECTS:
23136414Ssklower  *
23236414Ssklower  * NOTES:
23336414Ssklower  */
23436414Ssklower void
23536414Ssklower tp_getoptions(tpcb)
23636414Ssklower struct tp_pcb *tpcb;
23736414Ssklower {
23836414Ssklower 	tpcb->tp_seqmask =
23936414Ssklower 		tpcb->tp_xtd_format ?	TP_XTD_FMT_MASK :	TP_NML_FMT_MASK ;
24036414Ssklower 	tpcb->tp_seqbit =
24136414Ssklower 		tpcb->tp_xtd_format ?	TP_XTD_FMT_BIT :	TP_NML_FMT_BIT ;
24236414Ssklower 	tpcb->tp_seqhalf = tpcb->tp_seqbit >> 1;
24336414Ssklower 	tpcb->tp_dt_ticks =
24436414Ssklower 		MAX(tpcb->tp_dt_ticks, (tpcb->tp_peer_acktime + 2));
24536414Ssklower 
24636414Ssklower }
24736414Ssklower 
24836414Ssklower /*
24936414Ssklower  * NAME:  tp_recycle_tsuffix()
25036414Ssklower  *
25136414Ssklower  * CALLED FROM:
25236414Ssklower  *  Called when a ref is frozen.
25336414Ssklower  *
25436414Ssklower  * FUNCTION and ARGUMENTS:
25536414Ssklower  *  allows the suffix to be reused.
25636414Ssklower  *
25736414Ssklower  * RETURNS: zilch
25836414Ssklower  *
25936414Ssklower  * SIDE EFFECTS:
26036414Ssklower  *
26136414Ssklower  * NOTES:
26236414Ssklower  */
26336414Ssklower void
26436414Ssklower tp_recycle_tsuffix(tpcb)
26536414Ssklower 	struct tp_pcb	*tpcb;
26636414Ssklower {
26737469Ssklower 	bzero((caddr_t)tpcb->tp_lsuffix, sizeof( tpcb->tp_lsuffix));
26837469Ssklower 	bzero((caddr_t)tpcb->tp_fsuffix, sizeof( tpcb->tp_fsuffix));
26936414Ssklower 	tpcb->tp_fsuffixlen = tpcb->tp_lsuffixlen = 0;
27036414Ssklower 
27136414Ssklower 	(tpcb->tp_nlproto->nlp_recycle_suffix)(tpcb->tp_npcb);
27236414Ssklower }
27336414Ssklower 
27436414Ssklower /*
27536414Ssklower  * NAME: tp_quench()
27636414Ssklower  *
27736414Ssklower  * CALLED FROM:
27836414Ssklower  *  tp{af}_quench() when ICMP source quench or similar thing arrives.
27936414Ssklower  *
28036414Ssklower  * FUNCTION and ARGUMENTS:
28136414Ssklower  *  Drop the congestion window back to 1.
28236414Ssklower  *  Congestion window scheme:
28336414Ssklower  *  Initial value is 1.  ("slow start" as Nagle, et. al. call it)
28436414Ssklower  *  For each good ack that arrives, the congestion window is increased
28536414Ssklower  *  by 1 (up to max size of logical infinity, which is to say,
28636414Ssklower  *	it doesn't wrap around).
28736414Ssklower  *  Source quench causes it to drop back to 1.
28836414Ssklower  *  tp_send() uses the smaller of (regular window, congestion window).
28936414Ssklower  *  One retransmission strategy option is to have any retransmission
29036414Ssklower  *	cause reset the congestion window back  to 1.
29136414Ssklower  *
29236414Ssklower  *	(cmd) is either PRC_QUENCH: source quench, or
29336414Ssklower  *		PRC_QUENCH2: dest. quench (dec bit)
29436414Ssklower  *
29536414Ssklower  * RETURNS:
29636414Ssklower  *
29736414Ssklower  * SIDE EFFECTS:
29836414Ssklower  *
29936414Ssklower  * NOTES:
30036414Ssklower  */
30136414Ssklower void
30236414Ssklower tp_quench( tpcb, cmd )
30336414Ssklower 	struct tp_pcb *tpcb;
30436414Ssklower 	int cmd;
30536414Ssklower {
30636414Ssklower 	IFDEBUG(D_QUENCH)
30736414Ssklower 		printf("tp_quench tpcb 0x%x ref 0x%x sufx 0x%x\n",
308*39197Ssklower 			tpcb, tpcb->tp_lref, *(u_short *)(tpcb->tp_lsuffix));
30936414Ssklower 		printf("cong_win 0x%x decbit 0x%x \n",
31036414Ssklower 			tpcb->tp_cong_win, tpcb->tp_decbit);
31136414Ssklower 	ENDDEBUG
31236414Ssklower 	switch(cmd) {
31336414Ssklower 		case PRC_QUENCH:
31436414Ssklower 			tpcb->tp_cong_win = 1;
31536414Ssklower 			IncStat(ts_quench);
31636414Ssklower 			break;
31736414Ssklower 		case PRC_QUENCH2:
31836414Ssklower 			tpcb->tp_cong_win = 1; /* might as well quench source also */
31936414Ssklower 			tpcb->tp_decbit = TP_DECBIT_CLEAR_COUNT;
32036414Ssklower 			IncStat(ts_rcvdecbit);
32136414Ssklower 			break;
32236414Ssklower 	}
32336414Ssklower }
32436414Ssklower 
32536414Ssklower 
32636414Ssklower /*
32736414Ssklower  * NAME:	tp_netcmd()
32836414Ssklower  *
32936414Ssklower  * CALLED FROM:
33036414Ssklower  *
33136414Ssklower  * FUNCTION and ARGUMENTS:
33236414Ssklower  *
33336414Ssklower  * RETURNS:
33436414Ssklower  *
33536414Ssklower  * SIDE EFFECTS:
33636414Ssklower  *
33736414Ssklower  * NOTES:
33836414Ssklower  */
33936414Ssklower tp_netcmd( tpcb, cmd )
34036414Ssklower 	struct tp_pcb *tpcb;
34136414Ssklower 	int cmd;
34236414Ssklower {
34336414Ssklower #if NARGOXTWENTYFIVE > 0
34436414Ssklower 	switch (cmd) {
34536414Ssklower 
34636414Ssklower 	case CONN_CLOSE:
34736414Ssklower 	case CONN_REFUSE:
34836414Ssklower 		cons_netcmd( cmd, tpcb->tp_npcb, 0, tpcb->tp_class == TP_CLASS_4);
34936414Ssklower 		/* TODO: can this last param be replaced by
35036414Ssklower 	 	*	tpcb->tp_netserv != ISO_CONS?)
35136414Ssklower 		*/
35236414Ssklower 		break;
35336414Ssklower 
35436414Ssklower 	default:
35536414Ssklower 		printf("tp_netcmd(0x%x, 0x%x) NOT IMPLEMENTED\n", tpcb, cmd);
35636414Ssklower 		break;
35736414Ssklower 	}
35836414Ssklower #else NARGOXTWENTYFIVE
35936414Ssklower 	printf("tp_netcmd(): X25 NOT CONFIGURED!!\n");
36036414Ssklower #endif NARGOXTWENTYFIVE > 0
36136414Ssklower }
36236414Ssklower /*
36336414Ssklower  * CALLED FROM:
36436414Ssklower  *  tp_ctloutput() and tp_emit()
36536414Ssklower  * FUNCTION and ARGUMENTS:
36636414Ssklower  * 	Convert a class mask to the highest numeric value it represents.
36736414Ssklower  */
36836414Ssklower 
36936414Ssklower int
37036414Ssklower tp_mask_to_num(x)
37136414Ssklower 	u_char x;
37236414Ssklower {
37336414Ssklower 	register int j;
37436414Ssklower 
37536414Ssklower 	for(j = 4; j>=0 ;j--) {
37636414Ssklower 		if(x & (1<<j))
37736414Ssklower 			break;
37836414Ssklower 	}
37936414Ssklower 	ASSERT( (j == 4) || (j == 0) ); /* for now */
38036414Ssklower 	if( (j != 4) && (j != 0) ) {
38136414Ssklower 		printf("ASSERTION ERROR: tp_mask_to_num: x 0x%x j %d\n",
38236414Ssklower 			x, j);
38336414Ssklower 	}
38436414Ssklower 	IFTRACE(D_TPINPUT)
38536414Ssklower 		tptrace(TPPTmisc, "tp_mask_to_num(x) returns j", x, j, 0, 0);
38636414Ssklower 	ENDTRACE
38736414Ssklower 	IFDEBUG(D_TPINPUT)
38836414Ssklower 		printf("tp_mask_to_num(0x%x) returns 0x%x\n", x, j);
38936414Ssklower 	ENDDEBUG
39036414Ssklower 	return j;
39136414Ssklower }
39236414Ssklower 
39336414Ssklower static
39436414Ssklower copyQOSparms(src, dst)
39536414Ssklower 	struct tp_conn_param *src, *dst;
39636414Ssklower {
39736414Ssklower 	/* copy all but the bits stuff at the end */
39836414Ssklower #define COPYSIZE (12 * sizeof(short))
39936414Ssklower 
40037469Ssklower 	bcopy((caddr_t)src, (caddr_t)dst, COPYSIZE);
40136414Ssklower 	dst->p_tpdusize = src->p_tpdusize;
40236414Ssklower 	dst->p_ack_strat = src->p_ack_strat;
40336414Ssklower 	dst->p_rx_strat = src->p_rx_strat;
40436414Ssklower #undef COPYSIZE
40536414Ssklower }
40636414Ssklower 
40736414Ssklower /*
40836414Ssklower  * CALLED FROM:
40936414Ssklower  *  tp_usrreq on PRU_CONNECT and tp_input on receipt of CR
41036414Ssklower  *
41136414Ssklower  * FUNCTION and ARGUMENTS:
41236414Ssklower  * 	route directly to x.25 if the address is type 37 - GROT.
41336414Ssklower  *  furthermore, let TP0 handle only type-37 addresses
41436414Ssklower  *
41536414Ssklower  *	Since this assumes that its address argument is in a mbuf, the
41636414Ssklower  *	parameter was changed to reflect this assumtion. This also
41736414Ssklower  *	implies that an mbuf must be allocated when this is
41836414Ssklower  *	called from tp_input
41936414Ssklower  *
42036414Ssklower  * RETURNS:
42136414Ssklower  *	errno value	 :
42236414Ssklower  *	EAFNOSUPPORT if can't find an nl_protosw for x.25 (really could panic)
42336414Ssklower  *	ECONNREFUSED if trying to run TP0 with non-type 37 address
42436414Ssklower  *  possibly other E* returned from cons_netcmd()
42536414Ssklower  * NOTE:
42636414Ssklower  *  Would like to eliminate as much of this as possible --
42736414Ssklower  *  only one set of defaults (let the user set the parms according
42836414Ssklower  *  to parameters provided in the directory service).
42936414Ssklower  *  Left here for now 'cause we don't yet have a clean way to handle
43036414Ssklower  *  it on the passive end.
43136414Ssklower  */
43236414Ssklower int
43336414Ssklower tp_route_to( m, tpcb, channel)
43436414Ssklower 	struct mbuf					*m;
43536414Ssklower 	register struct tp_pcb		*tpcb;
43636414Ssklower 	u_int 						channel;
43736414Ssklower {
43836414Ssklower 	register struct sockaddr_iso *siso;	/* NOTE: this may be a sockaddr_in */
43936414Ssklower 	extern struct tp_conn_param tp_conn_param[];
44036414Ssklower 	int error = 0;
44136414Ssklower 	int	vc_to_kill = 0; /* kludge */
44236414Ssklower 
44336414Ssklower 	siso = mtod(m, struct sockaddr_iso *);
44436414Ssklower 	IFTRACE(D_CONN)
44536414Ssklower 		tptraceTPCB(TPPTmisc,
44636414Ssklower 		"route_to: so  afi netservice class",
44737469Ssklower 		tpcb->tp_sock, siso->siso_addr.isoa_genaddr[0], tpcb->tp_netservice,
44836414Ssklower 			tpcb->tp_class);
44936414Ssklower 	ENDTRACE
45036414Ssklower 	IFDEBUG(D_CONN)
45136414Ssklower 		printf("tp_route_to( m x%x, channel 0x%x, tpcb 0x%x netserv 0x%x)\n",
45236414Ssklower 			m, channel, tpcb, tpcb->tp_netservice);
45336414Ssklower 		printf("m->mlen x%x, m->m_data:\n", m->m_len);
45436414Ssklower 		dump_buf(mtod(m, caddr_t), m->m_len);
45536414Ssklower 	ENDDEBUG
45636414Ssklower 	if( siso->siso_family != tpcb->tp_domain ) {
45736414Ssklower 		error = EAFNOSUPPORT;
45836414Ssklower 		goto done;
45936414Ssklower 	}
46037469Ssklower 	IFDEBUG(D_CONN)
46137469Ssklower 		printf("tp_route_to  calling nlp_pcbconn, netserv %d\n",
46237469Ssklower 			tpcb->tp_netservice);
46337469Ssklower 	ENDDEBUG
46437469Ssklower 	error = (tpcb->tp_nlproto->nlp_pcbconn)(tpcb->tp_sock->so_pcb, m);
46537469Ssklower 	if( error )
46637469Ssklower 		goto done;
46737469Ssklower 
46836414Ssklower 	{
46936414Ssklower 		register int save_netservice = tpcb->tp_netservice;
47036414Ssklower 
47136414Ssklower 		switch(tpcb->tp_netservice) {
47236414Ssklower 		case ISO_COSNS:
47336414Ssklower 		case ISO_CLNS:
47436414Ssklower 			/* This is a kludge but seems necessary so the passive end
47536414Ssklower 			 * can get long enough timers. sigh.
47637469Ssklower 			if( siso->siso_addr.osinet_idi[1] == (u_char)IDI_OSINET )
47736414Ssklower 			 */
47838841Ssklower #define	IDI_OSINET	0x0004	/* bcd of "0004" */
47937469Ssklower 			if( siso->siso_addr.isoa_genaddr[2] == (char)IDI_OSINET ) {
48036414Ssklower 				if( tpcb->tp_dont_change_params == 0) {
48136414Ssklower 					copyQOSparms( &tp_conn_param[ISO_COSNS],
48236414Ssklower 							&tpcb->_tp_param);
48336414Ssklower 				}
48436414Ssklower 				tpcb->tp_flags |= TPF_NLQOS_PDN;
48536414Ssklower 			}
48636414Ssklower 			/* drop through to IN_CLNS*/
48736414Ssklower 		case IN_CLNS:
48837469Ssklower 			if (iso_localifa(siso))
48937469Ssklower 				tpcb->tp_flags |= TPF_PEER_ON_SAMENET;
49036414Ssklower 			if( (tpcb->tp_class & TP_CLASS_4)==0 ) {
49136414Ssklower 				error = EPROTOTYPE;
49236414Ssklower 				break;
49336414Ssklower 			}
49436414Ssklower 			tpcb->tp_class = TP_CLASS_4;  /* IGNORE dont_change_parms */
49536414Ssklower 			break;
49636414Ssklower 
49736414Ssklower 		case ISO_CONS:
49836414Ssklower #if NARGOXTWENTYFIVE > 0
49936414Ssklower 			tpcb->tp_flags |= TPF_NLQOS_PDN;
50036414Ssklower 			if( tpcb->tp_dont_change_params == 0 ) {
50136414Ssklower 				copyQOSparms( &tp_conn_param[ISO_CONS],
50236414Ssklower 							&tpcb->_tp_param);
50336414Ssklower 			}
50436414Ssklower 			/*
50536414Ssklower 			 * for use over x.25 really need a small receive window,
50636414Ssklower 			 * need to start slowly, need small max negotiable tpdu size,
50736414Ssklower 			 * and need to use the congestion window to the max
50836414Ssklower 			 * IGNORES tp_dont_change_params for these!
50936414Ssklower 			 */
51036414Ssklower 			if( tpcb->tp_sock->so_snd.sb_hiwat > 512 ) {
51136414Ssklower 				(void) soreserve(tpcb->tp_sock, 512, 512 );/* GAG */
51236414Ssklower 			}
51336414Ssklower 			tpcb->tp_rx_strat =  TPRX_USE_CW;
51436414Ssklower 
51536414Ssklower 			if( (tpcb->tp_nlproto != &nl_protosw[ISO_CONS]) ) {
51636414Ssklower 				/* if the listener was restricting us to clns,
51736414Ssklower 				 * ( we never get here if the listener isn't af_iso )
51836414Ssklower 				 * refuse the connection :
51936414Ssklower 				 * but we don't have a way to restrict thus - it's
52036414Ssklower 				 * utterly permissive.
52136414Ssklower 					if(channel)  {
52236414Ssklower 						(void) cons_netcmd(CONN_REFUSE, tpcb->tp_npcb,
52336414Ssklower 								channel, tpcb->tp_class == TP_CLASS_4);
52436414Ssklower 						error = EPFNOSUPPORT;
52536414Ssklower 						goto done;
52636414Ssklower 					}
52736414Ssklower 				 */
52836414Ssklower 				IFDEBUG(D_CONN)
52936414Ssklower 					printf(
53036414Ssklower 					"tp_route_to( CHANGING nlproto old 0x%x new 0x%x)\n",
53136414Ssklower 							tpcb->tp_nlproto , &nl_protosw[ISO_CONS]);
53236414Ssklower 				ENDDEBUG
53336414Ssklower 				tpcb->tp_nlproto = &nl_protosw[ISO_CONS];
53436414Ssklower 			}
53536414Ssklower 			/* Now we've got the right nl_protosw.
53636414Ssklower 			 * If we already have a channel (we were called from tp_input())
53736414Ssklower 			 * tell cons that we'll hang onto this channel.
53836414Ssklower 			 * If we don't already have one (we were called from usrreq())
53936414Ssklower 			 * -and if it's TP0 open a net connection and wait for it to finish.
54036414Ssklower 			 */
54136414Ssklower 			if( channel ) {
54236414Ssklower 				error = cons_netcmd( CONN_CONFIRM, tpcb->tp_npcb,
54336414Ssklower 								channel, tpcb->tp_class == TP_CLASS_4);
54436414Ssklower 				vc_to_kill ++;
54536414Ssklower 			} else if( tpcb->tp_class != TP_CLASS_4 /* class 4 only */) {
54636414Ssklower 				/* better open vc if any possibility of ending up
54736414Ssklower 				 * in non-multiplexing class
54836414Ssklower 				 */
54936414Ssklower 				error = cons_openvc(tpcb->tp_npcb, siso, tpcb->tp_sock);
55036414Ssklower 				vc_to_kill ++;
55136414Ssklower 			}
55236414Ssklower 			/* class 4 doesn't need to open a vc now - may use one already
55336414Ssklower 			 * opened or may open one only when it sends a pkt.
55436414Ssklower 			 */
55536414Ssklower #else NARGOXTWENTYFIVE > 0
55636414Ssklower 			error = ECONNREFUSED;
55736414Ssklower #endif NARGOXTWENTYFIVE > 0
55836414Ssklower 			break;
55936414Ssklower 		default:
56036414Ssklower 			error = EPROTOTYPE;
56136414Ssklower 		}
56236414Ssklower 
56336414Ssklower 		ASSERT( save_netservice == tpcb->tp_netservice);
56436414Ssklower 	}
56536414Ssklower 	if( error && vc_to_kill ) {
56636414Ssklower 		tp_netcmd( tpcb, CONN_CLOSE);
56736414Ssklower 		goto done;
56836414Ssklower 	}
56936414Ssklower 	{	/* start with the global rtt, rtv stats */
57036414Ssklower 		register int i =
57136414Ssklower 		   (int) tpcb->tp_flags & (TPF_PEER_ON_SAMENET | TPF_NLQOS_PDN);
57236414Ssklower 
57336414Ssklower 		tpcb->tp_rtt = tp_stat.ts_rtt[i];
57436414Ssklower 		tpcb->tp_rtv = tp_stat.ts_rtv[i];
57536414Ssklower 	}
57636414Ssklower done:
57736414Ssklower 	IFDEBUG(D_CONN)
57836414Ssklower 		printf("tp_route_to  returns 0x%x\n", error);
57936414Ssklower 	ENDDEBUG
58036414Ssklower 	IFTRACE(D_CONN)
58136414Ssklower 		tptraceTPCB(TPPTmisc, "route_to: returns: error netserv class", error,
58236414Ssklower 			tpcb->tp_netservice, tpcb->tp_class, 0);
58336414Ssklower 	ENDTRACE
58436414Ssklower 	return error;
58536414Ssklower }
58636414Ssklower 
58736414Ssklower #ifdef TP_PERF_MEAS
58836414Ssklower /*
58936414Ssklower  * CALLED FROM:
59036414Ssklower  *  tp_ctloutput() when the user sets TPOPT_PERF_MEAS on
59136414Ssklower  *  and tp_newsocket() when a new connection is made from
59236414Ssklower  *  a listening socket with tp_perf_on == true.
59336414Ssklower  * FUNCTION and ARGUMENTS:
59436414Ssklower  *  (tpcb) is the usual; this procedure gets a clear cluster mbuf for
59536414Ssklower  *  a tp_pmeas structure, and makes tpcb->tp_p_meas point to it.
59636414Ssklower  * RETURN VALUE:
59736414Ssklower  *  ENOBUFS if it cannot get a cluster mbuf.
59836414Ssklower  */
59936414Ssklower 
60036414Ssklower int
60136414Ssklower tp_setup_perf(tpcb)
60236414Ssklower 	register struct tp_pcb *tpcb;
60336414Ssklower {
60436414Ssklower 	register struct mbuf *q;
60536414Ssklower 
60637469Ssklower 	if( tpcb->tp_p_meas == 0 ) {
60737469Ssklower 		MGET(q, M_WAITOK, MT_PCB);
60836414Ssklower 		if (q == 0)
60936414Ssklower 			return ENOBUFS;
61037469Ssklower 		MCLGET(q, M_WAITOK);
61137469Ssklower 		if ((q->m_flags & M_EXT) == 0) {
61237469Ssklower 			(void) m_free(q);
61336414Ssklower 			return ENOBUFS;
61436414Ssklower 		}
61537469Ssklower 		q->m_len = sizeof (struct tp_pmeas);
61637469Ssklower 		tpcb->tp_p_mbuf = q;
61737469Ssklower 		tpcb->tp_p_meas = mtod(q, struct tp_pmeas *);
61837469Ssklower 		bzero( (caddr_t)tpcb->tp_p_meas, sizeof (struct tp_pmeas) );
61937469Ssklower 		IFDEBUG(D_PERF_MEAS)
62037469Ssklower 			printf(
62137469Ssklower 			"tpcb 0x%x so 0x%x ref 0x%x tp_p_meas 0x%x tp_perf_on 0x%x\n",
62237469Ssklower 				tpcb, tpcb->tp_sock, tpcb->tp_lref,
62337469Ssklower 				tpcb->tp_p_meas, tpcb->tp_perf_on);
62437469Ssklower 		ENDDEBUG
62537469Ssklower 		tpcb->tp_perf_on = 1;
62636414Ssklower 	}
62736414Ssklower 	return 0;
62836414Ssklower }
62936414Ssklower #endif TP_PERF_MEAS
63036414Ssklower 
63136414Ssklower #ifdef ARGO_DEBUG
63236414Ssklower dump_addr (addr)
63336414Ssklower 	register struct sockaddr *addr;
63436414Ssklower {
63536414Ssklower 	switch( addr->sa_family ) {
63636414Ssklower 		case AF_INET:
63737469Ssklower 			dump_inaddr((struct sockaddr_in *)addr);
63836414Ssklower 			break;
63937469Ssklower #ifdef ISO
64036414Ssklower 		case AF_ISO:
64137469Ssklower 			dump_isoaddr((struct sockaddr_iso *)addr);
64236414Ssklower 			break;
64337469Ssklower #endif ISO
64436414Ssklower 		default:
64536414Ssklower 			printf("BAD AF: 0x%x\n", addr->sa_family);
64636414Ssklower 			break;
64736414Ssklower 	}
64836414Ssklower }
64936414Ssklower 
65037469Ssklower #define	MAX_COLUMNS	8
65137469Ssklower /*
65237469Ssklower  *	Dump the buffer to the screen in a readable format. Format is:
65337469Ssklower  *
65437469Ssklower  *		hex/dec  where hex is the hex format, dec is the decimal format.
65537469Ssklower  *		columns of hex/dec numbers will be printed, followed by the
65637469Ssklower  *		character representations (if printable).
65737469Ssklower  */
65837469Ssklower Dump_buf(buf, len)
65937469Ssklower caddr_t	buf;
66037469Ssklower int		len;
66137469Ssklower {
66237469Ssklower 	int		i,j;
66337469Ssklower 
66437469Ssklower 	printf("Dump buf 0x%x len 0x%x\n", buf, len);
66537469Ssklower 	for (i = 0; i < len; i += MAX_COLUMNS) {
66637469Ssklower 		printf("+%d:\t", i);
66737469Ssklower 		for (j = 0; j < MAX_COLUMNS; j++) {
66837469Ssklower 			if (i + j < len) {
66937469Ssklower 				printf("%x/%d\t", buf[i+j]&0xff, buf[i+j]);
67037469Ssklower 			} else {
67137469Ssklower 				printf("	");
67237469Ssklower 			}
67337469Ssklower 		}
67437469Ssklower 
67537469Ssklower 		for (j = 0; j < MAX_COLUMNS; j++) {
67637469Ssklower 			if (i + j < len) {
67737469Ssklower 				if (((buf[i+j]) > 31) && ((buf[i+j]) < 128))
67837469Ssklower 					printf("%c", buf[i+j]&0xff);
67937469Ssklower 				else
68037469Ssklower 					printf(".");
68137469Ssklower 			}
68237469Ssklower 		}
68337469Ssklower 		printf("\n");
68437469Ssklower 	}
68537469Ssklower }
68637469Ssklower 
68737469Ssklower 
68836414Ssklower #endif ARGO_DEBUG
68936414Ssklower 
690