📄 natftpalg.c
字号:
if (status != NAT_OK) { nat_printf(NAT_PRINTF_ERROR, "natFtpInit: natGetID failed with error %d\n", status); return(status); } memset(&agent_info, 0, sizeof(agent_info)); agent_info.type = NAT_AGENT_TYPE_ALG; agent_info.flags = NAT_FLAG_POST_XLAT; agent_info.session_tag.protocol = IPPROTO_TCP; agent_info.session_tag.transport = ftp_port; agent_info.packet_callback = natFtpPacket; sprintf(agent_info.desc, "%.*s", (int)(sizeof(agent_info.desc)-1), ftp_alg_desc); sprintf(agent_info.name, "%.*s", (int)(sizeof(agent_info.name)-1), ftp_alg_name); status = natRegisterAgent(nat_id.id, &agent_info); if (status != NAT_OK) { nat_printf (NAT_PRINTF_ERROR, "natFtpInit: natRegisterAgent failed with error %d\n", status); return(status); } printf ("FTP ALG registered with NAT\n"); semGive(natInitSync); return(OK);}/*****************************************************************************************Function: ftp_get_tcp_entryDescription: Since the FTP ALG is in post NAT translation, by now the IP header already contains the translated source address (we call it global address as opposed to local address). Thus, the address translation must already exist in the NAT IP translation list. This function calls the API function natGetAddrBind to find the translation entry in the IP translation list, then use that entry to find the TCP entry spawned off the IP translation (which is how TCP connection is handled internally by NAT when it operates in basic NAT mode). This TCP entry will be needed later by natFtpPacket for TCP sequence adjustment.******************************************************************************************/STATUS ftp_get_tcp_entry( ULONG local_address, char *packet, NAT_TRANSPORT *transport){ NAT_BIND_INFO bind_info; NAT_BIND_SESSION session; NAT_STATUS status; TCP_PACKET *sptr_tcp_packet; sptr_tcp_packet = (TCP_PACKET *) packet; /* sanity check to ensure that the bind descriptor for the IP translation already exists */ if ((status = natGetAddrBind((u_long)&nat, (u_long)local_address, ntohl(sptr_tcp_packet->ip_header.source_address), &bind_info)) != NAT_OK) { nat_printf (NAT_PRINTF_ERROR, "ftp_get_tcp_entry: Status = %d, Bind of local address %x to global address %x not found\n", status, local_address, ntohl(sptr_tcp_packet->ip_header.source_address)); return (ERROR); } /* call natGetTransportBind to get the pointer to the TCP translation entry */ session.protocol = IPPROTO_TCP; session.local_addr = local_address; session.local_transport = ntohs(sptr_tcp_packet->tcp_header.source_port);; session.global_addr = ntohl(sptr_tcp_packet->ip_header.source_address); session.global_transport = ntohs(sptr_tcp_packet->tcp_header.source_port); session.remote_addr = ntohl(sptr_tcp_packet->ip_header.destination_address); session.remote_transport = ntohs(sptr_tcp_packet->tcp_header.destination_port); if ((status = natGetTransportBind((u_long)&nat, &session, &bind_info, NAT_BIND_FULL)) != NAT_OK) { nat_printf (NAT_PRINTF_ERROR, "ftp_get_tcp_entry: Status = %d, Transport Bind of address %x port %d not found\n", status, ntohl(sptr_tcp_packet->ip_header.source_address), ntohs(sptr_tcp_packet->tcp_header.source_port)); return(ERROR); } /* need this for TCP sequence adjustment later */ transport->tcp_block_ptr = (char *) bind_info.nat_transport_entry; transport->global_address = bind_info.global_addr; return (OK);}/************************************************************************************Function: ftp_get_global_transportDescription: Since the FTP ALG is in post NAT translation, by now the TCP connection has been established between FTP client and server. The source address/port in IP/TCP header has been translated. This function calls natGetTransportBind to get the TCP control block entry in the TCP translation list. This entry will be needed later by natFtpPacket for TCP sequence adjustment. Furthermore, this function creates a new TCP control block using the address/port pair from the FTP PORT or PASV parameters by calling the API function natSetBind in preparation of the upcoming data connection. This must be done by the ALG in NAPT mode to get the translated port number (i.e. global port number) so the natFtpPacket can put it in the FTP payload to replace the original port number for the establishment of the data connection.************************************************************************************/STATUS ftp_get_global_transport( ULONG local_address, USHORT local_port, char *packet, NAT_TRANSPORT *transport){ NAT_BIND_INFO bind_info; NAT_BIND_SESSION session; NAT_STATUS status; TCP_PACKET *sptr_tcp_packet; sptr_tcp_packet = (TCP_PACKET *) packet; /* check to make sure the FTP control bind exists */ session.protocol = IPPROTO_TCP; session.local_addr = local_address; session.local_transport = local_port; session.global_addr = ntohl(sptr_tcp_packet->ip_header.source_address); session.global_transport = ntohs(sptr_tcp_packet->tcp_header.source_port); session.remote_addr = ntohl(sptr_tcp_packet->ip_header.destination_address); session.remote_transport = ntohs(sptr_tcp_packet->tcp_header.destination_port); if ((status = natGetTransportBind((u_long)&nat, &session, &bind_info, NAT_BIND_FULL)) != NAT_OK) { nat_printf (NAT_PRINTF_ERROR, "ftp_get_global_transport: Status = %d, Transport Bind of address %x port %d not found\n", status, ntohl(sptr_tcp_packet->ip_header.source_address), ntohs(sptr_tcp_packet->tcp_header.source_port)); return(ERROR); } /* need this for TCP sequence adjustment later */ transport->tcp_block_ptr = (char *) bind_info.nat_transport_entry; /* create a new bind for FTP data connection (note that the data packet hasn't been received yet) */ memset(&bind_info,0,sizeof(bind_info)); bind_info.id = 0; /* request to create a new bind */ bind_info.agent_id = agent_info.id; bind_info.type = NAT_BIND_NAPT; bind_info.direction = NAT_OUTBOUND; bind_info.protocol = IPPROTO_TCP; bind_info.static_entry = FALSE; bind_info.local_addr = (u_long)local_address; bind_info.local_transport = local_port; bind_info.global_addr = ntohl(sptr_tcp_packet->ip_header.source_address); bind_info.global_transport = 0; bind_info.remote_addr = ntohl(sptr_tcp_packet->ip_header.destination_address); bind_info.remote_transport = 0; /* destination port is still unknown here */ status = natSetBind((u_long)&nat, agent_info.id, &bind_info); if(status != NAT_OK) { nat_printf (NAT_PRINTF_ERROR, "ftp_get_global_transport: natSetBind returned %d\n",status); return (ERROR); } transport->global_address = bind_info.global_addr; transport->global_port = bind_info.global_transport; return (OK);}/************************************************************************************Function: adjust_tcp_sequenceDescription: Adjust TCP sequence number and recompute the TCP checksum.************************************************************************************/STATUS adjust_tcp_sequence ( char *tcp_packet, char *old_string, char *new_string, ULONG old_string_length, ULONG new_string_length, char *tcp_entry ){ TCP_TRANSLATION_ENTRY *sptr_tcp_translation_entry; TCP_PACKET *sptr_tcp_packet; int sequence_number_delta; ULONG end_of_packet_length; ULONG data_length; USHORT total_length; USHORT tcp_length, new_tcp_length; char *end_old_string; char *end_of_tcp_header; long result; SEQUENCE_ENTRY *sptr_sequence_entry = NULL; SEQUENCE_ENTRY *sptr_old_sequence_entry = NULL; BYTE *bptr_end_of_packet_buffer = NULL; sptr_tcp_packet = (TCP_PACKET *) tcp_packet; sptr_tcp_translation_entry = (TCP_TRANSLATION_ENTRY *) tcp_entry; /* find the start of TCP payload */ end_of_tcp_header = (char *) (&sptr_tcp_packet->tcp_header); end_of_tcp_header += (sptr_tcp_packet->tcp_header.header_length_byte.header_length << 2); end_old_string = (char *)(old_string + old_string_length); end_of_packet_length = 0x00000000L; tcp_length = (USHORT) (sptr_tcp_packet->ip_header.total_length - (sptr_tcp_packet->ip_header.version_header_length.header_length << 2)); data_length = (ULONG) (sptr_tcp_packet->ip_header.total_length - (sptr_tcp_packet->ip_header.version_header_length.header_length << 2) - (sptr_tcp_packet->tcp_header.header_length_byte.header_length << 2)); sequence_number_delta = (int) (new_string_length - old_string_length); if (sequence_number_delta != 0x0000) { end_of_packet_length = (ULONG) (data_length - (end_old_string - end_of_tcp_header)); if (end_of_packet_length != 0x00000000L) { bptr_end_of_packet_buffer = (BYTE *) malloc (end_of_packet_length); if (bptr_end_of_packet_buffer == NULL) return (ERROR); } if (sptr_sequence_entry == NULL) { sptr_sequence_entry = (SEQUENCE_ENTRY *) calloc (1, sizeof (SEQUENCE_ENTRY)); if (sptr_sequence_entry == NULL) { if (bptr_end_of_packet_buffer != NULL) { free (bptr_end_of_packet_buffer); } return (ERROR); } sptr_sequence_entry->link.sptr_forward_link = NULL; sptr_sequence_entry->link.sptr_backward_link = NULL; sptr_sequence_entry->sequence_number_base_adjust = 0x00000000L; sptr_sequence_entry->sequence_number_base = ntohl (sptr_tcp_packet->tcp_header.sequence_number); sptr_sequence_entry->sequence_number_delta = sequence_number_delta; } else { sptr_sequence_entry->sequence_number_delta = sptr_sequence_entry->sequence_number_delta + sequence_number_delta; } total_length = (USHORT) (sptr_tcp_packet->ip_header.total_length + sequence_number_delta); sptr_tcp_packet->ip_header.total_length = total_length; /* host order */ if (end_of_packet_length != 0x00000000L) { memcpy (bptr_end_of_packet_buffer, end_old_string, end_of_packet_length); } } checksum_fixup ((BYTE *) &sptr_tcp_packet->tcp_header.checksum, (BYTE *) old_string, (USHORT) old_string_length, (BYTE *) new_string, (USHORT) new_string_length); memcpy (old_string, new_string, new_string_length); if (sequence_number_delta != 0x0000) { end_old_string = old_string + new_string_length; if (end_of_packet_length != 0x00000000L) { memcpy (end_old_string, bptr_end_of_packet_buffer, end_of_packet_length); free (bptr_end_of_packet_buffer); } } new_tcp_length = (USHORT) (tcp_length + sequence_number_delta); new_tcp_length = htons (new_tcp_length); tcp_length = htons (tcp_length); checksum_fixup ((BYTE *) &sptr_tcp_packet->tcp_header.checksum, (BYTE *) &tcp_length, sizeof (USHORT), (BYTE *) &new_tcp_length, sizeof (USHORT)); sptr_old_sequence_entry = NULL; if (sptr_sequence_entry != NULL) { sptr_sequence_entry->timer_enabled = FALSE; sptr_sequence_entry->entry_timer = nat.sequence_entry_timer; sptr_old_sequence_entry = (SEQUENCE_ENTRY *) DLL_FIRST ( (DL_LIST *) &sptr_tcp_translation_entry->local_sequence_delta_list); if (sptr_old_sequence_entry != NULL) { result = sptr_sequence_entry->sequence_number_base - sptr_old_sequence_entry->sequence_number_base; if (result > 0x00000000L) { sptr_sequence_entry->sequence_number_base_adjust = sptr_old_sequence_entry->sequence_number_delta + sptr_old_sequence_entry->sequence_number_base_adjust; sptr_old_sequence_entry->timer_enabled = TRUE; } else { free (sptr_sequence_entry); sptr_sequence_entry = NULL; } } if (sptr_sequence_entry != NULL) { dllInsert ((DL_LIST *) &sptr_tcp_translation_entry->local_sequence_delta_list, NULL, (DL_NODE *) sptr_sequence_entry); } } return(OK);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -