📄 nat_util.c
字号:
/* nat_util.c *//* Copyright 2000-2003 Wind River Systems, Inc. *//* @format.tab-size 4, @format.use-tabs true, @format.new-line lf *//*modification history--------------------01c,24apr03,zhu updated copyright01b,21apr03,myz replaced swap(_long) with the ntohs(l) macros, replaced RWOS list functions with ones in dllLib.c.01a,15apr03,zhu fix for deleting static port mapping040903 vks updated Copyright info040303 vks replaced table_malloc with calloc110802 zhu fixed a bug for basic NAT tcp translation entry comparison092302 vvv unconditionally include fix for SPR #65740120601 tk Fix SPR72007: Inbound session to non-standard port failed.112601 tk Fix SPR65740: ARP problem with Basic-NAT.101901 tk Fix data type to avoid warning in T3 compiler.100301 tk Provide semaphore locks on match functions to access respective. translation lists to prevent race condition with the NAT Timer task. Add match_sa_with_static_entry() function to match address in IP static entry table.092401 tk Fix bug. Changed match_spoofed_port_with_tcp_entry() and match_spoofed_port_with_udp_entry() to return entry pointer found only for static entry created by ALG or dynamic entry created by session started outbound.. 082301 tk Add registerStaticEntryToTranslationList() to enter static TCP/UDP entry to translation list and bind list.080701 tk Add match_ports_with_udp_entry_global() and match_ports_with_tcp_entry_global() for H.323 handling.072601 tk Fix bug. Remove match_ports_with_tcp_entry() and create 2 functions: match_ports_with_tcp_entry_inbound() and match_ports_with_tcp_entry_outbound() to look for matching TCP entry for inbound and outbound TCP packet. Similarly, Remove match_ports_with_udp_entry() and create 2 functions: match_ports_with_udp_entry_inbound() and match_ports_with_udp_entry_outbound() to look for matching UDP entry for inbound and outbound UDP packet.071001 tk Create a new function create_static_ip_entry() for creating a new static IP entry in the IP translation list.060401 tk Fix the logic in new_ip_translation_entry if called in NAPT mode. No new IP entry should be created in NAPT mode, so just return NULL. Fix in match_sa_with_global_address() to return NULL if static entry match found but the static entry is disabled. This fixes SPR#67129: Disabling static entry doesn't disable IP static mapping immediately.050701 tk Update nat_packet_discriminator to handle ICMP time_exceeded message as a datagram rather than a transaction.042101 tk Update nat_packet_discriminator to handle ICMP redirect message as a unique type as NAT should not translate it per RFC# 1631. *//*#define CS_DEBUG*/#include <string.h>#include <stdio.h>#include "nat.h"#include <arpLib.h>/************************************************************************************/enum NAT_PORT_TYPE get_nat_port_type (USHORT port_number){ enum NAT_PORT_TYPE nat_port_type; if (nat.port[port_number].type == NAT_GLOBAL_PORT) { nat_port_type = NAT_GLOBAL_PORT; } else { nat_port_type = NAT_LOCAL_PORT; } return (nat_port_type);}/*****************************************************************************************Function: match_sa_with_global_addressDescription:This function looks for a global address match in the IP translation list.*****************************************************************************************/IP_TRANSLATION_ENTRY *match_sa_with_global_address (IP_ADDRESS global_address, IP_TRANSLATION_HEADER *sptr_ip_translation_list){ IP_TRANSLATION_ENTRY *sptr_ip_translation_entry; semTake(ipListLock, WAIT_FOREVER); for (sptr_ip_translation_entry = (IP_TRANSLATION_ENTRY *) DLL_FIRST ((DL_LIST *) sptr_ip_translation_list); sptr_ip_translation_entry != NULL; sptr_ip_translation_entry = (IP_TRANSLATION_ENTRY *) DLL_NEXT ((DL_NODE *) sptr_ip_translation_entry)) { if (global_address == sptr_ip_translation_entry->sa_global_address) { if (sptr_ip_translation_entry->static_entry == true && nat.static_entries_enabled == false) { nat_printf (NAT_PRINTF_DATA, "matched_sa_with_global_address: static address 0x%lx disabled\n", global_address); semGive (ipListLock); return (NULL); } nat_printf (NAT_PRINTF_TRACE, "Found match for global address %x in IP list\n", global_address); semGive (ipListLock); return (sptr_ip_translation_entry); } } nat_printf (NAT_PRINTF_TRACE, "No match for global address %x in IP list\n", global_address); semGive (ipListLock); return (NULL);}/*****************************************************************************************Function:Description:This function looks for a local address match in the IP translation list.*****************************************************************************************/IP_TRANSLATION_ENTRY *match_sa_with_local_address (IP_ADDRESS source_address, IP_TRANSLATION_HEADER *sptr_ip_translation_list){ IP_TRANSLATION_ENTRY *sptr_ip_translation_entry; semTake(ipListLock, WAIT_FOREVER); for (sptr_ip_translation_entry = (IP_TRANSLATION_ENTRY *) DLL_FIRST ((DL_LIST *) sptr_ip_translation_list); sptr_ip_translation_entry != NULL; sptr_ip_translation_entry = (IP_TRANSLATION_ENTRY *) DLL_NEXT ((DL_NODE *) sptr_ip_translation_entry)) { if (source_address == sptr_ip_translation_entry->sa_local_address) { nat_printf (NAT_PRINTF_TRACE, "Found match for local address %x in IP list\n", source_address); semGive (ipListLock); return (sptr_ip_translation_entry); } } nat_printf (NAT_PRINTF_TRACE, "No match for local address %x in IP list\n", source_address); semGive (ipListLock); return (NULL);}/************************************************************************/ULONG_ENUM (NAT_PACKET_TYPES) nat_packet_discriminator (IP_PACKET *sptr_ip_packet){ ICMP_PACKET *sptr_icmp_packet; UDP_PACKET *sptr_udp_packet; switch (sptr_ip_packet->header.protocol) { case ICMP_PROTOCOL: sptr_icmp_packet = (ICMP_PACKET *) sptr_ip_packet; if ((sptr_icmp_packet->header.type == ICMP_ECHO_REPLY_TYPE) || (sptr_icmp_packet->header.type == ICMP_ECHO_REQUEST_TYPE) || (sptr_icmp_packet->header.type == ICMP_TIMESTAMP_TYPE) || (sptr_icmp_packet->header.type == ICMP_TIMESTAMP_REPLY_TYPE) || (sptr_icmp_packet->header.type == ICMP_ADDRESS_MASK_TYPE) || (sptr_icmp_packet->header.type == ICMP_ADDR_MASK_REPLY_TYPE)) { return (NAT_ICMP_TRANSACTION); } else /* tk - per RFC 1631: NAT doesn't handle ICMP Redirect message */ if (sptr_icmp_packet->header.type == ICMP_REDIRECT_TYPE) { return (NAT_ICMP_REDIRECT); } else { return (NAT_ICMP_DATAGRAM); } case TCP_PROTOCOL: return (NAT_TCP); case UDP_PROTOCOL: sptr_udp_packet = (UDP_PACKET *) sptr_ip_packet; if (ntohs (sptr_udp_packet->header.destination_port) == RIP_PORT) { return (NAT_RIP); } return (NAT_UDP); case OSPF_PROTOCOL: return (NAT_OSPF); default: return (NAT_UNKNOWN_PROTOCOL); }}/*****************************************************************************Function: match_ports_with_tcp_entry_outboundDescription:Look for TCP entry with matching local address, local port, and remote port.This check is made for outbound packets.*****************************************************************************/TCP_TRANSLATION_ENTRY *match_ports_with_tcp_entry_outbound ( USHORT remote_port, USHORT local_port, IP_ADDRESS local_address, TCP_TRANSLATION_HEADER *sptr_tcp_translation_list){ TCP_TRANSLATION_ENTRY *sptr_tcp_translation_entry; semTake (tcpListLock, WAIT_FOREVER); for (sptr_tcp_translation_entry = (TCP_TRANSLATION_ENTRY *) DLL_FIRST ((DL_LIST *) sptr_tcp_translation_list); sptr_tcp_translation_entry != NULL; sptr_tcp_translation_entry = (TCP_TRANSLATION_ENTRY *) DLL_NEXT ((DL_NODE *) sptr_tcp_translation_entry)) { if ((sptr_tcp_translation_entry->local_port == local_port) && (sptr_tcp_translation_entry->remote_port == remote_port) && (sptr_tcp_translation_entry->local_address == local_address)) { nat_printf (NAT_PRINTF_TRACE, "Found match for local_addr/port = %08lx:%d, remote port = %d in TCP list\n", local_address, local_port, remote_port); semGive (tcpListLock); return (sptr_tcp_translation_entry); } } semGive (tcpListLock); nat_printf (NAT_PRINTF_TRACE, "No match for local_addr/port = %08lx:%d, remote port=%d in TCP list\n", local_address, local_port, remote_port); return (NULL);}/*****************************************************************************Function: match_ports_with_tcp_entry_inboundDescription:Look for TCP entry with matching local port, remote address and remote port.This check is made for inbound packets.*****************************************************************************/TCP_TRANSLATION_ENTRY *match_ports_with_tcp_entry_inbound ( USHORT remote_port, USHORT global_port, IP_ADDRESS remote_address, TCP_TRANSLATION_HEADER *sptr_tcp_translation_list){ TCP_TRANSLATION_ENTRY *sptr_tcp_translation_entry; semTake (tcpListLock, WAIT_FOREVER); for (sptr_tcp_translation_entry = (TCP_TRANSLATION_ENTRY *) DLL_FIRST ((DL_LIST *) sptr_tcp_translation_list); sptr_tcp_translation_entry != NULL; sptr_tcp_translation_entry = (TCP_TRANSLATION_ENTRY *) DLL_NEXT ((DL_NODE *) sptr_tcp_translation_entry)) { if (nat.single_global_address_enabled == FALSE) { if ((sptr_tcp_translation_entry->local_port == global_port) && (sptr_tcp_translation_entry->remote_port == remote_port) && (sptr_tcp_translation_entry->remote_address == remote_address)) { nat_printf (NAT_PRINTF_TRACE, "Found match for remote addr/port = %08lx:%d, global port=%d in TCP list\n", remote_address, remote_port, global_port); semGive (tcpListLock); return (sptr_tcp_translation_entry); } } else { if ((sptr_tcp_translation_entry->spoofed_local_port == global_port) && (sptr_tcp_translation_entry->remote_port == remote_port) && (sptr_tcp_translation_entry->remote_address == remote_address)) { nat_printf (NAT_PRINTF_TRACE, "Found match for remote addr/port = %08lx:%d, global port=%d in TCP list\n", remote_address, remote_port, global_port); semGive (tcpListLock); return (sptr_tcp_translation_entry); } } } semGive (tcpListLock); nat_printf (NAT_PRINTF_TRACE, "No match for remote addr/port = %08lx:%d, global port=%d in TCP list\n", remote_address, remote_port, global_port); return (NULL);}/*****************************************************************************Function: match_ports_with_tcp_entry_globalDescription:Look for TCP entry with matching local address, local port, and global portthat has the same value as its local port. This matching routine may berequired by some protocols (e.g. H.323).This check is made for outbound packets.*****************************************************************************/TCP_TRANSLATION_ENTRY *match_ports_with_tcp_entry_global ( USHORT local_port, IP_ADDRESS local_address, TCP_TRANSLATION_HEADER *sptr_tcp_translation_list){ TCP_TRANSLATION_ENTRY *sptr_tcp_translation_entry; semTake (tcpListLock, WAIT_FOREVER); for (sptr_tcp_translation_entry = (TCP_TRANSLATION_ENTRY *) DLL_FIRST ((DL_LIST *) sptr_tcp_translation_list); sptr_tcp_translation_entry != NULL; sptr_tcp_translation_entry = (TCP_TRANSLATION_ENTRY *) DLL_NEXT ((DL_NODE *) sptr_tcp_translation_entry)) { if ((sptr_tcp_translation_entry->local_port == local_port) && (sptr_tcp_translation_entry->spoofed_local_port == local_port) && (sptr_tcp_translation_entry->local_address == local_address)) { nat_printf (NAT_PRINTF_TRACE, "Found match for local address/port = %08lx:%d, global port=%d in TCP list\n", local_address, local_port, local_port); semGive (tcpListLock); return (sptr_tcp_translation_entry); } } nat_printf (NAT_PRINTF_TRACE, "No match for local address/port = %08lx:%d, global port=%d in TCP list\n", local_address, local_port, local_port); semGive (tcpListLock); return (NULL);}/*****************************************************************************Function: match_spoofed_port_with_tcp_entryDescription:Look for TCP entry with matching spoofed port. There can be up to four typesof TCP entries in the TCP translation list:1. Dummy static entries created from static table.2. Real static entries created by external agent (e.g. ALG)3. Dynamic entries created from a static entry. In this case, the spoofed port may not be unique.4. Dynamic entries created by outbound session. Here, the spoofed port is unique.Return the entry pointer only if either the matching spoofed port belongs toan entry of type 2 or 4 mentioned above.*****************************************************************************/TCP_TRANSLATION_ENTRY *match_spoofed_port_with_tcp_entry ( USHORT spoofed_port, TCP_TRANSLATION_HEADER *sptr_tcp_translation_list, BOOL findDummyStatic){ TCP_TRANSLATION_ENTRY *sptr_tcp_translation_entry; NAT_BIND_INFO *bind_id; semTake (tcpListLock, WAIT_FOREVER); for (sptr_tcp_translation_entry = (TCP_TRANSLATION_ENTRY *) DLL_FIRST ((DL_LIST *) sptr_tcp_translation_list); sptr_tcp_translation_entry != NULL; sptr_tcp_translation_entry = (TCP_TRANSLATION_ENTRY *) DLL_NEXT ((DL_NODE *) sptr_tcp_translation_entry)) { /* If looking for dummy static entry (to delete), skip dynamic entries. */ if(findDummyStatic && (sptr_tcp_translation_entry->static_entry == FALSE) ) continue; if (sptr_tcp_translation_entry->spoofed_local_port == spoofed_port) { nat_printf (NAT_PRINTF_TRACE, "Found match for spoofed port %d in TCP list\n", spoofed_port); if (sptr_tcp_translation_entry->static_entry == TRUE) { bind_id = (NAT_BIND_INFO *) sptr_tcp_translation_entry->bind_id; if (bind_id->agent_id == 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -