📄 tcpxmit.c
字号:
tcp_rslf(nsvp, nsvp->sv_err); break; }#endif /* TCP_TRANSACTION_TCP */ /* Make sure the previous connection still an "active" one before rejecting the new one */ if (nsvp->sv_state != CLOSED) { normal; return(FNS_EADDRINUSE); } } /* for */ normal; } /* if ACK_OFF */ /****************************************************************************/ /* Obtain the MTU of the interface to which the SYN has been routed */ if_mtu = ndp->nd_ipmtu;#ifdef IP_RFC_1191 /* Obtain the path MTU to the destination to which the SYN is being sent. If path MTU not available, use the MTU of the interface to which this SYN has been routed. Compute the largest TCP segment this implies (P/MTU minus the maximum size of all of the protocol headers) */ send_mss = ip_get_path_mtu(svp->sv_dest.ip_nethost); if (send_mss == -1) {#endif /* IP_RFC_1191 */ send_mss = if_mtu; mss_source = TCP_MSS_SOURCE_IF_MTU;#ifdef IP_RFC_1191 } else { mss_source = TCP_MSS_SOURCE_PATH_MTU; }#endif /* IP_RFC_1191 */ send_mss -= (SIZEOF_TCPH_T+IP_MHL); /* The value we advertise as our receive MSS will be based on the interface MTU, unless it has been specified from some other source (presumably the TCP_SET_RCV_MSS socket option (this is what will be sent in the MSS option field of this SYN) */ if (svp->sv_rcv_mss == 0) { svp->sv_rcv_mss = (if_mtu - (SIZEOF_TCPH_T+IP_MHL)); } critical; /* Tell our "wizard" for setting the send MSS this interface-MTU-derived value. This "wizard" will decide whether to use it or not. */ tcp_set_send_mss(svp, (u16)send_mss,mss_source ); /* also, do any adjustments on the initial round-trip-time * and ack delay values */ /* Initialize the values used for the smooth round trip time algorithm and retransmission delay timer */ if (svp->sv_srtt == (u32)0L) {#ifdef TCP_TRANSACTION_TCP /* For transaction TCP, if we have cached a round trip time measurment from a previous connection, remember that here and use it for the initial value of this connection */ if (svp->sv_t_tcp_flags & SV_TRANSACTION) { t_tcp_cache_entry_ *ce; /* Must be critical here */ ce = t_tcp_find_cache_entry(svp->sv_dest.ip_nethost); if (ce) { svp->sv_srtt = ce->ce_srtt; /* os_printf("\ntxp_xmit: setting srtt to cached value %u\n",svp->sv_srtt); */ } } if (svp->sv_srtt == (u32)0L) { /* in case we didn't find cache entry */#endif /* TCP_TRANSACTION_TCP */ /* Initial value for smoothed round-trip-time measurement algorithm */ svp->sv_srtt = SRTT_INITIAL_VALUE;#ifdef TCP_TRANSACTION_TCP }#endif /* TCP_TRANSACTION_TCP */ /* Initial value for the retransmit timer, until we obtain a round-trip time measurement */ svp->sv_retrtim = svp->sv_initretrim; /* Note from MBM: The following line puzzles me -- it looks like its saying "If the retransmission timer is already running, stop it and start it with the initial value of the retransmit timer.". What about the case where the timer is not presently running? */ if (!t_stopped(svp->sv_rextcb)) { t_start(svp->sv_rextcb, svp->sv_retrtim); } } normal; /* set option values into the segment */ tcp_dink_syn_options(tcphp,svp); if ( ACK_ON(flags) ) /* This is a SYN|ACK. Time to open up the receive * queue based on the final MSS negotiated. */ tcp_rmax_set(svp); } /* if SYN_ON */ sop = sv_valid_sop(svp, sop); if ( svp && ACK_ON(flags) ) { /* Time to compute the receive window. For outbound packets, * this is the only place that this is done. This insures * that at the start of a connection, the sv_mss has already * been completely negotiated. */ if ( svp->sv_flags & SV_RFINFLG ) /* FIN seen -- nothing more expected */ u1 = 0; else if ( sop && sop->so_rq.gq_inuse ) /* socket has buffer capacity, but silly window avoidance may dictate that we not presently advertise it */ u1 = tcp_rwind_to_advertise(svp); else /* leave room for the FIN */ u1 = 1; HostToNet16(&tcphp[TCPH_WINDOW], u1); /* Restart the counter of how many bytes read from the socket since we acked */ svp->sv_rcvsncwupd = 0;#ifdef TCP_TIMESTAMPS /* RFC 1323 requires us to keep track of last sequence number that has been ACKED, which may not be caught up to RCV.NEXT when ACKs are being delayed */ M32U(svp->sv_last_ack_sent, = , NetToHost32(&tcphp[TCPH_ACKNO]));#endif } else {#ifdef TCP_TRANSACTION_TCP /* If transaction TCP and we are still sending our request and have not yet received the SYN-ACK response to our initial SYN-DATA segment (thus the receive queue has not been "opened up" yet), we need to advertise a window anyway -- otherwise, their SYN-ACK could not contain any data, defeating the purpose of transaction TCP */ if ( svp && (svp->sv_t_tcp_flags & SV_TRANSACTION) ) { HostToNet16(&tcphp[TCPH_WINDOW],svp->sv_rq_max ); } else #endif HostToNet16(&tcphp[TCPH_WINDOW], (u16)0); }/* msd: restore the source address of the message if this isn't an * initial connection; this insures that despite the actual link * layer device chosen by the router, the socket will not appear * to 'move' addresses and thus become disconnected */ if ((SYN_OFF(flags) || ACK_ON(flags)) && svp) { HostToMem32(&(m_ptr(mp,IPH_T)[IPH_SADDR]), svp->sv_src.ip_nethost); mp->m_src.a_ipa.ip_nethost = svp->sv_src.ip_nethost; /* for ARP, ULP */ } /* scrutinize the TTL of the IP packet; adjust the socket's current * TTL value upward (bounding has been done by 'ip_dink') */ if (sop && (u1 = m_ptr(mp, IPH_T)[IPH_TTL]) > ipsu.ipsu_ttl) ipsu.ipsu_ttl = (u8)u1;/* Compute TCP header checksum. This packet is on its way to the network. * This is the last time TCP will deal with this packet. */ piphp = &m_ptr(mp, IPH_T)[IPH_PIPH]; zbsave = piphp[PIPH_ZERO]; /* don't blast the TTL */ piphp[PIPH_ZERO] = 0; /* The piph_protocol field is assumed to be correct here. */ u1 = mp->m_tp - mp->m_cp; /* length of TCP header + data */ HostToNet16(&piphp[PIPH_LENGTH], u1); HostToNet16(&tcphp[TCPH_CHECKSUM], oc_sum((a16 *)piphp, SIZEOF_PIPH_T)); checksum = ~oc_sum((a16 *)tcphp, u1); if ( checksum == 0xFFFF) checksum = 0; HostToNet16(&tcphp[TCPH_CHECKSUM], checksum); piphp[PIPH_ZERO] = zbsave; critical; smfhist(mp, tcp_dink);#ifdef TRACE trace1(tcp_tstate, "tcp_dink: src(%s)[", ipa2str(&mp->m_src.a_ipa, (char *)0)); if (tcp_tstate) { if (valid_sop(mp)) os_printf("%d", mp->m_soindx); else os_printf("*"); os_printf("] => dest(%s) <%s>\n", ipa2str(&mp->m_dest.a_ipa, (char *)0), tcp_pf(flags)); }#endif /*TRACE*/ normal; TCP_TRACE_SEGMENT(mp, 0); return 0;} /* tcp_dink *//* Outbound transmission point. * Final TCP header construction before checksum. */ export st tcp_xmit (fast m * mp){ fast TCPH_T * tcphp; use_critical; critical; trace1(tcp_trace, "tcp_xmit(0x%x):\n", mp); normal; tcphp = (TCPH_T *)mp->m_cp; HostToMem16(&tcphp[TCPH_SPORT], mp->m_src.a_ipa.ip_port); HostToMem16(&tcphp[TCPH_DPORT], mp->m_dest.a_ipa.ip_port); mp->m_type = tcp_prp->pr_protocol; /* so IP can target 'tcp_dink' */ critical; if (mp->m_svp != (tcpsv_t *)0) mp->m_prec = mp->m_svp->sv_prec; /* pass precedence back down under; if there is no state vector, */ /* then the precedence will already be set here. */ normal;#ifdef TCP_STATS ++tcp_txmit;#endif INC_MIB_CNTR_TCP_OUT_SEGMENTS#ifndef AVOID_MSM return (st)ip_send;#else return(ip_send(mp));#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -