Commit 1113ebbc authored by Nikolay Aleksandrov's avatar Nikolay Aleksandrov Committed by David S. Miller
Browse files

net: ipmr: move the tbl id check in ipmr_new_table



Move the table id check in ipmr_new_table and make it return error
pointer. We need this change for the upcoming netlink table manipulation
support in order to avoid code duplication and a race condition.

Signed-off-by: default avatarNikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 930d3142
Loading
Loading
Loading
Loading
+17 −11
Original line number Diff line number Diff line
@@ -252,8 +252,8 @@ static int __net_init ipmr_rules_init(struct net *net)
	INIT_LIST_HEAD(&net->ipv4.mr_tables);

	mrt = ipmr_new_table(net, RT_TABLE_DEFAULT);
	if (!mrt) {
		err = -ENOMEM;
	if (IS_ERR(mrt)) {
		err = PTR_ERR(mrt);
		goto err1;
	}

@@ -301,8 +301,13 @@ static int ipmr_fib_lookup(struct net *net, struct flowi4 *flp4,

static int __net_init ipmr_rules_init(struct net *net)
{
	net->ipv4.mrt = ipmr_new_table(net, RT_TABLE_DEFAULT);
	return net->ipv4.mrt ? 0 : -ENOMEM;
	struct mr_table *mrt;

	mrt = ipmr_new_table(net, RT_TABLE_DEFAULT);
	if (IS_ERR(mrt))
		return PTR_ERR(mrt);
	net->ipv4.mrt = mrt;
	return 0;
}

static void __net_exit ipmr_rules_exit(struct net *net)
@@ -319,13 +324,17 @@ static struct mr_table *ipmr_new_table(struct net *net, u32 id)
	struct mr_table *mrt;
	unsigned int i;

	/* "pimreg%u" should not exceed 16 bytes (IFNAMSIZ) */
	if (id != RT_TABLE_DEFAULT && id >= 1000000000)
		return ERR_PTR(-EINVAL);

	mrt = ipmr_get_table(net, id);
	if (mrt)
		return mrt;

	mrt = kzalloc(sizeof(*mrt), GFP_KERNEL);
	if (!mrt)
		return NULL;
		return ERR_PTR(-ENOMEM);
	write_pnet(&mrt->net, net);
	mrt->id = id;

@@ -1407,17 +1416,14 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi
		if (get_user(v, (u32 __user *)optval))
			return -EFAULT;

		/* "pimreg%u" should not exceed 16 bytes (IFNAMSIZ) */
		if (v != RT_TABLE_DEFAULT && v >= 1000000000)
			return -EINVAL;

		rtnl_lock();
		ret = 0;
		if (sk == rtnl_dereference(mrt->mroute_sk)) {
			ret = -EBUSY;
		} else {
			if (!ipmr_new_table(net, v))
				ret = -ENOMEM;
			mrt = ipmr_new_table(net, v);
			if (IS_ERR(mrt))
				ret = PTR_ERR(mrt);
			else
				raw_sk(sk)->ipmr_table = v;
		}