📄 nat_tcp.c
字号:
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_tcp_translation_global_rx_nats (TCP_PACKET *sptr_tcp_packet)
{
NAT_CURRENCY_TRANSLATION_ENTRY *sptr_tcp_translation_entry=NULL;
USHORT checksum;
IP_ADDRESS address;
USHORT local_port_number;
bool do_state_transition=FALSE;
NAT_PORT_STATIC_ENTRY *sptr_port_static_entry=NULL;
unsigned long out_porthash;
NAT_BIND_INFO bind_info, *bind_id=NULL;
NAT_STATUS status;
/* if destination address is different from global address, handle as basic NAT */
if (ntohl(sptr_tcp_packet->ip_header.destination_address) != nat.global_address)
{
if (handle_tcp_translation_global_rx_natg (sptr_tcp_packet) == PASS)
{
return (PASS);
}
else
{
return (PASS); /* pass to network stack untranslated */
}
}
semTake(natentrylock, WAIT_FOREVER);
if(!sptr_tcp_translation_entry)
sptr_tcp_translation_entry = match_ports_with_tcp_entry_inbound (sptr_tcp_packet);
if (sptr_tcp_translation_entry == NULL)
{
if (sptr_tcp_packet->tcp_header.flags.synchronize_flag == TRUE)
{
semGive(natentrylock);
sptr_port_static_entry = match_tcp_port_with_static_entry (ntohs (sptr_tcp_packet->tcp_header.destination_port));
if (sptr_port_static_entry != NULL)
{
memset(&bind_info,0,sizeof(bind_info));
bind_info.agent_id = 0; /* agent is NAT */
bind_info.type = NAT_BIND_NAPT;
bind_info.direction = NAT_INBOUND;
bind_info.protocol = IPPROTO_TCP;
bind_info.static_entry = FALSE;
bind_info.global_transport = sptr_port_static_entry->global_port_number;
/* source and destination transport addresses must be in host format */
bind_info.local_addr = sptr_port_static_entry->local_address;
bind_info.local_transport = sptr_port_static_entry->local_port_number;
bind_info.remote_addr = ntohl (sptr_tcp_packet->ip_header.source_address);
bind_info.remote_transport = ntohs(sptr_tcp_packet->tcp_header.source_port);
status = natSetBind((u_long)&nat, 0, &bind_info);
if(status != NAT_OK)
{
nat_printf (NAT_PRINTF_ERROR,
"handle_tcp_translation_global_rx_nats: natSetBind returned %d\n",status);
return(FAIL);
}
semTake(natentrylock, WAIT_FOREVER);
sptr_tcp_translation_entry = (NAT_CURRENCY_TRANSLATION_ENTRY *) bind_info.nat_transport_entry;
if(natDeleteOut_port_Link(sptr_tcp_translation_entry)==OK)
{
out_porthash=bind_info.global_transport&(UPPER_EPHEMERAL_PORT_VALUE-1);
sptr_tcp_translation_entry->next_entrys_link=out_port_map[out_porthash].next_entrys_link;
out_port_map[out_porthash].next_entrys_link=sptr_tcp_translation_entry;
}
sptr_tcp_translation_entry->spoofed_local_port = bind_info.global_transport;
sptr_tcp_translation_entry->local_address = sptr_port_static_entry->local_address;
sptr_tcp_translation_entry->dynamicFromStatic = TRUE;
}
else
{
return (FAIL);
}
}
/* 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_tcp_translation_entry == NULL)
{
if (handle_tcp_translation_global_rx_natg (sptr_tcp_packet) == PASS)
{
semGive(natentrylock);
nat_printf(NAT_PRINTF_TRACE, "TCP packet successfully translated in Basic NAT\n");
return (PASS);
}
else
{
semGive(natentrylock);
nat_printf(NAT_PRINTF_TRACE, "TCP packet passed untranslated to network stack\n");
return (PASS);
}
}
}
if((sptr_tcp_packet->tcp_header.flags.reset_flag)||
(sptr_tcp_packet->tcp_header.flags.finished_flag))
{
sptr_tcp_translation_entry->nat_aging_state = NAT_FIN_STATE;
}
else if(sptr_tcp_translation_entry->nat_aging_state == NAT_SYNCH_STATE)
{
sptr_tcp_translation_entry->nat_aging_state = NAT_ESTABLISHED_STATE;
}
if(sptr_tcp_translation_entry->nat_aging_state == NAT_SYNCH_STATE)
sptr_tcp_translation_entry->currenty_translation_entry_timer = NAT_TCP_CONNECTING_TIMER;
else if(sptr_tcp_translation_entry->nat_aging_state == NAT_ESTABLISHED_STATE)
sptr_tcp_translation_entry->currenty_translation_entry_timer = NAT_TCP_CONNECTED_TIMER;
else if(sptr_tcp_translation_entry->nat_aging_state ==NAT_FIN_STATE)
sptr_tcp_translation_entry->currenty_translation_entry_timer = NAT_TCP_CLOSING_TIMER;
else
sptr_tcp_translation_entry->currenty_translation_entry_timer = NAT_TCP_CONNECTED_TIMER;
if(!sptr_tcp_translation_entry->remote_port)
sptr_tcp_translation_entry->remote_port = ntohs (sptr_tcp_packet->tcp_header.source_port);
/*
if(!sptr_tcp_translation_entry->remote_address)
{
printf("sptr_tcp_translation_entry\n");
printf("sptr_tcp_translation_entry unmark %d",natUnmark_in_map(sptr_tcp_translation_entry));
sptr_tcp_translation_entry->remote_address = ntohl (sptr_tcp_packet->ip_header.source_address);
natMark_in_map(sptr_tcp_translation_entry);
}
*/
/* set the remote port and address in the bind entry */
bind_id = (NAT_BIND_INFO *) sptr_tcp_translation_entry->bind_id;
bind_id->remote_transport = sptr_tcp_translation_entry->remote_port;
bind_id->remote_addr = sptr_tcp_translation_entry->remote_address;
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;
}
else
{
do_state_transition = FALSE;
}
sptr_tcp_translation_entry->global_sequence_number = sptr_tcp_packet->tcp_header.sequence_number;
*/
local_port_number = htons (sptr_tcp_translation_entry->local_port);
checksum = sptr_tcp_packet->tcp_header.checksum;
checksum_fixup ((BYTE *) &checksum,
(BYTE *) &sptr_tcp_packet->tcp_header.destination_port, sizeof (USHORT),
(BYTE *) &local_port_number, sizeof (USHORT));
sptr_tcp_packet->tcp_header.destination_port = local_port_number;
sptr_tcp_packet->tcp_header.checksum = checksum;
address = htonl (sptr_tcp_translation_entry->local_address);
checksum_fixup ((BYTE *) &sptr_tcp_packet->tcp_header.checksum,
(BYTE *) &sptr_tcp_packet->ip_header.destination_address, sizeof (IP_ADDRESS),
(BYTE *) &address, sizeof (IP_ADDRESS));
checksum = sptr_tcp_packet->ip_header.header_checksum;
checksum_fixup ((BYTE *) &checksum,
(BYTE *) &sptr_tcp_packet->ip_header.destination_address, sizeof (IP_ADDRESS),
(BYTE *) &address, sizeof (IP_ADDRESS));
sptr_tcp_packet->ip_header.destination_address = address;
sptr_tcp_packet->ip_header.header_checksum = checksum;
/*Added at 2005-12-20 by Flyhorse*/
if(_func_packetsend!=NULL) /*PPPOE is running*/
{
if((sptr_tcp_packet->tcp_header.flags.synchronize_flag == TRUE)&&
(sptr_tcp_packet->tcp_header.header_length_byte.header_length>5)&&
(sptr_tcp_packet->options_or_data.tcp_options.kind==2))
{
USHORT pppoeTcpMss=htons(1452);
checksum = sptr_tcp_packet->tcp_header.checksum;
checksum_fixup((BYTE *)&checksum,(BYTE *) &sptr_tcp_packet->options_or_data.tcp_options.maximum_segment_size,
sizeof(USHORT),(BYTE *) &pppoeTcpMss,sizeof(USHORT));
sptr_tcp_packet->options_or_data.tcp_options.maximum_segment_size=pppoeTcpMss;
sptr_tcp_packet->tcp_header.checksum=checksum;
}
}
if (do_state_transition == TRUE)
{
if (sptr_tcp_packet->tcp_header.flags.acknowledgment_flag == TRUE)
{
tcp_state_transistion_global_rx (NAT_ACK, sptr_tcp_translation_entry);
}
if (sptr_tcp_packet->tcp_header.flags.synchronize_flag == TRUE)
{
tcp_state_transistion_global_rx (NAT_SYNCH, sptr_tcp_translation_entry);
}
if (sptr_tcp_packet->tcp_header.flags.finished_flag == TRUE)
{
tcp_state_transistion_global_rx (NAT_FIN, sptr_tcp_translation_entry);
}
if (sptr_tcp_packet->tcp_header.flags.reset_flag == TRUE)
{
tcp_state_transistion_global_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_global_rx (NAT_ESTABLISHED, sptr_tcp_translation_entry);
}
}
semGive(natentrylock);
natStats.tcp_pkts_i2l++;
natStats.tcp_bytes_i2l += ntohs(sptr_tcp_packet->ip_header.total_length);
return (PASS);
}
/*************************************************************************************
Function:
To handle address translation of packet received from local port in NAPT mode.
Description:
Match transport address with existing TCP control block list. If found use this
control block.
If not found, look for match in IP control block list. If match is found here,
look for match in TCP control block list belonging to matched IP address. If
the match is found, process packet as Basic NAT. Else, process it in NAPT mode.
Once the transport address gets translated, check the TCP flag and do the TCP
state transition to reset the connection timers (local and global connections)
if necessary.
*************************************************************************************/
enum TEST handle_tcp_translation_local_rx_nats (TCP_PACKET *sptr_tcp_packet)
{
NAT_CURRENCY_TRANSLATION_ENTRY *sptr_tcp_translation_entry=NULL;
NAT_BIND_INFO bind_info;
NAT_STATUS status;
USHORT checksum;
IP_ADDRESS address;
USHORT local_spoofed_port_number;
bool do_state_transition=FALSE;
int mss;
semTake(natentrylock, WAIT_FOREVER);
sptr_tcp_translation_entry = find_entry (sptr_tcp_packet->ip_header.source_address,
sptr_tcp_packet->ip_header.destination_address,sptr_tcp_packet->tcp_header.source_port,sptr_tcp_packet->tcp_header.destination_port);
/* tk: 08/07/01
This code is added for H.323 protocol to avoid duplicate bind entries.
The TCP bind might have been created with its global port == local port.
In such case, we can use the existing bind entry.
*/
if (!sptr_tcp_translation_entry)
{
sptr_tcp_translation_entry = match_ports_with_entry_global (sptr_tcp_packet->ip_header.source_address,
sptr_tcp_packet->ip_header.destination_address,sptr_tcp_packet->tcp_header.source_port);
}
if (!sptr_tcp_translation_entry)
{
/* look for source address match in ip static table. If found, process
as basic NAT.
*/
/*printf("match_ports_with_entry_global NULL\n");*/
semGive(natentrylock);
if (match_sa_with_static_entry (
ntohl (sptr_tcp_packet->ip_header.source_address)) == OK)
{
if (handle_tcp_translation_local_rx_natg (sptr_tcp_packet) == PASS)
{
return (PASS);
}
else
{
return (FAIL);
}
}
/* from here on, process normally in NAPT mode */
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_NAPT;
bind_info.direction = NAT_OUTBOUND;
bind_info.protocol = IPPROTO_TCP;
bind_info.static_entry = FALSE;
/* source and destination transport addresses must be in host format */
bind_info.local_addr = ntohl(sptr_tcp_packet->ip_header.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);
status = natSetBind((u_long)&nat, 0, &bind_info);
if(status != NAT_OK)
{
return(FAIL);
}
semTake(natentrylock, WAIT_FOREVER);
sptr_tcp_translation_entry = (NAT_CURRENCY_TRANSLATION_ENTRY *) bind_info.nat_transport_entry;
}
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -