📄 tp_input.c
字号:
tp_newsocket(so, faddr, cons_channel, class_to_use, ((tpcb->tp_netservice == IN_CLNS) ? IN_CLNS : (dgout_routine == tpcons_output)?ISO_CONS:ISO_CLNS)) ) == (struct socket *)0 ) { /* note - even if netservice is IN_CLNS, as far as * the tp entity is concerned, the only differences * are CO vs CL */ IFDEBUG(D_CONN) printf("tp_newsocket returns 0\n"); ENDDEBUG goto discard; clear_parent_tcb: tpcb = 0; goto respond; } tpcb = sototpcb(so); insque(tpcb, parent_tpcb); /* * Stash the addresses in the net level pcb * kind of like a pcbconnect() but don't need * or want all those checks. */ (tpcb->tp_nlproto->nlp_putnetaddr)(tpcb->tp_npcb, faddr, TP_FOREIGN); (tpcb->tp_nlproto->nlp_putnetaddr)(tpcb->tp_npcb, laddr, TP_LOCAL); /* stash the f suffix in the new tpcb */ if (tpcb->tp_fsuffixlen = fsufxlen) { bcopy(fsufxloc, tpcb->tp_fsuffix, fsufxlen); (tpcb->tp_nlproto->nlp_putsufx) (tpcb->tp_npcb, fsufxloc, fsufxlen, TP_FOREIGN); } /* stash the l suffix in the new tpcb */ tpcb->tp_lsuffixlen = lsufxlen; bcopy(lsufxloc, tpcb->tp_lsuffix, lsufxlen); (tpcb->tp_nlproto->nlp_putsufx) (tpcb->tp_npcb, lsufxloc, lsufxlen, TP_LOCAL);#ifdef TP_PERF_MEAS if( tpcb->tp_perf_on = perf_meas ) { /* assignment */ /* ok, let's create an mbuf for stashing the * statistics if one doesn't already exist */ (void) tp_setup_perf(tpcb); }#endif /* TP_PERF_MEAS */ tpcb->tp_fref = sref; /* We've already checked for consistency with the options * set in tpp, but we couldn't set them earlier because * we didn't want to change options in the LISTENING tpcb. * Now we set the options in the new socket's tpcb. */ (void) tp_consistency( tpcb, TP_FORCE, &tpp); if(!tpcb->tp_use_checksum) IncStat(ts_csum_off); if(tpcb->tp_xpd_service) IncStat(ts_use_txpd); if(tpcb->tp_xtd_format) IncStat(ts_xtd_fmt); tpcb->tp_peer_acktime = acktime; /* * The following kludge is used to test retransmissions and * timeout during connection establishment. */ IFDEBUG(D_ZDREF) IncStat(ts_zdebug); /*tpcb->tp_fref = 0;*/ ENDDEBUG } LOCAL_CREDIT(tpcb); IncStat(ts_CR_rcvd); if (!tpcb->tp_cebit_off) { tpcb->tp_win_recv = tp_start_win << 8; tpcb->tp_cong_sample.cs_size = 0; CONG_INIT_SAMPLE(tpcb); CONG_UPDATE_SAMPLE(tpcb, ce_bit); } } else if ( dutype == ER_TPDU_type ) { /* * ER TPDUs have to be recognized separately * because they don't necessarily have a tpcb * with them and we don't want err out looking for such * a beast. * We could put a bunch of little kludges in the * next section of code so it would avoid references to tpcb * if dutype == ER_TPDU_type but we don't want code for ERs to * mess up code for data transfer. */ IncStat(ts_ER_rcvd); e.ev_number = ER_TPDU; e.ATTR(ER_TPDU).e_reason = (u_char)hdr->tpdu_ERreason; CHECK (((int)dref <= 0 || dref >= tp_refinfo.tpr_size || (tpcb = tp_ref[dref].tpr_pcb ) == (struct tp_pcb *) 0 || tpcb->tp_refstate == REF_FREE || tpcb->tp_refstate == REF_FROZEN), E_TP_MISM_REFS, ts_inv_dref, discard, 0) } else { /* tpdu type is CC, XPD, XAK, GR, AK, DR, DC, or DT */ /* In the next 4 checks, * _tpduf is the fixed part; add 2 to get the dref bits of * the fixed part (can't take the address of a bit field) */#ifdef TPCONS if (cons_channel && dutype == DT_TPDU_type) { struct isopcb *isop = ((struct isopcb *) ((struct pklcd *)cons_channel)->lcd_upnext); if (isop && isop->isop_refcnt == 1 && isop->isop_socket && (tpcb = sototpcb(isop->isop_socket)) && (tpcb->tp_class == TP_CLASS_0/* || == CLASS_1 */)) { IFDEBUG(D_TPINPUT) printf("tpinput_dt: class 0 short circuit\n"); ENDDEBUG dref = tpcb->tp_lref; sref = tpcb->tp_fref; CHECK( (tpcb->tp_refstate == REF_FREE), E_TP_MISM_REFS,ts_inv_dref, nonx_dref, (1 + 2 + (caddr_t)&hdr->_tpduf - (caddr_t)hdr)) goto tp0_data; } }#endif { CHECK( ((int)dref <= 0 || dref >= tp_refinfo.tpr_size) , E_TP_MISM_REFS,ts_inv_dref, nonx_dref, (1 + 2 + (caddr_t)&hdr->_tpduf - (caddr_t)hdr)) CHECK( ((tpcb = tp_ref[dref].tpr_pcb ) == (struct tp_pcb *) 0 ), E_TP_MISM_REFS,ts_inv_dref, nonx_dref, (1 + 2 + (caddr_t)&hdr->_tpduf - (caddr_t)hdr)) CHECK( (tpcb->tp_refstate == REF_FREE), E_TP_MISM_REFS,ts_inv_dref, nonx_dref, (1 + 2 + (caddr_t)&hdr->_tpduf - (caddr_t)hdr)) } IFDEBUG(D_TPINPUT) printf("HAVE A TPCB 2: 0x%x\n", tpcb); ENDDEBUG /* causes a DR to be sent for CC; ER for all else */ CHECK( (tpcb->tp_refstate == REF_FROZEN), (dutype == CC_TPDU_type?E_TP_NO_SESSION:E_TP_MISM_REFS), ts_inv_dref, respond, (1 + 2 + (caddr_t)&hdr->_tpduf - (caddr_t)hdr)) IFDEBUG(D_TPINPUT) printf("state of dref %d ok, tpcb 0x%x\n", dref,tpcb); ENDDEBUG /* * At this point the state of the dref could be * FROZEN: tpr_pcb == NULL, has ( reference only) timers * for example, DC may arrive after the close() has detached * the tpcb (e.g., if user turned off SO_LISTEN option) * OPENING : a tpcb exists but no timers yet * OPEN : tpcb exists & timers are outstanding */ if (!tpcb->tp_cebit_off) CONG_UPDATE_SAMPLE(tpcb, ce_bit); dusize = tpcb->tp_tpdusize; pdusize = tpcb->tp_ptpdusize; dutype = hdr->tpdu_type << 8; /* for the switch below */ WHILE_OPTIONS(P, hdr, tpcb->tp_xtd_format) /* { */#define caseof(x,y) case (((x)<<8)+(y)) switch( dutype | vbptr(P)->tpv_code ) { caseof( CC_TPDU_type, TPP_addl_opt ): /* not in class 0; 1 octet */ vb_getval(P, u_char, addlopt); break; caseof( CC_TPDU_type, TPP_tpdu_size ): { u_char odusize = dusize; vb_getval(P, u_char, dusize); CHECK( (dusize < TP_MIN_TPDUSIZE || dusize > TP_MAX_TPDUSIZE || dusize > odusize), E_TP_INV_PVAL, ts_inv_pval, respond, (1 + (caddr_t)&vbptr(P)->tpv_val - (caddr_t)hdr) ) IFDEBUG(D_TPINPUT) printf("CC dusize 0x%x\n", dusize); ENDDEBUG } break; caseof( CC_TPDU_type, TPP_ptpdu_size ): { u_short opdusize = pdusize; switch (vbptr(P)->tpv_len) { case 1: pdusize = vbval(P, u_char); break; case 2: pdusize = ntohs(vbval(P, u_short)); break; default: ; IFDEBUG(D_TPINPUT) printf("malformed prefered TPDU option\n"); ENDDEBUG } CHECK( (pdusize == 0 || (opdusize && (pdusize > opdusize))), E_TP_INV_PVAL, ts_inv_pval, respond, (1 + (caddr_t)&vbptr(P)->tpv_val - (caddr_t)hdr) ) } break; caseof( CC_TPDU_type, TPP_calling_sufx): IFDEBUG(D_TPINPUT) printf("CC calling (local) sufxlen 0x%x\n", lsufxlen); ENDDEBUG lsufxloc = (caddr_t) &vbptr(P)->tpv_val; lsufxlen = vbptr(P)->tpv_len; break; caseof( CC_TPDU_type, TPP_acktime ): /* class 4 only, 2 octets */ vb_getval(P, u_short, acktime); acktime = ntohs(acktime); acktime = acktime/500; /* convert to slowtimo ticks */ if( (short)acktime <=0 ) acktime = 2; break; caseof( CC_TPDU_type, TPP_called_sufx): fsufxloc = (caddr_t) &vbptr(P)->tpv_val; fsufxlen = vbptr(P)->tpv_len; IFDEBUG(D_TPINPUT) printf("CC called (foreign) sufx len %d\n", fsufxlen); ENDDEBUG break; caseof( CC_TPDU_type, TPP_checksum): caseof( DR_TPDU_type, TPP_checksum): caseof( DT_TPDU_type, TPP_checksum): caseof( XPD_TPDU_type, TPP_checksum): if( tpcb->tp_use_checksum ) { CHECK( iso_check_csum(m, tpdu_len), E_TP_INV_PVAL, ts_bad_csum, discard, 0) } break; /* this is different from the above because in the context * of concat/ sep tpdu_len might not be the same as hdr len */ caseof( AK_TPDU_type, TPP_checksum): caseof( XAK_TPDU_type, TPP_checksum): caseof( DC_TPDU_type, TPP_checksum): if( tpcb->tp_use_checksum ) { CHECK( iso_check_csum(m, (int)hdr->tpdu_li + 1), E_TP_INV_PVAL, ts_bad_csum, discard, 0) } break;#ifdef notdef caseof( DR_TPDU_type, TPP_addl_info ): /* ignore - its length and meaning are * user defined and there's no way * to pass this info to the user anyway */ break;#endif /* notdef */ caseof( AK_TPDU_type, TPP_subseq ): /* used after reduction of window */ vb_getval(P, u_short, subseq); subseq = ntohs(subseq); IFDEBUG(D_ACKRECV) printf("AK dref 0x%x Subseq 0x%x\n", dref, subseq); ENDDEBUG break; caseof( AK_TPDU_type, TPP_flow_cntl_conf ): { u_int ylwe; u_short ysubseq, ycredit; fcc_present = TRUE; vb_getval(P, u_int, ylwe); vb_getval(P, u_short, ysubseq); vb_getval(P, u_short, ycredit); ylwe = ntohl(ylwe); ysubseq = ntohs(ysubseq); ycredit = ntohs(ycredit); IFDEBUG(D_ACKRECV) printf("%s%x, subseq 0x%x, cdt 0x%x dref 0x%x\n", "AK FCC lwe 0x", ylwe, ysubseq, ycredit, dref); ENDDEBUG } break; default: IFDEBUG(D_TPINPUT) printf("param ignored dutype 0x%x, code 0x%x\n", dutype, vbptr(P)->tpv_code); ENDDEBUG IFTRACE(D_TPINPUT) tptrace(TPPTmisc, "param ignored dutype code ", dutype, vbptr(P)->tpv_code ,0,0); ENDTRACE IncStat(ts_param_ignored); break;#undef caseof } /* } */ END_WHILE_OPTIONS(P) /* NOTE: the variable dutype has been shifted left! */ switch( hdr->tpdu_type ) { case CC_TPDU_type: /* If CC comes back with an unacceptable class * respond with a DR or ER */ opt = hdr->tpdu_CCoptions; /* 1 byte */ { tpp = tpcb->_tp_param; tpp.p_class = (1<<hdr->tpdu_CCclass); tpp.p_tpdusize = dusize; tpp.p_ptpdusize = pdusize; tpp.p_dont_change_params = 0; tpp.p_xtd_format = (opt & TPO_XTD_FMT) == TPO_XTD_FMT; tpp.p_xpd_service = (addlopt & TPAO_USE_TXPD) == TPAO_USE_TXPD; tpp.p_use_checksum = (addlopt & TPAO_NO_CSUM) == 0;#ifdef notdef tpp.p_use_efc = (opt & TPO_USE_EFC) == TPO_USE_EFC; tpp.p_use_nxpd = (addlopt & TPAO_USE_NXPD) == TPAO_USE_NXPD; tpp.p_use_rcc = (addlopt & TPAO_USE_RCC) == TPAO_USE_RCC;#endif /* notdef */ CHECK( tp_consistency(tpcb, TP_FORCE, &tpp) != 0, E_TP_NEGOT_FAILED, ts_negotfailed, respond, (1 + 2 + (caddr_t)&hdr->_tpdufr.CRCC - (caddr_t)hdr) /* ^ more or less the location of class */ ) IFTRACE(D_CONN) tptrace(TPPTmisc, "after 1 consist class, out, tpconsout", tpcb->tp_class, dgout_routine, tpcons_output, 0 ); ENDTRACE CHECK( ((class_to_use == TP_CLASS_0)&& (dgout_routine != tpcons_output)), E_TP_NEGOT_FAILED, ts_negotfailed, respond, (1 + 2 + (caddr_t)&hdr->_tpdufr.CRCC - (caddr_t)hdr) /* ^ more or less the location of class */ )#ifdef TPCONS if (tpcb->tp_netservice == ISO_CONS && class_to_use == TP_CLASS_0) { struct isopcb *isop = (struct isopcb *)tpcb->tp_npcb; struct pklcd *lcp = (struct pklcd *)isop->isop_chan; lcp->lcd_flags &= ~X25_DG_CIRCUIT; }#endif } if( ! tpcb->tp_use_checksum) IncStat(ts_csum_off); if(tpcb->tp_xpd_service) IncStat(ts_use_txpd); if(tpcb->tp_xtd_format) IncStat(ts_xtd_fmt); IFTRACE(D_CONN) tptrace(TPPTmisc, "after CC class flags dusize CCclass", tpcb->tp_class, tpcb->tp_flags, tpcb->tp_tpdusize, hdr->tpdu_CCclass); ENDTRACE /* if called or calling suffices appeared on the CC, * they'd better jive with what's in the pcb */ if( fsufxlen ) { CHECK( ((tpcb->tp_fsuffixlen != fsufxlen) || bcmp(fsufxloc, tpcb->tp_fsuffix, fsufxlen)), E_TP_INV_PVAL,ts_inv_sufx, respond, (1+fsufxloc - (caddr_t)hdr)) } if( lsufxlen ) { CHECK( ((tpcb->tp_lsuffixlen != lsufxlen) || bcmp(lsufxloc, tpcb->tp_lsuffix, lsufxlen)), E_TP_INV_PVAL,ts_inv_sufx, respond, (1+lsufxloc - (caddr_t)hdr)) } e.ATTR(CC_TPDU).e_sref = sref; e.ATTR(CC_TPDU).e_cdt = hdr->tpdu_CCcdt; takes_data = TRUE; e.ev_number = CC_TPDU; IncStat(ts_CC_rcvd); break; case DC_TPDU_type: if (sref != tpcb->tp_fref) printf("INPUT: inv sufx DCsref 0x%x, tp_fref 0x%x\n", sref, tpcb->tp_fref); CHECK( (sref != tpcb->tp_fref), E_TP_MISM_REFS, ts_inv_sufx, discard, (1 + (caddr_t)&hdr->tpdu_DCsref - (caddr_t)hdr)) e.ev_number = DC_TPDU; IncStat(ts_DC_rcvd);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -