mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 12:43:29 +02:00
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>
This commit is contained in:
@@ -38,4 +38,5 @@ bool nf_nat_mangle_udp_packet(struct sk_buff *skb, struct nf_conn *ct,
|
|||||||
* to port ct->master->saved_proto. */
|
* to port ct->master->saved_proto. */
|
||||||
void nf_nat_follow_master(struct nf_conn *ct, struct nf_conntrack_expect *this);
|
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
|
#endif
|
||||||
|
@@ -291,20 +291,7 @@ static int nat_t120(struct sk_buff *skb, struct nf_conn *ct,
|
|||||||
exp->expectfn = nf_nat_follow_master;
|
exp->expectfn = nf_nat_follow_master;
|
||||||
exp->dir = !dir;
|
exp->dir = !dir;
|
||||||
|
|
||||||
/* Try to get same port: if not, try to change it. */
|
nated_port = nf_nat_exp_find_port(exp, nated_port);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nated_port == 0) { /* No port available */
|
if (nated_port == 0) { /* No port available */
|
||||||
net_notice_ratelimited("nf_nat_h323: out of TCP ports\n");
|
net_notice_ratelimited("nf_nat_h323: out of TCP ports\n");
|
||||||
return 0;
|
return 0;
|
||||||
@@ -347,20 +334,7 @@ static int nat_h245(struct sk_buff *skb, struct nf_conn *ct,
|
|||||||
if (info->sig_port[dir] == port)
|
if (info->sig_port[dir] == port)
|
||||||
nated_port = ntohs(info->sig_port[!dir]);
|
nated_port = ntohs(info->sig_port[!dir]);
|
||||||
|
|
||||||
/* Try to get same port: if not, try to change it. */
|
nated_port = nf_nat_exp_find_port(exp, nated_port);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nated_port == 0) { /* No port available */
|
if (nated_port == 0) { /* No port available */
|
||||||
net_notice_ratelimited("nf_nat_q931: out of TCP ports\n");
|
net_notice_ratelimited("nf_nat_q931: out of TCP ports\n");
|
||||||
return 0;
|
return 0;
|
||||||
@@ -439,20 +413,7 @@ static int nat_q931(struct sk_buff *skb, struct nf_conn *ct,
|
|||||||
if (info->sig_port[dir] == port)
|
if (info->sig_port[dir] == port)
|
||||||
nated_port = ntohs(info->sig_port[!dir]);
|
nated_port = ntohs(info->sig_port[!dir]);
|
||||||
|
|
||||||
/* Try to get same port: if not, try to change it. */
|
nated_port = nf_nat_exp_find_port(exp, nated_port);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nated_port == 0) { /* No port available */
|
if (nated_port == 0) { /* No port available */
|
||||||
net_notice_ratelimited("nf_nat_ras: out of TCP ports\n");
|
net_notice_ratelimited("nf_nat_ras: out of TCP ports\n");
|
||||||
return 0;
|
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->expectfn = ip_nat_callforwarding_expect;
|
||||||
exp->dir = !dir;
|
exp->dir = !dir;
|
||||||
|
|
||||||
/* Try to get same port: if not, try to change it. */
|
nated_port = nf_nat_exp_find_port(exp, ntohs(port));
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nated_port == 0) { /* No port available */
|
if (nated_port == 0) { /* No port available */
|
||||||
net_notice_ratelimited("nf_nat_q931: out of TCP ports\n");
|
net_notice_ratelimited("nf_nat_q931: out of TCP ports\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
@@ -44,19 +44,7 @@ static unsigned int help(struct sk_buff *skb,
|
|||||||
exp->expectfn = nf_nat_follow_master;
|
exp->expectfn = nf_nat_follow_master;
|
||||||
|
|
||||||
/* Try to get same port: if not, try to change it. */
|
/* Try to get same port: if not, try to change it. */
|
||||||
for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
|
port = nf_nat_exp_find_port(exp, ntohs(exp->saved_proto.tcp.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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (port == 0) {
|
if (port == 0) {
|
||||||
nf_ct_helper_log(skb, exp->master, "all ports in use");
|
nf_ct_helper_log(skb, exp->master, "all ports in use");
|
||||||
return NF_DROP;
|
return NF_DROP;
|
||||||
|
@@ -86,22 +86,9 @@ static unsigned int nf_nat_ftp(struct sk_buff *skb,
|
|||||||
* this one. */
|
* this one. */
|
||||||
exp->expectfn = nf_nat_follow_master;
|
exp->expectfn = nf_nat_follow_master;
|
||||||
|
|
||||||
/* Try to get same port: if not, try to change it. */
|
port = nf_nat_exp_find_port(exp, ntohs(exp->saved_proto.tcp.port));
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (port == 0) {
|
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;
|
return NF_DROP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -198,3 +198,22 @@ void nf_nat_follow_master(struct nf_conn *ct,
|
|||||||
nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST);
|
nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(nf_nat_follow_master);
|
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);
|
||||||
|
@@ -48,20 +48,8 @@ static unsigned int help(struct sk_buff *skb,
|
|||||||
exp->dir = IP_CT_DIR_REPLY;
|
exp->dir = IP_CT_DIR_REPLY;
|
||||||
exp->expectfn = nf_nat_follow_master;
|
exp->expectfn = nf_nat_follow_master;
|
||||||
|
|
||||||
/* Try to get same port: if not, try to change it. */
|
port = nf_nat_exp_find_port(exp,
|
||||||
for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
|
ntohs(exp->saved_proto.tcp.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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (port == 0) {
|
if (port == 0) {
|
||||||
nf_ct_helper_log(skb, ct, "all ports in use");
|
nf_ct_helper_log(skb, ct, "all ports in use");
|
||||||
return NF_DROP;
|
return NF_DROP;
|
||||||
|
@@ -410,19 +410,7 @@ static unsigned int nf_nat_sip_expect(struct sk_buff *skb, unsigned int protoff,
|
|||||||
exp->dir = !dir;
|
exp->dir = !dir;
|
||||||
exp->expectfn = nf_nat_sip_expected;
|
exp->expectfn = nf_nat_sip_expected;
|
||||||
|
|
||||||
for (; port != 0; port++) {
|
port = nf_nat_exp_find_port(exp, 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (port == 0) {
|
if (port == 0) {
|
||||||
nf_ct_helper_log(skb, ct, "all ports in use for SIP");
|
nf_ct_helper_log(skb, ct, "all ports in use for SIP");
|
||||||
return NF_DROP;
|
return NF_DROP;
|
||||||
|
Reference in New Issue
Block a user