Skip to content

Commit 29f7074

Browse files
committed
[components][net][lwip-nat] Fix translated port allocation and adapt to lwIP 2.1
Allocate the translated port from the free slot index instead of the scan counter: the loop counter equals the table size once the allocation path is taken, so every new mapping got the same port (base + table size) and concurrent UDP/TCP sessions collided, return traffic could be matched to the wrong entry. Adapt the file to lwIP 2.1 as well: lwip/tcp_impl.h is lwip/prot/tcp.h and lwip/timers.h is lwip/timeouts.h now. Two behaviour changes come with it: NAT is applied only when both the source and the destination network match the rule, and the oldest ICMP entry (LRU) is evicted instead of dropping new echo requests when the ICMP table is full. Signed-off-by: zelong_666 <2027636040@qq.com>
1 parent da5098b commit 29f7074

1 file changed

Lines changed: 41 additions & 11 deletions

File tree

‎components/net/lwip-nat/ipv4_nat.c‎

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,13 @@
7777
#include "lwip/netif.h"
7878
#include "lwip/ip_addr.h"
7979
#include "lwip/icmp.h"
80-
#include "lwip/tcp_impl.h"
80+
/* lwIP 2.1 adaptation: tcp_impl.h was renamed/moved to prot/tcp.h (SiFli local modification) */
81+
#include "lwip/prot/tcp.h"
8182
#include "lwip/udp.h"
8283
#include "lwip/mem.h"
8384
#include "lwip/sys.h"
84-
#include "lwip/timers.h"
85+
/* lwIP 2.1 adaptation: timers.h was renamed/moved to timeouts.h (SiFli local modification) */
86+
#include "lwip/timeouts.h"
8587
#include "netif/etharp.h"
8688

8789
#include <limits.h>
@@ -371,8 +373,15 @@ ip_nat_shallnat(const struct ip_hdr *iphdr)
371373
ip_nat_conf_t *nat_config = ip_nat_cfg;
372374

373375
for (nat_config = ip_nat_cfg; nat_config != NULL; nat_config = nat_config->next) {
376+
/*
377+
* SiFli local modification
378+
* Original RT-Thread implementation (NAT if either source or dest
379+
* matches the rule).
380+
* Changed to && locally: NAT is applied only when both the source and
381+
* dest networks match the rule.
382+
*/
374383
if (ip_addr_netcmp(&(iphdr->dest), &(nat_config->entry.dest_net),
375-
&(nat_config->entry.dest_netmask)) ||
384+
&(nat_config->entry.dest_netmask)) &&
376385
ip_addr_netcmp(&(iphdr->src), &(nat_config->entry.source_net),
377386
&(nat_config->entry.source_netmask))) {
378387
break;
@@ -679,18 +688,37 @@ ip_nat_out(struct pbuf *p)
679688
("ip_nat_out: short icmp echo packet (%" U16_F " bytes) discarded\n", p->tot_len));
680689
} else {
681690
if (ICMPH_TYPE(icmphdr) == ICMP_ECHO) {
691+
/*
692+
* SiFli local modification
693+
* Original RT-Thread implementation (drops new ICMP requests when
694+
* the table is full).
695+
* Changed locally: when no free slot is found, evict the oldest entry
696+
* (smallest ttl) using LRU and reuse its slot, so new echo requests
697+
* are not dropped when the ICMP table is full.
698+
*/
699+
int oldest = -1;
700+
s32_t oldest_ttl = LWIP_NAT_TTL_INFINITE;
701+
682702
for (i = 0; i < LWIP_NAT_DEFAULT_STATE_TABLES_ICMP; i++) {
683703
if (!ip_nat_icmp_table[i].common.ttl) {
684704
nat_entry.icmp = &ip_nat_icmp_table[i];
685-
ip_nat_cmn_init(nat_config, iphdr, nat_entry.cmn);
686-
nat_entry.icmp->id = icmphdr->id;
687-
nat_entry.icmp->seqno = icmphdr->seqno;
688-
ip_nat_dbg_dump_icmp_nat_entry(" ip_nat_out: created new NAT entry ", nat_entry.icmp);
689705
break;
690706
}
707+
if (ip_nat_icmp_table[i].common.ttl < oldest_ttl) {
708+
oldest = i;
709+
oldest_ttl = ip_nat_icmp_table[i].common.ttl;
710+
}
711+
}
712+
if (nat_entry.icmp == NULL && oldest >= 0) {
713+
nat_entry.icmp = &ip_nat_icmp_table[oldest];
714+
IPNAT_ENTRY_RESET(&nat_entry.icmp->common);
691715
}
692-
if (NULL == nat_entry.icmp)
693-
{
716+
if (nat_entry.icmp != NULL) {
717+
ip_nat_cmn_init(nat_config, iphdr, nat_entry.cmn);
718+
nat_entry.icmp->id = icmphdr->id;
719+
nat_entry.icmp->seqno = icmphdr->seqno;
720+
ip_nat_dbg_dump_icmp_nat_entry(" ip_nat_out: created new NAT entry ", nat_entry.icmp);
721+
} else {
694722
LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_out: no more NAT entries for ICMP available\n"));
695723
}
696724
}
@@ -817,7 +845,8 @@ ip_nat_udp_lookup_outgoing(ip_nat_conf_t *nat_config, const struct ip_hdr *iphdr
817845
if (allocate) {
818846
if (last_free != -1) {
819847
nat_entry.udp = &ip_nat_udp_table[last_free];
820-
nat_entry.udp->nport = htons((u16_t) (LWIP_NAT_DEFAULT_UDP_SOURCE_PORT + i));
848+
/* SiFli local modification */
849+
nat_entry.udp->nport = htons((u16_t) (LWIP_NAT_DEFAULT_UDP_SOURCE_PORT + last_free));
821850
nat_entry.udp->sport = udphdr->src;
822851
nat_entry.udp->dport = udphdr->dest;
823852
ip_nat_cmn_init(nat_config, iphdr, nat_entry.cmn);
@@ -902,7 +931,8 @@ ip_nat_tcp_lookup_outgoing(ip_nat_conf_t *nat_config, const struct ip_hdr *iphdr
902931
if (allocate) {
903932
if (last_free != -1) {
904933
nat_entry.tcp = &ip_nat_tcp_table[last_free];
905-
nat_entry.tcp->nport = htons((u16_t) (LWIP_NAT_DEFAULT_TCP_SOURCE_PORT + i));
934+
/* SiFli local modification */
935+
nat_entry.tcp->nport = htons((u16_t) (LWIP_NAT_DEFAULT_TCP_SOURCE_PORT + last_free));
906936
nat_entry.tcp->sport = tcphdr->src;
907937
nat_entry.tcp->dport = tcphdr->dest;
908938
ip_nat_cmn_init(nat_config, iphdr, nat_entry.cmn);

0 commit comments

Comments
 (0)