149268Sbostic /*- 249268Sbostic * Copyright (c) 1991 The Regents of the University of California. 349268Sbostic * All rights reserved. 449268Sbostic * 549268Sbostic * %sccs.include.redist.c% 649268Sbostic * 7*50648Ssklower * @(#)tp_subr2.c 7.12 (Berkeley) 07/29/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" 83*50648Ssklower #include "../net/if_types.h" 8445900Ssklower #ifdef TRUE 8545900Ssklower #undef FALSE 8645900Ssklower #undef TRUE 8745900Ssklower #endif 8845900Ssklower #include "../netccitt/x25.h" 8945900Ssklower #include "../netccitt/pk.h" 9045900Ssklower #include "../netccitt/pk_var.h" 9145900Ssklower 9236414Ssklower /* 9336414Ssklower * NAME: tp_local_credit() 9436414Ssklower * 9536414Ssklower * CALLED FROM: 9636414Ssklower * tp_emit(), tp_usrreq() 9736414Ssklower * 9836414Ssklower * FUNCTION and ARGUMENTS: 9936414Ssklower * Computes the local credit and stashes it in tpcb->tp_lcredit. 10036414Ssklower * It's a macro in the production system rather than a procdure. 10136414Ssklower * 10236414Ssklower * RETURNS: 10336414Ssklower * 10436414Ssklower * SIDE EFFECTS: 10536414Ssklower * 10636414Ssklower * NOTES: 10736414Ssklower * This doesn't actually get called in a production system - 10836414Ssklower * the macro gets expanded instead in place of calls to this proc. 10936414Ssklower * But for debugging, we call this and that allows us to add 11036414Ssklower * debugging messages easily here. 11136414Ssklower */ 11236414Ssklower void 11336414Ssklower tp_local_credit(tpcb) 11436414Ssklower struct tp_pcb *tpcb; 11536414Ssklower { 11636414Ssklower LOCAL_CREDIT(tpcb); 11736414Ssklower IFDEBUG(D_CREDIT) 11836414Ssklower printf("ref 0x%x lcdt 0x%x l_tpdusize 0x%x decbit 0x%x\n", 11936414Ssklower tpcb->tp_refp - tp_ref, 12036414Ssklower tpcb->tp_lcredit, 12136414Ssklower tpcb->tp_l_tpdusize, 12236414Ssklower tpcb->tp_decbit, 12336414Ssklower tpcb->tp_cong_win 12436414Ssklower ); 12536414Ssklower ENDDEBUG 12636414Ssklower IFTRACE(D_CREDIT) 12736414Ssklower tptraceTPCB(TPPTmisc, 12836414Ssklower "lcdt tpdusz \n", 12936414Ssklower tpcb->tp_lcredit, tpcb->tp_l_tpdusize, 0, 0); 13036414Ssklower ENDTRACE 13136414Ssklower } 13236414Ssklower 13336414Ssklower /* 13436414Ssklower * NAME: tp_protocol_error() 13536414Ssklower * 13636414Ssklower * CALLED FROM: 13736414Ssklower * tp_driver(), when it doesn't know what to do with 13836414Ssklower * a combo of event, state, predicate 13936414Ssklower * 14036414Ssklower * FUNCTION and ARGUMENTS: 14136414Ssklower * print error mesg 14236414Ssklower * 14336414Ssklower * RETURN VALUE: 14436414Ssklower * EIO - always 14536414Ssklower * 14636414Ssklower * SIDE EFFECTS: 14736414Ssklower * 14836414Ssklower * NOTES: 14936414Ssklower */ 15036414Ssklower int 15136414Ssklower tp_protocol_error(e,tpcb) 15236414Ssklower struct tp_event *e; 15336414Ssklower struct tp_pcb *tpcb; 15436414Ssklower { 15536414Ssklower printf("TP PROTOCOL ERROR! tpcb 0x%x event 0x%x, state 0x%x\n", 15636414Ssklower tpcb, e->ev_number, tpcb->tp_state); 15736414Ssklower IFTRACE(D_DRIVER) 15836414Ssklower tptraceTPCB(TPPTmisc, "PROTOCOL ERROR tpcb event state", 15936414Ssklower tpcb, e->ev_number, tpcb->tp_state, 0 ); 16036414Ssklower ENDTRACE 16136414Ssklower return EIO; /* for lack of anything better */ 16236414Ssklower } 16336414Ssklower 16436414Ssklower 16536414Ssklower /* Not used at the moment */ 16636414Ssklower ProtoHook 16736414Ssklower tp_drain() 16836414Ssklower { 16936414Ssklower return 0; 17036414Ssklower } 17136414Ssklower 17236414Ssklower 17336414Ssklower /* 17436414Ssklower * NAME: tp_indicate() 17536414Ssklower * 17636414Ssklower * CALLED FROM: 17736414Ssklower * tp.trans when XPD arrive, when a connection is being disconnected by 17836414Ssklower * the arrival of a DR or ER, and when a connection times out. 17936414Ssklower * 18036414Ssklower * FUNCTION and ARGUMENTS: 18136414Ssklower * (ind) is the type of indication : T_DISCONNECT, T_XPD 18236414Ssklower * (error) is an E* value that will be put in the socket structure 18336414Ssklower * to be passed along to the user later. 18436414Ssklower * Gives a SIGURG to the user process or group indicated by the socket 18536414Ssklower * attached to the tpcb. 18636414Ssklower * 18736414Ssklower * RETURNS: Rien 18836414Ssklower * 18936414Ssklower * SIDE EFFECTS: 19036414Ssklower * 19136414Ssklower * NOTES: 19236414Ssklower */ 19336414Ssklower void 19436414Ssklower tp_indicate(ind, tpcb, error) 19536414Ssklower int ind; 19636414Ssklower u_short error; 19736414Ssklower register struct tp_pcb *tpcb; 19836414Ssklower { 19936414Ssklower register struct socket *so = tpcb->tp_sock; 20036414Ssklower IFTRACE(D_INDICATION) 20139197Ssklower tptraceTPCB(TPPTindicate, ind, *(u_short *)(tpcb->tp_lsuffix), 20239197Ssklower *(u_short *)(tpcb->tp_fsuffix), error,so->so_pgid); 20336414Ssklower ENDTRACE 20436414Ssklower IFDEBUG(D_INDICATION) 20537469Ssklower char *ls, *fs; 20636414Ssklower ls = tpcb->tp_lsuffix, 20736414Ssklower fs = tpcb->tp_fsuffix, 20836414Ssklower 20936414Ssklower printf( 21037469Ssklower "indicate 0x%x lsuf 0x%02x%02x fsuf 0x%02x%02x err 0x%x noind 0x%x ref 0x%x\n", 21136414Ssklower ind, 21236414Ssklower *ls, *(ls+1), *fs, *(fs+1), 21337469Ssklower error, /*so->so_pgrp,*/ 21436414Ssklower tpcb->tp_no_disc_indications, 21536414Ssklower tpcb->tp_lref); 21636414Ssklower ENDDEBUG 21736414Ssklower 21848744Ssklower if (ind == ER_TPDU) { 21948744Ssklower register struct mbuf *m; 22048744Ssklower struct tp_disc_reason x; 22148744Ssklower 22248744Ssklower if ((so->so_state & SS_CANTRCVMORE) == 0 && 22348744Ssklower (m = m_get(M_DONTWAIT, MT_OOBDATA)) != 0) { 22448744Ssklower 22548744Ssklower x.dr_hdr.cmsg_len = m->m_len = sizeof(x); 22648744Ssklower x.dr_hdr.cmsg_level = SOL_TRANSPORT; 22748744Ssklower x.dr_hdr.cmsg_type= TPOPT_DISC_REASON; 22848744Ssklower x.dr_reason = error; 22948744Ssklower *mtod(m, struct tp_disc_reason *) = x; 23048744Ssklower sbappendrecord(&tpcb->tp_Xrcv, m); 23148744Ssklower error = 0; 23248744Ssklower } else 23348744Ssklower error = ECONNRESET; 23448744Ssklower } 23536414Ssklower so->so_error = error; 23636414Ssklower 23736414Ssklower if (ind == T_DISCONNECT) { 23848744Ssklower so->so_error = ENOTCONN; 23936414Ssklower if ( tpcb->tp_no_disc_indications ) 24036414Ssklower return; 24136414Ssklower } 24236414Ssklower IFTRACE(D_INDICATION) 24336414Ssklower tptraceTPCB(TPPTmisc, "doing sohasoutofband(so)", so,0,0,0); 24436414Ssklower ENDTRACE 24536414Ssklower sohasoutofband(so); 24636414Ssklower } 24736414Ssklower 24836414Ssklower /* 24936414Ssklower * NAME : tp_getoptions() 25036414Ssklower * 25136414Ssklower * CALLED FROM: 25236414Ssklower * tp.trans whenever we go into OPEN state 25336414Ssklower * 25436414Ssklower * FUNCTION and ARGUMENTS: 25536414Ssklower * sets the proper flags and values in the tpcb, to control 25636414Ssklower * the appropriate actions for the given class, options, 25736414Ssklower * sequence space, etc, etc. 25836414Ssklower * 25936414Ssklower * RETURNS: Nada 26036414Ssklower * 26136414Ssklower * SIDE EFFECTS: 26236414Ssklower * 26336414Ssklower * NOTES: 26436414Ssklower */ 26536414Ssklower void 26636414Ssklower tp_getoptions(tpcb) 26736414Ssklower struct tp_pcb *tpcb; 26836414Ssklower { 26936414Ssklower tpcb->tp_seqmask = 27036414Ssklower tpcb->tp_xtd_format ? TP_XTD_FMT_MASK : TP_NML_FMT_MASK ; 27136414Ssklower tpcb->tp_seqbit = 27236414Ssklower tpcb->tp_xtd_format ? TP_XTD_FMT_BIT : TP_NML_FMT_BIT ; 27336414Ssklower tpcb->tp_seqhalf = tpcb->tp_seqbit >> 1; 27436414Ssklower tpcb->tp_dt_ticks = 27536414Ssklower MAX(tpcb->tp_dt_ticks, (tpcb->tp_peer_acktime + 2)); 27636414Ssklower 27736414Ssklower } 27836414Ssklower 27936414Ssklower /* 28036414Ssklower * NAME: tp_recycle_tsuffix() 28136414Ssklower * 28236414Ssklower * CALLED FROM: 28336414Ssklower * Called when a ref is frozen. 28436414Ssklower * 28536414Ssklower * FUNCTION and ARGUMENTS: 28636414Ssklower * allows the suffix to be reused. 28736414Ssklower * 28836414Ssklower * RETURNS: zilch 28936414Ssklower * 29036414Ssklower * SIDE EFFECTS: 29136414Ssklower * 29236414Ssklower * NOTES: 29336414Ssklower */ 29436414Ssklower void 29536414Ssklower tp_recycle_tsuffix(tpcb) 29636414Ssklower struct tp_pcb *tpcb; 29736414Ssklower { 29837469Ssklower bzero((caddr_t)tpcb->tp_lsuffix, sizeof( tpcb->tp_lsuffix)); 29937469Ssklower bzero((caddr_t)tpcb->tp_fsuffix, sizeof( tpcb->tp_fsuffix)); 30036414Ssklower tpcb->tp_fsuffixlen = tpcb->tp_lsuffixlen = 0; 30136414Ssklower 30236414Ssklower (tpcb->tp_nlproto->nlp_recycle_suffix)(tpcb->tp_npcb); 30336414Ssklower } 30436414Ssklower 30536414Ssklower /* 30636414Ssklower * NAME: tp_quench() 30736414Ssklower * 30836414Ssklower * CALLED FROM: 30936414Ssklower * tp{af}_quench() when ICMP source quench or similar thing arrives. 31036414Ssklower * 31136414Ssklower * FUNCTION and ARGUMENTS: 31236414Ssklower * Drop the congestion window back to 1. 31336414Ssklower * Congestion window scheme: 31436414Ssklower * Initial value is 1. ("slow start" as Nagle, et. al. call it) 31536414Ssklower * For each good ack that arrives, the congestion window is increased 31636414Ssklower * by 1 (up to max size of logical infinity, which is to say, 31736414Ssklower * it doesn't wrap around). 31836414Ssklower * Source quench causes it to drop back to 1. 31936414Ssklower * tp_send() uses the smaller of (regular window, congestion window). 32036414Ssklower * One retransmission strategy option is to have any retransmission 32136414Ssklower * cause reset the congestion window back to 1. 32236414Ssklower * 32336414Ssklower * (cmd) is either PRC_QUENCH: source quench, or 32436414Ssklower * PRC_QUENCH2: dest. quench (dec bit) 32536414Ssklower * 32636414Ssklower * RETURNS: 32736414Ssklower * 32836414Ssklower * SIDE EFFECTS: 32936414Ssklower * 33036414Ssklower * NOTES: 33136414Ssklower */ 33236414Ssklower void 33336414Ssklower tp_quench( tpcb, cmd ) 33436414Ssklower struct tp_pcb *tpcb; 33536414Ssklower int cmd; 33636414Ssklower { 33736414Ssklower IFDEBUG(D_QUENCH) 33836414Ssklower printf("tp_quench tpcb 0x%x ref 0x%x sufx 0x%x\n", 33939197Ssklower tpcb, tpcb->tp_lref, *(u_short *)(tpcb->tp_lsuffix)); 34036414Ssklower printf("cong_win 0x%x decbit 0x%x \n", 34136414Ssklower tpcb->tp_cong_win, tpcb->tp_decbit); 34236414Ssklower ENDDEBUG 34336414Ssklower switch(cmd) { 34436414Ssklower case PRC_QUENCH: 34536414Ssklower tpcb->tp_cong_win = 1; 34636414Ssklower IncStat(ts_quench); 34736414Ssklower break; 34836414Ssklower case PRC_QUENCH2: 34936414Ssklower tpcb->tp_cong_win = 1; /* might as well quench source also */ 35036414Ssklower tpcb->tp_decbit = TP_DECBIT_CLEAR_COUNT; 35136414Ssklower IncStat(ts_rcvdecbit); 35236414Ssklower break; 35336414Ssklower } 35436414Ssklower } 35536414Ssklower 35636414Ssklower 35736414Ssklower /* 35836414Ssklower * NAME: tp_netcmd() 35936414Ssklower * 36036414Ssklower * CALLED FROM: 36136414Ssklower * 36236414Ssklower * FUNCTION and ARGUMENTS: 36336414Ssklower * 36436414Ssklower * RETURNS: 36536414Ssklower * 36636414Ssklower * SIDE EFFECTS: 36736414Ssklower * 36836414Ssklower * NOTES: 36936414Ssklower */ 37036414Ssklower tp_netcmd( tpcb, cmd ) 37136414Ssklower struct tp_pcb *tpcb; 37236414Ssklower int cmd; 37336414Ssklower { 37445900Ssklower #ifdef TPCONS 37545900Ssklower struct isopcb *isop; 37645900Ssklower struct pklcd *lcp; 37745900Ssklower 37845900Ssklower if (tpcb->tp_netservice != ISO_CONS) 37945900Ssklower return; 38045900Ssklower isop = (struct isopcb *)tpcb->tp_npcb; 38145900Ssklower lcp = (struct pklcd *)isop->isop_chan; 38236414Ssklower switch (cmd) { 38336414Ssklower 38436414Ssklower case CONN_CLOSE: 38536414Ssklower case CONN_REFUSE: 386*50648Ssklower if (isop->isop_refcnt == 1) { 387*50648Ssklower /* This is really superfluous, since it would happen 388*50648Ssklower anyway in iso_pcbdetach, although it is a courtesy 389*50648Ssklower to free up the x.25 channel before the refwait timer 390*50648Ssklower expires. */ 391*50648Ssklower lcp->lcd_upper = 0; 392*50648Ssklower lcp->lcd_upnext = 0; 39345900Ssklower pk_disconnect(lcp); 394*50648Ssklower isop->isop_chan = 0; 395*50648Ssklower isop->isop_refcnt = 0; 396*50648Ssklower } 39736414Ssklower break; 39836414Ssklower 39936414Ssklower default: 40036414Ssklower printf("tp_netcmd(0x%x, 0x%x) NOT IMPLEMENTED\n", tpcb, cmd); 40136414Ssklower break; 40236414Ssklower } 40345900Ssklower #else TPCONS 40436414Ssklower printf("tp_netcmd(): X25 NOT CONFIGURED!!\n"); 40545900Ssklower #endif 40636414Ssklower } 40736414Ssklower /* 40836414Ssklower * CALLED FROM: 40936414Ssklower * tp_ctloutput() and tp_emit() 41036414Ssklower * FUNCTION and ARGUMENTS: 41136414Ssklower * Convert a class mask to the highest numeric value it represents. 41236414Ssklower */ 41336414Ssklower 41436414Ssklower int 41536414Ssklower tp_mask_to_num(x) 41636414Ssklower u_char x; 41736414Ssklower { 41836414Ssklower register int j; 41936414Ssklower 42036414Ssklower for(j = 4; j>=0 ;j--) { 42136414Ssklower if(x & (1<<j)) 42236414Ssklower break; 42336414Ssklower } 42436414Ssklower ASSERT( (j == 4) || (j == 0) ); /* for now */ 42536414Ssklower if( (j != 4) && (j != 0) ) { 42636414Ssklower printf("ASSERTION ERROR: tp_mask_to_num: x 0x%x j %d\n", 42736414Ssklower x, j); 42836414Ssklower } 42936414Ssklower IFTRACE(D_TPINPUT) 43036414Ssklower tptrace(TPPTmisc, "tp_mask_to_num(x) returns j", x, j, 0, 0); 43136414Ssklower ENDTRACE 43236414Ssklower IFDEBUG(D_TPINPUT) 43336414Ssklower printf("tp_mask_to_num(0x%x) returns 0x%x\n", x, j); 43436414Ssklower ENDDEBUG 43536414Ssklower return j; 43636414Ssklower } 43736414Ssklower 43836414Ssklower static 43936414Ssklower copyQOSparms(src, dst) 44036414Ssklower struct tp_conn_param *src, *dst; 44136414Ssklower { 44236414Ssklower /* copy all but the bits stuff at the end */ 44336414Ssklower #define COPYSIZE (12 * sizeof(short)) 44436414Ssklower 44537469Ssklower bcopy((caddr_t)src, (caddr_t)dst, COPYSIZE); 44636414Ssklower dst->p_tpdusize = src->p_tpdusize; 44736414Ssklower dst->p_ack_strat = src->p_ack_strat; 44836414Ssklower dst->p_rx_strat = src->p_rx_strat; 44936414Ssklower #undef COPYSIZE 45036414Ssklower } 45136414Ssklower 45236414Ssklower /* 45336414Ssklower * CALLED FROM: 45436414Ssklower * tp_usrreq on PRU_CONNECT and tp_input on receipt of CR 45536414Ssklower * 45636414Ssklower * FUNCTION and ARGUMENTS: 45736414Ssklower * route directly to x.25 if the address is type 37 - GROT. 45836414Ssklower * furthermore, let TP0 handle only type-37 addresses 45936414Ssklower * 46036414Ssklower * Since this assumes that its address argument is in a mbuf, the 46136414Ssklower * parameter was changed to reflect this assumtion. This also 46236414Ssklower * implies that an mbuf must be allocated when this is 46336414Ssklower * called from tp_input 46436414Ssklower * 46536414Ssklower * RETURNS: 46636414Ssklower * errno value : 46736414Ssklower * EAFNOSUPPORT if can't find an nl_protosw for x.25 (really could panic) 46836414Ssklower * ECONNREFUSED if trying to run TP0 with non-type 37 address 46936414Ssklower * possibly other E* returned from cons_netcmd() 47036414Ssklower * NOTE: 47136414Ssklower * Would like to eliminate as much of this as possible -- 47236414Ssklower * only one set of defaults (let the user set the parms according 47336414Ssklower * to parameters provided in the directory service). 47436414Ssklower * Left here for now 'cause we don't yet have a clean way to handle 47536414Ssklower * it on the passive end. 47636414Ssklower */ 47736414Ssklower int 47836414Ssklower tp_route_to( m, tpcb, channel) 47936414Ssklower struct mbuf *m; 48036414Ssklower register struct tp_pcb *tpcb; 48145900Ssklower caddr_t channel; 48236414Ssklower { 48336414Ssklower register struct sockaddr_iso *siso; /* NOTE: this may be a sockaddr_in */ 48436414Ssklower extern struct tp_conn_param tp_conn_param[]; 485*50648Ssklower int error = 0, save_netservice = tpcb->tp_netservice; 486*50648Ssklower register struct rtentry *rt = 0; 48736414Ssklower 48836414Ssklower siso = mtod(m, struct sockaddr_iso *); 48936414Ssklower IFTRACE(D_CONN) 49036414Ssklower tptraceTPCB(TPPTmisc, 49136414Ssklower "route_to: so afi netservice class", 49237469Ssklower tpcb->tp_sock, siso->siso_addr.isoa_genaddr[0], tpcb->tp_netservice, 49336414Ssklower tpcb->tp_class); 49436414Ssklower ENDTRACE 49536414Ssklower IFDEBUG(D_CONN) 49636414Ssklower printf("tp_route_to( m x%x, channel 0x%x, tpcb 0x%x netserv 0x%x)\n", 49736414Ssklower m, channel, tpcb, tpcb->tp_netservice); 49836414Ssklower printf("m->mlen x%x, m->m_data:\n", m->m_len); 49936414Ssklower dump_buf(mtod(m, caddr_t), m->m_len); 50036414Ssklower ENDDEBUG 501*50648Ssklower if (channel) { 50245900Ssklower #ifdef TPCONS 503*50648Ssklower struct pklcd *lcp = (struct pklcd *)channel; 50445900Ssklower struct isopcb *isop = (struct isopcb *)lcp->lcd_upnext, 50550435Ssklower *isop_new = (struct isopcb *)tpcb->tp_npcb; 506*50648Ssklower /* The next 2 lines believe that you haven't 507*50648Ssklower set any network level options or done a pcbconnect 508*50648Ssklower and XXXXXXX'edly apply to both inpcb's and isopcb's */ 50945900Ssklower remque(isop_new); 51045900Ssklower free(isop_new, M_PCB); 51150435Ssklower tpcb->tp_npcb = (caddr_t)isop; 512*50648Ssklower tpcb->tp_netservice = ISO_CONS; 513*50648Ssklower tpcb->tp_nlproto = nl_protosw + ISO_CONS; 514*50648Ssklower isop->isop_socket = tpcb->tp_sock; 515*50648Ssklower if (isop->isop_refcnt == 0) 51645900Ssklower iso_putsufx(isop, tpcb->tp_lsuffix, tpcb->tp_lsuffixlen, TP_LOCAL); 517*50648Ssklower else 518*50648Ssklower /* there are already connections sharing this */; 51945900Ssklower isop->isop_refcnt++; 52045900Ssklower #endif 521*50648Ssklower } else { 522*50648Ssklower switch (siso->siso_family) { 523*50648Ssklower default: 524*50648Ssklower error = EAFNOSUPPORT; 525*50648Ssklower goto done; 526*50648Ssklower #ifdef ISO 527*50648Ssklower case AF_ISO: 528*50648Ssklower tpcb->tp_netservice = ISO_CLNS; 529*50648Ssklower if (rt = rtalloc1((struct sockaddr *)siso, 0)) { 530*50648Ssklower rt->rt_refcnt--; 531*50648Ssklower if (rt->rt_flags & RTF_PROTO1) 532*50648Ssklower tpcb->tp_netservice = ISO_CONS; 533*50648Ssklower } 534*50648Ssklower break; 535*50648Ssklower #endif 536*50648Ssklower #ifdef INET 537*50648Ssklower case AF_INET: 538*50648Ssklower tpcb->tp_netservice = IN_CLNS; 539*50648Ssklower } 540*50648Ssklower #endif 541*50648Ssklower if (tpcb->tp_nlproto->nlp_afamily != siso->siso_family) { 542*50648Ssklower IFDEBUG(D_CONN) 543*50648Ssklower printf("tp_route_to( CHANGING nlproto old 0x%x new 0x%x)\n", 544*50648Ssklower save_netservice, tpcb->tp_netservice); 545*50648Ssklower ENDDEBUG 546*50648Ssklower if (error = tp_set_npcb(tpcb)) 547*50648Ssklower goto done; 548*50648Ssklower } 549*50648Ssklower IFDEBUG(D_CONN) 550*50648Ssklower printf("tp_route_to calling nlp_pcbconn, netserv %d\n", 551*50648Ssklower tpcb->tp_netservice); 552*50648Ssklower ENDDEBUG 553*50648Ssklower tpcb->tp_nlproto = nl_protosw + tpcb->tp_netservice; 55450435Ssklower error = (tpcb->tp_nlproto->nlp_pcbconn)(tpcb->tp_npcb, m); 555*50648Ssklower } 55637469Ssklower if( error ) 55737469Ssklower goto done; 55837469Ssklower 55936414Ssklower { 56036414Ssklower switch(tpcb->tp_netservice) { 56136414Ssklower case ISO_COSNS: 56236414Ssklower case ISO_CLNS: 56336414Ssklower /* This is a kludge but seems necessary so the passive end 56436414Ssklower * can get long enough timers. sigh. 56537469Ssklower if( siso->siso_addr.osinet_idi[1] == (u_char)IDI_OSINET ) 56636414Ssklower */ 567*50648Ssklower if (rt && rt->rt_ifp && rt->rt_ifp->if_type == IFT_X25) { 56836414Ssklower if( tpcb->tp_dont_change_params == 0) { 56936414Ssklower copyQOSparms( &tp_conn_param[ISO_COSNS], 57036414Ssklower &tpcb->_tp_param); 57136414Ssklower } 57236414Ssklower tpcb->tp_flags |= TPF_NLQOS_PDN; 57336414Ssklower } 57436414Ssklower /* drop through to IN_CLNS*/ 57536414Ssklower case IN_CLNS: 57637469Ssklower if (iso_localifa(siso)) 57737469Ssklower tpcb->tp_flags |= TPF_PEER_ON_SAMENET; 578*50648Ssklower if((tpcb->tp_class & TP_CLASS_4) == 0) { 57936414Ssklower error = EPROTOTYPE; 58036414Ssklower break; 58136414Ssklower } 58236414Ssklower tpcb->tp_class = TP_CLASS_4; /* IGNORE dont_change_parms */ 58336414Ssklower break; 58436414Ssklower 58536414Ssklower case ISO_CONS: 58645900Ssklower #ifdef TPCONS 58736414Ssklower tpcb->tp_flags |= TPF_NLQOS_PDN; 58836414Ssklower if( tpcb->tp_dont_change_params == 0 ) { 58936414Ssklower copyQOSparms( &tp_conn_param[ISO_CONS], 59036414Ssklower &tpcb->_tp_param); 59136414Ssklower } 59236414Ssklower /* 59336414Ssklower * for use over x.25 really need a small receive window, 59436414Ssklower * need to start slowly, need small max negotiable tpdu size, 59536414Ssklower * and need to use the congestion window to the max 59636414Ssklower * IGNORES tp_dont_change_params for these! 59736414Ssklower */ 59836414Ssklower if( tpcb->tp_sock->so_snd.sb_hiwat > 512 ) { 59936414Ssklower (void) soreserve(tpcb->tp_sock, 512, 512 );/* GAG */ 60036414Ssklower } 60136414Ssklower tpcb->tp_rx_strat = TPRX_USE_CW; 60236414Ssklower 60336414Ssklower /* class 4 doesn't need to open a vc now - may use one already 60436414Ssklower * opened or may open one only when it sends a pkt. 60536414Ssklower */ 60645900Ssklower #else TPCONS 60736414Ssklower error = ECONNREFUSED; 60845900Ssklower #endif TPCONS 60936414Ssklower break; 61036414Ssklower default: 61136414Ssklower error = EPROTOTYPE; 61236414Ssklower } 61336414Ssklower 61436414Ssklower } 61545900Ssklower if (error) { 61636414Ssklower tp_netcmd( tpcb, CONN_CLOSE); 61736414Ssklower goto done; 61836414Ssklower } 61936414Ssklower { /* start with the global rtt, rtv stats */ 62036414Ssklower register int i = 62136414Ssklower (int) tpcb->tp_flags & (TPF_PEER_ON_SAMENET | TPF_NLQOS_PDN); 62236414Ssklower 62336414Ssklower tpcb->tp_rtt = tp_stat.ts_rtt[i]; 62436414Ssklower tpcb->tp_rtv = tp_stat.ts_rtv[i]; 62536414Ssklower } 62636414Ssklower done: 62736414Ssklower IFDEBUG(D_CONN) 62836414Ssklower printf("tp_route_to returns 0x%x\n", error); 62936414Ssklower ENDDEBUG 63036414Ssklower IFTRACE(D_CONN) 63136414Ssklower tptraceTPCB(TPPTmisc, "route_to: returns: error netserv class", error, 63236414Ssklower tpcb->tp_netservice, tpcb->tp_class, 0); 63336414Ssklower ENDTRACE 63436414Ssklower return error; 63536414Ssklower } 63636414Ssklower 63747280Ssklower 63847280Ssklower /* class zero version */ 63947280Ssklower void 64047280Ssklower tp0_stash( tpcb, e ) 64147280Ssklower register struct tp_pcb *tpcb; 64247280Ssklower register struct tp_event *e; 64347280Ssklower { 64447280Ssklower #ifndef lint 64547280Ssklower #define E e->ATTR(DT_TPDU) 64647280Ssklower #else lint 64747280Ssklower #define E e->ev_union.EV_DT_TPDU 64847280Ssklower #endif lint 64947280Ssklower 65047280Ssklower register struct sockbuf *sb = &tpcb->tp_sock->so_rcv; 65147280Ssklower register struct isopcb *isop = (struct isopcb *)tpcb->tp_npcb; 65247280Ssklower 65347280Ssklower IFPERF(tpcb) 65447280Ssklower PStat(tpcb, Nb_from_ll) += E.e_datalen; 65547280Ssklower tpmeas(tpcb->tp_lref, TPtime_from_ll, &e->e_time, 65647280Ssklower E.e_seq, PStat(tpcb, Nb_from_ll), E.e_datalen); 65747280Ssklower ENDPERF 65847280Ssklower 65947280Ssklower IFDEBUG(D_STASH) 66047280Ssklower printf("stash EQ: seq 0x%x datalen 0x%x eot 0x%x", 66147280Ssklower E.e_seq, E.e_datalen, E.e_eot); 66247280Ssklower ENDDEBUG 66347280Ssklower 66447280Ssklower IFTRACE(D_STASH) 66547280Ssklower tptraceTPCB(TPPTmisc, "stash EQ: seq len eot", 66647280Ssklower E.e_seq, E.e_datalen, E.e_eot, 0); 66747280Ssklower ENDTRACE 66847280Ssklower 66947280Ssklower if ( E.e_eot ) { 67047280Ssklower register struct mbuf *n = E.e_data; 67147280Ssklower n->m_flags |= M_EOR; 67247280Ssklower n->m_act = MNULL; /* set on tp_input */ 67347280Ssklower } 67447280Ssklower sbappend(sb, E.e_data); 67547280Ssklower IFDEBUG(D_STASH) 67647280Ssklower dump_mbuf(sb->sb_mb, "stash 0: so_rcv after appending"); 67747280Ssklower ENDDEBUG 67847280Ssklower if (tpcb->tp_netservice != ISO_CONS) 67947280Ssklower printf("tp0_stash: tp running over something wierd\n"); 68047280Ssklower else { 68147280Ssklower register struct pklcd *lcp = (struct pklcd *)isop->isop_chan; 68247280Ssklower pk_flowcontrol(lcp, sbspace(sb) <= 0, 1); 68347280Ssklower } 68447280Ssklower } 68547280Ssklower 68647280Ssklower void 68747280Ssklower tp0_openflow(tpcb) 68847280Ssklower register struct tp_pcb *tpcb; 68947280Ssklower { 69047280Ssklower register struct isopcb *isop = (struct isopcb *)tpcb->tp_npcb; 69147280Ssklower if (tpcb->tp_netservice != ISO_CONS) 69247280Ssklower printf("tp0_openflow: tp running over something wierd\n"); 69347280Ssklower else { 69447280Ssklower register struct pklcd *lcp = (struct pklcd *)isop->isop_chan; 69547280Ssklower if (lcp->lcd_rxrnr_condition) 69647280Ssklower pk_flowcontrol(lcp, 0, 0); 69747280Ssklower } 69847280Ssklower } 69947280Ssklower #ifndef TPCONS 70047280Ssklower static 70147280Ssklower pk_flowcontrol() {} 70247280Ssklower #endif 70347280Ssklower 70436414Ssklower #ifdef TP_PERF_MEAS 70536414Ssklower /* 70636414Ssklower * CALLED FROM: 70736414Ssklower * tp_ctloutput() when the user sets TPOPT_PERF_MEAS on 70836414Ssklower * and tp_newsocket() when a new connection is made from 70936414Ssklower * a listening socket with tp_perf_on == true. 71036414Ssklower * FUNCTION and ARGUMENTS: 71136414Ssklower * (tpcb) is the usual; this procedure gets a clear cluster mbuf for 71236414Ssklower * a tp_pmeas structure, and makes tpcb->tp_p_meas point to it. 71336414Ssklower * RETURN VALUE: 71436414Ssklower * ENOBUFS if it cannot get a cluster mbuf. 71536414Ssklower */ 71636414Ssklower 71736414Ssklower int 71836414Ssklower tp_setup_perf(tpcb) 71936414Ssklower register struct tp_pcb *tpcb; 72036414Ssklower { 72136414Ssklower register struct mbuf *q; 72236414Ssklower 72337469Ssklower if( tpcb->tp_p_meas == 0 ) { 72437469Ssklower MGET(q, M_WAITOK, MT_PCB); 72536414Ssklower if (q == 0) 72636414Ssklower return ENOBUFS; 72737469Ssklower MCLGET(q, M_WAITOK); 72837469Ssklower if ((q->m_flags & M_EXT) == 0) { 72937469Ssklower (void) m_free(q); 73036414Ssklower return ENOBUFS; 73136414Ssklower } 73237469Ssklower q->m_len = sizeof (struct tp_pmeas); 73337469Ssklower tpcb->tp_p_mbuf = q; 73437469Ssklower tpcb->tp_p_meas = mtod(q, struct tp_pmeas *); 73537469Ssklower bzero( (caddr_t)tpcb->tp_p_meas, sizeof (struct tp_pmeas) ); 73637469Ssklower IFDEBUG(D_PERF_MEAS) 73737469Ssklower printf( 73837469Ssklower "tpcb 0x%x so 0x%x ref 0x%x tp_p_meas 0x%x tp_perf_on 0x%x\n", 73937469Ssklower tpcb, tpcb->tp_sock, tpcb->tp_lref, 74037469Ssklower tpcb->tp_p_meas, tpcb->tp_perf_on); 74137469Ssklower ENDDEBUG 74237469Ssklower tpcb->tp_perf_on = 1; 74336414Ssklower } 74436414Ssklower return 0; 74536414Ssklower } 74636414Ssklower #endif TP_PERF_MEAS 74736414Ssklower 74836414Ssklower #ifdef ARGO_DEBUG 74936414Ssklower dump_addr (addr) 75036414Ssklower register struct sockaddr *addr; 75136414Ssklower { 75236414Ssklower switch( addr->sa_family ) { 75336414Ssklower case AF_INET: 75437469Ssklower dump_inaddr((struct sockaddr_in *)addr); 75536414Ssklower break; 75637469Ssklower #ifdef ISO 75736414Ssklower case AF_ISO: 75837469Ssklower dump_isoaddr((struct sockaddr_iso *)addr); 75936414Ssklower break; 76037469Ssklower #endif ISO 76136414Ssklower default: 76236414Ssklower printf("BAD AF: 0x%x\n", addr->sa_family); 76336414Ssklower break; 76436414Ssklower } 76536414Ssklower } 76636414Ssklower 76737469Ssklower #define MAX_COLUMNS 8 76837469Ssklower /* 76937469Ssklower * Dump the buffer to the screen in a readable format. Format is: 77037469Ssklower * 77137469Ssklower * hex/dec where hex is the hex format, dec is the decimal format. 77237469Ssklower * columns of hex/dec numbers will be printed, followed by the 77337469Ssklower * character representations (if printable). 77437469Ssklower */ 77537469Ssklower Dump_buf(buf, len) 77637469Ssklower caddr_t buf; 77737469Ssklower int len; 77837469Ssklower { 77937469Ssklower int i,j; 78050236Ssklower #define Buf ((u_char *)buf) 78137469Ssklower printf("Dump buf 0x%x len 0x%x\n", buf, len); 78237469Ssklower for (i = 0; i < len; i += MAX_COLUMNS) { 78337469Ssklower printf("+%d:\t", i); 78437469Ssklower for (j = 0; j < MAX_COLUMNS; j++) { 78537469Ssklower if (i + j < len) { 78650236Ssklower printf("%x/%d\t", Buf[i+j], Buf[i+j]); 78737469Ssklower } else { 78837469Ssklower printf(" "); 78937469Ssklower } 79037469Ssklower } 79137469Ssklower 79237469Ssklower for (j = 0; j < MAX_COLUMNS; j++) { 79337469Ssklower if (i + j < len) { 79450236Ssklower if (((Buf[i+j]) > 31) && ((Buf[i+j]) < 128)) 79550236Ssklower printf("%c", Buf[i+j]); 79637469Ssklower else 79737469Ssklower printf("."); 79837469Ssklower } 79937469Ssklower } 80037469Ssklower printf("\n"); 80137469Ssklower } 80237469Ssklower } 80337469Ssklower 80437469Ssklower 80536414Ssklower #endif ARGO_DEBUG 80636414Ssklower 807