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*47280Ssklower * @(#)tp_subr2.c 7.6 (Berkeley) 03/12/91 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 /* this def'n is to cause the expansion of this macro in the 4736414Ssklower * routine tp_local_credit : 4836414Ssklower */ 4936414Ssklower #define LOCAL_CREDIT_EXPAND 5036414Ssklower 5136414Ssklower #include "param.h" 5236414Ssklower #include "mbuf.h" 5336414Ssklower #include "socket.h" 5436414Ssklower #include "socketvar.h" 5536414Ssklower #include "domain.h" 5636414Ssklower #include "protosw.h" 5736414Ssklower #include "errno.h" 5836414Ssklower #include "types.h" 5936414Ssklower #include "time.h" 6036414Ssklower #include "kernel.h" 6136414Ssklower #undef MNULL 6237469Ssklower #include "argo_debug.h" 6337469Ssklower #include "tp_param.h" 6437469Ssklower #include "tp_ip.h" 6537469Ssklower #include "iso.h" 6637469Ssklower #include "iso_errno.h" 6737469Ssklower #include "iso_pcb.h" 6837469Ssklower #include "tp_timer.h" 6937469Ssklower #include "tp_stat.h" 7037469Ssklower #include "tp_tpdu.h" 7137469Ssklower #include "tp_pcb.h" 7237469Ssklower #include "tp_seq.h" 7337469Ssklower #include "tp_trace.h" 7437469Ssklower #include "tp_user.h" 7537469Ssklower #include "cons.h" 7636414Ssklower 7745900Ssklower #include "../net/if.h" 7845900Ssklower #ifdef TRUE 7945900Ssklower #undef FALSE 8045900Ssklower #undef TRUE 8145900Ssklower #endif 8245900Ssklower #include "../netccitt/x25.h" 8345900Ssklower #include "../netccitt/pk.h" 8445900Ssklower #include "../netccitt/pk_var.h" 8545900Ssklower 8636414Ssklower /* 8736414Ssklower * NAME: tp_local_credit() 8836414Ssklower * 8936414Ssklower * CALLED FROM: 9036414Ssklower * tp_emit(), tp_usrreq() 9136414Ssklower * 9236414Ssklower * FUNCTION and ARGUMENTS: 9336414Ssklower * Computes the local credit and stashes it in tpcb->tp_lcredit. 9436414Ssklower * It's a macro in the production system rather than a procdure. 9536414Ssklower * 9636414Ssklower * RETURNS: 9736414Ssklower * 9836414Ssklower * SIDE EFFECTS: 9936414Ssklower * 10036414Ssklower * NOTES: 10136414Ssklower * This doesn't actually get called in a production system - 10236414Ssklower * the macro gets expanded instead in place of calls to this proc. 10336414Ssklower * But for debugging, we call this and that allows us to add 10436414Ssklower * debugging messages easily here. 10536414Ssklower */ 10636414Ssklower void 10736414Ssklower tp_local_credit(tpcb) 10836414Ssklower struct tp_pcb *tpcb; 10936414Ssklower { 11036414Ssklower LOCAL_CREDIT(tpcb); 11136414Ssklower IFDEBUG(D_CREDIT) 11236414Ssklower printf("ref 0x%x lcdt 0x%x l_tpdusize 0x%x decbit 0x%x\n", 11336414Ssklower tpcb->tp_refp - tp_ref, 11436414Ssklower tpcb->tp_lcredit, 11536414Ssklower tpcb->tp_l_tpdusize, 11636414Ssklower tpcb->tp_decbit, 11736414Ssklower tpcb->tp_cong_win 11836414Ssklower ); 11936414Ssklower ENDDEBUG 12036414Ssklower IFTRACE(D_CREDIT) 12136414Ssklower tptraceTPCB(TPPTmisc, 12236414Ssklower "lcdt tpdusz \n", 12336414Ssklower tpcb->tp_lcredit, tpcb->tp_l_tpdusize, 0, 0); 12436414Ssklower ENDTRACE 12536414Ssklower } 12636414Ssklower 12736414Ssklower /* 12836414Ssklower * NAME: tp_protocol_error() 12936414Ssklower * 13036414Ssklower * CALLED FROM: 13136414Ssklower * tp_driver(), when it doesn't know what to do with 13236414Ssklower * a combo of event, state, predicate 13336414Ssklower * 13436414Ssklower * FUNCTION and ARGUMENTS: 13536414Ssklower * print error mesg 13636414Ssklower * 13736414Ssklower * RETURN VALUE: 13836414Ssklower * EIO - always 13936414Ssklower * 14036414Ssklower * SIDE EFFECTS: 14136414Ssklower * 14236414Ssklower * NOTES: 14336414Ssklower */ 14436414Ssklower int 14536414Ssklower tp_protocol_error(e,tpcb) 14636414Ssklower struct tp_event *e; 14736414Ssklower struct tp_pcb *tpcb; 14836414Ssklower { 14936414Ssklower printf("TP PROTOCOL ERROR! tpcb 0x%x event 0x%x, state 0x%x\n", 15036414Ssklower tpcb, e->ev_number, tpcb->tp_state); 15136414Ssklower IFTRACE(D_DRIVER) 15236414Ssklower tptraceTPCB(TPPTmisc, "PROTOCOL ERROR tpcb event state", 15336414Ssklower tpcb, e->ev_number, tpcb->tp_state, 0 ); 15436414Ssklower ENDTRACE 15536414Ssklower return EIO; /* for lack of anything better */ 15636414Ssklower } 15736414Ssklower 15836414Ssklower 15936414Ssklower /* Not used at the moment */ 16036414Ssklower ProtoHook 16136414Ssklower tp_drain() 16236414Ssklower { 16336414Ssklower return 0; 16436414Ssklower } 16536414Ssklower 16636414Ssklower 16736414Ssklower /* 16836414Ssklower * NAME: tp_indicate() 16936414Ssklower * 17036414Ssklower * CALLED FROM: 17136414Ssklower * tp.trans when XPD arrive, when a connection is being disconnected by 17236414Ssklower * the arrival of a DR or ER, and when a connection times out. 17336414Ssklower * 17436414Ssklower * FUNCTION and ARGUMENTS: 17536414Ssklower * (ind) is the type of indication : T_DISCONNECT, T_XPD 17636414Ssklower * (error) is an E* value that will be put in the socket structure 17736414Ssklower * to be passed along to the user later. 17836414Ssklower * Gives a SIGURG to the user process or group indicated by the socket 17936414Ssklower * attached to the tpcb. 18036414Ssklower * 18136414Ssklower * RETURNS: Rien 18236414Ssklower * 18336414Ssklower * SIDE EFFECTS: 18436414Ssklower * 18536414Ssklower * NOTES: 18636414Ssklower */ 18736414Ssklower void 18836414Ssklower tp_indicate(ind, tpcb, error) 18936414Ssklower int ind; 19036414Ssklower u_short error; 19136414Ssklower register struct tp_pcb *tpcb; 19236414Ssklower { 19336414Ssklower register struct socket *so = tpcb->tp_sock; 19436414Ssklower IFTRACE(D_INDICATION) 19539197Ssklower tptraceTPCB(TPPTindicate, ind, *(u_short *)(tpcb->tp_lsuffix), 19639197Ssklower *(u_short *)(tpcb->tp_fsuffix), error,so->so_pgid); 19736414Ssklower ENDTRACE 19836414Ssklower IFDEBUG(D_INDICATION) 19937469Ssklower char *ls, *fs; 20036414Ssklower ls = tpcb->tp_lsuffix, 20136414Ssklower fs = tpcb->tp_fsuffix, 20236414Ssklower 20336414Ssklower printf( 20437469Ssklower "indicate 0x%x lsuf 0x%02x%02x fsuf 0x%02x%02x err 0x%x noind 0x%x ref 0x%x\n", 20536414Ssklower ind, 20636414Ssklower *ls, *(ls+1), *fs, *(fs+1), 20737469Ssklower error, /*so->so_pgrp,*/ 20836414Ssklower tpcb->tp_no_disc_indications, 20936414Ssklower tpcb->tp_lref); 21036414Ssklower ENDDEBUG 21136414Ssklower 21236414Ssklower so->so_error = error; 21336414Ssklower 21436414Ssklower if (ind == T_DISCONNECT) { 21536414Ssklower if ( tpcb->tp_no_disc_indications ) 21636414Ssklower return; 21736414Ssklower } 21836414Ssklower IFTRACE(D_INDICATION) 21936414Ssklower tptraceTPCB(TPPTmisc, "doing sohasoutofband(so)", so,0,0,0); 22036414Ssklower ENDTRACE 22136414Ssklower sohasoutofband(so); 22236414Ssklower } 22336414Ssklower 22436414Ssklower /* 22536414Ssklower * NAME : tp_getoptions() 22636414Ssklower * 22736414Ssklower * CALLED FROM: 22836414Ssklower * tp.trans whenever we go into OPEN state 22936414Ssklower * 23036414Ssklower * FUNCTION and ARGUMENTS: 23136414Ssklower * sets the proper flags and values in the tpcb, to control 23236414Ssklower * the appropriate actions for the given class, options, 23336414Ssklower * sequence space, etc, etc. 23436414Ssklower * 23536414Ssklower * RETURNS: Nada 23636414Ssklower * 23736414Ssklower * SIDE EFFECTS: 23836414Ssklower * 23936414Ssklower * NOTES: 24036414Ssklower */ 24136414Ssklower void 24236414Ssklower tp_getoptions(tpcb) 24336414Ssklower struct tp_pcb *tpcb; 24436414Ssklower { 24536414Ssklower tpcb->tp_seqmask = 24636414Ssklower tpcb->tp_xtd_format ? TP_XTD_FMT_MASK : TP_NML_FMT_MASK ; 24736414Ssklower tpcb->tp_seqbit = 24836414Ssklower tpcb->tp_xtd_format ? TP_XTD_FMT_BIT : TP_NML_FMT_BIT ; 24936414Ssklower tpcb->tp_seqhalf = tpcb->tp_seqbit >> 1; 25036414Ssklower tpcb->tp_dt_ticks = 25136414Ssklower MAX(tpcb->tp_dt_ticks, (tpcb->tp_peer_acktime + 2)); 25236414Ssklower 25336414Ssklower } 25436414Ssklower 25536414Ssklower /* 25636414Ssklower * NAME: tp_recycle_tsuffix() 25736414Ssklower * 25836414Ssklower * CALLED FROM: 25936414Ssklower * Called when a ref is frozen. 26036414Ssklower * 26136414Ssklower * FUNCTION and ARGUMENTS: 26236414Ssklower * allows the suffix to be reused. 26336414Ssklower * 26436414Ssklower * RETURNS: zilch 26536414Ssklower * 26636414Ssklower * SIDE EFFECTS: 26736414Ssklower * 26836414Ssklower * NOTES: 26936414Ssklower */ 27036414Ssklower void 27136414Ssklower tp_recycle_tsuffix(tpcb) 27236414Ssklower struct tp_pcb *tpcb; 27336414Ssklower { 27437469Ssklower bzero((caddr_t)tpcb->tp_lsuffix, sizeof( tpcb->tp_lsuffix)); 27537469Ssklower bzero((caddr_t)tpcb->tp_fsuffix, sizeof( tpcb->tp_fsuffix)); 27636414Ssklower tpcb->tp_fsuffixlen = tpcb->tp_lsuffixlen = 0; 27736414Ssklower 27836414Ssklower (tpcb->tp_nlproto->nlp_recycle_suffix)(tpcb->tp_npcb); 27936414Ssklower } 28036414Ssklower 28136414Ssklower /* 28236414Ssklower * NAME: tp_quench() 28336414Ssklower * 28436414Ssklower * CALLED FROM: 28536414Ssklower * tp{af}_quench() when ICMP source quench or similar thing arrives. 28636414Ssklower * 28736414Ssklower * FUNCTION and ARGUMENTS: 28836414Ssklower * Drop the congestion window back to 1. 28936414Ssklower * Congestion window scheme: 29036414Ssklower * Initial value is 1. ("slow start" as Nagle, et. al. call it) 29136414Ssklower * For each good ack that arrives, the congestion window is increased 29236414Ssklower * by 1 (up to max size of logical infinity, which is to say, 29336414Ssklower * it doesn't wrap around). 29436414Ssklower * Source quench causes it to drop back to 1. 29536414Ssklower * tp_send() uses the smaller of (regular window, congestion window). 29636414Ssklower * One retransmission strategy option is to have any retransmission 29736414Ssklower * cause reset the congestion window back to 1. 29836414Ssklower * 29936414Ssklower * (cmd) is either PRC_QUENCH: source quench, or 30036414Ssklower * PRC_QUENCH2: dest. quench (dec bit) 30136414Ssklower * 30236414Ssklower * RETURNS: 30336414Ssklower * 30436414Ssklower * SIDE EFFECTS: 30536414Ssklower * 30636414Ssklower * NOTES: 30736414Ssklower */ 30836414Ssklower void 30936414Ssklower tp_quench( tpcb, cmd ) 31036414Ssklower struct tp_pcb *tpcb; 31136414Ssklower int cmd; 31236414Ssklower { 31336414Ssklower IFDEBUG(D_QUENCH) 31436414Ssklower printf("tp_quench tpcb 0x%x ref 0x%x sufx 0x%x\n", 31539197Ssklower tpcb, tpcb->tp_lref, *(u_short *)(tpcb->tp_lsuffix)); 31636414Ssklower printf("cong_win 0x%x decbit 0x%x \n", 31736414Ssklower tpcb->tp_cong_win, tpcb->tp_decbit); 31836414Ssklower ENDDEBUG 31936414Ssklower switch(cmd) { 32036414Ssklower case PRC_QUENCH: 32136414Ssklower tpcb->tp_cong_win = 1; 32236414Ssklower IncStat(ts_quench); 32336414Ssklower break; 32436414Ssklower case PRC_QUENCH2: 32536414Ssklower tpcb->tp_cong_win = 1; /* might as well quench source also */ 32636414Ssklower tpcb->tp_decbit = TP_DECBIT_CLEAR_COUNT; 32736414Ssklower IncStat(ts_rcvdecbit); 32836414Ssklower break; 32936414Ssklower } 33036414Ssklower } 33136414Ssklower 33236414Ssklower 33336414Ssklower /* 33436414Ssklower * NAME: tp_netcmd() 33536414Ssklower * 33636414Ssklower * CALLED FROM: 33736414Ssklower * 33836414Ssklower * FUNCTION and ARGUMENTS: 33936414Ssklower * 34036414Ssklower * RETURNS: 34136414Ssklower * 34236414Ssklower * SIDE EFFECTS: 34336414Ssklower * 34436414Ssklower * NOTES: 34536414Ssklower */ 34636414Ssklower tp_netcmd( tpcb, cmd ) 34736414Ssklower struct tp_pcb *tpcb; 34836414Ssklower int cmd; 34936414Ssklower { 35045900Ssklower #ifdef TPCONS 35145900Ssklower struct isopcb *isop; 35245900Ssklower struct pklcd *lcp; 35345900Ssklower 35445900Ssklower if (tpcb->tp_netservice != ISO_CONS) 35545900Ssklower return; 35645900Ssklower isop = (struct isopcb *)tpcb->tp_npcb; 35745900Ssklower lcp = (struct pklcd *)isop->isop_chan; 35836414Ssklower switch (cmd) { 35936414Ssklower 36036414Ssklower case CONN_CLOSE: 36136414Ssklower case CONN_REFUSE: 36245900Ssklower if (isop->isop_refcnt == 1) 36345900Ssklower pk_disconnect(lcp); 36445900Ssklower isop->isop_chan = 0; 36545900Ssklower isop->isop_refcnt = 0; 36636414Ssklower break; 36736414Ssklower 36836414Ssklower default: 36936414Ssklower printf("tp_netcmd(0x%x, 0x%x) NOT IMPLEMENTED\n", tpcb, cmd); 37036414Ssklower break; 37136414Ssklower } 37245900Ssklower #else TPCONS 37336414Ssklower printf("tp_netcmd(): X25 NOT CONFIGURED!!\n"); 37445900Ssklower #endif 37536414Ssklower } 37636414Ssklower /* 37736414Ssklower * CALLED FROM: 37836414Ssklower * tp_ctloutput() and tp_emit() 37936414Ssklower * FUNCTION and ARGUMENTS: 38036414Ssklower * Convert a class mask to the highest numeric value it represents. 38136414Ssklower */ 38236414Ssklower 38336414Ssklower int 38436414Ssklower tp_mask_to_num(x) 38536414Ssklower u_char x; 38636414Ssklower { 38736414Ssklower register int j; 38836414Ssklower 38936414Ssklower for(j = 4; j>=0 ;j--) { 39036414Ssklower if(x & (1<<j)) 39136414Ssklower break; 39236414Ssklower } 39336414Ssklower ASSERT( (j == 4) || (j == 0) ); /* for now */ 39436414Ssklower if( (j != 4) && (j != 0) ) { 39536414Ssklower printf("ASSERTION ERROR: tp_mask_to_num: x 0x%x j %d\n", 39636414Ssklower x, j); 39736414Ssklower } 39836414Ssklower IFTRACE(D_TPINPUT) 39936414Ssklower tptrace(TPPTmisc, "tp_mask_to_num(x) returns j", x, j, 0, 0); 40036414Ssklower ENDTRACE 40136414Ssklower IFDEBUG(D_TPINPUT) 40236414Ssklower printf("tp_mask_to_num(0x%x) returns 0x%x\n", x, j); 40336414Ssklower ENDDEBUG 40436414Ssklower return j; 40536414Ssklower } 40636414Ssklower 40736414Ssklower static 40836414Ssklower copyQOSparms(src, dst) 40936414Ssklower struct tp_conn_param *src, *dst; 41036414Ssklower { 41136414Ssklower /* copy all but the bits stuff at the end */ 41236414Ssklower #define COPYSIZE (12 * sizeof(short)) 41336414Ssklower 41437469Ssklower bcopy((caddr_t)src, (caddr_t)dst, COPYSIZE); 41536414Ssklower dst->p_tpdusize = src->p_tpdusize; 41636414Ssklower dst->p_ack_strat = src->p_ack_strat; 41736414Ssklower dst->p_rx_strat = src->p_rx_strat; 41836414Ssklower #undef COPYSIZE 41936414Ssklower } 42036414Ssklower 42136414Ssklower /* 42236414Ssklower * CALLED FROM: 42336414Ssklower * tp_usrreq on PRU_CONNECT and tp_input on receipt of CR 42436414Ssklower * 42536414Ssklower * FUNCTION and ARGUMENTS: 42636414Ssklower * route directly to x.25 if the address is type 37 - GROT. 42736414Ssklower * furthermore, let TP0 handle only type-37 addresses 42836414Ssklower * 42936414Ssklower * Since this assumes that its address argument is in a mbuf, the 43036414Ssklower * parameter was changed to reflect this assumtion. This also 43136414Ssklower * implies that an mbuf must be allocated when this is 43236414Ssklower * called from tp_input 43336414Ssklower * 43436414Ssklower * RETURNS: 43536414Ssklower * errno value : 43636414Ssklower * EAFNOSUPPORT if can't find an nl_protosw for x.25 (really could panic) 43736414Ssklower * ECONNREFUSED if trying to run TP0 with non-type 37 address 43836414Ssklower * possibly other E* returned from cons_netcmd() 43936414Ssklower * NOTE: 44036414Ssklower * Would like to eliminate as much of this as possible -- 44136414Ssklower * only one set of defaults (let the user set the parms according 44236414Ssklower * to parameters provided in the directory service). 44336414Ssklower * Left here for now 'cause we don't yet have a clean way to handle 44436414Ssklower * it on the passive end. 44536414Ssklower */ 44636414Ssklower int 44736414Ssklower tp_route_to( m, tpcb, channel) 44836414Ssklower struct mbuf *m; 44936414Ssklower register struct tp_pcb *tpcb; 45045900Ssklower caddr_t channel; 45136414Ssklower { 45236414Ssklower register struct sockaddr_iso *siso; /* NOTE: this may be a sockaddr_in */ 45336414Ssklower extern struct tp_conn_param tp_conn_param[]; 45445900Ssklower struct pklcd *lcp = (struct pklcd *)channel; 45536414Ssklower int error = 0; 45636414Ssklower 45736414Ssklower siso = mtod(m, struct sockaddr_iso *); 45836414Ssklower IFTRACE(D_CONN) 45936414Ssklower tptraceTPCB(TPPTmisc, 46036414Ssklower "route_to: so afi netservice class", 46137469Ssklower tpcb->tp_sock, siso->siso_addr.isoa_genaddr[0], tpcb->tp_netservice, 46236414Ssklower tpcb->tp_class); 46336414Ssklower ENDTRACE 46436414Ssklower IFDEBUG(D_CONN) 46536414Ssklower printf("tp_route_to( m x%x, channel 0x%x, tpcb 0x%x netserv 0x%x)\n", 46636414Ssklower m, channel, tpcb, tpcb->tp_netservice); 46736414Ssklower printf("m->mlen x%x, m->m_data:\n", m->m_len); 46836414Ssklower dump_buf(mtod(m, caddr_t), m->m_len); 46936414Ssklower ENDDEBUG 47045900Ssklower if (siso->siso_family != tpcb->tp_domain) { 47136414Ssklower error = EAFNOSUPPORT; 47236414Ssklower goto done; 47336414Ssklower } 47437469Ssklower IFDEBUG(D_CONN) 47537469Ssklower printf("tp_route_to calling nlp_pcbconn, netserv %d\n", 47637469Ssklower tpcb->tp_netservice); 47737469Ssklower ENDDEBUG 47845900Ssklower #ifdef TPCONS 47945900Ssklower if (lcp) { 48045900Ssklower struct isopcb *isop = (struct isopcb *)lcp->lcd_upnext, 48145900Ssklower *isop_new = (struct isopcb *)tpcb->tp_sock->so_pcb; 48245900Ssklower remque(isop_new); 48345900Ssklower free(isop_new, M_PCB); 48445900Ssklower tpcb->tp_sock->so_pcb = (caddr_t)isop; 48545900Ssklower if (isop->isop_refcnt == 0) { 48645900Ssklower extern struct isopcb tp_isopcb; 48745900Ssklower remque(isop); 48845900Ssklower insque(isop, &tp_isopcb); 48945900Ssklower isop->isop_head = &tp_isopcb; 49045900Ssklower iso_putsufx(isop, tpcb->tp_lsuffix, tpcb->tp_lsuffixlen, TP_LOCAL); 49145900Ssklower } 49245900Ssklower /* else there are already connections sharing this */ 49345900Ssklower isop->isop_refcnt++; 49445900Ssklower } else 49545900Ssklower #endif 49645900Ssklower error = (tpcb->tp_nlproto->nlp_pcbconn)(tpcb->tp_sock->so_pcb, m); 49737469Ssklower if( error ) 49837469Ssklower goto done; 49937469Ssklower 50036414Ssklower { 50136414Ssklower register int save_netservice = tpcb->tp_netservice; 50236414Ssklower 50336414Ssklower switch(tpcb->tp_netservice) { 50436414Ssklower case ISO_COSNS: 50536414Ssklower case ISO_CLNS: 50636414Ssklower /* This is a kludge but seems necessary so the passive end 50736414Ssklower * can get long enough timers. sigh. 50837469Ssklower if( siso->siso_addr.osinet_idi[1] == (u_char)IDI_OSINET ) 50936414Ssklower */ 51038841Ssklower #define IDI_OSINET 0x0004 /* bcd of "0004" */ 51137469Ssklower if( siso->siso_addr.isoa_genaddr[2] == (char)IDI_OSINET ) { 51236414Ssklower if( tpcb->tp_dont_change_params == 0) { 51336414Ssklower copyQOSparms( &tp_conn_param[ISO_COSNS], 51436414Ssklower &tpcb->_tp_param); 51536414Ssklower } 51636414Ssklower tpcb->tp_flags |= TPF_NLQOS_PDN; 51736414Ssklower } 51836414Ssklower /* drop through to IN_CLNS*/ 51936414Ssklower case IN_CLNS: 52037469Ssklower if (iso_localifa(siso)) 52137469Ssklower tpcb->tp_flags |= TPF_PEER_ON_SAMENET; 52236414Ssklower if( (tpcb->tp_class & TP_CLASS_4)==0 ) { 52336414Ssklower error = EPROTOTYPE; 52436414Ssklower break; 52536414Ssklower } 52636414Ssklower tpcb->tp_class = TP_CLASS_4; /* IGNORE dont_change_parms */ 52736414Ssklower break; 52836414Ssklower 52936414Ssklower case ISO_CONS: 53045900Ssklower #ifdef TPCONS 53136414Ssklower tpcb->tp_flags |= TPF_NLQOS_PDN; 53236414Ssklower if( tpcb->tp_dont_change_params == 0 ) { 53336414Ssklower copyQOSparms( &tp_conn_param[ISO_CONS], 53436414Ssklower &tpcb->_tp_param); 53536414Ssklower } 53636414Ssklower /* 53736414Ssklower * for use over x.25 really need a small receive window, 53836414Ssklower * need to start slowly, need small max negotiable tpdu size, 53936414Ssklower * and need to use the congestion window to the max 54036414Ssklower * IGNORES tp_dont_change_params for these! 54136414Ssklower */ 54236414Ssklower if( tpcb->tp_sock->so_snd.sb_hiwat > 512 ) { 54336414Ssklower (void) soreserve(tpcb->tp_sock, 512, 512 );/* GAG */ 54436414Ssklower } 54536414Ssklower tpcb->tp_rx_strat = TPRX_USE_CW; 54636414Ssklower 54736414Ssklower if( (tpcb->tp_nlproto != &nl_protosw[ISO_CONS]) ) { 54836414Ssklower IFDEBUG(D_CONN) 54936414Ssklower printf( 55036414Ssklower "tp_route_to( CHANGING nlproto old 0x%x new 0x%x)\n", 55136414Ssklower tpcb->tp_nlproto , &nl_protosw[ISO_CONS]); 55236414Ssklower ENDDEBUG 55336414Ssklower tpcb->tp_nlproto = &nl_protosw[ISO_CONS]; 55436414Ssklower } 55536414Ssklower /* class 4 doesn't need to open a vc now - may use one already 55636414Ssklower * opened or may open one only when it sends a pkt. 55736414Ssklower */ 55845900Ssklower #else TPCONS 55936414Ssklower error = ECONNREFUSED; 56045900Ssklower #endif TPCONS 56136414Ssklower break; 56236414Ssklower default: 56336414Ssklower error = EPROTOTYPE; 56436414Ssklower } 56536414Ssklower 56636414Ssklower ASSERT( save_netservice == tpcb->tp_netservice); 56736414Ssklower } 56845900Ssklower if (error) { 56936414Ssklower tp_netcmd( tpcb, CONN_CLOSE); 57036414Ssklower goto done; 57136414Ssklower } 57236414Ssklower { /* start with the global rtt, rtv stats */ 57336414Ssklower register int i = 57436414Ssklower (int) tpcb->tp_flags & (TPF_PEER_ON_SAMENET | TPF_NLQOS_PDN); 57536414Ssklower 57636414Ssklower tpcb->tp_rtt = tp_stat.ts_rtt[i]; 57736414Ssklower tpcb->tp_rtv = tp_stat.ts_rtv[i]; 57836414Ssklower } 57936414Ssklower done: 58036414Ssklower IFDEBUG(D_CONN) 58136414Ssklower printf("tp_route_to returns 0x%x\n", error); 58236414Ssklower ENDDEBUG 58336414Ssklower IFTRACE(D_CONN) 58436414Ssklower tptraceTPCB(TPPTmisc, "route_to: returns: error netserv class", error, 58536414Ssklower tpcb->tp_netservice, tpcb->tp_class, 0); 58636414Ssklower ENDTRACE 58736414Ssklower return error; 58836414Ssklower } 58936414Ssklower 590*47280Ssklower 591*47280Ssklower /* class zero version */ 592*47280Ssklower void 593*47280Ssklower tp0_stash( tpcb, e ) 594*47280Ssklower register struct tp_pcb *tpcb; 595*47280Ssklower register struct tp_event *e; 596*47280Ssklower { 597*47280Ssklower #ifndef lint 598*47280Ssklower #define E e->ATTR(DT_TPDU) 599*47280Ssklower #else lint 600*47280Ssklower #define E e->ev_union.EV_DT_TPDU 601*47280Ssklower #endif lint 602*47280Ssklower 603*47280Ssklower register struct sockbuf *sb = &tpcb->tp_sock->so_rcv; 604*47280Ssklower register struct isopcb *isop = (struct isopcb *)tpcb->tp_npcb; 605*47280Ssklower 606*47280Ssklower IFPERF(tpcb) 607*47280Ssklower PStat(tpcb, Nb_from_ll) += E.e_datalen; 608*47280Ssklower tpmeas(tpcb->tp_lref, TPtime_from_ll, &e->e_time, 609*47280Ssklower E.e_seq, PStat(tpcb, Nb_from_ll), E.e_datalen); 610*47280Ssklower ENDPERF 611*47280Ssklower 612*47280Ssklower IFDEBUG(D_STASH) 613*47280Ssklower printf("stash EQ: seq 0x%x datalen 0x%x eot 0x%x", 614*47280Ssklower E.e_seq, E.e_datalen, E.e_eot); 615*47280Ssklower ENDDEBUG 616*47280Ssklower 617*47280Ssklower IFTRACE(D_STASH) 618*47280Ssklower tptraceTPCB(TPPTmisc, "stash EQ: seq len eot", 619*47280Ssklower E.e_seq, E.e_datalen, E.e_eot, 0); 620*47280Ssklower ENDTRACE 621*47280Ssklower 622*47280Ssklower if ( E.e_eot ) { 623*47280Ssklower register struct mbuf *n = E.e_data; 624*47280Ssklower n->m_flags |= M_EOR; 625*47280Ssklower n->m_act = MNULL; /* set on tp_input */ 626*47280Ssklower } 627*47280Ssklower sbappend(sb, E.e_data); 628*47280Ssklower IFDEBUG(D_STASH) 629*47280Ssklower dump_mbuf(sb->sb_mb, "stash 0: so_rcv after appending"); 630*47280Ssklower ENDDEBUG 631*47280Ssklower if (tpcb->tp_netservice != ISO_CONS) 632*47280Ssklower printf("tp0_stash: tp running over something wierd\n"); 633*47280Ssklower else { 634*47280Ssklower register struct pklcd *lcp = (struct pklcd *)isop->isop_chan; 635*47280Ssklower pk_flowcontrol(lcp, sbspace(sb) <= 0, 1); 636*47280Ssklower } 637*47280Ssklower } 638*47280Ssklower 639*47280Ssklower void 640*47280Ssklower tp0_openflow(tpcb) 641*47280Ssklower register struct tp_pcb *tpcb; 642*47280Ssklower { 643*47280Ssklower register struct isopcb *isop = (struct isopcb *)tpcb->tp_npcb; 644*47280Ssklower if (tpcb->tp_netservice != ISO_CONS) 645*47280Ssklower printf("tp0_openflow: tp running over something wierd\n"); 646*47280Ssklower else { 647*47280Ssklower register struct pklcd *lcp = (struct pklcd *)isop->isop_chan; 648*47280Ssklower if (lcp->lcd_rxrnr_condition) 649*47280Ssklower pk_flowcontrol(lcp, 0, 0); 650*47280Ssklower } 651*47280Ssklower } 652*47280Ssklower #ifndef TPCONS 653*47280Ssklower static 654*47280Ssklower pk_flowcontrol() {} 655*47280Ssklower #endif 656*47280Ssklower 65736414Ssklower #ifdef TP_PERF_MEAS 65836414Ssklower /* 65936414Ssklower * CALLED FROM: 66036414Ssklower * tp_ctloutput() when the user sets TPOPT_PERF_MEAS on 66136414Ssklower * and tp_newsocket() when a new connection is made from 66236414Ssklower * a listening socket with tp_perf_on == true. 66336414Ssklower * FUNCTION and ARGUMENTS: 66436414Ssklower * (tpcb) is the usual; this procedure gets a clear cluster mbuf for 66536414Ssklower * a tp_pmeas structure, and makes tpcb->tp_p_meas point to it. 66636414Ssklower * RETURN VALUE: 66736414Ssklower * ENOBUFS if it cannot get a cluster mbuf. 66836414Ssklower */ 66936414Ssklower 67036414Ssklower int 67136414Ssklower tp_setup_perf(tpcb) 67236414Ssklower register struct tp_pcb *tpcb; 67336414Ssklower { 67436414Ssklower register struct mbuf *q; 67536414Ssklower 67637469Ssklower if( tpcb->tp_p_meas == 0 ) { 67737469Ssklower MGET(q, M_WAITOK, MT_PCB); 67836414Ssklower if (q == 0) 67936414Ssklower return ENOBUFS; 68037469Ssklower MCLGET(q, M_WAITOK); 68137469Ssklower if ((q->m_flags & M_EXT) == 0) { 68237469Ssklower (void) m_free(q); 68336414Ssklower return ENOBUFS; 68436414Ssklower } 68537469Ssklower q->m_len = sizeof (struct tp_pmeas); 68637469Ssklower tpcb->tp_p_mbuf = q; 68737469Ssklower tpcb->tp_p_meas = mtod(q, struct tp_pmeas *); 68837469Ssklower bzero( (caddr_t)tpcb->tp_p_meas, sizeof (struct tp_pmeas) ); 68937469Ssklower IFDEBUG(D_PERF_MEAS) 69037469Ssklower printf( 69137469Ssklower "tpcb 0x%x so 0x%x ref 0x%x tp_p_meas 0x%x tp_perf_on 0x%x\n", 69237469Ssklower tpcb, tpcb->tp_sock, tpcb->tp_lref, 69337469Ssklower tpcb->tp_p_meas, tpcb->tp_perf_on); 69437469Ssklower ENDDEBUG 69537469Ssklower tpcb->tp_perf_on = 1; 69636414Ssklower } 69736414Ssklower return 0; 69836414Ssklower } 69936414Ssklower #endif TP_PERF_MEAS 70036414Ssklower 70136414Ssklower #ifdef ARGO_DEBUG 70236414Ssklower dump_addr (addr) 70336414Ssklower register struct sockaddr *addr; 70436414Ssklower { 70536414Ssklower switch( addr->sa_family ) { 70636414Ssklower case AF_INET: 70737469Ssklower dump_inaddr((struct sockaddr_in *)addr); 70836414Ssklower break; 70937469Ssklower #ifdef ISO 71036414Ssklower case AF_ISO: 71137469Ssklower dump_isoaddr((struct sockaddr_iso *)addr); 71236414Ssklower break; 71337469Ssklower #endif ISO 71436414Ssklower default: 71536414Ssklower printf("BAD AF: 0x%x\n", addr->sa_family); 71636414Ssklower break; 71736414Ssklower } 71836414Ssklower } 71936414Ssklower 72037469Ssklower #define MAX_COLUMNS 8 72137469Ssklower /* 72237469Ssklower * Dump the buffer to the screen in a readable format. Format is: 72337469Ssklower * 72437469Ssklower * hex/dec where hex is the hex format, dec is the decimal format. 72537469Ssklower * columns of hex/dec numbers will be printed, followed by the 72637469Ssklower * character representations (if printable). 72737469Ssklower */ 72837469Ssklower Dump_buf(buf, len) 72937469Ssklower caddr_t buf; 73037469Ssklower int len; 73137469Ssklower { 73237469Ssklower int i,j; 73337469Ssklower 73437469Ssklower printf("Dump buf 0x%x len 0x%x\n", buf, len); 73537469Ssklower for (i = 0; i < len; i += MAX_COLUMNS) { 73637469Ssklower printf("+%d:\t", i); 73737469Ssklower for (j = 0; j < MAX_COLUMNS; j++) { 73837469Ssklower if (i + j < len) { 73937469Ssklower printf("%x/%d\t", buf[i+j]&0xff, buf[i+j]); 74037469Ssklower } else { 74137469Ssklower printf(" "); 74237469Ssklower } 74337469Ssklower } 74437469Ssklower 74537469Ssklower for (j = 0; j < MAX_COLUMNS; j++) { 74637469Ssklower if (i + j < len) { 74737469Ssklower if (((buf[i+j]) > 31) && ((buf[i+j]) < 128)) 74837469Ssklower printf("%c", buf[i+j]&0xff); 74937469Ssklower else 75037469Ssklower printf("."); 75137469Ssklower } 75237469Ssklower } 75337469Ssklower printf("\n"); 75437469Ssklower } 75537469Ssklower } 75637469Ssklower 75737469Ssklower 75836414Ssklower #endif ARGO_DEBUG 75936414Ssklower 760