📄 nat_tcp.c
字号:
/* nat_tcp.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) and htons(l) macros, replaced RWOS list functions with ones in dllLib.c.01a,15apr03,zhu check tcp reset flag040903 vks updated Copyright info 040303 vks replaced table_malloc call with calloc101501 tk Fix bug. When no matches found for inbound TCP 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_tcp_translation_global_rx_nats() to create one or more dynamic binds from a static entry so that the static bind can support multiple global clients to the same local server.082301 tk Assign remote address to the translation entry and bind entry upon receiving TCP packet from global port in NAPT mode.080701 tk Add code in handle_tcp_translation_local_rx_nats for handling H.323 protocol.072601 tk Fix call to match_ports_with_tcp_entry to use match_ports_with_tcp_entry_inbound and match_ports_with_tcp_entry_outbound instead.070201 tk Modified implementations to call natSetBind to create TCP control blocks so it will work with the upgraded version of ALG API.051401 tk Fix natShow for basic NAT. Local address is displayed as global address.051101 tk Fix NAPT so it can also work with static address-based translations.051001 tk Fix TCP state transition problem. TCP local or/and global state may be in the wrong state. One known effect of this is TCP control block might not get freed 12 hours after the TCP connection was closed. Problem was due to failure to do swap_long on the sequence numbers when comparing current and previous sequence numbers to determine whether it needs to do state transition.050401 tk Fix problem of multiple global servers being unable to connect to a local server simultaneously. Also, fix the indication of static or dynamic binds in the TCP control blocks (in the TCP translation list).042101 tk Add some comments*//*#define TCP_DEBUG*/#include "nat.h"/**************************************************************************************************/static enum TEST handle_tcp_translation_global_rx_natg (TCP_PACKET *sptr_tcp_packet);static enum TEST handle_tcp_translation_global_rx_nats (TCP_PACKET *sptr_tcp_packet);static void do_tcp_sequence_number_fixup (enum NAT_TCP_DELTA_SIGN delta_sign, ULONG *ulptr_packet_sequence_number, USHORT *usptr_checksum, SEQUENCE_HEADER *sptr_sequence_list);/**************************************************************************************************/enum TEST handle_tcp_translation_global_rx (TCP_PACKET *sptr_tcp_packet){ enum TEST pass_or_fail; if (nat.single_global_address_enabled == TRUE) { pass_or_fail = handle_tcp_translation_global_rx_nats (sptr_tcp_packet); } else { pass_or_fail = handle_tcp_translation_global_rx_natg (sptr_tcp_packet); } return (pass_or_fail); }/*************************************************************************************************/enum TEST handle_tcp_translation_local_rx (TCP_PACKET *sptr_tcp_packet){ enum TEST pass_or_fail; if (nat.single_global_address_enabled == TRUE) { pass_or_fail = handle_tcp_translation_local_rx_nats (sptr_tcp_packet); } else { pass_or_fail = handle_tcp_translation_local_rx_natg (sptr_tcp_packet); } return (pass_or_fail);}/******************************************************************************************** Description: handle_ip_translation_local_rx_natg() replaces the source IP with IP from global address pool. It also creates a new entry in the IP translation list. new_tcp_translation_entry() creates a new entry in the TCP translation list.********************************************************************************************/enum TEST handle_tcp_translation_local_rx_natg (TCP_PACKET *sptr_tcp_packet){ TCP_TRANSLATION_ENTRY *sptr_tcp_translation_entry; IP_TRANSLATION_ENTRY *sptr_working_ip_translation_entry; BYTE_ENUM (BOOLEAN) do_state_transition; IP_ADDRESS source_address; NAT_BIND_INFO bind_info; NAT_STATUS status; source_address = sptr_tcp_packet->ip_header.source_address; sptr_working_ip_translation_entry = handle_ip_translation_local_rx_natg ((IP_PACKET *) sptr_tcp_packet); if (sptr_working_ip_translation_entry == NULL) { return (FAIL); } checksum_fixup ((BYTE *) &sptr_tcp_packet->tcp_header.checksum, (BYTE *) &source_address, sizeof (source_address), (BYTE *) &sptr_tcp_packet->ip_header.source_address, sizeof (source_address)); sptr_tcp_translation_entry = match_ports_with_tcp_entry_outbound ( ntohs (sptr_tcp_packet->tcp_header.destination_port), ntohs (sptr_tcp_packet->tcp_header.source_port), ntohl (source_address), &sptr_working_ip_translation_entry->tcp_translation_list); if (sptr_tcp_translation_entry == NULL) { if (sptr_tcp_packet->tcp_header.flags.synchronize_flag == TRUE) { memset(&bind_info,0,sizeof(bind_info)); bind_info.agent_id = 0; /* agent is NAT */ bind_info.type = NAT_BIND_BASIC; bind_info.direction = NAT_OUTBOUND; bind_info.protocol = IPPROTO_TCP; bind_info.static_entry = FALSE; /* convert source and destination transport addresses to host format */ bind_info.local_addr = ntohl(source_address); bind_info.local_transport = ntohs(sptr_tcp_packet->tcp_header.source_port); bind_info.remote_addr = ntohl(sptr_tcp_packet->ip_header.destination_address); bind_info.remote_transport = ntohs(sptr_tcp_packet->tcp_header.destination_port); /* save the current IP translation entry */ bind_info.nat_address_entry = (u_long) sptr_working_ip_translation_entry; status = natSetBind((u_long)&nat, 0, &bind_info); if(status != NAT_OK) { nat_printf (NAT_PRINTF_ERROR, "handle_tcp_translation_local_rx_natg: natSetBind returned %d\n",status); return(FAIL); } sptr_tcp_translation_entry = (TCP_TRANSLATION_ENTRY *) bind_info.nat_transport_entry; } else { return (FAIL); } } tcp_sequence_number_fixup_local_rx (&sptr_tcp_packet->tcp_header, sptr_tcp_translation_entry); if (ntohl(sptr_tcp_packet->tcp_header.sequence_number) >= ntohl(sptr_tcp_translation_entry->local_sequence_number)) { do_state_transition = TRUE; } else if(sptr_tcp_packet->tcp_header.flags.reset_flag == TRUE) { do_state_transition = TRUE; } else { do_state_transition = FALSE; } sptr_tcp_translation_entry->local_sequence_number = sptr_tcp_packet->tcp_header.sequence_number; if (do_state_transition == TRUE) { if (sptr_tcp_packet->tcp_header.flags.acknowledgment_flag == TRUE) { tcp_state_transistion_local_rx (NAT_ACK, sptr_tcp_translation_entry); } if (sptr_tcp_packet->tcp_header.flags.synchronize_flag == TRUE) { tcp_state_transistion_local_rx (NAT_SYNCH, sptr_tcp_translation_entry); } if (sptr_tcp_packet->tcp_header.flags.finished_flag == TRUE) { tcp_state_transistion_local_rx (NAT_FIN, sptr_tcp_translation_entry); } if (sptr_tcp_packet->tcp_header.flags.reset_flag == TRUE) { tcp_state_transistion_local_rx (NAT_RESET, sptr_tcp_translation_entry); } if ((sptr_tcp_packet->tcp_header.flags.acknowledgment_flag == FALSE) && (sptr_tcp_packet->tcp_header.flags.synchronize_flag == FALSE) && (sptr_tcp_packet->tcp_header.flags.reset_flag == FALSE) && (sptr_tcp_packet->tcp_header.flags.finished_flag == FALSE)) { tcp_state_transistion_local_rx (NAT_ESTABLISHED, sptr_tcp_translation_entry); } } return (PASS);}/************************************************************************************************** Description: Check if there is a match for destination address in IP translation list. If not, return. Else, replace destination IP with local IP and adjust checksum. Check for match in the TCP translation list. If not, create an entry in the TCP translation list.**************************************************************************************************/static enum TEST handle_tcp_translation_global_rx_natg (TCP_PACKET *sptr_tcp_packet){ IP_TRANSLATION_ENTRY *sptr_ip_translation_entry; bool do_state_transition; TCP_TRANSLATION_ENTRY *sptr_tcp_translation_entry; IP_ADDRESS destination_address; NAT_BIND_INFO bind_info; NAT_STATUS status; destination_address = sptr_tcp_packet->ip_header.destination_address; sptr_ip_translation_entry = handle_ip_translation_global_rx_natg ((IP_PACKET *) sptr_tcp_packet); if (sptr_ip_translation_entry == NULL) { return (PASS); /* changed so that packets meant for upper layers can be passed to IP */ } checksum_fixup ((BYTE *) &sptr_tcp_packet->tcp_header.checksum, (BYTE *) &destination_address, sizeof (destination_address), (BYTE *) &sptr_tcp_packet->ip_header.destination_address, sizeof (destination_address)); sptr_tcp_translation_entry = match_ports_with_tcp_entry_inbound ( ntohs (sptr_tcp_packet->tcp_header.source_port), ntohs (sptr_tcp_packet->tcp_header.destination_port), ntohl (sptr_tcp_packet->ip_header.source_address), &sptr_ip_translation_entry->tcp_translation_list); if (sptr_tcp_translation_entry == NULL) { if (sptr_tcp_packet->tcp_header.flags.synchronize_flag == TRUE) { memset(&bind_info,0,sizeof(bind_info)); bind_info.agent_id = 0; /* agent is NAT */ bind_info.type = NAT_BIND_BASIC; bind_info.direction = NAT_INBOUND; bind_info.protocol = IPPROTO_TCP; bind_info.static_entry = FALSE; /* convert source and destination transport addresses to host format */ bind_info.local_addr = ntohl(sptr_tcp_packet->ip_header.destination_address); bind_info.local_transport = ntohs(sptr_tcp_packet->tcp_header.destination_port); bind_info.remote_addr = ntohl(sptr_tcp_packet->ip_header.source_address); bind_info.remote_transport = ntohs(sptr_tcp_packet->tcp_header.source_port); /* save the current IP translation entry */ bind_info.nat_address_entry = (u_long) sptr_ip_translation_entry; status = natSetBind((u_long)&nat, 0, &bind_info); if(status != NAT_OK) { nat_printf (NAT_PRINTF_ERROR, "handle_tcp_translation_global_rx_natg: natSetBind returned %d\n",status); return(FAIL); } sptr_tcp_translation_entry = (TCP_TRANSLATION_ENTRY *) bind_info.nat_transport_entry; } else { return (FAIL); } } tcp_sequence_number_fixup_global_rx (&sptr_tcp_packet->tcp_header, sptr_tcp_translation_entry); if (ntohl(sptr_tcp_packet->tcp_header.sequence_number) >= ntohl(sptr_tcp_translation_entry->global_sequence_number)) { do_state_transition = TRUE; } else if (sptr_tcp_packet->tcp_header.flags.reset_flag == TRUE) { do_state_transition = TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -