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

📄 natpkt.c

📁 代码在ti的c67系列单片机上实现了完整的TCPIP协议栈
💻 C
📖 第 1 页 / 共 2 页
字号:
    IPDst = RdNet32( &pIpHdr->dwIPDst );

    // If destination isn't us, or the source isn't from outside the
    // targeted subnet, return
    if( IPDst != NatIpServer || (IPSrc&NatIpMask) == NatIpAddr )
        return(0);

    // Get the length of the IP header
    IPHdrLen = (pIpHdr->VerLen & 0xf) * 4;

    // Translation varies slightly by protocol
    if( pIpHdr->Protocol == IPPROTO_TCP )
    {
        // TCP Packet Translation

        // Get TCP packet header
        pTcpHdr = (TCPHDR *)(((UINT8 *)pIpHdr) + IPHdrLen);

        pPortDst = &pTcpHdr->DstPort;
        pChecksum = &pTcpHdr->TCPChecksum;
        PortSrc = HNC16( pTcpHdr->SrcPort );
    }
    else if( pIpHdr->Protocol == IPPROTO_UDP )
    {
        // UDP Packet Translation
        UDPHDR  *pUdpHdr;

        // Get UDP packet header
        pUdpHdr = (UDPHDR *)(((UINT8 *)pIpHdr) + IPHdrLen);

        pPortDst = &pUdpHdr->DstPort;
        pChecksum = &pUdpHdr->UDPChecksum;
        PortSrc = HNC16( pUdpHdr->SrcPort );
    }
    else if( pIpHdr->Protocol == IPPROTO_ICMP )
    {
        // ICMP Packet Translation
        ICMPHDR *pIcHdr;
        uint    tmp;

        // Get ICMP packet header
        pIcHdr = (ICMPHDR *)(((UINT8 *)pIpHdr) + IPHdrLen);

        // First see if this is an ICMP error packet
        tmp = (uint)pIcHdr->Type;
        if( tmp==ICMP_UNREACH || tmp==ICMP_SOURCEQUENCH || tmp==ICMP_REDIRECT
                              || tmp==ICMP_TIMXCEED || tmp==ICMP_PARAMPROB )
            return( NatIcmpError( hPkt, pIpHdr ) );

        // Here we only translate ECHO and TSTAMP replies
        if( tmp != ICMP_ECHOREPLY && tmp != ICMP_TSTAMPREPLY )
            return( 0 );

        pPortDst = (UINT16 *)pIcHdr->Data;
        pChecksum = &pIcHdr->Checksum;
        PortSrc = 0;
    }
    else
        return(0);

    // Get dest port
    PortDst = *pPortDst;
    PortDst = HNC16(PortDst);

    if( !PortDst )
        return(0);

    nats.dwRxQualified++;

    // Find a NATINFO entry
    pni = NatFindPNI( 0, 0, IPSrc, PortSrc, pIpHdr->Protocol, PortDst );

    // If no NATINFO, return
    if( !pni )
        return(0);

    // Alter the destination IP and port
    nats.dwRxAltered++;

    // Change PortDst to be the NEW dest port
    PortDst = HNC16( pni->PortLocal );

    // Track changes for checksum modification (ICMP doesn't use IP address)
    if( pIpHdr->Protocol != IPPROTO_ICMP )
        CkMod = NatCkMod( IPDst, *pPortDst, pni->IPLocal, PortDst );
    else
        CkMod = NatCkMod( 0, *pPortDst, 0, PortDst );

    // Alter the packet
    WrNet32( &pIpHdr->dwIPDst, pni->IPLocal );
    *pPortDst = PortDst;

    // Adjust the TCP/UDP/ICMP checksum
    CkOrg = (UINT32) ~*pChecksum;
    CkOrg += CkMod;
    CkOrg = (CkOrg&0xFFFF) + (CkOrg>>16);
    CkOrg = ~CkOrg;
    *pChecksum = (UINT16)CkOrg;

    // Set new NAT record timeout value
    if( pIpHdr->Protocol == IPPROTO_TCP )
        NatTcpTimeout( pni, pTcpHdr );
    else
        pni->Timeout = llTimerGetTime(0) + NAT_IDLE_SECONDS;

    // The packet is now "from" us (local IF)
    // This suspends normal error checks for looping packets
    PktSetIFRx( hPkt, 0 );

    //
    // If this entry has a "proxy", we always consume the packet.
    // The proxy will forward any new packets directly to IP
    //
    if( pni->hProxyEntry )
    {
        ProxyRx( pni, hPkt, pIpHdr );
        return(-1);
    }

    return(1);
}

//--------------------------------------------------------------------
// NatIcmpError - NAT Processing of ICMP Error packets
//
// Here, we are only interested ICMP error packets, where the header
// of the offending IP datagram is attached.
//
// If this function returns 1, the packet should be re-forwarded
//--------------------------------------------------------------------
static int NatIcmpError( HANDLE hPkt, IPHDR *pIpHdr )
{
    uint    IPHdrLen;
    ICMPHDR *pIcHdr;
    uint    icmpsize;
    IPHDR   *pIpHdr2;
    NATINFO *pni;
    UINT16  PortDst;
    UINT16  *pPortDst;

    // Get Pointer to protocol header
    IPHdrLen = (pIpHdr->VerLen & 0xf) * 4;
    pIcHdr = (ICMPHDR *)(((UINT8 *)pIpHdr) + IPHdrLen);

    // Get the total length of the ICMP message
    icmpsize = (uint)(HNC16( pIpHdr->TotalLen )) - IPHdrLen;

    // The only packets that we process is where the OFFENDING packet
    // was sent from a translated source.
    pIpHdr2  = (IPHDR *)(pIcHdr->Data + 4);
    IPHdrLen = (pIpHdr2->VerLen & 0xf) * 4;

    // Translation varies slightly by protocol
    if( pIpHdr2->Protocol == IPPROTO_TCP || pIpHdr2->Protocol == IPPROTO_UDP )
    {
        // TCP/UDP Packet Translation
        TCPHDR  *pTcpHdr;

        // Get TCP packet header
        pTcpHdr = (TCPHDR *)(((UINT8 *)pIpHdr2) + IPHdrLen);

        pPortDst = &pTcpHdr->SrcPort;
    }
    else if( pIpHdr->Protocol == IPPROTO_ICMP )
    {
        // ICMP Packet Translation
        ICMPHDR *pIcHdr2;

        // Get ICMP packet header
        pIcHdr2 = (ICMPHDR *)(((UINT8 *)pIpHdr2) + IPHdrLen);

        // We only translate ECHO and TSTAMP requests
        if( pIcHdr2->Type != ICMP_ECHO && pIcHdr2->Type != ICMP_TSTAMP )
            return(0);

        pPortDst = (UINT16 *)pIcHdr2->Data;
    }
    else
        return(0);

    // Get dest port
    PortDst = *pPortDst;
    PortDst = HNC16(PortDst);

    if( !PortDst )
        return(0);

    nats.dwRxQualified++;

    // Find a NATINFO entry
    pni = NatFindPNI( 0, 0, 0, 0, pIpHdr2->Protocol, PortDst );

    // If no NATINFO, return
    if( !pni )
        return(0);

    // Alter the source IP and port in the OFFENDING header, and
    // the DstIP in the real IP header
    nats.dwRxAltered++;

    // Alter the packet
    WrNet32( &pIpHdr->dwIPDst, pni->IPLocal );
    WrNet32( &pIpHdr2->dwIPSrc, pni->IPLocal );
    *pPortDst = HNC16(pni->PortLocal);

    // Note: We won't alter the NAT entry timeout since we don't track
    //       the original protocol here. Plus an error isn't exactly
    //       active use of the entry.

    // Since this function is called infrequently, we'll
    // just re-checksum the whole packet.
    ICMPChecksum( pIcHdr, icmpsize );

    // The packet is now "from" us (local IF)
    // This suspends normal error checks for looping packets
    PktSetIFRx( hPkt, 0 );

    return(1);
}

//--------------------------------------------------------------------
// NatTcpTimeout()
//
// Sets a reasonable TCP timeout based on a guess at the current
// TCP state. Note: We only care about keeping the normal established
// state open for a long period of time. Once a FIN or RST is
// detected, the connect is expected to remain relatively active
// until fully closed. I.E.: Idle half closed sessions are not kept.
//--------------------------------------------------------------------
static void NatTcpTimeout( NATINFO *pni, TCPHDR *pTcpHdr )
{
    switch( pni->TcpState )
    {
    case NI_TCP_CLOSED:
        if( (pTcpHdr->Flags & (SYN|FIN|RST)) == SYN )
            pni->TcpState = NI_TCP_SYNSENT;
        break;

    case NI_TCP_SYNSENT:
        if( (pTcpHdr->Flags & (SYN|FIN|RST|ACK)) == ACK )
        {
            pni->TcpState = NI_TCP_ESTAB;

            // Maintain stats
            nats.dwLongTerm++;
            if( nats.dwLongTerm > nats.dwMaxLongTerm )
                nats.dwMaxLongTerm = nats.dwLongTerm;
        }
        else if( pTcpHdr->Flags & (RST|FIN) )
            pni->TcpState = NI_TCP_CLOSED;
        break;

    case NI_TCP_ESTAB:
        if( pTcpHdr->Flags & (RST|FIN) )
        {
            pni->TcpState = NI_TCP_CLOSED;

            // Maintain stats
            nats.dwLongTerm--;
        }
        break;
    }

    pni->Timeout = llTimerGetTime(0) + StateTimeout[ pni->TcpState ];
}
#endif

⌨️ 快捷键说明

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