Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1fefe147 authored by Florian Westphal's avatar Florian Westphal Committed by Pablo Neira Ayuso
Browse files

netfilter: synproxy: only register hooks when needed



Defer registration of the synproxy hooks until the first SYNPROXY rule is
added.  Also means we only register hooks in namespaces that need it.

Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 122868b3
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -52,6 +52,8 @@ struct synproxy_stats {
struct synproxy_net {
	struct nf_conn			*tmpl;
	struct synproxy_stats __percpu	*stats;
	unsigned int			hook_ref4;
	unsigned int			hook_ref6;
};

extern unsigned int synproxy_net_id;
+39 −34
Original line number Diff line number Diff line
@@ -409,19 +409,56 @@ static unsigned int ipv4_synproxy_hook(void *priv,
	return NF_ACCEPT;
}

static struct nf_hook_ops ipv4_synproxy_ops[] __read_mostly = {
	{
		.hook		= ipv4_synproxy_hook,
		.pf		= NFPROTO_IPV4,
		.hooknum	= NF_INET_LOCAL_IN,
		.priority	= NF_IP_PRI_CONNTRACK_CONFIRM - 1,
	},
	{
		.hook		= ipv4_synproxy_hook,
		.pf		= NFPROTO_IPV4,
		.hooknum	= NF_INET_POST_ROUTING,
		.priority	= NF_IP_PRI_CONNTRACK_CONFIRM - 1,
	},
};

static int synproxy_tg4_check(const struct xt_tgchk_param *par)
{
	struct synproxy_net *snet = synproxy_pernet(par->net);
	const struct ipt_entry *e = par->entryinfo;
	int err;

	if (e->ip.proto != IPPROTO_TCP ||
	    e->ip.invflags & XT_INV_PROTO)
		return -EINVAL;

	return nf_ct_netns_get(par->net, par->family);
	err = nf_ct_netns_get(par->net, par->family);
	if (err)
		return err;

	if (snet->hook_ref4 == 0) {
		err = nf_register_net_hooks(par->net, ipv4_synproxy_ops,
					    ARRAY_SIZE(ipv4_synproxy_ops));
		if (err) {
			nf_ct_netns_put(par->net, par->family);
			return err;
		}
	}

	snet->hook_ref4++;
	return err;
}

static void synproxy_tg4_destroy(const struct xt_tgdtor_param *par)
{
	struct synproxy_net *snet = synproxy_pernet(par->net);

	snet->hook_ref4--;
	if (snet->hook_ref4 == 0)
		nf_unregister_net_hooks(par->net, ipv4_synproxy_ops,
					ARRAY_SIZE(ipv4_synproxy_ops));
	nf_ct_netns_put(par->net, par->family);
}

@@ -436,46 +473,14 @@ static struct xt_target synproxy_tg4_reg __read_mostly = {
	.me		= THIS_MODULE,
};

static struct nf_hook_ops ipv4_synproxy_ops[] __read_mostly = {
	{
		.hook		= ipv4_synproxy_hook,
		.pf		= NFPROTO_IPV4,
		.hooknum	= NF_INET_LOCAL_IN,
		.priority	= NF_IP_PRI_CONNTRACK_CONFIRM - 1,
	},
	{
		.hook		= ipv4_synproxy_hook,
		.pf		= NFPROTO_IPV4,
		.hooknum	= NF_INET_POST_ROUTING,
		.priority	= NF_IP_PRI_CONNTRACK_CONFIRM - 1,
	},
};

static int __init synproxy_tg4_init(void)
{
	int err;

	err = nf_register_hooks(ipv4_synproxy_ops,
				ARRAY_SIZE(ipv4_synproxy_ops));
	if (err < 0)
		goto err1;

	err = xt_register_target(&synproxy_tg4_reg);
	if (err < 0)
		goto err2;

	return 0;

err2:
	nf_unregister_hooks(ipv4_synproxy_ops, ARRAY_SIZE(ipv4_synproxy_ops));
err1:
	return err;
	return xt_register_target(&synproxy_tg4_reg);
}

static void __exit synproxy_tg4_exit(void)
{
	xt_unregister_target(&synproxy_tg4_reg);
	nf_unregister_hooks(ipv4_synproxy_ops, ARRAY_SIZE(ipv4_synproxy_ops));
}

module_init(synproxy_tg4_init);
+39 −34
Original line number Diff line number Diff line
@@ -430,20 +430,57 @@ static unsigned int ipv6_synproxy_hook(void *priv,
	return NF_ACCEPT;
}

static struct nf_hook_ops ipv6_synproxy_ops[] __read_mostly = {
	{
		.hook		= ipv6_synproxy_hook,
		.pf		= NFPROTO_IPV6,
		.hooknum	= NF_INET_LOCAL_IN,
		.priority	= NF_IP_PRI_CONNTRACK_CONFIRM - 1,
	},
	{
		.hook		= ipv6_synproxy_hook,
		.pf		= NFPROTO_IPV6,
		.hooknum	= NF_INET_POST_ROUTING,
		.priority	= NF_IP_PRI_CONNTRACK_CONFIRM - 1,
	},
};

static int synproxy_tg6_check(const struct xt_tgchk_param *par)
{
	struct synproxy_net *snet = synproxy_pernet(par->net);
	const struct ip6t_entry *e = par->entryinfo;
	int err;

	if (!(e->ipv6.flags & IP6T_F_PROTO) ||
	    e->ipv6.proto != IPPROTO_TCP ||
	    e->ipv6.invflags & XT_INV_PROTO)
		return -EINVAL;

	return nf_ct_netns_get(par->net, par->family);
	err = nf_ct_netns_get(par->net, par->family);
	if (err)
		return err;

	if (snet->hook_ref6 == 0) {
		err = nf_register_net_hooks(par->net, ipv6_synproxy_ops,
					    ARRAY_SIZE(ipv6_synproxy_ops));
		if (err) {
			nf_ct_netns_put(par->net, par->family);
			return err;
		}
	}

	snet->hook_ref6++;
	return err;
}

static void synproxy_tg6_destroy(const struct xt_tgdtor_param *par)
{
	struct synproxy_net *snet = synproxy_pernet(par->net);

	snet->hook_ref6--;
	if (snet->hook_ref6 == 0)
		nf_unregister_net_hooks(par->net, ipv6_synproxy_ops,
					ARRAY_SIZE(ipv6_synproxy_ops));
	nf_ct_netns_put(par->net, par->family);
}

@@ -458,46 +495,14 @@ static struct xt_target synproxy_tg6_reg __read_mostly = {
	.me		= THIS_MODULE,
};

static struct nf_hook_ops ipv6_synproxy_ops[] __read_mostly = {
	{
		.hook		= ipv6_synproxy_hook,
		.pf		= NFPROTO_IPV6,
		.hooknum	= NF_INET_LOCAL_IN,
		.priority	= NF_IP_PRI_CONNTRACK_CONFIRM - 1,
	},
	{
		.hook		= ipv6_synproxy_hook,
		.pf		= NFPROTO_IPV6,
		.hooknum	= NF_INET_POST_ROUTING,
		.priority	= NF_IP_PRI_CONNTRACK_CONFIRM - 1,
	},
};

static int __init synproxy_tg6_init(void)
{
	int err;

	err = nf_register_hooks(ipv6_synproxy_ops,
				ARRAY_SIZE(ipv6_synproxy_ops));
	if (err < 0)
		goto err1;

	err = xt_register_target(&synproxy_tg6_reg);
	if (err < 0)
		goto err2;

	return 0;

err2:
	nf_unregister_hooks(ipv6_synproxy_ops, ARRAY_SIZE(ipv6_synproxy_ops));
err1:
	return err;
	return xt_register_target(&synproxy_tg6_reg);
}

static void __exit synproxy_tg6_exit(void)
{
	xt_unregister_target(&synproxy_tg6_reg);
	nf_unregister_hooks(ipv6_synproxy_ops, ARRAY_SIZE(ipv6_synproxy_ops));
}

module_init(synproxy_tg6_init);