Commit 024f35c5 authored by David S. Miller's avatar David S. Miller
Browse files


Steffen Klassert says:

====================
pull request (net): ipsec 2015-12-22

Just one patch to fix dst_entries_init with multiple namespaces.
From Dan Streetman.

Please pull or let me know if there are problems.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents e459dfee a8a572a6
Loading
Loading
Loading
Loading
+37 −9
Original line number Diff line number Diff line
@@ -259,7 +259,7 @@ static void xfrm4_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
	xfrm_dst_ifdown(dst, dev);
}

static struct dst_ops xfrm4_dst_ops = {
static struct dst_ops xfrm4_dst_ops_template = {
	.family =		AF_INET,
	.gc =			xfrm4_garbage_collect,
	.update_pmtu =		xfrm4_update_pmtu,
@@ -273,7 +273,7 @@ static struct dst_ops xfrm4_dst_ops = {

static struct xfrm_policy_afinfo xfrm4_policy_afinfo = {
	.family = 		AF_INET,
	.dst_ops =		&xfrm4_dst_ops,
	.dst_ops =		&xfrm4_dst_ops_template,
	.dst_lookup =		xfrm4_dst_lookup,
	.get_saddr =		xfrm4_get_saddr,
	.decode_session =	_decode_session4,
@@ -295,7 +295,7 @@ static struct ctl_table xfrm4_policy_table[] = {
	{ }
};

static int __net_init xfrm4_net_init(struct net *net)
static int __net_init xfrm4_net_sysctl_init(struct net *net)
{
	struct ctl_table *table;
	struct ctl_table_header *hdr;
@@ -323,7 +323,7 @@ err_alloc:
	return -ENOMEM;
}

static void __net_exit xfrm4_net_exit(struct net *net)
static void __net_exit xfrm4_net_sysctl_exit(struct net *net)
{
	struct ctl_table *table;

@@ -335,12 +335,44 @@ static void __net_exit xfrm4_net_exit(struct net *net)
	if (!net_eq(net, &init_net))
		kfree(table);
}
#else /* CONFIG_SYSCTL */
static int inline xfrm4_net_sysctl_init(struct net *net)
{
	return 0;
}

static void inline xfrm4_net_sysctl_exit(struct net *net)
{
}
#endif

static int __net_init xfrm4_net_init(struct net *net)
{
	int ret;

	memcpy(&net->xfrm.xfrm4_dst_ops, &xfrm4_dst_ops_template,
	       sizeof(xfrm4_dst_ops_template));
	ret = dst_entries_init(&net->xfrm.xfrm4_dst_ops);
	if (ret)
		return ret;

	ret = xfrm4_net_sysctl_init(net);
	if (ret)
		dst_entries_destroy(&net->xfrm.xfrm4_dst_ops);

	return ret;
}

static void __net_exit xfrm4_net_exit(struct net *net)
{
	xfrm4_net_sysctl_exit(net);
	dst_entries_destroy(&net->xfrm.xfrm4_dst_ops);
}

static struct pernet_operations __net_initdata xfrm4_net_ops = {
	.init	= xfrm4_net_init,
	.exit	= xfrm4_net_exit,
};
#endif

static void __init xfrm4_policy_init(void)
{
@@ -349,13 +381,9 @@ static void __init xfrm4_policy_init(void)

void __init xfrm4_init(void)
{
	dst_entries_init(&xfrm4_dst_ops);

	xfrm4_state_init();
	xfrm4_policy_init();
	xfrm4_protocol_init();
#ifdef CONFIG_SYSCTL
	register_pernet_subsys(&xfrm4_net_ops);
#endif
}
+38 −15
Original line number Diff line number Diff line
@@ -279,7 +279,7 @@ static void xfrm6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
	xfrm_dst_ifdown(dst, dev);
}

static struct dst_ops xfrm6_dst_ops = {
static struct dst_ops xfrm6_dst_ops_template = {
	.family =		AF_INET6,
	.gc =			xfrm6_garbage_collect,
	.update_pmtu =		xfrm6_update_pmtu,
@@ -293,7 +293,7 @@ static struct dst_ops xfrm6_dst_ops = {

static struct xfrm_policy_afinfo xfrm6_policy_afinfo = {
	.family =		AF_INET6,
	.dst_ops =		&xfrm6_dst_ops,
	.dst_ops =		&xfrm6_dst_ops_template,
	.dst_lookup =		xfrm6_dst_lookup,
	.get_saddr =		xfrm6_get_saddr,
	.decode_session =	_decode_session6,
@@ -325,7 +325,7 @@ static struct ctl_table xfrm6_policy_table[] = {
	{ }
};

static int __net_init xfrm6_net_init(struct net *net)
static int __net_init xfrm6_net_sysctl_init(struct net *net)
{
	struct ctl_table *table;
	struct ctl_table_header *hdr;
@@ -353,7 +353,7 @@ err_alloc:
	return -ENOMEM;
}

static void __net_exit xfrm6_net_exit(struct net *net)
static void __net_exit xfrm6_net_sysctl_exit(struct net *net)
{
	struct ctl_table *table;

@@ -365,24 +365,52 @@ static void __net_exit xfrm6_net_exit(struct net *net)
	if (!net_eq(net, &init_net))
		kfree(table);
}
#else /* CONFIG_SYSCTL */
static int inline xfrm6_net_sysctl_init(struct net *net)
{
	return 0;
}

static void inline xfrm6_net_sysctl_exit(struct net *net)
{
}
#endif

static int __net_init xfrm6_net_init(struct net *net)
{
	int ret;

	memcpy(&net->xfrm.xfrm6_dst_ops, &xfrm6_dst_ops_template,
	       sizeof(xfrm6_dst_ops_template));
	ret = dst_entries_init(&net->xfrm.xfrm6_dst_ops);
	if (ret)
		return ret;

	ret = xfrm6_net_sysctl_init(net);
	if (ret)
		dst_entries_destroy(&net->xfrm.xfrm6_dst_ops);

	return ret;
}

static void __net_exit xfrm6_net_exit(struct net *net)
{
	xfrm6_net_sysctl_exit(net);
	dst_entries_destroy(&net->xfrm.xfrm6_dst_ops);
}

static struct pernet_operations xfrm6_net_ops = {
	.init	= xfrm6_net_init,
	.exit	= xfrm6_net_exit,
};
#endif

int __init xfrm6_init(void)
{
	int ret;

	dst_entries_init(&xfrm6_dst_ops);

	ret = xfrm6_policy_init();
	if (ret) {
		dst_entries_destroy(&xfrm6_dst_ops);
	if (ret)
		goto out;
	}
	ret = xfrm6_state_init();
	if (ret)
		goto out_policy;
@@ -391,9 +419,7 @@ int __init xfrm6_init(void)
	if (ret)
		goto out_state;

#ifdef CONFIG_SYSCTL
	register_pernet_subsys(&xfrm6_net_ops);
#endif
out:
	return ret;
out_state:
@@ -405,11 +431,8 @@ out_policy:

void xfrm6_fini(void)
{
#ifdef CONFIG_SYSCTL
	unregister_pernet_subsys(&xfrm6_net_ops);
#endif
	xfrm6_protocol_fini();
	xfrm6_policy_fini();
	xfrm6_state_fini();
	dst_entries_destroy(&xfrm6_dst_ops);
}
+0 −38
Original line number Diff line number Diff line
@@ -2826,7 +2826,6 @@ static struct neighbour *xfrm_neigh_lookup(const struct dst_entry *dst,

int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
{
	struct net *net;
	int err = 0;
	if (unlikely(afinfo == NULL))
		return -EINVAL;
@@ -2857,26 +2856,6 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
	}
	spin_unlock(&xfrm_policy_afinfo_lock);

	rtnl_lock();
	for_each_net(net) {
		struct dst_ops *xfrm_dst_ops;

		switch (afinfo->family) {
		case AF_INET:
			xfrm_dst_ops = &net->xfrm.xfrm4_dst_ops;
			break;
#if IS_ENABLED(CONFIG_IPV6)
		case AF_INET6:
			xfrm_dst_ops = &net->xfrm.xfrm6_dst_ops;
			break;
#endif
		default:
			BUG();
		}
		*xfrm_dst_ops = *afinfo->dst_ops;
	}
	rtnl_unlock();

	return err;
}
EXPORT_SYMBOL(xfrm_policy_register_afinfo);
@@ -2912,22 +2891,6 @@ int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo)
}
EXPORT_SYMBOL(xfrm_policy_unregister_afinfo);

static void __net_init xfrm_dst_ops_init(struct net *net)
{
	struct xfrm_policy_afinfo *afinfo;

	rcu_read_lock();
	afinfo = rcu_dereference(xfrm_policy_afinfo[AF_INET]);
	if (afinfo)
		net->xfrm.xfrm4_dst_ops = *afinfo->dst_ops;
#if IS_ENABLED(CONFIG_IPV6)
	afinfo = rcu_dereference(xfrm_policy_afinfo[AF_INET6]);
	if (afinfo)
		net->xfrm.xfrm6_dst_ops = *afinfo->dst_ops;
#endif
	rcu_read_unlock();
}

static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
{
	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
@@ -3076,7 +3039,6 @@ static int __net_init xfrm_net_init(struct net *net)
	rv = xfrm_policy_init(net);
	if (rv < 0)
		goto out_policy;
	xfrm_dst_ops_init(net);
	rv = xfrm_sysctl_init(net);
	if (rv < 0)
		goto out_sysctl;