📄 nat_rx.c
字号:
/* nat_rx.c *//* Copyright 2000-2003 Wind River Systems, Inc. *//* @format.tab-size 4, @format.use-tabs true, @format.new-line lf *//*modification history--------------------01j,18jul03,vks changes for Virtual Stack01i,16jun03,myz Replace old fragment translation APIs with new ones.01h,09may03,myz reworked SPR6969801g,02may03,vks corrected header for natIpOutputFilterHook, removed #ifdef 0 code from it01f,01may03,zhu renamed SPR69698_PATCH to NAT_OUTPUT_FILTER01e,28apr03,myz fixed problem introduced in 01c version.01d,28apr03,myz removed org_src_addr, use the value in org_ip_header.01c,25apr03,myz Modified nat_rx function to improve the performance.01b,21apr03,myz replaced swap(_long) with the ntohs(l) and htons(l) macros.01a,15apr03,zhu replaced function call with direct access, fixed a bug in ALG fragments092402 vvv replaced rw_container lists with linked lists to improve performance092302 vvv used direct copy instead of memcpy to copy IP header to improve performance101901 tk Fix data type to avoid warning in T3 compiler.101601 tk Add a case for ICMP protocol in nat_get_src_transport().092801 tk Fix SPR69698: Added a special hook to handle icmp error generated by IP stack. This hook was not included in the NAT 1.1 FCS.071301 tk Add code to call the agent callback function for no-NAT translation.051501 tk Fix SPR67123: Global FTP client can't connect to local server when client issues PASV command. Add new function nat_get_src_transport() to check source port.042101 tk Fix ICMP redirect packet handling. Should be ignored by NAT per RFC1631.*//* ANSI headers */#include <string.h>/* RouterWare headers */ #include "nat.h"#include "net/mbuf.h"#include "netBufLib.h"#ifdef VIRTUAL_STACK#include "netinet/vsLib.h"#endif /* VIRTUAL_STACK *//* Local defines */#define IF_DEV_NAME_LEN 16/********************************************************************************************Static functions and variables********************************************************************************************/static enum TEST nat_handle_translation_for_global_rx (IP_PACKET*, enum NAT_PACKET_TYPES nat_packet_type);static enum TEST nat_handle_translation_for_local_rx (M_BLK*, enum NAT_PACKET_TYPES nat_packet_type);LOCAL void natTranslatedIpPacketConvert (M_BLK_ID, struct ifnet *,int);/********************************************************************************************Function declarations********************************************************************************************/extern NAT_AGENT_INFO *nat_find_agent( NAT_CLASS *nat_p, u_short protocol, u_long remote_port, u_long local_port );#ifndef VIRTUAL_STACKextern VOIDFUNCPTR _icmpErrorHook;#endif /* VIRTUAL_STACK */LOCAL VOIDFUNCPTR stdIcmpErrorHook = NULL;void natIcmpErrorHook (struct mbuf *, int, int, ULONG, struct ifnet *);/*******************************************************************************************/enum TEST nat_rx (USHORT port_number, M_BLK* pMblk) { enum NAT_PORT_TYPE nat_port_type; ULONG_ENUM (NAT_PACKET_TYPES) nat_packet_type; enum NAT_FILTER nat_filter_result; NAT_AGENT_INFO* agent_info; enum TEST return_code; u_long org_dst_addr; u_long org_src_addr; char addr_str[32]; IP_PACKET *sptr_ip_packet; NAT_DIRECTION direction; UINT16 srcTransport, dstTransport; void * pFragEntry; sptr_ip_packet = (IP_PACKET*) pMblk->mBlkHdr.mData; /* possible unaligned access if the offset value is not set properly in * the ethernet END driver */ org_dst_addr = sptr_ip_packet->header.destination_address; org_src_addr = sptr_ip_packet->header.source_address; nat_port_type = nat.port[port_number].type; /* local or global port */ /* do filter first (translate or not translate), so packets do not need * to be translated, such as local traffic, can get out this function ASAP. */ nat_filter_result = nat_filter_rx (ntohl(org_dst_addr), port_number, nat_port_type); if (nat_filter_result == NAT_DONT_TRANSLATE) { return (PASS); } else if (nat_filter_result == NAT_FILTER) { return (FAIL); } /* Now check ICMP redirect msg, Per RFC1631: NAT doesn't handle it */ nat_packet_type = nat_packet_discriminator (sptr_ip_packet); if (nat_packet_type == NAT_ICMP_REDIRECT) { return (PASS); } /* Handle fragmented IP datagram */ pFragEntry = NULL; if ( (sptr_ip_packet->header.fragment & IP_FRAGMENT_OFFSET_MASK) == 0) { if (sptr_ip_packet->header.fragment & IP_FRAGMENT_FLAG_MORE_FRAGMENTS) { /* first fragment, create fragment translation entry */ pFragEntry = (void *)natFragTranEntryGet (nat_port_type, sptr_ip_packet); if (pFragEntry == NULL) return (FAIL); } } else /* subsequent fragment */ { return_code = natFragAddrTranslate (nat_port_type, sptr_ip_packet); return (return_code); } if (nat_port_type == NAT_GLOBAL_PORT) { direction = NAT_INBOUND; } else /* local port */ { direction = NAT_OUTBOUND; } /* Do not translate OSPF or outbound RIP packets */ if ((nat_packet_type == NAT_OSPF) || ((nat_packet_type == NAT_RIP) && (direction == NAT_OUTBOUND))) { return (PASS); } /********************************************/ /* Search for installed ALG for this packet */ /********************************************/ if (sptr_ip_packet->header.protocol == IPPROTO_TCP) { srcTransport = ntohs( ((TCP_PACKET*) sptr_ip_packet)->tcp_header.source_port ); dstTransport = ntohs( ((TCP_PACKET*) sptr_ip_packet)->tcp_header.destination_port ); } else if(sptr_ip_packet->header.protocol == IPPROTO_UDP) { srcTransport = ntohs( ((UDP_PACKET*) sptr_ip_packet)->header.source_port ); dstTransport = ntohs( ((UDP_PACKET*) sptr_ip_packet)->header.destination_port ); } else { srcTransport = 0; dstTransport = 0; } agent_info = nat_find_agent(&nat, sptr_ip_packet->header.protocol, dstTransport, srcTransport); nat.agent_info = agent_info; /* ALG packet translations - PRE NAT */ if (agent_info != NULL && agent_info->flags & NAT_FLAG_PRE_XLAT && agent_info->packet_callback != NULL) { nat_printf (NAT_PRINTF_TRACE, "nat_rx: calling agent (%s) packet callback (pre-NAT)\n", agent_info->name); if (agent_info->packet_callback((u_long)&nat, agent_info->id, 0, /* session_id */ direction, sptr_ip_packet)==FALSE) { nat_printf(NAT_PRINTF_TRACE, "nat_rx: agent (%s) packet callback returned FALSE\n", agent_info->name); return(FAIL); } } /* NAT Built-in translations (TCP/UDP/ICMP) if no matching registered * agent or the registered agent processes only the payload */ if (agent_info == NULL || (agent_info->flags & NAT_FLAG_NO_XLAT)==0) { switch (nat_port_type) { case NAT_GLOBAL_PORT: return_code = nat_handle_translation_for_global_rx ( sptr_ip_packet, nat_packet_type); if (return_code == FAIL) return (FAIL); if (pFragEntry != NULL) { return_code = natFragTranAddrSave(NAT_GLOBAL_PORT, pFragEntry, sptr_ip_packet->header.destination_address); if (return_code == FAIL) return (FAIL); } break; case NAT_LOCAL_PORT: return_code = nat_handle_translation_for_local_rx (pMblk, nat_packet_type); if (return_code == FAIL) return (FAIL); if (pFragEntry != NULL) { return_code = natFragTranAddrSave(NAT_LOCAL_PORT,pFragEntry, sptr_ip_packet->header.source_address); if (return_code == FAIL) return (FAIL); } break; default: nat_printf (NAT_PRINTF_ERROR, "nat_rx: Unknown port type %d for port number %d\n", nat_port_type, port_number); return (FAIL); } } /* ALG packet translations - POST NAT */ if (agent_info != NULL && agent_info->flags & NAT_FLAG_POST_XLAT && agent_info->packet_callback != NULL) { nat_printf (NAT_PRINTF_TRACE, "nat_rx: calling agent (%s) packet callback (post-NAT)\n", agent_info->name); if (agent_info->packet_callback((u_long)&nat, agent_info->id, 0, direction, sptr_ip_packet)==FALSE) { nat_printf(NAT_PRINTF_TRACE, "nat_rx: agent (%s) packet callback returned FALSE\n", agent_info->name); return(FALSE); } } /* ALG translates entire packet */ if (agent_info != NULL && agent_info->flags & NAT_FLAG_NO_XLAT && agent_info->packet_callback != NULL) { nat_printf (NAT_PRINTF_TRACE, "nat_rx: calling agent (%s) packet callback (no-NAT)\n", agent_info->name); if (agent_info->packet_callback((u_long)&nat, agent_info->id, 0, direction, sptr_ip_packet)==FALSE) { nat_printf(NAT_PRINTF_TRACE, "nat_rx: agent (%s) packet callback returned FALSE\n", agent_info->name); return(FALSE); } /* If this is first fragment of larger packet, store the modified * address. */ if (pFragEntry != NULL) /* insert the new source address here */ { if (nat_port_type == NAT_GLOBAL_PORT) return_code = natFragTranAddrSave(NAT_GLOBAL_PORT,pFragEntry, sptr_ip_packet->header.destination_address); else return_code = natFragTranAddrSave(NAT_LOCAL_PORT,pFragEntry, sptr_ip_packet->header.source_address); if (return_code == FAIL) return (FAIL); } } if (nat.printing_enabled == true || nat.logging_enabled == true) { struct in_addr iaddr; iaddr.s_addr = org_src_addr; inet_ntoa_b(iaddr,addr_str); nat_printf (NAT_PRINTF_DATA, "nat_rx: original IP hdr source address: %s\n", addr_str); iaddr.s_addr = sptr_ip_packet->header.source_address; inet_ntoa_b(iaddr,addr_str); nat_printf (NAT_PRINTF_DATA, "nat_rx: translated IP hdr source address: %s\n", addr_str); iaddr.s_addr = org_dst_addr; inet_ntoa_b(iaddr,addr_str); nat_printf (NAT_PRINTF_DATA, "nat_rx: original IP hdr destination address: %s\n", addr_str); iaddr.s_addr = sptr_ip_packet->header.destination_address; inet_ntoa_b(iaddr,addr_str); nat_printf (NAT_PRINTF_DATA, "nat_rx: translated IP hdr destination address: %s\n", addr_str); } return (PASS); }/******************************************************************************************** This function handles translation of inbound packets (i.e. received from global port).********************************************************************************************/static enum TEST nat_handle_translation_for_global_rx (IP_PACKET* p_packet, enum NAT_PACKET_TYPES nat_packet_type){ enum TEST return_code; switch (nat_packet_type) { case NAT_TCP: return_code = handle_tcp_translation_global_rx ((TCP_PACKET*)p_packet); break; case NAT_ICMP_DATAGRAM: return_code = handle_icmp_translation_global_rx_datagram ((ICMP_PACKET*)p_packet); break; case NAT_ICMP_TRANSACTION:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -