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

📄 natftpalg.c

📁 VXWORKS NAT 部分源代码3 有兴趣朋友可以参考下
💻 C
📖 第 1 页 / 共 2 页
字号:
	agent_info.session_tag.protocol = IPPROTO_TCP;
	agent_info.session_tag.transport = ftp_port;
	agent_info.packet_callback = natFtpPacket;

	sprintf(agent_info.desc, "%.*s", (int)(sizeof(agent_info.desc)-1), ftp_alg_desc);
	sprintf(agent_info.name, "%.*s", (int)(sizeof(agent_info.name)-1), ftp_alg_name);

	status = natRegisterAgent(nat_id.id, &agent_info);

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

		return(status);
		}

	printf ("FTP ALG registered with NAT\n");

	semGive(natInitSync);

	return(OK);
}


STATUS natFtpend(void)
{
	STATUS			status;

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

	status = natUnregisterAgent(nat_id.id, agent_info.id);

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

		return(status);
		}
	semGive(natInitSync);

	return(OK);
}

/*****************************************************************************************
Function:	ftp_get_tcp_entry

Description: 
	Since the FTP ALG is in post NAT translation, by now the IP header already contains
	the translated source address (we call it global address as opposed to local address).
	Thus, the address translation must already exist in the NAT IP translation list.
	This function calls the API function natGetAddrBind to find the translation entry
	in the IP translation list, then use that entry to find the TCP entry spawned off
	the IP translation (which is how TCP connection is handled internally by NAT when
	it operates in basic NAT mode).  This TCP entry will be needed later by natFtpPacket
	for TCP sequence adjustment.
******************************************************************************************/
STATUS ftp_get_tcp_entry(
	ULONG	local_address,
	char	*packet,
	NAT_TRANSPORT *transport)
{
	NAT_BIND_INFO  bind_info;
	NAT_BIND_SESSION    session;
	NAT_STATUS	status;
	TCP_PACKET *sptr_tcp_packet;

	sptr_tcp_packet = (TCP_PACKET *) packet;

	/* sanity check to ensure that the bind descriptor for the IP translation already exists */
	if ((status = natGetAddrBind((u_long)&nat, 
					(u_long)local_address, 
					ntohl(sptr_tcp_packet->ip_header.source_address), 
					&bind_info)) != NAT_OK)
	{
		nat_printf (NAT_PRINTF_ERROR, 
			"ftp_get_tcp_entry: Status = %d, Bind of local address %x to global address %x not found\n", 
			status, local_address, ntohl(sptr_tcp_packet->ip_header.source_address));

		return (ERROR);
	}

	/* call natGetTransportBind to get the pointer to the TCP translation entry */

	session.protocol = IPPROTO_TCP;
	session.local_addr = local_address;
	session.local_transport = ntohs(sptr_tcp_packet->tcp_header.source_port);;
	session.global_addr = ntohl(sptr_tcp_packet->ip_header.source_address);
	session.global_transport = ntohs(sptr_tcp_packet->tcp_header.source_port);
	session.remote_addr = ntohl(sptr_tcp_packet->ip_header.destination_address);
	session.remote_transport = ntohs(sptr_tcp_packet->tcp_header.destination_port);

	if ((status = natGetTransportBind((u_long)&nat, &session, &bind_info, NAT_BIND_FULL)) != NAT_OK)
	{
		nat_printf (NAT_PRINTF_ERROR, 
			"ftp_get_tcp_entry: Status = %d, Transport Bind of address %x port %d not found\n",
			status, ntohl(sptr_tcp_packet->ip_header.source_address),
			ntohs(sptr_tcp_packet->tcp_header.source_port));

		return(ERROR);
	}

	/* need this for TCP sequence adjustment later */
	transport->tcp_block_ptr = (char *) bind_info.nat_transport_entry;
	transport->global_address = bind_info.global_addr;

	return (OK);
}

/************************************************************************************
Function:	ftp_get_global_transport

Description: 
	Since the FTP ALG is in post NAT translation, by now the TCP connection has been
	established between FTP client and server.  The source address/port in IP/TCP
	header has been translated.  This function calls natGetTransportBind to get the
	TCP control block entry in the TCP translation list.  This entry will be needed
	later by natFtpPacket for TCP sequence adjustment.  Furthermore, this function
	creates a new TCP control block using the address/port pair from the FTP PORT or
	PASV parameters by calling the API function natSetBind in preparation of the
	upcoming data connection.  This must be done by the ALG in NAPT mode to get the
	translated port number (i.e. global port number) so the natFtpPacket can put it 
	in the FTP payload to replace the original port number for the establishment of 
	the data connection.
************************************************************************************/
STATUS ftp_get_global_transport(
	ULONG	local_address,
	USHORT	local_port,
	char	*packet,
	NAT_TRANSPORT *transport)
{
	NAT_BIND_INFO  bind_info;
	NAT_BIND_SESSION    session;
	NAT_STATUS	status;
	TCP_PACKET *sptr_tcp_packet;

	sptr_tcp_packet = (TCP_PACKET *) packet;

	/* check to make sure the FTP control bind exists */

	session.protocol = IPPROTO_TCP;
	session.local_addr = local_address;
	session.local_transport = local_port;
	session.global_addr = ntohl(sptr_tcp_packet->ip_header.source_address);
	session.global_transport = ntohs(sptr_tcp_packet->tcp_header.source_port);
	session.remote_addr = ntohl(sptr_tcp_packet->ip_header.destination_address);
	session.remote_transport = ntohs(sptr_tcp_packet->tcp_header.destination_port);

	if ((status = natGetTransportBind((u_long)&nat, &session, &bind_info, NAT_BIND_FULL)) != NAT_OK)
	{
		
		nat_printf (NAT_PRINTF_ERROR, 
			"ftp_get_global_transport: Status = %d, Transport Bind of address %x port %d not found\n",
			status, ntohl(sptr_tcp_packet->ip_header.source_address),
			ntohs(sptr_tcp_packet->tcp_header.source_port));

		return(ERROR);
	}

	/* need this for TCP sequence adjustment later */
	transport->tcp_block_ptr = (char *) bind_info.nat_transport_entry;

	/* create a new bind for FTP data connection (note that the data packet hasn't 
	   been received yet) */				
	memset(&bind_info,0,sizeof(bind_info));
	bind_info.id = 0;	/* request to create a new bind */
	bind_info.agent_id = agent_info.id;
	bind_info.type = NAT_BIND_NAPT;
	bind_info.direction = NAT_OUTBOUND;
	bind_info.protocol = IPPROTO_TCP;
	bind_info.static_entry = FALSE;
	bind_info.local_addr = (u_long)local_address;
	bind_info.local_transport = local_port;
	bind_info.global_addr = ntohl(sptr_tcp_packet->ip_header.source_address);
	bind_info.global_transport = 0;
	bind_info.remote_addr = ntohl(sptr_tcp_packet->ip_header.destination_address);
	bind_info.remote_transport = 0;	/* destination port is still unknown here */

	status = natSetBind((u_long)&nat, agent_info.id, &bind_info);
	if(status != NAT_OK)
	{
		nat_printf (NAT_PRINTF_ERROR, "ftp_get_global_transport: natSetBind returned %d\n",status);
		return (ERROR);
	}

	transport->global_address = bind_info.global_addr;
	transport->global_port = bind_info.global_transport;

	return (OK);
}

/************************************************************************************
Function:	adjust_tcp_sequence

Description: 
	Adjust TCP sequence number and recompute the TCP checksum.
************************************************************************************/
STATUS adjust_tcp_sequence (
	char	*tcp_packet,
	char	*old_string,
	char	*new_string,
	ULONG	old_string_length,
	ULONG	new_string_length,
	char	*tcp_entry
	)
{
	NAT_CURRENCY_TRANSLATION_ENTRY *sptr_tcp_translation_entry=NULL;
	TCP_PACKET *sptr_tcp_packet;
	int		sequence_number_delta;
	ULONG	end_of_packet_length;
	ULONG	data_length;
	USHORT 	total_length;
	USHORT	tcp_length, new_tcp_length;
	char	*end_old_string;
	char	*end_of_tcp_header;
	long	result;
	SEQUENCE_ENTRY *sptr_sequence_entry = NULL;
	SEQUENCE_ENTRY *sptr_old_sequence_entry = NULL;
	BYTE *bptr_end_of_packet_buffer = NULL;

	sptr_tcp_packet = (TCP_PACKET *) tcp_packet;
	sptr_tcp_translation_entry = (NAT_CURRENCY_TRANSLATION_ENTRY *) tcp_entry;


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

	end_old_string = (char *)(old_string + old_string_length);
	
	end_of_packet_length = 0x00000000L;

	tcp_length = (USHORT) (sptr_tcp_packet->ip_header.total_length - 
				(sptr_tcp_packet->ip_header.version_header_length.header_length << 2));
	data_length = (ULONG) (sptr_tcp_packet->ip_header.total_length - 
				(sptr_tcp_packet->ip_header.version_header_length.header_length << 2) - 
				(sptr_tcp_packet->tcp_header.header_length_byte.header_length << 2));

	sequence_number_delta = (int) (new_string_length - old_string_length);

	if (sequence_number_delta != 0x0000)
	{
		end_of_packet_length = (ULONG) (data_length - (end_old_string - end_of_tcp_header)); 

		if (end_of_packet_length != 0x00000000L)
		{
			bptr_end_of_packet_buffer = (BYTE *) malloc (end_of_packet_length);

			if (bptr_end_of_packet_buffer == NULL)
			    return (ERROR);
		}

		if (sptr_sequence_entry == NULL)
		{
			sptr_sequence_entry = (SEQUENCE_ENTRY *) calloc (1, sizeof (SEQUENCE_ENTRY));

			if (sptr_sequence_entry == NULL)
			{
				if (bptr_end_of_packet_buffer != NULL)
				{
					free (bptr_end_of_packet_buffer);
				}
	
				return (ERROR);
			}

			sptr_sequence_entry->link.sptr_forward_link = NULL;
			sptr_sequence_entry->link.sptr_backward_link = NULL;
			sptr_sequence_entry->sequence_number_base_adjust = 0x00000000L;
			sptr_sequence_entry->sequence_number_base = ntohl (sptr_tcp_packet->tcp_header.sequence_number);
			sptr_sequence_entry->sequence_number_delta = sequence_number_delta;
		}
		else
		{
			sptr_sequence_entry->sequence_number_delta = sptr_sequence_entry->sequence_number_delta + sequence_number_delta;
		}


		total_length = (USHORT) (sptr_tcp_packet->ip_header.total_length + sequence_number_delta);

		sptr_tcp_packet->ip_header.total_length = total_length;	/* host order */

		if (end_of_packet_length != 0x00000000L)
		{
			memcpy (bptr_end_of_packet_buffer, end_old_string, end_of_packet_length);
		}
	}

	checksum_fixup ((BYTE *) &sptr_tcp_packet->tcp_header.checksum,
				(BYTE *) old_string, (USHORT) old_string_length,
				(BYTE *) new_string, (USHORT) new_string_length);
			
	memcpy (old_string, new_string, new_string_length);

	if (sequence_number_delta != 0x0000)
	{
		end_old_string = old_string + new_string_length;

		if (end_of_packet_length != 0x00000000L)
		{
			memcpy (end_old_string, bptr_end_of_packet_buffer, end_of_packet_length);

			free (bptr_end_of_packet_buffer);
		}
	}

	new_tcp_length = (USHORT) (tcp_length + sequence_number_delta);

	new_tcp_length = htons (new_tcp_length);

	tcp_length = htons (tcp_length);

	checksum_fixup ((BYTE *) &sptr_tcp_packet->tcp_header.checksum,
					(BYTE *) &tcp_length, sizeof (USHORT),
					(BYTE *) &new_tcp_length, sizeof (USHORT));
	

	sptr_old_sequence_entry = NULL;

	if (sptr_sequence_entry != NULL)
	{
		sptr_sequence_entry->timer_enabled = FALSE;
		sptr_sequence_entry->entry_timer = nat.sequence_entry_timer;

		sptr_old_sequence_entry = (SEQUENCE_ENTRY *) DLL_FIRST (
					(DL_LIST *) &sptr_tcp_translation_entry->local_sequence_delta_list);

		if (sptr_old_sequence_entry != NULL)
		{
			result = sptr_sequence_entry->sequence_number_base - sptr_old_sequence_entry->sequence_number_base;

			if (result > 0x00000000L)
			{
				sptr_sequence_entry->sequence_number_base_adjust = sptr_old_sequence_entry->sequence_number_delta +
							sptr_old_sequence_entry->sequence_number_base_adjust;

				sptr_old_sequence_entry->timer_enabled = TRUE;
			}
			else
			{
				free (sptr_sequence_entry);

				sptr_sequence_entry = NULL;
			}
		}

		if (sptr_sequence_entry != NULL)
		{
			dllInsert ((DL_LIST *) &sptr_tcp_translation_entry->local_sequence_delta_list, NULL, (DL_NODE *) sptr_sequence_entry);
		}
	}

	return(OK);
}

⌨️ 快捷键说明

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