📄 natftpalg.c
字号:
/* natFtpAlg.c *//* Copyright 2000-2003 Wind River Systems, Inc. *//* @format.tab-size 4, @format.use-tabs true, @format.new-line lf *//* WindNet NAT "installable" FTP Application Level Gateway (ALG) *//*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 and table_free with calloc and free respectively092002 vvv fixed Diab warning102201 tk Fix code to find start of FTP payload to take into account the option field in the IP header.092101 tk Modify due to changes in the natGetTransportBind() format. Problem found due to NAT changes to work with mib. Also, bug fixes for multiple FTP clients session with local FTP server.071301 tk Redo entire implementation of ALG to use the upgraded version of NAT ALG API to interact with NAT. The new implementation is based on the assumption that the IP/TCP headers have been translated by NAT (i.e. post NAT translation). The TCP sequence adjustment code is now modularized in a separate subroutine.060701 tk Fix Linux FTP problem. Linux FTP uses the options field in the TCP header while the code always assumed the TCP header was always 20 bytes long (SPR#67124).051501 tk Fix handling of reply to PASV command (SPR#67123).030901 tk Fix synchronization problem with NAT initialization.*//*#define FTP_DEBUG*//* ANSI headers */#include <stdio.h> /* printf */#include <string.h> /* memset *//* VxWorks headers */#include <in.h> /* IPPROTO_TCP *//* NAT-specific headers */#include <nat/natAlgApi.h>#include "nat.h" /* IP_ADDRESS */#include "natFtpAlg.h"static const char* ftp_alg_desc = "WindNet NAT - FTP ALG v1.0 - Copyright 2000-2003 Wind River Systems, Inc.";static const char* ftp_alg_name = "FTP ALG";static NAT_ID_INFO nat_id;static NAT_AGENT_INFO agent_info;/*****************************************************************************************Function: natFtpPacketDescription: ******************************************************************************************/BOOL natFtpPacket(u_long nat_id, u_long agent_id, u_long session_id, NAT_DIRECTION direction, void* packet){ USHORT local_port_number; USHORT global_port_number; char *cptr_port_string; char *cptr_end_port_string; char *end_of_tcp_header; USHORT tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; IP_ADDRESS local_address; IP_ADDRESS global_address; BYTE *bptr_local_address; BYTE *bptr_global_address; char port_string[FTP_MAXIMUM_PORT_STRING_LENGTH]; /* also for PASV string */ ULONG new_port_string_length; ULONG old_port_string_length; TCP_TRANSLATION_ENTRY *sptr_tcp_translation_entry = NULL; int dummy_value; TCP_PACKET *sptr_tcp_packet; NAT_TRANSPORT transport; TCP_HEADER *tcp_start; if (direction != NAT_OUTBOUND) { return(TRUE); } sptr_tcp_packet = (TCP_PACKET*)packet; memset(&transport, 0, sizeof(NAT_TRANSPORT)); /* need to look for the port or pasv command. Then have to look for the IP address and the port address. Then must create a TCP control block and spoof the port number, and change the ip address, and do the sequence number setting. */ /* find the start of TCP payload */ cptr_port_string = (char *) (&sptr_tcp_packet->ip_header); cptr_port_string += (sptr_tcp_packet->ip_header.version_header_length.header_length << 2); tcp_start = (TCP_HEADER *) cptr_port_string; cptr_port_string += (tcp_start->header_length_byte.header_length << 2); end_of_tcp_header = cptr_port_string; /***************************************************/ /* PASV Section (for FTP servers "behind" the NAT) */ /***************************************************/ if (sscanf (cptr_port_string, FTP_PASV_PARAMETER_STRING, &dummy_value, &tmp1, &tmp2, &tmp3, &tmp4, &tmp5, &tmp6) == FTP_PASV_PARAMETER_COUNT) { nat_printf (NAT_PRINTF_TRACE, "FTP ALG: FTP Reply for PASV command\n"); sprintf (port_string, FTP_PASV_PARAMETER_STRING, FTP_PASV_RETURN_CODE, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6); nat_printf (NAT_PRINTF_TRACE, "FTP ALG: FTP old PASV string: %s\n", port_string); cptr_end_port_string = strchr (cptr_port_string, FTP_PASV_STRING_END_MARKER); if (cptr_end_port_string == NULL) { return(TRUE); /* incomplete PASV command, disregard */ } ++cptr_end_port_string; old_port_string_length = (ULONG) (cptr_end_port_string - cptr_port_string); /* tk: The global (remote) port is still unknown now, so just set it to 0. The remote port will be set to the right port number when the data connection is initiated by the local FTP client. */ global_port_number = 0x0000; local_port_number = (USHORT) (tmp5 * 0x100 + tmp6); bptr_local_address = (BYTE *) &local_address; bptr_local_address[3] = (BYTE) (tmp4 & 0x00FF); bptr_local_address[2] = (BYTE) (tmp3 & 0x00FF); bptr_local_address[1] = (BYTE) (tmp2 & 0x00FF); bptr_local_address[0] = (BYTE) (tmp1 & 0x00FF); local_address = ntohl (local_address); nat_printf (NAT_PRINTF_DATA, "FTP ALG: FTP PASV IP address: %x\n", local_address); if (nat.single_global_address_enabled == false) { /* basic NAT */ if (ftp_get_tcp_entry((ULONG)local_address, (char *) sptr_tcp_packet, &transport) != OK) { nat_printf(NAT_PRINTF_ERROR, "natFtpPacket: ftp_get_tcp_entry returns ERROR\n"); return (FALSE); } sptr_tcp_translation_entry = (TCP_TRANSLATION_ENTRY *) transport.tcp_block_ptr; } else { /* NAPT */ if (ftp_get_global_transport(local_address, local_port_number, (char *) sptr_tcp_packet, &transport) != OK) { nat_printf(NAT_PRINTF_ERROR, "natFtpPacket: ftp_get_tcp_entry returns ERROR\n"); return (FALSE); } sptr_tcp_translation_entry = (TCP_TRANSLATION_ENTRY *) transport.tcp_block_ptr; local_port_number = transport.global_port; tmp5 = (USHORT) (local_port_number/0x100); tmp6 = (USHORT) (local_port_number % 0x100); } global_address = transport.global_address; global_address = htonl (global_address); bptr_global_address = (BYTE *) &global_address; tmp4 = bptr_global_address[3]; tmp3 = bptr_global_address[2]; tmp2 = bptr_global_address[1]; tmp1 = bptr_global_address[0]; sprintf (port_string, FTP_PASV_PARAMETER_STRING, FTP_PASV_RETURN_CODE, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6); nat_printf (NAT_PRINTF_TRACE, "FTP ALG: FTP new PASV string: %s\n", port_string);#ifdef FTP_DEBUG printf ("FTP PASV IP address: 0x%lx\n", local_address); printf ("FTP PASV translated IP Address 0x%lx\n", ntohl(global_address)); printf ("FTP translated PASV string: %.*s\n", strlen(port_string)-2, port_string);#endif new_port_string_length = (ULONG) strlen (port_string); if (adjust_tcp_sequence( (char *)sptr_tcp_packet, cptr_port_string, port_string, old_port_string_length, new_port_string_length, (char *)sptr_tcp_translation_entry) == ERROR) { return (FALSE); } } /****************/ /* PORT Section */ /****************/ else { if (sscanf (cptr_port_string, FTP_PORT_PARAMETER_STRING, &tmp1, &tmp2, &tmp3, &tmp4, &tmp5, &tmp6) == FTP_PORT_PARAMETER_COUNT) { nat_printf (NAT_PRINTF_TRACE, "FTP ALG: FTP PORT command found\n"); cptr_end_port_string = strchr (cptr_port_string, FTP_PORT_STRING_END_MARKER); if (cptr_end_port_string == NULL) { nat_printf (NAT_PRINTF_ERROR, "natFtpPacket: Incomplete PORT command, disregard\n"); return(TRUE); /* incomplete PORT command, disregard */ } ++cptr_end_port_string; old_port_string_length = (ULONG) (cptr_end_port_string - cptr_port_string); nat_printf (NAT_PRINTF_TRACE, "FTP ALG: FTP PORT command: %.*s\n" ,old_port_string_length-2, cptr_port_string); /* tk: The global (remote) port is still unknown now, so just set it to 0. The remote port will be set to the right port number when the data connection is initiated by the remote FTP server. */ global_port_number = 0x0000; local_port_number = (USHORT) (tmp5 * 0x100 + tmp6); bptr_local_address = (BYTE *) &local_address; bptr_local_address[3] = (BYTE) (tmp4 & 0x00FF); bptr_local_address[2] = (BYTE) (tmp3 & 0x00FF); bptr_local_address[1] = (BYTE) (tmp2 & 0x00FF); bptr_local_address[0] = (BYTE) (tmp1 & 0x00FF); sprintf (port_string, FTP_PORT_PARAMETER_STRING, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6); nat_printf (NAT_PRINTF_DATA, "FTP ALG: FTP original PORT string: %.*s\n", strlen(port_string)-2, port_string); local_address = ntohl (local_address); if (nat.single_global_address_enabled == false) { /* basic NAT */ if (ftp_get_tcp_entry((ULONG)local_address, (char *) sptr_tcp_packet, &transport) != OK) { return (FALSE); } sptr_tcp_translation_entry = (TCP_TRANSLATION_ENTRY *) transport.tcp_block_ptr; } else { /* NAPT */ if (ftp_get_global_transport(local_address, local_port_number, (char *) sptr_tcp_packet, &transport) != OK) { return (FALSE); } sptr_tcp_translation_entry = (TCP_TRANSLATION_ENTRY *) transport.tcp_block_ptr; local_port_number = transport.global_port; tmp5 = (USHORT) (local_port_number/0x100); tmp6 = (USHORT) (local_port_number % 0x100); } global_address = transport.global_address; global_address = htonl (global_address); bptr_global_address = (BYTE *) &global_address; tmp4 = bptr_global_address[3]; tmp3 = bptr_global_address[2]; tmp2 = bptr_global_address[1]; tmp1 = bptr_global_address[0]; sprintf (port_string, FTP_PORT_PARAMETER_STRING, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6); nat_printf (NAT_PRINTF_TRACE, "FTP ALG: FTP translated PORT string: %.*s\n", strlen(port_string)-2, port_string);#ifdef FTP_DEBUG printf ("FTP PORT IP address: 0x%lx\n", local_address); printf ("FTP PORT translated IP Address 0x%lx\n", ntohl(global_address)); printf ("FTP translated PORT string: %.*s\n", strlen(port_string)-2, port_string);#endif new_port_string_length = (ULONG) strlen (port_string); if (adjust_tcp_sequence( /* adjust TCP sequence number */ (char *)sptr_tcp_packet, cptr_port_string, port_string, old_port_string_length, new_port_string_length, (char *)sptr_tcp_translation_entry) == ERROR) { return (FALSE); } } } return (TRUE);}/*****************************************************************************************Function: natFtpInitDescription: ******************************************************************************************/STATUS natFtpInit(u_short ftp_port){ STATUS status; semTake (natInitSync, WAIT_FOREVER); /* wait for event */ nat_printf(NAT_PRINTF_INIT, "FTP initialization: port = %u\n", ftp_port); memset(&nat_id, 0, sizeof(nat_id)); status = natGetID(&nat_id);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -