Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: nat: move repetitive nat port reserve loop to a helper

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>

+30 -111
+1
include/net/netfilter/nf_nat_helper.h
··· 38 38 * to port ct->master->saved_proto. */ 39 39 void nf_nat_follow_master(struct nf_conn *ct, struct nf_conntrack_expect *this); 40 40 41 + u16 nf_nat_exp_find_port(struct nf_conntrack_expect *exp, u16 port); 41 42 #endif
+4 -56
net/ipv4/netfilter/nf_nat_h323.c
··· 291 291 exp->expectfn = nf_nat_follow_master; 292 292 exp->dir = !dir; 293 293 294 - /* Try to get same port: if not, try to change it. */ 295 - for (; nated_port != 0; nated_port++) { 296 - int ret; 297 - 298 - exp->tuple.dst.u.tcp.port = htons(nated_port); 299 - ret = nf_ct_expect_related(exp, 0); 300 - if (ret == 0) 301 - break; 302 - else if (ret != -EBUSY) { 303 - nated_port = 0; 304 - break; 305 - } 306 - } 307 - 294 + nated_port = nf_nat_exp_find_port(exp, nated_port); 308 295 if (nated_port == 0) { /* No port available */ 309 296 net_notice_ratelimited("nf_nat_h323: out of TCP ports\n"); 310 297 return 0; ··· 334 347 if (info->sig_port[dir] == port) 335 348 nated_port = ntohs(info->sig_port[!dir]); 336 349 337 - /* Try to get same port: if not, try to change it. */ 338 - for (; nated_port != 0; nated_port++) { 339 - int ret; 340 - 341 - exp->tuple.dst.u.tcp.port = htons(nated_port); 342 - ret = nf_ct_expect_related(exp, 0); 343 - if (ret == 0) 344 - break; 345 - else if (ret != -EBUSY) { 346 - nated_port = 0; 347 - break; 348 - } 349 - } 350 - 350 + nated_port = nf_nat_exp_find_port(exp, nated_port); 351 351 if (nated_port == 0) { /* No port available */ 352 352 net_notice_ratelimited("nf_nat_q931: out of TCP ports\n"); 353 353 return 0; ··· 413 439 if (info->sig_port[dir] == port) 414 440 nated_port = ntohs(info->sig_port[!dir]); 415 441 416 - /* Try to get same port: if not, try to change it. */ 417 - for (; nated_port != 0; nated_port++) { 418 - int ret; 419 - 420 - exp->tuple.dst.u.tcp.port = htons(nated_port); 421 - ret = nf_ct_expect_related(exp, 0); 422 - if (ret == 0) 423 - break; 424 - else if (ret != -EBUSY) { 425 - nated_port = 0; 426 - break; 427 - } 428 - } 429 - 442 + nated_port = nf_nat_exp_find_port(exp, nated_port); 430 443 if (nated_port == 0) { /* No port available */ 431 444 net_notice_ratelimited("nf_nat_ras: out of TCP ports\n"); 432 445 return 0; ··· 493 532 exp->expectfn = ip_nat_callforwarding_expect; 494 533 exp->dir = !dir; 495 534 496 - /* Try to get same port: if not, try to change it. */ 497 - for (nated_port = ntohs(port); nated_port != 0; nated_port++) { 498 - int ret; 499 - 500 - exp->tuple.dst.u.tcp.port = htons(nated_port); 501 - ret = nf_ct_expect_related(exp, 0); 502 - if (ret == 0) 503 - break; 504 - else if (ret != -EBUSY) { 505 - nated_port = 0; 506 - break; 507 - } 508 - } 509 - 535 + nated_port = nf_nat_exp_find_port(exp, ntohs(port)); 510 536 if (nated_port == 0) { /* No port available */ 511 537 net_notice_ratelimited("nf_nat_q931: out of TCP ports\n"); 512 538 return 0;
+1 -13
net/netfilter/nf_nat_amanda.c
··· 44 44 exp->expectfn = nf_nat_follow_master; 45 45 46 46 /* Try to get same port: if not, try to change it. */ 47 - for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) { 48 - int res; 49 - 50 - exp->tuple.dst.u.tcp.port = htons(port); 51 - res = nf_ct_expect_related(exp, 0); 52 - if (res == 0) 53 - break; 54 - else if (res != -EBUSY) { 55 - port = 0; 56 - break; 57 - } 58 - } 59 - 47 + port = nf_nat_exp_find_port(exp, ntohs(exp->saved_proto.tcp.port)); 60 48 if (port == 0) { 61 49 nf_ct_helper_log(skb, exp->master, "all ports in use"); 62 50 return NF_DROP;
+2 -15
net/netfilter/nf_nat_ftp.c
··· 86 86 * this one. */ 87 87 exp->expectfn = nf_nat_follow_master; 88 88 89 - /* Try to get same port: if not, try to change it. */ 90 - for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) { 91 - int ret; 92 - 93 - exp->tuple.dst.u.tcp.port = htons(port); 94 - ret = nf_ct_expect_related(exp, 0); 95 - if (ret == 0) 96 - break; 97 - else if (ret != -EBUSY) { 98 - port = 0; 99 - break; 100 - } 101 - } 102 - 89 + port = nf_nat_exp_find_port(exp, ntohs(exp->saved_proto.tcp.port)); 103 90 if (port == 0) { 104 - nf_ct_helper_log(skb, ct, "all ports in use"); 91 + nf_ct_helper_log(skb, exp->master, "all ports in use"); 105 92 return NF_DROP; 106 93 } 107 94
+19
net/netfilter/nf_nat_helper.c
··· 198 198 nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST); 199 199 } 200 200 EXPORT_SYMBOL(nf_nat_follow_master); 201 + 202 + u16 nf_nat_exp_find_port(struct nf_conntrack_expect *exp, u16 port) 203 + { 204 + /* Try to get same port: if not, try to change it. */ 205 + for (; port != 0; port++) { 206 + int res; 207 + 208 + exp->tuple.dst.u.tcp.port = htons(port); 209 + res = nf_ct_expect_related(exp, 0); 210 + if (res == 0) 211 + return port; 212 + 213 + if (res != -EBUSY) 214 + break; 215 + } 216 + 217 + return 0; 218 + } 219 + EXPORT_SYMBOL_GPL(nf_nat_exp_find_port);
+2 -14
net/netfilter/nf_nat_irc.c
··· 48 48 exp->dir = IP_CT_DIR_REPLY; 49 49 exp->expectfn = nf_nat_follow_master; 50 50 51 - /* Try to get same port: if not, try to change it. */ 52 - for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) { 53 - int ret; 54 - 55 - exp->tuple.dst.u.tcp.port = htons(port); 56 - ret = nf_ct_expect_related(exp, 0); 57 - if (ret == 0) 58 - break; 59 - else if (ret != -EBUSY) { 60 - port = 0; 61 - break; 62 - } 63 - } 64 - 51 + port = nf_nat_exp_find_port(exp, 52 + ntohs(exp->saved_proto.tcp.port)); 65 53 if (port == 0) { 66 54 nf_ct_helper_log(skb, ct, "all ports in use"); 67 55 return NF_DROP;
+1 -13
net/netfilter/nf_nat_sip.c
··· 410 410 exp->dir = !dir; 411 411 exp->expectfn = nf_nat_sip_expected; 412 412 413 - for (; port != 0; port++) { 414 - int ret; 415 - 416 - exp->tuple.dst.u.udp.port = htons(port); 417 - ret = nf_ct_expect_related(exp, NF_CT_EXP_F_SKIP_MASTER); 418 - if (ret == 0) 419 - break; 420 - else if (ret != -EBUSY) { 421 - port = 0; 422 - break; 423 - } 424 - } 425 - 413 + port = nf_nat_exp_find_port(exp, port); 426 414 if (port == 0) { 427 415 nf_ct_helper_log(skb, ct, "all ports in use for SIP"); 428 416 return NF_DROP;