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

📄 tcpmisc.c

📁 用于嵌入式系统的TCP/IP协议栈及若干服务
💻 C
📖 第 1 页 / 共 5 页
字号:
 for (svp = (tcpsv_t *)tcp_q.q_next; svp != (tcpsv_t *)&tcp_q;                   svp = (tcpsv_t *)svp->sv_q.q_next) {     if ( (svp->sv_state == CLOSED) || (svp->sv_state == LISTEN) )            continue;     /* Note: tcp_set_send_mss will make sure that if the path MTU	    is larger than the MSS the peer sent us in a SYN MSS option,		that we don't set the MSS larger than that option. */     if (svp->sv_dest.ip_nethost == hostaddr) {        tcp_set_send_mss (svp, (u16) new_mss, TCP_MSS_SOURCE_PATH_MTU );	 } } /* for */ return(0);} /* tcp_pmtu_change_notif */#endif /* IP_RFC_1191 *//*************************************************************************                                                                       **  Function :                                                           **                                                                       **  Description :                                                        **                                                                       **                                                                       **  Parameters : None.                                                   **                                                                       **  Return : None.                                                       **                                                                       *************************************************************************//* 'ip_icmp' calls on us here.  Two types of ICMP messages arrive here; * Destination unreachable and Source Quench. */export  st      tcp_icmp (fast m * mp){    fast    u8      type;    fast    u8      code;    fast    TCPH_T  * tcphp;    fast    tcpsv_t * svp;    int     err;    use_critical;    trace0(tcp_trace, "tcp_icmp:\n");    type = (u8)mp->m_p0;            /* ICMP type */     code = (u8)mp->m_p1;            /* ICMP code */    /* The tcp header in this context only contains port numbers and     * a sequence number */    debug2(tcp_debug, "tcp_icmp: received icmp packet, type %d, code, %d\n", type, code);    /* pointer to bogus TCP packet (8 bytes worth) */    tcphp = (TCPH_T *)mp->m_cp;    err = FNS_ENOERR;    /* scan the tcp_q for state vectors to harass */    critical;    svp = (tcpsv_t *)tcp_q.q_next;    while (svp != (tcpsv_t *)&tcp_q)     {        sv_bind(svp, tcp_icmp, true);        normal;        if (svp->sv_q.q_flags & F_Q_ZAPPED) /* it's a zombie! */            goto nextone;        if (svp->sv_state == CLOSED)            /* don't target closed state vectors */            goto nextone;        /* source, destination ports and destination host must         * match EXACTLY */        if ( (ntohs(svp->sv_src.ip_port) == NetToHost16(&tcphp[TCPH_SPORT]) )          && (ntohs(svp->sv_dest.ip_port) == NetToHost16(&tcphp[TCPH_DPORT]) )          && (svp->sv_dest.ip_nethost == mp->m_dest.a_ipa.ip_nethost) )        { /* match */            fast    so_t    * sop;          switch (type) {            case ICMP_DUR:  /* destination unreachable message */#if 0  /* removed by MBM when implementing path MTU discovery */				if (svp->sv_state != SYN_SENT)                /* only affect connections */                    break;#endif                /* Set the error code according to the condtion being				   reported */                 switch (code) {                    case DUR_FRAG:  /* frag. needed & DF set */					   /* By the time this notification gets delivered to						  us, we will already have adjusted our MSS due to						  the broadcast PMTU change notification we received 						  (done from ip_icmp before sending this message up						  to us). The only thing to do here is initiate 						  retransmission because we are being informed that 						  a segment was discarded on this connection. That						  retransmission will use the new, smaller MSS */					    (void) t_start(svp->sv_rextcb, 1);						break;                    case DUR_HOST:  /* host unreachable */                       err = FNS_EHOSTUNREACH; break;                    case DUR_PROTO: /* protocol unreachable */					   err = FNS_ENOPROTOOPT; break;                    case DUR_PORT:  /* port unreachable */                       err = FNS_ECONNREFUSED; break;                       err = FNS_EMSGSIZE; break;                    case DUR_NET:   /* network unreachable */                       svp->sv_err = FNS_ENETUNREACH; break;                    case DUR_ROUTE: /* source route failed */                    default:        /* some bogus code */                       err = FNS_ENETUNREACH; break;                 } /* switch */				 /* If its a fatal error for the connection, reset ourselves. 				    Otherwise, we've already done the processing we need to do for				    this message */				 if (err != FNS_ENOERR) {                    tcp_rslf(svp, err);				 }                 break;            case ICMP_SQ :  /* source quench message */                /* Here we immediately drop the send queue                 * size to one, and set (or increase) the                 * amount of time we will leave it at one                 * before starting to increase it.  The                 * countdown is decremented in tcp_perftimer,                 * and there the send queue size is gradually                 * increased back to the maximum, if no                 * further SQ requests come in.                 */                sop = sv_valid_sop(svp, sop);                if (sop != (so_t *)0) {                    gq_max_set(&sop->so_sq, (int)svp->sv_mss);                    /* Set (or increase) slowdown period */                    svp->sv_sqcntdwn += 60000 / MS_PER_TICK;                    /* Go into re-xmit mode */                    svp->sv_flags |= SV_RIP;#ifdef TCP_SS_CA_FRETR_FREC                     M32M(svp->sv_rexmt_seqno, =, svp->sv_suna);#endif                }                break;            }        }nextone:        /* detach the state vector, and pick up the next one */        critical;        svp = sv_detach(svp, tcp_icmp, true);    } /* switch */    normal;    return (st)mp->m_dispfn;}#ifdef TCP_QUIET/* turn off tcp_quiet time and wakeup any process that is napping on * this event *//*ARGSUSED; this routine is called from a table, so * uarg is declared but not used*/pflocal int     tcp_noisy (void * uarg){    tcp_quiet = (tcb *)0;    os_wakeup((char *)&tcp_quiet);    return 0;}#endif/* TCP initialization */export  int     tcpinit (pr_t * prp){    trace0(tcp_trace, "tcpinit:\n");    if (!tcp_initialized) {#ifdef TCP_QUIET                        i32     residual;#endif        tcp_initialized = true;        tcp_port = ((int) OS_RAND) & 0xFF;        q_init(&tcp_q, F_Q_HEADER);        tcp_prp = prp;#ifdef TCP_QUIET    /* TCP quiet time [9.2.14.3.1, pg. 88] */    /* BOOT_TIME is the minimum amount of time (in seconds)     * that it takes for the system to boot-up (cold boot) UNTIL     * FUSION first initializes (gets to this routine).  Since     * TCP cannot know what previously used sequence numbers     * have been used in earlier lifes, it must wait for one     * maximum segment lifetime (4:15 minutes) UNTIL it generates     * any TCP segment.  Since there is no way for TCP to be     * generating segments during reboot, the amount of time     * it takes to reboot can be subtracted out, thus allowing     * the use of TCP somewhat sooner.     *     * BOOT_TIME is a configuration dependant constant, and     * should be defined in <config.h>     */    /* Fudge BOOT_TIME by 5 seconds */        residual = ONEMSL - (max((u32)BOOT_TIME - 5, 0)*1000L);        residual = max(1, residual);        /* start the timer for tcp_quiet */        tcp_quiet = t_new((tcb *)0, tcp_noisy, (void *)0, (u32)residual, F_T_ONESHOT);#endif#ifdef TCP_TRANSACTION_TCP    t_tcp_initialize();#endif /* TCP_TRANSACTION_TCP */	    }            return 0;       /* indicate that TCP is now up */}/******************************************************************************//* * Used by getpeername and getsockname,  Getpeername * is type 1, getsockname is type 2.  Note that * getpeername is only valid if we're connected. */export  inttcp_outaddr (so_t * sop, saddr * name, int * namelen, int type){    fast                tcpsv_t * svp;    struct in_sockaddr  * is_addrp;    use_critical;    if ((name == (saddr *)0) || (namelen == (int *)0) ||         (*namelen < sizeof(struct in_sockaddr)))        return FNS_EFAULT;            *namelen = min(sizeof(struct in_sockaddr), *namelen);    is_addrp = (struct in_sockaddr *)name;    critical;    if ((svp = sop->so_svp) == (tcpsv_t *)0) {        normal;        debug0(tcp_debug, "tcp_outaddr: no state vector\n");        return FNS_ENOTCONN;    }    if( type ) {        /* Not connected */        switch (svp->sv_state) {        case SYN_RECVD:        case ESTAB:                   case FIN1_WAIT:        case FIN2_WAIT:        case LAST_ACK:            break;        default:            normal;            return FNS_ENOTCONN;        }    }    sv_bind(svp, tcp_outaddr, true);    normal;    is_addrp->sin_family = AF_INET;    if (type == 0) /* source address */    {        is_addrp->sin_addr.s_addr = svp->sv_src.ip_nethost;        is_addrp->sin_port = ntohs(svp->sv_src.ip_port);    }    else /* destination address */    {        is_addrp->sin_addr.s_addr = svp->sv_dest.ip_nethost;        is_addrp->sin_port = ntohs(svp->sv_dest.ip_port);            }    sv_detach(svp, tcp_outaddr, true);    return 0;}/******************************************************************************/export  void sv_nstate (fast char * msg, fast tcpsv_t * svp, fast u16 new_state){#ifdef DEBUG    so_t    * sop;#endif    use_critical;    critical;    assert(svp->sv_refcnt != 0, "sv_nstate: state vector not bound\n");    assert(new_state <= TIME_WAIT, "sv_nstate: bogus new state\n");#ifdef  DEBUG    if (msg == (char *)0)        msg = "<dunno>";    if (svp->sv_state != new_state) { /* state change */    /*  compute sop once */        sop = svp->sv_sop;        if (sop == (so_t *)0)            trace3(tcp_tstate, "%s: [*] %s => %s\n", msg, tcp_st(svp->sv_state), tcp_st(new_state));        else            trace4(tcp_tstate, "%s: [%d] %s => %s\n", msg, sop->so_index, tcp_st(svp->sv_state), tcp_st(new_state));    }#endif#if 0	/* debugging stuff put in by MBM */    {static int ctr = 0;	 os_printf("\n(%u) sv_nstate -- (svp=%p) (%d): transitioning from %d to %d\n",		              t_time,svp,++ctr,svp->sv_state,new_state);	}#endif    svp->sv_state = new_state;    if (svp->sv_refcnt > 1)        os_wakeup((char *)&svp->sv_state);    normal;}/* bind a state vector and a socket together */export  void    sv_so_bind (fast tcpsv_t * svp, fast so_t * sop){    use_critical;    /* the state vector must be given to us bound */    assert(svp->sv_refcnt != 0, "sv_so_bind: svp not bound\n");    critical;    assert(sop->so_svp == (tcpsv_t *)0, "sv_so_bind: socket already bound\n");    assert(svp->sv_sop == (so_t *)0, "sv_so_bind: state vector already bound (incorrectly too...)\n");    sv_bind(sop->so_svp = svp, sop, false); /* bind here because socket references it */    svp->sv_sop = sop;    svp->sv_soindx = sop->so_index; /* for validation use later */    normal;}/* remove the socket binding from a state vector */export  void    sv_so_detach (fast tcpsv_t * svp){    fast    so_t * sop;    use_critical;    critical;    sop = svp->sv_sop;    if (sop == (so_t *)0) {        normal;        debug0(tcp_debug, "sv_so_detach: no sop\n");        return;    }    sop->so_svp = (tcpsv_t *)0;    svp->sv_sop = (so_t *)0;    svp->sv_soindx = 0;    sv_detach(svp, sop, false);}#if defined(SNMP) || defined(WANT_NETWORK_STATISTICS) export  u32     countTcpCurrEstab (void){    fast    tcpsv_t * svp;    u32 count;    use_critical;    count = 0;    if (tcp_prp == (pr_t *)0)        return count;   /* allow time to initialize */    critical;    for (svp = (tcpsv_t *)tcp_q.q_next; svp != (tcpsv_t *)&tcp_q;               svp = (tcpsv_t *)svp->sv_q.q_next) 

⌨️ 快捷键说明

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