📄 tp_input.c
字号:
break; case DR_TPDU_type: IFTRACE(D_TPINPUT) tptrace(TPPTmisc, "DR recvd", hdr->tpdu_DRreason, 0, 0, 0); ENDTRACE if (sref != tpcb->tp_fref) { printf("INPUT: inv sufx DRsref 0x%x tp_fref 0x%x\n", sref, tpcb->tp_fref); } CHECK( (sref != 0 && sref != tpcb->tp_fref && tpcb->tp_state != TP_CRSENT), (TP_ERROR_SNDC | E_TP_MISM_REFS),ts_inv_sufx, respond, (1 + (caddr_t)&hdr->tpdu_DRsref - (caddr_t)hdr)) e.ATTR(DR_TPDU).e_reason = hdr->tpdu_DRreason; e.ATTR(DR_TPDU).e_sref = (u_short)sref; takes_data = TRUE; e.ev_number = DR_TPDU; IncStat(ts_DR_rcvd); break; case ER_TPDU_type: IFTRACE(D_TPINPUT) tptrace(TPPTmisc, "ER recvd", hdr->tpdu_ERreason,0,0,0); ENDTRACE e.ev_number = ER_TPDU; e.ATTR(ER_TPDU).e_reason = hdr->tpdu_ERreason; IncStat(ts_ER_rcvd); break; case AK_TPDU_type: e.ATTR(AK_TPDU).e_subseq = subseq; e.ATTR(AK_TPDU).e_fcc_present = fcc_present; if (tpcb->tp_xtd_format) {#ifdef BYTE_ORDER union seq_type seqeotX; seqeotX.s_seqeot = ntohl(hdr->tpdu_seqeotX); e.ATTR(AK_TPDU).e_seq = seqeotX.s_seq; e.ATTR(AK_TPDU).e_cdt = ntohs(hdr->tpdu_AKcdtX);#else e.ATTR(AK_TPDU).e_cdt = hdr->tpdu_AKcdtX; e.ATTR(AK_TPDU).e_seq = hdr->tpdu_AKseqX;#endif /* BYTE_ORDER */ } else { e.ATTR(AK_TPDU).e_cdt = hdr->tpdu_AKcdt; e.ATTR(AK_TPDU).e_seq = hdr->tpdu_AKseq; } IFTRACE(D_TPINPUT) tptrace(TPPTmisc, "AK recvd seq cdt subseq fcc_pres", e.ATTR(AK_TPDU).e_seq, e.ATTR(AK_TPDU).e_cdt, subseq, fcc_present); ENDTRACE e.ev_number = AK_TPDU; IncStat(ts_AK_rcvd); IncPStat(tpcb, tps_AK_rcvd); break; case XAK_TPDU_type: if (tpcb->tp_xtd_format) {#ifdef BYTE_ORDER union seq_type seqeotX; seqeotX.s_seqeot = ntohl(hdr->tpdu_seqeotX); e.ATTR(XAK_TPDU).e_seq = seqeotX.s_seq;#else e.ATTR(XAK_TPDU).e_seq = hdr->tpdu_XAKseqX;#endif /* BYTE_ORDER */ } else { e.ATTR(XAK_TPDU).e_seq = hdr->tpdu_XAKseq; } e.ev_number = XAK_TPDU; IncStat(ts_XAK_rcvd); IncPStat(tpcb, tps_XAK_rcvd); break; case XPD_TPDU_type: if (tpcb->tp_xtd_format) {#ifdef BYTE_ORDER union seq_type seqeotX; seqeotX.s_seqeot = ntohl(hdr->tpdu_seqeotX); e.ATTR(XPD_TPDU).e_seq = seqeotX.s_seq;#else e.ATTR(XPD_TPDU).e_seq = hdr->tpdu_XPDseqX;#endif /* BYTE_ORDER */ } else { e.ATTR(XPD_TPDU).e_seq = hdr->tpdu_XPDseq; } takes_data = TRUE; e.ev_number = XPD_TPDU; IncStat(ts_XPD_rcvd); IncPStat(tpcb, tps_XPD_rcvd); break; case DT_TPDU_type: { /* the y option will cause occasional packets to be dropped. * A little crude but it works. */ IFDEBUG(D_DROP) if(time.tv_usec & 0x4 && hdr->tpdu_DTseq & 0x1) { IncStat(ts_ydebug); goto discard; } ENDDEBUG } if (tpcb->tp_class == TP_CLASS_0) { tp0_data: e.ATTR(DT_TPDU).e_seq = 0; /* actually don't care */ e.ATTR(DT_TPDU).e_eot = (((struct tp0du *)hdr)->tp0du_eot); } else if (tpcb->tp_xtd_format) {#ifdef BYTE_ORDER union seq_type seqeotX; seqeotX.s_seqeot = ntohl(hdr->tpdu_seqeotX); e.ATTR(DT_TPDU).e_seq = seqeotX.s_seq; e.ATTR(DT_TPDU).e_eot = seqeotX.s_eot;#else e.ATTR(DT_TPDU).e_seq = hdr->tpdu_DTseqX; e.ATTR(DT_TPDU).e_eot = hdr->tpdu_DTeotX;#endif /* BYTE_ORDER */ } else { e.ATTR(DT_TPDU).e_seq = hdr->tpdu_DTseq; e.ATTR(DT_TPDU).e_eot = hdr->tpdu_DTeot; } if(e.ATTR(DT_TPDU).e_eot) IncStat(ts_eot_input); takes_data = TRUE; e.ev_number = DT_TPDU; IncStat(ts_DT_rcvd); IncPStat(tpcb, tps_DT_rcvd); break; case GR_TPDU_type: tp_indicate(T_DISCONNECT, tpcb, ECONNABORTED); /* drop through */ default: /* this should NEVER happen because there is a * check for dutype well above here */ error = E_TP_INV_TPDU; /* causes an ER */ IFDEBUG(D_TPINPUT) printf("INVALID dutype 0x%x\n", hdr->tpdu_type); ENDDEBUG IncStat(ts_inv_dutype); goto respond; } } /* peel off the tp header; * remember that the du_li doesn't count itself. * This may leave us w/ an empty mbuf at the front of a chain. * We can't just throw away the empty mbuf because hdr still points * into the mbuf's data area and we're still using hdr (the tpdu header) */ m->m_len -= ((int)hdr->tpdu_li + 1); m->m_data += ((int)hdr->tpdu_li + 1); if (takes_data) { int max = tpdu_info[ hdr->tpdu_type ] [TP_MAX_DATA_INDEX]; int datalen = tpdu_len - hdr->tpdu_li - 1, mbtype = MT_DATA; struct { struct tp_disc_reason dr; struct cmsghdr x_hdr; } x;#define c_hdr x.x_hdr register struct mbuf *n; CHECK( (max && datalen > max), E_TP_LENGTH_INVAL, ts_inv_length, respond, (max + hdr->tpdu_li + 1) ); switch( hdr->tpdu_type ) { case CR_TPDU_type: c_hdr.cmsg_type = TPOPT_CONN_DATA; goto make_control_msg; case CC_TPDU_type: c_hdr.cmsg_type = TPOPT_CFRM_DATA; goto make_control_msg; case DR_TPDU_type: x.dr.dr_hdr.cmsg_len = sizeof(x) - sizeof(c_hdr); x.dr.dr_hdr.cmsg_type = TPOPT_DISC_REASON; x.dr.dr_hdr.cmsg_level = SOL_TRANSPORT; x.dr.dr_reason = hdr->tpdu_DRreason; c_hdr.cmsg_type = TPOPT_DISC_DATA; make_control_msg: datalen += sizeof(c_hdr); c_hdr.cmsg_len = datalen; c_hdr.cmsg_level = SOL_TRANSPORT; mbtype = MT_CONTROL; MGET(n, M_DONTWAIT, MT_DATA); if (n == 0) {m_freem(m); m = 0; datalen = 0; goto invoke; } if (hdr->tpdu_type == DR_TPDU_type) { datalen += sizeof(x) - sizeof(c_hdr); bcopy((caddr_t)&x, mtod(n, caddr_t), n->m_len = sizeof(x)); } else bcopy((caddr_t)&c_hdr, mtod(n, caddr_t), n->m_len = sizeof(c_hdr)); n->m_next = m; m = n; /* FALLTHROUGH */ case XPD_TPDU_type: if (mbtype != MT_CONTROL) mbtype = MT_OOBDATA; m->m_flags |= M_EOR; /* FALLTHROUGH */ case DT_TPDU_type: for (n = m; n; n = n->m_next) { MCHTYPE(n, mbtype); } invoke: e.ATTR(DT_TPDU).e_datalen = datalen; e.ATTR(DT_TPDU).e_data = m; break; default: printf( "ERROR in tp_input! hdr->tpdu_type 0x%x takes_data 0x%x m 0x%x\n", hdr->tpdu_type, takes_data, m); break; } /* prevent m_freem() after tp_driver() from throwing it all away */ m = MNULL; } IncStat(ts_tpdu_rcvd); IFDEBUG(D_TPINPUT) printf( "tp_input: before driver, state 0x%x event 0x%x m 0x%x", tpcb->tp_state, e.ev_number, m ); printf(" e.e_data 0x%x\n", e.ATTR(DT_TPDU).e_data); printf("takes_data 0x%x m_len 0x%x, tpdu_len 0x%x\n", takes_data, (m==MNULL)?0:m->m_len, tpdu_len); ENDDEBUG error = tp_driver(tpcb, &e); ASSERT(tpcb != (struct tp_pcb *)0); ASSERT(tpcb->tp_sock != (struct socket *)0); if( tpcb->tp_sock->so_error == 0 ) tpcb->tp_sock->so_error = error; /* Kludge to keep the state tables under control (adding * data on connect & disconnect & freeing the mbuf containing * the data would have exploded the tables and made a big mess ). */ switch(e.ev_number) { case CC_TPDU: case DR_TPDU: case CR_TPDU: m = e.ATTR(CC_TPDU).e_data; /* same field for all three dutypes */ IFDEBUG(D_TPINPUT) printf("after driver, restoring m to 0x%x, takes_data 0x%x\n", m, takes_data); ENDDEBUG break; default: break; } /* Concatenated sequences are terminated by any tpdu that * carries data: CR, CC, DT, XPD, DR. * All other tpdu types may be concatenated: AK, XAK, DC, ER. */separate: if ( takes_data == 0 ) { ASSERT( m != MNULL ); /* * we already peeled off the prev. tp header so * we can just pull up some more and repeat */ if( m = tp_inputprep(m) ) { IFDEBUG(D_TPINPUT) hdr = mtod(m, struct tpdu *); printf("tp_input @ separate: hdr 0x%x size %d m 0x%x\n", hdr, (int) hdr->tpdu_li + 1, m); dump_mbuf(m, "tp_input after driver, at separate"); ENDDEBUG IncStat(ts_concat_rcvd); goto again; } } if ( m != MNULL ) { IFDEBUG(D_TPINPUT) printf("tp_input : m_freem(0x%x)\n", m); ENDDEBUG m_freem(m); IFDEBUG(D_TPINPUT) printf("tp_input : after m_freem 0x%x\n", m); ENDDEBUG } return (ProtoHook) tpcb;discard: /* class 4: drop the tpdu */ /* class 2,0: Should drop the net connection, if you can figure out * to which connection it applies */ IFDEBUG(D_TPINPUT) printf("tp_input DISCARD\n"); ENDDEBUG IFTRACE(D_TPINPUT) tptrace(TPPTmisc, "tp_input DISCARD m", m,0,0,0); ENDTRACE m_freem(m); IncStat(ts_recv_drop); return (ProtoHook)0;nonx_dref: switch (dutype) { default: goto discard; case CC_TPDU_type: /* error = E_TP_MISM_REFS; */ break; case DR_TPDU_type: error |= TP_ERROR_SNDC; }respond: IFDEBUG(D_TPINPUT) printf("RESPOND: error 0x%x, errlen 0x%x\n", error, errlen); ENDDEBUG IFTRACE(D_TPINPUT) tptrace(TPPTmisc, "tp_input RESPOND m error sref", m, error, sref, 0); ENDTRACE if (sref == 0) goto discard; (void) tp_error_emit(error, (u_long)sref, (struct sockaddr_iso *)faddr, (struct sockaddr_iso *)laddr, m, errlen, tpcb, cons_channel, dgout_routine); IFDEBUG(D_ERROR_EMIT) printf("tp_input after error_emit\n"); ENDDEBUG#ifdef lint printf("",sref,opt);#endif /* lint */ IncStat(ts_recv_drop); return (ProtoHook)0;}/* * NAME: tp_headersize() * * CALLED FROM: * tp_emit() and tp_sbsend() * TP needs to know the header size so it can figure out how * much data to put in each tpdu. * * FUNCTION, ARGUMENTS, and RETURN VALUE: * For a given connection, represented by (tpcb), and * tpdu type (dutype), return the size of a tp header. * * RETURNS: the expected size of the heade in bytesr * * SIDE EFFECTS: * * NOTES: It would be nice if it got the network header size as well. */inttp_headersize(dutype, tpcb) int dutype; struct tp_pcb *tpcb;{ register int size = 0; IFTRACE(D_CONN) tptrace(TPPTmisc, "tp_headersize dutype class xtd_format", dutype, tpcb->tp_class, tpcb->tp_xtd_format, 0); ENDTRACE if( !( (tpcb->tp_class == TP_CLASS_0) || (tpcb->tp_class == TP_CLASS_4) || (dutype == DR_TPDU_type) || (dutype == CR_TPDU_type) )) { printf("tp_headersize:dutype 0x%x, class 0x%x", dutype, tpcb->tp_class); /* TODO: identify this and GET RID OF IT */ } ASSERT( (tpcb->tp_class == TP_CLASS_0) || (tpcb->tp_class == TP_CLASS_4) || (dutype == DR_TPDU_type) || (dutype == CR_TPDU_type) ); if( tpcb->tp_class == TP_CLASS_0 ) { size = tpdu_info[ dutype ] [TP_LEN_CLASS_0_INDEX]; } else { size = tpdu_info[ dutype ] [tpcb->tp_xtd_format]; } return size; /* caller must get network level header size separately */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -