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

📄 natftpalg.c

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

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

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

/* WindNet NAT "installable" FTP Application Level Gateway (ALG) */

/*
modification history
--------------------
01b,24apr03,zhu  updated copyright
01a,21apr03,myz replaced swap(_long) with the ntohs(l) and htons(l) macros,
                replaced RWOS list functions with ones in dllLib.c
040903  vks updated Copyright info
040303  vks replaced table_malloc and table_free with calloc and free respectively
092002  vvv fixed Diab warning
102201  tk  Fix code to find start of FTP payload to take into account the
            option field in the IP header.
092101  tk  Modify due to changes in the natGetTransportBind() format.  Problem
			found due to NAT changes to work with mib.  Also, bug fixes for
			multiple FTP clients session with local FTP server.
071301	tk	Redo entire implementation of ALG to use the upgraded version of NAT
			ALG API to interact with NAT.  The new implementation is based on the
			assumption that the IP/TCP headers have been translated by NAT (i.e.
			post NAT translation).  The TCP sequence adjustment code is now
			modularized in a separate subroutine.
060701	tk	Fix Linux FTP problem.  Linux FTP uses the options field in the TCP
			header while the code always assumed the TCP header was always 20
			bytes long (SPR#67124).
051501	tk	Fix handling of reply to PASV command (SPR#67123).
030901	tk	Fix synchronization problem with NAT initialization.
*/
/*
#define		FTP_DEBUG
*/
/* ANSI headers */
#include <stdio.h>			/* printf */
#include <string.h>			/* memset */

/* VxWorks headers */
#include <in.h>				/* IPPROTO_TCP */

/* NAT-specific headers */
#include <nat/natAlgApi.h>
#include "nat.h"			/* IP_ADDRESS */
#include "natFtpAlg.h"

static const char* ftp_alg_desc 
	= "WindNet NAT - FTP ALG v1.0 - Copyright 2000-2003 Wind River Systems, Inc.";

static const char* ftp_alg_name = "FTP ALG";

static	NAT_ID_INFO		nat_id;
NAT_AGENT_INFO	agent_info;

/*****************************************************************************************
Function:	natFtpPacket

Description: 
	
******************************************************************************************/
BOOL natFtpPacket(u_long nat_id, u_long agent_id, u_long session_id, 
	NAT_DIRECTION direction, void* packet)
{
	USHORT local_port_number;
	USHORT global_port_number;
	char *cptr_port_string;
	char *cptr_end_port_string;
	char *end_of_tcp_header;	
	USHORT tmp1, tmp2, tmp3, tmp4, tmp5, tmp6;
	IP_ADDRESS local_address;
	IP_ADDRESS global_address;
	BYTE *bptr_local_address;
	BYTE *bptr_global_address;
	char port_string[FTP_MAXIMUM_PORT_STRING_LENGTH];	/* also for PASV string */
	ULONG new_port_string_length;
	ULONG old_port_string_length;	
	NAT_CURRENCY_TRANSLATION_ENTRY *sptr_tcp_translation_entry = NULL;
	int dummy_value;
	TCP_PACKET *sptr_tcp_packet;
	NAT_TRANSPORT transport;
	TCP_HEADER *tcp_start;

	if (direction != NAT_OUTBOUND)
		{
		return(TRUE);
		}

	sptr_tcp_packet = (TCP_PACKET*)packet;

	memset(&transport, 0, sizeof(NAT_TRANSPORT));

	/* need to look for the port or pasv command.  Then have to look for the IP address and
	   the port address.  Then must create a TCP control block and spoof the port
	   number, and change the ip address, and do the sequence number setting.
	*/

	/* find the start of TCP payload */
	cptr_port_string = (char *) (&sptr_tcp_packet->ip_header);
	cptr_port_string += (sptr_tcp_packet->ip_header.version_header_length.header_length << 2);
	tcp_start = (TCP_HEADER *) cptr_port_string;
	cptr_port_string += (tcp_start->header_length_byte.header_length << 2);
	end_of_tcp_header = cptr_port_string; 

	/***************************************************/
	/* PASV Section (for FTP servers "behind" the NAT) */
	/***************************************************/

	if (sscanf (cptr_port_string, FTP_PASV_PARAMETER_STRING, &dummy_value, &tmp1, &tmp2, &tmp3, &tmp4, &tmp5, &tmp6) == 
		FTP_PASV_PARAMETER_COUNT)
		{
		nat_printf (NAT_PRINTF_TRACE, "FTP ALG: FTP Reply for PASV command\n");

		sprintf (port_string, FTP_PASV_PARAMETER_STRING, FTP_PASV_RETURN_CODE, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6);

		nat_printf (NAT_PRINTF_TRACE, "FTP ALG: FTP old PASV string: %s\n", port_string);

		cptr_end_port_string = strchr (cptr_port_string, FTP_PASV_STRING_END_MARKER);

		if (cptr_end_port_string == NULL)
			{
			return(TRUE);	/* incomplete PASV command, disregard */
			}

		++cptr_end_port_string;

		old_port_string_length = (ULONG) (cptr_end_port_string - cptr_port_string);

		/* tk:  The global (remote) port is still unknown now, so just set it to 0.
		   The remote port will be set to the right port number when the data connection 
		   is initiated by the local FTP client.
		*/
		global_port_number = 0x0000;

		local_port_number = (USHORT) (tmp5 * 0x100 + tmp6);

		bptr_local_address = (BYTE *) &local_address;
			
		bptr_local_address[3] = (BYTE) (tmp4 & 0x00FF);
		bptr_local_address[2] = (BYTE) (tmp3 & 0x00FF);
		bptr_local_address[1] = (BYTE) (tmp2 & 0x00FF);
		bptr_local_address[0] = (BYTE) (tmp1 & 0x00FF);

		local_address = ntohl (local_address);

		nat_printf (NAT_PRINTF_DATA, "FTP ALG: FTP PASV IP address: %x\n", local_address);

		if (nat.single_global_address_enabled == false)
				{	/* basic NAT */
				if (ftp_get_tcp_entry((ULONG)local_address, (char *) sptr_tcp_packet,
						&transport) != OK)
					{
					nat_printf(NAT_PRINTF_ERROR, "natFtpPacket: ftp_get_tcp_entry returns ERROR\n");
					return (FALSE);
					}

				sptr_tcp_translation_entry = (NAT_CURRENCY_TRANSLATION_ENTRY *) transport.tcp_block_ptr;
				}
			else
				{	/* NAPT */
				if (ftp_get_global_transport(local_address, local_port_number,
					(char *) sptr_tcp_packet, &transport) != OK)
					{
					nat_printf(NAT_PRINTF_ERROR, "natFtpPacket: ftp_get_tcp_entry returns ERROR\n");
					return (FALSE);
					}

				sptr_tcp_translation_entry = (NAT_CURRENCY_TRANSLATION_ENTRY *) transport.tcp_block_ptr;
				local_port_number = transport.global_port;

				tmp5 = (USHORT) (local_port_number/0x100);
				tmp6 = (USHORT) (local_port_number % 0x100);
				}
			
		global_address = transport.global_address;
		global_address = htonl (global_address);
				
		bptr_global_address = (BYTE *) &global_address;

		tmp4 = bptr_global_address[3];
		tmp3 = bptr_global_address[2];
		tmp2 = bptr_global_address[1];
		tmp1 = bptr_global_address[0];

		sprintf (port_string, FTP_PASV_PARAMETER_STRING, FTP_PASV_RETURN_CODE, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6);

		nat_printf (NAT_PRINTF_TRACE, "FTP ALG: FTP new PASV string: %s\n", port_string);

#ifdef	FTP_DEBUG
			printf ("FTP PASV IP address: 0x%lx\n", local_address);

			printf ("FTP PASV translated IP Address 0x%lx\n", ntohl(global_address));

			printf ("FTP translated PASV string: %.*s\n", 
						strlen(port_string)-2, port_string);
#endif
		new_port_string_length = (ULONG) strlen (port_string);

		if (adjust_tcp_sequence(
					(char *)sptr_tcp_packet, 
					cptr_port_string, 
					port_string,
					old_port_string_length, 
					new_port_string_length, 
					(char *)sptr_tcp_translation_entry) == ERROR)
			{
			return (FALSE);
			}
		}

	/****************/
	/* PORT Section */
	/****************/

	else
		{
		if (sscanf (cptr_port_string, FTP_PORT_PARAMETER_STRING, 
				&tmp1, &tmp2, &tmp3, &tmp4, &tmp5, &tmp6) == FTP_PORT_PARAMETER_COUNT)		
			{
			nat_printf (NAT_PRINTF_TRACE, "FTP ALG: FTP PORT command found\n");

			cptr_end_port_string = strchr (cptr_port_string, FTP_PORT_STRING_END_MARKER);

			if (cptr_end_port_string == NULL)
				{
				nat_printf (NAT_PRINTF_ERROR, "natFtpPacket: Incomplete PORT command, disregard\n");
				return(TRUE);	/* incomplete PORT command, disregard */
				}

			++cptr_end_port_string;

			old_port_string_length = (ULONG) (cptr_end_port_string - cptr_port_string);

			nat_printf (NAT_PRINTF_TRACE, "FTP ALG: FTP PORT command: %.*s\n"
					,old_port_string_length-2, cptr_port_string);

			/* tk:  The global (remote) port is still unknown now, so just set it to 0.
			   The remote port will be set to the right port number when the data connection 
			   is initiated by the remote FTP server.
			*/
			global_port_number = 0x0000;

			local_port_number = (USHORT) (tmp5 * 0x100 + tmp6);

			bptr_local_address = (BYTE *) &local_address;
		
			bptr_local_address[3] = (BYTE) (tmp4 & 0x00FF);
			bptr_local_address[2] = (BYTE) (tmp3 & 0x00FF);
			bptr_local_address[1] = (BYTE) (tmp2 & 0x00FF);
			bptr_local_address[0] = (BYTE) (tmp1 & 0x00FF);

			sprintf (port_string, FTP_PORT_PARAMETER_STRING, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6);

			nat_printf (NAT_PRINTF_DATA, "FTP ALG: FTP original PORT string: %.*s\n", 
						strlen(port_string)-2, port_string);

			local_address = ntohl (local_address);

			if (nat.single_global_address_enabled == false)
			{	/* basic NAT */
				if (ftp_get_tcp_entry((ULONG)local_address, (char *) sptr_tcp_packet,
						&transport) != OK)
				{
					return (FALSE);
				}

				sptr_tcp_translation_entry = (NAT_CURRENCY_TRANSLATION_ENTRY *) transport.tcp_block_ptr;
			}
			else
			{	/* NAPT */
				if (ftp_get_global_transport(local_address, local_port_number,
					(char *) sptr_tcp_packet, &transport) != OK)
				{
					return (FALSE);
				}

				sptr_tcp_translation_entry = (NAT_CURRENCY_TRANSLATION_ENTRY *) transport.tcp_block_ptr;
				local_port_number = transport.global_port;
				tmp5 = (USHORT) (local_port_number/0x100);
				tmp6 = (USHORT) (local_port_number % 0x100);
				
			}

			global_address = transport.global_address;

			global_address = htonl (global_address);
			
			bptr_global_address = (BYTE *) &global_address;
			
			tmp4 = bptr_global_address[3];
			tmp3 = bptr_global_address[2];
			tmp2 = bptr_global_address[1];
			tmp1 = bptr_global_address[0];
			
			sprintf (port_string, FTP_PORT_PARAMETER_STRING, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6);

			nat_printf (NAT_PRINTF_TRACE, "FTP ALG: FTP translated PORT string: %.*s\n", 
						strlen(port_string)-2, port_string);

#ifdef	FTP_DEBUG
			printf ("FTP PORT IP address: 0x%lx\n", local_address);

			printf ("FTP PORT translated IP Address 0x%lx\n", ntohl(global_address));

			printf ("FTP translated PORT string: %.*s\n", 
						strlen(port_string)-2, port_string);
#endif

			new_port_string_length = (ULONG) strlen (port_string);
			if (adjust_tcp_sequence(	/* adjust TCP sequence number */
					(char *)sptr_tcp_packet, 
					cptr_port_string, 
					port_string,
					old_port_string_length, 
					new_port_string_length, 
					(char *)sptr_tcp_translation_entry) == ERROR)
				{
				return (FALSE);
				}
			}
		}
			
		return (TRUE);

}

/*****************************************************************************************
Function:	natFtpInit

Description: 
	
******************************************************************************************/
STATUS natFtpInit(u_short ftp_port)
{
	STATUS			status;

	semTake (natInitSync, WAIT_FOREVER);    /* wait for event */

	nat_printf(NAT_PRINTF_INIT, "FTP initialization: port = %u\n", ftp_port);

	memset(&nat_id, 0, sizeof(nat_id));

	status = natGetID(&nat_id);

	if (status != NAT_OK)
		{
		nat_printf(NAT_PRINTF_ERROR, "natFtpInit: natGetID failed with error %d\n", status);

		return(status);
		}

	memset(&agent_info, 0, sizeof(agent_info));

	agent_info.type = NAT_AGENT_TYPE_ALG;
	agent_info.flags = NAT_FLAG_POST_XLAT;

⌨️ 快捷键说明

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