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*48744Ssklower * @(#)tp_subr2.c 7.7 (Berkeley) 04/26/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 212*48744Ssklower if (ind == ER_TPDU) { 213*48744Ssklower register struct mbuf *m; 214*48744Ssklower struct tp_disc_reason x; 215*48744Ssklower 216*48744Ssklower if ((so->so_state & SS_CANTRCVMORE) == 0 && 217*48744Ssklower (m = m_get(M_DONTWAIT, MT_OOBDATA)) != 0) { 218*48744Ssklower 219*48744Ssklower x.dr_hdr.cmsg_len = m->m_len = sizeof(x); 220*48744Ssklower x.dr_hdr.cmsg_level = SOL_TRANSPORT; 221*48744Ssklower x.dr_hdr.cmsg_type= TPOPT_DISC_REASON; 222*48744Ssklower x.dr_reason = error; 223*48744Ssklower *mtod(m, struct tp_disc_reason *) = x; 224*48744Ssklower sbappendrecord(&tpcb->tp_Xrcv, m); 225*48744Ssklower error = 0; 226*48744Ssklower } else 227*48744Ssklower error = ECONNRESET; 228*48744Ssklower } 22936414Ssklower so->so_error = error; 23036414Ssklower 23136414Ssklower if (ind == T_DISCONNECT) { 232*48744Ssklower so->so_error = ENOTCONN; 23336414Ssklower if ( tpcb->tp_no_disc_indications ) 23436414Ssklower return; 23536414Ssklower } 23636414Ssklower IFTRACE(D_INDICATION) 23736414Ssklower tptraceTPCB(TPPTmisc, "doing sohasoutofband(so)", so,0,0,0); 23836414Ssklower ENDTRACE 23936414Ssklower sohasoutofband(so); 24036414Ssklower } 24136414Ssklower 24236414Ssklower /* 24336414Ssklower * NAME : tp_getoptions() 24436414Ssklower * 24536414Ssklower * CALLED FROM: 24636414Ssklower * tp.trans whenever we go into OPEN state 24736414Ssklower * 24836414Ssklower * FUNCTION and ARGUMENTS: 24936414Ssklower * sets the proper flags and values in the tpcb, to control 25036414Ssklower * the appropriate actions for the given class, options, 25136414Ssklower * sequence space, etc, etc. 25236414Ssklower * 25336414Ssklower * RETURNS: Nada 25436414Ssklower * 25536414Ssklower * SIDE EFFECTS: 25636414Ssklower * 25736414Ssklower * NOTES: 25836414Ssklower */ 25936414Ssklower void 26036414Ssklower tp_getoptions(tpcb) 26136414Ssklower struct tp_pcb *tpcb; 26236414Ssklower { 26336414Ssklower tpcb->tp_seqmask = 26436414Ssklower tpcb->tp_xtd_format ? TP_XTD_FMT_MASK : TP_NML_FMT_MASK ; 26536414Ssklower tpcb->tp_seqbit = 26636414Ssklower tpcb->tp_xtd_format ? TP_XTD_FMT_BIT : TP_NML_FMT_BIT ; 26736414Ssklower tpcb->tp_seqhalf = tpcb->tp_seqbit >> 1; 26836414Ssklower tpcb->tp_dt_ticks = 26936414Ssklower MAX(tpcb->tp_dt_ticks, (tpcb->tp_peer_acktime + 2)); 27036414Ssklower 27136414Ssklower } 27236414Ssklower 27336414Ssklower /* 27436414Ssklower * NAME: tp_recycle_tsuffix() 27536414Ssklower * 27636414Ssklower * CALLED FROM: 27736414Ssklower * Called when a ref is frozen. 27836414Ssklower * 27936414Ssklower * FUNCTION and ARGUMENTS: 28036414Ssklower * allows the suffix to be reused. 28136414Ssklower * 28236414Ssklower * RETURNS: zilch 28336414Ssklower * 28436414Ssklower * SIDE EFFECTS: 28536414Ssklower * 28636414Ssklower * NOTES: 28736414Ssklower */ 28836414Ssklower void 28936414Ssklower tp_recycle_tsuffix(tpcb) 29036414Ssklower struct tp_pcb *tpcb; 29136414Ssklower { 29237469Ssklower bzero((caddr_t)tpcb->tp_lsuffix, sizeof( tpcb->tp_lsuffix)); 29337469Ssklower bzero((caddr_t)tpcb->tp_fsuffix, sizeof( tpcb->tp_fsuffix)); 29436414Ssklower tpcb->tp_fsuffixlen = tpcb->tp_lsuffixlen = 0; 29536414Ssklower 29636414Ssklower (tpcb->tp_nlproto->nlp_recycle_suffix)(tpcb->tp_npcb); 29736414Ssklower } 29836414Ssklower 29936414Ssklower /* 30036414Ssklower * NAME: tp_quench() 30136414Ssklower * 30236414Ssklower * CALLED FROM: 30336414Ssklower * tp{af}_quench() when ICMP source quench or similar thing arrives. 30436414Ssklower * 30536414Ssklower * FUNCTION and ARGUMENTS: 30636414Ssklower * Drop the congestion window back to 1. 30736414Ssklower * Congestion window scheme: 30836414Ssklower * Initial value is 1. ("slow start" as Nagle, et. al. call it) 30936414Ssklower * For each good ack that arrives, the congestion window is increased 31036414Ssklower * by 1 (up to max size of logical infinity, which is to say, 31136414Ssklower * it doesn't wrap around). 31236414Ssklower * Source quench causes it to drop back to 1. 31336414Ssklower * tp_send() uses the smaller of (regular window, congestion window). 31436414Ssklower * One retransmission strategy option is to have any retransmission 31536414Ssklower * cause reset the congestion window back to 1. 31636414Ssklower * 31736414Ssklower * (cmd) is either PRC_QUENCH: source quench, or 31836414Ssklower * PRC_QUENCH2: dest. quench (dec bit) 31936414Ssklower * 32036414Ssklower * RETURNS: 32136414Ssklower * 32236414Ssklower * SIDE EFFECTS: 32336414Ssklower * 32436414Ssklower * NOTES: 32536414Ssklower */ 32636414Ssklower void 32736414Ssklower tp_quench( tpcb, cmd ) 32836414Ssklower struct tp_pcb *tpcb; 32936414Ssklower int cmd; 33036414Ssklower { 33136414Ssklower IFDEBUG(D_QUENCH) 33236414Ssklower printf("tp_quench tpcb 0x%x ref 0x%x sufx 0x%x\n", 33339197Ssklower tpcb, tpcb->tp_lref, *(u_short *)(tpcb->tp_lsuffix)); 33436414Ssklower printf("cong_win 0x%x decbit 0x%x \n", 33536414Ssklower tpcb->tp_cong_win, tpcb->tp_decbit); 33636414Ssklower ENDDEBUG 33736414Ssklower switch(cmd) { 33836414Ssklower case PRC_QUENCH: 33936414Ssklower tpcb->tp_cong_win = 1; 34036414Ssklower IncStat(ts_quench); 34136414Ssklower break; 34236414Ssklower case PRC_QUENCH2: 34336414Ssklower tpcb->tp_cong_win = 1; /* might as well quench source also */ 34436414Ssklower tpcb->tp_decbit = TP_DECBIT_CLEAR_COUNT; 34536414Ssklower IncStat(ts_rcvdecbit); 34636414Ssklower break; 34736414Ssklower } 34836414Ssklower } 34936414Ssklower 35036414Ssklower 35136414Ssklower /* 35236414Ssklower * NAME: tp_netcmd() 35336414Ssklower * 35436414Ssklower * CALLED FROM: 35536414Ssklower * 35636414Ssklower * FUNCTION and ARGUMENTS: 35736414Ssklower * 35836414Ssklower * RETURNS: 35936414Ssklower * 36036414Ssklower * SIDE EFFECTS: 36136414Ssklower * 36236414Ssklower * NOTES: 36336414Ssklower */ 36436414Ssklower tp_netcmd( tpcb, cmd ) 36536414Ssklower struct tp_pcb *tpcb; 36636414Ssklower int cmd; 36736414Ssklower { 36845900Ssklower #ifdef TPCONS 36945900Ssklower struct isopcb *isop; 37045900Ssklower struct pklcd *lcp; 37145900Ssklower 37245900Ssklower if (tpcb->tp_netservice != ISO_CONS) 37345900Ssklower return; 37445900Ssklower isop = (struct isopcb *)tpcb->tp_npcb; 37545900Ssklower lcp = (struct pklcd *)isop->isop_chan; 37636414Ssklower switch (cmd) { 37736414Ssklower 37836414Ssklower case CONN_CLOSE: 37936414Ssklower case CONN_REFUSE: 38045900Ssklower if (isop->isop_refcnt == 1) 38145900Ssklower pk_disconnect(lcp); 38245900Ssklower isop->isop_chan = 0; 38345900Ssklower isop->isop_refcnt = 0; 38436414Ssklower break; 38536414Ssklower 38636414Ssklower default: 38736414Ssklower printf("tp_netcmd(0x%x, 0x%x) NOT IMPLEMENTED\n", tpcb, cmd); 38836414Ssklower break; 38936414Ssklower } 39045900Ssklower #else TPCONS 39136414Ssklower printf("tp_netcmd(): X25 NOT CONFIGURED!!\n"); 39245900Ssklower #endif 39336414Ssklower } 39436414Ssklower /* 39536414Ssklower * CALLED FROM: 39636414Ssklower * tp_ctloutput() and tp_emit() 39736414Ssklower * FUNCTION and ARGUMENTS: 39836414Ssklower * Convert a class mask to the highest numeric value it represents. 39936414Ssklower */ 40036414Ssklower 40136414Ssklower int 40236414Ssklower tp_mask_to_num(x) 40336414Ssklower u_char x; 40436414Ssklower { 40536414Ssklower register int j; 40636414Ssklower 40736414Ssklower for(j = 4; j>=0 ;j--) { 40836414Ssklower if(x & (1<<j)) 40936414Ssklower break; 41036414Ssklower } 41136414Ssklower ASSERT( (j == 4) || (j == 0) ); /* for now */ 41236414Ssklower if( (j != 4) && (j != 0) ) { 41336414Ssklower printf("ASSERTION ERROR: tp_mask_to_num: x 0x%x j %d\n", 41436414Ssklower x, j); 41536414Ssklower } 41636414Ssklower IFTRACE(D_TPINPUT) 41736414Ssklower tptrace(TPPTmisc, "tp_mask_to_num(x) returns j", x, j, 0, 0); 41836414Ssklower ENDTRACE 41936414Ssklower IFDEBUG(D_TPINPUT) 42036414Ssklower printf("tp_mask_to_num(0x%x) returns 0x%x\n", x, j); 42136414Ssklower ENDDEBUG 42236414Ssklower return j; 42336414Ssklower } 42436414Ssklower 42536414Ssklower static 42636414Ssklower copyQOSparms(src, dst) 42736414Ssklower struct tp_conn_param *src, *dst; 42836414Ssklower { 42936414Ssklower /* copy all but the bits stuff at the end */ 43036414Ssklower #define COPYSIZE (12 * sizeof(short)) 43136414Ssklower 43237469Ssklower bcopy((caddr_t)src, (caddr_t)dst, COPYSIZE); 43336414Ssklower dst->p_tpdusize = src->p_tpdusize; 43436414Ssklower dst->p_ack_strat = src->p_ack_strat; 43536414Ssklower dst->p_rx_strat = src->p_rx_strat; 43636414Ssklower #undef COPYSIZE 43736414Ssklower } 43836414Ssklower 43936414Ssklower /* 44036414Ssklower * CALLED FROM: 44136414Ssklower * tp_usrreq on PRU_CONNECT and tp_input on receipt of CR 44236414Ssklower * 44336414Ssklower * FUNCTION and ARGUMENTS: 44436414Ssklower * route directly to x.25 if the address is type 37 - GROT. 44536414Ssklower * furthermore, let TP0 handle only type-37 addresses 44636414Ssklower * 44736414Ssklower * Since this assumes that its address argument is in a mbuf, the 44836414Ssklower * parameter was changed to reflect this assumtion. This also 44936414Ssklower * implies that an mbuf must be allocated when this is 45036414Ssklower * called from tp_input 45136414Ssklower * 45236414Ssklower * RETURNS: 45336414Ssklower * errno value : 45436414Ssklower * EAFNOSUPPORT if can't find an nl_protosw for x.25 (really could panic) 45536414Ssklower * ECONNREFUSED if trying to run TP0 with non-type 37 address 45636414Ssklower * possibly other E* returned from cons_netcmd() 45736414Ssklower * NOTE: 45836414Ssklower * Would like to eliminate as much of this as possible -- 45936414Ssklower * only one set of defaults (let the user set the parms according 46036414Ssklower * to parameters provided in the directory service). 46136414Ssklower * Left here for now 'cause we don't yet have a clean way to handle 46236414Ssklower * it on the passive end. 46336414Ssklower */ 46436414Ssklower int 46536414Ssklower tp_route_to( m, tpcb, channel) 46636414Ssklower struct mbuf *m; 46736414Ssklower register struct tp_pcb *tpcb; 46845900Ssklower caddr_t channel; 46936414Ssklower { 47036414Ssklower register struct sockaddr_iso *siso; /* NOTE: this may be a sockaddr_in */ 47136414Ssklower extern struct tp_conn_param tp_conn_param[]; 47245900Ssklower struct pklcd *lcp = (struct pklcd *)channel; 47336414Ssklower int error = 0; 47436414Ssklower 47536414Ssklower siso = mtod(m, struct sockaddr_iso *); 47636414Ssklower IFTRACE(D_CONN) 47736414Ssklower tptraceTPCB(TPPTmisc, 47836414Ssklower "route_to: so afi netservice class", 47937469Ssklower tpcb->tp_sock, siso->siso_addr.isoa_genaddr[0], tpcb->tp_netservice, 48036414Ssklower tpcb->tp_class); 48136414Ssklower ENDTRACE 48236414Ssklower IFDEBUG(D_CONN) 48336414Ssklower printf("tp_route_to( m x%x, channel 0x%x, tpcb 0x%x netserv 0x%x)\n", 48436414Ssklower m, channel, tpcb, tpcb->tp_netservice); 48536414Ssklower printf("m->mlen x%x, m->m_data:\n", m->m_len); 48636414Ssklower dump_buf(mtod(m, caddr_t), m->m_len); 48736414Ssklower ENDDEBUG 48845900Ssklower if (siso->siso_family != tpcb->tp_domain) { 48936414Ssklower error = EAFNOSUPPORT; 49036414Ssklower goto done; 49136414Ssklower } 49237469Ssklower IFDEBUG(D_CONN) 49337469Ssklower printf("tp_route_to calling nlp_pcbconn, netserv %d\n", 49437469Ssklower tpcb->tp_netservice); 49537469Ssklower ENDDEBUG 49645900Ssklower #ifdef TPCONS 49745900Ssklower if (lcp) { 49845900Ssklower struct isopcb *isop = (struct isopcb *)lcp->lcd_upnext, 49945900Ssklower *isop_new = (struct isopcb *)tpcb->tp_sock->so_pcb; 50045900Ssklower remque(isop_new); 50145900Ssklower free(isop_new, M_PCB); 50245900Ssklower tpcb->tp_sock->so_pcb = (caddr_t)isop; 50345900Ssklower if (isop->isop_refcnt == 0) { 50445900Ssklower extern struct isopcb tp_isopcb; 50545900Ssklower remque(isop); 50645900Ssklower insque(isop, &tp_isopcb); 50745900Ssklower isop->isop_head = &tp_isopcb; 50845900Ssklower iso_putsufx(isop, tpcb->tp_lsuffix, tpcb->tp_lsuffixlen, TP_LOCAL); 50945900Ssklower } 51045900Ssklower /* else there are already connections sharing this */ 51145900Ssklower isop->isop_refcnt++; 51245900Ssklower } else 51345900Ssklower #endif 51445900Ssklower error = (tpcb->tp_nlproto->nlp_pcbconn)(tpcb->tp_sock->so_pcb, m); 51537469Ssklower if( error ) 51637469Ssklower goto done; 51737469Ssklower 51836414Ssklower { 51936414Ssklower register int save_netservice = tpcb->tp_netservice; 52036414Ssklower 52136414Ssklower switch(tpcb->tp_netservice) { 52236414Ssklower case ISO_COSNS: 52336414Ssklower case ISO_CLNS: 52436414Ssklower /* This is a kludge but seems necessary so the passive end 52536414Ssklower * can get long enough timers. sigh. 52637469Ssklower if( siso->siso_addr.osinet_idi[1] == (u_char)IDI_OSINET ) 52736414Ssklower */ 52838841Ssklower #define IDI_OSINET 0x0004 /* bcd of "0004" */ 52937469Ssklower if( siso->siso_addr.isoa_genaddr[2] == (char)IDI_OSINET ) { 53036414Ssklower if( tpcb->tp_dont_change_params == 0) { 53136414Ssklower copyQOSparms( &tp_conn_param[ISO_COSNS], 53236414Ssklower &tpcb->_tp_param); 53336414Ssklower } 53436414Ssklower tpcb->tp_flags |= TPF_NLQOS_PDN; 53536414Ssklower } 53636414Ssklower /* drop through to IN_CLNS*/ 53736414Ssklower case IN_CLNS: 53837469Ssklower if (iso_localifa(siso)) 53937469Ssklower tpcb->tp_flags |= TPF_PEER_ON_SAMENET; 54036414Ssklower if( (tpcb->tp_class & TP_CLASS_4)==0 ) { 54136414Ssklower error = EPROTOTYPE; 54236414Ssklower break; 54336414Ssklower } 54436414Ssklower tpcb->tp_class = TP_CLASS_4; /* IGNORE dont_change_parms */ 54536414Ssklower break; 54636414Ssklower 54736414Ssklower case ISO_CONS: 54845900Ssklower #ifdef TPCONS 54936414Ssklower tpcb->tp_flags |= TPF_NLQOS_PDN; 55036414Ssklower if( tpcb->tp_dont_change_params == 0 ) { 55136414Ssklower copyQOSparms( &tp_conn_param[ISO_CONS], 55236414Ssklower &tpcb->_tp_param); 55336414Ssklower } 55436414Ssklower /* 55536414Ssklower * for use over x.25 really need a small receive window, 55636414Ssklower * need to start slowly, need small max negotiable tpdu size, 55736414Ssklower * and need to use the congestion window to the max 55836414Ssklower * IGNORES tp_dont_change_params for these! 55936414Ssklower */ 56036414Ssklower if( tpcb->tp_sock->so_snd.sb_hiwat > 512 ) { 56136414Ssklower (void) soreserve(tpcb->tp_sock, 512, 512 );/* GAG */ 56236414Ssklower } 56336414Ssklower tpcb->tp_rx_strat = TPRX_USE_CW; 56436414Ssklower 56536414Ssklower if( (tpcb->tp_nlproto != &nl_protosw[ISO_CONS]) ) { 56636414Ssklower IFDEBUG(D_CONN) 56736414Ssklower printf( 56836414Ssklower "tp_route_to( CHANGING nlproto old 0x%x new 0x%x)\n", 56936414Ssklower tpcb->tp_nlproto , &nl_protosw[ISO_CONS]); 57036414Ssklower ENDDEBUG 57136414Ssklower tpcb->tp_nlproto = &nl_protosw[ISO_CONS]; 57236414Ssklower } 57336414Ssklower /* class 4 doesn't need to open a vc now - may use one already 57436414Ssklower * opened or may open one only when it sends a pkt. 57536414Ssklower */ 57645900Ssklower #else TPCONS 57736414Ssklower error = ECONNREFUSED; 57845900Ssklower #endif TPCONS 57936414Ssklower break; 58036414Ssklower default: 58136414Ssklower error = EPROTOTYPE; 58236414Ssklower } 58336414Ssklower 58436414Ssklower ASSERT( save_netservice == tpcb->tp_netservice); 58536414Ssklower } 58645900Ssklower if (error) { 58736414Ssklower tp_netcmd( tpcb, CONN_CLOSE); 58836414Ssklower goto done; 58936414Ssklower } 59036414Ssklower { /* start with the global rtt, rtv stats */ 59136414Ssklower register int i = 59236414Ssklower (int) tpcb->tp_flags & (TPF_PEER_ON_SAMENET | TPF_NLQOS_PDN); 59336414Ssklower 59436414Ssklower tpcb->tp_rtt = tp_stat.ts_rtt[i]; 59536414Ssklower tpcb->tp_rtv = tp_stat.ts_rtv[i]; 59636414Ssklower } 59736414Ssklower done: 59836414Ssklower IFDEBUG(D_CONN) 59936414Ssklower printf("tp_route_to returns 0x%x\n", error); 60036414Ssklower ENDDEBUG 60136414Ssklower IFTRACE(D_CONN) 60236414Ssklower tptraceTPCB(TPPTmisc, "route_to: returns: error netserv class", error, 60336414Ssklower tpcb->tp_netservice, tpcb->tp_class, 0); 60436414Ssklower ENDTRACE 60536414Ssklower return error; 60636414Ssklower } 60736414Ssklower 60847280Ssklower 60947280Ssklower /* class zero version */ 61047280Ssklower void 61147280Ssklower tp0_stash( tpcb, e ) 61247280Ssklower register struct tp_pcb *tpcb; 61347280Ssklower register struct tp_event *e; 61447280Ssklower { 61547280Ssklower #ifndef lint 61647280Ssklower #define E e->ATTR(DT_TPDU) 61747280Ssklower #else lint 61847280Ssklower #define E e->ev_union.EV_DT_TPDU 61947280Ssklower #endif lint 62047280Ssklower 62147280Ssklower register struct sockbuf *sb = &tpcb->tp_sock->so_rcv; 62247280Ssklower register struct isopcb *isop = (struct isopcb *)tpcb->tp_npcb; 62347280Ssklower 62447280Ssklower IFPERF(tpcb) 62547280Ssklower PStat(tpcb, Nb_from_ll) += E.e_datalen; 62647280Ssklower tpmeas(tpcb->tp_lref, TPtime_from_ll, &e->e_time, 62747280Ssklower E.e_seq, PStat(tpcb, Nb_from_ll), E.e_datalen); 62847280Ssklower ENDPERF 62947280Ssklower 63047280Ssklower IFDEBUG(D_STASH) 63147280Ssklower printf("stash EQ: seq 0x%x datalen 0x%x eot 0x%x", 63247280Ssklower E.e_seq, E.e_datalen, E.e_eot); 63347280Ssklower ENDDEBUG 63447280Ssklower 63547280Ssklower IFTRACE(D_STASH) 63647280Ssklower tptraceTPCB(TPPTmisc, "stash EQ: seq len eot", 63747280Ssklower E.e_seq, E.e_datalen, E.e_eot, 0); 63847280Ssklower ENDTRACE 63947280Ssklower 64047280Ssklower if ( E.e_eot ) { 64147280Ssklower register struct mbuf *n = E.e_data; 64247280Ssklower n->m_flags |= M_EOR; 64347280Ssklower n->m_act = MNULL; /* set on tp_input */ 64447280Ssklower } 64547280Ssklower sbappend(sb, E.e_data); 64647280Ssklower IFDEBUG(D_STASH) 64747280Ssklower dump_mbuf(sb->sb_mb, "stash 0: so_rcv after appending"); 64847280Ssklower ENDDEBUG 64947280Ssklower if (tpcb->tp_netservice != ISO_CONS) 65047280Ssklower printf("tp0_stash: tp running over something wierd\n"); 65147280Ssklower else { 65247280Ssklower register struct pklcd *lcp = (struct pklcd *)isop->isop_chan; 65347280Ssklower pk_flowcontrol(lcp, sbspace(sb) <= 0, 1); 65447280Ssklower } 65547280Ssklower } 65647280Ssklower 65747280Ssklower void 65847280Ssklower tp0_openflow(tpcb) 65947280Ssklower register struct tp_pcb *tpcb; 66047280Ssklower { 66147280Ssklower register struct isopcb *isop = (struct isopcb *)tpcb->tp_npcb; 66247280Ssklower if (tpcb->tp_netservice != ISO_CONS) 66347280Ssklower printf("tp0_openflow: tp running over something wierd\n"); 66447280Ssklower else { 66547280Ssklower register struct pklcd *lcp = (struct pklcd *)isop->isop_chan; 66647280Ssklower if (lcp->lcd_rxrnr_condition) 66747280Ssklower pk_flowcontrol(lcp, 0, 0); 66847280Ssklower } 66947280Ssklower } 67047280Ssklower #ifndef TPCONS 67147280Ssklower static 67247280Ssklower pk_flowcontrol() {} 67347280Ssklower #endif 67447280Ssklower 67536414Ssklower #ifdef TP_PERF_MEAS 67636414Ssklower /* 67736414Ssklower * CALLED FROM: 67836414Ssklower * tp_ctloutput() when the user sets TPOPT_PERF_MEAS on 67936414Ssklower * and tp_newsocket() when a new connection is made from 68036414Ssklower * a listening socket with tp_perf_on == true. 68136414Ssklower * FUNCTION and ARGUMENTS: 68236414Ssklower * (tpcb) is the usual; this procedure gets a clear cluster mbuf for 68336414Ssklower * a tp_pmeas structure, and makes tpcb->tp_p_meas point to it. 68436414Ssklower * RETURN VALUE: 68536414Ssklower * ENOBUFS if it cannot get a cluster mbuf. 68636414Ssklower */ 68736414Ssklower 68836414Ssklower int 68936414Ssklower tp_setup_perf(tpcb) 69036414Ssklower register struct tp_pcb *tpcb; 69136414Ssklower { 69236414Ssklower register struct mbuf *q; 69336414Ssklower 69437469Ssklower if( tpcb->tp_p_meas == 0 ) { 69537469Ssklower MGET(q, M_WAITOK, MT_PCB); 69636414Ssklower if (q == 0) 69736414Ssklower return ENOBUFS; 69837469Ssklower MCLGET(q, M_WAITOK); 69937469Ssklower if ((q->m_flags & M_EXT) == 0) { 70037469Ssklower (void) m_free(q); 70136414Ssklower return ENOBUFS; 70236414Ssklower } 70337469Ssklower q->m_len = sizeof (struct tp_pmeas); 70437469Ssklower tpcb->tp_p_mbuf = q; 70537469Ssklower tpcb->tp_p_meas = mtod(q, struct tp_pmeas *); 70637469Ssklower bzero( (caddr_t)tpcb->tp_p_meas, sizeof (struct tp_pmeas) ); 70737469Ssklower IFDEBUG(D_PERF_MEAS) 70837469Ssklower printf( 70937469Ssklower "tpcb 0x%x so 0x%x ref 0x%x tp_p_meas 0x%x tp_perf_on 0x%x\n", 71037469Ssklower tpcb, tpcb->tp_sock, tpcb->tp_lref, 71137469Ssklower tpcb->tp_p_meas, tpcb->tp_perf_on); 71237469Ssklower ENDDEBUG 71337469Ssklower tpcb->tp_perf_on = 1; 71436414Ssklower } 71536414Ssklower return 0; 71636414Ssklower } 71736414Ssklower #endif TP_PERF_MEAS 71836414Ssklower 71936414Ssklower #ifdef ARGO_DEBUG 72036414Ssklower dump_addr (addr) 72136414Ssklower register struct sockaddr *addr; 72236414Ssklower { 72336414Ssklower switch( addr->sa_family ) { 72436414Ssklower case AF_INET: 72537469Ssklower dump_inaddr((struct sockaddr_in *)addr); 72636414Ssklower break; 72737469Ssklower #ifdef ISO 72836414Ssklower case AF_ISO: 72937469Ssklower dump_isoaddr((struct sockaddr_iso *)addr); 73036414Ssklower break; 73137469Ssklower #endif ISO 73236414Ssklower default: 73336414Ssklower printf("BAD AF: 0x%x\n", addr->sa_family); 73436414Ssklower break; 73536414Ssklower } 73636414Ssklower } 73736414Ssklower 73837469Ssklower #define MAX_COLUMNS 8 73937469Ssklower /* 74037469Ssklower * Dump the buffer to the screen in a readable format. Format is: 74137469Ssklower * 74237469Ssklower * hex/dec where hex is the hex format, dec is the decimal format. 74337469Ssklower * columns of hex/dec numbers will be printed, followed by the 74437469Ssklower * character representations (if printable). 74537469Ssklower */ 74637469Ssklower Dump_buf(buf, len) 74737469Ssklower caddr_t buf; 74837469Ssklower int len; 74937469Ssklower { 75037469Ssklower int i,j; 75137469Ssklower 75237469Ssklower printf("Dump buf 0x%x len 0x%x\n", buf, len); 75337469Ssklower for (i = 0; i < len; i += MAX_COLUMNS) { 75437469Ssklower printf("+%d:\t", i); 75537469Ssklower for (j = 0; j < MAX_COLUMNS; j++) { 75637469Ssklower if (i + j < len) { 75737469Ssklower printf("%x/%d\t", buf[i+j]&0xff, buf[i+j]); 75837469Ssklower } else { 75937469Ssklower printf(" "); 76037469Ssklower } 76137469Ssklower } 76237469Ssklower 76337469Ssklower for (j = 0; j < MAX_COLUMNS; j++) { 76437469Ssklower if (i + j < len) { 76537469Ssklower if (((buf[i+j]) > 31) && ((buf[i+j]) < 128)) 76637469Ssklower printf("%c", buf[i+j]&0xff); 76737469Ssklower else 76837469Ssklower printf("."); 76937469Ssklower } 77037469Ssklower } 77137469Ssklower printf("\n"); 77237469Ssklower } 77337469Ssklower } 77437469Ssklower 77537469Ssklower 77636414Ssklower #endif ARGO_DEBUG 77736414Ssklower 778