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

📄 nath323alg.c

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

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

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

/* WindNet NAT "installable" H.323 Application Level Gateway (ALG) */

/*
modification history
--------------------
01b,23apr03,zhu  updated copyright
01a,21apr03,myz replaced swap(_long) with the ntohs(l) and htons(l) macros.
111202  zhu Fixed Endianess problems for MACROs.
091902  jsv	Changed memory accesses to use macros and avoid alignment
                exceptions on MIPS.
101901  tk	Fix data type to avoid warning in T3 compiler.
092101  tk      Modify due to changes in the natGetTransportBind() format.
080801	tk	Add event callback routine for H.245 ALG
073001	tk	Redo entire H323 ALG. The old code was incorrectly designed.
042001	tk	Fix a bug in natH245Packet and add more comments
030901	tk	Fix synchronization problem with NAT initialization.
*/
/*
#define	H323_DEBUG
*/
/* NAT-specific headers */
#include <nat/natAlgApi.h>
#include "nat.h"			/* IP_ADDRESS */
#include <nat_api.h>		/* natGetGlobalAddress */

/* ANSI headers */
#include <stdio.h>			/* printf */
#include <string.h>			/* memset */

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

/* Global function declarations */
STATUS natH323Init(u_short h323_port);

static const char* h225_alg_desc 
	= "WindNet NAT - H.323/H.225 ALG v1.0 - Copyright 2000-2003 Wind River Systems, Inc.";
static const char* h225_alg_name = "H.225 ALG";

static const char* h245_alg_desc 
	= "WindNet NAT - H.323/H.245 ALG v1.0 - Copyright 2000-2003 Wind River Systems, Inc.";
static const char* h245_alg_name = "H.245 ALG";

static	NAT_ID_INFO		nat_instance[1];	/* currently support only one instance of NAT */
NAT_AGENT_INFO	h323Alg[2];	/* support 2 ALGs: H.225 and H.245 */

/* constants */
#define	IP_PORT_LENGTH			6	/* size of IP and port */
#define MAX_LOGICAL_CHANNELS	20	/* max number of logical channels (UDP) that can be opened */
#define T1_120_PORT				1503	/* T1.120 standard port */

/* macros */
#if	_BYTE_ORDER==_LITTLE_ENDIAN
#define READ_ALIGN_SAFE32(ptr)  ((ULONG)(  ((((BYTE*)(ptr))[3]) << 24) |    \
                                           ((((BYTE*)(ptr))[2]) << 16) |    \
                                           ((((BYTE*)(ptr))[1]) << 8)  |    \
                                           ((((BYTE*)(ptr))[0]) << 0)       \
                                ))
#define READ_ALIGN_SAFE16(ptr)  ((USHORT)( ((((BYTE*)(ptr))[1]) << 8)  |    \
                                           ((((BYTE*)(ptr))[0]) << 0)       \
                                ))
#define WRITE_ALIGN_SAFE32(ptr, val)                                        \
                            do {                                            \
                                ((BYTE*)(ptr))[3] = (((ULONG)(val)) >> 24); \
                                ((BYTE*)(ptr))[2] = (((ULONG)(val)) >> 16); \
                                ((BYTE*)(ptr))[1] = (((ULONG)(val)) >> 8);  \
                                ((BYTE*)(ptr))[0] = (((ULONG)(val)) >> 0);  \
                            } while(0)
#define WRITE_ALIGN_SAFE16(ptr, val)                                        \
                            do {                                            \
                                ((BYTE*)(ptr))[1] = (((ULONG)(val)) >> 8);  \
                                ((BYTE*)(ptr))[0] = (((ULONG)(val)) >> 0);  \
                            } while(0)

#endif	/* _BYTE_ORDER==_LITTLE_ENDIAN */


#if	_BYTE_ORDER==_BIG_ENDIAN
#define READ_ALIGN_SAFE32(ptr)  ((ULONG)(  ((((BYTE*)(ptr))[0]) << 24) |    \
                                           ((((BYTE*)(ptr))[1]) << 16) |    \
                                           ((((BYTE*)(ptr))[2]) << 8)  |    \
                                           ((((BYTE*)(ptr))[3]) << 0)       \
                                ))
#define READ_ALIGN_SAFE16(ptr)  ((USHORT)( ((((BYTE*)(ptr))[0]) << 8)  |    \
                                           ((((BYTE*)(ptr))[1]) << 0)       \
                                ))
#define WRITE_ALIGN_SAFE32(ptr, val)                                        \
                            do {                                            \
                                ((BYTE*)(ptr))[0] = (((ULONG)(val)) >> 24); \
                                ((BYTE*)(ptr))[1] = (((ULONG)(val)) >> 16); \
                                ((BYTE*)(ptr))[2] = (((ULONG)(val)) >> 8);  \
                                ((BYTE*)(ptr))[3] = (((ULONG)(val)) >> 0);  \
                            } while(0)
#define WRITE_ALIGN_SAFE16(ptr, val)                                        \
                            do {                                            \
                                ((BYTE*)(ptr))[0] = (((ULONG)(val)) >> 8);  \
                                ((BYTE*)(ptr))[1] = (((ULONG)(val)) >> 0);  \
                            } while(0)

#endif	/* _BYTE_ORDER==_BIG_ENDIAN */


/* data types */
typedef enum {
	H225Alg = 0,
	H245Alg
} H323AlgType;

typedef struct {
	IP_ADDRESS	ip_addr;
	USHORT		port;
} TRANSPORT_ADDR;

/* Function declaration */
static STATUS natRegisterAlg (			/* to register an H.323 ALG to NAT */
		NAT_ID_INFO *nat_id, 
		u_short port, 
		H323AlgType alg,
		NAT_AGENT_INFO *agent_info_p);

static void natAdjustChecksum(		/* adjust checksum for changes in H.323 payload data */
	BYTE		*data,
	TRANSPORT_ADDR	*new_transport,
	NAT_BIND_TYPE	nat_type,
	USHORT		*checksum);

/* static variables */
static u_long	logical_channel_bind[MAX_LOGICAL_CHANNELS];

/*****************************************************************************
Function:	natH245Packet

Description:
This function handles the H.245 call control packets.  NAT calls this function
after translating the address and port number in the IP and TCP headers, and 
when the source or destination port is the H.245 port. The H.245 port was 
negotiated during the H.225 call signaling session and registered to NAT.
The H.245 call control protocol is used in H.323 to negotiate call parameters 
between two end-points.  For example, it negotiates the UDP connections for 
the open logical channels for RTP and RTCP streams between the two endpoints.
In addition, it also negotiates the TCP connection for the T1.120 session. 

NOTE 1:
The H.245 message is ASN.1 encoded. However, due to resource and schedule 
constraint, rather than employing an ASN.1 decoder, this function uses a simple 
work-around alternative which appears to work just as well.  This work-around 
strategy looks for the ip+port address in the H.245 payload by taking advantage 
of the fact that the port number always follows immediately after the ip address.  
Since the ALG can get the expected ip address from NAT, it can search byte by 
byte for this ip address to locate where it is in the H.245 payload.

  Local host (L) <---------------> NAT <----------------> Global host (G)

The tuple of IP address and TCP/UDP port number is sometimes called transport
address in some publications, and the same terminology will be used here.

For an outbound packet, L may be sending its transport addresses to G to let
G make TCP/UDP connections to it.  Similarly, for an inbound packet, G may be
sending its transport addresses to L to let L make TCP/UDP connections to it.
Since only the L's transport addresses in the payload need to be translated,
it is sufficient to examine only the outbound packets.

NOTE 2: 
TCP sequence adjustment is not required since it is a binary substitution of
IP address and port number in the payload.  However, the checksum in the TCP
header must be adjusted when the TCP payload is modified.
*****************************************************************************/
BOOL natH245Packet(u_long nat_id, u_long agent_id, u_long session_id, 
	NAT_DIRECTION direction, void* packet)
{
	BYTE			*data, *data_start;
	TCP_PACKET		*tcp_packet;
	USHORT			port, *port_data;
	USHORT			checksum;
	IP_ADDRESS		local_address, ip_addr, *ip_data;
	NAT_ID_INFO		*nat_p;
	NAT_BIND_INFO	bind_info;
	NAT_BIND_SESSION    session;
	NAT_STATUS		status;
	int				i, data_length;
	TRANSPORT_ADDR	transport;

	if (direction == NAT_INBOUND)
	{
		return (TRUE);
	}

	if (nat_instance[0].id != nat_id)
	{
		nat_printf(NAT_PRINTF_ERROR, "natH225Packet: Invalid nat id\n");
		return(FALSE);
	}

	nat_p = &nat_instance[0];

	tcp_packet = (TCP_PACKET*)packet;

	/* length of TCP payload */
	data_length = (u_long) (tcp_packet->ip_header.total_length - 
				(tcp_packet->ip_header.version_header_length.header_length << 2) - 
				(tcp_packet->tcp_header.header_length_byte.header_length << 2));

	if (data_length <= 0)	/* no payload to look at */
	{
		return (TRUE);
	}

	/* go to start of TCP payload */
	data = (BYTE *)(&tcp_packet->tcp_header);
	data += (tcp_packet->tcp_header.header_length_byte.header_length << 2);
	data_start = data;

	/* From L's global transport address in TCP/IP header, locate the TCP bind entry
	   to obtain L's local transport address.
	*/
	session.protocol = IPPROTO_TCP;
	session.local_addr = 0;
	session.local_transport = 0;
	session.global_addr = ntohl(tcp_packet->ip_header.source_address);
	session.global_transport = ntohs(tcp_packet->tcp_header.source_port);
	session.remote_addr = ntohl(tcp_packet->ip_header.destination_address);
	session.remote_transport = ntohs(tcp_packet->tcp_header.destination_port);

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

		return(FALSE);
	}

	nat_printf(NAT_PRINTF_TRACE, "H245ALG: Bind entry match found\n");

	local_address = bind_info.local_addr;	/* L's local ip */

	/* search for L's ip address in the H.245 payload for all possible
	** TCP/UDP connections that may be negotiated.  For each one found, create
	** create a static TCP/UDP control block to get the translated transport address.
	** We must do this for all L's ip address found in the H.245 payload
	** since we are not decoding the ASN.1 message thus don't really know
	** which ones will actually be used.  A check is made to prevent creation
	** of duplicate bind entries.  The ID of each created static entry is recorded
	** so the ALG can delete them when the Netmeeting session is terminated.
	*/
	while ((data + IP_PORT_LENGTH) <= (data_start + data_length))
	{
		ip_addr = READ_ALIGN_SAFE32(data);
		ip_addr = ntohl (ip_addr);

		/* look for L's global address match */
		if (ip_addr == local_address)
		{				
            		port = READ_ALIGN_SAFE16(data + sizeof(IP_ADDRESS));
			port = ntohs (port);

			if (port > LOWER_EPHEMERAL_PORT_VALUE)
			{
				nat_printf(NAT_PRINTF_TRACE, "Local host address found in H245 payload\n");

				nat_printf(NAT_PRINTF_DATA, 
					"H245 ALG: Local host's ip match found, ip = %x, port = %x\n", ip_addr, port);

				/* if NAPT, create a UDP bind entry for this transport address if it hasn't
				   been created yet
				*/
				if (nat_p->type == NAT_TYPE_NAPT)
				{
					memset(&bind_info,0,sizeof(NAT_BIND_INFO));	/* reset bind_info */

					if (port == T1_120_PORT)
					{
						session.protocol = IPPROTO_TCP;
					}
					else
					{
						session.protocol = IPPROTO_UDP;
					}
					session.local_addr = local_address;
					session.local_transport = port;
					session.global_addr = 0;
					session.global_transport = 0;
					session.remote_addr = ntohl(tcp_packet->ip_header.destination_address);
					session.remote_transport = 0;
					
					if ((status = natGetTransportBind(nat_id, &session, 
						&bind_info, NAT_BIND_PARTIAL)) == NAT_BIND_NO_MATCH)				
					{
						memset(&bind_info,0,sizeof(NAT_BIND_INFO));
						bind_info.id = 0;	/* request to create a new bind */
						bind_info.agent_id = h323Alg[H245Alg].id;
						bind_info.type = NAT_BIND_NAPT;
						bind_info.direction = NAT_OUTBOUND;
						if (port == T1_120_PORT)
						{
							bind_info.protocol = IPPROTO_TCP;
						}
						else
						{
							bind_info.protocol = IPPROTO_UDP;
						}
						bind_info.static_entry = TRUE;
						bind_info.use_local_port = TRUE;
						bind_info.local_addr = local_address;
						bind_info.local_transport = port;
						bind_info.global_addr = ntohl(tcp_packet->ip_header.source_address);
						bind_info.global_transport = 0;
						bind_info.remote_addr = ntohl(tcp_packet->ip_header.destination_address);
						bind_info.remote_transport = 0;	/* destination port is still unknown now */
	
						status = natSetBind(nat_id, agent_id, &bind_info);
						if(status != NAT_OK)
						{
							nat_printf (NAT_PRINTF_ERROR, 
								"H245 ALG: Failed to create UDP bind, natSetBind returned %d\n",status);
							return (FALSE);
						}

						nat_printf(NAT_PRINTF_TRACE, "H245 ALG: New bind created\n");

						nat_printf(NAT_PRINTF_DATA, 
							"H245 ALG: A new bind created for la = %x, lp = %d, gp =%d\n",
							bind_info.local_addr, bind_info.local_transport, bind_info.global_transport);

						/* record the ID of the created bind */
						for (i=0; i<MAX_LOGICAL_CHANNELS; i++)
						{
							if (logical_channel_bind[i] == 0)
							{
								logical_channel_bind[i] = bind_info.id;
								break;
							}
						}
						if (i == MAX_LOGICAL_CHANNELS)
						{
							printf("Number of binds created by H.245 exceeds the limit\n");
						}
					}
					else
					{
						if (status != NAT_OK)
						{
							nat_printf(NAT_PRINTF_ERROR, 
								"natH245Packet: natGetTransportBind returns error\n");

							return (FALSE);
						}
					}
				}	/* NAPT */

				/********************************************************************
				   Replace L's local address with its global address in the payload.
				   Adjust the TCP checksum accordingly.
				*********************************************************************/
				
				ip_data = (IP_ADDRESS *) data;
				transport.ip_addr = htonl (bind_info.global_addr);
				port_data = (USHORT *) (data + sizeof(IP_ADDRESS));

⌨️ 快捷键说明

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