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

📄 nath323alg.c

📁 VXWORKS NAT 部分源代码3 有兴趣朋友可以参考下
💻 C
📖 第 1 页 / 共 3 页
字号:
				checksum = tcp_packet->tcp_header.checksum;
				if (nat_p->type == NAT_TYPE_NAPT)
				{
					transport.port = htons (bind_info.global_transport);
					natAdjustChecksum((BYTE *)ip_data, &transport, NAT_BIND_NAPT, &checksum);
				}
				else
				{
					transport.port = READ_ALIGN_SAFE16(port_data);
					natAdjustChecksum((BYTE *)ip_data, &transport, NAT_BIND_BASIC, &checksum);
				}

				tcp_packet->tcp_header.checksum = checksum;
                		WRITE_ALIGN_SAFE32(ip_data, transport.ip_addr);
                		WRITE_ALIGN_SAFE16(port_data, transport.port);
						
				data += IP_PORT_LENGTH;
			}
			else	/* detected port number is not a valid ephemeral port value */
			{				
				nat_printf(NAT_PRINTF_DATA, "H245 ALG: detected port invalid, ignore! port = %d\n", port);

				data++;
			}
		}
		else	/* ip_addr != local_address */
		{
			data++;
		}
	}	/* end while loop */

	return (TRUE);
}

/*****************************************************************************
Function:	natH225Packet

Description:
This function handles the H.225/Q.931 call signalling 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.323 port
registered to NAT during the H.323 ALG registration (the standard port for 
H.323 protocol is 1720).  The H.225 call signalling protocol is used in H.323 
to establish connection between two end-points.

This function must look at both an outbound as well as an inbound packet.
H.323 connection can be attempted from local to global endpoint or vice
versa.

NOTE 1:
The fields in the H.225 message are ASN.1 encoded. However, due to schedule,
constraint, rather than employing an ASN.1 decoder, this function uses a simple 
strategy to look for the ip+port address in the H.225 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.225 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.

Case 1:  Local (L) endpoint to global (G) endpoint connection

L starts a TCP connection to G and the H.225 call signaling session starts.
The establishment of this TCP connection is all handled by NAT, so by now,
NAT should have the bind entry for this connection.  During the H.225 session,
L will embed its sourceCallSignalAddress (ip/port) and G's transport address
in the H.225 payload to G.  Thus, this function must parse for each H.225 
outbound packet, look for L's transport address, and substitute it with the 
translated address obtained from NAT.

In addition, this function must also observe the H.225 inbound packets from G
to look for the H.245 transport address (ip/port) in the connect message from 
G.  The port number provided by G here will serve as the H.245 port number.
L will use this port number to open the H.245 TCP connection with G.  So upon 
obtaining the H.245 port number, this function must also register the H.245 
ALG agent to NAT . 

Case 2:  Global (G) endpoint to local (L) endpoint connection

G starts a TCP connection to L via the NAT's H.323 static entry and the H.225
call signaling session starts.  As in case 1, the establishment of this TCP 
connection is all handled by NAT, so by now, NAT should have the bind entry 
for this connection.  During the H.225 session, G will embed its sourceCall-
SignalAddress and L's global transport address in the H.225 payload.  So, this
function must examine all inbound H.225 packets and substitute L's global 
transport address with its real transport address.

In addition, this function must also observe the H.225 outbound packets
to look for L's H.245 transport address which is embedded in the connect 
message from L to G. The port number embedded in this message will serve as 
the H.245 port number.

G will use this port number to open the H.245 TCP connection with L.  So, this
function must also register the H.245 ALG agent to NAT upon obtaining the
H.245 port number.  Furthermore, since the H.245 TCP connection will be
started from G to L, this function must create a new TCP bind entry for the 
impending H.245 port connection.

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 natH225Packet(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;
	IP_ADDRESS		local_port, local_address, ip_addr, *ip_data;
	USHORT			checksum;
	NAT_ID_INFO		*nat_p;
	NAT_BIND_INFO	bind_info;
	NAT_BIND_SESSION    session;
	NAT_STATUS		status;
	int				data_length;
	NAT_DIRECTION	session_direction;
	TRANSPORT_ADDR	transport;

	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;

	if (direction == NAT_OUTBOUND)	/* outbound packet */
	{
		/* get the H.225 TCP bind descriptor using L's translated source transport 
		   address from the source address in the TCP/IP header.  From the bind 
		   descriptor, obtain L's real transport address and the session flow (i.e. 
		   who starts the connection first) of this connection.
		*/
		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, 
				"H225 ALG (outbound): 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);
		}

		local_address = bind_info.local_addr;
		local_port = bind_info.local_transport;
		session_direction = bind_info.direction;
		
		if (session_direction == NAT_OUTBOUND)		/* session started by L */
		{
			nat_printf(NAT_PRINTF_TRACE, 
				"H225 ALG: outbound packet, outbound session. Look for sourceCallSignalAddress from local host.\n");

			while ((data + IP_PORT_LENGTH) <= (data_start + data_length))
			{
                		ip_addr = READ_ALIGN_SAFE32(data);
				ip_addr = ntohl (ip_addr);
				
				/* look for L's sourceCallSignalAddress match */
				if (ip_addr == bind_info.local_addr)
				{				
                    			port = READ_ALIGN_SAFE16(data + sizeof (IP_ADDRESS));
					port = ntohs (port);

					if (port == bind_info.local_transport)
					{	/* replace with L's translated sourceCallSignalAdress */
						nat_printf(NAT_PRINTF_TRACE, 
							"H225 ALG: Replace local address and port in H225 payload\n");
						nat_printf(NAT_PRINTF_DATA, 
							"H225 ALG: Original local address = %x, port = %d\n", 
							ip_addr, port);

						ip_data = (IP_ADDRESS *) data;
						transport.ip_addr = htonl (bind_info.global_addr);
						port_data = (USHORT *) (data + sizeof(IP_ADDRESS));
						checksum = tcp_packet->tcp_header.checksum;
						if (nat_p->type == NAT_TYPE_NAPT)
						{
							transport.port = htons (bind_info.global_transport);
							natAdjustChecksum((BYTE *)ip_data, &transport, NAT_BIND_NAPT, &checksum);
						}
						else
						{
							transport.port = READ_ALIGN_SAFE16(port_data);
							natAdjustChecksum((BYTE *)ip_data, &transport, NAT_BIND_BASIC, &checksum);
						}

						tcp_packet->tcp_header.checksum = checksum;
                        			WRITE_ALIGN_SAFE32(ip_data, transport.ip_addr);
                        			WRITE_ALIGN_SAFE16(port_data, transport.port);
						
						data += IP_PORT_LENGTH;

						nat_printf(NAT_PRINTF_DATA, 
							"H225 ALG: Translated local address = %x, port = %d\n", 
							ntohl(READ_ALIGN_SAFE32(ip_data)), ntohs(READ_ALIGN_SAFE16(port_data)));
					}
					else	/* port != bind_info.local_transport */
					{
						data++;

						nat_printf(NAT_PRINTF_TRACE, 
							"H225 ALG: Matched local address found, but not the port number\n");
					}
				}
				else	/* ip_addr != bind_info.local_addr */
				{
					data++;
				}
			}
		}
		else	/* session started by G */
		{
			nat_printf(NAT_PRINTF_TRACE, 
				"H225 ALG: outbound packet, inbound session. Look for H245Address from local host.\n");

			while ((data + IP_PORT_LENGTH) <= (data_start + data_length))
			{
                		ip_addr = READ_ALIGN_SAFE32(data);
				ip_addr = ntohl (ip_addr);

				/* look for L's H245Address port */
				if (ip_addr == bind_info.local_addr)
				{				
                    			port = READ_ALIGN_SAFE16(data + sizeof (IP_ADDRESS));
					port = ntohs (port);

					nat_printf(NAT_PRINTF_TRACE, "H225 ALG: Found H245Address in H225 payload\n");
					nat_printf(NAT_PRINTF_DATA, 
						"H225 ALG: Local original H245Address is: ip = %x, port = %x\n", ip_addr, port);

					/* register H.245 ALG to NAT */
					if (natRegisterAlg (nat_p, port, H245Alg, &h323Alg[H245Alg]) != OK)
					{
						nat_printf(NAT_PRINTF_ERROR, 
							"natH225Packet: Failed to register H245 ALG with local H.245 port\n");
						return (FALSE);
					}

					nat_printf(NAT_PRINTF_TRACE, "H225 ALG: H245 ALG is registered with NAT\n");
		
					/* if NAPT, create a H.245 TCP bind entry to prepare for H.245
					   connection request from G
					*/
					if (nat_p->type == NAT_TYPE_NAPT)
					{ 
						memset(&bind_info,0,sizeof(bind_info));
						bind_info.id = 0;	/* request to create a new bind */
						bind_info.agent_id = h323Alg[H225Alg].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 = 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, 
								"natH225Packet: Failed to create bind, natSetBind returned %d\n",status);
							return (ERROR);
						}
						nat_printf(NAT_PRINTF_TRACE, "H225 ALG: H.245 TCP bind successfully created\n");
					}	/* NAPT */

					/* replace L's local address with its global address in the payload */
					ip_data = (IP_ADDRESS *) data;
					transport.ip_addr = htonl (bind_info.global_addr);
					port_data = (USHORT *) (data + sizeof(IP_ADDRESS));
					checksum = tcp_packet->tcp_header.checksum;
					if (nat_p->type == NAT_TYPE_NAPT)
					{
						transport.port = htons (bind_info.global_transport);
						natAdjustChecksum((BYTE *)ip_data, &transport, NAT_BIND_NAPT, &checksum);
					}
					else
					{
						transport.port = READ_ALIGN_SAFE16(port_data);
						natAdjustChecksum((BYTE *)ip_data, &transport, NAT_BIND_BASIC, &checksum);
					}

					tcp_packet->tcp_header.checksum = checksum;
                    			WRITE_ALIGN_SAFE32(ip_data, transport.ip_addr);
                    			WRITE_ALIGN_SAFE16(port_data, transport.port);
						
					data += IP_PORT_LENGTH;

					nat_printf(NAT_PRINTF_DATA, "H225 ALG: Translated local H245Address is: ip = %x, port = %x\n", 
							ntohl(READ_ALIGN_SAFE32(ip_data)), ntohs(READ_ALIGN_SAFE16(port_data)));
					nat_printf(NAT_PRINTF_TRACE, "H225 ALG: H245Address successfully translated in the payload\n");
				}
				else	/* ip_addr != bind_info.local_addr */
				{
					data++;
				}	
			}/* while */	
		}	/* else: session started by G */	
	}	/* if: direction == NAT_OUTBOUND */	
	else	/* inbound packet */
	{
		/* get the H.225 TCP bind descriptor using L's real transport address
		   from the destination address in the TCP/IP header (post-NAT translation).
		   From the bind descriptor, obtain G's transport address and the session 
		   flow (i.e. who starts the connection first) of this connection.
		*/
		session.protocol = IPPROTO_TCP;
		session.local_addr = ntohl(tcp_packet->ip_header.destination_address);
		session.local_transport = ntohs(tcp_packet->tcp_header.destination_port);
		session.global_addr = 0;
		session.global_transport = 0;
		session.remote_addr = ntohl(tcp_packet->ip_header.source_address);
		session.remote_transport = ntohs(tcp_packet->tcp_header.source_port);

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

			return(FALSE);
		}

		session_direction = bind_info.direction;

		if (session_direction == NAT_OUTBOUND)		/* session started by L */
		{
			nat_printf(NAT_PRINTF_TRACE, 
				"H225 ALG: inbound packet, outbound session. Look for H245Address from remote host.\n");
			
			while ((data + IP_PORT_LENGTH) <= (data_start + data_length))
			{

⌨️ 快捷键说明

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