|
|
1.1.1.3 ! root 1: /* tp_driver.c,v 1.2 1993/05/20 05:27:34 cgd Exp */ ! 2: 1.1 root 3: #define _XEBEC_PG static 4: 5: #include "tp_states.h" 6: 7: static struct act_ent { 8: int a_newstate; 9: int a_action; 10: } statetable[] = { {0,0}, 11: #include "tp_states.init" 12: }; 13: 14: #include "param.h" 15: #include "socket.h" 16: #include "socketvar.h" 17: #include "protosw.h" 18: #include "mbuf.h" 19: #include "time.h" 20: #include "errno.h" 21: #include "../netiso/tp_param.h" 22: #include "../netiso/tp_stat.h" 23: #include "../netiso/tp_pcb.h" 24: #include "../netiso/tp_tpdu.h" 25: #include "../netiso/argo_debug.h" 26: #include "../netiso/tp_trace.h" 27: #include "../netiso/iso_errno.h" 28: #include "../netiso/tp_seq.h" 29: #include "../netiso/cons.h" 30: 31: #define DRIVERTRACE TPPTdriver 32: #define sbwakeup(sb) sowakeup(p->tp_sock, sb); 33: #define MCPY(d, w) (d ? m_copym(d, 0, (int)M_COPYALL, w): 0) 34: 35: static trick_hc = 1; 36: 37: int tp_emit(), 38: tp_goodack(), tp_goodXack(), 39: tp_stash() 40: ; 41: void tp_indicate(), tp_getoptions(), 42: tp_soisdisconnecting(), tp_soisdisconnected(), 43: tp_recycle_tsuffix(), 44: tp_etimeout(), tp_euntimeout(), 45: tp_euntimeout_lss(), tp_ctimeout(), 46: tp_cuntimeout(), tp_ctimeout_MIN(), 47: tp_freeref(), tp_detach(), 48: tp0_stash(), tp0_send(), 49: tp_netcmd(), tp_send() 50: ; 51: 52: typedef struct tp_pcb tpcb_struct; 53: 54: 55: 56: typedef tpcb_struct tp_PCB_; 57: 58: #include "tp_events.h" 59: 60: _XEBEC_PG int _Xebec_action(a,e,p) 61: int a; 62: struct tp_event *e; 63: tp_PCB_ *p; 64: { 65: switch(a) { 66: case -1: return tp_protocol_error(e,p); 67: case 0x1: 68: { 69: (void) tp_emit(DC_TPDU_type, p, 0, 0, MNULL); 70: } 71: break; 72: case 0x2: 73: { 74: # ifdef TP_DEBUG 75: if( e->ev_number != AK_TPDU ) 76: printf("TPDU 0x%x in REFWAIT!!!!\n", e->ev_number); 77: # endif TP_DEBUG 78: } 79: break; 80: case 0x3: 81: { 82: /* oh, man is this grotesque or what? */ 83: (void) tp_goodack(p, e->ev_union.EV_AK_TPDU.e_cdt, e->ev_union.EV_AK_TPDU.e_seq, e->ev_union.EV_AK_TPDU.e_subseq); 84: /* but it's necessary because this pseudo-ack may happen 85: * before the CC arrives, but we HAVE to adjust the 86: * snduna as a result of the ack, WHENEVER it arrives 87: */ 88: } 89: break; 90: case 0x4: 91: { 92: tp_detach(p); 93: } 94: break; 95: case 0x5: 96: { 97: p->tp_refp->tpr_state = REF_OPEN; /* has timers ??? */ 98: } 99: break; 100: case 0x6: 101: { 102: IFTRACE(D_CONN) 103: tptrace(TPPTmisc, "CR datalen data", e->ev_union.EV_CR_TPDU.e_datalen, e->ev_union.EV_CR_TPDU.e_data,0,0); 104: ENDTRACE 105: IFDEBUG(D_CONN) 106: printf("CR datalen 0x%x data 0x%x", e->ev_union.EV_CR_TPDU.e_datalen, e->ev_union.EV_CR_TPDU.e_data); 107: ENDDEBUG 108: p->tp_refp->tpr_state = REF_OPEN; /* has timers */ 109: p->tp_fcredit = e->ev_union.EV_CR_TPDU.e_cdt; 110: 111: if (e->ev_union.EV_CR_TPDU.e_datalen > 0) { 112: /* n/a for class 0 */ 113: ASSERT(p->tp_Xrcv.sb_cc == 0); 114: sbappendrecord(&p->tp_Xrcv, e->ev_union.EV_CR_TPDU.e_data); 115: e->ev_union.EV_CR_TPDU.e_data = MNULL; 116: } 117: } 118: break; 119: case 0x7: 120: { 121: IncStat(ts_tp0_conn); 122: IFTRACE(D_CONN) 123: tptrace(TPPTmisc, "Confiming", p, 0,0,0); 124: ENDTRACE 125: IFDEBUG(D_CONN) 126: printf("Confirming connection: p" ); 127: ENDDEBUG 128: soisconnected(p->tp_sock); 129: (void) tp_emit(CC_TPDU_type, p, 0,0, MNULL) ; 130: p->tp_fcredit = 1; 131: } 132: break; 133: case 0x8: 134: { 135: IncStat(ts_tp4_conn); /* even though not quite open */ 136: IFTRACE(D_CONN) 137: tptrace(TPPTmisc, "Confiming", p, 0,0,0); 138: ENDTRACE 139: IFDEBUG(D_CONN) 140: printf("Confirming connection: p" ); 141: ENDDEBUG 142: soisconnecting(p->tp_sock); 143: if ((p->tp_rx_strat & TPRX_FASTSTART) && (p->tp_fcredit > 0)) 144: p->tp_cong_win = p->tp_fcredit; 145: p->tp_retrans = p->tp_Nretrans; 146: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_cc_ticks); 147: } 148: break; 149: case 0x9: 150: { 151: register struct tp_ref *r = p->tp_refp; 152: 153: IFDEBUG(D_CONN) 154: printf("event: CR_TPDU emit CC failed done " ); 155: ENDDEBUG 156: soisdisconnected(p->tp_sock); 157: tp_recycle_tsuffix( p ); 158: tp_freeref(r); 159: tp_detach(p); 160: } 161: break; 162: case 0xa: 163: { 164: int error; 165: struct mbuf *data = MNULL; 166: 167: IFTRACE(D_CONN) 168: tptrace(TPPTmisc, "T_CONN_req flags ucddata", (int)p->tp_flags, 169: p->tp_ucddata, 0, 0); 170: ENDTRACE 171: data = MCPY(p->tp_ucddata, M_WAIT); 172: if (data) { 173: IFDEBUG(D_CONN) 174: printf("T_CONN_req.trans m_copy cc 0x%x\n", 175: p->tp_ucddata); 176: dump_mbuf(data, "sosnd @ T_CONN_req"); 177: ENDDEBUG 178: } 179: 180: if (error = tp_emit(CR_TPDU_type, p, 0, 0, data) ) 181: return error; /* driver WON'T change state; will return error */ 182: 183: p->tp_refp->tpr_state = REF_OPEN; /* has timers */ 184: if(p->tp_class != TP_CLASS_0) { 185: p->tp_retrans = p->tp_Nretrans; 186: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_cr_ticks); 187: } 188: } 189: break; 190: case 0xb: 191: { 192: sbflush(&p->tp_Xrcv); /* purge non-delivered data data */ 193: if (e->ev_union.EV_DR_TPDU.e_datalen > 0) { 194: sbappendrecord(&p->tp_Xrcv, e->ev_union.EV_DR_TPDU.e_data); 195: e->ev_union.EV_DR_TPDU.e_data = MNULL; 196: } 197: /* must return no error, or disc data and reason can't be read */ 198: tp_indicate(T_DISCONNECT, p, 0); 199: tp_soisdisconnected(p); 200: if (p->tp_class != TP_CLASS_0) { 201: if (p->tp_state == TP_OPEN ) { 202: tp_euntimeout(p->tp_refp, TM_data_retrans); /* all */ 203: tp_cuntimeout(p->tp_refp, TM_retrans); 204: tp_cuntimeout(p->tp_refp, TM_inact); 205: tp_cuntimeout(p->tp_refp, TM_sendack); 206: } 207: tp_cuntimeout(p->tp_refp, TM_retrans); 208: if( e->ev_union.EV_DR_TPDU.e_sref != 0 ) 209: (void) tp_emit(DC_TPDU_type, p, 0, 0, MNULL); 210: } 211: } 212: break; 213: case 0xc: 214: { 215: if( e->ev_union.EV_DR_TPDU.e_sref != 0 ) 216: (void) tp_emit(DC_TPDU_type, p, 0, 0, MNULL); 217: /* reference timer already set - reset it to be safe (???) */ 218: tp_euntimeout(p->tp_refp, TM_reference); /* all */ 219: tp_etimeout(p->tp_refp, TM_reference, 0, 0, 0, (int)p->tp_refer_ticks); 220: } 221: break; 222: case 0xd: 223: { 224: tp_cuntimeout(p->tp_refp, TM_retrans); 225: tp_indicate(ER_TPDU, p, e->ev_union.EV_ER_TPDU.e_reason); 226: tp_soisdisconnected(p); 227: } 228: break; 229: case 0xe: 230: { 231: tp_cuntimeout(p->tp_refp, TM_retrans); 232: tp_soisdisconnected(p); 233: } 234: break; 235: case 0xf: 236: { 237: tp_indicate(ER_TPDU, p, e->ev_union.EV_ER_TPDU.e_reason); 238: tp_cuntimeout(p->tp_refp, TM_retrans); 239: tp_soisdisconnected(p); 240: } 241: break; 242: case 0x10: 243: { 244: tp_cuntimeout(p->tp_refp, TM_retrans); 245: tp_soisdisconnected(p); 246: } 247: break; 248: case 0x11: 249: { /* don't ask me why we have to do this - spec says so */ 250: (void) tp_emit(DR_TPDU_type, p, 0, E_TP_NO_SESSION, MNULL); 251: /* don't bother with retransmissions of the DR */ 252: } 253: break; 254: case 0x12: 255: { 256: tp_soisdisconnecting(p->tp_sock); 257: tp_indicate(ER_TPDU, p, e->ev_union.EV_ER_TPDU.e_reason); 258: tp_soisdisconnected(p); 259: tp_netcmd( p, CONN_CLOSE ); 260: } 261: break; 262: case 0x13: 263: { 264: if (p->tp_state == TP_OPEN) { 265: tp_euntimeout(p->tp_refp, TM_data_retrans); /* all */ 266: tp_cuntimeout(p->tp_refp, TM_inact); 267: tp_cuntimeout(p->tp_refp, TM_sendack); 268: } 269: tp_soisdisconnecting(p->tp_sock); 270: tp_indicate(ER_TPDU, p, e->ev_union.EV_ER_TPDU.e_reason); 271: p->tp_retrans = p->tp_Nretrans; 272: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_dr_ticks); 273: (void) tp_emit(DR_TPDU_type, p, 0, E_TP_PROTO_ERR, MNULL); 274: } 275: break; 276: case 0x14: 277: { 278: tp_cuntimeout(p->tp_refp, TM_retrans); 279: IncStat(ts_tp0_conn); 280: p->tp_fcredit = 1; 281: soisconnected(p->tp_sock); 282: } 283: break; 284: case 0x15: 285: { 286: IFDEBUG(D_CONN) 287: printf("trans: CC_TPDU in CRSENT state flags 0x%x\n", 288: (int)p->tp_flags); 289: ENDDEBUG 290: IncStat(ts_tp4_conn); 291: p->tp_fref = e->ev_union.EV_CC_TPDU.e_sref; 292: p->tp_fcredit = e->ev_union.EV_CC_TPDU.e_cdt; 293: p->tp_ackrcvd = 0; 294: if ((p->tp_rx_strat & TPRX_FASTSTART) && (e->ev_union.EV_CC_TPDU.e_cdt > 0)) 295: p->tp_cong_win = e->ev_union.EV_CC_TPDU.e_cdt; 296: tp_getoptions(p); 297: tp_cuntimeout(p->tp_refp, TM_retrans); 298: if (p->tp_ucddata) { 299: IFDEBUG(D_CONN) 300: printf("dropping user connect data cc 0x%x\n", 301: p->tp_ucddata->m_len); 302: ENDDEBUG 303: m_freem(p->tp_ucddata); 304: p->tp_ucddata = 0; 305: } 306: soisconnected(p->tp_sock); 307: if (e->ev_union.EV_CC_TPDU.e_datalen > 0) { 308: ASSERT(p->tp_Xrcv.sb_cc == 0); /* should be empty */ 309: sbappendrecord(&p->tp_Xrcv, e->ev_union.EV_CC_TPDU.e_data); 310: e->ev_union.EV_CC_TPDU.e_data = MNULL; 311: } 312: 313: (void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, MNULL); 314: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); 315: } 316: break; 317: case 0x16: 318: { 319: struct mbuf *data = MNULL; 320: int error; 321: 322: IncStat(ts_retrans_cr); 323: p->tp_cong_win = 1; 324: p->tp_ackrcvd = 0; 325: data = MCPY(p->tp_ucddata, M_NOWAIT); 326: if(p->tp_ucddata) { 327: IFDEBUG(D_CONN) 328: printf("TM_retrans.trans m_copy cc 0x%x\n", data); 329: dump_mbuf(p->tp_ucddata, "sosnd @ TM_retrans"); 330: ENDDEBUG 331: if( data == MNULL ) 332: return ENOBUFS; 333: } 334: 335: p->tp_retrans --; 336: if( error = tp_emit(CR_TPDU_type, p, 0, 0, data) ) { 337: p->tp_sock->so_error = error; 338: } 339: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_cr_ticks); 340: } 341: break; 342: case 0x17: 343: { 344: IncStat(ts_conn_gaveup); 345: p->tp_sock->so_error = ETIMEDOUT; 346: tp_indicate(T_DISCONNECT, p, ETIMEDOUT); 347: tp_soisdisconnected(p); 348: } 349: break; 350: case 0x18: 351: { 352: int error; 353: struct mbuf *data = MCPY(p->tp_ucddata, M_WAIT); 354: 355: if( error = tp_emit(CC_TPDU_type, p, 0, 0, data) ) { 356: p->tp_sock->so_error = error; 357: } 358: p->tp_retrans = p->tp_Nretrans; 359: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_cc_ticks); 360: } 361: break; 362: case 0x19: 363: { 364: int doack; 365: 366: /* 367: * Get rid of any confirm or connect data, so that if we 368: * crash or close, it isn't thought of as disconnect data. 369: */ 370: if (p->tp_ucddata) { 371: m_freem(p->tp_ucddata); 372: p->tp_ucddata = 0; 373: } 374: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); 375: tp_cuntimeout(p->tp_refp, TM_retrans); 376: soisconnected(p->tp_sock); 377: tp_getoptions(p); 378: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); 379: 380: /* see also next 2 transitions, if you make any changes */ 381: 382: doack = tp_stash(p, e); 383: IFDEBUG(D_DATA) 384: printf("tp_stash returns %d\n",doack); 385: ENDDEBUG 386: 387: if(doack) { 388: (void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, MNULL ); 389: tp_ctimeout(p->tp_refp, TM_sendack, (int)p->tp_keepalive_ticks); 390: } else 391: tp_ctimeout( p->tp_refp, TM_sendack, (int)p->tp_sendack_ticks); 392: 393: IFDEBUG(D_DATA) 394: printf("after stash calling sbwakeup\n"); 395: ENDDEBUG 396: } 397: break; 398: case 0x1a: 399: { 400: tp0_stash(p, e); 401: sbwakeup( &p->tp_sock->so_rcv ); 402: 403: IFDEBUG(D_DATA) 404: printf("after stash calling sbwakeup\n"); 405: ENDDEBUG 406: } 407: break; 408: case 0x1b: 409: { 410: int doack; /* tells if we must ack immediately */ 411: 412: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); 413: sbwakeup( &p->tp_sock->so_rcv ); 414: 415: doack = tp_stash(p, e); 416: IFDEBUG(D_DATA) 417: printf("tp_stash returns %d\n",doack); 418: ENDDEBUG 419: 420: if(doack) 421: (void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, MNULL ); 422: else 423: tp_ctimeout_MIN( p->tp_refp, TM_sendack, (int)p->tp_sendack_ticks); 424: 425: IFDEBUG(D_DATA) 426: printf("after stash calling sbwakeup\n"); 427: ENDDEBUG 428: } 429: break; 430: case 0x1c: 431: { 432: IFTRACE(D_DATA) 433: tptrace(TPPTmisc, "NIW seq rcvnxt lcredit ", 434: e->ev_union.EV_DT_TPDU.e_seq, p->tp_rcvnxt, p->tp_lcredit, 0); 435: ENDTRACE 436: IncStat(ts_dt_niw); 437: m_freem(e->ev_union.EV_DT_TPDU.e_data); 438: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); 439: (void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, MNULL ); 440: } 441: break; 442: case 0x1d: 443: { 444: if (p->tp_ucddata) { 445: m_freem(p->tp_ucddata); 446: p->tp_ucddata = 0; 447: } 448: (void) tp_goodack(p, e->ev_union.EV_AK_TPDU.e_cdt, e->ev_union.EV_AK_TPDU.e_seq, e->ev_union.EV_AK_TPDU.e_subseq); 449: tp_cuntimeout(p->tp_refp, TM_retrans); 450: 451: tp_getoptions(p); 452: soisconnected(p->tp_sock); 453: IFTRACE(D_CONN) 454: struct socket *so = p->tp_sock; 455: tptrace(TPPTmisc, 456: "called sosiconn: so so_state rcv.sb_sel rcv.sb_flags", 457: so, so->so_state, so->so_rcv.sb_sel, so->so_rcv.sb_flags); 458: tptrace(TPPTmisc, 459: "called sosiconn 2: so_qlen so_error so_rcv.sb_cc so_head", 460: so->so_qlen, so->so_error, so->so_rcv.sb_cc, so->so_head); 461: ENDTRACE 462: 463: tp_ctimeout(p->tp_refp, TM_sendack, (int)p->tp_keepalive_ticks); 464: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); 465: } 466: break; 467: case 0x1e: 468: { 469: if( p->tp_state == TP_AKWAIT ) { 470: if (p->tp_ucddata) { 471: m_freem(p->tp_ucddata); 472: p->tp_ucddata = 0; 473: } 474: tp_cuntimeout(p->tp_refp, TM_retrans); 475: tp_getoptions(p); 476: soisconnected(p->tp_sock); 477: tp_ctimeout(p->tp_refp, TM_sendack, (int)p->tp_keepalive_ticks); 478: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); 479: } 480: IFTRACE(D_XPD) 481: tptrace(TPPTmisc, "XPD tpdu accepted Xrcvnxt, e_seq datalen m_len\n", 482: p->tp_Xrcvnxt,e->ev_union.EV_XPD_TPDU.e_seq, e->ev_union.EV_XPD_TPDU.e_datalen, e->ev_union.EV_XPD_TPDU.e_data->m_len); 483: ENDTRACE 484: 485: p->tp_sock->so_state |= SS_RCVATMARK; 486: e->ev_union.EV_XPD_TPDU.e_data->m_flags |= M_EOR; 487: sbinsertoob(&p->tp_Xrcv, e->ev_union.EV_XPD_TPDU.e_data); 488: IFDEBUG(D_XPD) 489: dump_mbuf(e->ev_union.EV_XPD_TPDU.e_data, "XPD TPDU: tp_Xrcv"); 490: ENDDEBUG 491: tp_indicate(T_XDATA, p, 0); 492: sbwakeup( &p->tp_Xrcv ); 493: 494: (void) tp_emit(XAK_TPDU_type, p, p->tp_Xrcvnxt, 0, MNULL); 495: SEQ_INC(p, p->tp_Xrcvnxt); 496: } 497: break; 498: case 0x1f: 499: { 500: if( p->tp_Xrcv.sb_cc == 0 ) { 501: /* kludge for select(): */ 502: /* p->tp_sock->so_state &= ~SS_OOBAVAIL; */ 503: } 504: } 505: break; 506: case 0x20: 507: { 508: IFTRACE(D_XPD) 509: tptrace(TPPTmisc, "XPD tpdu niw (Xrcvnxt, e_seq) or not cdt (cc)\n", 510: p->tp_Xrcvnxt, e->ev_union.EV_XPD_TPDU.e_seq, p->tp_Xrcv.sb_cc , 0); 511: ENDTRACE 512: if( p->tp_Xrcvnxt != e->ev_union.EV_XPD_TPDU.e_seq ) 513: IncStat(ts_xpd_niw); 514: if( p->tp_Xrcv.sb_cc ) { 515: /* might as well kick 'em again */ 516: tp_indicate(T_XDATA, p, 0); 517: IncStat(ts_xpd_dup); 518: } 519: m_freem(e->ev_union.EV_XPD_TPDU.e_data); 520: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); 521: /* don't send an xack because the xak gives "last one received", not 522: * "next one i expect" (dumb) 523: */ 524: } 525: break; 526: case 0x21: 527: { 528: struct socket *so = p->tp_sock; 529: 530: /* detach from parent socket so it can finish closing */ 531: if (so->so_head) { 532: if (!soqremque(so, 0) && !soqremque(so, 1)) 533: panic("tp: T_DETACH"); 534: so->so_head = 0; 535: } 536: tp_soisdisconnecting(p->tp_sock); 537: tp_netcmd( p, CONN_CLOSE); 538: tp_soisdisconnected(p); 539: } 540: break; 541: case 0x22: 542: { 543: struct socket *so = p->tp_sock; 544: struct mbuf *data = MNULL; 545: 546: /* detach from parent socket so it can finish closing */ 547: if (so->so_head) { 548: if (!soqremque(so, 0) && !soqremque(so, 1)) 549: panic("tp: T_DETACH"); 550: so->so_head = 0; 551: } 552: if (p->tp_state != TP_CLOSING) { 553: tp_soisdisconnecting(p->tp_sock); 554: data = MCPY(p->tp_ucddata, M_NOWAIT); 555: (void) tp_emit(DR_TPDU_type, p, 0, E_TP_NORMAL_DISC, data); 556: p->tp_retrans = p->tp_Nretrans; 557: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_dr_ticks); 558: } 559: } 560: break; 561: case 0x23: 562: { 563: tp_soisdisconnecting(p->tp_sock); 564: tp_netcmd( p, CONN_CLOSE); 565: tp_soisdisconnected(p); 566: } 567: break; 568: case 0x24: 569: { 570: struct mbuf *data = MCPY(p->tp_ucddata, M_WAIT); 571: 572: if(p->tp_state == TP_OPEN) { 573: tp_euntimeout(p->tp_refp, TM_data_retrans); /* all */ 574: tp_cuntimeout(p->tp_refp, TM_inact); 575: tp_cuntimeout(p->tp_refp, TM_sendack); 576: } 577: if (data) { 578: IFDEBUG(D_CONN) 579: printf("T_DISC_req.trans tp_ucddata 0x%x\n", 580: p->tp_ucddata); 581: dump_mbuf(data, "ucddata @ T_DISC_req"); 582: ENDDEBUG 583: } 584: tp_soisdisconnecting(p->tp_sock); 585: p->tp_retrans = p->tp_Nretrans; 586: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_dr_ticks); 587: 588: if( trick_hc ) 589: return tp_emit(DR_TPDU_type, p, 0, e->ev_union.EV_T_DISC_req.e_reason, data); 590: } 591: break; 592: case 0x25: 593: { 594: int error; 595: struct mbuf *data = MCPY(p->tp_ucddata, M_WAIT); 596: 597: IncStat(ts_retrans_cc); 598: p->tp_retrans --; 599: p->tp_cong_win = 1; 600: p->tp_ackrcvd = 0; 601: 602: if( error = tp_emit(CC_TPDU_type, p, 0, 0, data) ) 603: p->tp_sock->so_error = error; 604: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_cc_ticks); 605: } 606: break; 607: case 0x26: 608: { 609: IncStat(ts_conn_gaveup); 610: tp_soisdisconnecting(p->tp_sock); 611: p->tp_sock->so_error = ETIMEDOUT; 612: tp_indicate(T_DISCONNECT, p, ETIMEDOUT); 613: (void) tp_emit(DR_TPDU_type, p, 0, E_TP_CONGEST, MNULL); 614: p->tp_retrans = p->tp_Nretrans; 615: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_dr_ticks); 616: } 617: break; 618: case 0x27: 619: { 620: tp_euntimeout(p->tp_refp, TM_data_retrans); /* all */ 621: tp_cuntimeout(p->tp_refp, TM_inact); 622: tp_cuntimeout(p->tp_refp, TM_sendack); 623: 624: IncStat(ts_conn_gaveup); 625: tp_soisdisconnecting(p->tp_sock); 626: p->tp_sock->so_error = ETIMEDOUT; 627: tp_indicate(T_DISCONNECT, p, ETIMEDOUT); 628: (void) tp_emit(DR_TPDU_type, p, 0, E_TP_CONGEST_2, MNULL); 629: p->tp_retrans = p->tp_Nretrans; 630: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_dr_ticks); 631: } 632: break; 633: case 0x28: 634: { 635: p->tp_cong_win = 1; 636: p->tp_ackrcvd = 0; 637: /* resume XPD */ 638: if ( p->tp_Xsnd.sb_mb ) { 639: struct mbuf *m = m_copy(p->tp_Xsnd.sb_mb, 0, (int)p->tp_Xsnd.sb_cc); 640: /* m_copy doesn't preserve the m_xlink field, but at this pt. 641: * that doesn't matter 642: */ 643: 644: IFTRACE(D_XPD) 645: tptrace(TPPTmisc, "XPD retrans: Xuna Xsndnxt sndhiwat snduna", 646: p->tp_Xuna, p->tp_Xsndnxt, p->tp_sndhiwat, 647: p->tp_snduna); 648: ENDTRACE 649: IFDEBUG(D_XPD) 650: dump_mbuf(m, "XPD retrans emitting M"); 651: ENDDEBUG 652: IncStat(ts_retrans_xpd); 653: p->tp_retrans --; 654: (void) tp_emit(XPD_TPDU_type, p, p->tp_Xuna, 1, m); 655: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_xpd_ticks); 656: } 657: } 658: break; 659: case 0x29: 660: { 661: register SeqNum low, lowsave = 0; 662: register struct tp_rtc *r = p->tp_snduna_rtc; 663: register struct mbuf *m; 664: register SeqNum high = e->ev_union.EV_TM_data_retrans.e_high; 665: 666: low = p->tp_snduna; 667: lowsave = high = low; 668: 669: tp_euntimeout_lss(p->tp_refp, TM_data_retrans, 670: SEQ_ADD(p, p->tp_sndhiwat, 1)); 671: p->tp_retrans_hiwat = p->tp_sndhiwat; 672: 673: if ((p->tp_rx_strat & TPRX_EACH) == 0) 674: high = (high>low)?low:high; 675: 676: if( p->tp_rx_strat & TPRX_USE_CW ) { 677: register int i; 678: 679: p->tp_cong_win = 1; 680: p->tp_ackrcvd = 0; 681: i = SEQ_ADD(p, low, p->tp_cong_win); 682: 683: high = SEQ_MIN(p, high, p->tp_sndhiwat); 684: 685: } 686: 687: while( SEQ_LEQ(p, low, high) ){ 688: if ( r == (struct tp_rtc *)0 ){ 689: IFDEBUG(D_RTC) 690: printf( "tp: retrans rtc list is GONE!\n"); 691: ENDDEBUG 692: break; 693: } 694: if ( r->tprt_seq == low ){ 695: if(( m = m_copy(r->tprt_data, 0, r->tprt_octets ))== MNULL) 696: break; 697: (void) tp_emit(DT_TPDU_type, p, low, r->tprt_eot, m); 698: IncStat(ts_retrans_dt); 699: SEQ_INC(p, low ); 700: } 701: r = r->tprt_next; 702: } 703: /* CE_BIT 704: if ( SEQ_LEQ(p, lowsave, high) ){ 705: */ 706: e->ev_union.EV_TM_data_retrans.e_retrans --; 707: tp_etimeout(p->tp_refp, TM_data_retrans, (caddr_t)lowsave, 708: (caddr_t)high, e->ev_union.EV_TM_data_retrans.e_retrans, 709: (p->tp_Nretrans - e->ev_union.EV_TM_data_retrans.e_retrans) * (int)p->tp_dt_ticks); 710: /* CE_BIT 711: } 712: */ 713: } 714: break; 715: case 0x2a: 716: { 717: p->tp_retrans --; 718: (void) tp_emit(DR_TPDU_type, p, 0, E_TP_DR_NO_REAS, MNULL); 719: IncStat(ts_retrans_dr); 720: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_dr_ticks); 721: } 722: break; 723: case 0x2b: 724: { 725: p->tp_sock->so_error = ETIMEDOUT; 726: p->tp_refp->tpr_state = REF_FROZEN; 727: tp_recycle_tsuffix( p ); 728: tp_etimeout(p->tp_refp, TM_reference, 0,0,0, (int)p->tp_refer_ticks); 729: } 730: break; 731: case 0x2c: 732: { 733: tp_freeref(p->tp_refp); 734: tp_detach(p); 735: } 736: break; 737: case 0x2d: 738: { 739: if( p->tp_class != TP_CLASS_0) { 740: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); 741: if ( e->ev_number == CC_TPDU ) 742: (void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, MNULL); 743: } 744: /* ignore it if class 0 - state tables are blank for this */ 745: } 746: break; 747: case 0x2e: 748: { 749: IFTRACE(D_DATA) 750: tptrace(TPPTmisc, "T_DATA_req sndhiwat snduna fcredit, tpcb", 751: p->tp_sndhiwat, p->tp_snduna, p->tp_fcredit, p); 752: ENDTRACE 753: 754: tp_send(p); 755: } 756: break; 757: case 0x2f: 758: { 759: int error = 0; 760: 761: /* resume XPD */ 762: if ( p->tp_Xsnd.sb_mb ) { 763: struct mbuf *m = m_copy(p->tp_Xsnd.sb_mb, 0, (int)p->tp_Xsnd.sb_cc); 764: /* m_copy doesn't preserve the m_xlink field, but at this pt. 765: * that doesn't matter 766: */ 767: 768: IFTRACE(D_XPD) 769: tptrace(TPPTmisc, "XPD req: Xuna Xsndnxt sndhiwat snduna", 770: p->tp_Xuna, p->tp_Xsndnxt, p->tp_sndhiwat, 771: p->tp_snduna); 772: ENDTRACE 773: IFDEBUG(D_XPD) 774: printf("T_XPD_req: sb_cc 0x%x\n", p->tp_Xsnd.sb_cc); 775: dump_mbuf(m, "XPD req emitting M"); 776: ENDDEBUG 777: error = 778: tp_emit(XPD_TPDU_type, p, p->tp_Xuna, 1, m); 779: p->tp_retrans = p->tp_Nretrans; 780: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_xpd_ticks); 781: SEQ_INC(p, p->tp_Xsndnxt); 782: } 783: if(trick_hc) 784: return error; 785: } 786: break; 787: case 0x30: 788: { 789: IFDEBUG(D_ACKRECV) 790: printf("GOOD ACK seq 0x%x cdt 0x%x\n", e->ev_union.EV_AK_TPDU.e_seq, e->ev_union.EV_AK_TPDU.e_cdt); 791: ENDDEBUG 792: if( p->tp_class != TP_CLASS_0) { 793: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); 794: tp_euntimeout_lss(p->tp_refp, TM_data_retrans, e->ev_union.EV_AK_TPDU.e_seq); 795: } 796: sbwakeup( &p->tp_sock->so_snd ); 797: 798: if (p->tp_sndhiwat <= p->tp_retrans_hiwat && 799: p->tp_snduna <= p->tp_retrans_hiwat) { 800: 801: register struct mbuf *m; 802: /* extern struct mbuf *m_copy(); */ 803: register struct tp_rtc *r; 804: SeqNum high, retrans, low_save; 805: 806: high = SEQ_MIN(p, SEQ_ADD(p, p->tp_snduna, 807: MIN(p->tp_cong_win, p->tp_fcredit)) - 1, 808: p->tp_sndhiwat); 809: low_save = retrans = SEQ_MAX(p, SEQ_ADD(p, p->tp_last_retrans, 1), 810: p->tp_snduna); 811: for (; SEQ_LEQ(p, retrans, high); SEQ_INC(p, retrans)) { 812: 813: for (r = p->tp_snduna_rtc; r; r = r->tprt_next){ 814: if ( r->tprt_seq == retrans ){ 815: if(( m = m_copy(r->tprt_data, 0, r->tprt_octets )) 816: == MNULL) 817: break; 818: (void) tp_emit(DT_TPDU_type, p, retrans, 819: r->tprt_eot, m); 820: p->tp_last_retrans = retrans; 821: IncStat(ts_retrans_dt); 822: break; 823: } 824: } 825: if ( r == (struct tp_rtc *)0 ){ 826: IFDEBUG(D_RTC) 827: printf( "tp: retrans rtc list is GONE!\n"); 828: ENDDEBUG 829: break; 830: } 831: } 832: tp_etimeout(p->tp_refp, TM_data_retrans, (caddr_t)low_save, 833: (caddr_t)high, p->tp_retrans, (int)p->tp_dt_ticks); 834: if (SEQ_DEC(p, retrans) == p->tp_retrans_hiwat) 835: tp_send(p); 836: } 837: else { 838: tp_send(p); 839: } 840: IFDEBUG(D_ACKRECV) 841: printf("GOOD ACK new sndhiwat 0x%x\n", p->tp_sndhiwat); 842: ENDDEBUG 843: } 844: break; 845: case 0x31: 846: { 847: IFTRACE(D_ACKRECV) 848: tptrace(TPPTmisc, "BOGUS ACK fcc_present, tp_r_subseq e_subseq", 849: e->ev_union.EV_AK_TPDU.e_fcc_present, p->tp_r_subseq, e->ev_union.EV_AK_TPDU.e_subseq, 0); 850: ENDTRACE 851: if( p->tp_class != TP_CLASS_0 ) { 852: 853: if ( !e->ev_union.EV_AK_TPDU.e_fcc_present ) { 854: /* send ACK with FCC */ 855: IncStat( ts_ackreason[_ACK_FCC_] ); 856: (void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 1, MNULL); 857: } 858: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); 859: } 860: } 861: break; 862: case 0x32: 863: { 864: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); 865: tp_cuntimeout(p->tp_refp, TM_retrans); 866: 867: sbwakeup( &p->tp_sock->so_snd ); 868: 869: /* resume normal data */ 870: tp_send(p); 871: } 872: break; 873: case 0x33: 874: { 875: IFTRACE(D_ACKRECV) 876: tptrace(TPPTmisc, "BOGUS XACK eventtype ", e->ev_number, 0, 0,0); 877: ENDTRACE 878: if( p->tp_class != TP_CLASS_0 ) { 879: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); 880: } 881: } 882: break; 883: case 0x34: 884: { 885: IFTRACE(D_TIMER) 886: tptrace(TPPTsendack, -1, p->tp_lcredit, p->tp_sent_uwe, 887: p->tp_sent_lcdt, 0); 888: ENDTRACE 889: IncPStat(p, tps_n_TMsendack); 890: (void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, MNULL); 891: } 892: break; 893: case 0x35: 894: { 895: if (sbspace(&p->tp_sock->so_rcv) > 0) 896: tp0_openflow(p); 897: } 898: break; 899: case 0x36: 900: { 901: if( trick_hc ) { 902: IncStat(ts_ackreason[_ACK_USRRCV_]); 903: 904: /* send an ACK only if there's new information */ 905: LOCAL_CREDIT( p ); 906: if ((p->tp_rcvnxt != p->tp_sent_rcvnxt) || 907: (p->tp_lcredit != p->tp_sent_lcdt)) 908: 909: return tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, MNULL); 910: } 911: } 912: break; 913: case 0x37: 914: { 915: if(trick_hc) 916: return ECONNABORTED; 917: } 918: break; 919: case 0x38: 920: { 921: ASSERT( p->tp_state != TP_LISTENING ); 922: tp_indicate(T_DISCONNECT, p, ECONNRESET); 923: tp_soisdisconnected(p); 924: } 925: break; 926: } 927: return 0; 928: } 929: 930: _XEBEC_PG int 931: _Xebec_index( e,p ) 932: struct tp_event *e; 933: tp_PCB_ *p; 934: { 935: switch( (e->ev_number<<4)+(p->tp_state) ) { 936: case 0x12: 937: if ( p->tp_retrans > 0 ) return 0x1e; 938: else return 0x1f; 939: case 0x13: 940: if ( p->tp_retrans > 0 ) return 0x2f; 941: else return 0x30; 942: case 0x14: 943: if ( p->tp_retrans > 0 ) return 0x32; 944: else return 0x31; 945: case 0x15: 946: if ( p->tp_retrans > 0 ) return 0x34; 947: else return 0x35; 948: case 0x54: 949: if ( e->ev_union.EV_TM_data_retrans.e_retrans > 0 ) return 0x33; 950: else return 0x31; 951: case 0x64: 952: if (p->tp_class == TP_CLASS_0) return 0x1a; 953: else return 0x1b; 954: case 0x77: 955: if ( p->tp_class == TP_CLASS_0) return 0xd; 956: else return 0xe; 957: case 0x86: 958: if ( e->ev_union.EV_DR_TPDU.e_sref != 0 ) return 0x2; 959: else return 0x3; 960: case 0xa2: 961: if (p->tp_class == TP_CLASS_0) return 0x1c; 962: else return 0x1d; 963: case 0xb2: 964: if (p->tp_class == TP_CLASS_0) return 0x5; 965: else return 0x0; 966: case 0xb4: 967: if ( tp_goodack(p, e->ev_union.EV_AK_TPDU.e_cdt, e->ev_union.EV_AK_TPDU.e_seq, e->ev_union.EV_AK_TPDU.e_subseq) ) return 0x3a; 968: else return 0x3b; 969: case 0xc3: 970: if ( IN_RWINDOW( p, e->ev_union.EV_DT_TPDU.e_seq, 971: p->tp_rcvnxt, SEQ(p, p->tp_rcvnxt + p->tp_lcredit)) ) return 0x21; 972: else return 0x24; 973: case 0xc4: 974: if ( p->tp_class == TP_CLASS_0 ) return 0x22; 975: else if ( IN_RWINDOW( p, e->ev_union.EV_DT_TPDU.e_seq, 976: p->tp_rcvnxt, SEQ(p, p->tp_rcvnxt + p->tp_lcredit)) ) return 0x23; 977: else return 0x25; 978: case 0xd3: 979: if (p->tp_Xrcvnxt == e->ev_union.EV_XPD_TPDU.e_seq) return 0x27; 980: else return 0x2a; 981: case 0xd4: 982: if (p->tp_Xrcvnxt == e->ev_union.EV_XPD_TPDU.e_seq) return 0x27; 983: else return 0x29; 984: case 0xe4: 985: if ( tp_goodXack(p, e->ev_union.EV_XAK_TPDU.e_seq) ) return 0x3c; 986: else return 0x3d; 987: case 0x102: 988: if ( p->tp_class == TP_CLASS_0 ) return 0x2d; 989: else return 0x2e; 990: case 0x104: 991: if ( p->tp_class == TP_CLASS_0 ) return 0x2d; 992: else return 0x2e; 993: case 0x144: 994: if (p->tp_class == TP_CLASS_0) return 0x3f; 995: else return 0x40; 996: case 0x162: 997: if (p->tp_class == TP_CLASS_0) return 0x2b; 998: else return 0x2c; 999: case 0x172: 1000: if ( p->tp_class != TP_CLASS_4 ) return 0x42; 1001: else return 0x46; 1002: case 0x174: 1003: if ( p->tp_class != TP_CLASS_4 ) return 0x42; 1004: else return 0x47; 1005: case 0x177: 1006: if ( p->tp_class != TP_CLASS_4 ) return 0x42; 1007: else return 0x43; 1008: case 0x188: 1009: if ( p->tp_class == TP_CLASS_0 ) return 0xf; 1010: else if (tp_emit(CC_TPDU_type, p, 0,0, MCPY(p->tp_ucddata, M_NOWAIT)) == 0) return 0x10; 1011: else return 0x11; 1012: default: return 0; 1013: } /* end switch */ 1014: } /* _Xebec_index() */ 1015: static int inx[26][9] = { {0,0,0,0,0,0,0,0,0,}, 1016: {0x0,0x0,0x0,0x0,0x31,0x0,0x0,0x0,0x0, }, 1017: {0x0,0x0,-1,-1,-1,-1,0x0,0x0,0x0, }, 1018: {0x0,0x0,0x0,0x0,0x3e,0x0,0x0,0x0,0x0, }, 1019: {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, }, 1020: {0x0,0x0,0x0,0x0,0x0,0x0,0x36,0x0,0x0, }, 1021: {0x0,0x0,0x0,0x0,-1,0x0,0x0,0x0,0x0, }, 1022: {0x0,0x7,0x15,0x1b,-1,0x17,0x3,0xa,0x0, }, 1023: {0x0,0x19,0x6,0x20,0x37,0x8,0x3,-1,0x0, }, 1024: {0x0,0x14,0x13,0x13,0x13,0x16,-1,0xa,0x0, }, 1025: {0x0,0x7,0x6,0x1,0x9,0x18,0x3,0xa,0x0, }, 1026: {0x0,0x19,-1,0x1,0x37,0x8,0x3,0xa,0x0, }, 1027: {0x0,0x7,-1,0x26,-1,0x8,0x3,0xa,0x0, }, 1028: {0x0,0x7,0x6,-1,-1,0x8,0x3,0xa,0x0, }, 1029: {0x0,0x7,0x6,-1,-1,0x8,0x3,0xa,0x0, }, 1030: {0x0,0x7,0x6,0x1,-1,0x8,0x3,0xa,0x0, }, 1031: {0x0,0x12,0x0,0x0,0x0,0x0,0x0,0x0,0x0, }, 1032: {0x0,0x0,-1,0x2e,-1,0x0,0x4,0x0,0x2e, }, 1033: {0x0,0xb,0x0,0x0,0x0,0x0,0x0,0x0,0x0, }, 1034: {0x0,0x0,0x0,0x0,0x38,0x0,0x0,0x0,0x0, }, 1035: {0x0,0x0,0x0,0x0,0x39,0x0,0x0,0x0,0x0, }, 1036: {0x0,0x0,0x0,0x0,-1,0x0,0x41,0x0,0x0, }, 1037: {0x0,0x0,0x0,0x0,0x28,0x0,0x41,0x0,0x0, }, 1038: {0x0,0xc,-1,0x2c,0x0,0x2c,0x4,0xc,0x2c, }, 1039: {0x0,0x49,-1,0x45,-1,0x44,0x48,-1,0x0, }, 1040: {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,-1, }, 1041: }; 1042: tp_driver(p, e) 1043: register tp_PCB_ *p; 1044: register struct tp_event *e; 1045: { 1046: register int index, error=0; 1047: struct act_ent *a; 1048: static struct act_ent erroraction = {0,-1}; 1049: 1050: index = inx[1 + e->ev_number][p->tp_state]; 1051: if(index<0) index=_Xebec_index(e, p); 1052: if (index==0) { 1053: a = &erroraction; 1054: } else 1055: a = &statetable[index]; 1056: 1057: if(a->a_action) 1058: error = _Xebec_action( a->a_action, e, p ); 1059: IFTRACE(D_DRIVER) 1060: tptrace(DRIVERTRACE, a->a_newstate, p->tp_state, e->ev_number, a->a_action, 0); 1061: 1062: ENDTRACE 1063: if(error==0) 1064: p->tp_state = a->a_newstate; 1065: return error; 1066: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.