mirror of
https://github.com/apache/nuttx.git
synced 2026-05-09 23:12:17 +08:00
net/nat: Let ICMP echo id zero be a valid NAT id.
Make nat_port_select() return an error code and report the selected external port through an output parameter. This separates selection failure from the valid ICMP echo identifier value zero, so outbound NAT entry creation no longer rejects ICMP echo requests that use id zero. Signed-off-by: Shunchao Hu <ankohuu@gmail.com>
This commit is contained in:
committed by
Alan C. Assis
parent
f97b29c4c4
commit
d619ee6541
@@ -411,6 +411,7 @@ ipv4_nat_outbound_entry_find(FAR struct net_driver_s *dev, uint8_t protocol,
|
||||
FAR hash_node_t *tmp;
|
||||
uint16_t external_port;
|
||||
int32_t current_time = TICK2SEC(clock_systime_ticks());
|
||||
int ret;
|
||||
|
||||
ipv4_nat_reclaim_entry(current_time);
|
||||
|
||||
@@ -454,9 +455,10 @@ ipv4_nat_outbound_entry_find(FAR struct net_driver_s *dev, uint8_t protocol,
|
||||
"proto=%" PRIu8 ", local=%" PRIx32 ":%" PRIu16 ", try create one.\n",
|
||||
protocol, local_ip, local_port);
|
||||
|
||||
external_port = nat_port_select(dev, PF_INET, protocol,
|
||||
(FAR union ip_addr_u *)&dev->d_ipaddr, local_port);
|
||||
if (!external_port)
|
||||
ret = nat_port_select(dev, PF_INET, protocol,
|
||||
(FAR union ip_addr_u *)&dev->d_ipaddr, local_port,
|
||||
&external_port);
|
||||
if (ret < 0)
|
||||
{
|
||||
nwarn("WARNING: Failed to find an available port!\n");
|
||||
return NULL;
|
||||
|
||||
@@ -411,6 +411,7 @@ ipv6_nat_outbound_entry_find(FAR struct net_driver_s *dev, uint8_t protocol,
|
||||
FAR union ip_addr_u *external_ip;
|
||||
uint16_t external_port;
|
||||
int32_t current_time = TICK2SEC(clock_systime_ticks());
|
||||
int ret;
|
||||
|
||||
ipv6_nat_reclaim_entry(current_time);
|
||||
|
||||
@@ -457,10 +458,10 @@ ipv6_nat_outbound_entry_find(FAR struct net_driver_s *dev, uint8_t protocol,
|
||||
local_ip[4], local_ip[5], local_ip[6], local_ip[7], local_port);
|
||||
|
||||
external_ip = (FAR union ip_addr_u *)netdev_ipv6_srcaddr(dev, peer_ip);
|
||||
external_port = nat_port_select(dev, PF_INET6, protocol,
|
||||
external_ip, local_port);
|
||||
ret = nat_port_select(dev, PF_INET6, protocol, external_ip, local_port,
|
||||
&external_port);
|
||||
|
||||
if (!external_port)
|
||||
if (ret < 0)
|
||||
{
|
||||
nwarn("WARNING: Failed to find an available port!\n");
|
||||
return NULL;
|
||||
|
||||
+53
-30
@@ -56,13 +56,14 @@ static rmutex_t g_nat_lock = NXRMUTEX_INITIALIZER;
|
||||
* Used when corresponding stack is disabled.
|
||||
*
|
||||
* Input Parameters:
|
||||
* domain - The domain of the packet.
|
||||
* protocol - The L4 protocol of the packet.
|
||||
* ip - The IP bind with the port (in network byte order).
|
||||
* local_port - The local port (in network byte order), as reference.
|
||||
* domain - The domain of the packet.
|
||||
* protocol - The L4 protocol of the packet.
|
||||
* ip - The IP bind with the port (in network byte order).
|
||||
* local_port - The local port (in network byte order), as reference.
|
||||
* external_port - The selected external port (in network byte order).
|
||||
*
|
||||
* Returned Value:
|
||||
* port number on success; 0 on failure
|
||||
* 0 on success; a negated errno on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@@ -71,12 +72,15 @@ static rmutex_t g_nat_lock = NXRMUTEX_INITIALIZER;
|
||||
(defined(CONFIG_NET_ICMP) && !defined(CONFIG_NET_ICMP_SOCKET)) || \
|
||||
(defined(CONFIG_NET_ICMPv6) && !defined(CONFIG_NET_ICMPv6_SOCKET))
|
||||
|
||||
static uint16_t nat_port_select_without_stack(
|
||||
static int nat_port_select_without_stack(
|
||||
uint8_t domain, uint8_t protocol, FAR const union ip_addr_u *ip,
|
||||
uint16_t local_port)
|
||||
uint16_t local_port, FAR uint16_t *external_port)
|
||||
{
|
||||
uint16_t portno = local_port;
|
||||
uint16_t hport = NTOHS(portno);
|
||||
|
||||
DEBUGASSERT(external_port != NULL);
|
||||
|
||||
while (nat_port_inuse(domain, protocol, ip, portno))
|
||||
{
|
||||
NET_PORT_NEXT_NH(portno, hport);
|
||||
@@ -84,11 +88,12 @@ static uint16_t nat_port_select_without_stack(
|
||||
{
|
||||
/* We have looped back, failed. */
|
||||
|
||||
return 0;
|
||||
return -EADDRINUSE;
|
||||
}
|
||||
}
|
||||
|
||||
return portno;
|
||||
*external_port = portno;
|
||||
return OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -216,22 +221,26 @@ bool nat_port_inuse(uint8_t domain, uint8_t protocol,
|
||||
* Select an available port number for TCP/UDP protocol, or id for ICMP.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - The device on which the packet will be sent.
|
||||
* domain - The domain of the packet.
|
||||
* protocol - The L4 protocol of the packet.
|
||||
* external_ip - The external IP bind with the port.
|
||||
* local_port - The local port of the packet, as reference.
|
||||
* dev - The device on which the packet will be sent.
|
||||
* domain - The domain of the packet.
|
||||
* protocol - The L4 protocol of the packet.
|
||||
* external_ip - The external IP bind with the port.
|
||||
* local_port - The local port of the packet, as reference.
|
||||
* external_port - The selected external port.
|
||||
*
|
||||
* Returned Value:
|
||||
* External port number on success; 0 on failure
|
||||
* 0 on success; a negated errno on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
uint16_t nat_port_select(FAR struct net_driver_s *dev,
|
||||
uint8_t domain, uint8_t protocol,
|
||||
FAR const union ip_addr_u *external_ip,
|
||||
uint16_t local_port)
|
||||
int nat_port_select(FAR struct net_driver_s *dev,
|
||||
uint8_t domain, uint8_t protocol,
|
||||
FAR const union ip_addr_u *external_ip,
|
||||
uint16_t local_port,
|
||||
FAR uint16_t *external_port)
|
||||
{
|
||||
DEBUGASSERT(external_port != NULL);
|
||||
|
||||
switch (protocol)
|
||||
{
|
||||
#ifdef CONFIG_NET_TCP
|
||||
@@ -249,10 +258,17 @@ uint16_t nat_port_select(FAR struct net_driver_s *dev,
|
||||
ret = tcp_selectport(domain, external_ip, 0);
|
||||
}
|
||||
|
||||
return ret > 0 ? ret : 0;
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
*external_port = ret;
|
||||
return OK;
|
||||
#else
|
||||
return nat_port_select_without_stack(domain, IP_PROTO_TCP,
|
||||
external_ip, local_port);
|
||||
external_ip, local_port,
|
||||
external_port);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@@ -284,10 +300,12 @@ uint16_t nat_port_select(FAR struct net_driver_s *dev,
|
||||
|
||||
/* TODO: Try keep origin port as possible. */
|
||||
|
||||
return HTONS(udp_select_port(domain, &u));
|
||||
*external_port = HTONS(udp_select_port(domain, &u));
|
||||
return *external_port == 0 ? -EADDRINUSE : OK;
|
||||
#else
|
||||
return nat_port_select_without_stack(domain, IP_PROTO_UDP,
|
||||
external_ip, local_port);
|
||||
external_ip, local_port,
|
||||
external_port);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@@ -306,14 +324,16 @@ uint16_t nat_port_select(FAR struct net_driver_s *dev,
|
||||
{
|
||||
/* We have looped back, failed. */
|
||||
|
||||
return 0;
|
||||
return -EADDRINUSE;
|
||||
}
|
||||
}
|
||||
|
||||
return id;
|
||||
*external_port = id;
|
||||
return OK;
|
||||
#else
|
||||
return nat_port_select_without_stack(domain, IP_PROTO_ICMP,
|
||||
external_ip, local_port);
|
||||
external_ip, local_port,
|
||||
external_port);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@@ -332,14 +352,16 @@ uint16_t nat_port_select(FAR struct net_driver_s *dev,
|
||||
{
|
||||
/* We have looped back, failed. */
|
||||
|
||||
return 0;
|
||||
return -EADDRINUSE;
|
||||
}
|
||||
}
|
||||
|
||||
return id;
|
||||
*external_port = id;
|
||||
return OK;
|
||||
#else
|
||||
return nat_port_select_without_stack(domain, IP_PROTO_ICMP6,
|
||||
external_ip, local_port);
|
||||
external_ip, local_port,
|
||||
external_port);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@@ -347,7 +369,8 @@ uint16_t nat_port_select(FAR struct net_driver_s *dev,
|
||||
|
||||
/* Select original port for unsupported protocol. */
|
||||
|
||||
return local_port;
|
||||
*external_port = local_port;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
+12
-10
@@ -256,21 +256,23 @@ bool nat_port_inuse(uint8_t domain, uint8_t protocol,
|
||||
* Select an available port number for TCP/UDP protocol, or id for ICMP.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - The device on which the packet will be sent.
|
||||
* domain - The domain of the packet.
|
||||
* protocol - The L4 protocol of the packet.
|
||||
* external_ip - The external IP bind with the port.
|
||||
* local_port - The local port of the packet, as reference.
|
||||
* dev - The device on which the packet will be sent.
|
||||
* domain - The domain of the packet.
|
||||
* protocol - The L4 protocol of the packet.
|
||||
* external_ip - The external IP bind with the port.
|
||||
* local_port - The local port of the packet, as reference.
|
||||
* external_port - The selected external port.
|
||||
*
|
||||
* Returned Value:
|
||||
* External port number on success; 0 on failure
|
||||
* 0 on success; a negated errno on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
uint16_t nat_port_select(FAR struct net_driver_s *dev,
|
||||
uint8_t domain, uint8_t protocol,
|
||||
FAR const union ip_addr_u *external_ip,
|
||||
uint16_t local_port);
|
||||
int nat_port_select(FAR struct net_driver_s *dev,
|
||||
uint8_t domain, uint8_t protocol,
|
||||
FAR const union ip_addr_u *external_ip,
|
||||
uint16_t local_port,
|
||||
FAR uint16_t *external_port);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nat_expire_time
|
||||
|
||||
Reference in New Issue
Block a user