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

📄 natpkt.c

📁 代码在ti的c67系列单片机上实现了完整的TCPIP协议栈
💻 C
📖 第 1 页 / 共 2 页
字号:
//--------------------------------------------------------------------------
// Ip Stack
//--------------------------------------------------------------------------
// NATPKT.C
//
// Network Address Translation - Packet Routines
//
// Author: Michael A. Denio
// Copyright 1999, 2000 by Texas Instruments Inc.
//-------------------------------------------------------------------------
#include <stkmain.h>
#ifdef _INCLUDE_NAT_CODE
#include "nat.h"

// The IP address info used in mappings
IPN NatIpServer = 0;
static IPN NatIpAddr   = 0;
static IPN NatIpMask   = 0;

// Timeouts based on TCP state
static UINT32 StateTimeout[3] = { NAT_TCP_IDLE_SECONDS,
                                  NAT_TCP_SYN_SECONDS,
                                  NAT_TCP_ACTIVE_SECONDS };

// TCP Flag Equates
#define FIN 0x01
#define SYN 0x02
#define RST 0x04
#define PSH 0x08
#define ACK 0x10
#define URG 0x20

// NAT Translation Statistics
NATSTATS nats;

static UINT32   NatCkMod(IPN IPOld, UINT16 PortOld, IPN IPNew, UINT16 PortNew );
static void     NatTcpTimeout( NATINFO *pni, TCPHDR *pTcpHdr );
static int      NatIcmpError( HANDLE hPkt, IPHDR *pIpHdr );


//--------------------------------------------------------------------
// NatSetConfig - Setup the NAT configuration
//--------------------------------------------------------------------
void NatSetConfig( IPN IPAddr, IPN IPMask, IPN IPServer )
{
    // Quick sanity check. The Sever IP can't be in the mapping subnet
    // Setting the mask to NULL will disable NAT
    if( (IPServer & IPMask) == (IPAddr & IPMask) )
        IPMask = 0;

    NatIpAddr   = IPAddr;
    NatIpMask   = IPMask;
    NatIpServer = IPServer;
}

//--------------------------------------------------------------------
// NatCkMod()
//
// Calculates the modification factor for adjusting an IP checksum
//--------------------------------------------------------------------
static UINT32 NatCkMod( IPN IPOld, UINT16 PortOld, IPN IPNew, UINT16 PortNew )
{
    UINT32  CkMod,CkOrg;

    CkOrg =  IPOld & 0xFFFF;
    CkOrg += (IPOld>>16) & 0xFFFF;
    CkOrg += (UINT32) PortOld;
    CkOrg =  (CkOrg&0xFFFF) + (CkOrg>>16);
    CkOrg =  (CkOrg&0xFFFF) + (CkOrg>>16);
    CkMod =  IPNew & 0xFFFF;
    CkMod += (IPNew>>16) & 0xFFFF;
    CkMod += (UINT32) PortNew;
    CkMod =  (CkMod&0xFFFF) + (CkMod>>16);
    CkMod =  (CkMod&0xFFFF) + (CkMod>>16);
    CkMod -= CkOrg;
    return( ((CkMod&0xFFFF) + (CkMod>>16)) & 0xFFFF );
}

//--------------------------------------------------------------------
// NatIpTxInput - NAT Processing of IP Tx packet
//
// Before packet is sent to IPTx for forwarding it is examined to see
// if the IP source address is in the NatIpAddr/NatIpMask range. If so,
// the following is performed:
//
// 1. For TCP and UDP packets, the source IP and source Port are used
//    to search for a NATINFO entry. If found, the source IP and source
//    port are modfied to be NatIpServer, and the mapping port.
//
//    For ICMP packets, a special function is called to detect echo
//    requests.
//
// 2. If a NATINFO entry is not found for (1), then a new entry is
//    created before the alterations are performed.
//
// 3. If (2) fails, the packet is discarded.
//
// If this function returns 1, the packet was consumed; else returns 0
//--------------------------------------------------------------------
int NatIpTxInput( HANDLE hPkt, IPHDR *pIpHdr )
{
    IPN     IPSrc,IPDst;
    UINT16  *pPortSrc;
    UINT16  PortSrc;
    UINT16  PortDst;
    uint    IPHdrLen;
    NATINFO *pni;
    UINT32  CkMod,CkOrg;
    UINT16  *pChecksum;
    TCPHDR  *pTcpHdr;

    // If we're not configured, return
    if( !(NatIpAddr&NatIpMask) )
        return(0);

    nats.dwTxExamined++;

    // Get IP Source & Destination
    IPSrc = RdNet32( &pIpHdr->dwIPSrc );
    IPDst = RdNet32( &pIpHdr->dwIPDst );

    // If source isn't from the targeted subnet, or it was sent to the
    // targeted subnet, return
    if( (IPSrc&NatIpMask) != NatIpAddr || (IPDst&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);

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

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

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

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

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

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

    // Get source port
    PortSrc = *pPortSrc;
    PortSrc = HNC16(PortSrc);

    nats.dwTxQualified++;

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

    // If no NATINFO, abort
    if( !pni )
    {
        PktFree( hPkt );
        return(1);
    }

    // Alter the source IP and port
    nats.dwTxAltered++;

    // Change PortSrc to be the NEW source port
    PortSrc = HNC16( pni->PortMapped );

    // Track changes for checksum modification (ICMP doesn't use IP address)
    if( pIpHdr->Protocol != IPPROTO_ICMP )
         CkMod = NatCkMod( IPSrc, *pPortSrc, NatIpServer, PortSrc );
    else
         CkMod = NatCkMod( 0, *pPortSrc, 0, PortSrc );

    // Alter the packet
    WrNet32( &pIpHdr->dwIPSrc, NatIpServer );
    *pPortSrc = PortSrc;

    // 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;

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

    return(0);
}

//--------------------------------------------------------------------
// NatIpRxInput - NAT Processing of IP Rx packet
//
// Packets that to be "delivered" to upper layer protocols are first
// sent to this routine. If the destination IP address matches the
// NatIpServer address, then the following is performed:
//
// 1. For TCP and UDP packets with a destination port in the Nat
//    mapping port range, use the port to find a NATINFO entry and
//    alter the destination IP address and destination port
//    and return TRUE.
//
// 2. Convert incoming ICMP error packets where the attached IP header
//    meets the citeria of (1) above.
//
// If this function returns 1, the packet should be re-forwarded
// If this function returns -1, the packet was consumed
//--------------------------------------------------------------------
int NatIpRxInput( HANDLE hPkt, IPHDR *pIpHdr )
{
    IPN     IPSrc,IPDst;
    UINT16  *pPortDst;
    UINT16  PortSrc;
    UINT16  PortDst;
    uint    IPHdrLen;
    NATINFO *pni;
    UINT32  CkMod,CkOrg;
    UINT16  *pChecksum;
    TCPHDR  *pTcpHdr;

    // If we're not configured, return
    if( !(NatIpAddr&NatIpMask) )
        return(0);

    nats.dwRxExamined++;

    // Get IP Source & Destination
    IPSrc = RdNet32( &pIpHdr->dwIPSrc );

⌨️ 快捷键说明

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