forked from mirrors/linux
		
	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: Richard Alpe <richard.alpe@ericsson.com>
Reviewed-by: Erik Hugne <erik.hugne@ericsson.com>
Reviewed-by: Jon Maloy <jon.maloy@ericsson.com>
Acked-by: Ying Xue <ying.xue@windriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
			
			
This commit is contained in:
		
							parent
							
								
									7cc76f5150
								
							
						
					
					
						commit
						0655f6a863
					
				
					 8 changed files with 320 additions and 3 deletions
				
			
		
							
								
								
									
										83
									
								
								include/uapi/linux/tipc_netlink.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								include/uapi/linux/tipc_netlink.h
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,83 @@ | |||
| /*
 | ||||
|  * 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 | ||||
|  | @ -1,7 +1,7 @@ | |||
| /*
 | ||||
|  * 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; | ||||
| } | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| /*
 | ||||
|  * 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); | ||||
|  |  | |||
|  | @ -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> | ||||
|  |  | |||
|  | @ -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; | ||||
| } | ||||
|  |  | |||
|  | @ -37,6 +37,7 @@ | |||
| #ifndef _TIPC_LINK_H | ||||
| #define _TIPC_LINK_H | ||||
| 
 | ||||
| #include <net/genetlink.h> | ||||
| #include "msg.h" | ||||
| #include "node.h" | ||||
| 
 | ||||
|  | @ -239,6 +240,8 @@ void tipc_link_set_queue_limits(struct tipc_link *l_ptr, u32 window); | |||
| void tipc_link_retransmit(struct tipc_link *l_ptr, | ||||
| 			  struct sk_buff *start, u32 retransmits); | ||||
| 
 | ||||
| int tipc_nl_parse_link_prop(struct nlattr *prop, struct nlattr *props[]); | ||||
| 
 | ||||
| /*
 | ||||
|  * Link sequence number manipulation routines (uses modulo 2**16 arithmetic) | ||||
|  */ | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| /*
 | ||||
|  * net/tipc/netlink.c: TIPC configuration handling | ||||
|  * | ||||
|  * Copyright (c) 2005-2006, Ericsson AB | ||||
|  * Copyright (c) 2005-2006, 2014, Ericsson AB | ||||
|  * Copyright (c) 2005-2007, Wind River Systems | ||||
|  * All rights reserved. | ||||
|  * | ||||
|  | @ -36,6 +36,7 @@ | |||
| 
 | ||||
| #include "core.h" | ||||
| #include "config.h" | ||||
| #include "bearer.h" | ||||
| #include <net/genetlink.h> | ||||
| 
 | ||||
| static int handle_cmd(struct sk_buff *skb, struct genl_info *info) | ||||
|  | @ -68,6 +69,12 @@ static int handle_cmd(struct sk_buff *skb, struct genl_info *info) | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static const struct nla_policy tipc_nl_policy[TIPC_NLA_MAX + 1] = { | ||||
| 	[TIPC_NLA_UNSPEC]	= { .type = NLA_UNSPEC, }, | ||||
| 	[TIPC_NLA_BEARER]	= { .type = NLA_NESTED, }, | ||||
| }; | ||||
| 
 | ||||
| /* Legacy ASCII API */ | ||||
| static struct genl_family tipc_genl_family = { | ||||
| 	.id		= GENL_ID_GENERATE, | ||||
| 	.name		= TIPC_GENL_NAME, | ||||
|  | @ -76,6 +83,7 @@ static struct genl_family tipc_genl_family = { | |||
| 	.maxattr	= 0, | ||||
| }; | ||||
| 
 | ||||
| /* Legacy ASCII API */ | ||||
| static struct genl_ops tipc_genl_ops[] = { | ||||
| 	{ | ||||
| 		.cmd		= TIPC_GENL_CMD, | ||||
|  | @ -83,11 +91,42 @@ static struct genl_ops tipc_genl_ops[] = { | |||
| 	}, | ||||
| }; | ||||
| 
 | ||||
| /* Users of the legacy API (tipc-config) can't handle that we add operations,
 | ||||
|  * so we have a separate genl handling for the new API. | ||||
|  */ | ||||
| struct genl_family tipc_genl_v2_family = { | ||||
| 	.id		= GENL_ID_GENERATE, | ||||
| 	.name		= TIPC_GENL_V2_NAME, | ||||
| 	.version	= TIPC_GENL_V2_VERSION, | ||||
| 	.hdrsize	= 0, | ||||
| 	.maxattr	= TIPC_NLA_MAX, | ||||
| }; | ||||
| 
 | ||||
| static const struct genl_ops tipc_genl_v2_ops[] = { | ||||
| 	{ | ||||
| 		.cmd	= TIPC_NL_BEARER_DISABLE, | ||||
| 		.doit	= tipc_nl_bearer_disable, | ||||
| 		.policy = tipc_nl_policy, | ||||
| 	}, | ||||
| 	{ | ||||
| 		.cmd	= TIPC_NL_BEARER_ENABLE, | ||||
| 		.doit	= tipc_nl_bearer_enable, | ||||
| 		.policy = tipc_nl_policy, | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
| int tipc_netlink_start(void) | ||||
| { | ||||
| 	int res; | ||||
| 
 | ||||
| 	res = genl_register_family_with_ops(&tipc_genl_family, tipc_genl_ops); | ||||
| 	if (res) { | ||||
| 		pr_err("Failed to register legacy interface\n"); | ||||
| 		return res; | ||||
| 	} | ||||
| 
 | ||||
| 	res = genl_register_family_with_ops(&tipc_genl_v2_family, | ||||
| 					    tipc_genl_v2_ops); | ||||
| 	if (res) { | ||||
| 		pr_err("Failed to register netlink interface\n"); | ||||
| 		return res; | ||||
|  | @ -98,4 +137,5 @@ int tipc_netlink_start(void) | |||
| void tipc_netlink_stop(void) | ||||
| { | ||||
| 	genl_unregister_family(&tipc_genl_family); | ||||
| 	genl_unregister_family(&tipc_genl_v2_family); | ||||
| } | ||||
|  |  | |||
							
								
								
									
										41
									
								
								net/tipc/netlink.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								net/tipc/netlink.h
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,41 @@ | |||
| /*
 | ||||
|  * net/tipc/netlink.h: Include file for TIPC netlink code | ||||
|  * | ||||
|  * 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 _TIPC_NETLINK_H | ||||
| #define _TIPC_NETLINK_H | ||||
| 
 | ||||
| extern struct genl_family tipc_genl_v2_family; | ||||
| 
 | ||||
| #endif | ||||
		Loading…
	
		Reference in a new issue
	
	 Richard Alpe
						Richard Alpe