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