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

📄 nat_tcp.c

📁 VXWORKS NAT 部分源代码3 有兴趣朋友可以参考下
💻 C
📖 第 1 页 / 共 3 页
字号:
/* nat_tcp.c */ 

/* Copyright 2000-2003 Wind River Systems, Inc. */

/* @format.tab-size 4, @format.use-tabs true, @format.new-line lf */

/*
modification history
--------------------
01c,24apr03,zhu  updated copyright
01b,21apr03,myz  replaced swap(_long) with the ntohs(l) and htons(l) macros,
                 replaced RWOS list functions with ones in dllLib.c.
01a,15apr03,zhu  check tcp reset flag
040903  vks  	 	updated Copyright info	
040303  vks  		replaced table_malloc call with calloc
101501  tk		Fix bug.  When no matches found for inbound TCP packet in NAPT, return(PASS)
				to pass the untranslated packet to the network stack.
100301  tk      	Fix bug.  Address (IP) static entry didn't work in NAPT.
092401	tk		Fix bug in handle_tcp_translation_global_rx_nats() to create one or more dynamic
				binds from a static entry so that the static bind can support multiple global
				clients to the same local server.
082301	tk		Assign remote address to the translation entry and bind entry upon receiving
				TCP packet from global port in NAPT mode.
080701	tk		Add code in handle_tcp_translation_local_rx_nats for handling H.323 protocol.
072601	tk		Fix call to match_ports_with_tcp_entry to use match_ports_with_tcp_entry_inbound
				and match_ports_with_tcp_entry_outbound instead.
070201	tk		Modified implementations to call natSetBind to create TCP control blocks so it
				will work with the upgraded version of ALG API.
051401	tk		Fix natShow for basic NAT. Local address is displayed as global address.
051101	tk		Fix NAPT so it can also work with static address-based translations.
051001	tk		Fix TCP state transition problem.  TCP local or/and global state may be in the
				wrong state.  One known effect of this is TCP control block might not get freed
				12 hours after the TCP connection was closed.  Problem was due to failure to do
				swap_long on the sequence numbers when comparing current and previous sequence
				numbers to determine whether it needs to do state transition.
050401  tk		Fix problem of multiple global servers being unable to connect to a local server
				simultaneously.  Also, fix the indication of static or dynamic binds in the 
				TCP control blocks (in the TCP translation list).
042101	tk		Add some comments
*/
/*
#define		TCP_DEBUG
*/

#include "nat.h"
#include "nat_api.h"
IMPORT FUNCPTR _func_packetsend;

/**************************************************************************************************/
static enum TEST handle_tcp_translation_global_rx_natg (TCP_PACKET *sptr_tcp_packet);
static enum TEST handle_tcp_translation_global_rx_nats (TCP_PACKET *sptr_tcp_packet);
static void do_tcp_sequence_number_fixup (enum NAT_TCP_DELTA_SIGN delta_sign, ULONG *ulptr_packet_sequence_number,
	USHORT *usptr_checksum, SEQUENCE_HEADER *sptr_sequence_list);

/**************************************************************************************************/
enum TEST handle_tcp_translation_global_rx (TCP_PACKET *sptr_tcp_packet)
{
	enum TEST pass_or_fail;

	if (nat.single_global_address_enabled == TRUE)
	{
		pass_or_fail = handle_tcp_translation_global_rx_nats (sptr_tcp_packet);
	}
	else
	{
		
		pass_or_fail = handle_tcp_translation_global_rx_natg (sptr_tcp_packet);
	}

	return (pass_or_fail);				
}
/*************************************************************************************************/
enum TEST handle_tcp_translation_local_rx (TCP_PACKET *sptr_tcp_packet)
{
	enum TEST pass_or_fail;

	if (nat.single_global_address_enabled == TRUE)
	{
		pass_or_fail = handle_tcp_translation_local_rx_nats (sptr_tcp_packet);
	}
	else
	{
		
		pass_or_fail = handle_tcp_translation_local_rx_natg (sptr_tcp_packet);
	}

	return (pass_or_fail);
}

/********************************************************************************************
	Description:	
		handle_ip_translation_local_rx_natg() replaces the source IP with IP from global address
		pool.  It also creates a new entry in the IP translation list.
		new_tcp_translation_entry() creates a new entry in the TCP translation list.
********************************************************************************************/
enum TEST handle_tcp_translation_local_rx_natg (TCP_PACKET *sptr_tcp_packet)
{
	NAT_CURRENCY_TRANSLATION_ENTRY *sptr_tcp_translation_entry=NULL;
	IP_TRANSLATION_ENTRY *sptr_working_ip_translation_entry=NULL;
	BYTE_ENUM (BOOLEAN) do_state_transition;
	IP_ADDRESS source_address;
	NAT_BIND_INFO		bind_info;
	NAT_STATUS			status;

	source_address = sptr_tcp_packet->ip_header.source_address;

	sptr_working_ip_translation_entry = handle_ip_translation_local_rx_natg ((IP_PACKET *) sptr_tcp_packet);

	if (sptr_working_ip_translation_entry == NULL)
	{
		return (FAIL);
	}

	checksum_fixup ((BYTE *) &sptr_tcp_packet->tcp_header.checksum,
						(BYTE *) &source_address, sizeof (source_address),
						(BYTE *) &sptr_tcp_packet->ip_header.source_address, sizeof (source_address));
	semTake(natentrylock, WAIT_FOREVER);
	sptr_tcp_translation_entry = find_entry (sptr_tcp_packet->ip_header.source_address,
			sptr_tcp_packet->ip_header.destination_address,sptr_tcp_packet->tcp_header.source_port,sptr_tcp_packet->tcp_header.destination_port);

	if (sptr_tcp_translation_entry == NULL)
	{
		semGive(natentrylock);
		if (sptr_tcp_packet->tcp_header.flags.synchronize_flag == TRUE)
		{
			memset(&bind_info,0,sizeof(bind_info));
			bind_info.agent_id = 0;		/* agent is NAT */
			bind_info.type = NAT_BIND_BASIC;
			bind_info.direction = NAT_OUTBOUND;
			bind_info.protocol = IPPROTO_TCP;
			bind_info.static_entry = FALSE;
			/* convert source and destination transport addresses to host format */
			bind_info.local_addr = ntohl(source_address);
			bind_info.local_transport = ntohs(sptr_tcp_packet->tcp_header.source_port);
			bind_info.remote_addr = ntohl(sptr_tcp_packet->ip_header.destination_address);
			bind_info.remote_transport = ntohs(sptr_tcp_packet->tcp_header.destination_port);
			/* save the current IP translation entry */
			bind_info.nat_address_entry = (u_long) sptr_working_ip_translation_entry;
	
			status = natSetBind((u_long)&nat, 0, &bind_info);
			if(status != NAT_OK)
			{
				nat_printf (NAT_PRINTF_ERROR, 
					"handle_tcp_translation_local_rx_natg: natSetBind returned %d\n",status);
				return(FAIL);
			}
			semTake(natentrylock, WAIT_FOREVER);
			sptr_tcp_translation_entry = (NAT_CURRENCY_TRANSLATION_ENTRY *) bind_info.nat_transport_entry;
		}
		else
		{
			return (FAIL);
		}
	}

	tcp_sequence_number_fixup_local_rx (&sptr_tcp_packet->tcp_header, sptr_tcp_translation_entry);
/*
	if (ntohl(sptr_tcp_packet->tcp_header.sequence_number) >= 
			ntohl(sptr_tcp_translation_entry->local_sequence_number))
	{
		do_state_transition = TRUE;
	}
	else
	*/
	if(sptr_tcp_packet->tcp_header.flags.reset_flag == TRUE)
	{
		do_state_transition = TRUE;
	}
    		else
		{
		    do_state_transition = FALSE;
		}
/*
	sptr_tcp_translation_entry->local_sequence_number = sptr_tcp_packet->tcp_header.sequence_number;
*/

	if (do_state_transition == TRUE)
	{
		if (sptr_tcp_packet->tcp_header.flags.acknowledgment_flag == TRUE)
		{
			tcp_state_transistion_local_rx (NAT_ACK, sptr_tcp_translation_entry);
		}

		if (sptr_tcp_packet->tcp_header.flags.synchronize_flag == TRUE)
		{
			tcp_state_transistion_local_rx (NAT_SYNCH, sptr_tcp_translation_entry);
		}

		if (sptr_tcp_packet->tcp_header.flags.finished_flag == TRUE)
		{
			tcp_state_transistion_local_rx (NAT_FIN, sptr_tcp_translation_entry);
		}

		if (sptr_tcp_packet->tcp_header.flags.reset_flag == TRUE)
		{
			tcp_state_transistion_local_rx (NAT_RESET, sptr_tcp_translation_entry);
		}
			
		if ((sptr_tcp_packet->tcp_header.flags.acknowledgment_flag == FALSE) &&
			(sptr_tcp_packet->tcp_header.flags.synchronize_flag == FALSE) &&
			(sptr_tcp_packet->tcp_header.flags.reset_flag == FALSE) &&
			(sptr_tcp_packet->tcp_header.flags.finished_flag == FALSE))
		{
			tcp_state_transistion_local_rx (NAT_ESTABLISHED, sptr_tcp_translation_entry);
		}
	}
	semGive(natentrylock);
	return (PASS);
}

/**************************************************************************************************
	Description:
		Check if there is a match for destination address in IP translation list.
		If not, return.
		Else, replace destination IP with local IP and adjust checksum.
		Check for match in the TCP translation list.
		If not, create an entry in the TCP translation list.
**************************************************************************************************/
static enum TEST handle_tcp_translation_global_rx_natg (TCP_PACKET *sptr_tcp_packet)
{
	IP_TRANSLATION_ENTRY *sptr_ip_translation_entry=NULL;
	bool do_state_transition;
	NAT_CURRENCY_TRANSLATION_ENTRY *sptr_tcp_translation_entry=NULL;
	IP_ADDRESS destination_address;
	NAT_BIND_INFO		bind_info;
	NAT_STATUS			status;

	destination_address = sptr_tcp_packet->ip_header.destination_address;

	sptr_ip_translation_entry = handle_ip_translation_global_rx_natg ((IP_PACKET *) sptr_tcp_packet);

	if (sptr_ip_translation_entry == NULL)
	{
		return (PASS); /* changed so that packets meant for upper layers can be passed to IP */
	}

	checksum_fixup ((BYTE *) &sptr_tcp_packet->tcp_header.checksum,
						(BYTE *) &destination_address, sizeof (destination_address),
						(BYTE *) &sptr_tcp_packet->ip_header.destination_address, sizeof (destination_address));
	semTake(natentrylock, WAIT_FOREVER);
	sptr_tcp_translation_entry = match_ports_with_tcp_entry_inbound (sptr_tcp_packet);

	if (sptr_tcp_translation_entry == NULL)
	{
		semGive(natentrylock);
		if (sptr_tcp_packet->tcp_header.flags.synchronize_flag == TRUE)
		{
			
			memset(&bind_info,0,sizeof(bind_info));
			bind_info.agent_id = 0;		/* agent is NAT */
			bind_info.type = NAT_BIND_BASIC;
			bind_info.direction = NAT_INBOUND;
			bind_info.protocol = IPPROTO_TCP;
			bind_info.static_entry = FALSE;
			/* convert source and destination transport addresses to host format */
			bind_info.local_addr = ntohl(sptr_tcp_packet->ip_header.destination_address);
			bind_info.local_transport = ntohs(sptr_tcp_packet->tcp_header.destination_port);
			bind_info.remote_addr = ntohl(sptr_tcp_packet->ip_header.source_address);
			bind_info.remote_transport = ntohs(sptr_tcp_packet->tcp_header.source_port);
			/* save the current IP translation entry */
			bind_info.nat_address_entry = (u_long) sptr_ip_translation_entry;
	
			status = natSetBind((u_long)&nat, 0, &bind_info);
			if(status != NAT_OK)
			{
				nat_printf (NAT_PRINTF_ERROR, 
					"handle_tcp_translation_global_rx_natg: natSetBind returned %d\n",status);
				return(FAIL);
			}
			semTake(natentrylock, WAIT_FOREVER);
			sptr_tcp_translation_entry = (NAT_CURRENCY_TRANSLATION_ENTRY *) bind_info.nat_transport_entry;
		}
		else
		{
			return (FAIL);
		}
	}

	tcp_sequence_number_fixup_global_rx (&sptr_tcp_packet->tcp_header, sptr_tcp_translation_entry);
/*
	if (ntohl(sptr_tcp_packet->tcp_header.sequence_number) >= 
			ntohl(sptr_tcp_translation_entry->global_sequence_number))
	{
		do_state_transition = TRUE;
	}
	else 
	*/
	if (sptr_tcp_packet->tcp_header.flags.reset_flag == TRUE)
	{
		do_state_transition = TRUE;
	}
	else
 	{
            do_state_transition = FALSE;
	}

/*
	sptr_tcp_translation_entry->global_sequence_number = sptr_tcp_packet->tcp_header.sequence_number;
*/
	if (do_state_transition == TRUE)
	{
		if (sptr_tcp_packet->tcp_header.flags.acknowledgment_flag == TRUE)
		{
			tcp_state_transistion_global_rx (NAT_ACK, sptr_tcp_translation_entry);
		}

		if (sptr_tcp_packet->tcp_header.flags.synchronize_flag == TRUE)
		{
			tcp_state_transistion_global_rx (NAT_SYNCH, sptr_tcp_translation_entry);
		}

		if (sptr_tcp_packet->tcp_header.flags.finished_flag == TRUE)
		{
			tcp_state_transistion_global_rx (NAT_FIN, sptr_tcp_translation_entry);
		}

		if (sptr_tcp_packet->tcp_header.flags.reset_flag == TRUE)
		{
			tcp_state_transistion_global_rx (NAT_RESET, sptr_tcp_translation_entry);
		}
			
		if ((sptr_tcp_packet->tcp_header.flags.acknowledgment_flag == FALSE) &&
			(sptr_tcp_packet->tcp_header.flags.synchronize_flag == FALSE) &&
			(sptr_tcp_packet->tcp_header.flags.reset_flag == FALSE) &&
			(sptr_tcp_packet->tcp_header.flags.finished_flag == FALSE))
		{
			tcp_state_transistion_global_rx (NAT_ESTABLISHED, sptr_tcp_translation_entry);
		}
	}
	semGive(natentrylock);
	return (PASS);
}
/**************************************************************************************************
Description:
	This function handles translation of TCP packets received from global port in NAPT mode.
	- First, see if there is a match of the spoofed port.  
	- If yes and this is not a static entry (see NOTE below), go ahead and translate.
	- If no or static entry, check for a match of the tuple of local address & port and 
	  global port in the TCP translation list.
	- If no match is found, check if the destination port can be found in the static port table.
	- If no, look for a match in the IP translation list (i.e. process it as Basic NAT).
	- Fix up the TCP sequence number if necessary.
	- Do the address and port translation on the packet before giving it to the higher layer.

NOTE:
	If static entry is true, it implies the session was started inbound.  It is not enough that 
	the spoofed port match is found since the spoofed port is the global port assigned from the 

⌨️ 快捷键说明

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