149268Sbostic /*- 249268Sbostic * Copyright (c) 1991 The Regents of the University of California. 349268Sbostic * All rights reserved. 449268Sbostic * 549268Sbostic * %sccs.include.redist.c% 649268Sbostic * 7*50435Ssklower * @(#)tp_subr2.c 7.11 (Berkeley) 07/18/91 849268Sbostic */ 949268Sbostic 1036414Ssklower /*********************************************************** 1136414Ssklower Copyright IBM Corporation 1987 1236414Ssklower 1336414Ssklower All Rights Reserved 1436414Ssklower 1536414Ssklower Permission to use, copy, modify, and distribute this software and its 1636414Ssklower documentation for any purpose and without fee is hereby granted, 1736414Ssklower provided that the above copyright notice appear in all copies and that 1836414Ssklower both that copyright notice and this permission notice appear in 1936414Ssklower supporting documentation, and that the name of IBM not be 2036414Ssklower used in advertising or publicity pertaining to distribution of the 2136414Ssklower software without specific, written prior permission. 2236414Ssklower 2336414Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 2436414Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 2536414Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 2636414Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 2736414Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 2836414Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 2936414Ssklower SOFTWARE. 3036414Ssklower 3136414Ssklower ******************************************************************/ 3236414Ssklower 3336414Ssklower /* 3436414Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 3536414Ssklower */ 3636414Ssklower /* 3736414Ssklower * ARGO TP 3836414Ssklower * 3936414Ssklower * $Header: tp_subr2.c,v 5.5 88/11/18 17:28:55 nhall Exp $ 4036414Ssklower * $Source: /usr/argo/sys/netiso/RCS/tp_subr2.c,v $ 4136414Ssklower * 4236414Ssklower * Some auxiliary routines: 4349268Sbostic * tp_protocol_error: required by xebec- called when a combo of state, 4449268Sbostic * event, predicate isn't covered for by the transition file. 4549268Sbostic * tp_indicate: gives indications(signals) to the user process 4649268Sbostic * tp_getoptions: initializes variables that are affected by the options 4749268Sbostic * chosen. 4836414Ssklower */ 4936414Ssklower 5036414Ssklower /* this def'n is to cause the expansion of this macro in the 5136414Ssklower * routine tp_local_credit : 5236414Ssklower */ 5336414Ssklower #define LOCAL_CREDIT_EXPAND 5436414Ssklower 5536414Ssklower #include "param.h" 5650243Ssklower #include "systm.h" 5736414Ssklower #include "mbuf.h" 5836414Ssklower #include "socket.h" 5936414Ssklower #include "socketvar.h" 6036414Ssklower #include "domain.h" 6136414Ssklower #include "protosw.h" 6236414Ssklower #include "errno.h" 6336414Ssklower #include "types.h" 6436414Ssklower #include "time.h" 6536414Ssklower #include "kernel.h" 6636414Ssklower #undef MNULL 6737469Ssklower #include "argo_debug.h" 6837469Ssklower #include "tp_param.h" 6937469Ssklower #include "tp_ip.h" 7037469Ssklower #include "iso.h" 7137469Ssklower #include "iso_errno.h" 7237469Ssklower #include "iso_pcb.h" 7337469Ssklower #include "tp_timer.h" 7437469Ssklower #include "tp_stat.h" 7537469Ssklower #include "tp_tpdu.h" 7637469Ssklower #include "tp_pcb.h" 7737469Ssklower #include "tp_seq.h" 7837469Ssklower #include "tp_trace.h" 7937469Ssklower #include "tp_user.h" 8037469Ssklower #include "cons.h" 8136414Ssklower 8245900Ssklower #include "../net/if.h" 8345900Ssklower #ifdef TRUE 8445900Ssklower #undef FALSE 8545900Ssklower #undef TRUE 8645900Ssklower #endif 8745900Ssklower #include "../netccitt/x25.h" 8845900Ssklower #include "../netccitt/pk.h" 8945900Ssklower #include "../netccitt/pk_var.h" 9045900Ssklower 9136414Ssklower /* 9236414Ssklower * NAME: tp_local_credit() 9336414Ssklower * 9436414Ssklower * CALLED FROM: 9536414Ssklower * tp_emit(), tp_usrreq() 9636414Ssklower * 9736414Ssklower * FUNCTION and ARGUMENTS: 9836414Ssklower * Computes the local credit and stashes it in tpcb->tp_lcredit. 9936414Ssklower * It's a macro in the production system rather than a procdure. 10036414Ssklower * 10136414Ssklower * RETURNS: 10236414Ssklower * 10336414Ssklower * SIDE EFFECTS: 10436414Ssklower * 10536414Ssklower * NOTES: 10636414Ssklower * This doesn't actually get called in a production system - 10736414Ssklower * the macro gets expanded instead in place of calls to this proc. 10836414Ssklower * But for debugging, we call this and that allows us to add 10936414Ssklower * debugging messages easily here. 11036414Ssklower */ 11136414Ssklower void 11236414Ssklower tp_local_credit(tpcb) 11336414Ssklower struct tp_pcb *tpcb; 11436414Ssklower { 11536414Ssklower LOCAL_CREDIT(tpcb); 11636414Ssklower IFDEBUG(D_CREDIT) 11736414Ssklower printf("ref 0x%x lcdt 0x%x l_tpdusize 0x%x decbit 0x%x\n", 11836414Ssklower tpcb->tp_refp - tp_ref, 11936414Ssklower tpcb->tp_lcredit, 12036414Ssklower tpcb->tp_l_tpdusize, 12136414Ssklower tpcb->tp_decbit, 12236414Ssklower tpcb->tp_cong_win 12336414Ssklower ); 12436414Ssklower ENDDEBUG 12536414Ssklower IFTRACE(D_CREDIT) 12636414Ssklower tptraceTPCB(TPPTmisc, 12736414Ssklower "lcdt tpdusz \n", 12836414Ssklower tpcb->tp_lcredit, tpcb->tp_l_tpdusize, 0, 0); 12936414Ssklower ENDTRACE 13036414Ssklower } 13136414Ssklower 13236414Ssklower /* 13336414Ssklower * NAME: tp_protocol_error() 13436414Ssklower * 13536414Ssklower * CALLED FROM: 13636414Ssklower * tp_driver(), when it doesn't know what to do with 13736414Ssklower * a combo of event, state, predicate 13836414Ssklower * 13936414Ssklower * FUNCTION and ARGUMENTS: 14036414Ssklower * print error mesg 14136414Ssklower * 14236414Ssklower * RETURN VALUE: 14336414Ssklower * EIO - always 14436414Ssklower * 14536414Ssklower * SIDE EFFECTS: 14636414Ssklower * 14736414Ssklower * NOTES: 14836414Ssklower */ 14936414Ssklower int 15036414Ssklower tp_protocol_error(e,tpcb) 15136414Ssklower struct tp_event *e; 15236414Ssklower struct tp_pcb *tpcb; 15336414Ssklower { 15436414Ssklower printf("TP PROTOCOL ERROR! tpcb 0x%x event 0x%x, state 0x%x\n", 15536414Ssklower tpcb, e->ev_number, tpcb->tp_state); 15636414Ssklower IFTRACE(D_DRIVER) 15736414Ssklower tptraceTPCB(TPPTmisc, "PROTOCOL ERROR tpcb event state", 15836414Ssklower tpcb, e->ev_number, tpcb->tp_state, 0 ); 15936414Ssklower ENDTRACE 16036414Ssklower return EIO; /* for lack of anything better */ 16136414Ssklower } 16236414Ssklower 16336414Ssklower 16436414Ssklower /* Not used at the moment */ 16536414Ssklower ProtoHook 16636414Ssklower tp_drain() 16736414Ssklower { 16836414Ssklower return 0; 16936414Ssklower } 17036414Ssklower 17136414Ssklower 17236414Ssklower /* 17336414Ssklower * NAME: tp_indicate() 17436414Ssklower * 17536414Ssklower * CALLED FROM: 17636414Ssklower * tp.trans when XPD arrive, when a connection is being disconnected by 17736414Ssklower * the arrival of a DR or ER, and when a connection times out. 17836414Ssklower * 17936414Ssklower * FUNCTION and ARGUMENTS: 18036414Ssklower * (ind) is the type of indication : T_DISCONNECT, T_XPD 18136414Ssklower * (error) is an E* value that will be put in the socket structure 18236414Ssklower * to be passed along to the user later. 18336414Ssklower * Gives a SIGURG to the user process or group indicated by the socket 18436414Ssklower * attached to the tpcb. 18536414Ssklower * 18636414Ssklower * RETURNS: Rien 18736414Ssklower * 18836414Ssklower * SIDE EFFECTS: 18936414Ssklower * 19036414Ssklower * NOTES: 19136414Ssklower */ 19236414Ssklower void 19336414Ssklower tp_indicate(ind, tpcb, error) 19436414Ssklower int ind; 19536414Ssklower u_short error; 19636414Ssklower register struct tp_pcb *tpcb; 19736414Ssklower { 19836414Ssklower register struct socket *so = tpcb->tp_sock; 19936414Ssklower IFTRACE(D_INDICATION) 20039197Ssklower tptraceTPCB(TPPTindicate, ind, *(u_short *)(tpcb->tp_lsuffix), 20139197Ssklower *(u_short *)(tpcb->tp_fsuffix), error,so->so_pgid); 20236414Ssklower ENDTRACE 20336414Ssklower IFDEBUG(D_INDICATION) 20437469Ssklower char *ls, *fs; 20536414Ssklower ls = tpcb->tp_lsuffix, 20636414Ssklower fs = tpcb->tp_fsuffix, 20736414Ssklower 20836414Ssklower printf( 20937469Ssklower "indicate 0x%x lsuf 0x%02x%02x fsuf 0x%02x%02x err 0x%x noind 0x%x ref 0x%x\n", 21036414Ssklower ind, 21136414Ssklower *ls, *(ls+1), *fs, *(fs+1), 21237469Ssklower error, /*so->so_pgrp,*/ 21336414Ssklower tpcb->tp_no_disc_indications, 21436414Ssklower tpcb->tp_lref); 21536414Ssklower ENDDEBUG 21636414Ssklower 21748744Ssklower if (ind == ER_TPDU) { 21848744Ssklower register struct mbuf *m; 21948744Ssklower struct tp_disc_reason x; 22048744Ssklower 22148744Ssklower if ((so->so_state & SS_CANTRCVMORE) == 0 && 22248744Ssklower (m = m_get(M_DONTWAIT, MT_OOBDATA)) != 0) { 22348744Ssklower 22448744Ssklower x.dr_hdr.cmsg_len = m->m_len = sizeof(x); 22548744Ssklower x.dr_hdr.cmsg_level = SOL_TRANSPORT; 22648744Ssklower x.dr_hdr.cmsg_type= TPOPT_DISC_REASON; 22748744Ssklower x.dr_reason = error; 22848744Ssklower *mtod(m, struct tp_disc_reason *) = x; 22948744Ssklower sbappendrecord(&tpcb->tp_Xrcv, m); 23048744Ssklower error = 0; 23148744Ssklower } else 23248744Ssklower error = ECONNRESET; 23348744Ssklower } 23436414Ssklower so->so_error = error; 23536414Ssklower 23636414Ssklower if (ind == T_DISCONNECT) { 23748744Ssklower so->so_error = ENOTCONN; 23836414Ssklower if ( tpcb->tp_no_disc_indications ) 23936414Ssklower return; 24036414Ssklower } 24136414Ssklower IFTRACE(D_INDICATION) 24236414Ssklower tptraceTPCB(TPPTmisc, "doing sohasoutofband(so)", so,0,0,0); 24336414Ssklower ENDTRACE 24436414Ssklower sohasoutofband(so); 24536414Ssklower } 24636414Ssklower 24736414Ssklower /* 24836414Ssklower * NAME : tp_getoptions() 24936414Ssklower * 25036414Ssklower * CALLED FROM: 25136414Ssklower * tp.trans whenever we go into OPEN state 25236414Ssklower * 25336414Ssklower * FUNCTION and ARGUMENTS: 25436414Ssklower * sets the proper flags and values in the tpcb, to control 25536414Ssklower * the appropriate actions for the given class, options, 25636414Ssklower * sequence space, etc, etc. 25736414Ssklower * 25836414Ssklower * RETURNS: Nada 25936414Ssklower * 26036414Ssklower * SIDE EFFECTS: 26136414Ssklower * 26236414Ssklower * NOTES: 26336414Ssklower */ 26436414Ssklower void 26536414Ssklower tp_getoptions(tpcb) 26636414Ssklower struct tp_pcb *tpcb; 26736414Ssklower { 26836414Ssklower tpcb->tp_seqmask = 26936414Ssklower tpcb->tp_xtd_format ? TP_XTD_FMT_MASK : TP_NML_FMT_MASK ; 27036414Ssklower tpcb->tp_seqbit = 27136414Ssklower tpcb->tp_xtd_format ? TP_XTD_FMT_BIT : TP_NML_FMT_BIT ; 27236414Ssklower tpcb->tp_seqhalf = tpcb->tp_seqbit >> 1; 27336414Ssklower tpcb->tp_dt_ticks = 27436414Ssklower MAX(tpcb->tp_dt_ticks, (tpcb->tp_peer_acktime + 2)); 27536414Ssklower 27636414Ssklower } 27736414Ssklower 27836414Ssklower /* 27936414Ssklower * NAME: tp_recycle_tsuffix() 28036414Ssklower * 28136414Ssklower * CALLED FROM: 28236414Ssklower * Called when a ref is frozen. 28336414Ssklower * 28436414Ssklower * FUNCTION and ARGUMENTS: 28536414Ssklower * allows the suffix to be reused. 28636414Ssklower * 28736414Ssklower * RETURNS: zilch 28836414Ssklower * 28936414Ssklower * SIDE EFFECTS: 29036414Ssklower * 29136414Ssklower * NOTES: 29236414Ssklower */ 29336414Ssklower void 29436414Ssklower tp_recycle_tsuffix(tpcb) 29536414Ssklower struct tp_pcb *tpcb; 29636414Ssklower { 29737469Ssklower bzero((caddr_t)tpcb->tp_lsuffix, sizeof( tpcb->tp_lsuffix)); 29837469Ssklower bzero((caddr_t)tpcb->tp_fsuffix, sizeof( tpcb->tp_fsuffix)); 29936414Ssklower tpcb->tp_fsuffixlen = tpcb->tp_lsuffixlen = 0; 30036414Ssklower 30136414Ssklower (tpcb->tp_nlproto->nlp_recycle_suffix)(tpcb->tp_npcb); 30236414Ssklower } 30336414Ssklower 30436414Ssklower /* 30536414Ssklower * NAME: tp_quench() 30636414Ssklower * 30736414Ssklower * CALLED FROM: 30836414Ssklower * tp{af}_quench() when ICMP source quench or similar thing arrives. 30936414Ssklower * 31036414Ssklower * FUNCTION and ARGUMENTS: 31136414Ssklower * Drop the congestion window back to 1. 31236414Ssklower * Congestion window scheme: 31336414Ssklower * Initial value is 1. ("slow start" as Nagle, et. al. call it) 31436414Ssklower * For each good ack that arrives, the congestion window is increased 31536414Ssklower * by 1 (up to max size of logical infinity, which is to say, 31636414Ssklower * it doesn't wrap around). 31736414Ssklower * Source quench causes it to drop back to 1. 31836414Ssklower * tp_send() uses the smaller of (regular window, congestion window). 31936414Ssklower * One retransmission strategy option is to have any retransmission 32036414Ssklower * cause reset the congestion window back to 1. 32136414Ssklower * 32236414Ssklower * (cmd) is either PRC_QUENCH: source quench, or 32336414Ssklower * PRC_QUENCH2: dest. quench (dec bit) 32436414Ssklower * 32536414Ssklower * RETURNS: 32636414Ssklower * 32736414Ssklower * SIDE EFFECTS: 32836414Ssklower * 32936414Ssklower * NOTES: 33036414Ssklower */ 33136414Ssklower void 33236414Ssklower tp_quench( tpcb, cmd ) 33336414Ssklower struct tp_pcb *tpcb; 33436414Ssklower int cmd; 33536414Ssklower { 33636414Ssklower IFDEBUG(D_QUENCH) 33736414Ssklower printf("tp_quench tpcb 0x%x ref 0x%x sufx 0x%x\n", 33839197Ssklower tpcb, tpcb->tp_lref, *(u_short *)(tpcb->tp_lsuffix)); 33936414Ssklower printf("cong_win 0x%x decbit 0x%x \n", 34036414Ssklower tpcb->tp_cong_win, tpcb->tp_decbit); 34136414Ssklower ENDDEBUG 34236414Ssklower switch(cmd) { 34336414Ssklower case PRC_QUENCH: 34436414Ssklower tpcb->tp_cong_win = 1; 34536414Ssklower IncStat(ts_quench); 34636414Ssklower break; 34736414Ssklower case PRC_QUENCH2: 34836414Ssklower tpcb->tp_cong_win = 1; /* might as well quench source also */ 34936414Ssklower tpcb->tp_decbit = TP_DECBIT_CLEAR_COUNT; 35036414Ssklower IncStat(ts_rcvdecbit); 35136414Ssklower break; 35236414Ssklower } 35336414Ssklower } 35436414Ssklower 35536414Ssklower 35636414Ssklower /* 35736414Ssklower * NAME: tp_netcmd() 35836414Ssklower * 35936414Ssklower * CALLED FROM: 36036414Ssklower * 36136414Ssklower * FUNCTION and ARGUMENTS: 36236414Ssklower * 36336414Ssklower * RETURNS: 36436414Ssklower * 36536414Ssklower * SIDE EFFECTS: 36636414Ssklower * 36736414Ssklower * NOTES: 36836414Ssklower */ 36936414Ssklower tp_netcmd( tpcb, cmd ) 37036414Ssklower struct tp_pcb *tpcb; 37136414Ssklower int cmd; 37236414Ssklower { 37345900Ssklower #ifdef TPCONS 37445900Ssklower struct isopcb *isop; 37545900Ssklower struct pklcd *lcp; 37645900Ssklower 37745900Ssklower if (tpcb->tp_netservice != ISO_CONS) 37845900Ssklower return; 37945900Ssklower isop = (struct isopcb *)tpcb->tp_npcb; 38045900Ssklower lcp = (struct pklcd *)isop->isop_chan; 38136414Ssklower switch (cmd) { 38236414Ssklower 38336414Ssklower case CONN_CLOSE: 38436414Ssklower case CONN_REFUSE: 38545900Ssklower if (isop->isop_refcnt == 1) 38645900Ssklower pk_disconnect(lcp); 38745900Ssklower isop->isop_chan = 0; 38845900Ssklower isop->isop_refcnt = 0; 38936414Ssklower break; 39036414Ssklower 39136414Ssklower default: 39236414Ssklower printf("tp_netcmd(0x%x, 0x%x) NOT IMPLEMENTED\n", tpcb, cmd); 39336414Ssklower break; 39436414Ssklower } 39545900Ssklower #else TPCONS 39636414Ssklower printf("tp_netcmd(): X25 NOT CONFIGURED!!\n"); 39745900Ssklower #endif 39836414Ssklower } 39936414Ssklower /* 40036414Ssklower * CALLED FROM: 40136414Ssklower * tp_ctloutput() and tp_emit() 40236414Ssklower * FUNCTION and ARGUMENTS: 40336414Ssklower * Convert a class mask to the highest numeric value it represents. 40436414Ssklower */ 40536414Ssklower 40636414Ssklower int 40736414Ssklower tp_mask_to_num(x) 40836414Ssklower u_char x; 40936414Ssklower { 41036414Ssklower register int j; 41136414Ssklower 41236414Ssklower for(j = 4; j>=0 ;j--) { 41336414Ssklower if(x & (1<<j)) 41436414Ssklower break; 41536414Ssklower } 41636414Ssklower ASSERT( (j == 4) || (j == 0) ); /* for now */ 41736414Ssklower if( (j != 4) && (j != 0) ) { 41836414Ssklower printf("ASSERTION ERROR: tp_mask_to_num: x 0x%x j %d\n", 41936414Ssklower x, j); 42036414Ssklower } 42136414Ssklower IFTRACE(D_TPINPUT) 42236414Ssklower tptrace(TPPTmisc, "tp_mask_to_num(x) returns j", x, j, 0, 0); 42336414Ssklower ENDTRACE 42436414Ssklower IFDEBUG(D_TPINPUT) 42536414Ssklower printf("tp_mask_to_num(0x%x) returns 0x%x\n", x, j); 42636414Ssklower ENDDEBUG 42736414Ssklower return j; 42836414Ssklower } 42936414Ssklower 43036414Ssklower static 43136414Ssklower copyQOSparms(src, dst) 43236414Ssklower struct tp_conn_param *src, *dst; 43336414Ssklower { 43436414Ssklower /* copy all but the bits stuff at the end */ 43536414Ssklower #define COPYSIZE (12 * sizeof(short)) 43636414Ssklower 43737469Ssklower bcopy((caddr_t)src, (caddr_t)dst, COPYSIZE); 43836414Ssklower dst->p_tpdusize = src->p_tpdusize; 43936414Ssklower dst->p_ack_strat = src->p_ack_strat; 44036414Ssklower dst->p_rx_strat = src->p_rx_strat; 44136414Ssklower #undef COPYSIZE 44236414Ssklower } 44336414Ssklower 44436414Ssklower /* 44536414Ssklower * CALLED FROM: 44636414Ssklower * tp_usrreq on PRU_CONNECT and tp_input on receipt of CR 44736414Ssklower * 44836414Ssklower * FUNCTION and ARGUMENTS: 44936414Ssklower * route directly to x.25 if the address is type 37 - GROT. 45036414Ssklower * furthermore, let TP0 handle only type-37 addresses 45136414Ssklower * 45236414Ssklower * Since this assumes that its address argument is in a mbuf, the 45336414Ssklower * parameter was changed to reflect this assumtion. This also 45436414Ssklower * implies that an mbuf must be allocated when this is 45536414Ssklower * called from tp_input 45636414Ssklower * 45736414Ssklower * RETURNS: 45836414Ssklower * errno value : 45936414Ssklower * EAFNOSUPPORT if can't find an nl_protosw for x.25 (really could panic) 46036414Ssklower * ECONNREFUSED if trying to run TP0 with non-type 37 address 46136414Ssklower * possibly other E* returned from cons_netcmd() 46236414Ssklower * NOTE: 46336414Ssklower * Would like to eliminate as much of this as possible -- 46436414Ssklower * only one set of defaults (let the user set the parms according 46536414Ssklower * to parameters provided in the directory service). 46636414Ssklower * Left here for now 'cause we don't yet have a clean way to handle 46736414Ssklower * it on the passive end. 46836414Ssklower */ 46936414Ssklower int 47036414Ssklower tp_route_to( m, tpcb, channel) 47136414Ssklower struct mbuf *m; 47236414Ssklower register struct tp_pcb *tpcb; 47345900Ssklower caddr_t channel; 47436414Ssklower { 47536414Ssklower register struct sockaddr_iso *siso; /* NOTE: this may be a sockaddr_in */ 47636414Ssklower extern struct tp_conn_param tp_conn_param[]; 47745900Ssklower struct pklcd *lcp = (struct pklcd *)channel; 47836414Ssklower int error = 0; 47936414Ssklower 48036414Ssklower siso = mtod(m, struct sockaddr_iso *); 48136414Ssklower IFTRACE(D_CONN) 48236414Ssklower tptraceTPCB(TPPTmisc, 48336414Ssklower "route_to: so afi netservice class", 48437469Ssklower tpcb->tp_sock, siso->siso_addr.isoa_genaddr[0], tpcb->tp_netservice, 48536414Ssklower tpcb->tp_class); 48636414Ssklower ENDTRACE 48736414Ssklower IFDEBUG(D_CONN) 48836414Ssklower printf("tp_route_to( m x%x, channel 0x%x, tpcb 0x%x netserv 0x%x)\n", 48936414Ssklower m, channel, tpcb, tpcb->tp_netservice); 49036414Ssklower printf("m->mlen x%x, m->m_data:\n", m->m_len); 49136414Ssklower dump_buf(mtod(m, caddr_t), m->m_len); 49236414Ssklower ENDDEBUG 49345900Ssklower if (siso->siso_family != tpcb->tp_domain) { 49436414Ssklower error = EAFNOSUPPORT; 49536414Ssklower goto done; 49636414Ssklower } 49737469Ssklower IFDEBUG(D_CONN) 49837469Ssklower printf("tp_route_to calling nlp_pcbconn, netserv %d\n", 49937469Ssklower tpcb->tp_netservice); 50037469Ssklower ENDDEBUG 50145900Ssklower #ifdef TPCONS 50245900Ssklower if (lcp) { 50345900Ssklower struct isopcb *isop = (struct isopcb *)lcp->lcd_upnext, 504*50435Ssklower *isop_new = (struct isopcb *)tpcb->tp_npcb; 50545900Ssklower remque(isop_new); 50645900Ssklower free(isop_new, M_PCB); 507*50435Ssklower tpcb->tp_npcb = (caddr_t)isop; 50845900Ssklower if (isop->isop_refcnt == 0) { 50945900Ssklower extern struct isopcb tp_isopcb; 51045900Ssklower remque(isop); 51145900Ssklower insque(isop, &tp_isopcb); 51245900Ssklower isop->isop_head = &tp_isopcb; 51345900Ssklower iso_putsufx(isop, tpcb->tp_lsuffix, tpcb->tp_lsuffixlen, TP_LOCAL); 51445900Ssklower } 51545900Ssklower /* else there are already connections sharing this */ 51645900Ssklower isop->isop_refcnt++; 51745900Ssklower } else 51845900Ssklower #endif 519*50435Ssklower error = (tpcb->tp_nlproto->nlp_pcbconn)(tpcb->tp_npcb, m); 52037469Ssklower if( error ) 52137469Ssklower goto done; 52237469Ssklower 52336414Ssklower { 52436414Ssklower register int save_netservice = tpcb->tp_netservice; 52536414Ssklower 52636414Ssklower switch(tpcb->tp_netservice) { 52736414Ssklower case ISO_COSNS: 52836414Ssklower case ISO_CLNS: 52936414Ssklower /* This is a kludge but seems necessary so the passive end 53036414Ssklower * can get long enough timers. sigh. 53137469Ssklower if( siso->siso_addr.osinet_idi[1] == (u_char)IDI_OSINET ) 53236414Ssklower */ 53338841Ssklower #define IDI_OSINET 0x0004 /* bcd of "0004" */ 53437469Ssklower if( siso->siso_addr.isoa_genaddr[2] == (char)IDI_OSINET ) { 53536414Ssklower if( tpcb->tp_dont_change_params == 0) { 53636414Ssklower copyQOSparms( &tp_conn_param[ISO_COSNS], 53736414Ssklower &tpcb->_tp_param); 53836414Ssklower } 53936414Ssklower tpcb->tp_flags |= TPF_NLQOS_PDN; 54036414Ssklower } 54136414Ssklower /* drop through to IN_CLNS*/ 54236414Ssklower case IN_CLNS: 54337469Ssklower if (iso_localifa(siso)) 54437469Ssklower tpcb->tp_flags |= TPF_PEER_ON_SAMENET; 54536414Ssklower if( (tpcb->tp_class & TP_CLASS_4)==0 ) { 54636414Ssklower error = EPROTOTYPE; 54736414Ssklower break; 54836414Ssklower } 54936414Ssklower tpcb->tp_class = TP_CLASS_4; /* IGNORE dont_change_parms */ 55036414Ssklower break; 55136414Ssklower 55236414Ssklower case ISO_CONS: 55345900Ssklower #ifdef TPCONS 55436414Ssklower tpcb->tp_flags |= TPF_NLQOS_PDN; 55536414Ssklower if( tpcb->tp_dont_change_params == 0 ) { 55636414Ssklower copyQOSparms( &tp_conn_param[ISO_CONS], 55736414Ssklower &tpcb->_tp_param); 55836414Ssklower } 55936414Ssklower /* 56036414Ssklower * for use over x.25 really need a small receive window, 56136414Ssklower * need to start slowly, need small max negotiable tpdu size, 56236414Ssklower * and need to use the congestion window to the max 56336414Ssklower * IGNORES tp_dont_change_params for these! 56436414Ssklower */ 56536414Ssklower if( tpcb->tp_sock->so_snd.sb_hiwat > 512 ) { 56636414Ssklower (void) soreserve(tpcb->tp_sock, 512, 512 );/* GAG */ 56736414Ssklower } 56836414Ssklower tpcb->tp_rx_strat = TPRX_USE_CW; 56936414Ssklower 57036414Ssklower if( (tpcb->tp_nlproto != &nl_protosw[ISO_CONS]) ) { 57136414Ssklower IFDEBUG(D_CONN) 57236414Ssklower printf( 57336414Ssklower "tp_route_to( CHANGING nlproto old 0x%x new 0x%x)\n", 57436414Ssklower tpcb->tp_nlproto , &nl_protosw[ISO_CONS]); 57536414Ssklower ENDDEBUG 57636414Ssklower tpcb->tp_nlproto = &nl_protosw[ISO_CONS]; 57736414Ssklower } 57836414Ssklower /* class 4 doesn't need to open a vc now - may use one already 57936414Ssklower * opened or may open one only when it sends a pkt. 58036414Ssklower */ 58145900Ssklower #else TPCONS 58236414Ssklower error = ECONNREFUSED; 58345900Ssklower #endif TPCONS 58436414Ssklower break; 58536414Ssklower default: 58636414Ssklower error = EPROTOTYPE; 58736414Ssklower } 58836414Ssklower 58936414Ssklower ASSERT( save_netservice == tpcb->tp_netservice); 59036414Ssklower } 59145900Ssklower if (error) { 59236414Ssklower tp_netcmd( tpcb, CONN_CLOSE); 59336414Ssklower goto done; 59436414Ssklower } 59536414Ssklower { /* start with the global rtt, rtv stats */ 59636414Ssklower register int i = 59736414Ssklower (int) tpcb->tp_flags & (TPF_PEER_ON_SAMENET | TPF_NLQOS_PDN); 59836414Ssklower 59936414Ssklower tpcb->tp_rtt = tp_stat.ts_rtt[i]; 60036414Ssklower tpcb->tp_rtv = tp_stat.ts_rtv[i]; 60136414Ssklower } 60236414Ssklower done: 60336414Ssklower IFDEBUG(D_CONN) 60436414Ssklower printf("tp_route_to returns 0x%x\n", error); 60536414Ssklower ENDDEBUG 60636414Ssklower IFTRACE(D_CONN) 60736414Ssklower tptraceTPCB(TPPTmisc, "route_to: returns: error netserv class", error, 60836414Ssklower tpcb->tp_netservice, tpcb->tp_class, 0); 60936414Ssklower ENDTRACE 61036414Ssklower return error; 61136414Ssklower } 61236414Ssklower 61347280Ssklower 61447280Ssklower /* class zero version */ 61547280Ssklower void 61647280Ssklower tp0_stash( tpcb, e ) 61747280Ssklower register struct tp_pcb *tpcb; 61847280Ssklower register struct tp_event *e; 61947280Ssklower { 62047280Ssklower #ifndef lint 62147280Ssklower #define E e->ATTR(DT_TPDU) 62247280Ssklower #else lint 62347280Ssklower #define E e->ev_union.EV_DT_TPDU 62447280Ssklower #endif lint 62547280Ssklower 62647280Ssklower register struct sockbuf *sb = &tpcb->tp_sock->so_rcv; 62747280Ssklower register struct isopcb *isop = (struct isopcb *)tpcb->tp_npcb; 62847280Ssklower 62947280Ssklower IFPERF(tpcb) 63047280Ssklower PStat(tpcb, Nb_from_ll) += E.e_datalen; 63147280Ssklower tpmeas(tpcb->tp_lref, TPtime_from_ll, &e->e_time, 63247280Ssklower E.e_seq, PStat(tpcb, Nb_from_ll), E.e_datalen); 63347280Ssklower ENDPERF 63447280Ssklower 63547280Ssklower IFDEBUG(D_STASH) 63647280Ssklower printf("stash EQ: seq 0x%x datalen 0x%x eot 0x%x", 63747280Ssklower E.e_seq, E.e_datalen, E.e_eot); 63847280Ssklower ENDDEBUG 63947280Ssklower 64047280Ssklower IFTRACE(D_STASH) 64147280Ssklower tptraceTPCB(TPPTmisc, "stash EQ: seq len eot", 64247280Ssklower E.e_seq, E.e_datalen, E.e_eot, 0); 64347280Ssklower ENDTRACE 64447280Ssklower 64547280Ssklower if ( E.e_eot ) { 64647280Ssklower register struct mbuf *n = E.e_data; 64747280Ssklower n->m_flags |= M_EOR; 64847280Ssklower n->m_act = MNULL; /* set on tp_input */ 64947280Ssklower } 65047280Ssklower sbappend(sb, E.e_data); 65147280Ssklower IFDEBUG(D_STASH) 65247280Ssklower dump_mbuf(sb->sb_mb, "stash 0: so_rcv after appending"); 65347280Ssklower ENDDEBUG 65447280Ssklower if (tpcb->tp_netservice != ISO_CONS) 65547280Ssklower printf("tp0_stash: tp running over something wierd\n"); 65647280Ssklower else { 65747280Ssklower register struct pklcd *lcp = (struct pklcd *)isop->isop_chan; 65847280Ssklower pk_flowcontrol(lcp, sbspace(sb) <= 0, 1); 65947280Ssklower } 66047280Ssklower } 66147280Ssklower 66247280Ssklower void 66347280Ssklower tp0_openflow(tpcb) 66447280Ssklower register struct tp_pcb *tpcb; 66547280Ssklower { 66647280Ssklower register struct isopcb *isop = (struct isopcb *)tpcb->tp_npcb; 66747280Ssklower if (tpcb->tp_netservice != ISO_CONS) 66847280Ssklower printf("tp0_openflow: tp running over something wierd\n"); 66947280Ssklower else { 67047280Ssklower register struct pklcd *lcp = (struct pklcd *)isop->isop_chan; 67147280Ssklower if (lcp->lcd_rxrnr_condition) 67247280Ssklower pk_flowcontrol(lcp, 0, 0); 67347280Ssklower } 67447280Ssklower } 67547280Ssklower #ifndef TPCONS 67647280Ssklower static 67747280Ssklower pk_flowcontrol() {} 67847280Ssklower #endif 67947280Ssklower 68036414Ssklower #ifdef TP_PERF_MEAS 68136414Ssklower /* 68236414Ssklower * CALLED FROM: 68336414Ssklower * tp_ctloutput() when the user sets TPOPT_PERF_MEAS on 68436414Ssklower * and tp_newsocket() when a new connection is made from 68536414Ssklower * a listening socket with tp_perf_on == true. 68636414Ssklower * FUNCTION and ARGUMENTS: 68736414Ssklower * (tpcb) is the usual; this procedure gets a clear cluster mbuf for 68836414Ssklower * a tp_pmeas structure, and makes tpcb->tp_p_meas point to it. 68936414Ssklower * RETURN VALUE: 69036414Ssklower * ENOBUFS if it cannot get a cluster mbuf. 69136414Ssklower */ 69236414Ssklower 69336414Ssklower int 69436414Ssklower tp_setup_perf(tpcb) 69536414Ssklower register struct tp_pcb *tpcb; 69636414Ssklower { 69736414Ssklower register struct mbuf *q; 69836414Ssklower 69937469Ssklower if( tpcb->tp_p_meas == 0 ) { 70037469Ssklower MGET(q, M_WAITOK, MT_PCB); 70136414Ssklower if (q == 0) 70236414Ssklower return ENOBUFS; 70337469Ssklower MCLGET(q, M_WAITOK); 70437469Ssklower if ((q->m_flags & M_EXT) == 0) { 70537469Ssklower (void) m_free(q); 70636414Ssklower return ENOBUFS; 70736414Ssklower } 70837469Ssklower q->m_len = sizeof (struct tp_pmeas); 70937469Ssklower tpcb->tp_p_mbuf = q; 71037469Ssklower tpcb->tp_p_meas = mtod(q, struct tp_pmeas *); 71137469Ssklower bzero( (caddr_t)tpcb->tp_p_meas, sizeof (struct tp_pmeas) ); 71237469Ssklower IFDEBUG(D_PERF_MEAS) 71337469Ssklower printf( 71437469Ssklower "tpcb 0x%x so 0x%x ref 0x%x tp_p_meas 0x%x tp_perf_on 0x%x\n", 71537469Ssklower tpcb, tpcb->tp_sock, tpcb->tp_lref, 71637469Ssklower tpcb->tp_p_meas, tpcb->tp_perf_on); 71737469Ssklower ENDDEBUG 71837469Ssklower tpcb->tp_perf_on = 1; 71936414Ssklower } 72036414Ssklower return 0; 72136414Ssklower } 72236414Ssklower #endif TP_PERF_MEAS 72336414Ssklower 72436414Ssklower #ifdef ARGO_DEBUG 72536414Ssklower dump_addr (addr) 72636414Ssklower register struct sockaddr *addr; 72736414Ssklower { 72836414Ssklower switch( addr->sa_family ) { 72936414Ssklower case AF_INET: 73037469Ssklower dump_inaddr((struct sockaddr_in *)addr); 73136414Ssklower break; 73237469Ssklower #ifdef ISO 73336414Ssklower case AF_ISO: 73437469Ssklower dump_isoaddr((struct sockaddr_iso *)addr); 73536414Ssklower break; 73637469Ssklower #endif ISO 73736414Ssklower default: 73836414Ssklower printf("BAD AF: 0x%x\n", addr->sa_family); 73936414Ssklower break; 74036414Ssklower } 74136414Ssklower } 74236414Ssklower 74337469Ssklower #define MAX_COLUMNS 8 74437469Ssklower /* 74537469Ssklower * Dump the buffer to the screen in a readable format. Format is: 74637469Ssklower * 74737469Ssklower * hex/dec where hex is the hex format, dec is the decimal format. 74837469Ssklower * columns of hex/dec numbers will be printed, followed by the 74937469Ssklower * character representations (if printable). 75037469Ssklower */ 75137469Ssklower Dump_buf(buf, len) 75237469Ssklower caddr_t buf; 75337469Ssklower int len; 75437469Ssklower { 75537469Ssklower int i,j; 75650236Ssklower #define Buf ((u_char *)buf) 75737469Ssklower printf("Dump buf 0x%x len 0x%x\n", buf, len); 75837469Ssklower for (i = 0; i < len; i += MAX_COLUMNS) { 75937469Ssklower printf("+%d:\t", i); 76037469Ssklower for (j = 0; j < MAX_COLUMNS; j++) { 76137469Ssklower if (i + j < len) { 76250236Ssklower printf("%x/%d\t", Buf[i+j], Buf[i+j]); 76337469Ssklower } else { 76437469Ssklower printf(" "); 76537469Ssklower } 76637469Ssklower } 76737469Ssklower 76837469Ssklower for (j = 0; j < MAX_COLUMNS; j++) { 76937469Ssklower if (i + j < len) { 77050236Ssklower if (((Buf[i+j]) > 31) && ((Buf[i+j]) < 128)) 77150236Ssklower printf("%c", Buf[i+j]); 77237469Ssklower else 77337469Ssklower printf("."); 77437469Ssklower } 77537469Ssklower } 77637469Ssklower printf("\n"); 77737469Ssklower } 77837469Ssklower } 77937469Ssklower 78037469Ssklower 78136414Ssklower #endif ARGO_DEBUG 78236414Ssklower 783