1*36401Ssklower /*********************************************************** 2*36401Ssklower Copyright IBM Corporation 1987 3*36401Ssklower 4*36401Ssklower All Rights Reserved 5*36401Ssklower 6*36401Ssklower Permission to use, copy, modify, and distribute this software and its 7*36401Ssklower documentation for any purpose and without fee is hereby granted, 8*36401Ssklower provided that the above copyright notice appear in all copies and that 9*36401Ssklower both that copyright notice and this permission notice appear in 10*36401Ssklower supporting documentation, and that the name of IBM not be 11*36401Ssklower used in advertising or publicity pertaining to distribution of the 12*36401Ssklower software without specific, written prior permission. 13*36401Ssklower 14*36401Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 15*36401Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 16*36401Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 17*36401Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 18*36401Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 19*36401Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 20*36401Ssklower SOFTWARE. 21*36401Ssklower 22*36401Ssklower ******************************************************************/ 23*36401Ssklower 24*36401Ssklower /* 25*36401Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 26*36401Ssklower */ 27*36401Ssklower /* 28*36401Ssklower * ARGO TP 29*36401Ssklower * 30*36401Ssklower * $Header: tp_input.c,v 5.6 88/11/18 17:27:38 nhall Exp $ 31*36401Ssklower * $Source: /usr/argo/sys/netiso/RCS/tp_input.c,v $ 32*36401Ssklower * 33*36401Ssklower * tp_input() gets an mbuf chain from ip. Actually, not directly 34*36401Ssklower * from ip, because ip calls a net-level routine that strips off 35*36401Ssklower * the net header and then calls tp_input(), passing the proper type 36*36401Ssklower * of addresses for the address family in use (how it figures out 37*36401Ssklower * which AF is not yet determined. 38*36401Ssklower * 39*36401Ssklower * Decomposing the tpdu is some of the most laughable code. The variable-length 40*36401Ssklower * parameters and the problem of non-aligned memory references 41*36401Ssklower * necessitates such abominations as the macros WHILE_OPTIONS (q.v. below) 42*36401Ssklower * to loop through the header and decompose it. 43*36401Ssklower * 44*36401Ssklower * The routine tp_newsocket() is called when a CR comes in for a listening 45*36401Ssklower * socket. tp_input calls sonewconn() and tp_newsocket() to set up the 46*36401Ssklower * "child" socket. Most tpcb values are copied from the parent tpcb into 47*36401Ssklower * the child. 48*36401Ssklower * 49*36401Ssklower * Also in here is tp_headersize() (grot) which tells the expected size 50*36401Ssklower * of a tp header, to be used by other layers. It's in here because it 51*36401Ssklower * uses the static structure tpdu_info. 52*36401Ssklower */ 53*36401Ssklower 54*36401Ssklower #ifndef lint 55*36401Ssklower static char *rcsid = "$Header: tp_input.c,v 5.6 88/11/18 17:27:38 nhall Exp $"; 56*36401Ssklower #endif lint 57*36401Ssklower 58*36401Ssklower #include "argoxtwentyfive.h" 59*36401Ssklower #include "param.h" 60*36401Ssklower #include "mbuf.h" 61*36401Ssklower #include "socket.h" 62*36401Ssklower #include "socketvar.h" 63*36401Ssklower #include "domain.h" 64*36401Ssklower #include "protosw.h" 65*36401Ssklower #include "errno.h" 66*36401Ssklower #include "time.h" 67*36401Ssklower #include "kernel.h" 68*36401Ssklower #include "types.h" 69*36401Ssklower #include "../netiso/iso_errno.h" 70*36401Ssklower #include "../netiso/tp_param.h" 71*36401Ssklower #include "../netiso/tp_timer.h" 72*36401Ssklower #include "../netiso/tp_stat.h" 73*36401Ssklower #include "../netiso/tp_pcb.h" 74*36401Ssklower #include "../netiso/argo_debug.h" 75*36401Ssklower #include "../netiso/tp_trace.h" 76*36401Ssklower #include "../netiso/tp_tpdu.h" 77*36401Ssklower #include "../netiso/iso.h" 78*36401Ssklower #include "../netiso/cons.h" 79*36401Ssklower 80*36401Ssklower int iso_check_csum(), tp_driver(), tp_headersize(), tp_error_emit(); 81*36401Ssklower 82*36401Ssklower #ifdef lint 83*36401Ssklower #undef ATTR 84*36401Ssklower #define ATTR(X)ev_number 85*36401Ssklower #endif lint 86*36401Ssklower 87*36401Ssklower struct mbuf * 88*36401Ssklower tp_inputprep(m) 89*36401Ssklower struct mbuf *m; 90*36401Ssklower { 91*36401Ssklower struct tpdu *hdr; 92*36401Ssklower 93*36401Ssklower IFDEBUG(D_TPINPUT) 94*36401Ssklower printf("tp_inputprep: m 0x%x\n") ; 95*36401Ssklower ENDDEBUG 96*36401Ssklower 97*36401Ssklower while( m->m_len < 1 ) { 98*36401Ssklower if( (m = m_free(m)) == MNULL ) { 99*36401Ssklower return (struct mbuf *)0; 100*36401Ssklower } 101*36401Ssklower } 102*36401Ssklower 103*36401Ssklower if(m->m_off & 0x3) { 104*36401Ssklower /* align to a 4-byte boundary - sigh */ 105*36401Ssklower register struct mbuf *n; 106*36401Ssklower 107*36401Ssklower MGET(n, M_DONTWAIT, m->m_type); 108*36401Ssklower if( n == MNULL ) { 109*36401Ssklower m_freem(m); 110*36401Ssklower return (struct mbuf *)0; 111*36401Ssklower } 112*36401Ssklower n->m_act = MNULL; 113*36401Ssklower n->m_len = m->m_len; 114*36401Ssklower n->m_next = m->m_next; 115*36401Ssklower bcopy( mtod(m, caddr_t), mtod(n, caddr_t), m->m_len ); 116*36401Ssklower m->m_next = 0; 117*36401Ssklower m_free(m); 118*36401Ssklower m = n; 119*36401Ssklower } 120*36401Ssklower CHANGE_MTYPE(m, TPMT_DATA); 121*36401Ssklower 122*36401Ssklower /* we KNOW that there is at least 1 byte in this mbuf */ 123*36401Ssklower 124*36401Ssklower hdr = mtod( m, struct tpdu *); 125*36401Ssklower 126*36401Ssklower /* 127*36401Ssklower * now pull up the whole tp header 128*36401Ssklower */ 129*36401Ssklower if ( m->m_len < hdr->tpdu_li + 1 ) { 130*36401Ssklower if ((m = m_pullup(m, (int)(hdr->tpdu_li) + 1)) == MNULL ) { 131*36401Ssklower IncStat(ts_recv_drop); 132*36401Ssklower return (struct mbuf *)0; 133*36401Ssklower } 134*36401Ssklower } 135*36401Ssklower IFDEBUG(D_INPUT) 136*36401Ssklower printf( 137*36401Ssklower " at end: m 0x%x hdr->tpdu_li 0x%x m_len 0x%x\n",m, 138*36401Ssklower hdr->tpdu_li,m->m_len); 139*36401Ssklower ENDDEBUG 140*36401Ssklower return m; 141*36401Ssklower } 142*36401Ssklower 143*36401Ssklower /* begin groan 144*36401Ssklower * -- this array and the following macros allow you to step through the 145*36401Ssklower * parameters of the variable part of a header 146*36401Ssklower * note that if for any reason the values of the **_TPDU macros (in tp_events.h) 147*36401Ssklower * should change, this array has to be rearranged 148*36401Ssklower */ 149*36401Ssklower 150*36401Ssklower #define TP_LEN_CLASS_0_INDEX 2 151*36401Ssklower #define TP_MAX_DATA_INDEX 3 152*36401Ssklower 153*36401Ssklower static u_char tpdu_info[][4] = 154*36401Ssklower { 155*36401Ssklower /* length max data len */ 156*36401Ssklower /* reg fmt xtd fmt class 0 */ 157*36401Ssklower /* UNUSED 0x0 */ 0x0 , 0x0, 0x0, 0x0, 158*36401Ssklower /* XPD_TPDU_type 0x1 */ 0x5, 0x8, 0x0, TP_MAX_XPD_DATA, 159*36401Ssklower /* XAK_TPDU_type 0x2 */ 0x5 , 0x8, 0x0, 0x0, 160*36401Ssklower /* GR_TPDU_type 0x3 */ 0x0 , 0x0, 0x0, 0x0, 161*36401Ssklower /* UNUSED 0x4 */ 0x0 , 0x0, 0x0, 0x0, 162*36401Ssklower /* UNUSED 0x5 */ 0x0 , 0x0, 0x0, 0x0, 163*36401Ssklower /* AK_TPDU_type 0x6 */ 0x5, 0xa, 0x0, 0x0, 164*36401Ssklower /* ER_TPDU_type 0x7 */ 0x5, 0x5, 0x0, 0x0, 165*36401Ssklower /* DR_TPDU_type 0x8 */ 0x7, 0x7, 0x7, TP_MAX_DR_DATA, 166*36401Ssklower /* UNUSED 0x9 */ 0x0 , 0x0, 0x0, 0x0, 167*36401Ssklower /* UNUSED 0xa */ 0x0 , 0x0, 0x0, 0x0, 168*36401Ssklower /* UNUSED 0xb */ 0x0 , 0x0, 0x0, 0x0, 169*36401Ssklower /* DC_TPDU_type 0xc */ 0x6, 0x6, 0x0, 0x0, 170*36401Ssklower /* CC_TPDU_type 0xd */ 0x7, 0x7, 0x7, TP_MAX_CC_DATA, 171*36401Ssklower /* CR_TPDU_type 0xe */ 0x7, 0x7, 0x7, TP_MAX_CR_DATA, 172*36401Ssklower /* DT_TPDU_type 0xf */ 0x5, 0x8, 0x3, 0x0, 173*36401Ssklower }; 174*36401Ssklower 175*36401Ssklower /* 176*36401Ssklower * WHENEVER YOU USE THE FOLLOWING MACRO, 177*36401Ssklower * BE SURE THE TPDUTYPE IS A LEGIT VALUE FIRST! 178*36401Ssklower */ 179*36401Ssklower 180*36401Ssklower #define WHILE_OPTIONS(P, hdr,format)\ 181*36401Ssklower { register caddr_t P;\ 182*36401Ssklower P = (caddr_t)(hdr) +\ 183*36401Ssklower tpdu_info[(hdr)->tpdu_type][(format)];\ 184*36401Ssklower while( P < (caddr_t)(hdr) + (int)((hdr)->tpdu_li) ) { 185*36401Ssklower 186*36401Ssklower #define END_WHILE_OPTIONS(P)\ 187*36401Ssklower P = P + 2 + (int)((struct tp_vbp *)P)->tpv_len ;\ 188*36401Ssklower } } 189*36401Ssklower 190*36401Ssklower #define CHECK(Phrase, Erval, Stat, Whattodo, Loc)\ 191*36401Ssklower if(Phrase) { error = (Erval); errloc = (caddr_t)(Loc); IncStat(Stat); \ 192*36401Ssklower goto Whattodo; } 193*36401Ssklower 194*36401Ssklower /* end groan */ 195*36401Ssklower 196*36401Ssklower /* 197*36401Ssklower * NAME: tp_newsocket() 198*36401Ssklower * 199*36401Ssklower * CALLED FROM: 200*36401Ssklower * tp_input() on incoming CR, when a socket w/ the called suffix 201*36401Ssklower * is awaiting a connection request 202*36401Ssklower * 203*36401Ssklower * FUNCTION and ARGUMENTS: 204*36401Ssklower * Create a new socket structure, attach to it a new transport pcb, 205*36401Ssklower * using a copy of the net level pcb for the parent socket. 206*36401Ssklower * (so) is the parent socket. 207*36401Ssklower * (fname) is the foreign address (all that's used is the nsap portion) 208*36401Ssklower * 209*36401Ssklower * RETURN VALUE: 210*36401Ssklower * a new socket structure, being this end of the newly formed connection. 211*36401Ssklower * 212*36401Ssklower * SIDE EFFECTS: 213*36401Ssklower * Sets a few things in the tpcb and net level pcb 214*36401Ssklower * 215*36401Ssklower * NOTES: 216*36401Ssklower */ 217*36401Ssklower static struct socket * 218*36401Ssklower tp_newsocket(so, fname, cons_channel, class_to_use, netservice) 219*36401Ssklower struct socket *so; 220*36401Ssklower struct sockaddr *fname; 221*36401Ssklower u_int cons_channel; 222*36401Ssklower u_char class_to_use; 223*36401Ssklower u_int netservice; 224*36401Ssklower { 225*36401Ssklower register struct tp_pcb *tpcb = sototpcb(so); /* old tpcb, needed below */ 226*36401Ssklower struct tp_pcb * newtpcb; 227*36401Ssklower struct proc * selproc = so->so_rcv.sb_sel; /* kludge for select */ 228*36401Ssklower 229*36401Ssklower /* 230*36401Ssklower * sonewconn() gets a new socket structure, 231*36401Ssklower * a new lower layer pcb and a new tpcb, 232*36401Ssklower * but the pcbs are unnamed (not bound) 233*36401Ssklower */ 234*36401Ssklower IFTRACE(D_NEWSOCK) 235*36401Ssklower tptraceTPCB(TPPTmisc, "newsock: listg_so,_tpcb selproc, so_head", 236*36401Ssklower so, tpcb, selproc, so->so_head); 237*36401Ssklower ENDTRACE 238*36401Ssklower 239*36401Ssklower if ((so = sonewconn(so)) == (struct socket *)0) 240*36401Ssklower return so; 241*36401Ssklower IFTRACE(D_NEWSOCK) 242*36401Ssklower tptraceTPCB(TPPTmisc, "newsock: after newconn so, selproc, so_head", 243*36401Ssklower so, selproc, so->so_head, 0); 244*36401Ssklower ENDTRACE 245*36401Ssklower 246*36401Ssklower so->so_rcv.sb_sel = selproc; /* so that soisconnected() after receipt 247*36401Ssklower * of the ack will wake this guy up if he's selecting on the 248*36401Ssklower * listening socket 249*36401Ssklower */ 250*36401Ssklower IFDEBUG(D_NEWSOCK) 251*36401Ssklower printf("tp_newsocket(channel 0x%x) after sonewconn so 0x%x \n", so); 252*36401Ssklower dump_isoaddr(fname); 253*36401Ssklower { 254*36401Ssklower struct socket *t, *head ; 255*36401Ssklower 256*36401Ssklower head = so->so_head; 257*36401Ssklower t = so; 258*36401Ssklower printf("so 0x%x so_head 0x%x so_q0 0x%x, q0len %d\n", 259*36401Ssklower t, t->so_head, t->so_q0, t->so_q0len); 260*36401Ssklower while( (t=t->so_q0) && t!= so && t!= head) 261*36401Ssklower printf("so 0x%x so_head 0x%x so_q0 0x%x, q0len %d\n", 262*36401Ssklower t, t->so_head, t->so_q0, t->so_q0len); 263*36401Ssklower } 264*36401Ssklower ENDDEBUG 265*36401Ssklower 266*36401Ssklower /* 267*36401Ssklower * before we clobber the old tpcb ptr, get these items from the parent pcb 268*36401Ssklower */ 269*36401Ssklower newtpcb = sototpcb(so); 270*36401Ssklower newtpcb->_tp_param = tpcb->_tp_param; 271*36401Ssklower newtpcb->tp_flags = tpcb->tp_flags; 272*36401Ssklower newtpcb->tp_lcredit = tpcb->tp_lcredit; 273*36401Ssklower newtpcb->tp_l_tpdusize = tpcb->tp_l_tpdusize; 274*36401Ssklower newtpcb->tp_lsuffixlen = tpcb->tp_lsuffixlen; 275*36401Ssklower bcopy( tpcb->tp_lsuffix, newtpcb->tp_lsuffix, newtpcb->tp_lsuffixlen); 276*36401Ssklower soreserve(so, tpcb->tp_winsize, tpcb->tp_winsize); 277*36401Ssklower 278*36401Ssklower if( /* old */ tpcb->tp_flags & (TPF_CONN_DATA_OUT | TPF_DISC_DATA_OUT )) { 279*36401Ssklower /* 280*36401Ssklower * Flags has already been copied, now copy the data 281*36401Ssklower * -- these data are the connect- or disconnect- data. 282*36401Ssklower */ 283*36401Ssklower struct mbuf *conndata; 284*36401Ssklower 285*36401Ssklower ASSERT(tpcb->tp_sock->so_snd.sb_mb != MNULL); 286*36401Ssklower ASSERT(tpcb->tp_sock->so_snd.sb_cc != 0); 287*36401Ssklower conndata = m_copy( tpcb->tp_sock->so_snd.sb_mb, 0, 288*36401Ssklower tpcb->tp_sock->so_snd.sb_cc); 289*36401Ssklower IFDEBUG(D_CONN) 290*36401Ssklower dump_mbuf(conndata, "conndata after mcopy"); 291*36401Ssklower dump_mbuf(tpcb->tp_sock->so_snd.sb_mb, "old sosnd after mcopy"); 292*36401Ssklower dump_mbuf(so->so_snd.sb_mb, "new (so->)sosnd before sbapndrec"); 293*36401Ssklower dump_mbuf(conndata, "conndata before sbappendrec"); 294*36401Ssklower ENDDEBUG 295*36401Ssklower sbappendrecord( &so->so_snd, conndata ); 296*36401Ssklower } 297*36401Ssklower 298*36401Ssklower tpcb = newtpcb; 299*36401Ssklower tpcb->tp_state = TP_LISTENING; 300*36401Ssklower tpcb->tp_class = class_to_use; 301*36401Ssklower tpcb->tp_netservice = netservice; 302*36401Ssklower 303*36401Ssklower 304*36401Ssklower ASSERT( fname != 0 ) ; /* just checking */ 305*36401Ssklower if ( fname ) { 306*36401Ssklower /* 307*36401Ssklower * tp_route_to takes its address argument in the form of an mbuf. 308*36401Ssklower */ 309*36401Ssklower struct mbuf *m; 310*36401Ssklower int err; 311*36401Ssklower 312*36401Ssklower MGET(m, M_DONTWAIT, MT_SONAME); /* mbuf type used is confusing */ 313*36401Ssklower if (m) { 314*36401Ssklower /* 315*36401Ssklower * this seems a bit grotesque, but tp_route_to expects 316*36401Ssklower * an mbuf * instead of simply a sockaddr; it calls the ll 317*36401Ssklower * pcb_connect, which expects the name/addr in an mbuf as well. 318*36401Ssklower * sigh. 319*36401Ssklower */ 320*36401Ssklower bcopy((caddr_t)fname, mtod(m, caddr_t), sizeof (struct sockaddr)); 321*36401Ssklower m->m_act = MNULL; 322*36401Ssklower m->m_len = (fname->sa_family == AF_INET) ? 323*36401Ssklower sizeof(struct sockaddr_in) : sizeof(struct sockaddr_iso); 324*36401Ssklower 325*36401Ssklower /* grot : have to say the kernel can override params in 326*36401Ssklower * the passive open case 327*36401Ssklower */ 328*36401Ssklower tpcb->tp_dont_change_params = 0; 329*36401Ssklower err = tp_route_to( m, tpcb, cons_channel); 330*36401Ssklower m_free(m); 331*36401Ssklower 332*36401Ssklower if (!err) 333*36401Ssklower goto ok; 334*36401Ssklower } 335*36401Ssklower IFDEBUG(D_CONN) 336*36401Ssklower printf("tp_route_to FAILED! detaching tpcb 0x%x, so 0x%x\n", 337*36401Ssklower tpcb, so); 338*36401Ssklower ENDDEBUG 339*36401Ssklower (void) tp_detach(tpcb); 340*36401Ssklower return 0; 341*36401Ssklower } 342*36401Ssklower ok: 343*36401Ssklower IFDEBUG(D_TPINPUT) 344*36401Ssklower printf("tp_newsocket returning so 0x%x, sototpcb(so) 0x%x\n", 345*36401Ssklower so, sototpcb(so)); 346*36401Ssklower ENDDEBUG 347*36401Ssklower return so; 348*36401Ssklower } 349*36401Ssklower 350*36401Ssklower #ifndef CONS 351*36401Ssklower tpcons_output() 352*36401Ssklower { 353*36401Ssklower return(0); 354*36401Ssklower } 355*36401Ssklower #endif !CONS 356*36401Ssklower 357*36401Ssklower /* 358*36401Ssklower * NAME: tp_input() 359*36401Ssklower * 360*36401Ssklower * CALLED FROM: 361*36401Ssklower * net layer input routine 362*36401Ssklower * 363*36401Ssklower * FUNCTION and ARGUMENTS: 364*36401Ssklower * Process an incoming TPDU (m), finding the associated tpcb if there 365*36401Ssklower * is one. Create the appropriate type of event and call the driver. 366*36401Ssklower * (faddr) and (laddr) are the foreign and local addresses. 367*36401Ssklower * 368*36401Ssklower * When tp_input() is called we KNOW that the ENTIRE TP HEADER 369*36401Ssklower * has been m_pullup-ed. 370*36401Ssklower * 371*36401Ssklower * RETURN VALUE: Nada 372*36401Ssklower * 373*36401Ssklower * SIDE EFFECTS: 374*36401Ssklower * When using COSNS it may affect the state of the net-level pcb 375*36401Ssklower * 376*36401Ssklower * NOTE: 377*36401Ssklower * The initial value of acktime is 2 so that we will never 378*36401Ssklower * have a 0 value for tp_peer_acktime. It gets used in the 379*36401Ssklower * computation of the retransmission timer value, and so it 380*36401Ssklower * mustn't be zero. 381*36401Ssklower * 2 seems like a reasonable minimum. 382*36401Ssklower */ 383*36401Ssklower ProtoHook 384*36401Ssklower tp_input(m, faddr, laddr, cons_channel, dgout_routine) 385*36401Ssklower register struct mbuf *m; 386*36401Ssklower struct sockaddr *faddr, *laddr; /* NSAP addresses */ 387*36401Ssklower u_int cons_channel; 388*36401Ssklower int (*dgout_routine)(); 389*36401Ssklower 390*36401Ssklower { 391*36401Ssklower register struct tp_pcb *tpcb = (struct tp_pcb *)0; 392*36401Ssklower register struct tpdu *hdr = mtod(m, struct tpdu *); 393*36401Ssklower struct socket *so; 394*36401Ssklower struct tp_event e; 395*36401Ssklower int error = 0; 396*36401Ssklower unsigned dutype; 397*36401Ssklower u_short dref, sref, acktime, subseq; /*VAX*/ 398*36401Ssklower u_char preferred_class=0, class_to_use=0; 399*36401Ssklower u_char opt, dusize, addlopt; 400*36401Ssklower #ifdef TP_PERF_MEAS 401*36401Ssklower u_char perf_meas=0; 402*36401Ssklower #endif TP_PERF_MEAS 403*36401Ssklower u_char fsufxlen; 404*36401Ssklower u_char lsufxlen; 405*36401Ssklower caddr_t fsufxloc=0, lsufxloc=0; 406*36401Ssklower int tpdu_len; 407*36401Ssklower u_int takes_data; 408*36401Ssklower u_int fcc_present; 409*36401Ssklower caddr_t errloc=0; 410*36401Ssklower struct tp_conn_param tpp; 411*36401Ssklower int tpcons_output(); 412*36401Ssklower 413*36401Ssklower #ifdef TP_PERF_MEAS 414*36401Ssklower GET_CUR_TIME( &e.e_time ); 415*36401Ssklower #endif TP_PERF_MEAS 416*36401Ssklower 417*36401Ssklower IFDEBUG(D_TPINPUT) 418*36401Ssklower printf("tp_input(0x%x, ... 0x%x)\n", m, cons_channel); 419*36401Ssklower ENDDEBUG 420*36401Ssklower 421*36401Ssklower again: 422*36401Ssklower 423*36401Ssklower tpdu_len = 0; 424*36401Ssklower tpcb = (struct tp_pcb *)0; 425*36401Ssklower fsufxlen = 0; 426*36401Ssklower lsufxlen = 0; 427*36401Ssklower addlopt = 0; 428*36401Ssklower acktime = 2; 429*36401Ssklower dusize = TP_DFL_TPDUSIZE; 430*36401Ssklower sref = 0; 431*36401Ssklower subseq = 0; 432*36401Ssklower takes_data = FALSE; 433*36401Ssklower fcc_present = FALSE; 434*36401Ssklower 435*36401Ssklower /* 436*36401Ssklower * get the actual tpdu length - necessary for monitoring 437*36401Ssklower * and for checksumming 438*36401Ssklower * 439*36401Ssklower * Also, maybe measure the mbuf chain lengths and sizes. 440*36401Ssklower */ 441*36401Ssklower 442*36401Ssklower { register struct mbuf *n=m; 443*36401Ssklower # ifdef ARGO_DEBUG 444*36401Ssklower int chain_length = 0; 445*36401Ssklower # endif ARGO_DEBUG 446*36401Ssklower 447*36401Ssklower for(;;) { 448*36401Ssklower tpdu_len += n->m_len; 449*36401Ssklower IFDEBUG(D_MBUF_MEAS) 450*36401Ssklower if( n->m_off > MMAXOFF) { 451*36401Ssklower IncStat(ts_mb_cluster); 452*36401Ssklower } else { 453*36401Ssklower IncStat(ts_mb_small); 454*36401Ssklower } 455*36401Ssklower chain_length ++; 456*36401Ssklower ENDDEBUG 457*36401Ssklower if (n->m_next == MNULL ) { 458*36401Ssklower break; 459*36401Ssklower } 460*36401Ssklower n = n->m_next; 461*36401Ssklower } 462*36401Ssklower IFDEBUG(D_MBUF_MEAS) 463*36401Ssklower if(chain_length > 16) 464*36401Ssklower chain_length = 0; /* zero used for anything > 16 */ 465*36401Ssklower tp_stat.ts_mb_len_distr[chain_length] ++; 466*36401Ssklower ENDDEBUG 467*36401Ssklower } 468*36401Ssklower IFTRACE(D_TPINPUT) 469*36401Ssklower tptraceTPCB(TPPTtpduin, hdr->tpdu_type, hdr, hdr->tpdu_li+1, tpdu_len, 470*36401Ssklower 0); 471*36401Ssklower ENDTRACE 472*36401Ssklower 473*36401Ssklower dref = ntohs((short)hdr->tpdu_dref); 474*36401Ssklower sref = ntohs((short)hdr->tpdu_sref); 475*36401Ssklower dutype = (int)hdr->tpdu_type; 476*36401Ssklower 477*36401Ssklower IFDEBUG(D_TPINPUT) 478*36401Ssklower printf("input: dutype 0x%x cons_channel 0x%x dref 0x%x\n", dutype, 479*36401Ssklower cons_channel, dref); 480*36401Ssklower printf("input: dref 0x%x sref 0x%x\n", dref, sref); 481*36401Ssklower ENDDEBUG 482*36401Ssklower IFTRACE(D_TPINPUT) 483*36401Ssklower tptrace(TPPTmisc, "channel dutype dref ", 484*36401Ssklower cons_channel, dutype, dref, 0); 485*36401Ssklower ENDTRACE 486*36401Ssklower 487*36401Ssklower 488*36401Ssklower #ifdef ARGO_DEBUG 489*36401Ssklower if( (dutype < TP_MIN_TPDUTYPE) || (dutype > TP_MAX_TPDUTYPE)) { 490*36401Ssklower printf("BAD dutype! 0x%x, channel 0x%x dref 0x%x\n", 491*36401Ssklower dutype, cons_channel, dref); 492*36401Ssklower dump_buf (m, sizeof( struct mbuf )); 493*36401Ssklower 494*36401Ssklower IncStat(ts_inv_dutype); 495*36401Ssklower goto discard; 496*36401Ssklower } 497*36401Ssklower #endif ARGO_DEBUG 498*36401Ssklower 499*36401Ssklower CHECK( (dutype < TP_MIN_TPDUTYPE || dutype > TP_MAX_TPDUTYPE), 500*36401Ssklower E_TP_INV_TPDU, ts_inv_dutype, respond, 501*36401Ssklower 2 ); 502*36401Ssklower /* unfortunately we can't take the address of the tpdu_type field, 503*36401Ssklower * since it's a bit field - so we just use the constant offset 2 504*36401Ssklower */ 505*36401Ssklower 506*36401Ssklower /* Now this isn't very neat but since you locate a pcb one way 507*36401Ssklower * at the beginning of connection establishment, and by 508*36401Ssklower * the dref for each tpdu after that, we have to treat CRs differently 509*36401Ssklower */ 510*36401Ssklower if ( dutype == CR_TPDU_type ) { 511*36401Ssklower u_char alt_classes = 0; 512*36401Ssklower 513*36401Ssklower #ifdef notdef /* This is done up above */ 514*36401Ssklower sref = hdr->tpdu_CRsref; 515*36401Ssklower #endif notdef 516*36401Ssklower preferred_class = (1 << hdr->tpdu_CRclass); 517*36401Ssklower opt = hdr->tpdu_CRoptions; 518*36401Ssklower 519*36401Ssklower WHILE_OPTIONS(P, hdr, 1 ) /* { */ 520*36401Ssklower 521*36401Ssklower switch( vbptr(P)->tpv_code ) { 522*36401Ssklower 523*36401Ssklower case TPP_tpdu_size: 524*36401Ssklower vb_getval(P, u_char, dusize); 525*36401Ssklower IFDEBUG(D_TPINPUT) 526*36401Ssklower printf("CR dusize 0x%x\n", dusize); 527*36401Ssklower ENDDEBUG 528*36401Ssklower CHECK( (dusize < TP_MIN_TPDUSIZE || dusize > TP_MAX_TPDUSIZE), 529*36401Ssklower E_TP_INV_PVAL, ts_inv_pval, respond, 530*36401Ssklower (1 + (caddr_t)&vbptr(P)->tpv_val - P) ) 531*36401Ssklower break; 532*36401Ssklower case TPP_addl_opt: 533*36401Ssklower vb_getval(P, u_char, addlopt); 534*36401Ssklower break; 535*36401Ssklower case TPP_calling_sufx: 536*36401Ssklower /* could use vb_getval, but we want to save the loc & len 537*36401Ssklower * for later use 538*36401Ssklower */ 539*36401Ssklower fsufxloc = (caddr_t) &vbptr(P)->tpv_val; 540*36401Ssklower fsufxlen = vbptr(P)->tpv_len; 541*36401Ssklower IFDEBUG(D_TPINPUT) 542*36401Ssklower printf("CR fsufx:"); 543*36401Ssklower { register int j; 544*36401Ssklower for(j=0; j<fsufxlen; j++ ) { 545*36401Ssklower printf(" 0x%x. ", *((caddr_t)(fsufxloc+j)) ); 546*36401Ssklower } 547*36401Ssklower printf("\n"); 548*36401Ssklower } 549*36401Ssklower ENDDEBUG 550*36401Ssklower break; 551*36401Ssklower case TPP_called_sufx: 552*36401Ssklower /* could use vb_getval, but we want to save the loc & len 553*36401Ssklower * for later use 554*36401Ssklower */ 555*36401Ssklower lsufxloc = (caddr_t) &vbptr(P)->tpv_val; 556*36401Ssklower lsufxlen = vbptr(P)->tpv_len; 557*36401Ssklower IFDEBUG(D_TPINPUT) 558*36401Ssklower printf("CR lsufx:"); 559*36401Ssklower { register int j; 560*36401Ssklower for(j=0; j<lsufxlen; j++ ) { 561*36401Ssklower printf(" 0x%x. ", *((caddr_t)(lsufxloc+j)) ); 562*36401Ssklower } 563*36401Ssklower printf("\n"); 564*36401Ssklower } 565*36401Ssklower ENDDEBUG 566*36401Ssklower break; 567*36401Ssklower 568*36401Ssklower #ifdef TP_PERF_MEAS 569*36401Ssklower case TPP_perf_meas: 570*36401Ssklower vb_getval(P, u_char, perf_meas); 571*36401Ssklower break; 572*36401Ssklower #endif TP_PERF_MEAS 573*36401Ssklower 574*36401Ssklower case TPP_vers: 575*36401Ssklower /* not in class 0; 1 octet; in CR_TPDU only */ 576*36401Ssklower CHECK( (vbval(P, u_char) != TP_VERSION ), 577*36401Ssklower E_TP_INV_PVAL, ts_inv_pval, respond, 578*36401Ssklower (1 + (caddr_t)&vbptr(P)->tpv_val - P) ) 579*36401Ssklower break; 580*36401Ssklower case TPP_acktime: 581*36401Ssklower vb_getval(P, u_short, acktime); 582*36401Ssklower acktime = ntohs(acktime); 583*36401Ssklower acktime = acktime/500; /* convert to slowtimo ticks */ 584*36401Ssklower if((short)acktime <=0 ) 585*36401Ssklower acktime = 2; /* don't allow a bad peer to screw us up */ 586*36401Ssklower IFDEBUG(D_TPINPUT) 587*36401Ssklower printf("CR acktime 0x%x\n", acktime); 588*36401Ssklower ENDDEBUG 589*36401Ssklower break; 590*36401Ssklower 591*36401Ssklower case TPP_alt_class: 592*36401Ssklower { 593*36401Ssklower u_char *aclass = 0; 594*36401Ssklower register int i; 595*36401Ssklower 596*36401Ssklower for (i = ((struct tp_vbp *)P)->tpv_len; i>0; i--) { 597*36401Ssklower aclass = 598*36401Ssklower (u_char *) &(((struct tp_vbp *)P)->tpv_val); 599*36401Ssklower alt_classes |= (1<<(*aclass)); 600*36401Ssklower } 601*36401Ssklower IFDEBUG(D_TPINPUT) 602*36401Ssklower printf("alt_classes 0x%x\n", alt_classes); 603*36401Ssklower ENDDEBUG 604*36401Ssklower } 605*36401Ssklower break; 606*36401Ssklower 607*36401Ssklower case TPP_security: 608*36401Ssklower case TPP_residER: 609*36401Ssklower case TPP_priority: 610*36401Ssklower case TPP_transdelay: 611*36401Ssklower case TPP_throughput: 612*36401Ssklower case TPP_addl_info: 613*36401Ssklower case TPP_subseq: 614*36401Ssklower IFDEBUG(D_TPINPUT) 615*36401Ssklower printf("param ignored CR_TPDU code= 0x%x\n", 616*36401Ssklower vbptr(P)->tpv_code); 617*36401Ssklower ENDDEBUG 618*36401Ssklower IncStat(ts_param_ignored); 619*36401Ssklower break; 620*36401Ssklower 621*36401Ssklower case TPP_checksum: 622*36401Ssklower IFDEBUG(D_TPINPUT) 623*36401Ssklower printf("CR before cksum\n"); 624*36401Ssklower ENDDEBUG 625*36401Ssklower 626*36401Ssklower CHECK( iso_check_csum(m, tpdu_len), 627*36401Ssklower E_TP_INV_PVAL, ts_bad_csum, discard, 0) 628*36401Ssklower 629*36401Ssklower IFDEBUG(D_TPINPUT) 630*36401Ssklower printf("CR before cksum\n"); 631*36401Ssklower ENDDEBUG 632*36401Ssklower break; 633*36401Ssklower 634*36401Ssklower default: 635*36401Ssklower IncStat(ts_inv_pcode); 636*36401Ssklower error = E_TP_INV_PCODE; 637*36401Ssklower goto discard; 638*36401Ssklower 639*36401Ssklower } 640*36401Ssklower 641*36401Ssklower /* } */ END_WHILE_OPTIONS(P) 642*36401Ssklower 643*36401Ssklower if( lsufxlen == 0) { 644*36401Ssklower /* can't look for a tpcb w/o any called sufx */ 645*36401Ssklower error = E_TP_LENGTH_INVAL; 646*36401Ssklower IncStat(ts_inv_sufx); 647*36401Ssklower goto respond; 648*36401Ssklower } else { 649*36401Ssklower register struct tp_ref *rp; 650*36401Ssklower register int r; 651*36401Ssklower extern int tp_maxrefopen; 652*36401Ssklower 653*36401Ssklower rp = &tp_ref[1]; /* zero-th one is never open */ 654*36401Ssklower for( r=1 ; (r <= tp_maxrefopen) ; r++,rp++ ) { 655*36401Ssklower if (rp->tpr_state!=REF_OPENING) 656*36401Ssklower continue; 657*36401Ssklower if ( bcmp(lsufxloc, rp->tpr_pcb->tp_lsuffix, lsufxlen)==0 ) { 658*36401Ssklower tpcb = rp->tpr_pcb; 659*36401Ssklower if( laddr->sa_family != 660*36401Ssklower tpcb->tp_sock->so_proto->pr_domain->dom_family ) { 661*36401Ssklower IFDEBUG(D_CONN) 662*36401Ssklower printf( 663*36401Ssklower "MISMATCHED AF on CR! laddr.family 0x%x expected 0x%x\n", 664*36401Ssklower laddr->sa_family, 665*36401Ssklower tpcb->tp_sock->so_proto->pr_domain->dom_family ); 666*36401Ssklower ENDDEBUG 667*36401Ssklower continue; 668*36401Ssklower } 669*36401Ssklower IFTRACE(D_TPINPUT) 670*36401Ssklower tptrace(TPPTmisc, "tp_input: ref *lsufxloc refstate", 671*36401Ssklower r, *lsufxloc, rp->tpr_state, 0); 672*36401Ssklower ENDTRACE 673*36401Ssklower /* found it */ 674*36401Ssklower break; 675*36401Ssklower } 676*36401Ssklower } 677*36401Ssklower 678*36401Ssklower CHECK( (r > tp_maxrefopen), E_TP_NO_SESSION, ts_inv_sufx, respond, 679*36401Ssklower (1 + 2 + (caddr_t)&hdr->_tpduf - (caddr_t)hdr)) 680*36401Ssklower /* _tpduf is the fixed part; add 2 to get the dref bits of 681*36401Ssklower * the fixed part (can't take the address of a bit field) 682*36401Ssklower */ 683*36401Ssklower } 684*36401Ssklower 685*36401Ssklower /* 686*36401Ssklower * WE HAVE A TPCB 687*36401Ssklower * already know that the classes in the CR match at least 688*36401Ssklower * one class implemented, but we don't know yet if they 689*36401Ssklower * include any classes permitted by this server. 690*36401Ssklower */ 691*36401Ssklower 692*36401Ssklower IFDEBUG(D_TPINPUT) 693*36401Ssklower printf("HAVE A TPCB 1: 0x%x\n", tpcb); 694*36401Ssklower ENDDEBUG 695*36401Ssklower IFDEBUG(D_CONN) 696*36401Ssklower printf( 697*36401Ssklower "CR: bef CHKS: flags 0x%x class_to_use 0x%x alt 0x%x opt 0x%x tp_class 0x%x\n", 698*36401Ssklower tpcb->tp_flags, class_to_use, alt_classes, opt, tpcb->tp_class); 699*36401Ssklower ENDDEBUG 700*36401Ssklower /* tpcb->tp_class doesn't include any classes not implemented */ 701*36401Ssklower class_to_use = (preferred_class & tpcb->tp_class); 702*36401Ssklower if( (class_to_use = preferred_class & tpcb->tp_class) == 0 ) 703*36401Ssklower class_to_use = alt_classes & tpcb->tp_class; 704*36401Ssklower 705*36401Ssklower class_to_use = 1 << tp_mask_to_num(class_to_use); 706*36401Ssklower 707*36401Ssklower { 708*36401Ssklower tpp = tpcb->_tp_param; 709*36401Ssklower tpp.p_class = class_to_use; 710*36401Ssklower tpp.p_tpdusize = dusize; 711*36401Ssklower tpp.p_xtd_format = (opt & TPO_XTD_FMT) == TPO_XTD_FMT; 712*36401Ssklower tpp.p_xpd_service = (addlopt & TPAO_USE_TXPD) == TPAO_USE_TXPD; 713*36401Ssklower tpp.p_use_checksum = (tpp.p_class == TP_CLASS_0)?0: 714*36401Ssklower (addlopt & TPAO_NO_CSUM) == 0; 715*36401Ssklower #ifdef notdef 716*36401Ssklower tpp.p_use_efc = (opt & TPO_USE_EFC) == TPO_USE_EFC; 717*36401Ssklower tpp.p_use_nxpd = (addlopt & TPAO_USE_NXPD) == TPAO_USE_NXPD; 718*36401Ssklower tpp.p_use_rcc = (addlopt & TPAO_USE_RCC) == TPAO_USE_RCC; 719*36401Ssklower #endif notdef 720*36401Ssklower 721*36401Ssklower CHECK( 722*36401Ssklower tp_consistency(tpcb, 0 /* not force or strict */, &tpp) != 0, 723*36401Ssklower E_TP_NEGOT_FAILED, ts_negotfailed, respond, 724*36401Ssklower (1 + 2 + (caddr_t)&hdr->_tpdufr.CRCC - (caddr_t)hdr) 725*36401Ssklower /* ^ more or less the location of class */ 726*36401Ssklower ) 727*36401Ssklower } 728*36401Ssklower IFTRACE(D_CONN) 729*36401Ssklower tptrace(TPPTmisc, 730*36401Ssklower "after 1 consist class_to_use class, out, tpconsout", 731*36401Ssklower class_to_use, 732*36401Ssklower tpcb->tp_class, dgout_routine, tpcons_output 733*36401Ssklower ); 734*36401Ssklower ENDTRACE 735*36401Ssklower CHECK( 736*36401Ssklower ((class_to_use == TP_CLASS_0)&&(dgout_routine != tpcons_output)), 737*36401Ssklower E_TP_NEGOT_FAILED, ts_negotfailed, respond, 738*36401Ssklower (1 + 2 + (caddr_t)&hdr->_tpdufr.CRCC - (caddr_t)hdr) 739*36401Ssklower /* ^ more or less the location of class */ 740*36401Ssklower ) 741*36401Ssklower IFDEBUG(D_CONN) 742*36401Ssklower printf("CR: after CRCCCHECKS: tpcb 0x%x, flags 0x%x\n", 743*36401Ssklower tpcb, tpcb->tp_flags); 744*36401Ssklower ENDDEBUG 745*36401Ssklower takes_data = TRUE; 746*36401Ssklower e.ATTR(CR_TPDU).e_cdt = hdr->tpdu_CRcdt; 747*36401Ssklower e.ev_number = CR_TPDU; 748*36401Ssklower 749*36401Ssklower so = tpcb->tp_sock; 750*36401Ssklower if (so->so_options & SO_ACCEPTCONN) { 751*36401Ssklower /* 752*36401Ssklower * Create a socket, tpcb, ll pcb, etc. 753*36401Ssklower * for this newborn connection, and fill in all the values. 754*36401Ssklower */ 755*36401Ssklower IFDEBUG(D_CONN) 756*36401Ssklower printf("abt to call tp_newsocket(0x%x, 0x%x, 0x%x, 0x%x)\n", 757*36401Ssklower so, laddr, faddr, cons_channel); 758*36401Ssklower ENDDEBUG 759*36401Ssklower if( (so = 760*36401Ssklower tp_newsocket(so, faddr, cons_channel, 761*36401Ssklower class_to_use, 762*36401Ssklower (dgout_routine == tpcons_output)?ISO_CONS:ISO_CLNS) 763*36401Ssklower ) == (struct socket *)0 ) { 764*36401Ssklower /* note - even if netservice is IN_CLNS, as far as 765*36401Ssklower * the tp entity is concerned, the only differences 766*36401Ssklower * are CO vs CL 767*36401Ssklower */ 768*36401Ssklower IFDEBUG(D_CONN) 769*36401Ssklower printf("tp_newsocket returns 0\n"); 770*36401Ssklower ENDDEBUG 771*36401Ssklower goto discard; 772*36401Ssklower } 773*36401Ssklower tpcb = sototpcb(so); 774*36401Ssklower 775*36401Ssklower /* stash the f suffix in the new tpcb */ 776*36401Ssklower /* l suffix is already there */ 777*36401Ssklower 778*36401Ssklower bcopy( fsufxloc, tpcb->tp_fsuffix, fsufxlen); 779*36401Ssklower if( (tpcb->tp_fsuffixlen = fsufxlen) == sizeof(short) ) { 780*36401Ssklower /* even if it's AF_ISO */ 781*36401Ssklower bcopy (fsufxloc, &(satosin(faddr)->sin_port), sizeof(short)); 782*36401Ssklower (tpcb->tp_nlproto->nlp_putsufx)(so->so_pcb, faddr, TP_FOREIGN); 783*36401Ssklower } 784*36401Ssklower 785*36401Ssklower /* 786*36401Ssklower * stash the addresses in the net level pcb 787*36401Ssklower * kind of like a pcbconnect() but don't need 788*36401Ssklower * or want all those checks. 789*36401Ssklower */ 790*36401Ssklower (tpcb->tp_nlproto->nlp_putnetaddr)(so->so_pcb, faddr, TP_FOREIGN); 791*36401Ssklower (tpcb->tp_nlproto->nlp_putnetaddr)(so->so_pcb, laddr, TP_LOCAL); 792*36401Ssklower 793*36401Ssklower /* 794*36401Ssklower * in the AF_INET case, we need the l,f addrs to contain the ports 795*36401Ssklower */ 796*36401Ssklower if( tpcb->tp_domain == AF_INET) { 797*36401Ssklower CHECK((fsufxlen != sizeof(short))||(lsufxlen != sizeof(short)), 798*36401Ssklower E_TP_ADDR_UNK, ts_inv_dref, respond, 799*36401Ssklower (fsufxloc - (caddr_t)hdr)) 800*36401Ssklower bcopy (lsufxloc, &(satosin(laddr)->sin_port), sizeof(short)); 801*36401Ssklower (tpcb->tp_nlproto->nlp_putsufx)(so->so_pcb, laddr, TP_LOCAL); 802*36401Ssklower /* 803*36401Ssklower this has already been done 'cause the fsufxlen is 804*36401Ssklower sizeof(short): 805*36401Ssklower bcopy (fsufxloc, &(satosin(faddr)->sin_port), 806*36401Ssklower sizeof(short)); 807*36401Ssklower (tpcb->tp_nlproto->nlp_putsufx)(so->so_pcb, faddr, 808*36401Ssklower TP_FOREIGN); 809*36401Ssklower */ 810*36401Ssklower } 811*36401Ssklower 812*36401Ssklower #ifdef TP_PERF_MEAS 813*36401Ssklower if( tpcb->tp_perf_on = perf_meas ) { /* assignment */ 814*36401Ssklower /* ok, let's create an mbuf for stashing the 815*36401Ssklower * statistics if one doesn't already exist 816*36401Ssklower */ 817*36401Ssklower (void) tp_setup_perf(tpcb); 818*36401Ssklower } 819*36401Ssklower #endif TP_PERF_MEAS 820*36401Ssklower tpcb->tp_fref = sref; 821*36401Ssklower 822*36401Ssklower /* We've already checked for consistency with the options 823*36401Ssklower * set in tpp, but we couldn't set them earlier because 824*36401Ssklower * we didn't want to change options in the LISTENING tpcb. 825*36401Ssklower * Now we set the options in the new socket's tpcb. 826*36401Ssklower */ 827*36401Ssklower (void) tp_consistency( tpcb, TP_FORCE, &tpp); 828*36401Ssklower 829*36401Ssklower if(!tpcb->tp_use_checksum) 830*36401Ssklower IncStat(ts_csum_off); 831*36401Ssklower if(tpcb->tp_xpd_service) 832*36401Ssklower IncStat(ts_use_txpd); 833*36401Ssklower if(tpcb->tp_xtd_format) 834*36401Ssklower IncStat(ts_xtd_fmt); 835*36401Ssklower 836*36401Ssklower /* 837*36401Ssklower * Get the maximum transmission unit from the lower layer(s) 838*36401Ssklower * so we can negotiate a reasonable max TPDU size. 839*36401Ssklower */ 840*36401Ssklower (tpcb->tp_nlproto->nlp_mtu)(so, so->so_pcb, 841*36401Ssklower &tpcb->tp_l_tpdusize, &tpcb->tp_tpdusize, 0); 842*36401Ssklower tpcb->tp_peer_acktime = acktime; 843*36401Ssklower 844*36401Ssklower /* 845*36401Ssklower * The following kludge is used to test retransmissions and 846*36401Ssklower * timeout during connection establishment. 847*36401Ssklower */ 848*36401Ssklower IFDEBUG(D_ZDREF) 849*36401Ssklower IncStat(ts_zdebug); 850*36401Ssklower tpcb->tp_fref = 0; 851*36401Ssklower ENDDEBUG 852*36401Ssklower } 853*36401Ssklower IncStat(ts_CR_rcvd); 854*36401Ssklower } else if ( dutype == ER_TPDU_type ) { 855*36401Ssklower /* 856*36401Ssklower * ER TPDUs have to be recognized separately 857*36401Ssklower * because they don't necessarily have a tpcb 858*36401Ssklower * with them and we don't want err out looking for such 859*36401Ssklower * a beast. 860*36401Ssklower * We could put a bunch of little kludges in the 861*36401Ssklower * next section of code so it would avoid references to tpcb 862*36401Ssklower * if dutype == ER_TPDU_type but we don't want code for ERs to 863*36401Ssklower * mess up code for data transfer. 864*36401Ssklower */ 865*36401Ssklower IncStat(ts_ER_rcvd); 866*36401Ssklower e.ev_number = ER_TPDU; 867*36401Ssklower e.ATTR(ER_TPDU).e_reason = (u_char)hdr->tpdu_ERreason; 868*36401Ssklower takes_data = 1; 869*36401Ssklower } else { 870*36401Ssklower /* tpdu type is CC, XPD, XAK, GR, AK, DR, DC, or DT */ 871*36401Ssklower 872*36401Ssklower /* In the next 4 checks, 873*36401Ssklower * _tpduf is the fixed part; add 2 to get the dref bits of 874*36401Ssklower * the fixed part (can't take the address of a bit field) 875*36401Ssklower */ 876*36401Ssklower if(cons_channel) { 877*36401Ssklower #if NARGOXTWENTYFIVE > 0 878*36401Ssklower extern struct tp_pcb *cons_chan_to_tpcb(); 879*36401Ssklower 880*36401Ssklower tpcb = cons_chan_to_tpcb( cons_channel ); 881*36401Ssklower /* Problem: We may have a legit 882*36401Ssklower * error situation yet we may or may not have 883*36401Ssklower * a correspondence between the tpcb and the vc, 884*36401Ssklower * e.g., TP4cr--> <no dice, respond w/ DR on vc> 885*36401Ssklower * <--- DR 886*36401Ssklower * Now it's up to TP to look at the tpdu and do one of: 887*36401Ssklower * confirm(dgm)(cr), confirm(circuit)(cr), reject(cr), or 888*36401Ssklower * nothing, if the circuit is already open (any other tpdu). 889*36401Ssklower * Sigh. 890*36401Ssklower */ 891*36401Ssklower 892*36401Ssklower /* I don't know about this error value */ 893*36401Ssklower CHECK( (tpcb == (struct tp_pcb *)0) , 894*36401Ssklower E_TP_NO_CR_ON_NC, ts_inv_dref, respond, 895*36401Ssklower (1 + 2 + (caddr_t)&hdr->_tpduf - (caddr_t)hdr)) 896*36401Ssklower #else 897*36401Ssklower printf("tp_input(): X25 NOT CONFIGURED!!\n"); 898*36401Ssklower #endif NARGOXTWENTYFIVE > 0 899*36401Ssklower 900*36401Ssklower } else { 901*36401Ssklower 902*36401Ssklower CHECK( ((int)dref <= 0 || dref >= N_TPREF) , 903*36401Ssklower E_TP_MISM_REFS,ts_inv_dref, respond, 904*36401Ssklower (1 + 2 + (caddr_t)&hdr->_tpduf - (caddr_t)hdr)) 905*36401Ssklower CHECK( ((tpcb = tp_ref[dref].tpr_pcb ) == (struct tp_pcb *) 0 ), 906*36401Ssklower E_TP_MISM_REFS,ts_inv_dref, respond, 907*36401Ssklower (1 + 2 + (caddr_t)&hdr->_tpduf - (caddr_t)hdr)) 908*36401Ssklower CHECK( (tpcb->tp_refp->tpr_state == REF_FREE), 909*36401Ssklower E_TP_MISM_REFS,ts_inv_dref, respond, 910*36401Ssklower (1 + 2 + (caddr_t)&hdr->_tpduf - (caddr_t)hdr)) 911*36401Ssklower } 912*36401Ssklower 913*36401Ssklower IFDEBUG(D_TPINPUT) 914*36401Ssklower printf("HAVE A TPCB 2: 0x%x\n", tpcb); 915*36401Ssklower ENDDEBUG 916*36401Ssklower 917*36401Ssklower /* causes a DR to be sent for CC; ER for all else */ 918*36401Ssklower CHECK( (tpcb->tp_refp->tpr_state == REF_FROZEN), 919*36401Ssklower (dutype == CC_TPDU_type?E_TP_NO_SESSION:E_TP_MISM_REFS), 920*36401Ssklower ts_inv_dref, respond, 921*36401Ssklower (1 + 2 + (caddr_t)&hdr->_tpduf - (caddr_t)hdr)) 922*36401Ssklower 923*36401Ssklower IFDEBUG(D_TPINPUT) 924*36401Ssklower printf("state of dref %d ok, tpcb 0x%x\n", dref,tpcb); 925*36401Ssklower ENDDEBUG 926*36401Ssklower /* 927*36401Ssklower * At this point the state of the dref could be 928*36401Ssklower * FROZEN: tpr_pcb == NULL, has ( reference only) timers 929*36401Ssklower * for example, DC may arrive after the close() has detached 930*36401Ssklower * the tpcb (e.g., if user turned off SO_LISTEN option) 931*36401Ssklower * OPENING : a tpcb exists but no timers yet 932*36401Ssklower * OPEN : tpcb exists & timers are outstanding 933*36401Ssklower */ 934*36401Ssklower 935*36401Ssklower dusize = tpcb->tp_tpdusize; 936*36401Ssklower 937*36401Ssklower dutype = hdr->tpdu_type << 8; /* for the switch below */ 938*36401Ssklower 939*36401Ssklower WHILE_OPTIONS(P, hdr, tpcb->tp_xtd_format) /* { */ 940*36401Ssklower 941*36401Ssklower # define caseof(x,y) case (((x)<<8)+(y)) 942*36401Ssklower switch( dutype | vbptr(P)->tpv_code ) { 943*36401Ssklower 944*36401Ssklower caseof( CC_TPDU_type, TPP_addl_opt ): 945*36401Ssklower /* not in class 0; 1 octet */ 946*36401Ssklower vb_getval(P, u_char, addlopt); 947*36401Ssklower break; 948*36401Ssklower caseof( CC_TPDU_type, TPP_tpdu_size ): 949*36401Ssklower vb_getval(P, u_char, dusize); 950*36401Ssklower CHECK( (dusize < TP_MIN_TPDUSIZE || dusize > 951*36401Ssklower TP_MAX_TPDUSIZE), E_TP_INV_PVAL, ts_inv_pval, respond, 952*36401Ssklower (1 + (caddr_t)&vbptr(P)->tpv_val - P) ) 953*36401Ssklower IFDEBUG(D_TPINPUT) 954*36401Ssklower printf("CC dusize 0x%x\n", dusize); 955*36401Ssklower ENDDEBUG 956*36401Ssklower break; 957*36401Ssklower caseof( CC_TPDU_type, TPP_calling_sufx): 958*36401Ssklower IFDEBUG(D_TPINPUT) 959*36401Ssklower printf("CC calling (local) sufxlen 0x%x\n", lsufxlen); 960*36401Ssklower ENDDEBUG 961*36401Ssklower lsufxloc = (caddr_t) &vbptr(P)->tpv_val; 962*36401Ssklower lsufxlen = vbptr(P)->tpv_len; 963*36401Ssklower break; 964*36401Ssklower caseof( CC_TPDU_type, TPP_acktime ): 965*36401Ssklower /* class 4 only, 2 octets */ 966*36401Ssklower vb_getval(P, u_short, acktime); 967*36401Ssklower acktime = acktime/500; /* convert to slowtimo ticks */ 968*36401Ssklower if( (short)acktime <=0 ) 969*36401Ssklower acktime = 2; 970*36401Ssklower break; 971*36401Ssklower caseof( CC_TPDU_type, TPP_called_sufx): 972*36401Ssklower fsufxloc = (caddr_t) &vbptr(P)->tpv_val; 973*36401Ssklower fsufxlen = vbptr(P)->tpv_len; 974*36401Ssklower IFDEBUG(D_TPINPUT) 975*36401Ssklower printf("CC called (foreign) sufx len %d\n", fsufxlen); 976*36401Ssklower ENDDEBUG 977*36401Ssklower break; 978*36401Ssklower 979*36401Ssklower caseof( CC_TPDU_type, TPP_checksum): 980*36401Ssklower caseof( DR_TPDU_type, TPP_checksum): 981*36401Ssklower caseof( DT_TPDU_type, TPP_checksum): 982*36401Ssklower caseof( XPD_TPDU_type, TPP_checksum): 983*36401Ssklower if( tpcb->tp_use_checksum ) { 984*36401Ssklower CHECK( iso_check_csum(m, tpdu_len), 985*36401Ssklower E_TP_INV_PVAL, ts_bad_csum, discard, 0) 986*36401Ssklower } 987*36401Ssklower break; 988*36401Ssklower 989*36401Ssklower /* this is different from the above because in the context 990*36401Ssklower * of concat/ sep tpdu_len might not be the same as hdr len 991*36401Ssklower */ 992*36401Ssklower caseof( AK_TPDU_type, TPP_checksum): 993*36401Ssklower caseof( XAK_TPDU_type, TPP_checksum): 994*36401Ssklower caseof( DC_TPDU_type, TPP_checksum): 995*36401Ssklower if( tpcb->tp_use_checksum ) { 996*36401Ssklower CHECK( iso_check_csum(m, hdr->tpdu_li + 1), 997*36401Ssklower E_TP_INV_PVAL, ts_bad_csum, discard, 0) 998*36401Ssklower } 999*36401Ssklower break; 1000*36401Ssklower #ifdef notdef 1001*36401Ssklower caseof( DR_TPDU_type, TPP_addl_info ): 1002*36401Ssklower /* ignore - its length and meaning are 1003*36401Ssklower * user defined and there's no way 1004*36401Ssklower * to pass this info to the user anyway 1005*36401Ssklower */ 1006*36401Ssklower break; 1007*36401Ssklower #endif notdef 1008*36401Ssklower 1009*36401Ssklower caseof( AK_TPDU_type, TPP_subseq ): 1010*36401Ssklower /* used after reduction of window */ 1011*36401Ssklower vb_getval(P, u_short, subseq); 1012*36401Ssklower subseq = ntohs(subseq); 1013*36401Ssklower IFDEBUG(D_ACKRECV) 1014*36401Ssklower printf("AK Subsequence # 0x%x\n", subseq); 1015*36401Ssklower ENDDEBUG 1016*36401Ssklower break; 1017*36401Ssklower 1018*36401Ssklower caseof( AK_TPDU_type, TPP_flow_cntl_conf ): 1019*36401Ssklower { 1020*36401Ssklower u_int ylwe; 1021*36401Ssklower u_short ysubseq, ycredit; 1022*36401Ssklower 1023*36401Ssklower fcc_present = TRUE; 1024*36401Ssklower vb_getval(P, u_int, ylwe); 1025*36401Ssklower vb_getval(P, u_short, ysubseq); 1026*36401Ssklower vb_getval(P, u_short, ycredit); 1027*36401Ssklower ylwe = ntohl(ylwe); 1028*36401Ssklower ysubseq = ntohs(ysubseq); 1029*36401Ssklower ycredit = ntohs(ycredit); 1030*36401Ssklower IFDEBUG(D_ACKRECV) 1031*36401Ssklower printf("AK FCC lwe 0x%x, subseq 0x%x, cdt 0x%x\n", 1032*36401Ssklower ylwe, ysubseq, ycredit); 1033*36401Ssklower ENDDEBUG 1034*36401Ssklower } 1035*36401Ssklower break; 1036*36401Ssklower 1037*36401Ssklower default: 1038*36401Ssklower IFDEBUG(D_TPINPUT) 1039*36401Ssklower printf("param ignored dutype 0x%x, code 0x%x\n", 1040*36401Ssklower dutype, vbptr(P)->tpv_code); 1041*36401Ssklower ENDDEBUG 1042*36401Ssklower IFTRACE(D_TPINPUT) 1043*36401Ssklower tptrace(TPPTmisc, "param ignored dutype code ", 1044*36401Ssklower dutype, vbptr(P)->tpv_code ,0,0); 1045*36401Ssklower ENDTRACE 1046*36401Ssklower IncStat(ts_param_ignored); 1047*36401Ssklower break; 1048*36401Ssklower #undef caseof 1049*36401Ssklower } 1050*36401Ssklower /* } */ END_WHILE_OPTIONS(P) 1051*36401Ssklower 1052*36401Ssklower /* NOTE: the variable dutype has been shifted left! */ 1053*36401Ssklower 1054*36401Ssklower switch( hdr->tpdu_type ) { 1055*36401Ssklower case CC_TPDU_type: 1056*36401Ssklower /* If CC comes back with an unacceptable class 1057*36401Ssklower * respond with a DR or ER 1058*36401Ssklower */ 1059*36401Ssklower 1060*36401Ssklower opt = hdr->tpdu_CCoptions; /* 1 byte */ 1061*36401Ssklower 1062*36401Ssklower { 1063*36401Ssklower tpp = tpcb->_tp_param; 1064*36401Ssklower tpp.p_class = (1<<hdr->tpdu_CCclass); 1065*36401Ssklower tpp.p_tpdusize = dusize; 1066*36401Ssklower tpp.p_dont_change_params = 0; 1067*36401Ssklower tpp.p_xtd_format = (opt & TPO_XTD_FMT) == TPO_XTD_FMT; 1068*36401Ssklower tpp.p_xpd_service = (addlopt & TPAO_USE_TXPD) == TPAO_USE_TXPD; 1069*36401Ssklower tpp.p_use_checksum = (addlopt & TPAO_NO_CSUM) == 0; 1070*36401Ssklower #ifdef notdef 1071*36401Ssklower tpp.p_use_efc = (opt & TPO_USE_EFC) == TPO_USE_EFC; 1072*36401Ssklower tpp.p_use_nxpd = (addlopt & TPAO_USE_NXPD) == TPAO_USE_NXPD; 1073*36401Ssklower tpp.p_use_rcc = (addlopt & TPAO_USE_RCC) == TPAO_USE_RCC; 1074*36401Ssklower #endif notdef 1075*36401Ssklower 1076*36401Ssklower CHECK( 1077*36401Ssklower tp_consistency(tpcb, TP_FORCE, &tpp) != 0, 1078*36401Ssklower E_TP_NEGOT_FAILED, ts_negotfailed, respond, 1079*36401Ssklower (1 + 2 + (caddr_t)&hdr->_tpdufr.CRCC - (caddr_t)hdr) 1080*36401Ssklower /* ^ more or less the location of class */ 1081*36401Ssklower ) 1082*36401Ssklower IFTRACE(D_CONN) 1083*36401Ssklower tptrace(TPPTmisc, 1084*36401Ssklower "after 1 consist class, out, tpconsout", 1085*36401Ssklower tpcb->tp_class, dgout_routine, tpcons_output, 0 1086*36401Ssklower ); 1087*36401Ssklower ENDTRACE 1088*36401Ssklower CHECK( 1089*36401Ssklower ((class_to_use == TP_CLASS_0)&& 1090*36401Ssklower (dgout_routine != tpcons_output)), 1091*36401Ssklower E_TP_NEGOT_FAILED, ts_negotfailed, respond, 1092*36401Ssklower (1 + 2 + (caddr_t)&hdr->_tpdufr.CRCC - (caddr_t)hdr) 1093*36401Ssklower /* ^ more or less the location of class */ 1094*36401Ssklower ) 1095*36401Ssklower } 1096*36401Ssklower if( ! tpcb->tp_use_checksum) 1097*36401Ssklower IncStat(ts_csum_off); 1098*36401Ssklower if(tpcb->tp_xpd_service) 1099*36401Ssklower IncStat(ts_use_txpd); 1100*36401Ssklower if(tpcb->tp_xtd_format) 1101*36401Ssklower IncStat(ts_xtd_fmt); 1102*36401Ssklower 1103*36401Ssklower IFTRACE(D_CONN) 1104*36401Ssklower tptrace(TPPTmisc, "after CC class flags dusize CCclass", 1105*36401Ssklower tpcb->tp_class, tpcb->tp_flags, tpcb->tp_tpdusize, 1106*36401Ssklower hdr->tpdu_CCclass); 1107*36401Ssklower ENDTRACE 1108*36401Ssklower 1109*36401Ssklower /* 1110*36401Ssklower * Get the maximum transmission unit from the lower layer(s) 1111*36401Ssklower * so we can decide how large a TPDU size to negotiate. 1112*36401Ssklower * It would be nice if the arguments to this 1113*36401Ssklower * were more reasonable. 1114*36401Ssklower */ 1115*36401Ssklower (tpcb->tp_nlproto->nlp_mtu)(tpcb->tp_sock, tpcb->tp_sock->so_pcb, 1116*36401Ssklower &tpcb->tp_l_tpdusize, &tpcb->tp_tpdusize, 0); 1117*36401Ssklower 1118*36401Ssklower #ifdef CONS 1119*36401Ssklower /* Could be that this CC came in on a NEW vc, in which case 1120*36401Ssklower * we have to confirm it. 1121*36401Ssklower */ 1122*36401Ssklower if( cons_channel ) 1123*36401Ssklower cons_netcmd( CONN_CONFIRM, tpcb->tp_npcb, cons_channel, 1124*36401Ssklower tpcb->tp_class == TP_CLASS_4); 1125*36401Ssklower #endif CONS 1126*36401Ssklower 1127*36401Ssklower tpcb->tp_peer_acktime = acktime; 1128*36401Ssklower 1129*36401Ssklower /* if called or calling suffices appeared on the CC, 1130*36401Ssklower * they'd better jive with what's in the pcb 1131*36401Ssklower */ 1132*36401Ssklower if( fsufxlen ) { 1133*36401Ssklower CHECK( ((tpcb->tp_fsuffixlen != fsufxlen) || 1134*36401Ssklower bcmp(fsufxloc, tpcb->tp_fsuffix, fsufxlen)), 1135*36401Ssklower E_TP_INV_PVAL,ts_inv_sufx, respond, 1136*36401Ssklower (1+fsufxloc - (caddr_t)hdr)) 1137*36401Ssklower } 1138*36401Ssklower if( lsufxlen ) { 1139*36401Ssklower CHECK( ((tpcb->tp_lsuffixlen != lsufxlen) || 1140*36401Ssklower bcmp(lsufxloc, tpcb->tp_lsuffix, lsufxlen)), 1141*36401Ssklower E_TP_INV_PVAL,ts_inv_sufx, respond, 1142*36401Ssklower (1+lsufxloc - (caddr_t)hdr)) 1143*36401Ssklower } 1144*36401Ssklower 1145*36401Ssklower #ifdef notdef 1146*36401Ssklower e.ATTR(CC_TPDU).e_sref = (u_short)hdr->tpdu_CCsref; 1147*36401Ssklower #else 1148*36401Ssklower e.ATTR(CC_TPDU).e_sref = sref; 1149*36401Ssklower #endif notdef 1150*36401Ssklower e.ATTR(CC_TPDU).e_cdt = hdr->tpdu_CCcdt; 1151*36401Ssklower takes_data = TRUE; 1152*36401Ssklower e.ev_number = CC_TPDU; 1153*36401Ssklower IncStat(ts_CC_rcvd); 1154*36401Ssklower break; 1155*36401Ssklower 1156*36401Ssklower case DC_TPDU_type: 1157*36401Ssklower #ifdef notdef 1158*36401Ssklower if (hdr->tpdu_DCsref != tpcb->tp_fref) 1159*36401Ssklower printf("INPUT: inv sufx DCsref 0x%x, tp_fref 0x%x\n", 1160*36401Ssklower hdr->tpdu_DCsref, tpcb->tp_fref); 1161*36401Ssklower #else 1162*36401Ssklower if (sref != tpcb->tp_fref) 1163*36401Ssklower printf("INPUT: inv sufx DCsref 0x%x, tp_fref 0x%x\n", 1164*36401Ssklower sref, tpcb->tp_fref); 1165*36401Ssklower #endif notdef 1166*36401Ssklower 1167*36401Ssklower #ifdef notdef 1168*36401Ssklower CHECK( (hdr->tpdu_DCsref != tpcb->tp_fref), 1169*36401Ssklower E_TP_MISM_REFS, ts_inv_sufx, respond, 1170*36401Ssklower (1 + (caddr_t)&hdr->tpdu_DCsref - (caddr_t)hdr)) 1171*36401Ssklower #else 1172*36401Ssklower CHECK( (sref != tpcb->tp_fref), 1173*36401Ssklower E_TP_MISM_REFS, ts_inv_sufx, respond, 1174*36401Ssklower (1 + (caddr_t)&hdr->tpdu_DCsref - (caddr_t)hdr)) 1175*36401Ssklower #endif notdef 1176*36401Ssklower e.ev_number = DC_TPDU; 1177*36401Ssklower IncStat(ts_DC_rcvd); 1178*36401Ssklower break; 1179*36401Ssklower 1180*36401Ssklower case DR_TPDU_type: 1181*36401Ssklower IFTRACE(D_TPINPUT) 1182*36401Ssklower tptrace(TPPTmisc, "DR recvd", hdr->tpdu_DRreason, 0, 0, 0); 1183*36401Ssklower ENDTRACE 1184*36401Ssklower #ifdef vax 1185*36401Ssklower if(sref != tpcb->tp_fref) 1186*36401Ssklower printf("INPUT: inv sufx DRsref 0x%x tp_fref 0x%x\n", 1187*36401Ssklower sref, tpcb->tp_fref); 1188*36401Ssklower 1189*36401Ssklower CHECK( (sref != tpcb->tp_fref), 1190*36401Ssklower E_TP_MISM_REFS,ts_inv_sufx, respond, 1191*36401Ssklower (1 + (caddr_t)&hdr->tpdu_DRsref - (caddr_t)hdr)) 1192*36401Ssklower 1193*36401Ssklower e.ATTR(DR_TPDU).e_reason = hdr->tpdu_DRreason; 1194*36401Ssklower e.ATTR(DR_TPDU).e_sref = (u_short)sref; 1195*36401Ssklower #else 1196*36401Ssklower if(hdr->tpdu_DRsref != tpcb->tp_fref) 1197*36401Ssklower printf("INPUT: inv sufx DRsref 0x%x tp_fref 0x%x\n", 1198*36401Ssklower hdr->tpdu_DRsref, tpcb->tp_fref); 1199*36401Ssklower 1200*36401Ssklower CHECK( (hdr->tpdu_DRsref != tpcb->tp_fref), 1201*36401Ssklower E_TP_MISM_REFS,ts_inv_sufx, respond, 1202*36401Ssklower (1 + (caddr_t)&hdr->tpdu_DRsref - (caddr_t)hdr)) 1203*36401Ssklower 1204*36401Ssklower e.ATTR(DR_TPDU).e_reason = 1205*36401Ssklower hdr->tpdu_DRreason; 1206*36401Ssklower e.ATTR(DR_TPDU).e_sref = (u_short)hdr->tpdu_DRsref; 1207*36401Ssklower #endif vax 1208*36401Ssklower takes_data = TRUE; 1209*36401Ssklower e.ev_number = DR_TPDU; 1210*36401Ssklower IncStat(ts_DR_rcvd); 1211*36401Ssklower break; 1212*36401Ssklower 1213*36401Ssklower case ER_TPDU_type: 1214*36401Ssklower IFTRACE(D_TPINPUT) 1215*36401Ssklower tptrace(TPPTmisc, "ER recvd", hdr->tpdu_ERreason,0,0,0); 1216*36401Ssklower ENDTRACE 1217*36401Ssklower e.ev_number = ER_TPDU; 1218*36401Ssklower e.ATTR(ER_TPDU).e_reason = hdr->tpdu_ERreason; 1219*36401Ssklower IncStat(ts_ER_rcvd); 1220*36401Ssklower break; 1221*36401Ssklower 1222*36401Ssklower case AK_TPDU_type: 1223*36401Ssklower 1224*36401Ssklower e.ATTR(AK_TPDU).e_subseq = subseq; 1225*36401Ssklower e.ATTR(AK_TPDU).e_fcc_present = fcc_present; 1226*36401Ssklower 1227*36401Ssklower if (tpcb->tp_xtd_format) { 1228*36401Ssklower #ifdef BYTE_ORDER 1229*36401Ssklower union seq_type seqeotX; 1230*36401Ssklower 1231*36401Ssklower seqeotX.s_seqeot = ntohl(hdr->tpdu_seqeotX); 1232*36401Ssklower e.ATTR(AK_TPDU).e_seq = seqeotX.s_seq; 1233*36401Ssklower e.ATTR(AK_TPDU).e_cdt = ntohs(hdr->tpdu_AKcdtX); 1234*36401Ssklower #else 1235*36401Ssklower e.ATTR(AK_TPDU).e_cdt = hdr->tpdu_AKcdtX; 1236*36401Ssklower e.ATTR(AK_TPDU).e_seq = hdr->tpdu_AKseqX; 1237*36401Ssklower #endif BYTE_ORDER 1238*36401Ssklower } else { 1239*36401Ssklower e.ATTR(AK_TPDU).e_cdt = hdr->tpdu_AKcdt; 1240*36401Ssklower e.ATTR(AK_TPDU).e_seq = hdr->tpdu_AKseq; 1241*36401Ssklower } 1242*36401Ssklower IFTRACE(D_TPINPUT) 1243*36401Ssklower tptrace(TPPTmisc, "AK recvd seq cdt subseq fcc_pres", 1244*36401Ssklower e.ATTR(AK_TPDU).e_seq, e.ATTR(AK_TPDU).e_cdt, 1245*36401Ssklower subseq, fcc_present); 1246*36401Ssklower ENDTRACE 1247*36401Ssklower 1248*36401Ssklower e.ev_number = AK_TPDU; 1249*36401Ssklower IncStat(ts_AK_rcvd); 1250*36401Ssklower IncPStat(tpcb, tps_AK_rcvd); 1251*36401Ssklower break; 1252*36401Ssklower 1253*36401Ssklower case XAK_TPDU_type: 1254*36401Ssklower if (tpcb->tp_xtd_format) { 1255*36401Ssklower #ifdef BYTE_ORDER 1256*36401Ssklower union seq_type seqeotX; 1257*36401Ssklower 1258*36401Ssklower seqeotX.s_seqeot = ntohl(hdr->tpdu_seqeotX); 1259*36401Ssklower e.ATTR(XAK_TPDU).e_seq = seqeotX.s_seq; 1260*36401Ssklower #else 1261*36401Ssklower e.ATTR(XAK_TPDU).e_seq = hdr->tpdu_XAKseqX; 1262*36401Ssklower #endif BYTE_ORDER 1263*36401Ssklower } else { 1264*36401Ssklower e.ATTR(XAK_TPDU).e_seq = hdr->tpdu_XAKseq; 1265*36401Ssklower } 1266*36401Ssklower e.ev_number = XAK_TPDU; 1267*36401Ssklower IncStat(ts_XAK_rcvd); 1268*36401Ssklower IncPStat(tpcb, tps_XAK_rcvd); 1269*36401Ssklower break; 1270*36401Ssklower 1271*36401Ssklower case XPD_TPDU_type: 1272*36401Ssklower if (tpcb->tp_xtd_format) { 1273*36401Ssklower #ifdef BYTE_ORDER 1274*36401Ssklower union seq_type seqeotX; 1275*36401Ssklower 1276*36401Ssklower seqeotX.s_seqeot = ntohl(hdr->tpdu_seqeotX); 1277*36401Ssklower e.ATTR(XPD_TPDU).e_seq = seqeotX.s_seq; 1278*36401Ssklower #else 1279*36401Ssklower e.ATTR(XPD_TPDU).e_seq = hdr->tpdu_XPDseqX; 1280*36401Ssklower #endif BYTE_ORDER 1281*36401Ssklower } else { 1282*36401Ssklower e.ATTR(XPD_TPDU).e_seq = hdr->tpdu_XPDseq; 1283*36401Ssklower } 1284*36401Ssklower takes_data = TRUE; 1285*36401Ssklower e.ev_number = XPD_TPDU; 1286*36401Ssklower IncStat(ts_XPD_rcvd); 1287*36401Ssklower IncPStat(tpcb, tps_XPD_rcvd); 1288*36401Ssklower break; 1289*36401Ssklower 1290*36401Ssklower case DT_TPDU_type: 1291*36401Ssklower { /* the y option will cause occasional packets to be dropped. 1292*36401Ssklower * A little crude but it works. 1293*36401Ssklower */ 1294*36401Ssklower 1295*36401Ssklower IFDEBUG(D_DROP) 1296*36401Ssklower if(time.tv_usec & 0x4 && hdr->tpdu_DTseq & 0x1) { 1297*36401Ssklower IncStat(ts_ydebug); 1298*36401Ssklower goto discard; 1299*36401Ssklower } 1300*36401Ssklower ENDDEBUG 1301*36401Ssklower } 1302*36401Ssklower if (tpcb->tp_class == TP_CLASS_0) { 1303*36401Ssklower e.ATTR(DT_TPDU).e_seq = 0; /* actually don't care */ 1304*36401Ssklower e.ATTR(DT_TPDU).e_eot = (((struct tp0du *)hdr)->tp0du_eot); 1305*36401Ssklower } else if (tpcb->tp_xtd_format) { 1306*36401Ssklower #ifdef BYTE_ORDER 1307*36401Ssklower union seq_type seqeotX; 1308*36401Ssklower 1309*36401Ssklower seqeotX.s_seqeot = ntohl(hdr->tpdu_seqeotX); 1310*36401Ssklower e.ATTR(DT_TPDU).e_seq = seqeotX.s_seq; 1311*36401Ssklower e.ATTR(DT_TPDU).e_eot = seqeotX.s_eot; 1312*36401Ssklower #else 1313*36401Ssklower e.ATTR(DT_TPDU).e_seq = hdr->tpdu_DTseqX; 1314*36401Ssklower e.ATTR(DT_TPDU).e_eot = hdr->tpdu_DTeotX; 1315*36401Ssklower #endif BYTE_ORDER 1316*36401Ssklower } else { 1317*36401Ssklower e.ATTR(DT_TPDU).e_seq = hdr->tpdu_DTseq; 1318*36401Ssklower e.ATTR(DT_TPDU).e_eot = hdr->tpdu_DTeot; 1319*36401Ssklower } 1320*36401Ssklower if(e.ATTR(DT_TPDU).e_eot) 1321*36401Ssklower IncStat(ts_eot_input); 1322*36401Ssklower takes_data = TRUE; 1323*36401Ssklower e.ev_number = DT_TPDU; 1324*36401Ssklower IncStat(ts_DT_rcvd); 1325*36401Ssklower IncPStat(tpcb, tps_DT_rcvd); 1326*36401Ssklower break; 1327*36401Ssklower 1328*36401Ssklower case GR_TPDU_type: 1329*36401Ssklower tp_indicate(T_DISCONNECT, tpcb, ECONNABORTED); 1330*36401Ssklower /* drop through */ 1331*36401Ssklower default: 1332*36401Ssklower /* this should NEVER happen because there is a 1333*36401Ssklower * check for dutype well above here 1334*36401Ssklower */ 1335*36401Ssklower error = E_TP_INV_TPDU; /* causes an ER */ 1336*36401Ssklower IFDEBUG(D_TPINPUT) 1337*36401Ssklower printf("INVALID dutype 0x%x\n", hdr->tpdu_type); 1338*36401Ssklower ENDDEBUG 1339*36401Ssklower IncStat(ts_inv_dutype); 1340*36401Ssklower goto respond; 1341*36401Ssklower } 1342*36401Ssklower } 1343*36401Ssklower 1344*36401Ssklower /* peel off the tp header; 1345*36401Ssklower * remember that the du_li doesn't count itself. 1346*36401Ssklower * This may leave us w/ an empty mbuf at the front of a chain. 1347*36401Ssklower * We can't just throw away the empty mbuf because hdr still points 1348*36401Ssklower * into the mbuf's data area and we're still using hdr (the tpdu header) 1349*36401Ssklower */ 1350*36401Ssklower m->m_len -= ((int)hdr->tpdu_li + 1); 1351*36401Ssklower m->m_off += ((int)hdr->tpdu_li + 1); 1352*36401Ssklower 1353*36401Ssklower if(takes_data) { 1354*36401Ssklower register int max; 1355*36401Ssklower 1356*36401Ssklower switch( hdr->tpdu_type ) { 1357*36401Ssklower case CR_TPDU_type: 1358*36401Ssklower case CC_TPDU_type: 1359*36401Ssklower case DR_TPDU_type: 1360*36401Ssklower case XPD_TPDU_type: 1361*36401Ssklower case DT_TPDU_type: 1362*36401Ssklower e.ATTR(DT_TPDU).e_datalen = tpdu_len - hdr->tpdu_li - 1; 1363*36401Ssklower max = tpdu_info[ hdr->tpdu_type ] [TP_MAX_DATA_INDEX]; 1364*36401Ssklower CHECK( (max && e.ATTR(DT_TPDU).e_datalen > max), 1365*36401Ssklower E_TP_LENGTH_INVAL,ts_inv_length, respond, (max + hdr->tpdu_li + 1)) 1366*36401Ssklower 1367*36401Ssklower e.ATTR(DT_TPDU).e_data = m; 1368*36401Ssklower break; 1369*36401Ssklower 1370*36401Ssklower default: 1371*36401Ssklower printf( 1372*36401Ssklower "ERROR in tp_input! hdr->tpdu_type 0x%x takes_data 0x%x m 0x%x\n", 1373*36401Ssklower hdr->tpdu_type, takes_data, m); 1374*36401Ssklower break; 1375*36401Ssklower } 1376*36401Ssklower /* prevent m_freem() after tp_driver() from throwing it all away */ 1377*36401Ssklower m = MNULL; 1378*36401Ssklower } 1379*36401Ssklower 1380*36401Ssklower IncStat(ts_tpdu_rcvd); 1381*36401Ssklower 1382*36401Ssklower IFDEBUG(D_TPINPUT) 1383*36401Ssklower printf( "tp_input: before driver, state 0x%x event 0x%x m 0x%x", 1384*36401Ssklower tpcb->tp_state, e.ev_number, m ); 1385*36401Ssklower printf(" e.e_data 0x%x\n", e.ATTR(DT_TPDU).e_data); 1386*36401Ssklower printf("takes_data 0x%x m_len 0x%x, tpdu_len 0x%x\n", 1387*36401Ssklower takes_data, (m==MNULL)?0:m->m_len, tpdu_len); 1388*36401Ssklower ENDDEBUG 1389*36401Ssklower 1390*36401Ssklower if( tpcb->tp_decbit != 0 ) /* unsigned 4 bits */ 1391*36401Ssklower tpcb->tp_decbit --; 1392*36401Ssklower 1393*36401Ssklower error = tp_driver(tpcb, &e); 1394*36401Ssklower 1395*36401Ssklower ASSERT(tpcb != (struct tp_pcb *)0); 1396*36401Ssklower ASSERT(tpcb->tp_sock != (struct socket *)0); 1397*36401Ssklower if( tpcb->tp_sock->so_error == 0 ) 1398*36401Ssklower tpcb->tp_sock->so_error = error; 1399*36401Ssklower 1400*36401Ssklower /* Kludge to keep the state tables under control (adding 1401*36401Ssklower * data on connect & disconnect & freeing the mbuf containing 1402*36401Ssklower * the data would have exploded the tables and made a big mess ). 1403*36401Ssklower */ 1404*36401Ssklower switch(e.ev_number) { 1405*36401Ssklower case CC_TPDU: 1406*36401Ssklower case DR_TPDU: 1407*36401Ssklower case CR_TPDU: 1408*36401Ssklower m = e.ATTR(CC_TPDU).e_data; /* same field for all three dutypes */ 1409*36401Ssklower IFDEBUG(D_TPINPUT) 1410*36401Ssklower printf("after driver, restoring m to 0x%x, takes_data 0x%x\n", 1411*36401Ssklower m, takes_data); 1412*36401Ssklower ENDDEBUG 1413*36401Ssklower break; 1414*36401Ssklower default: 1415*36401Ssklower break; 1416*36401Ssklower } 1417*36401Ssklower /* Concatenated sequences are terminated by any tpdu that 1418*36401Ssklower * carries data: CR, CC, DT, XPD, DR. 1419*36401Ssklower * All other tpdu types may be concatenated: AK, XAK, DC, ER. 1420*36401Ssklower */ 1421*36401Ssklower 1422*36401Ssklower separate: 1423*36401Ssklower if ( takes_data == 0 ) { 1424*36401Ssklower ASSERT( m != MNULL ); 1425*36401Ssklower /* 1426*36401Ssklower * we already peeled off the prev. tp header so 1427*36401Ssklower * we can just pull up some more and repeat 1428*36401Ssklower */ 1429*36401Ssklower 1430*36401Ssklower IFDEBUG(D_TPINPUT) 1431*36401Ssklower hdr = mtod(m, struct tpdu *); 1432*36401Ssklower printf("tp_input @ separate: hdr 0x%x size %d m 0x%x\n", 1433*36401Ssklower hdr, (int) hdr->tpdu_li + 1, m); 1434*36401Ssklower dump_mbuf(m, "tp_input after driver, at separate"); 1435*36401Ssklower ENDDEBUG 1436*36401Ssklower 1437*36401Ssklower if( m = tp_inputprep(m) ) { 1438*36401Ssklower IncStat(ts_concat_rcvd); 1439*36401Ssklower goto again; 1440*36401Ssklower } 1441*36401Ssklower } 1442*36401Ssklower if ( m != MNULL ) { 1443*36401Ssklower IFDEBUG(D_TPINPUT) 1444*36401Ssklower printf("tp_input : m_freem(0x%x)\n", m); 1445*36401Ssklower ENDDEBUG 1446*36401Ssklower m_freem(m); 1447*36401Ssklower IFDEBUG(D_TPINPUT) 1448*36401Ssklower printf("tp_input : after m_freem 0x%x\n", m); 1449*36401Ssklower ENDDEBUG 1450*36401Ssklower } 1451*36401Ssklower return (ProtoHook) tpcb; 1452*36401Ssklower 1453*36401Ssklower discard: 1454*36401Ssklower /* class 4: drop the tpdu */ 1455*36401Ssklower /* class 2,0: Should drop the net connection, if you can figure out 1456*36401Ssklower * to which connection it applies 1457*36401Ssklower */ 1458*36401Ssklower IFDEBUG(D_TPINPUT) 1459*36401Ssklower printf("tp_input DISCARD\n"); 1460*36401Ssklower ENDDEBUG 1461*36401Ssklower IFTRACE(D_TPINPUT) 1462*36401Ssklower tptrace(TPPTmisc, "tp_input DISCARD m", m,0,0,0); 1463*36401Ssklower ENDTRACE 1464*36401Ssklower m_freem(m); 1465*36401Ssklower IncStat(ts_recv_drop); 1466*36401Ssklower return (ProtoHook)0; 1467*36401Ssklower 1468*36401Ssklower respond: 1469*36401Ssklower IFDEBUG(D_ERROR_EMIT) 1470*36401Ssklower printf("RESPOND: error 0x%x, errloc 0x%x\n", error, errloc); 1471*36401Ssklower ENDDEBUG 1472*36401Ssklower IFTRACE(D_TPINPUT) 1473*36401Ssklower tptrace(TPPTmisc, "tp_input RESPOND m error sref", m,error,sref,0); 1474*36401Ssklower ENDTRACE 1475*36401Ssklower if( sref == 0 ) 1476*36401Ssklower goto discard; 1477*36401Ssklower (void) tp_error_emit(error, sref, faddr, laddr, 1478*36401Ssklower m, errloc, tpcb, cons_channel, dgout_routine 1479*36401Ssklower ); 1480*36401Ssklower IFDEBUG(D_ERROR_EMIT) 1481*36401Ssklower printf("tp_input after error_emit\n"); 1482*36401Ssklower ENDDEBUG 1483*36401Ssklower 1484*36401Ssklower #ifdef lint 1485*36401Ssklower printf("",sref,opt); 1486*36401Ssklower #endif lint 1487*36401Ssklower IncStat(ts_recv_drop); 1488*36401Ssklower return (ProtoHook)0; 1489*36401Ssklower } 1490*36401Ssklower 1491*36401Ssklower 1492*36401Ssklower /* 1493*36401Ssklower * NAME: tp_headersize() 1494*36401Ssklower * 1495*36401Ssklower * CALLED FROM: 1496*36401Ssklower * tp_emit() and tp_sbsend() 1497*36401Ssklower * TP needs to know the header size so it can figure out how 1498*36401Ssklower * much data to put in each tpdu. 1499*36401Ssklower * 1500*36401Ssklower * FUNCTION, ARGUMENTS, and RETURN VALUE: 1501*36401Ssklower * For a given connection, represented by (tpcb), and 1502*36401Ssklower * tpdu type (dutype), return the size of a tp header. 1503*36401Ssklower * 1504*36401Ssklower * RETURNS: the expected size of the heade in bytesr 1505*36401Ssklower * 1506*36401Ssklower * SIDE EFFECTS: 1507*36401Ssklower * 1508*36401Ssklower * NOTES: It would be nice if it got the network header size as well. 1509*36401Ssklower */ 1510*36401Ssklower int 1511*36401Ssklower tp_headersize(dutype, tpcb) 1512*36401Ssklower int dutype; 1513*36401Ssklower struct tp_pcb *tpcb; 1514*36401Ssklower { 1515*36401Ssklower register int size = 0; 1516*36401Ssklower 1517*36401Ssklower IFTRACE(D_CONN) 1518*36401Ssklower tptrace(TPPTmisc, "tp_headersize dutype class xtd_format", 1519*36401Ssklower dutype, tpcb->tp_class, tpcb->tp_xtd_format, 0); 1520*36401Ssklower ENDTRACE 1521*36401Ssklower if( !( (tpcb->tp_class == TP_CLASS_0) || 1522*36401Ssklower (tpcb->tp_class == TP_CLASS_4) || 1523*36401Ssklower (dutype == DR_TPDU_type) || 1524*36401Ssklower (dutype == CR_TPDU_type) )) { 1525*36401Ssklower printf("tp_headersize:dutype 0x%x, class 0x%x", 1526*36401Ssklower dutype, tpcb->tp_class); 1527*36401Ssklower /* TODO: identify this and GET RID OF IT */ 1528*36401Ssklower } 1529*36401Ssklower ASSERT( (tpcb->tp_class == TP_CLASS_0) || 1530*36401Ssklower (tpcb->tp_class == TP_CLASS_4) || 1531*36401Ssklower (dutype == DR_TPDU_type) || 1532*36401Ssklower (dutype == CR_TPDU_type) ); 1533*36401Ssklower 1534*36401Ssklower if( tpcb->tp_class == TP_CLASS_0 ) { 1535*36401Ssklower size = tpdu_info[ dutype ] [TP_LEN_CLASS_0_INDEX]; 1536*36401Ssklower } else { 1537*36401Ssklower size = tpdu_info[ dutype ] [tpcb->tp_xtd_format]; 1538*36401Ssklower } 1539*36401Ssklower return size; 1540*36401Ssklower /* caller must get network level header size separately */ 1541*36401Ssklower } 1542