📄 nat_udp.c
字号:
/* nat_udp.c *//* Copyright 2000-2003 Wind River Systems, Inc. *//* @format.tab-size 4, @format.use-tabs true, @format.new-line lf *//*modification history--------------------01b,24apr03,zhu updated copyright01a,21apr03,myz replaced swap(_long) with the ntohs(l) and htons(l) macros, replaced RWOS list functions with ones in dllLib.c040903 vks updated Copyright info040303 vks replaced table_malloc with calloc01a,25mar03,zhu UDP checksum of 0 is allowed. If 0, checksum must not be modified (RFC3022)101501 tk Fix bug. When no matches found for inbound UDP packet in NAPT, return(PASS) to pass the untranslated packet to the network stack.100301 tk Fix bug. Address (IP) static entry didn't work in NAPT.092401 tk Fix bug in handle_udp_translation_global_rx_nats() to create one or more dynamic binds from static entry so that the static bind can support multiple global clients to the same local server.080701 tk Add code in handle_udp_translation_local_rx_nats for handling H.323 protocol.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. 071101 tk Modified implementations to call natSetBind to create UDP control blocks so it will work with the upgraded version of ALG API.050401 tk Fix problem of multiple global clients being unable to connect to a local server simultaneously. Also, fix the indication of static or dynamic binds in the UDP control blocks (in the UDP translation list).042101 tk Fix bug. Semaphore (spoofingPortLock) lock problem. Add some comments. *//*#define UDP_DEBUG*/#include "nat.h"/************************************************************************/static enum TEST handle_udp_translation_global_rx_natg (UDP_PACKET *sptr_udp_packet);static enum TEST handle_udp_translation_global_rx_nats (UDP_PACKET *sptr_udp_packet);static enum TEST handle_udp_translation_local_rx_natg (UDP_PACKET *sptr_udp_packet);/***************************************************************************//******************************************************************************** This function handles inbound UDP packet translation.********************************************************************************/enum TEST handle_udp_translation_global_rx (UDP_PACKET *sptr_udp_packet){ enum TEST pass_or_fail; if (nat.single_global_address_enabled == TRUE) { pass_or_fail = handle_udp_translation_global_rx_nats (sptr_udp_packet); } else { pass_or_fail = handle_udp_translation_global_rx_natg (sptr_udp_packet); } return (pass_or_fail); }/******************************************************************************** This function handles outbound UDP packet translation.********************************************************************************/enum TEST handle_udp_translation_local_rx (UDP_PACKET *sptr_udp_packet){ enum TEST pass_or_fail; if (nat.single_global_address_enabled == TRUE) { pass_or_fail = handle_udp_translation_local_rx_nats (sptr_udp_packet); } else { pass_or_fail = handle_udp_translation_local_rx_natg (sptr_udp_packet); } return (pass_or_fail); }/***************************************************************************/static enum TEST handle_udp_translation_global_rx_natg (UDP_PACKET *sptr_udp_packet){ IP_ADDRESS destination_address; destination_address = sptr_udp_packet->ip_header.destination_address; if (handle_ip_translation_global_rx_natg ((IP_PACKET *) sptr_udp_packet) != NULL) { if (sptr_udp_packet->header.checksum != 0) { checksum_fixup ((BYTE *) &sptr_udp_packet->header.checksum, (BYTE *) &destination_address, sizeof (IP_ADDRESS), (BYTE *) &sptr_udp_packet->ip_header.destination_address, sizeof (IP_ADDRESS)); } return (PASS); } else { return (FAIL); } }/**************************************************************************************************Description: This function handles translation of UDP packets received from global port in NAPT mode. - First, see if there is a match of the spoofed port. - If yes and this is not a static entry (see NOTE below), go ahead and translate. - If no or static entry, check for a match of the tuple of local address & port and global port in the UDP translation list. - If no match is found, check if the destination port can be found in the static port table. - Do the address and port translation on the packet before giving it to the higher layer.NOTE: If static entry is true, it implies the session was started inbound. It is not enough that the spoofed port match is found since the spoofed port is the global port assigned from the static table. Hence, the spoofed port may not be uniquely mapped to a single session when multiple inbound sessions take place to the same local server.**************************************************************************************************/static enum TEST handle_udp_translation_global_rx_nats (UDP_PACKET *sptr_udp_packet){ UDP_TRANSLATION_ENTRY *sptr_udp_translation_entry; USHORT local_port_number; IP_ADDRESS address; USHORT checksum; NAT_PORT_STATIC_ENTRY *sptr_udp_static_entry; NAT_BIND_INFO bind_info, *bind_id; NAT_STATUS status; /* if destination address is different from global address, handle as basic NAT */ if (ntohl(sptr_udp_packet->ip_header.destination_address) != nat.global_address) { if (handle_udp_translation_global_rx_natg (sptr_udp_packet) == PASS) { return (PASS); } else { return (PASS); /* pass to network stack untranslated */ } } sptr_udp_translation_entry = match_spoofed_port_with_udp_entry (ntohs (sptr_udp_packet->header.destination_port), &nat.nats.udp_translation_list, FALSE); if (sptr_udp_translation_entry == NULL) { sptr_udp_translation_entry = match_ports_with_udp_entry_inbound ( ntohs (sptr_udp_packet->header.source_port), ntohs (sptr_udp_packet->header.destination_port), ntohl (sptr_udp_packet->ip_header.source_address), &nat.nats.udp_translation_list); if (sptr_udp_translation_entry == NULL) { sptr_udp_static_entry = match_udp_port_with_static_entry (ntohs (sptr_udp_packet->header.destination_port)); if (sptr_udp_static_entry != NULL) { memset(&bind_info,0,sizeof(bind_info)); bind_info.type = NAT_BIND_NAPT; bind_info.direction = NAT_INBOUND; bind_info.protocol = IPPROTO_UDP; bind_info.static_entry = FALSE; bind_info.global_transport = sptr_udp_static_entry->global_port_number; /* source and destination transport addresses must be in host format */ bind_info.local_addr = sptr_udp_static_entry->local_address; bind_info.local_transport = sptr_udp_static_entry->local_port_number; bind_info.remote_addr = ntohl (sptr_udp_packet->ip_header.source_address); bind_info.remote_transport = ntohs (sptr_udp_packet->header.source_port); status = natSetBind((u_long)&nat, 0, &bind_info); if(status != NAT_OK) { nat_printf (NAT_PRINTF_ERROR, "handle_udp_translation_global_rx_nats: natSetBind returned %d\n",status); return(FAIL); } sptr_udp_translation_entry = (UDP_TRANSLATION_ENTRY *) bind_info.nat_transport_entry; sptr_udp_translation_entry->spoofed_local_port = bind_info.global_transport; sptr_udp_translation_entry->local_address = sptr_udp_static_entry->local_address; sptr_udp_translation_entry->dynamicFromStatic = TRUE; } } /* if no match in port static entries, process as basic NAT to see if a match of address static entries can be found. This extra check is done in case an IP static address == NAPT global address exists. */ if (sptr_udp_translation_entry == NULL) { if (handle_udp_translation_global_rx_natg (sptr_udp_packet) == PASS) { nat_printf(NAT_PRINTF_TRACE, "UDP packet successfully translated in Basic NAT\n"); return (PASS); } else { nat_printf(NAT_PRINTF_TRACE, "UDP packet passed untranslated to network stack\n"); return (PASS); } } } bind_id = (NAT_BIND_INFO *) sptr_udp_translation_entry->bind_id; sptr_udp_translation_entry->remote_port = ntohs (sptr_udp_packet->header.source_port); sptr_udp_translation_entry->remote_address = ntohl (sptr_udp_packet->ip_header.source_address); bind_id->remote_addr = sptr_udp_translation_entry->remote_address; bind_id->remote_transport = sptr_udp_translation_entry->remote_port; if (sptr_udp_translation_entry->spoofed_local_port != 0x0000) { local_port_number = htons (sptr_udp_translation_entry->local_port); checksum = sptr_udp_packet->header.checksum; if (checksum != 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -