📄 natpkt.c
字号:
//--------------------------------------------------------------------------
// 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 + -