diff --git a/net/nat/ipv4_nat.c b/net/nat/ipv4_nat.c index f1d44155fc..8b0811e52e 100644 --- a/net/nat/ipv4_nat.c +++ b/net/nat/ipv4_nat.c @@ -321,4 +321,34 @@ int ipv4_nat_outbound(FAR struct net_driver_s *dev, return OK; } +/**************************************************************************** + * Name: ipv4_nat_port_inuse + * + * Description: + * Check whether a port is currently used by NAT. + * + * Input Parameters: + * protocol - The L4 protocol of the packet. + * ip - The IP bind with the port (in network byte order). + * port - The port number to check (in network byte order). + * + * Returned Value: + * True if the port is already used by NAT, otherwise false. + * + ****************************************************************************/ + +bool ipv4_nat_port_inuse(uint8_t protocol, in_addr_t ip, uint16_t port) +{ + FAR struct ipv4_nat_entry *entry = + ipv4_nat_inbound_entry_find(protocol, port); + + /* Not checking ip is enough for single NAT device, may save external_ip in + * entry for multiple device support in future. + */ + + UNUSED(ip); + + return entry != NULL; +} + #endif /* CONFIG_NET_NAT && CONFIG_NET_IPv4 */ diff --git a/net/nat/ipv4_nat_entry.c b/net/nat/ipv4_nat_entry.c index e0f7e92513..4a57549355 100644 --- a/net/nat/ipv4_nat_entry.c +++ b/net/nat/ipv4_nat_entry.c @@ -62,7 +62,6 @@ static uint16_t ipv4_nat_select_port(uint8_t protocol, uint16_t local_port) { /* TODO: Implement this, need to consider local ports and nat ports. * TODO: Shall we let the chosen port same as local_port if possible? - * TODO: Also need to modify local port number assignment. */ # warning Missing logic diff --git a/net/nat/nat.h b/net/nat/nat.h index c5b13e5a3e..e5df4db633 100644 --- a/net/nat/nat.h +++ b/net/nat/nat.h @@ -27,6 +27,7 @@ #include +#include #include #include @@ -156,6 +157,24 @@ int ipv4_nat_inbound(FAR struct net_driver_s *dev, int ipv4_nat_outbound(FAR struct net_driver_s *dev, FAR struct ipv4_hdr_s *ipv4); +/**************************************************************************** + * Name: ipv4_nat_port_inuse + * + * Description: + * Check whether a port is currently used by NAT. + * + * Input Parameters: + * protocol - The L4 protocol of the packet. + * ip - The IP bind with the port (in network byte order). + * port - The port number to check (in network byte order). + * + * Returned Value: + * True if the port is already used by NAT, otherwise false. + * + ****************************************************************************/ + +bool ipv4_nat_port_inuse(uint8_t protocol, in_addr_t ip, uint16_t port); + /**************************************************************************** * Name: ipv4_nat_inbound_entry_find * diff --git a/net/tcp/tcp_conn.c b/net/tcp/tcp_conn.c index 28c23998b9..a4719cec59 100644 --- a/net/tcp/tcp_conn.c +++ b/net/tcp/tcp_conn.c @@ -68,6 +68,7 @@ #include "tcp/tcp.h" #include "arp/arp.h" #include "icmpv6/icmpv6.h" +#include "nat/nat.h" /**************************************************************************** * Private Data @@ -244,7 +245,12 @@ static int tcp_selectport(uint8_t domain, portno = HTONS(g_last_tcp_port); } - while (tcp_listener(domain, ipaddr, portno)); + while (tcp_listener(domain, ipaddr, portno) +#if defined(CONFIG_NET_NAT) && defined(CONFIG_NET_IPv4) + || (domain == PF_INET && + ipv4_nat_port_inuse(IP_PROTO_TCP, ipaddr->ipv4, portno)) +#endif + ); } else { @@ -252,7 +258,12 @@ static int tcp_selectport(uint8_t domain, * connection is using this local port. */ - if (tcp_listener(domain, ipaddr, portno)) + if (tcp_listener(domain, ipaddr, portno) +#if defined(CONFIG_NET_NAT) && defined(CONFIG_NET_IPv4) + || (domain == PF_INET && + ipv4_nat_port_inuse(IP_PROTO_TCP, ipaddr->ipv4, portno)) +#endif + ) { /* It is in use... return EADDRINUSE */