⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcpnetd.c

📁 用于嵌入式系统的TCP/IP协议栈及若干服务
💻 C
📖 第 1 页 / 共 5 页
字号:
/**            Copyright (c) 1998-2001 by NETsilicon Inc.**  This software is copyrighted by and is the sole property of*  NETsilicon.  All rights, title, ownership, or other interests*  in the software remain the property of NETsilicon.  This*  software may only be used in accordance with the corresponding*  license agreement.  Any unauthorized use, duplication, transmission,*  distribution, or disclosure of this software is expressly forbidden.**  This Copyright notice may not be removed or modified without prior*  written consent of NETsilicon.**  NETsilicon, reserves the right to modify this software*  without notice.**  NETsilicon*  411 Waverley Oaks Road                  USA 781.647.1234*  Suite 227                               http://www.netsilicon.com*  Waltham, MA 02452                       AmericaSales@netsilicon.com***************************************************************************  $Name: Fusion 6.52 fix from 1.51.1.3 $*  $Date: 2002/04/18 13:40:02 $*  $Source: M:/psisrc/stack/tcp/rcs/tcpnetd.c $*  $Revision: 1.58.1.4 $***************************************************************************                         - Revision Log -                              ** Who   When        Why** FND   01/05/01    Rename t_start/t_delete to fns_t_start/fns_t_delete*                   to fix conflict with pSOS.****************************************************************************  File Description:  TCP - Transmission Control Protocol*                     Contains routines related to the TCP state machine**************************************************************************/#include "std.h"#include "flags.h"#include "ip.h"#include "m.h"#include "select.h"#include "so.h"#include "socket.h"#include "tcp.h"#include "timer.h"#include "nerrno.h"#include "debug.h"#include "fnsmib.h"#include "fnsproto.h"/* #define PRINT_ACKS *//* #define PRINT_RETR_FSM  */#define t_start fns_t_start#define t_delete fns_t_deletepflocal st  tcp_active(fast m * mp);local void tcp_urgdata(fast m *mp);local void tcp_urgstate (fast m *mp);pflocal st  tcp_copen(fast m * mp);local   void    tcp_estab(fast tcpsv_t * svp);pflocal st  tcp_naccept(fast m * mp);pflocal st  tcp_nstate(fast m * mp);pflocal st  tcp_passive(fast m * mp);pflocal int tcp_process_hold_queue(m *mp);local   int tcp_secmatch(fast m * mp);local   int tcp_spmatch(fast m * mp);local   void    tcp_stw(fast tcpsv_t * svp, fast u8 residual);local   int    tcp_upout(void * lsvp, void * unusedp);local   void    tcp_update(m * dmp);#ifdef PRINT_ACKSvoid print_insack_table(tcpsv_t *svp);#endif#ifdef TCP_KEEP_ALIVEimport  u32     tcp_idle_interval;import  boolean tcp_keep_alive;#endifimport  u32 nc_hsize, tcp_try_max;#ifdef  TRACEimport  boolean tcp_tat, tcp_thq, tcp_tnetd;import  boolean tcp_tpassive, tcp_trace, tcp_trcv;import  boolean tcp_treset, tcp_trslf, tcp_tud, tcp_turgent;#endif#ifdef  DEBUGimport  boolean tcp_debug;#endif#ifdef MSD_DEBUGimport  boolean msd_debug;                  /*msddebug*/import  u32 tcprackz;#endif/*************************************************************************                                                                       **  Function :                                                           **                                                                       **  Description :                                                        **                                                                       **                                                                       **  Parameters : None.                                                   **                                                                       **  Return : None.                                                       **                                                                       *************************************************************************//* Table VIII. Net deliver in a SYN_SENT state. [107] */pflocal st  tcp_active (fast m * mp){    fast    tcpsv_t * svp;    fast    u16 flags;    fast    TCPH_T  * tcphp;    fast    u32 ackno;    use_critical;    trace0(tcp_trace, "tcp_active:\n");    if ((svp = mp->m_svp) == (tcpsv_t *)0) {        debug0(tcp_debug, "tcp_active: no state vector\n");        return (st)mp->m_dispfn;    /* --no action */    }    assert(svp->sv_refcnt != 0, "tcp_active: sv not bound\n");    tcphp = (TCPH_T *)mp->m_cp;    flags = NetToHost16(&tcphp[TCPH_FLAGS]);    ackno = NetToHost32(&tcphp[TCPH_ACKNO]);    if (ACK_OFF(flags)) {   /* ACK status 1 : NONE */        trace0(tcp_tat, "tcp_active: ACK_OFF\n");        if (RST_ON(flags))            return (st)mp->m_dispfn;    /* --no action */        if (tcp_secmatch(mp) == NO) {            debug0(tcp_debug, "tcp_active: sending reset, tcp_secmatch failed\n");            return (st)tcp_reset;        }        if (SYN_OFF(flags))            return (st)mp->m_dispfn;    /* --no action */        svp->sv_src.ip_nethost = mp->m_dest.a_ipa.ip_nethost;        tcp_rsyn(mp);        if (svp->sv_prec < mp->m_prec)            svp->sv_prec = (u8)mp->m_prec;  /* raise precedence */        tcp_sndack(mp, svp);        if (FIN_ON(flags))  /* save_fin 9.4.6.3.38 [154] */            svp->sv_flags |= SV_RFINFLG;        return (st)mp->m_dispfn;    }    if (UC32M(ackno, <=, svp->sv_suna)  ||  UC32M(ackno, >, svp->sv_snxt)) {#ifdef TCP_TRANSACTION_TCP		/* RFC 1644 says (section 3.4, R2.1): "If SEG.ACK is not acceptable and		   cache.CCsent[fh] is non-zero, then simply drop the segment without 		   sending a RST. (The new SYN that the client is (re-)transmitting will		   eventually acknowledge any outstanding data and FIN at the server.)" */		{         if ( (svp->sv_t_tcp_flags & SV_TRANSACTION) && (SYN_ON(flags)) ) {		    t_tcp_cache_entry_ *ce = t_tcp_find_cache_entry(svp->sv_dest.ip_nethost);			if ( (ce) && (ce->ce_ccsent != 0) ) {               return (st)mp->m_dispfn;			}		 } /* if */		}#endif /* TCP_TRANSACTION_TCP */        /* ACK status 1 : INVALID */        /* 'tcp_reset' will not send the reset if RST is set */        debug0(tcp_debug, "tcp_active: sending reset, invalid ack\n");        return (st)tcp_reset;    }    /* ACK status 1 : VALID */    if (RST_ON(flags)) {    /* openfail */        /* The peer has refused this connection request for whatever reason. Abort		   the connection -- application can retry */        /* 'tcp_rslf' changes state to CLOSED */        tcp_rslf(svp, FNS_ECONNREFUSED);        return (st)mp->m_dispfn;    }    critical;    if (svp->sv_sop == (so_t *)0) { /* socket has gone away */        debug0(tcp_debug, "tcp_active: sending reset, no socket\n");        normal;        return (st)tcp_reset;    }    if (tcp_secmatch(mp) == NO  ||  svp->sv_prec > mp->m_prec) {        debug0(tcp_debug, "tcp_active: sending reset, sec/PREC fails\n");        debug1(tcp_debug, "tcp_active: tcp_secmatch = %d\n", tcp_secmatch(mp));        debug1(tcp_debug, "tcp_active: svp->sv_prec = %d\n", svp->sv_prec);        debug1(tcp_debug, "tcp_active: mp->m_prec = %d\n", mp->m_prec);        normal;        return (st)tcp_reset;    }    if (SYN_OFF(flags)) {        normal;        return (st)mp->m_dispfn;    /* --no action */	}#ifdef TCP_TRANSACTION_TCP    if (svp->sv_t_tcp_flags & SV_TRANSACTION) {        TCPO_T *ccecho = tcp_find_option(tcphp, TCPO_CCECHO_KIND);		t_tcp_cache_entry_ *ce;	    /* RFC 1644, section 3.4 R2.2: "If the segment contains a CC.ECHO option whose	       SEG.CCECHO is different from TCB.CCsend, then the segment is unacceptable 	       and is dropped." */	    /* MBM note: Need to do this before call to tcp_rsyn because we don't want to 	       record the other options from the SYN if we are going to reject it due to 	       a bad CC.ECHO */        if (ccecho != ((TCPO_T *) 0) ) {		   if (NetToHost32(&(ccecho[TCPO_VAL])) != svp->sv_ccsend) {			  normal;              return (st)mp->m_dispfn;		   }		}		/* The same RFC, same section, R2.3: "If cache.CCsent[fh] is zero, then it is	       set to TCB.CCsend. I think this is leaving out an importnat point though --		   it fails to specify what to do if the response does not contain a CC.ECHO		   option. But Stevens Volume 3, section 3.7 clearly states that the per-host		   cache for a server that is not speaking t/tcp should never be updated, so we		   will follow that here (otherwise the next time we contact the same host,		   we would behave as if it we thought it spoke t/tcp */		/* MBM question: What if previously this host did talk t/tcp to us but this time		   it isn't? Should we now invalidate/free the cache entry for it? I'll leave that		   question for another time (what if that host had an implementation like ours,		   where transaction TCP is enabled on a per-connection basis rather than		   globally -- we wouldn't want to disrupt the cache in that circumstance, 		   would we? */        if (ccecho != ((TCPO_T *) 0) ) {		   ce = t_tcp_find_cache_entry(svp->sv_dest.ip_nethost);		   if (ce->ce_ccsent == 0) ce->ce_ccsent = svp->sv_ccsend;		}	}#endif /* TCP_TRANSACTION_TCP */	normal;    /* Parse the information, particularly the options, from this SYN */    tcp_rsyn(mp);    svp->sv_prec = (u8)mp->m_prec;  /* raise precedence */    /* MBM -- the following was taken out for Fusion 6.5 -- it is done instead	   in tcp_dink for the outgoing initial SYN. The reason is, for transaction	   TCP (and theoretically for standard TCP, though our API wouldn't provide a	   way for it to happen) we could send out multiple data segments following the	   initial SYN prior to receiving the SYN-ACK we are processing here -- and those	   segments would not have a proper source address in the IP header. */#if 0    svp->sv_src.ip_nethost = mp->m_dest.a_ipa.ip_nethost;#endif    /* send an ack, since by the time this message makes it back to     * 'tcp_net_deliver', it will have a length of 0 */	/* MBM note: For transaction TCP, because we are calling tcp_sndack here,	   this ACK will contain the CC option because our state is still recorded	   as SYN_SENT even though we've received the SYN-ACK to our SYN (the recorded	   state doesn't gets changed during the tcp_copen processing. 	      This might technically be a violation of RFC 1644 section 3.4 S3, but	   I think this is harmless, because in this situation the other end doesn't	   know T/TCP and will just ignore the CC option (at least, it ignored the	   CC or CC.NEW option we sent in the initial SYN, otherwise it would not	   have responded with the SYN-ACK we are now processing. */	/* MBM note: It is possible that this segment (in addition to the SYN we've	   just processed) also contains data and/or a FIN. If so, "tcp_copen" will	   lead to the processing of that and generating an ACK -- so sending an ACK	   here is redundant. So if this segment has anything else to process beyond	   the SYN, we avoid sending the ACK here. */ 	if (!(tcp_dl(mp) > 1)) { /* segment contains more "data" than just a SYN */       tcp_sndack(mp, svp);	}    return (st)tcp_copen;   /* conn_open */} /* tcp_active *//************************************************************************//*  Extract out-of-band data (if any) from the segment and store it in  *//*  the state vector's "urgent" buffer                                  *//*     (Urgent data notification to application will wait until         *//*      "tcp_urgstate"                                                  *//************************************************************************/local void tcp_urgdata(fast m *mp){    fast    TCPH_T  * tcphp;    fast    tcpsv_t * svp;    fast    u16 urgoff;    char    *ubp;    char    *mvp;    mp->m_oob = 0;    /* if this socket is receiving its urgent data inline, nothing to do       here */    if ( (svp = mp->m_svp) == (tcpsv_t *)0) {        debug0(tcp_debug, "tcp_urgdata: no state vector\n");        return;    }    if (svp->sv_urg_mode != SV_URGMODE_OOB) return;     /* if there is no urgent pointer within this segment, then there        is nothing to do here */    tcphp = (TCPH_T *)(mp->m_cp);    if (URG_OFF(NetToHost16(&tcphp[TCPH_FLAGS]))) return;    /* Does the urgent pointer point to data within this segment. If not,       nothing to do here */    urgoff = NetToHost16(&tcphp[TCPH_URGENT]); /* points one past urgent byte */    ubp = (mp->m_hp + urgoff - 1);    if ( ubp > mp->m_tp) return;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -