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

📄 nat_filter_hook.c

📁 vxworks NAT 实现部分源代码。有兴趣可以参考下
💻 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 + -