wlan-ap-Telecominfraproject/feeds/qca-wifi-7/ipq53xx/patches-6.1/0511-linux-change-the-port-selection-algorithm-in-ftp-alg.patch
John Crispin 68cf54d9f7 qca-wifi-7: update to ath12.5.5
Signed-off-by: John Crispin <john@phrozen.org>
2025-02-27 12:45:52 +01:00

79 lines
2.7 KiB
Diff

From 61437a02ea51622c4c0b26517f46f2bf7cda023c Mon Sep 17 00:00:00 2001
From: Ken Zhu <guigenz@codeaurora.org>
Date: Mon, 8 Oct 2018 16:45:07 -0700
Subject: [PATCH] linux: change the port selection algorithm in ftp alg
In the case of MAP feature, the ports are limited to number with same PSID,
the port should be in this format |offset|psid|pad|, the offset usually is
6 bits, the psid varies in 0~8 and pad length of the rest bits after offset
and psid.
the new port use same first ten bits of port after SNAT and the last 6 bits
of original port and varies the last 6 bits only.
this makes sure that new port and the port after snat share the same PSID
Change-Id: I5e5a3c20fa0ec4e31273c5e23c6e6aa86ebb97f6
Signed-off-by: Ken Zhu <guigenz@codeaurora.org>
---
net/netfilter/nf_nat_ftp.c | 36 ++++++++++++++++++++++++++++++++++--
1 file changed, 34 insertions(+), 2 deletions(-)
diff --git a/net/netfilter/nf_nat_ftp.c b/net/netfilter/nf_nat_ftp.c
index c92a436d9c48..dea0f2af21cb 100644
--- a/net/netfilter/nf_nat_ftp.c
+++ b/net/netfilter/nf_nat_ftp.c
@@ -69,7 +69,7 @@ static unsigned int nf_nat_ftp(struct sk_buff *skb,
struct nf_conntrack_expect *exp)
{
union nf_inet_addr newaddr;
- u_int16_t port;
+ u16 port;
int dir = CTINFO2DIR(ctinfo);
struct nf_conn *ct = exp->master;
char buffer[sizeof("|1||65535|") + INET6_ADDRSTRLEN];
@@ -86,7 +86,39 @@ static unsigned int nf_nat_ftp(struct sk_buff *skb,
* this one. */
exp->expectfn = nf_nat_follow_master;
- port = nf_nat_exp_find_port(exp, ntohs(exp->saved_proto.tcp.port));
+ /* In the case of MAP-E, the FTP ALG source port number must use its own
+ * PSID. Otherwise the returned packets from ftp server will use other
+ * than its own IPv6 address. The port number of MAP-E has the format
+ * like offset | psid | pad. The offset length is usually 6 bits long.
+ * So this change reuses the least 10 bits which include the valid PSID
+ * and tries different offset value with a step size of 1024 till a
+ * free port number is available. */
+ port = (ntohs(exp->saved_proto.tcp.port) & ~((1 << 10) - 1)) +
+ (ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port) & ((1 << 10) - 1));
+ static const unsigned int max_attempts = 128;
+ int range, attempts_left;
+ u16 min = port;
+
+ range = USHRT_MAX - port;
+ attempts_left = range;
+
+ if (attempts_left > max_attempts)
+ attempts_left = max_attempts;
+
+ for (; ;) {
+ int ret;
+
+
+ exp->tuple.dst.u.tcp.port = htons(port);
+ ret = nf_ct_expect_related(exp, 0);
+ if (ret == 0)
+ break;
+ else if (ret != -EBUSY || (--attempts_left < 0)) {
+ port = 0;
+ break;
+ }
+ }
+
if (port == 0) {
nf_ct_helper_log(skb, exp->master, "all ports in use");
return NF_DROP;
--
2.34.1