Commit c92c2717 authored by Florian Westphal's avatar Florian Westphal
Browse files

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: default avatarPablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
parent 8556bceb
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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
+4 −56
Original line number Diff line number Diff line
@@ -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;
+1 −13
Original line number Diff line number Diff line
@@ -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;
+2 −15
Original line number Diff line number Diff line
@@ -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;
	}

+19 −0
Original line number Diff line number Diff line
@@ -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);
Loading