netfilter: nat: move repetitive nat port reserve loop to a helper
authorFlorian Westphal <fw@strlen.de>
Tue, 6 Sep 2022 15:20:35 +0000 (17:20 +0200)
committerFlorian Westphal <fw@strlen.de>
Wed, 7 Sep 2022 14:46:04 +0000 (16:46 +0200)
Almost all nat helpers reserve an expecation port the same way:
Try the port inidcated by the peer, then move to next port if that
port is already in use.

We can squash this into a helper.

Suggested-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Florian Westphal <fw@strlen.de>
include/net/netfilter/nf_nat_helper.h
net/ipv4/netfilter/nf_nat_h323.c
net/netfilter/nf_nat_amanda.c
net/netfilter/nf_nat_ftp.c
net/netfilter/nf_nat_helper.c
net/netfilter/nf_nat_irc.c
net/netfilter/nf_nat_sip.c

index efae846..44c421b 100644 (file)
@@ -38,4 +38,5 @@ bool nf_nat_mangle_udp_packet(struct sk_buff *skb, struct nf_conn *ct,
  * to port ct->master->saved_proto. */
 void nf_nat_follow_master(struct nf_conn *ct, struct nf_conntrack_expect *this);
 
+u16 nf_nat_exp_find_port(struct nf_conntrack_expect *exp, u16 port);
 #endif
index a334f0d..faee20a 100644 (file)
@@ -291,20 +291,7 @@ static int nat_t120(struct sk_buff *skb, struct nf_conn *ct,
        exp->expectfn = nf_nat_follow_master;
        exp->dir = !dir;
 
-       /* Try to get same port: if not, try to change it. */
-       for (; nated_port != 0; nated_port++) {
-               int ret;
-
-               exp->tuple.dst.u.tcp.port = htons(nated_port);
-               ret = nf_ct_expect_related(exp, 0);
-               if (ret == 0)
-                       break;
-               else if (ret != -EBUSY) {
-                       nated_port = 0;
-                       break;
-               }
-       }
-
+       nated_port = nf_nat_exp_find_port(exp, nated_port);
        if (nated_port == 0) {  /* No port available */
                net_notice_ratelimited("nf_nat_h323: out of TCP ports\n");
                return 0;
@@ -347,20 +334,7 @@ static int nat_h245(struct sk_buff *skb, struct nf_conn *ct,
        if (info->sig_port[dir] == port)
                nated_port = ntohs(info->sig_port[!dir]);
 
-       /* Try to get same port: if not, try to change it. */
-       for (; nated_port != 0; nated_port++) {
-               int ret;
-
-               exp->tuple.dst.u.tcp.port = htons(nated_port);
-               ret = nf_ct_expect_related(exp, 0);
-               if (ret == 0)
-                       break;
-               else if (ret != -EBUSY) {
-                       nated_port = 0;
-                       break;
-               }
-       }
-
+       nated_port = nf_nat_exp_find_port(exp, nated_port);
        if (nated_port == 0) {  /* No port available */
                net_notice_ratelimited("nf_nat_q931: out of TCP ports\n");
                return 0;
@@ -439,20 +413,7 @@ static int nat_q931(struct sk_buff *skb, struct nf_conn *ct,
        if (info->sig_port[dir] == port)
                nated_port = ntohs(info->sig_port[!dir]);
 
-       /* Try to get same port: if not, try to change it. */
-       for (; nated_port != 0; nated_port++) {
-               int ret;
-
-               exp->tuple.dst.u.tcp.port = htons(nated_port);
-               ret = nf_ct_expect_related(exp, 0);
-               if (ret == 0)
-                       break;
-               else if (ret != -EBUSY) {
-                       nated_port = 0;
-                       break;
-               }
-       }
-
+       nated_port = nf_nat_exp_find_port(exp, nated_port);
        if (nated_port == 0) {  /* No port available */
                net_notice_ratelimited("nf_nat_ras: out of TCP ports\n");
                return 0;
@@ -532,20 +493,7 @@ static int nat_callforwarding(struct sk_buff *skb, struct nf_conn *ct,
        exp->expectfn = ip_nat_callforwarding_expect;
        exp->dir = !dir;
 
-       /* Try to get same port: if not, try to change it. */
-       for (nated_port = ntohs(port); nated_port != 0; nated_port++) {
-               int ret;
-
-               exp->tuple.dst.u.tcp.port = htons(nated_port);
-               ret = nf_ct_expect_related(exp, 0);
-               if (ret == 0)
-                       break;
-               else if (ret != -EBUSY) {
-                       nated_port = 0;
-                       break;
-               }
-       }
-
+       nated_port = nf_nat_exp_find_port(exp, ntohs(port));
        if (nated_port == 0) {  /* No port available */
                net_notice_ratelimited("nf_nat_q931: out of TCP ports\n");
                return 0;
index 3bc7e08..98deef6 100644 (file)
@@ -44,19 +44,7 @@ static unsigned int help(struct sk_buff *skb,
        exp->expectfn = nf_nat_follow_master;
 
        /* Try to get same port: if not, try to change it. */
-       for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
-               int res;
-
-               exp->tuple.dst.u.tcp.port = htons(port);
-               res = nf_ct_expect_related(exp, 0);
-               if (res == 0)
-                       break;
-               else if (res != -EBUSY) {
-                       port = 0;
-                       break;
-               }
-       }
-
+       port = nf_nat_exp_find_port(exp, ntohs(exp->saved_proto.tcp.port));
        if (port == 0) {
                nf_ct_helper_log(skb, exp->master, "all ports in use");
                return NF_DROP;
index aace676..c92a436 100644 (file)
@@ -86,22 +86,9 @@ static unsigned int nf_nat_ftp(struct sk_buff *skb,
         * this one. */
        exp->expectfn = nf_nat_follow_master;
 
-       /* Try to get same port: if not, try to change it. */
-       for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
-               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) {
-                       port = 0;
-                       break;
-               }
-       }
-
+       port = nf_nat_exp_find_port(exp, ntohs(exp->saved_proto.tcp.port));
        if (port == 0) {
-               nf_ct_helper_log(skb, ct, "all ports in use");
+               nf_ct_helper_log(skb, exp->master, "all ports in use");
                return NF_DROP;
        }
 
index a263505..067d6d6 100644 (file)
@@ -198,3 +198,22 @@ void nf_nat_follow_master(struct nf_conn *ct,
        nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST);
 }
 EXPORT_SYMBOL(nf_nat_follow_master);
+
+u16 nf_nat_exp_find_port(struct nf_conntrack_expect *exp, u16 port)
+{
+       /* Try to get same port: if not, try to change it. */
+       for (; port != 0; port++) {
+               int res;
+
+               exp->tuple.dst.u.tcp.port = htons(port);
+               res = nf_ct_expect_related(exp, 0);
+               if (res == 0)
+                       return port;
+
+               if (res != -EBUSY)
+                       break;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(nf_nat_exp_find_port);
index c691ab8..19c4fcc 100644 (file)
@@ -48,20 +48,8 @@ static unsigned int help(struct sk_buff *skb,
        exp->dir = IP_CT_DIR_REPLY;
        exp->expectfn = nf_nat_follow_master;
 
-       /* Try to get same port: if not, try to change it. */
-       for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
-               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) {
-                       port = 0;
-                       break;
-               }
-       }
-
+       port = nf_nat_exp_find_port(exp,
+                                   ntohs(exp->saved_proto.tcp.port));
        if (port == 0) {
                nf_ct_helper_log(skb, ct, "all ports in use");
                return NF_DROP;
index f0a735e..cf4aeb2 100644 (file)
@@ -410,19 +410,7 @@ static unsigned int nf_nat_sip_expect(struct sk_buff *skb, unsigned int protoff,
        exp->dir = !dir;
        exp->expectfn = nf_nat_sip_expected;
 
-       for (; port != 0; port++) {
-               int ret;
-
-               exp->tuple.dst.u.udp.port = htons(port);
-               ret = nf_ct_expect_related(exp, NF_CT_EXP_F_SKIP_MASTER);
-               if (ret == 0)
-                       break;
-               else if (ret != -EBUSY) {
-                       port = 0;
-                       break;
-               }
-       }
-
+       port = nf_nat_exp_find_port(exp, port);
        if (port == 0) {
                nf_ct_helper_log(skb, ct, "all ports in use for SIP");
                return NF_DROP;