diff options
author | Florian Westphal <fw@strlen.de> | 2022-09-06 18:20:36 +0300 |
---|---|---|
committer | Florian Westphal <fw@strlen.de> | 2022-09-07 17:46:04 +0300 |
commit | adda60cc2bb0fa46bed004070f29f90db96afbb3 (patch) | |
tree | 9efa77eccff0666b38dbb5cee926625f19ef5aa1 /net/netfilter | |
parent | c92c27171040554cfda7a3fc925e9dbcb5b4a698 (diff) | |
download | linux-adda60cc2bb0fa46bed004070f29f90db96afbb3.tar.xz |
netfilter: nat: avoid long-running port range loop
Looping a large port range takes too long. Instead select a random
offset within [ntohs(exp->saved_proto.tcp.port), 65535] and try 128
ports.
This is a rehash of an erlier patch to do the same, but generalized
to handle other helpers as well.
Link: https://patchwork.ozlabs.org/project/netfilter-devel/patch/20210920204439.13179-2-Cole.Dishington@alliedtelesis.co.nz/
Signed-off-by: Florian Westphal <fw@strlen.de>
Diffstat (limited to 'net/netfilter')
-rw-r--r-- | net/netfilter/nf_nat_helper.c | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/net/netfilter/nf_nat_helper.c b/net/netfilter/nf_nat_helper.c index 067d6d6f6b7d..a95a25196943 100644 --- a/net/netfilter/nf_nat_helper.c +++ b/net/netfilter/nf_nat_helper.c @@ -201,8 +201,18 @@ EXPORT_SYMBOL(nf_nat_follow_master); u16 nf_nat_exp_find_port(struct nf_conntrack_expect *exp, u16 port) { + 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; + /* Try to get same port: if not, try to change it. */ - for (; port != 0; port++) { + for (;;) { int res; exp->tuple.dst.u.tcp.port = htons(port); @@ -210,8 +220,10 @@ u16 nf_nat_exp_find_port(struct nf_conntrack_expect *exp, u16 port) if (res == 0) return port; - if (res != -EBUSY) + if (res != -EBUSY || (--attempts_left < 0)) break; + + port = min + prandom_u32_max(range); } return 0; |