📄 nat_rx.c
字号:
/* nat_rx.c */
/* Copyright 2000-2003 Wind River Systems, Inc. */
/* @format.tab-size 4, @format.use-tabs true, @format.new-line lf */
/*
modification history
--------------------
01j,18jul03,vks changes for Virtual Stack
01i,16jun03,myz Replace old fragment translation APIs with new ones.
01h,09may03,myz reworked SPR69698
01g,02may03,vks corrected header for natIpOutputFilterHook, removed #ifdef 0
code from it
01f,01may03,zhu renamed SPR69698_PATCH to NAT_OUTPUT_FILTER
01e,28apr03,myz fixed problem introduced in 01c version.
01d,28apr03,myz removed org_src_addr, use the value in org_ip_header.
01c,25apr03,myz Modified nat_rx function to improve the performance.
01b,21apr03,myz replaced swap(_long) with the ntohs(l) and htons(l) macros.
01a,15apr03,zhu replaced function call with direct access, fixed a bug in ALG
fragments
092402 vvv replaced rw_container lists with linked lists to improve performance
092302 vvv used direct copy instead of memcpy to copy IP header to improve
performance
101901 tk Fix data type to avoid warning in T3 compiler.
101601 tk Add a case for ICMP protocol in nat_get_src_transport().
092801 tk Fix SPR69698: Added a special hook to handle icmp error generated
by IP stack. This hook was not included in the NAT 1.1 FCS.
071301 tk Add code to call the agent callback function for no-NAT translation.
051501 tk Fix SPR67123: Global FTP client can't connect to local server when
client issues PASV command. Add new function
nat_get_src_transport() to check source port.
042101 tk Fix ICMP redirect packet handling. Should be ignored by NAT
per RFC1631.
*/
/* ANSI headers */
#include <string.h>
/* RouterWare headers */
#include "nat.h"
#include "net/mbuf.h"
#include "netBufLib.h"
#ifdef VIRTUAL_STACK
#include "netinet/vsLib.h"
#endif /* VIRTUAL_STACK */
/* Local defines */
#define NAT_APPFILTER
#define IF_DEV_NAME_LEN 16
/********************************************************************************************
Static functions and variables
********************************************************************************************/
static enum TEST nat_handle_translation_for_global_rx (IP_PACKET*,
enum NAT_PACKET_TYPES nat_packet_type);
static enum TEST nat_handle_translation_for_local_rx (M_BLK*,
enum NAT_PACKET_TYPES nat_packet_type);
LOCAL void natTranslatedIpPacketConvert (M_BLK_ID, struct ifnet *,int);
#ifdef NAT_APPFILTER
IMPORT STATUS appFilterHook(M_BLK * );
#endif
/********************************************************************************************
Function declarations
********************************************************************************************/
extern NAT_AGENT_INFO *nat_find_agent(
NAT_CLASS *nat_p,
u_short protocol,
u_long remote_port,
u_long local_port
);
#ifndef VIRTUAL_STACK
extern VOIDFUNCPTR _icmpErrorHook;
#endif /* VIRTUAL_STACK */
LOCAL VOIDFUNCPTR stdIcmpErrorHook = NULL;
void natIcmpErrorHook (struct mbuf *, int, int, ULONG, struct ifnet *);
/*******************************************************************************************/
enum TEST nat_rx (USHORT port_number, M_BLK* pMblk)
{
enum NAT_PORT_TYPE nat_port_type;
ULONG_ENUM (NAT_PACKET_TYPES) nat_packet_type;
enum NAT_FILTER nat_filter_result;
NAT_AGENT_INFO* agent_info;
enum TEST return_code;
u_long org_dst_addr;
u_long org_src_addr;
char addr_str[32];
IP_PACKET *sptr_ip_packet;
NAT_DIRECTION direction;
UINT16 srcTransport, dstTransport;
void * pFragEntry;
sptr_ip_packet = (IP_PACKET*) pMblk->mBlkHdr.mData;
/* possible unaligned access if the offset value is not set properly in
* the ethernet END driver
*/
org_dst_addr = sptr_ip_packet->header.destination_address;
org_src_addr = sptr_ip_packet->header.source_address;
nat_port_type = nat.port[port_number].type; /* local or global port */
/* do filter first (translate or not translate), so packets do not need
* to be translated, such as local traffic, can get out this function ASAP.
*/
nat_filter_result = nat_filter_rx (ntohl(org_dst_addr), port_number,
nat_port_type);
if (nat_filter_result == NAT_DONT_TRANSLATE)
{
return (PASS);
}
else if (nat_filter_result == NAT_FILTER)
{
return (FAIL);
}
/* Now check ICMP redirect msg, Per RFC1631: NAT doesn't handle it */
nat_packet_type = nat_packet_discriminator (sptr_ip_packet);
if (nat_packet_type == NAT_ICMP_REDIRECT)
{
return (PASS);
}
/* Handle fragmented IP datagram */
pFragEntry = NULL;
#if 0
if ( (sptr_ip_packet->header.fragment & IP_FRAGMENT_OFFSET_MASK) == 0)
{
if (sptr_ip_packet->header.fragment & IP_FRAGMENT_FLAG_MORE_FRAGMENTS)
{
#if 0
/* first fragment, create fragment translation entry */
pFragEntry = (void *)natFragTranEntryGet (nat_port_type,
sptr_ip_packet);
if (pFragEntry == NULL)
return (FAIL);
#endif
return(FAIL);
}
}
else /* subsequent fragment */
{
/*
return_code = natFragAddrTranslate (nat_port_type, sptr_ip_packet);
return (return_code);
*/
return(FAIL);
}
#endif
/*!!!!!!!!!!!!!!!!!!!!!!!!!!LJJ Changed follow code. !!!!!!!!!!!!!!!!!!!!!!!!!!!*/
if (sptr_ip_packet->header.fragment & 0x3fff)
return (FAIL);
if (nat_port_type == NAT_GLOBAL_PORT)
{
direction = NAT_INBOUND;
}
else /* local port */
{
#ifdef NAT_APPFILTER
if(appFilterHook(pMblk)==OK)
{
return (FAIL);
}
#endif
direction = NAT_OUTBOUND;
}
#if 0
/* Do not translate OSPF or outbound RIP packets */
if ((nat_packet_type == NAT_OSPF)
|| ((nat_packet_type == NAT_RIP) && (direction == NAT_OUTBOUND)))
{
return (PASS);
}
#endif
/********************************************/
/* Search for installed ALG for this packet */
/********************************************/
if (sptr_ip_packet->header.protocol == IPPROTO_TCP)
{
srcTransport = ntohs( ((TCP_PACKET*)
sptr_ip_packet)->tcp_header.source_port );
dstTransport = ntohs( ((TCP_PACKET*)
sptr_ip_packet)->tcp_header.destination_port );
}
else if(sptr_ip_packet->header.protocol == IPPROTO_UDP)
{
srcTransport = ntohs( ((UDP_PACKET*)
sptr_ip_packet)->header.source_port );
dstTransport = ntohs( ((UDP_PACKET*)
sptr_ip_packet)->header.destination_port );
}
else
{
srcTransport = 0;
dstTransport = 0;
}
agent_info = nat_find_agent(&nat, sptr_ip_packet->header.protocol,
dstTransport, srcTransport);
nat.agent_info = agent_info;
/* ALG packet translations - PRE NAT */
if (agent_info != NULL && agent_info->flags & NAT_FLAG_PRE_XLAT
&& agent_info->packet_callback != NULL)
{
nat_printf (NAT_PRINTF_TRACE,
"nat_rx: calling agent (%s) packet callback (pre-NAT)\n",
agent_info->name);
if (agent_info->packet_callback((u_long)&nat, agent_info->id,
0, /* session_id */
direction, sptr_ip_packet)==FALSE)
{
nat_printf(NAT_PRINTF_TRACE,
"nat_rx: agent (%s) packet callback returned FALSE\n",
agent_info->name);
return(FAIL);
}
}
/* NAT Built-in translations (TCP/UDP/ICMP) if no matching registered
* agent or the registered agent processes only the payload
*/
if (agent_info == NULL || (agent_info->flags & NAT_FLAG_NO_XLAT)==0)
{
switch (nat_port_type)
{
case NAT_GLOBAL_PORT:
return_code = nat_handle_translation_for_global_rx (
sptr_ip_packet, nat_packet_type);
if (return_code == FAIL)
return (FAIL);
if (pFragEntry != NULL)
{
return_code = natFragTranAddrSave(NAT_GLOBAL_PORT,
pFragEntry,
sptr_ip_packet->header.destination_address);
if (return_code == FAIL)
return (FAIL);
}
break;
case NAT_LOCAL_PORT:
return_code = nat_handle_translation_for_local_rx (pMblk,
nat_packet_type);
if (return_code == FAIL)
return (FAIL);
if (pFragEntry != NULL)
{
return_code = natFragTranAddrSave(NAT_LOCAL_PORT,pFragEntry,
sptr_ip_packet->header.source_address);
if (return_code == FAIL)
return (FAIL);
}
break;
default:
nat_printf (NAT_PRINTF_ERROR,
"nat_rx: Unknown port type %d for port number %d\n",
nat_port_type, port_number);
return (FAIL);
}
}
/* ALG packet translations - POST NAT */
if (agent_info != NULL && agent_info->flags & NAT_FLAG_POST_XLAT
&& agent_info->packet_callback != NULL)
{
nat_printf (NAT_PRINTF_TRACE,
"nat_rx: calling agent (%s) packet callback (post-NAT)\n",
agent_info->name);
if (agent_info->packet_callback((u_long)&nat, agent_info->id, 0,
direction, sptr_ip_packet)==FALSE)
{
nat_printf(NAT_PRINTF_TRACE,
"nat_rx: agent (%s) packet callback returned FALSE\n",
agent_info->name);
return(FALSE);
}
}
/* ALG translates entire packet */
if (agent_info != NULL && agent_info->flags & NAT_FLAG_NO_XLAT
&& agent_info->packet_callback != NULL)
{
nat_printf (NAT_PRINTF_TRACE,
"nat_rx: calling agent (%s) packet callback (no-NAT)\n",
agent_info->name);
if (agent_info->packet_callback((u_long)&nat, agent_info->id, 0,
direction, sptr_ip_packet)==FALSE)
{
nat_printf(NAT_PRINTF_TRACE,
"nat_rx: agent (%s) packet callback returned FALSE\n",
agent_info->name);
return(FALSE);
}
/* If this is first fragment of larger packet, store the modified
* address.
*/
if (pFragEntry != NULL) /* insert the new source address here */
{
if (nat_port_type == NAT_GLOBAL_PORT)
return_code = natFragTranAddrSave(NAT_GLOBAL_PORT,pFragEntry,
sptr_ip_packet->header.destination_address);
else
return_code = natFragTranAddrSave(NAT_LOCAL_PORT,pFragEntry,
sptr_ip_packet->header.source_address);
if (return_code == FAIL)
return (FAIL);
}
}
if (nat.printing_enabled == true || nat.logging_enabled == true)
{
struct in_addr iaddr;
iaddr.s_addr = org_src_addr;
inet_ntoa_b(iaddr,addr_str);
nat_printf (NAT_PRINTF_DATA,
"nat_rx: original IP hdr source address: %s\n",
addr_str);
iaddr.s_addr = sptr_ip_packet->header.source_address;
inet_ntoa_b(iaddr,addr_str);
nat_printf (NAT_PRINTF_DATA,
"nat_rx: translated IP hdr source address: %s\n",
addr_str);
iaddr.s_addr = org_dst_addr;
inet_ntoa_b(iaddr,addr_str);
nat_printf (NAT_PRINTF_DATA,
"nat_rx: original IP hdr destination address: %s\n",
addr_str);
iaddr.s_addr = sptr_ip_packet->header.destination_address;
inet_ntoa_b(iaddr,addr_str);
nat_printf (NAT_PRINTF_DATA,
"nat_rx: translated IP hdr destination address: %s\n",
addr_str);
}
return (PASS);
}
/********************************************************************************************
This function handles translation of inbound packets (i.e. received from global port).
********************************************************************************************/
static enum TEST nat_handle_translation_for_global_rx (IP_PACKET* p_packet,
enum NAT_PACKET_TYPES nat_packet_type)
{
enum TEST return_code;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -