1*36414Ssklower /*********************************************************** 2*36414Ssklower Copyright IBM Corporation 1987 3*36414Ssklower 4*36414Ssklower All Rights Reserved 5*36414Ssklower 6*36414Ssklower Permission to use, copy, modify, and distribute this software and its 7*36414Ssklower documentation for any purpose and without fee is hereby granted, 8*36414Ssklower provided that the above copyright notice appear in all copies and that 9*36414Ssklower both that copyright notice and this permission notice appear in 10*36414Ssklower supporting documentation, and that the name of IBM not be 11*36414Ssklower used in advertising or publicity pertaining to distribution of the 12*36414Ssklower software without specific, written prior permission. 13*36414Ssklower 14*36414Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 15*36414Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 16*36414Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 17*36414Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 18*36414Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 19*36414Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 20*36414Ssklower SOFTWARE. 21*36414Ssklower 22*36414Ssklower ******************************************************************/ 23*36414Ssklower 24*36414Ssklower /* 25*36414Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 26*36414Ssklower */ 27*36414Ssklower /* 28*36414Ssklower * ARGO TP 29*36414Ssklower * 30*36414Ssklower * $Header: tp_subr2.c,v 5.5 88/11/18 17:28:55 nhall Exp $ 31*36414Ssklower * $Source: /usr/argo/sys/netiso/RCS/tp_subr2.c,v $ 32*36414Ssklower * 33*36414Ssklower * Some auxiliary routines: 34*36414Ssklower * tp_protocol_error: required by xebec- called when a combo of state, 35*36414Ssklower * event, predicate isn't covered for by the transition file. 36*36414Ssklower * tp_indicate: gives indications(signals) to the user process 37*36414Ssklower * tp_getoptions: initializes variables that are affected by the options 38*36414Ssklower * chosen. 39*36414Ssklower */ 40*36414Ssklower 41*36414Ssklower #ifndef lint 42*36414Ssklower static char *rcsid = "$Header: tp_subr2.c,v 5.5 88/11/18 17:28:55 nhall Exp $"; 43*36414Ssklower #endif lint 44*36414Ssklower 45*36414Ssklower #include "argoxtwentyfive.h" 46*36414Ssklower 47*36414Ssklower /* this def'n is to cause the expansion of this macro in the 48*36414Ssklower * routine tp_local_credit : 49*36414Ssklower */ 50*36414Ssklower #define LOCAL_CREDIT_EXPAND 51*36414Ssklower 52*36414Ssklower #include "param.h" 53*36414Ssklower #include "mbuf.h" 54*36414Ssklower #include "socket.h" 55*36414Ssklower #include "socketvar.h" 56*36414Ssklower #include "domain.h" 57*36414Ssklower #include "protosw.h" 58*36414Ssklower #include "errno.h" 59*36414Ssklower #include "types.h" 60*36414Ssklower #include "time.h" 61*36414Ssklower #include "kernel.h" 62*36414Ssklower #undef MNULL 63*36414Ssklower #include "../netiso/tp_ip.h" 64*36414Ssklower #include "../netiso/tp_param.h" 65*36414Ssklower #include "../netiso/tp_timer.h" 66*36414Ssklower #include "../netiso/tp_stat.h" 67*36414Ssklower #include "../netiso/argo_debug.h" 68*36414Ssklower #include "../netiso/tp_tpdu.h" 69*36414Ssklower #include "../netiso/iso.h" 70*36414Ssklower #include "../netiso/iso_errno.h" 71*36414Ssklower #include "../netiso/tp_pcb.h" 72*36414Ssklower #include "../netiso/tp_seq.h" 73*36414Ssklower #include "../netiso/tp_trace.h" 74*36414Ssklower #include "../netiso/iso_pcb.h" 75*36414Ssklower #include "../netiso/tp_user.h" 76*36414Ssklower #include "../netiso/cons.h" 77*36414Ssklower 78*36414Ssklower /* 79*36414Ssklower * NAME: tp_local_credit() 80*36414Ssklower * 81*36414Ssklower * CALLED FROM: 82*36414Ssklower * tp_emit(), tp_usrreq() 83*36414Ssklower * 84*36414Ssklower * FUNCTION and ARGUMENTS: 85*36414Ssklower * Computes the local credit and stashes it in tpcb->tp_lcredit. 86*36414Ssklower * It's a macro in the production system rather than a procdure. 87*36414Ssklower * 88*36414Ssklower * RETURNS: 89*36414Ssklower * 90*36414Ssklower * SIDE EFFECTS: 91*36414Ssklower * 92*36414Ssklower * NOTES: 93*36414Ssklower * This doesn't actually get called in a production system - 94*36414Ssklower * the macro gets expanded instead in place of calls to this proc. 95*36414Ssklower * But for debugging, we call this and that allows us to add 96*36414Ssklower * debugging messages easily here. 97*36414Ssklower */ 98*36414Ssklower void 99*36414Ssklower tp_local_credit(tpcb) 100*36414Ssklower struct tp_pcb *tpcb; 101*36414Ssklower { 102*36414Ssklower LOCAL_CREDIT(tpcb); 103*36414Ssklower IFDEBUG(D_CREDIT) 104*36414Ssklower printf("ref 0x%x lcdt 0x%x l_tpdusize 0x%x decbit 0x%x\n", 105*36414Ssklower tpcb->tp_refp - tp_ref, 106*36414Ssklower tpcb->tp_lcredit, 107*36414Ssklower tpcb->tp_l_tpdusize, 108*36414Ssklower tpcb->tp_decbit, 109*36414Ssklower tpcb->tp_cong_win 110*36414Ssklower ); 111*36414Ssklower ENDDEBUG 112*36414Ssklower IFTRACE(D_CREDIT) 113*36414Ssklower tptraceTPCB(TPPTmisc, 114*36414Ssklower "lcdt tpdusz \n", 115*36414Ssklower tpcb->tp_lcredit, tpcb->tp_l_tpdusize, 0, 0); 116*36414Ssklower ENDTRACE 117*36414Ssklower } 118*36414Ssklower 119*36414Ssklower /* 120*36414Ssklower * NAME: tp_protocol_error() 121*36414Ssklower * 122*36414Ssklower * CALLED FROM: 123*36414Ssklower * tp_driver(), when it doesn't know what to do with 124*36414Ssklower * a combo of event, state, predicate 125*36414Ssklower * 126*36414Ssklower * FUNCTION and ARGUMENTS: 127*36414Ssklower * print error mesg 128*36414Ssklower * 129*36414Ssklower * RETURN VALUE: 130*36414Ssklower * EIO - always 131*36414Ssklower * 132*36414Ssklower * SIDE EFFECTS: 133*36414Ssklower * 134*36414Ssklower * NOTES: 135*36414Ssklower */ 136*36414Ssklower int 137*36414Ssklower tp_protocol_error(e,tpcb) 138*36414Ssklower struct tp_event *e; 139*36414Ssklower struct tp_pcb *tpcb; 140*36414Ssklower { 141*36414Ssklower printf("TP PROTOCOL ERROR! tpcb 0x%x event 0x%x, state 0x%x\n", 142*36414Ssklower tpcb, e->ev_number, tpcb->tp_state); 143*36414Ssklower IFTRACE(D_DRIVER) 144*36414Ssklower tptraceTPCB(TPPTmisc, "PROTOCOL ERROR tpcb event state", 145*36414Ssklower tpcb, e->ev_number, tpcb->tp_state, 0 ); 146*36414Ssklower ENDTRACE 147*36414Ssklower return EIO; /* for lack of anything better */ 148*36414Ssklower } 149*36414Ssklower 150*36414Ssklower 151*36414Ssklower /* Not used at the moment */ 152*36414Ssklower ProtoHook 153*36414Ssklower tp_drain() 154*36414Ssklower { 155*36414Ssklower return 0; 156*36414Ssklower } 157*36414Ssklower 158*36414Ssklower 159*36414Ssklower /* 160*36414Ssklower * NAME: tp_indicate() 161*36414Ssklower * 162*36414Ssklower * CALLED FROM: 163*36414Ssklower * tp.trans when XPD arrive, when a connection is being disconnected by 164*36414Ssklower * the arrival of a DR or ER, and when a connection times out. 165*36414Ssklower * 166*36414Ssklower * FUNCTION and ARGUMENTS: 167*36414Ssklower * (ind) is the type of indication : T_DISCONNECT, T_XPD 168*36414Ssklower * (error) is an E* value that will be put in the socket structure 169*36414Ssklower * to be passed along to the user later. 170*36414Ssklower * Gives a SIGURG to the user process or group indicated by the socket 171*36414Ssklower * attached to the tpcb. 172*36414Ssklower * 173*36414Ssklower * RETURNS: Rien 174*36414Ssklower * 175*36414Ssklower * SIDE EFFECTS: 176*36414Ssklower * 177*36414Ssklower * NOTES: 178*36414Ssklower */ 179*36414Ssklower void 180*36414Ssklower tp_indicate(ind, tpcb, error) 181*36414Ssklower int ind; 182*36414Ssklower u_short error; 183*36414Ssklower register struct tp_pcb *tpcb; 184*36414Ssklower { 185*36414Ssklower register struct socket *so = tpcb->tp_sock; 186*36414Ssklower IFTRACE(D_INDICATION) 187*36414Ssklower tptraceTPCB(TPPTindicate, ind, *(int *)(tpcb->tp_lsuffix), 188*36414Ssklower *(int *)(tpcb->tp_fsuffix), error,so->so_pgrp); 189*36414Ssklower ENDTRACE 190*36414Ssklower IFDEBUG(D_INDICATION) 191*36414Ssklower u_char *ls, *fs; 192*36414Ssklower ls = tpcb->tp_lsuffix, 193*36414Ssklower fs = tpcb->tp_fsuffix, 194*36414Ssklower 195*36414Ssklower printf( 196*36414Ssklower "indicate 0x%x lsuf 0x%02x%02x fsuf 0x%02x%02x err 0x%x prgp 0x%x noind 0x%x ref 0x%x\n", 197*36414Ssklower ind, 198*36414Ssklower *ls, *(ls+1), *fs, *(fs+1), 199*36414Ssklower error,so->so_pgrp, 200*36414Ssklower tpcb->tp_no_disc_indications, 201*36414Ssklower tpcb->tp_lref); 202*36414Ssklower ENDDEBUG 203*36414Ssklower 204*36414Ssklower so->so_error = error; 205*36414Ssklower 206*36414Ssklower if (ind == T_DISCONNECT) { 207*36414Ssklower if ( tpcb->tp_no_disc_indications ) 208*36414Ssklower return; 209*36414Ssklower } 210*36414Ssklower IFTRACE(D_INDICATION) 211*36414Ssklower tptraceTPCB(TPPTmisc, "doing sohasoutofband(so)", so,0,0,0); 212*36414Ssklower ENDTRACE 213*36414Ssklower sohasoutofband(so); 214*36414Ssklower } 215*36414Ssklower 216*36414Ssklower /* 217*36414Ssklower * NAME : tp_getoptions() 218*36414Ssklower * 219*36414Ssklower * CALLED FROM: 220*36414Ssklower * tp.trans whenever we go into OPEN state 221*36414Ssklower * 222*36414Ssklower * FUNCTION and ARGUMENTS: 223*36414Ssklower * sets the proper flags and values in the tpcb, to control 224*36414Ssklower * the appropriate actions for the given class, options, 225*36414Ssklower * sequence space, etc, etc. 226*36414Ssklower * 227*36414Ssklower * RETURNS: Nada 228*36414Ssklower * 229*36414Ssklower * SIDE EFFECTS: 230*36414Ssklower * 231*36414Ssklower * NOTES: 232*36414Ssklower */ 233*36414Ssklower void 234*36414Ssklower tp_getoptions(tpcb) 235*36414Ssklower struct tp_pcb *tpcb; 236*36414Ssklower { 237*36414Ssklower tpcb->tp_seqmask = 238*36414Ssklower tpcb->tp_xtd_format ? TP_XTD_FMT_MASK : TP_NML_FMT_MASK ; 239*36414Ssklower tpcb->tp_seqbit = 240*36414Ssklower tpcb->tp_xtd_format ? TP_XTD_FMT_BIT : TP_NML_FMT_BIT ; 241*36414Ssklower tpcb->tp_seqhalf = tpcb->tp_seqbit >> 1; 242*36414Ssklower tpcb->tp_dt_ticks = 243*36414Ssklower MAX(tpcb->tp_dt_ticks, (tpcb->tp_peer_acktime + 2)); 244*36414Ssklower 245*36414Ssklower } 246*36414Ssklower 247*36414Ssklower /* 248*36414Ssklower * NAME: tp_recycle_tsuffix() 249*36414Ssklower * 250*36414Ssklower * CALLED FROM: 251*36414Ssklower * Called when a ref is frozen. 252*36414Ssklower * 253*36414Ssklower * FUNCTION and ARGUMENTS: 254*36414Ssklower * allows the suffix to be reused. 255*36414Ssklower * 256*36414Ssklower * RETURNS: zilch 257*36414Ssklower * 258*36414Ssklower * SIDE EFFECTS: 259*36414Ssklower * 260*36414Ssklower * NOTES: 261*36414Ssklower */ 262*36414Ssklower void 263*36414Ssklower tp_recycle_tsuffix(tpcb) 264*36414Ssklower struct tp_pcb *tpcb; 265*36414Ssklower { 266*36414Ssklower bzero( tpcb->tp_lsuffix, sizeof( tpcb->tp_lsuffix)); 267*36414Ssklower bzero( tpcb->tp_fsuffix, sizeof( tpcb->tp_fsuffix)); 268*36414Ssklower tpcb->tp_fsuffixlen = tpcb->tp_lsuffixlen = 0; 269*36414Ssklower 270*36414Ssklower (tpcb->tp_nlproto->nlp_recycle_suffix)(tpcb->tp_npcb); 271*36414Ssklower } 272*36414Ssklower 273*36414Ssklower /* 274*36414Ssklower * NAME: tp_quench() 275*36414Ssklower * 276*36414Ssklower * CALLED FROM: 277*36414Ssklower * tp{af}_quench() when ICMP source quench or similar thing arrives. 278*36414Ssklower * 279*36414Ssklower * FUNCTION and ARGUMENTS: 280*36414Ssklower * Drop the congestion window back to 1. 281*36414Ssklower * Congestion window scheme: 282*36414Ssklower * Initial value is 1. ("slow start" as Nagle, et. al. call it) 283*36414Ssklower * For each good ack that arrives, the congestion window is increased 284*36414Ssklower * by 1 (up to max size of logical infinity, which is to say, 285*36414Ssklower * it doesn't wrap around). 286*36414Ssklower * Source quench causes it to drop back to 1. 287*36414Ssklower * tp_send() uses the smaller of (regular window, congestion window). 288*36414Ssklower * One retransmission strategy option is to have any retransmission 289*36414Ssklower * cause reset the congestion window back to 1. 290*36414Ssklower * 291*36414Ssklower * (cmd) is either PRC_QUENCH: source quench, or 292*36414Ssklower * PRC_QUENCH2: dest. quench (dec bit) 293*36414Ssklower * 294*36414Ssklower * RETURNS: 295*36414Ssklower * 296*36414Ssklower * SIDE EFFECTS: 297*36414Ssklower * 298*36414Ssklower * NOTES: 299*36414Ssklower */ 300*36414Ssklower void 301*36414Ssklower tp_quench( tpcb, cmd ) 302*36414Ssklower struct tp_pcb *tpcb; 303*36414Ssklower int cmd; 304*36414Ssklower { 305*36414Ssklower IFDEBUG(D_QUENCH) 306*36414Ssklower printf("tp_quench tpcb 0x%x ref 0x%x sufx 0x%x\n", 307*36414Ssklower tpcb, tpcb->tp_lref, *(int *)(tpcb->tp_lsuffix)); 308*36414Ssklower printf("cong_win 0x%x decbit 0x%x \n", 309*36414Ssklower tpcb->tp_cong_win, tpcb->tp_decbit); 310*36414Ssklower ENDDEBUG 311*36414Ssklower switch(cmd) { 312*36414Ssklower case PRC_QUENCH: 313*36414Ssklower tpcb->tp_cong_win = 1; 314*36414Ssklower IncStat(ts_quench); 315*36414Ssklower break; 316*36414Ssklower case PRC_QUENCH2: 317*36414Ssklower tpcb->tp_cong_win = 1; /* might as well quench source also */ 318*36414Ssklower tpcb->tp_decbit = TP_DECBIT_CLEAR_COUNT; 319*36414Ssklower IncStat(ts_rcvdecbit); 320*36414Ssklower break; 321*36414Ssklower } 322*36414Ssklower } 323*36414Ssklower 324*36414Ssklower 325*36414Ssklower /* 326*36414Ssklower * NAME: tp_netcmd() 327*36414Ssklower * 328*36414Ssklower * CALLED FROM: 329*36414Ssklower * 330*36414Ssklower * FUNCTION and ARGUMENTS: 331*36414Ssklower * 332*36414Ssklower * RETURNS: 333*36414Ssklower * 334*36414Ssklower * SIDE EFFECTS: 335*36414Ssklower * 336*36414Ssklower * NOTES: 337*36414Ssklower */ 338*36414Ssklower tp_netcmd( tpcb, cmd ) 339*36414Ssklower struct tp_pcb *tpcb; 340*36414Ssklower int cmd; 341*36414Ssklower { 342*36414Ssklower #if NARGOXTWENTYFIVE > 0 343*36414Ssklower switch (cmd) { 344*36414Ssklower 345*36414Ssklower case CONN_CLOSE: 346*36414Ssklower case CONN_REFUSE: 347*36414Ssklower cons_netcmd( cmd, tpcb->tp_npcb, 0, tpcb->tp_class == TP_CLASS_4); 348*36414Ssklower /* TODO: can this last param be replaced by 349*36414Ssklower * tpcb->tp_netserv != ISO_CONS?) 350*36414Ssklower */ 351*36414Ssklower break; 352*36414Ssklower 353*36414Ssklower default: 354*36414Ssklower printf("tp_netcmd(0x%x, 0x%x) NOT IMPLEMENTED\n", tpcb, cmd); 355*36414Ssklower break; 356*36414Ssklower } 357*36414Ssklower #else NARGOXTWENTYFIVE 358*36414Ssklower printf("tp_netcmd(): X25 NOT CONFIGURED!!\n"); 359*36414Ssklower #endif NARGOXTWENTYFIVE > 0 360*36414Ssklower } 361*36414Ssklower /* 362*36414Ssklower * CALLED FROM: 363*36414Ssklower * tp_ctloutput() and tp_emit() 364*36414Ssklower * FUNCTION and ARGUMENTS: 365*36414Ssklower * Convert a class mask to the highest numeric value it represents. 366*36414Ssklower */ 367*36414Ssklower 368*36414Ssklower int 369*36414Ssklower tp_mask_to_num(x) 370*36414Ssklower u_char x; 371*36414Ssklower { 372*36414Ssklower register int j; 373*36414Ssklower 374*36414Ssklower for(j = 4; j>=0 ;j--) { 375*36414Ssklower if(x & (1<<j)) 376*36414Ssklower break; 377*36414Ssklower } 378*36414Ssklower ASSERT( (j == 4) || (j == 0) ); /* for now */ 379*36414Ssklower if( (j != 4) && (j != 0) ) { 380*36414Ssklower printf("ASSERTION ERROR: tp_mask_to_num: x 0x%x j %d\n", 381*36414Ssklower x, j); 382*36414Ssklower } 383*36414Ssklower IFTRACE(D_TPINPUT) 384*36414Ssklower tptrace(TPPTmisc, "tp_mask_to_num(x) returns j", x, j, 0, 0); 385*36414Ssklower ENDTRACE 386*36414Ssklower IFDEBUG(D_TPINPUT) 387*36414Ssklower printf("tp_mask_to_num(0x%x) returns 0x%x\n", x, j); 388*36414Ssklower ENDDEBUG 389*36414Ssklower return j; 390*36414Ssklower } 391*36414Ssklower 392*36414Ssklower static 393*36414Ssklower copyQOSparms(src, dst) 394*36414Ssklower struct tp_conn_param *src, *dst; 395*36414Ssklower { 396*36414Ssklower /* copy all but the bits stuff at the end */ 397*36414Ssklower #define COPYSIZE (12 * sizeof(short)) 398*36414Ssklower 399*36414Ssklower bcopy( src, dst, COPYSIZE); 400*36414Ssklower dst->p_tpdusize = src->p_tpdusize; 401*36414Ssklower dst->p_ack_strat = src->p_ack_strat; 402*36414Ssklower dst->p_rx_strat = src->p_rx_strat; 403*36414Ssklower #undef COPYSIZE 404*36414Ssklower } 405*36414Ssklower 406*36414Ssklower /* 407*36414Ssklower * CALLED FROM: 408*36414Ssklower * tp_usrreq on PRU_CONNECT and tp_input on receipt of CR 409*36414Ssklower * 410*36414Ssklower * FUNCTION and ARGUMENTS: 411*36414Ssklower * route directly to x.25 if the address is type 37 - GROT. 412*36414Ssklower * furthermore, let TP0 handle only type-37 addresses 413*36414Ssklower * 414*36414Ssklower * Since this assumes that its address argument is in a mbuf, the 415*36414Ssklower * parameter was changed to reflect this assumtion. This also 416*36414Ssklower * implies that an mbuf must be allocated when this is 417*36414Ssklower * called from tp_input 418*36414Ssklower * 419*36414Ssklower * RETURNS: 420*36414Ssklower * errno value : 421*36414Ssklower * EAFNOSUPPORT if can't find an nl_protosw for x.25 (really could panic) 422*36414Ssklower * ECONNREFUSED if trying to run TP0 with non-type 37 address 423*36414Ssklower * possibly other E* returned from cons_netcmd() 424*36414Ssklower * NOTE: 425*36414Ssklower * Would like to eliminate as much of this as possible -- 426*36414Ssklower * only one set of defaults (let the user set the parms according 427*36414Ssklower * to parameters provided in the directory service). 428*36414Ssklower * Left here for now 'cause we don't yet have a clean way to handle 429*36414Ssklower * it on the passive end. 430*36414Ssklower */ 431*36414Ssklower int 432*36414Ssklower tp_route_to( m, tpcb, channel) 433*36414Ssklower struct mbuf *m; 434*36414Ssklower register struct tp_pcb *tpcb; 435*36414Ssklower u_int channel; 436*36414Ssklower { 437*36414Ssklower register struct sockaddr_iso *siso; /* NOTE: this may be a sockaddr_in */ 438*36414Ssklower extern struct tp_conn_param tp_conn_param[]; 439*36414Ssklower int error = 0; 440*36414Ssklower int vc_to_kill = 0; /* kludge */ 441*36414Ssklower 442*36414Ssklower siso = mtod(m, struct sockaddr_iso *); 443*36414Ssklower IFTRACE(D_CONN) 444*36414Ssklower tptraceTPCB(TPPTmisc, 445*36414Ssklower "route_to: so afi netservice class", 446*36414Ssklower tpcb->tp_sock, siso->siso_addr.isoa_afi, tpcb->tp_netservice, 447*36414Ssklower tpcb->tp_class); 448*36414Ssklower ENDTRACE 449*36414Ssklower IFDEBUG(D_CONN) 450*36414Ssklower printf("tp_route_to( m x%x, channel 0x%x, tpcb 0x%x netserv 0x%x)\n", 451*36414Ssklower m, channel, tpcb, tpcb->tp_netservice); 452*36414Ssklower printf("m->mlen x%x, m->m_data:\n", m->m_len); 453*36414Ssklower dump_buf(mtod(m, caddr_t), m->m_len); 454*36414Ssklower ENDDEBUG 455*36414Ssklower if( siso->siso_family != tpcb->tp_domain ) { 456*36414Ssklower error = EAFNOSUPPORT; 457*36414Ssklower goto done; 458*36414Ssklower } 459*36414Ssklower { 460*36414Ssklower register int save_netservice = tpcb->tp_netservice; 461*36414Ssklower 462*36414Ssklower switch(tpcb->tp_netservice) { 463*36414Ssklower case ISO_COSNS: 464*36414Ssklower case ISO_CLNS: 465*36414Ssklower /* This is a kludge but seems necessary so the passive end 466*36414Ssklower * can get long enough timers. sigh. 467*36414Ssklower */ 468*36414Ssklower if( siso->siso_addr.osinet_idi[1] == (u_char)IDI_OSINET ) { 469*36414Ssklower if( tpcb->tp_dont_change_params == 0) { 470*36414Ssklower copyQOSparms( &tp_conn_param[ISO_COSNS], 471*36414Ssklower &tpcb->_tp_param); 472*36414Ssklower } 473*36414Ssklower tpcb->tp_flags |= TPF_NLQOS_PDN; 474*36414Ssklower } 475*36414Ssklower /* drop through to IN_CLNS*/ 476*36414Ssklower case IN_CLNS: 477*36414Ssklower if( (tpcb->tp_class & TP_CLASS_4)==0 ) { 478*36414Ssklower error = EPROTOTYPE; 479*36414Ssklower break; 480*36414Ssklower } 481*36414Ssklower tpcb->tp_class = TP_CLASS_4; /* IGNORE dont_change_parms */ 482*36414Ssklower break; 483*36414Ssklower 484*36414Ssklower case ISO_CONS: 485*36414Ssklower #if NARGOXTWENTYFIVE > 0 486*36414Ssklower tpcb->tp_flags |= TPF_NLQOS_PDN; 487*36414Ssklower if( tpcb->tp_dont_change_params == 0 ) { 488*36414Ssklower copyQOSparms( &tp_conn_param[ISO_CONS], 489*36414Ssklower &tpcb->_tp_param); 490*36414Ssklower } 491*36414Ssklower /* 492*36414Ssklower * for use over x.25 really need a small receive window, 493*36414Ssklower * need to start slowly, need small max negotiable tpdu size, 494*36414Ssklower * and need to use the congestion window to the max 495*36414Ssklower * IGNORES tp_dont_change_params for these! 496*36414Ssklower */ 497*36414Ssklower if( tpcb->tp_sock->so_snd.sb_hiwat > 512 ) { 498*36414Ssklower (void) soreserve(tpcb->tp_sock, 512, 512 );/* GAG */ 499*36414Ssklower } 500*36414Ssklower tpcb->tp_rx_strat = TPRX_USE_CW; 501*36414Ssklower 502*36414Ssklower if( (tpcb->tp_nlproto != &nl_protosw[ISO_CONS]) ) { 503*36414Ssklower /* if the listener was restricting us to clns, 504*36414Ssklower * ( we never get here if the listener isn't af_iso ) 505*36414Ssklower * refuse the connection : 506*36414Ssklower * but we don't have a way to restrict thus - it's 507*36414Ssklower * utterly permissive. 508*36414Ssklower if(channel) { 509*36414Ssklower (void) cons_netcmd(CONN_REFUSE, tpcb->tp_npcb, 510*36414Ssklower channel, tpcb->tp_class == TP_CLASS_4); 511*36414Ssklower error = EPFNOSUPPORT; 512*36414Ssklower goto done; 513*36414Ssklower } 514*36414Ssklower */ 515*36414Ssklower IFDEBUG(D_CONN) 516*36414Ssklower printf( 517*36414Ssklower "tp_route_to( CHANGING nlproto old 0x%x new 0x%x)\n", 518*36414Ssklower tpcb->tp_nlproto , &nl_protosw[ISO_CONS]); 519*36414Ssklower ENDDEBUG 520*36414Ssklower tpcb->tp_nlproto = &nl_protosw[ISO_CONS]; 521*36414Ssklower } 522*36414Ssklower /* Now we've got the right nl_protosw. 523*36414Ssklower * If we already have a channel (we were called from tp_input()) 524*36414Ssklower * tell cons that we'll hang onto this channel. 525*36414Ssklower * If we don't already have one (we were called from usrreq()) 526*36414Ssklower * -and if it's TP0 open a net connection and wait for it to finish. 527*36414Ssklower */ 528*36414Ssklower if( channel ) { 529*36414Ssklower error = cons_netcmd( CONN_CONFIRM, tpcb->tp_npcb, 530*36414Ssklower channel, tpcb->tp_class == TP_CLASS_4); 531*36414Ssklower vc_to_kill ++; 532*36414Ssklower } else if( tpcb->tp_class != TP_CLASS_4 /* class 4 only */) { 533*36414Ssklower /* better open vc if any possibility of ending up 534*36414Ssklower * in non-multiplexing class 535*36414Ssklower */ 536*36414Ssklower error = cons_openvc(tpcb->tp_npcb, siso, tpcb->tp_sock); 537*36414Ssklower vc_to_kill ++; 538*36414Ssklower } 539*36414Ssklower /* class 4 doesn't need to open a vc now - may use one already 540*36414Ssklower * opened or may open one only when it sends a pkt. 541*36414Ssklower */ 542*36414Ssklower #else NARGOXTWENTYFIVE > 0 543*36414Ssklower error = ECONNREFUSED; 544*36414Ssklower #endif NARGOXTWENTYFIVE > 0 545*36414Ssklower break; 546*36414Ssklower default: 547*36414Ssklower error = EPROTOTYPE; 548*36414Ssklower } 549*36414Ssklower 550*36414Ssklower ASSERT( save_netservice == tpcb->tp_netservice); 551*36414Ssklower } 552*36414Ssklower if( error ) 553*36414Ssklower goto done; 554*36414Ssklower IFDEBUG(D_CONN) 555*36414Ssklower printf("tp_route_to calling nlp_pcbconn, netserv %d\n", 556*36414Ssklower tpcb->tp_netservice); 557*36414Ssklower ENDDEBUG 558*36414Ssklower error = (tpcb->tp_nlproto->nlp_pcbconn)(tpcb->tp_sock->so_pcb, m); 559*36414Ssklower 560*36414Ssklower if( error && vc_to_kill ) { 561*36414Ssklower tp_netcmd( tpcb, CONN_CLOSE); 562*36414Ssklower goto done; 563*36414Ssklower } 564*36414Ssklower 565*36414Ssklower /* PHASE 2: replace iso_netmatch with iso_on_localnet(foreign addr) */ 566*36414Ssklower if( iso_netmatch( 567*36414Ssklower &(((struct isopcb *)(tpcb->tp_sock->so_pcb))->isop_laddr), 568*36414Ssklower &(((struct isopcb *)(tpcb->tp_sock->so_pcb))->isop_faddr) 569*36414Ssklower )) { 570*36414Ssklower tpcb->tp_flags |= TPF_PEER_ON_SAMENET; 571*36414Ssklower } 572*36414Ssklower 573*36414Ssklower { /* start with the global rtt, rtv stats */ 574*36414Ssklower register int i = 575*36414Ssklower (int) tpcb->tp_flags & (TPF_PEER_ON_SAMENET | TPF_NLQOS_PDN); 576*36414Ssklower 577*36414Ssklower tpcb->tp_rtt = tp_stat.ts_rtt[i]; 578*36414Ssklower tpcb->tp_rtv = tp_stat.ts_rtv[i]; 579*36414Ssklower } 580*36414Ssklower done: 581*36414Ssklower IFDEBUG(D_CONN) 582*36414Ssklower printf("tp_route_to returns 0x%x\n", error); 583*36414Ssklower ENDDEBUG 584*36414Ssklower IFTRACE(D_CONN) 585*36414Ssklower tptraceTPCB(TPPTmisc, "route_to: returns: error netserv class", error, 586*36414Ssklower tpcb->tp_netservice, tpcb->tp_class, 0); 587*36414Ssklower ENDTRACE 588*36414Ssklower return error; 589*36414Ssklower } 590*36414Ssklower 591*36414Ssklower #ifdef TP_PERF_MEAS 592*36414Ssklower /* 593*36414Ssklower * CALLED FROM: 594*36414Ssklower * tp_ctloutput() when the user sets TPOPT_PERF_MEAS on 595*36414Ssklower * and tp_newsocket() when a new connection is made from 596*36414Ssklower * a listening socket with tp_perf_on == true. 597*36414Ssklower * FUNCTION and ARGUMENTS: 598*36414Ssklower * (tpcb) is the usual; this procedure gets a clear cluster mbuf for 599*36414Ssklower * a tp_pmeas structure, and makes tpcb->tp_p_meas point to it. 600*36414Ssklower * RETURN VALUE: 601*36414Ssklower * ENOBUFS if it cannot get a cluster mbuf. 602*36414Ssklower */ 603*36414Ssklower 604*36414Ssklower int 605*36414Ssklower tp_setup_perf(tpcb) 606*36414Ssklower register struct tp_pcb *tpcb; 607*36414Ssklower { 608*36414Ssklower register struct mbuf *q; 609*36414Ssklower 610*36414Ssklower if( tpcb->tp_p_meas == (struct tp_pmeas *)0 ) { 611*36414Ssklower 612*36414Ssklower /* allocate a cluster for all the stats */ 613*36414Ssklower MGET(q, M_DONTWAIT, TPMT_PERF); /* something we don't otherwise use */ 614*36414Ssklower if (q == 0) 615*36414Ssklower return ENOBUFS; 616*36414Ssklower q->m_act = MNULL; 617*36414Ssklower MCLGET(q); /* for the tp_pmeas struct */ 618*36414Ssklower if(q->m_len == 0) { 619*36414Ssklower m_free(q); 620*36414Ssklower return ENOBUFS; 621*36414Ssklower } else { 622*36414Ssklower /* point into the cluster */ 623*36414Ssklower tpcb->tp_p_meas = mtod(q, struct tp_pmeas *); 624*36414Ssklower /* get rid of the original little mbuf */ 625*36414Ssklower q->m_off = 0; q->m_len = 0; 626*36414Ssklower m_free(q); 627*36414Ssklower bzero( (caddr_t)tpcb->tp_p_meas, sizeof (struct tp_pmeas) ); 628*36414Ssklower IFDEBUG(D_PERF_MEAS) 629*36414Ssklower printf( 630*36414Ssklower "tpcb 0x%x so 0x%x ref 0x%x tp_p_meas 0x%x tp_perf_on 0x%x\n", 631*36414Ssklower tpcb, tpcb->tp_sock, tpcb->tp_lref, 632*36414Ssklower tpcb->tp_p_meas, tpcb->tp_perf_on); 633*36414Ssklower ENDDEBUG 634*36414Ssklower tpcb->tp_perf_on = 1; 635*36414Ssklower } 636*36414Ssklower } 637*36414Ssklower return 0; 638*36414Ssklower } 639*36414Ssklower #endif TP_PERF_MEAS 640*36414Ssklower 641*36414Ssklower #ifdef ARGO_DEBUG 642*36414Ssklower dump_addr (addr) 643*36414Ssklower register struct sockaddr *addr; 644*36414Ssklower { 645*36414Ssklower switch( addr->sa_family ) { 646*36414Ssklower case AF_INET: 647*36414Ssklower dump_inaddr(addr); 648*36414Ssklower break; 649*36414Ssklower case AF_ISO: 650*36414Ssklower dump_isoaddr(addr); 651*36414Ssklower break; 652*36414Ssklower default: 653*36414Ssklower printf("BAD AF: 0x%x\n", addr->sa_family); 654*36414Ssklower break; 655*36414Ssklower } 656*36414Ssklower } 657*36414Ssklower 658*36414Ssklower #endif ARGO_DEBUG 659*36414Ssklower 660