mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-18 09:51:26 +00:00
79 lines
2.7 KiB
Diff
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
|
|
|