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

📄 nat_icmp_datagram.c

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

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

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

/*
modification history
--------------------
01g,16may03,myz  Reworked SPR#87054 fix
01f,13may03,myz  fixed wrong port number problem in functions: handle_icmp
		 _embedded_tcp(udp)_translation_global_rx_datagram_nats.
01e,23apr03,zhu  updated copyright
01d,21apr03,myz  replaced swap(_long) with the ntohs(l) and htons(l) macros.
01c,10apr03,zhu  allow icmp protocol type in icmp host unreachable message
                 datagram
01b,10apr03,zhu  cleaned up SPR#87054 fix
01a,28mar03,zhu  SPR#87054 fix: send ICMP host unreachable message back to
		 local host
100901  tk      Changes due to parameter addition in match_spoofed_port_with_udp_entry.
072601  tk      Fix call to match_ports_with_udp_entry to use match_ports_with_udp_entry_inbound
                and match_ports_with_udp_entry_outbound instead.  Also fix call to
                match_ports_with_tcp_entry to use match_ports_with_tcp_entry_inbound
                and match_ports_with_tcp_entry_outbound instead.
050701  tk      Update handle_icmp_translation_global_rx_datagram_nats to check for embedded ICMP
                frame (for time-exceeded message).  Add a new function
                handle_icmp_embedded_icmp_translation_global_rx_datagram_nats to process embedded
                ICMP translation (e.g. ICMP time-exceeded message).
042101  tk      Fix bugs in basic NAT ICMP translations for both global port and local port in
                functions handle_icmp_translation_global_rx_datagram_natg() and
                handle_icmp_translation_local_rx_datagram_natg () respectively.
                The bugs can cause page fault, wrong address translation in embedded IP, and
                checksum errors.
*/

#include "nat.h"
/************************************************************************/
static enum TEST handle_icmp_translation_global_rx_datagram_nats (ICMP_PACKET *sptr_icmp_packet);
static enum TEST handle_icmp_translation_global_rx_datagram_natg (ICMP_PACKET *sptr_icmp_packet);
static enum TEST handle_icmp_translation_local_rx_datagram_nats (ICMP_PACKET *sptr_icmp_packet);
static enum TEST handle_icmp_translation_local_rx_datagram_natg (ICMP_PACKET *sptr_icmp_packet);
static enum TEST handle_icmp_embedded_tcp_translation_global_rx_datagram_nats (ICMP_PACKET *sptr_icmp_packet);
static enum TEST handle_icmp_embedded_udp_translation_global_rx_datagram_nats (ICMP_PACKET *sptr_icmp_packet);
static enum TEST handle_icmp_embedded_tcp_translation_local_rx_datagram_nats (ICMP_PACKET *sptr_icmp_packet);
static enum TEST handle_icmp_embedded_udp_translation_local_rx_datagram_nats (ICMP_PACKET *sptr_icmp_packet);
static enum TEST handle_icmp_embedded_icmp_translation_global_rx_datagram_nats (ICMP_PACKET *sptr_icmp_packet);
/************************************************************************/
enum TEST handle_icmp_translation_global_rx_datagram (ICMP_PACKET *sptr_icmp_packet)
{
	enum TEST pass_or_fail;

	if (nat.single_global_address_enabled == TRUE)
	{
		pass_or_fail = handle_icmp_translation_global_rx_datagram_nats (
		sptr_icmp_packet);

		if (pass_or_fail == FAIL)
		{
			/* Try IP translation, in case it use Basic NAT static entries */

			pass_or_fail = handle_icmp_translation_global_rx_datagram_natg(
			sptr_icmp_packet);	
		}
	}
	else
	{
		pass_or_fail = handle_icmp_translation_global_rx_datagram_natg (
		sptr_icmp_packet);
	}

	return (pass_or_fail);              
}
/***************************************************************************/
enum TEST handle_icmp_translation_local_rx_datagram (ICMP_PACKET *sptr_icmp_packet)
{
	enum TEST pass_or_fail;

	if (nat.single_global_address_enabled == TRUE)
	{
		pass_or_fail = handle_icmp_translation_local_rx_datagram_nats (
		sptr_icmp_packet);

		if (pass_or_fail == FAIL)
		{
			/* Try IP translation, in case it use Basic NAT static entries */

			pass_or_fail = handle_icmp_translation_local_rx_datagram_natg(
			sptr_icmp_packet);   
		}
	}
	else
	{
		pass_or_fail = handle_icmp_translation_local_rx_datagram_natg (
		sptr_icmp_packet);
	}

	return (pass_or_fail);              
}

/**********************************************************************************************
Description:
    Handle packet received from global port in Basic NAT
**********************************************************************************************/
static enum TEST handle_icmp_translation_global_rx_datagram_natg (ICMP_PACKET *sptr_icmp_packet)
{
    ICMP_DATA changed_data;
    ICMP_DATA unchanged_data;
    IP_PACKET nested_ip_packet;
    IP_TRANSLATION_ENTRY *sptr_ip_translation_entry;
    USHORT  checksum;

    nested_ip_packet.header = sptr_icmp_packet->header.option.unreachable_message.ip_data;

    nat_printf (NAT_PRINTF_TRACE, "ICMP: translate embedded IP header\n");

    unchanged_data.ip_data.addresses.source_address = nested_ip_packet.header.source_address;
    unchanged_data.ip_data.addresses.destination_address = nested_ip_packet.header.destination_address;
    unchanged_data.ip_data.ip_checksum = nested_ip_packet.header.header_checksum;

    sptr_ip_translation_entry = match_sa_with_global_address (
            ntohl (unchanged_data.ip_data.addresses.source_address),
            &nat.natg.ip_translation_list);

    if (sptr_ip_translation_entry == NULL)
    {
        nat_printf (NAT_PRINTF_TRACE, "ICMP received global: Can't match embedded source IP in ICMP datagram.\n");
        return (FAIL);
    }
    
    changed_data.ip_data.addresses.source_address = htonl (sptr_ip_translation_entry->sa_local_address);    
    changed_data.ip_data.addresses.destination_address = nested_ip_packet.header.destination_address;
    changed_data.ip_data.ip_checksum = nested_ip_packet.header.header_checksum;

    /* adjust checksum in embedded IP header */
    checksum_fixup ((BYTE *) &changed_data.ip_data.ip_checksum,
            (BYTE *) &unchanged_data.ip_data.addresses.source_address, (USHORT) sizeof (IP_ADDRESS),
            (BYTE *) &changed_data.ip_data.addresses.source_address, (USHORT )sizeof (IP_ADDRESS));

    nested_ip_packet.header.source_address = changed_data.ip_data.addresses.source_address;
    nested_ip_packet.header.header_checksum = changed_data.ip_data.ip_checksum; 
    changed_data.icmp_checksum = sptr_icmp_packet->header.checksum;

    /* adjust ICMP header checksum, first with change in embedded IP address */
    checksum_fixup ((BYTE *) &changed_data.icmp_checksum,
            (BYTE *) &sptr_icmp_packet->header.option.unreachable_message.ip_data.source_address,
            sizeof (ULONG),
            (BYTE *) &nested_ip_packet.header.source_address,
            sizeof (ULONG));

    checksum = changed_data.icmp_checksum;  /* save for printing debug msg */

    /* adjust ICMP header checksum, then with change in embedded IP header checksum */
    checksum_fixup ((BYTE *) &changed_data.icmp_checksum,
            (BYTE *) &sptr_icmp_packet->header.option.unreachable_message.ip_data.header_checksum,
            sizeof (USHORT),
            (BYTE *) &nested_ip_packet.header.header_checksum,
            sizeof (USHORT));

    sptr_icmp_packet->header.option.unreachable_message.ip_data.source_address =
        changed_data.ip_data.addresses.source_address;
    sptr_icmp_packet->header.option.unreachable_message.ip_data.destination_address =
        changed_data.ip_data.addresses.destination_address;

    sptr_icmp_packet->header.option.unreachable_message.ip_data.header_checksum =
        changed_data.ip_data.ip_checksum;

    sptr_icmp_packet->header.checksum = changed_data.icmp_checksum;

    nat_printf (NAT_PRINTF_TRACE, "ICMP received global: translate IP header of ICMP packet\n");

    /* this function also adjusts IP header's checksum */
    if (handle_ip_translation_global_rx_natg ((IP_PACKET *) sptr_icmp_packet) == NULL)
        {
        return (FAIL);
        }

    return (PASS);  
}

/**********************************************************************************************
Description:
    Handle ICMP packet received from global port in NAPT.  The ICMP datagram may be of
    destination unreachable message or time-exceeded message.
**********************************************************************************************/
static enum TEST handle_icmp_translation_global_rx_datagram_nats (ICMP_PACKET *sptr_icmp_packet)
{
	if (sptr_icmp_packet->header.type == ICMP_DESTINATION_UNREACHABLE_TYPE)
	{
		switch (sptr_icmp_packet->header.option.unreachable_message.ip_data.protocol)
		{
			case TCP_PROTOCOL:
				if (handle_icmp_embedded_tcp_translation_global_rx_datagram_nats (sptr_icmp_packet) == FAIL)
				{
					return (FAIL);
				}

			break;

			case UDP_PROTOCOL:
				if (handle_icmp_embedded_udp_translation_global_rx_datagram_nats (sptr_icmp_packet) == FAIL)
				{
					return (FAIL);
				}

			break;

			case ICMP_PROTOCOL:
				if (handle_icmp_embedded_icmp_translation_global_rx_datagram_nats (sptr_icmp_packet) == FAIL)
				{
					return (FAIL);
				}

			break;

			default:
				nat_printf(NAT_PRINTF_ERROR,
				"Global port: Unrecognized protocol in ICMP unreachable message datagram.\n");
			return (FAIL);
		}
	}
	else if (sptr_icmp_packet->header.type == ICMP_TIME_EXCEEDED_TYPE)
	{
		switch (sptr_icmp_packet->header.option.time_exceeded_message.ip_data.protocol)
		{
			case ICMP_PROTOCOL:
				if (handle_icmp_embedded_icmp_translation_global_rx_datagram_nats (sptr_icmp_packet) == FAIL)
				{
					return (FAIL);
				}

			break;

			default:
				nat_printf (NAT_PRINTF_ERROR,
				"Global port: Unrecognized protocol in ICMP time-exceeded datagram.\n");
			return (FAIL);
		}
	}

	return (PASS);  
}

/**********************************************************************************************
Description:
    Handle ICMP packet received from local port in NAPT.  Only needs to handle destination
    unreachable message.  There is no reason that NAT should receive time-exceeded message
    from local port.
**********************************************************************************************/
static enum TEST handle_icmp_translation_local_rx_datagram_nats (ICMP_PACKET *sptr_icmp_packet)
{

	switch (sptr_icmp_packet->header.option.unreachable_message.ip_data.protocol)
	{
		case TCP_PROTOCOL:
			if (handle_icmp_embedded_tcp_translation_local_rx_datagram_nats (sptr_icmp_packet) == FAIL)
			{
				return (FAIL);
			}
		break;

		case UDP_PROTOCOL:
			if (handle_icmp_embedded_udp_translation_local_rx_datagram_nats (sptr_icmp_packet) == FAIL)
			{
				return (FAIL);
			}               
		break;

		default:
			nat_printf (NAT_PRINTF_ERROR,
			"Local port: Unrecognized protocol in ICMP unreachable message datagram.\n");
			return (FAIL);
	}

	return (PASS);
}

/***************************************************************************/
static enum TEST handle_icmp_embedded_tcp_translation_global_rx_datagram_nats (ICMP_PACKET *sptr_icmp_packet)
{
	 
	NAT_ICMP_EMBEDDED_HEADER *sptr_icmp_embedded_header=NULL;
	NAT_CURRENCY_TRANSLATION_ENTRY *sptr_tcp_translation_entry=NULL;
	IP_ADDRESS address;
	USHORT local_port_number;
	USHORT checksum;
	TCP_PACKET sptr_tcp_packet;

	sptr_tcp_packet = *(TCP_PACKET *)&sptr_icmp_packet->header.option.unreachable_message.ip_data;

	sptr_icmp_embedded_header = (NAT_ICMP_EMBEDDED_HEADER *) &sptr_icmp_packet->header.option.unreachable_message.ip_data;

	semTake(natentrylock, WAIT_FOREVER);

	if(!sptr_tcp_translation_entry)
		sptr_tcp_translation_entry = match_ports_with_tcp_entry_inbound (&sptr_tcp_packet);

	semGive(natentrylock);
	/* Did we find a TCP translation entry? */
	if (sptr_tcp_translation_entry == NULL)
	{
		/* no way to determine who to send the ICMP message to*/
		return FAIL;
	}

	/* TCP translation entry found */
	address = htonl (sptr_tcp_translation_entry->local_address);

	local_port_number = htons (sptr_tcp_translation_entry->local_port);

	tcp_sequence_number_fixup_global_rx (&sptr_tcp_packet.tcp_header, sptr_tcp_translation_entry);

	if (local_port_number != 0x0000)
	{
		checksum = sptr_tcp_packet.tcp_header.checksum;

		checksum_fixup ((BYTE *) &checksum,
		(BYTE *) &sptr_tcp_packet.tcp_header.source_port, sizeof (USHORT),
		(BYTE *) &local_port_number, sizeof (USHORT));

		sptr_tcp_packet.tcp_header.source_port = local_port_number;
		sptr_tcp_packet.tcp_header.checksum = checksum;
	}

	checksum = sptr_tcp_packet.ip_header.header_checksum;

	checksum_fixup ((BYTE *) &checksum,
	(BYTE *) &sptr_tcp_packet.ip_header.source_address, sizeof (IP_ADDRESS),
	(BYTE *) &address, sizeof (IP_ADDRESS));

	sptr_tcp_packet.ip_header.source_address = address;
	sptr_tcp_packet.ip_header.header_checksum = checksum;

	checksum = sptr_icmp_packet->header.checksum;

	checksum_fixup ((BYTE *) &checksum,
	(BYTE *) &sptr_icmp_packet->header.option.unreachable_message.ip_data, sizeof (NAT_ICMP_EMBEDDED_HEADER),
	(BYTE *) &sptr_tcp_packet, sizeof (NAT_ICMP_EMBEDDED_HEADER));

	*sptr_icmp_embedded_header = *(NAT_ICMP_EMBEDDED_HEADER *) &sptr_tcp_packet;
	sptr_icmp_packet->header.checksum = checksum;

	checksum = sptr_icmp_packet->ip_header.header_checksum;

	checksum_fixup ((BYTE *) &checksum,
	(BYTE *) &sptr_icmp_packet->ip_header.destination_address, sizeof (IP_ADDRESS),
	(BYTE *) &address, sizeof (IP_ADDRESS));

	sptr_icmp_packet->ip_header.destination_address = address;
	sptr_icmp_packet->ip_header.header_checksum = checksum;
    
    return (PASS);
}
/***************************************************************************/
static enum TEST handle_icmp_embedded_udp_translation_global_rx_datagram_nats (ICMP_PACKET *sptr_icmp_packet)
{
	NAT_ICMP_EMBEDDED_HEADER *sptr_icmp_embedded_header=NULL;
	NAT_CURRENCY_TRANSLATION_ENTRY *sptr_udp_translation_entry=NULL;
	IP_ADDRESS address;
	USHORT checksum;
	USHORT local_port_number;

⌨️ 快捷键说明

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