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

Commit 0655f6a8 authored by Richard Alpe's avatar Richard Alpe Committed by David S. Miller
Browse files

tipc: add bearer disable/enable to new netlink api



A new netlink API for tipc that can disable or enable a tipc bearer.

The new API is separated from the old API because of a bug in the
user space client (tipc-config). The problem is that older versions
of tipc-config has a very low receive limit and adding commands to
the legacy genl_opts struct causes the ctrl_getfamily() response
message to grow, subsequently breaking the tool.

The new API utilizes netlink policies for input validation. Where the
top-level netlink attributes are tipc-logical entities, like bearer.
The top level entities then contain nested attributes. In this case
a name, nested link properties and a domain.

Netlink commands implemented in this patch:
TIPC_NL_BEARER_ENABLE
TIPC_NL_BEARER_DISABLE

Netlink logical layout of bearer enable message:
-> bearer
    -> name
    [ -> domain ]
    [
    -> properties
        -> priority
    ]

Netlink logical layout of bearer disable message:
-> bearer
    -> name

Signed-off-by: default avatarRichard Alpe <richard.alpe@ericsson.com>
Reviewed-by: default avatarErik Hugne <erik.hugne@ericsson.com>
Reviewed-by: default avatarJon Maloy <jon.maloy@ericsson.com>
Acked-by: default avatarYing Xue <ying.xue@windriver.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7cc76f51
Loading
Loading
Loading
Loading
+83 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2014, Ericsson AB
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the names of the copyright holders nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 * Alternatively, this software may be distributed under the terms of the
 * GNU General Public License ("GPL") version 2 as published by the Free
 * Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _LINUX_TIPC_NETLINK_H_
#define _LINUX_TIPC_NETLINK_H_

#define TIPC_GENL_V2_NAME      "TIPCv2"
#define TIPC_GENL_V2_VERSION   0x1

/* Netlink commands */
enum {
	TIPC_NL_UNSPEC,
	TIPC_NL_LEGACY,
	TIPC_NL_BEARER_DISABLE,
	TIPC_NL_BEARER_ENABLE,

	__TIPC_NL_CMD_MAX,
	TIPC_NL_CMD_MAX = __TIPC_NL_CMD_MAX - 1
};

/* Top level netlink attributes */
enum {
	TIPC_NLA_UNSPEC,
	TIPC_NLA_BEARER,		/* nest */

	__TIPC_NLA_MAX,
	TIPC_NLA_MAX = __TIPC_NLA_MAX - 1
};

/* Bearer info */
enum {
	TIPC_NLA_BEARER_UNSPEC,
	TIPC_NLA_BEARER_NAME,		/* string */
	TIPC_NLA_BEARER_PROP,		/* nest */
	TIPC_NLA_BEARER_DOMAIN,		/* u32 */

	__TIPC_NLA_BEARER_MAX,
	TIPC_NLA_BEARER_MAX = __TIPC_NLA_BEARER_MAX - 1
};

/* Nest, link propreties. Valid for link, media and bearer */
enum {
	TIPC_NLA_PROP_UNSPEC,

	TIPC_NLA_PROP_PRIO,		/* u32 */
	TIPC_NLA_PROP_TOL,		/* u32 */
	TIPC_NLA_PROP_WIN,		/* u32 */

	__TIPC_NLA_PROP_MAX,
	TIPC_NLA_PROP_MAX = __TIPC_NLA_PROP_MAX - 1
};

#endif
+98 −1
Original line number Diff line number Diff line
/*
 * net/tipc/bearer.c: TIPC bearer code
 *
 * Copyright (c) 1996-2006, 2013, Ericsson AB
 * Copyright (c) 1996-2006, 2013-2014, Ericsson AB
 * Copyright (c) 2004-2006, 2010-2013, Wind River Systems
 * All rights reserved.
 *
@@ -37,6 +37,7 @@
#include "core.h"
#include "config.h"
#include "bearer.h"
#include "link.h"
#include "discover.h"

#define MAX_ADDR_STR 60
@@ -49,6 +50,17 @@ static struct tipc_media * const media_info_array[] = {
	NULL
};

static const struct nla_policy
tipc_nl_bearer_policy[TIPC_NLA_BEARER_MAX + 1]	= {
	[TIPC_NLA_BEARER_UNSPEC]		= { .type = NLA_UNSPEC },
	[TIPC_NLA_BEARER_NAME] = {
		.type = NLA_STRING,
		.len = TIPC_MAX_BEARER_NAME
	},
	[TIPC_NLA_BEARER_PROP]			= { .type = NLA_NESTED },
	[TIPC_NLA_BEARER_DOMAIN]		= { .type = NLA_U32 }
};

struct tipc_bearer __rcu *bearer_list[MAX_BEARERS + 1];

static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down);
@@ -627,3 +639,88 @@ void tipc_bearer_stop(void)
		}
	}
}

int tipc_nl_bearer_disable(struct sk_buff *skb, struct genl_info *info)
{
	int err;
	char *name;
	struct tipc_bearer *bearer;
	struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];

	if (!info->attrs[TIPC_NLA_BEARER])
		return -EINVAL;

	err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
			       info->attrs[TIPC_NLA_BEARER],
			       tipc_nl_bearer_policy);
	if (err)
		return err;

	if (!attrs[TIPC_NLA_BEARER_NAME])
		return -EINVAL;

	name = nla_data(attrs[TIPC_NLA_BEARER_NAME]);

	rtnl_lock();
	bearer = tipc_bearer_find(name);
	if (!bearer) {
		rtnl_unlock();
		return -EINVAL;
	}

	bearer_disable(bearer, false);
	rtnl_unlock();

	return 0;
}

int tipc_nl_bearer_enable(struct sk_buff *skb, struct genl_info *info)
{
	int err;
	char *bearer;
	struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
	u32 domain;
	u32 prio;

	prio = TIPC_MEDIA_LINK_PRI;
	domain = tipc_own_addr & TIPC_CLUSTER_MASK;

	if (!info->attrs[TIPC_NLA_BEARER])
		return -EINVAL;

	err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
			       info->attrs[TIPC_NLA_BEARER],
			       tipc_nl_bearer_policy);
	if (err)
		return err;

	if (!attrs[TIPC_NLA_BEARER_NAME])
		return -EINVAL;

	bearer = nla_data(attrs[TIPC_NLA_BEARER_NAME]);

	if (attrs[TIPC_NLA_BEARER_DOMAIN])
		domain = nla_get_u32(attrs[TIPC_NLA_BEARER_DOMAIN]);

	if (attrs[TIPC_NLA_BEARER_PROP]) {
		struct nlattr *props[TIPC_NLA_PROP_MAX + 1];

		err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_BEARER_PROP],
					      props);
		if (err)
			return err;

		if (props[TIPC_NLA_PROP_PRIO])
			prio = nla_get_u32(props[TIPC_NLA_PROP_PRIO]);
	}

	rtnl_lock();
	err = tipc_enable_bearer(bearer, domain, prio);
	if (err) {
		rtnl_unlock();
		return err;
	}
	rtnl_unlock();

	return 0;
}
+6 −1
Original line number Diff line number Diff line
/*
 * net/tipc/bearer.h: Include file for TIPC bearer code
 *
 * Copyright (c) 1996-2006, 2013, Ericsson AB
 * Copyright (c) 1996-2006, 2013-2014, Ericsson AB
 * Copyright (c) 2005, 2010-2011, Wind River Systems
 * All rights reserved.
 *
@@ -38,6 +38,8 @@
#define _TIPC_BEARER_H

#include "bcast.h"
#include "netlink.h"
#include <net/genetlink.h>

#define MAX_BEARERS	2
#define MAX_MEDIA	2
@@ -176,6 +178,9 @@ extern struct tipc_media eth_media_info;
extern struct tipc_media ib_media_info;
#endif

int tipc_nl_bearer_disable(struct sk_buff *skb, struct genl_info *info);
int tipc_nl_bearer_enable(struct sk_buff *skb, struct genl_info *info);

int tipc_media_set_priority(const char *name, u32 new_value);
int tipc_media_set_window(const char *name, u32 new_value);
void tipc_media_addr_printf(char *buf, int len, struct tipc_media_addr *a);
+1 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@

#include <linux/tipc.h>
#include <linux/tipc_config.h>
#include <linux/tipc_netlink.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/errno.h>
+47 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@
#include "name_distr.h"
#include "discover.h"
#include "config.h"
#include "netlink.h"

#include <linux/pkt_sched.h>

@@ -50,6 +51,14 @@ static const char *link_co_err = "Link changeover error, ";
static const char *link_rst_msg = "Resetting link ";
static const char *link_unk_evt = "Unknown link event ";

/* Properties valid for media, bearar and link */
static const struct nla_policy tipc_nl_prop_policy[TIPC_NLA_PROP_MAX + 1] = {
	[TIPC_NLA_PROP_UNSPEC]		= { .type = NLA_UNSPEC },
	[TIPC_NLA_PROP_PRIO]		= { .type = NLA_U32 },
	[TIPC_NLA_PROP_TOL]		= { .type = NLA_U32 },
	[TIPC_NLA_PROP_WIN]		= { .type = NLA_U32 }
};

/*
 * Out-of-range value for link session numbers
 */
@@ -2376,3 +2385,41 @@ static void link_print(struct tipc_link *l_ptr, const char *str)
	else
		pr_cont("\n");
}

/* Parse and validate nested (link) properties valid for media, bearer and link
 */
int tipc_nl_parse_link_prop(struct nlattr *prop, struct nlattr *props[])
{
	int err;

	err = nla_parse_nested(props, TIPC_NLA_PROP_MAX, prop,
			       tipc_nl_prop_policy);
	if (err)
		return err;

	if (props[TIPC_NLA_PROP_PRIO]) {
		u32 prio;

		prio = nla_get_u32(props[TIPC_NLA_PROP_PRIO]);
		if (prio > TIPC_MAX_LINK_PRI)
			return -EINVAL;
	}

	if (props[TIPC_NLA_PROP_TOL]) {
		u32 tol;

		tol = nla_get_u32(props[TIPC_NLA_PROP_TOL]);
		if ((tol < TIPC_MIN_LINK_TOL) || (tol > TIPC_MAX_LINK_TOL))
			return -EINVAL;
	}

	if (props[TIPC_NLA_PROP_WIN]) {
		u32 win;

		win = nla_get_u32(props[TIPC_NLA_PROP_WIN]);
		if ((win < TIPC_MIN_LINK_WIN) || (win > TIPC_MAX_LINK_WIN))
			return -EINVAL;
	}

	return 0;
}
Loading