📄 nat_filter_hook.c
字号:
/* nat_filter_hook.c */
/* Copyright 2000-2004 Wind River Systems, Inc. */
/* @format.tab-size 4, @format.use-tabs true, @format.new-line lf */
/*
modification history
--------------------
01g,22jan04,zhu updated parameters for output filter
01f,19nov03,zhu removed ntoh and other checks for ip preinput.
01e,27oct03,zhu Implemented split NAT: split NAT into preinput and output
filter hooks.
01d,09may03,myz removed SERVICES_ADDON loopback handling, now handled by the
natIcmpErrorHook.
01c,05may03,zhu removed the fix for loopback interface, because it causes a
ping problem for local interface
01b,01may03,zhu removed DMZ
01a,10apr03,zhu A few changes:
1. replace expensive sprintf
2. process ICMP error message from loopback interface
3. update static entried when dynamic global address changes
102001 tk On dynamic global address, refresh netmask as well.
081701 tk Add #define SHOW_PACKET_DISCARDED to show "packet discarded" trace.
053001 tk Add conditional if statement around nat_printf in nat_filter_hook
to speed up performance. Also, change debug message variables from
local to static reduce overhead cost of stack allocation and de-
allocation upon entering nat_filter_hook().
*/
/*
#define SHOW_PACKET_DISCARDED
*/
#include "nat.h"
/* VxWorks specific headers */
#include <inetLib.h>
#include <net/mbuf.h> /* struct mbuf and struct ifnet definitions */
#include <netinet/in.h>
#include <netinet/ip.h> /* struct ip definition */
#include <stdio.h> /* sprintf() prototype */
#include <nat_api.h>
#include "wanwork/wanWorkModeCommon.h"
#include "wanwork/wanbrige.h"
IMPORT DNS_Struct DNS_IPADDRESS;
static char* ip_proto_desc(ushort proto)
{
static char proto_desc[32];
switch(proto)
{
case IPPROTO_IP:
return("IP");
case IPPROTO_ICMP:
return("ICMP");
case IPPROTO_IGMP:
return("IGMP");
case IPPROTO_GGP:
return("GGP");
case IPPROTO_TCP:
return("TCP");
case IPPROTO_EGP:
return("EGP");
case IPPROTO_PUP:
return("PUP");
case IPPROTO_UDP:
return("UDP");
case IPPROTO_IDP:
return("IDP");
case IPPROTO_TP:
return("TP");
case IPPROTO_EON:
return("EON");
case IPPROTO_OSPF:
return("OSPF");
case IPPROTO_ENCAP:
return("ENCAP");
}
sprintf(proto_desc,"proto(%02X)",proto);
return(proto_desc);
}
LOCAL STATUS natdnsproxyhook(struct ifnet* pIf, struct mbuf** pPtrMbuf)
{
IP_ADDRESS address=0;
static int status=0;
M_BLK* pBlock = *pPtrMbuf;
USHORT checksum;
UDP_PACKET *sptr_udp_packet=(UDP_PACKET *) pBlock->mBlkHdr.mData;
if((pIf->if_unit==0)&&( htonl(sptr_udp_packet->ip_header.destination_address)==nat.port[0].address)
&&(htons(sptr_udp_packet->header.destination_port)==53))
{
pre:
if(DNS_IPADDRESS.firstdns && status!=1)
{
address = DNS_IPADDRESS.firstdns;
status=1;
}
else if(DNS_IPADDRESS.backdns)
{
address = DNS_IPADDRESS.backdns;
status=2;
}
else
{
if(status)
{
status=0;
goto pre;
}
else
return ERROR;
}
if (sptr_udp_packet->header.checksum != 0)
{
checksum_fixup ((BYTE *) &sptr_udp_packet->header.checksum,
(BYTE *) &sptr_udp_packet->ip_header.destination_address, sizeof (IP_ADDRESS),
(BYTE *) &address, sizeof (IP_ADDRESS));
}
checksum = sptr_udp_packet->ip_header.header_checksum;
checksum_fixup ((BYTE *) &checksum,
(BYTE *) &sptr_udp_packet->ip_header.destination_address, sizeof (IP_ADDRESS),
(BYTE *) &address, sizeof (IP_ADDRESS));
sptr_udp_packet->ip_header.destination_address = address;
sptr_udp_packet->ip_header.header_checksum = checksum;
}
else
return ERROR;
return OK;
}
/***************************************************************************
*
* natPreinputFilterHook - NAT filter called from pre-input packet intercept
* location in the IP stack.
*
*/
BOOL natPreinputFilterHook
(
struct mbuf** pPtrMbuf,
struct ip** pPtrIpHdr,
int *hlenp
)
{
return (nat_filter_hook ((*pPtrMbuf)->m_pkthdr.rcvif, pPtrMbuf, pPtrIpHdr, *hlenp, TRUE));
}
/***************************************************************************
*
* natOutputFilterHook - NAT filter called from output packet intercept
* location in the IP stack.
*
*/
BOOL natOutputFilterHook
(
struct ifnet* ifp,
struct mbuf** pPtrMbuf,
struct ip** pPtrIpHdr,
int *hlenp
)
{
return(nat_filter_hook ((*pPtrMbuf)->m_pkthdr.rcvif, pPtrMbuf, pPtrIpHdr, *hlenp, FALSE));
}
BOOL nat_filter_hook (struct ifnet* pIf, struct mbuf** pPtrMbuf, struct ip** pPtrIpHdr, int ipHdrLen, BOOL location)
{
int port_number;
USHORT org_length;
IP_PACKET* p_packet;
M_BLK* pBlock;
struct ifnet* global_if;
struct ifaddr* ifaddr;
IP_ADDRESS inAddr, inMask;
IP_ADDRESS last_global_address = nat.global_address;
if (nat.enabled == FALSE)
{
/*printf("nat_filter_hook: not enabled\n");*/
if((NAT_Brige.natbrigeenable)&&(pIf->if_unit==1))
goto nat_error;
nat_printf(NAT_PRINTF_ERROR, "nat_filter_hook: not enabled\n");
return (FALSE);
}
if (pIf == NULL)
{
/*printf("nat_filter_hook: NULL interface pointer\n");*/
/*
nat_printf(NAT_PRINTF_ERROR, "nat_filter_hook: NULL interface pointer\n");
*/
return (FALSE);
}
if (pPtrIpHdr == NULL || *pPtrIpHdr == NULL)
{
/*printf("nat_filter_hook: NULL IP header pointer\n");*/
nat_printf(NAT_PRINTF_ERROR, "nat_filter_hook: NULL IP header pointer\n");
return (FALSE);
}
if (pPtrMbuf == NULL || *pPtrMbuf == NULL)
{
/*printf("nat_filter_hook: NULL Mbuf pointer\n");*/
nat_printf(NAT_PRINTF_ERROR, "nat_filter_hook: NULL Mbuf pointer\n");
return (FALSE);
}
/* Find port for this interface */
for (port_number = 0; port_number < sizeof(nat.port)/sizeof(nat.port[0]);port_number++)
{
if (nat.port[port_number].ifunit==pIf)
{
break;
}
}
if (port_number >= sizeof(nat.port)/sizeof(nat.port[0]))
{
/*printf("nat_filter_hook: port for interface (%s) not found\n",ifname);*/
return (FALSE);
}
if ((nat.port[port_number].enabled == FALSE)||(nat.port[nat.global_port_number].enabled==FALSE))
{
/*printf("nat_filter_hook: port %d not enabled\n",port_number);*/
nat_printf(NAT_PRINTF_ERROR, "nat_filter_hook: port %d not enabled\n",port_number);
return (FALSE);
}
/*
* Pre-input location NAT filter: only translates incoming packets from
* global port, i.e. for any packets not from global port, don't translate.
* Output location NAT filter: only translates packets coming from
* local port, i.e. for any packets not from local port, don't translate.
*/
if (location == TRUE && nat.port[port_number].type != NAT_GLOBAL_PORT ) /* preinput */
{
natdnsproxyhook(pIf,pPtrMbuf);
/*printf("nat_filter_hook: PRE_INPUT ignore src port %d pkt\n", port_number);*/
nat_printf(NAT_PRINTF_TRACE, "nat_filter_hook: PRE_INPUT ignore src port %d pkt\n", port_number);
return (FALSE);
}
if (location == FALSE && nat.port[port_number].type != NAT_LOCAL_PORT ) /* output */
{
/*printf("nat_filter_hook: OUTPUT ignore src port %d pkt\n", port_number);*/
nat_printf(NAT_PRINTF_TRACE, "nat_filter_hook: OUTPUT ignore src port %d pkt\n", port_number);
return (FALSE);
}
/* Dynamic Global Address? */
if (nat.dynamic_global_address == TRUE|| nat.port[nat.global_port_number].ifunit == NULL)
{
global_if = nat.port[nat.global_port_number].ifunit;
if(global_if == NULL)
{
global_if = ifunit(nat.port[nat.global_port_number].ifname);
}
if (global_if != NULL) /* Interface Attached, Get Current Address */
{
/* Search for IP address */
for (ifaddr = global_if->if_addrlist; ifaddr != NULL; ifaddr = ifaddr->ifa_next)
{
if(ifaddr->ifa_addr->sa_family == AF_INET)
break;
}
if (ifaddr != NULL) /* IP Address found */
{
inAddr = ntohl(((struct sockaddr_in*) ifaddr->ifa_addr)->sin_addr.s_addr);
inMask = ntohl(((struct sockaddr_in*) ifaddr->ifa_netmask)->sin_addr.s_addr);
nat.port[nat.global_port_number].address = inAddr;
nat.port[nat.global_port_number].mask = inMask;
nat.port[nat.global_port_number].ifunit=global_if;
nat.port[nat.global_port_number].type = NAT_GLOBAL_PORT;
nat_printf(NAT_PRINTF_TRACE,
"nat_filter_hook: dynamic global interface addr: %08lX, mask: %08lX",
inAddr, inMask);
nat.global_address = inAddr;
nat.global_address_mask = inMask;
}
}
/*add by zbb*/
else
{
if(!nat.global_address)
return (FALSE);
}
}
/*
* Fix up for static entries used to forward certain ports to local machine.
* When the global address changes, we have to update the static entries and
* ICMP default address.
*/
if(last_global_address != nat.global_address)
{
NAT_PORT_STATIC_ENTRY entry;
char addrString[18];
struct in_addr iaddr;
int i;
/* Update static TCP entries using IP of global interface. */
for(i = 0; i < MAXIMUM_NUMBER_OF_TCP_STATIC_ENTRIES; i++)
{
entry = nat.tcp_static_entries[i];
if(!entry.local_address && !entry.local_port_number && !entry.global_port_number)
continue;
if(entry.local_address == last_global_address)
{
iaddr.s_addr = entry.local_address;
inet_ntoa_b(iaddr, addrString);
natTcpStaticDelete(addrString, entry.local_port_number, entry.global_port_number);
iaddr.s_addr = nat.global_address;
inet_ntoa_b(iaddr, addrString);
natTcpStaticAdd(entry.name,addrString, entry.local_port_number, entry.global_port_number);
}
}
/* Update static UDP entries using IP of global interface. */
for(i = 0; i < MAXIMUM_NUMBER_OF_UDP_STATIC_ENTRIES; i++)
{
entry = nat.udp_static_entries[i];
if(!entry.local_address && !entry.local_port_number && !entry.global_port_number)
continue;
if(entry.local_address == last_global_address)
{
iaddr.s_addr = entry.local_address;
inet_ntoa_b(iaddr, addrString);
natUdpStaticDelete(addrString, entry.local_port_number, entry.global_port_number);
iaddr.s_addr = nat.global_address;
inet_ntoa_b(iaddr, addrString);
natUdpStaticAdd(entry.name,addrString, entry.local_port_number, entry.global_port_number);
}
}
/* Update the default ICMP address if it matches the old global address. */
if(nat.nats.icmp_default_entry.local_address == last_global_address)
nat.nats.icmp_default_entry.local_address = nat.global_address;
last_global_address = nat.global_address;
}
p_packet = (IP_PACKET *) *pPtrIpHdr; /* *pPtrIpHdr == *pPtrMbuf->mBlkHdr.mData */
pBlock = *pPtrMbuf;
org_length = p_packet->header.total_length;
if (nat_rx (port_number, pBlock) == PASS)
{
pBlock->mBlkHdr.mLen = (USHORT) (pBlock->mBlkHdr.mLen
+ (p_packet->header.total_length - org_length));
return (FALSE); /* not filtered, normal processing should take place */
}
#ifdef SHOW_PACKET_DISCARDED
nat_printf(NAT_PRINTF_TRACE, "nat_filter_hook: packet discarded\n");
#endif
if(nat.filter_unknown_protocols)
{
nat_error:
netMblkClChainFree(*pPtrMbuf);
return (TRUE); /* filtered, no futher action should be taken with this packet */
}
return (FALSE); /* filtered, no futher action should be taken with this packet */
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -