xref: /openbmc/linux/net/netlabel/netlabel_mgmt.c (revision 60063497)
1d15c345fSPaul Moore /*
2d15c345fSPaul Moore  * NetLabel Management Support
3d15c345fSPaul Moore  *
4d15c345fSPaul Moore  * This file defines the management functions for the NetLabel system.  The
5d15c345fSPaul Moore  * NetLabel system manages static and dynamic label mappings for network
6d15c345fSPaul Moore  * protocols such as CIPSO and RIPSO.
7d15c345fSPaul Moore  *
8d15c345fSPaul Moore  * Author: Paul Moore <paul.moore@hp.com>
9d15c345fSPaul Moore  *
10d15c345fSPaul Moore  */
11d15c345fSPaul Moore 
12d15c345fSPaul Moore /*
1363c41688SPaul Moore  * (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008
14d15c345fSPaul Moore  *
15d15c345fSPaul Moore  * This program is free software;  you can redistribute it and/or modify
16d15c345fSPaul Moore  * it under the terms of the GNU General Public License as published by
17d15c345fSPaul Moore  * the Free Software Foundation; either version 2 of the License, or
18d15c345fSPaul Moore  * (at your option) any later version.
19d15c345fSPaul Moore  *
20d15c345fSPaul Moore  * This program is distributed in the hope that it will be useful,
21d15c345fSPaul Moore  * but WITHOUT ANY WARRANTY;  without even the implied warranty of
22d15c345fSPaul Moore  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
23d15c345fSPaul Moore  * the GNU General Public License for more details.
24d15c345fSPaul Moore  *
25d15c345fSPaul Moore  * You should have received a copy of the GNU General Public License
26d15c345fSPaul Moore  * along with this program;  if not, write to the Free Software
27d15c345fSPaul Moore  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28d15c345fSPaul Moore  *
29d15c345fSPaul Moore  */
30d15c345fSPaul Moore 
31d15c345fSPaul Moore #include <linux/types.h>
32d15c345fSPaul Moore #include <linux/socket.h>
33d15c345fSPaul Moore #include <linux/string.h>
34d15c345fSPaul Moore #include <linux/skbuff.h>
3563c41688SPaul Moore #include <linux/in.h>
3663c41688SPaul Moore #include <linux/in6.h>
375a0e3ad6STejun Heo #include <linux/slab.h>
38d15c345fSPaul Moore #include <net/sock.h>
39d15c345fSPaul Moore #include <net/netlink.h>
40d15c345fSPaul Moore #include <net/genetlink.h>
4163c41688SPaul Moore #include <net/ip.h>
4263c41688SPaul Moore #include <net/ipv6.h>
43d15c345fSPaul Moore #include <net/netlabel.h>
44d15c345fSPaul Moore #include <net/cipso_ipv4.h>
4560063497SArun Sharma #include <linux/atomic.h>
46d15c345fSPaul Moore 
47d15c345fSPaul Moore #include "netlabel_domainhash.h"
48d15c345fSPaul Moore #include "netlabel_user.h"
49d15c345fSPaul Moore #include "netlabel_mgmt.h"
50d15c345fSPaul Moore 
51c783f1ceSPaul Moore /* NetLabel configured protocol counter */
52c783f1ceSPaul Moore atomic_t netlabel_mgmt_protocount = ATOMIC_INIT(0);
5323bcdc1aSPaul Moore 
54fd385855SPaul Moore /* Argument struct for netlbl_domhsh_walk() */
55fd385855SPaul Moore struct netlbl_domhsh_walk_arg {
56fd385855SPaul Moore 	struct netlink_callback *nl_cb;
57fd385855SPaul Moore 	struct sk_buff *skb;
58fd385855SPaul Moore 	u32 seq;
59fd385855SPaul Moore };
60fd385855SPaul Moore 
61d15c345fSPaul Moore /* NetLabel Generic NETLINK CIPSOv4 family */
62d15c345fSPaul Moore static struct genl_family netlbl_mgmt_gnl_family = {
63d15c345fSPaul Moore 	.id = GENL_ID_GENERATE,
64d15c345fSPaul Moore 	.hdrsize = 0,
65d15c345fSPaul Moore 	.name = NETLBL_NLTYPE_MGMT_NAME,
66d15c345fSPaul Moore 	.version = NETLBL_PROTO_VERSION,
67fd385855SPaul Moore 	.maxattr = NLBL_MGMT_A_MAX,
68d15c345fSPaul Moore };
69d15c345fSPaul Moore 
70fd385855SPaul Moore /* NetLabel Netlink attribute policy */
71ef7c79edSPatrick McHardy static const struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = {
72fd385855SPaul Moore 	[NLBL_MGMT_A_DOMAIN] = { .type = NLA_NUL_STRING },
73fd385855SPaul Moore 	[NLBL_MGMT_A_PROTOCOL] = { .type = NLA_U32 },
74fd385855SPaul Moore 	[NLBL_MGMT_A_VERSION] = { .type = NLA_U32 },
75fd385855SPaul Moore 	[NLBL_MGMT_A_CV4DOI] = { .type = NLA_U32 },
76fd385855SPaul Moore };
77d15c345fSPaul Moore 
78d15c345fSPaul Moore /*
7963c41688SPaul Moore  * Helper Functions
8063c41688SPaul Moore  */
8163c41688SPaul Moore 
8263c41688SPaul Moore /**
8363c41688SPaul Moore  * netlbl_mgmt_add - Handle an ADD message
8463c41688SPaul Moore  * @info: the Generic NETLINK info block
8563c41688SPaul Moore  * @audit_info: NetLabel audit information
8663c41688SPaul Moore  *
8763c41688SPaul Moore  * Description:
8863c41688SPaul Moore  * Helper function for the ADD and ADDDEF messages to add the domain mappings
8963c41688SPaul Moore  * from the message to the hash table.  See netlabel.h for a description of the
9063c41688SPaul Moore  * message format.  Returns zero on success, negative values on failure.
9163c41688SPaul Moore  *
9263c41688SPaul Moore  */
9363c41688SPaul Moore static int netlbl_mgmt_add_common(struct genl_info *info,
9463c41688SPaul Moore 				  struct netlbl_audit *audit_info)
9563c41688SPaul Moore {
9663c41688SPaul Moore 	int ret_val = -EINVAL;
9763c41688SPaul Moore 	struct netlbl_dom_map *entry = NULL;
9863c41688SPaul Moore 	struct netlbl_domaddr_map *addrmap = NULL;
9963c41688SPaul Moore 	struct cipso_v4_doi *cipsov4 = NULL;
10063c41688SPaul Moore 	u32 tmp_val;
10163c41688SPaul Moore 
10263c41688SPaul Moore 	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
10363c41688SPaul Moore 	if (entry == NULL) {
10463c41688SPaul Moore 		ret_val = -ENOMEM;
10563c41688SPaul Moore 		goto add_failure;
10663c41688SPaul Moore 	}
10763c41688SPaul Moore 	entry->type = nla_get_u32(info->attrs[NLBL_MGMT_A_PROTOCOL]);
10863c41688SPaul Moore 	if (info->attrs[NLBL_MGMT_A_DOMAIN]) {
10963c41688SPaul Moore 		size_t tmp_size = nla_len(info->attrs[NLBL_MGMT_A_DOMAIN]);
11063c41688SPaul Moore 		entry->domain = kmalloc(tmp_size, GFP_KERNEL);
11163c41688SPaul Moore 		if (entry->domain == NULL) {
11263c41688SPaul Moore 			ret_val = -ENOMEM;
11363c41688SPaul Moore 			goto add_failure;
11463c41688SPaul Moore 		}
11563c41688SPaul Moore 		nla_strlcpy(entry->domain,
11663c41688SPaul Moore 			    info->attrs[NLBL_MGMT_A_DOMAIN], tmp_size);
11763c41688SPaul Moore 	}
11863c41688SPaul Moore 
11963c41688SPaul Moore 	/* NOTE: internally we allow/use a entry->type value of
12063c41688SPaul Moore 	 *       NETLBL_NLTYPE_ADDRSELECT but we don't currently allow users
12163c41688SPaul Moore 	 *       to pass that as a protocol value because we need to know the
12263c41688SPaul Moore 	 *       "real" protocol */
12363c41688SPaul Moore 
12463c41688SPaul Moore 	switch (entry->type) {
12563c41688SPaul Moore 	case NETLBL_NLTYPE_UNLABELED:
12663c41688SPaul Moore 		break;
12763c41688SPaul Moore 	case NETLBL_NLTYPE_CIPSOV4:
12863c41688SPaul Moore 		if (!info->attrs[NLBL_MGMT_A_CV4DOI])
12963c41688SPaul Moore 			goto add_failure;
13063c41688SPaul Moore 
13163c41688SPaul Moore 		tmp_val = nla_get_u32(info->attrs[NLBL_MGMT_A_CV4DOI]);
13263c41688SPaul Moore 		cipsov4 = cipso_v4_doi_getdef(tmp_val);
13363c41688SPaul Moore 		if (cipsov4 == NULL)
13463c41688SPaul Moore 			goto add_failure;
13563c41688SPaul Moore 		entry->type_def.cipsov4 = cipsov4;
13663c41688SPaul Moore 		break;
13763c41688SPaul Moore 	default:
13863c41688SPaul Moore 		goto add_failure;
13963c41688SPaul Moore 	}
14063c41688SPaul Moore 
14163c41688SPaul Moore 	if (info->attrs[NLBL_MGMT_A_IPV4ADDR]) {
14263c41688SPaul Moore 		struct in_addr *addr;
14363c41688SPaul Moore 		struct in_addr *mask;
14463c41688SPaul Moore 		struct netlbl_domaddr4_map *map;
14563c41688SPaul Moore 
14663c41688SPaul Moore 		addrmap = kzalloc(sizeof(*addrmap), GFP_KERNEL);
14763c41688SPaul Moore 		if (addrmap == NULL) {
14863c41688SPaul Moore 			ret_val = -ENOMEM;
14963c41688SPaul Moore 			goto add_failure;
15063c41688SPaul Moore 		}
15163c41688SPaul Moore 		INIT_LIST_HEAD(&addrmap->list4);
15263c41688SPaul Moore 		INIT_LIST_HEAD(&addrmap->list6);
15363c41688SPaul Moore 
15463c41688SPaul Moore 		if (nla_len(info->attrs[NLBL_MGMT_A_IPV4ADDR]) !=
15563c41688SPaul Moore 		    sizeof(struct in_addr)) {
15663c41688SPaul Moore 			ret_val = -EINVAL;
15763c41688SPaul Moore 			goto add_failure;
15863c41688SPaul Moore 		}
15963c41688SPaul Moore 		if (nla_len(info->attrs[NLBL_MGMT_A_IPV4MASK]) !=
16063c41688SPaul Moore 		    sizeof(struct in_addr)) {
16163c41688SPaul Moore 			ret_val = -EINVAL;
16263c41688SPaul Moore 			goto add_failure;
16363c41688SPaul Moore 		}
16463c41688SPaul Moore 		addr = nla_data(info->attrs[NLBL_MGMT_A_IPV4ADDR]);
16563c41688SPaul Moore 		mask = nla_data(info->attrs[NLBL_MGMT_A_IPV4MASK]);
16663c41688SPaul Moore 
16763c41688SPaul Moore 		map = kzalloc(sizeof(*map), GFP_KERNEL);
16863c41688SPaul Moore 		if (map == NULL) {
16963c41688SPaul Moore 			ret_val = -ENOMEM;
17063c41688SPaul Moore 			goto add_failure;
17163c41688SPaul Moore 		}
17263c41688SPaul Moore 		map->list.addr = addr->s_addr & mask->s_addr;
17363c41688SPaul Moore 		map->list.mask = mask->s_addr;
17463c41688SPaul Moore 		map->list.valid = 1;
17563c41688SPaul Moore 		map->type = entry->type;
17663c41688SPaul Moore 		if (cipsov4)
17763c41688SPaul Moore 			map->type_def.cipsov4 = cipsov4;
17863c41688SPaul Moore 
17963c41688SPaul Moore 		ret_val = netlbl_af4list_add(&map->list, &addrmap->list4);
18063c41688SPaul Moore 		if (ret_val != 0) {
18163c41688SPaul Moore 			kfree(map);
18263c41688SPaul Moore 			goto add_failure;
18363c41688SPaul Moore 		}
18463c41688SPaul Moore 
18563c41688SPaul Moore 		entry->type = NETLBL_NLTYPE_ADDRSELECT;
18663c41688SPaul Moore 		entry->type_def.addrsel = addrmap;
18763c41688SPaul Moore #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
18863c41688SPaul Moore 	} else if (info->attrs[NLBL_MGMT_A_IPV6ADDR]) {
18963c41688SPaul Moore 		struct in6_addr *addr;
19063c41688SPaul Moore 		struct in6_addr *mask;
19163c41688SPaul Moore 		struct netlbl_domaddr6_map *map;
19263c41688SPaul Moore 
19363c41688SPaul Moore 		addrmap = kzalloc(sizeof(*addrmap), GFP_KERNEL);
19463c41688SPaul Moore 		if (addrmap == NULL) {
19563c41688SPaul Moore 			ret_val = -ENOMEM;
19663c41688SPaul Moore 			goto add_failure;
19763c41688SPaul Moore 		}
19863c41688SPaul Moore 		INIT_LIST_HEAD(&addrmap->list4);
19963c41688SPaul Moore 		INIT_LIST_HEAD(&addrmap->list6);
20063c41688SPaul Moore 
20163c41688SPaul Moore 		if (nla_len(info->attrs[NLBL_MGMT_A_IPV6ADDR]) !=
20263c41688SPaul Moore 		    sizeof(struct in6_addr)) {
20363c41688SPaul Moore 			ret_val = -EINVAL;
20463c41688SPaul Moore 			goto add_failure;
20563c41688SPaul Moore 		}
20663c41688SPaul Moore 		if (nla_len(info->attrs[NLBL_MGMT_A_IPV6MASK]) !=
20763c41688SPaul Moore 		    sizeof(struct in6_addr)) {
20863c41688SPaul Moore 			ret_val = -EINVAL;
20963c41688SPaul Moore 			goto add_failure;
21063c41688SPaul Moore 		}
21163c41688SPaul Moore 		addr = nla_data(info->attrs[NLBL_MGMT_A_IPV6ADDR]);
21263c41688SPaul Moore 		mask = nla_data(info->attrs[NLBL_MGMT_A_IPV6MASK]);
21363c41688SPaul Moore 
21463c41688SPaul Moore 		map = kzalloc(sizeof(*map), GFP_KERNEL);
21563c41688SPaul Moore 		if (map == NULL) {
21663c41688SPaul Moore 			ret_val = -ENOMEM;
21763c41688SPaul Moore 			goto add_failure;
21863c41688SPaul Moore 		}
21963c41688SPaul Moore 		ipv6_addr_copy(&map->list.addr, addr);
22063c41688SPaul Moore 		map->list.addr.s6_addr32[0] &= mask->s6_addr32[0];
22163c41688SPaul Moore 		map->list.addr.s6_addr32[1] &= mask->s6_addr32[1];
22263c41688SPaul Moore 		map->list.addr.s6_addr32[2] &= mask->s6_addr32[2];
22363c41688SPaul Moore 		map->list.addr.s6_addr32[3] &= mask->s6_addr32[3];
22463c41688SPaul Moore 		ipv6_addr_copy(&map->list.mask, mask);
22563c41688SPaul Moore 		map->list.valid = 1;
22663c41688SPaul Moore 		map->type = entry->type;
22763c41688SPaul Moore 
22863c41688SPaul Moore 		ret_val = netlbl_af6list_add(&map->list, &addrmap->list6);
22963c41688SPaul Moore 		if (ret_val != 0) {
23063c41688SPaul Moore 			kfree(map);
23163c41688SPaul Moore 			goto add_failure;
23263c41688SPaul Moore 		}
23363c41688SPaul Moore 
23463c41688SPaul Moore 		entry->type = NETLBL_NLTYPE_ADDRSELECT;
23563c41688SPaul Moore 		entry->type_def.addrsel = addrmap;
23663c41688SPaul Moore #endif /* IPv6 */
23763c41688SPaul Moore 	}
23863c41688SPaul Moore 
23963c41688SPaul Moore 	ret_val = netlbl_domhsh_add(entry, audit_info);
24063c41688SPaul Moore 	if (ret_val != 0)
24163c41688SPaul Moore 		goto add_failure;
24263c41688SPaul Moore 
24363c41688SPaul Moore 	return 0;
24463c41688SPaul Moore 
24563c41688SPaul Moore add_failure:
24663c41688SPaul Moore 	if (cipsov4)
24763c41688SPaul Moore 		cipso_v4_doi_putdef(cipsov4);
24863c41688SPaul Moore 	if (entry)
24963c41688SPaul Moore 		kfree(entry->domain);
25063c41688SPaul Moore 	kfree(addrmap);
25163c41688SPaul Moore 	kfree(entry);
25263c41688SPaul Moore 	return ret_val;
25363c41688SPaul Moore }
25463c41688SPaul Moore 
25563c41688SPaul Moore /**
25663c41688SPaul Moore  * netlbl_mgmt_listentry - List a NetLabel/LSM domain map entry
25763c41688SPaul Moore  * @skb: the NETLINK buffer
25863c41688SPaul Moore  * @entry: the map entry
25963c41688SPaul Moore  *
26063c41688SPaul Moore  * Description:
26163c41688SPaul Moore  * This function is a helper function used by the LISTALL and LISTDEF command
26225985edcSLucas De Marchi  * handlers.  The caller is responsible for ensuring that the RCU read lock
26363c41688SPaul Moore  * is held.  Returns zero on success, negative values on failure.
26463c41688SPaul Moore  *
26563c41688SPaul Moore  */
26663c41688SPaul Moore static int netlbl_mgmt_listentry(struct sk_buff *skb,
26763c41688SPaul Moore 				 struct netlbl_dom_map *entry)
26863c41688SPaul Moore {
269f8a02479SPaul Moore 	int ret_val = 0;
27063c41688SPaul Moore 	struct nlattr *nla_a;
27163c41688SPaul Moore 	struct nlattr *nla_b;
27263c41688SPaul Moore 	struct netlbl_af4list *iter4;
27363c41688SPaul Moore #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
27463c41688SPaul Moore 	struct netlbl_af6list *iter6;
27563c41688SPaul Moore #endif
27663c41688SPaul Moore 
27763c41688SPaul Moore 	if (entry->domain != NULL) {
27863c41688SPaul Moore 		ret_val = nla_put_string(skb,
27963c41688SPaul Moore 					 NLBL_MGMT_A_DOMAIN, entry->domain);
28063c41688SPaul Moore 		if (ret_val != 0)
28163c41688SPaul Moore 			return ret_val;
28263c41688SPaul Moore 	}
28363c41688SPaul Moore 
28463c41688SPaul Moore 	switch (entry->type) {
28563c41688SPaul Moore 	case NETLBL_NLTYPE_ADDRSELECT:
28663c41688SPaul Moore 		nla_a = nla_nest_start(skb, NLBL_MGMT_A_SELECTORLIST);
28763c41688SPaul Moore 		if (nla_a == NULL)
28863c41688SPaul Moore 			return -ENOMEM;
28963c41688SPaul Moore 
29063c41688SPaul Moore 		netlbl_af4list_foreach_rcu(iter4,
29163c41688SPaul Moore 					   &entry->type_def.addrsel->list4) {
29263c41688SPaul Moore 			struct netlbl_domaddr4_map *map4;
29363c41688SPaul Moore 			struct in_addr addr_struct;
29463c41688SPaul Moore 
29563c41688SPaul Moore 			nla_b = nla_nest_start(skb, NLBL_MGMT_A_ADDRSELECTOR);
29663c41688SPaul Moore 			if (nla_b == NULL)
29763c41688SPaul Moore 				return -ENOMEM;
29863c41688SPaul Moore 
29963c41688SPaul Moore 			addr_struct.s_addr = iter4->addr;
30063c41688SPaul Moore 			ret_val = nla_put(skb, NLBL_MGMT_A_IPV4ADDR,
30163c41688SPaul Moore 					  sizeof(struct in_addr),
30263c41688SPaul Moore 					  &addr_struct);
30363c41688SPaul Moore 			if (ret_val != 0)
30463c41688SPaul Moore 				return ret_val;
30563c41688SPaul Moore 			addr_struct.s_addr = iter4->mask;
30663c41688SPaul Moore 			ret_val = nla_put(skb, NLBL_MGMT_A_IPV4MASK,
30763c41688SPaul Moore 					  sizeof(struct in_addr),
30863c41688SPaul Moore 					  &addr_struct);
30963c41688SPaul Moore 			if (ret_val != 0)
31063c41688SPaul Moore 				return ret_val;
31163c41688SPaul Moore 			map4 = netlbl_domhsh_addr4_entry(iter4);
31263c41688SPaul Moore 			ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL,
31363c41688SPaul Moore 					      map4->type);
31463c41688SPaul Moore 			if (ret_val != 0)
31563c41688SPaul Moore 				return ret_val;
31663c41688SPaul Moore 			switch (map4->type) {
31763c41688SPaul Moore 			case NETLBL_NLTYPE_CIPSOV4:
31863c41688SPaul Moore 				ret_val = nla_put_u32(skb, NLBL_MGMT_A_CV4DOI,
31963c41688SPaul Moore 						  map4->type_def.cipsov4->doi);
32063c41688SPaul Moore 				if (ret_val != 0)
32163c41688SPaul Moore 					return ret_val;
32263c41688SPaul Moore 				break;
32363c41688SPaul Moore 			}
32463c41688SPaul Moore 
32563c41688SPaul Moore 			nla_nest_end(skb, nla_b);
32663c41688SPaul Moore 		}
32763c41688SPaul Moore #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
32863c41688SPaul Moore 		netlbl_af6list_foreach_rcu(iter6,
32963c41688SPaul Moore 					   &entry->type_def.addrsel->list6) {
33063c41688SPaul Moore 			struct netlbl_domaddr6_map *map6;
33163c41688SPaul Moore 
33263c41688SPaul Moore 			nla_b = nla_nest_start(skb, NLBL_MGMT_A_ADDRSELECTOR);
33363c41688SPaul Moore 			if (nla_b == NULL)
33463c41688SPaul Moore 				return -ENOMEM;
33563c41688SPaul Moore 
33663c41688SPaul Moore 			ret_val = nla_put(skb, NLBL_MGMT_A_IPV6ADDR,
33763c41688SPaul Moore 					  sizeof(struct in6_addr),
33863c41688SPaul Moore 					  &iter6->addr);
33963c41688SPaul Moore 			if (ret_val != 0)
34063c41688SPaul Moore 				return ret_val;
34163c41688SPaul Moore 			ret_val = nla_put(skb, NLBL_MGMT_A_IPV6MASK,
34263c41688SPaul Moore 					  sizeof(struct in6_addr),
34363c41688SPaul Moore 					  &iter6->mask);
34463c41688SPaul Moore 			if (ret_val != 0)
34563c41688SPaul Moore 				return ret_val;
34663c41688SPaul Moore 			map6 = netlbl_domhsh_addr6_entry(iter6);
34763c41688SPaul Moore 			ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL,
34863c41688SPaul Moore 					      map6->type);
34963c41688SPaul Moore 			if (ret_val != 0)
35063c41688SPaul Moore 				return ret_val;
35163c41688SPaul Moore 
35263c41688SPaul Moore 			nla_nest_end(skb, nla_b);
35363c41688SPaul Moore 		}
35463c41688SPaul Moore #endif /* IPv6 */
35563c41688SPaul Moore 
35663c41688SPaul Moore 		nla_nest_end(skb, nla_a);
35763c41688SPaul Moore 		break;
35863c41688SPaul Moore 	case NETLBL_NLTYPE_UNLABELED:
35963c41688SPaul Moore 		ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL, entry->type);
36063c41688SPaul Moore 		break;
36163c41688SPaul Moore 	case NETLBL_NLTYPE_CIPSOV4:
36263c41688SPaul Moore 		ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL, entry->type);
36363c41688SPaul Moore 		if (ret_val != 0)
36463c41688SPaul Moore 			return ret_val;
36563c41688SPaul Moore 		ret_val = nla_put_u32(skb, NLBL_MGMT_A_CV4DOI,
36663c41688SPaul Moore 				      entry->type_def.cipsov4->doi);
36763c41688SPaul Moore 		break;
36863c41688SPaul Moore 	}
36963c41688SPaul Moore 
37063c41688SPaul Moore 	return ret_val;
37163c41688SPaul Moore }
37263c41688SPaul Moore 
37363c41688SPaul Moore /*
374d15c345fSPaul Moore  * NetLabel Command Handlers
375d15c345fSPaul Moore  */
376d15c345fSPaul Moore 
377d15c345fSPaul Moore /**
378d15c345fSPaul Moore  * netlbl_mgmt_add - Handle an ADD message
379d15c345fSPaul Moore  * @skb: the NETLINK buffer
380d15c345fSPaul Moore  * @info: the Generic NETLINK info block
381d15c345fSPaul Moore  *
382d15c345fSPaul Moore  * Description:
383d15c345fSPaul Moore  * Process a user generated ADD message and add the domains from the message
384d15c345fSPaul Moore  * to the hash table.  See netlabel.h for a description of the message format.
385d15c345fSPaul Moore  * Returns zero on success, negative values on failure.
386d15c345fSPaul Moore  *
387d15c345fSPaul Moore  */
388d15c345fSPaul Moore static int netlbl_mgmt_add(struct sk_buff *skb, struct genl_info *info)
389d15c345fSPaul Moore {
39095d4e6beSPaul Moore 	struct netlbl_audit audit_info;
391d15c345fSPaul Moore 
39263c41688SPaul Moore 	if ((!info->attrs[NLBL_MGMT_A_DOMAIN]) ||
39363c41688SPaul Moore 	    (!info->attrs[NLBL_MGMT_A_PROTOCOL]) ||
39463c41688SPaul Moore 	    (info->attrs[NLBL_MGMT_A_IPV4ADDR] &&
39563c41688SPaul Moore 	     info->attrs[NLBL_MGMT_A_IPV6ADDR]) ||
39663c41688SPaul Moore 	    (info->attrs[NLBL_MGMT_A_IPV4MASK] &&
39763c41688SPaul Moore 	     info->attrs[NLBL_MGMT_A_IPV6MASK]) ||
39863c41688SPaul Moore 	    ((info->attrs[NLBL_MGMT_A_IPV4ADDR] != NULL) ^
39963c41688SPaul Moore 	     (info->attrs[NLBL_MGMT_A_IPV4MASK] != NULL)) ||
40063c41688SPaul Moore 	    ((info->attrs[NLBL_MGMT_A_IPV6ADDR] != NULL) ^
40163c41688SPaul Moore 	     (info->attrs[NLBL_MGMT_A_IPV6MASK] != NULL)))
40263c41688SPaul Moore 		return -EINVAL;
403d15c345fSPaul Moore 
40495d4e6beSPaul Moore 	netlbl_netlink_auditinfo(skb, &audit_info);
40595d4e6beSPaul Moore 
40663c41688SPaul Moore 	return netlbl_mgmt_add_common(info, &audit_info);
407d15c345fSPaul Moore }
408d15c345fSPaul Moore 
409d15c345fSPaul Moore /**
410d15c345fSPaul Moore  * netlbl_mgmt_remove - Handle a REMOVE message
411d15c345fSPaul Moore  * @skb: the NETLINK buffer
412d15c345fSPaul Moore  * @info: the Generic NETLINK info block
413d15c345fSPaul Moore  *
414d15c345fSPaul Moore  * Description:
415d15c345fSPaul Moore  * Process a user generated REMOVE message and remove the specified domain
416d15c345fSPaul Moore  * mappings.  Returns zero on success, negative values on failure.
417d15c345fSPaul Moore  *
418d15c345fSPaul Moore  */
419d15c345fSPaul Moore static int netlbl_mgmt_remove(struct sk_buff *skb, struct genl_info *info)
420d15c345fSPaul Moore {
421fd385855SPaul Moore 	char *domain;
42295d4e6beSPaul Moore 	struct netlbl_audit audit_info;
423d15c345fSPaul Moore 
424fd385855SPaul Moore 	if (!info->attrs[NLBL_MGMT_A_DOMAIN])
425fd385855SPaul Moore 		return -EINVAL;
426d15c345fSPaul Moore 
42795d4e6beSPaul Moore 	netlbl_netlink_auditinfo(skb, &audit_info);
42895d4e6beSPaul Moore 
429fd385855SPaul Moore 	domain = nla_data(info->attrs[NLBL_MGMT_A_DOMAIN]);
43095d4e6beSPaul Moore 	return netlbl_domhsh_remove(domain, &audit_info);
431d15c345fSPaul Moore }
432d15c345fSPaul Moore 
433fd385855SPaul Moore /**
434fd385855SPaul Moore  * netlbl_mgmt_listall_cb - netlbl_domhsh_walk() callback for LISTALL
435fd385855SPaul Moore  * @entry: the domain mapping hash table entry
436fd385855SPaul Moore  * @arg: the netlbl_domhsh_walk_arg structure
437fd385855SPaul Moore  *
438fd385855SPaul Moore  * Description:
439fd385855SPaul Moore  * This function is designed to be used as a callback to the
440fd385855SPaul Moore  * netlbl_domhsh_walk() function for use in generating a response for a LISTALL
441fd385855SPaul Moore  * message.  Returns the size of the message on success, negative values on
442fd385855SPaul Moore  * failure.
443fd385855SPaul Moore  *
444fd385855SPaul Moore  */
445fd385855SPaul Moore static int netlbl_mgmt_listall_cb(struct netlbl_dom_map *entry, void *arg)
446fd385855SPaul Moore {
447fd385855SPaul Moore 	int ret_val = -ENOMEM;
448fd385855SPaul Moore 	struct netlbl_domhsh_walk_arg *cb_arg = arg;
449fd385855SPaul Moore 	void *data;
450d15c345fSPaul Moore 
45117c157c8SThomas Graf 	data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).pid,
45217c157c8SThomas Graf 			   cb_arg->seq, &netlbl_mgmt_gnl_family,
45317c157c8SThomas Graf 			   NLM_F_MULTI, NLBL_MGMT_C_LISTALL);
454fd385855SPaul Moore 	if (data == NULL)
455fd385855SPaul Moore 		goto listall_cb_failure;
456fd385855SPaul Moore 
45763c41688SPaul Moore 	ret_val = netlbl_mgmt_listentry(cb_arg->skb, entry);
458fd385855SPaul Moore 	if (ret_val != 0)
459fd385855SPaul Moore 		goto listall_cb_failure;
460fd385855SPaul Moore 
461fd385855SPaul Moore 	cb_arg->seq++;
462fd385855SPaul Moore 	return genlmsg_end(cb_arg->skb, data);
463fd385855SPaul Moore 
464fd385855SPaul Moore listall_cb_failure:
465fd385855SPaul Moore 	genlmsg_cancel(cb_arg->skb, data);
466d15c345fSPaul Moore 	return ret_val;
467d15c345fSPaul Moore }
468d15c345fSPaul Moore 
469d15c345fSPaul Moore /**
470fd385855SPaul Moore  * netlbl_mgmt_listall - Handle a LISTALL message
471d15c345fSPaul Moore  * @skb: the NETLINK buffer
472fd385855SPaul Moore  * @cb: the NETLINK callback
473d15c345fSPaul Moore  *
474d15c345fSPaul Moore  * Description:
475fd385855SPaul Moore  * Process a user generated LISTALL message and dumps the domain hash table in
476fd385855SPaul Moore  * a form suitable for use in a kernel generated LISTALL message.  Returns zero
477fd385855SPaul Moore  * on success, negative values on failure.
478d15c345fSPaul Moore  *
479d15c345fSPaul Moore  */
480fd385855SPaul Moore static int netlbl_mgmt_listall(struct sk_buff *skb,
481fd385855SPaul Moore 			       struct netlink_callback *cb)
482d15c345fSPaul Moore {
483fd385855SPaul Moore 	struct netlbl_domhsh_walk_arg cb_arg;
484fd385855SPaul Moore 	u32 skip_bkt = cb->args[0];
485fd385855SPaul Moore 	u32 skip_chain = cb->args[1];
486d15c345fSPaul Moore 
487fd385855SPaul Moore 	cb_arg.nl_cb = cb;
488fd385855SPaul Moore 	cb_arg.skb = skb;
489fd385855SPaul Moore 	cb_arg.seq = cb->nlh->nlmsg_seq;
490d15c345fSPaul Moore 
491fd385855SPaul Moore 	netlbl_domhsh_walk(&skip_bkt,
492fd385855SPaul Moore 			   &skip_chain,
493fd385855SPaul Moore 			   netlbl_mgmt_listall_cb,
494fd385855SPaul Moore 			   &cb_arg);
495d15c345fSPaul Moore 
496fd385855SPaul Moore 	cb->args[0] = skip_bkt;
497fd385855SPaul Moore 	cb->args[1] = skip_chain;
498fd385855SPaul Moore 	return skb->len;
499d15c345fSPaul Moore }
500d15c345fSPaul Moore 
501d15c345fSPaul Moore /**
502d15c345fSPaul Moore  * netlbl_mgmt_adddef - Handle an ADDDEF message
503d15c345fSPaul Moore  * @skb: the NETLINK buffer
504d15c345fSPaul Moore  * @info: the Generic NETLINK info block
505d15c345fSPaul Moore  *
506d15c345fSPaul Moore  * Description:
507d15c345fSPaul Moore  * Process a user generated ADDDEF message and respond accordingly.  Returns
508d15c345fSPaul Moore  * zero on success, negative values on failure.
509d15c345fSPaul Moore  *
510d15c345fSPaul Moore  */
511d15c345fSPaul Moore static int netlbl_mgmt_adddef(struct sk_buff *skb, struct genl_info *info)
512d15c345fSPaul Moore {
51395d4e6beSPaul Moore 	struct netlbl_audit audit_info;
514d15c345fSPaul Moore 
51563c41688SPaul Moore 	if ((!info->attrs[NLBL_MGMT_A_PROTOCOL]) ||
51663c41688SPaul Moore 	    (info->attrs[NLBL_MGMT_A_IPV4ADDR] &&
51763c41688SPaul Moore 	     info->attrs[NLBL_MGMT_A_IPV6ADDR]) ||
51863c41688SPaul Moore 	    (info->attrs[NLBL_MGMT_A_IPV4MASK] &&
51963c41688SPaul Moore 	     info->attrs[NLBL_MGMT_A_IPV6MASK]) ||
52063c41688SPaul Moore 	    ((info->attrs[NLBL_MGMT_A_IPV4ADDR] != NULL) ^
52163c41688SPaul Moore 	     (info->attrs[NLBL_MGMT_A_IPV4MASK] != NULL)) ||
52263c41688SPaul Moore 	    ((info->attrs[NLBL_MGMT_A_IPV6ADDR] != NULL) ^
52363c41688SPaul Moore 	     (info->attrs[NLBL_MGMT_A_IPV6MASK] != NULL)))
52463c41688SPaul Moore 		return -EINVAL;
525d15c345fSPaul Moore 
52695d4e6beSPaul Moore 	netlbl_netlink_auditinfo(skb, &audit_info);
52795d4e6beSPaul Moore 
52863c41688SPaul Moore 	return netlbl_mgmt_add_common(info, &audit_info);
529d15c345fSPaul Moore }
530d15c345fSPaul Moore 
531d15c345fSPaul Moore /**
532d15c345fSPaul Moore  * netlbl_mgmt_removedef - Handle a REMOVEDEF message
533d15c345fSPaul Moore  * @skb: the NETLINK buffer
534d15c345fSPaul Moore  * @info: the Generic NETLINK info block
535d15c345fSPaul Moore  *
536d15c345fSPaul Moore  * Description:
537d15c345fSPaul Moore  * Process a user generated REMOVEDEF message and remove the default domain
538d15c345fSPaul Moore  * mapping.  Returns zero on success, negative values on failure.
539d15c345fSPaul Moore  *
540d15c345fSPaul Moore  */
541d15c345fSPaul Moore static int netlbl_mgmt_removedef(struct sk_buff *skb, struct genl_info *info)
542d15c345fSPaul Moore {
54395d4e6beSPaul Moore 	struct netlbl_audit audit_info;
54495d4e6beSPaul Moore 
54595d4e6beSPaul Moore 	netlbl_netlink_auditinfo(skb, &audit_info);
54695d4e6beSPaul Moore 
54795d4e6beSPaul Moore 	return netlbl_domhsh_remove_default(&audit_info);
548d15c345fSPaul Moore }
549d15c345fSPaul Moore 
550d15c345fSPaul Moore /**
551d15c345fSPaul Moore  * netlbl_mgmt_listdef - Handle a LISTDEF message
552d15c345fSPaul Moore  * @skb: the NETLINK buffer
553d15c345fSPaul Moore  * @info: the Generic NETLINK info block
554d15c345fSPaul Moore  *
555d15c345fSPaul Moore  * Description:
556d15c345fSPaul Moore  * Process a user generated LISTDEF message and dumps the default domain
557d15c345fSPaul Moore  * mapping in a form suitable for use in a kernel generated LISTDEF message.
558d15c345fSPaul Moore  * Returns zero on success, negative values on failure.
559d15c345fSPaul Moore  *
560d15c345fSPaul Moore  */
561d15c345fSPaul Moore static int netlbl_mgmt_listdef(struct sk_buff *skb, struct genl_info *info)
562d15c345fSPaul Moore {
563d15c345fSPaul Moore 	int ret_val = -ENOMEM;
564fd385855SPaul Moore 	struct sk_buff *ans_skb = NULL;
565fd385855SPaul Moore 	void *data;
566fd385855SPaul Moore 	struct netlbl_dom_map *entry;
567d15c345fSPaul Moore 
568339bf98fSThomas Graf 	ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
569d15c345fSPaul Moore 	if (ans_skb == NULL)
570fd385855SPaul Moore 		return -ENOMEM;
57117c157c8SThomas Graf 	data = genlmsg_put_reply(ans_skb, info, &netlbl_mgmt_gnl_family,
57217c157c8SThomas Graf 				 0, NLBL_MGMT_C_LISTDEF);
573fd385855SPaul Moore 	if (data == NULL)
574fd385855SPaul Moore 		goto listdef_failure;
575d15c345fSPaul Moore 
576fd385855SPaul Moore 	rcu_read_lock();
577fd385855SPaul Moore 	entry = netlbl_domhsh_getentry(NULL);
578fd385855SPaul Moore 	if (entry == NULL) {
579fd385855SPaul Moore 		ret_val = -ENOENT;
580fd385855SPaul Moore 		goto listdef_failure_lock;
581fd385855SPaul Moore 	}
58263c41688SPaul Moore 	ret_val = netlbl_mgmt_listentry(ans_skb, entry);
583fd385855SPaul Moore 	rcu_read_unlock();
58463c41688SPaul Moore 	if (ret_val != 0)
58563c41688SPaul Moore 		goto listdef_failure;
586fd385855SPaul Moore 
587fd385855SPaul Moore 	genlmsg_end(ans_skb, data);
588fe785beeSDenis V. Lunev 	return genlmsg_reply(ans_skb, info);
589d15c345fSPaul Moore 
590fd385855SPaul Moore listdef_failure_lock:
591fd385855SPaul Moore 	rcu_read_unlock();
592d15c345fSPaul Moore listdef_failure:
593fd385855SPaul Moore 	kfree_skb(ans_skb);
594d15c345fSPaul Moore 	return ret_val;
595d15c345fSPaul Moore }
596d15c345fSPaul Moore 
597d15c345fSPaul Moore /**
598fd385855SPaul Moore  * netlbl_mgmt_protocols_cb - Write an individual PROTOCOL message response
599fd385855SPaul Moore  * @skb: the skb to write to
600fd385855SPaul Moore  * @cb: the NETLINK callback
601fd385855SPaul Moore  * @protocol: the NetLabel protocol to use in the message
602d15c345fSPaul Moore  *
603d15c345fSPaul Moore  * Description:
604fd385855SPaul Moore  * This function is to be used in conjunction with netlbl_mgmt_protocols() to
605fd385855SPaul Moore  * answer a application's PROTOCOLS message.  Returns the size of the message
606fd385855SPaul Moore  * on success, negative values on failure.
607d15c345fSPaul Moore  *
608d15c345fSPaul Moore  */
609fd385855SPaul Moore static int netlbl_mgmt_protocols_cb(struct sk_buff *skb,
610fd385855SPaul Moore 				    struct netlink_callback *cb,
611fd385855SPaul Moore 				    u32 protocol)
612d15c345fSPaul Moore {
613d15c345fSPaul Moore 	int ret_val = -ENOMEM;
614fd385855SPaul Moore 	void *data;
615d15c345fSPaul Moore 
61617c157c8SThomas Graf 	data = genlmsg_put(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq,
61717c157c8SThomas Graf 			   &netlbl_mgmt_gnl_family, NLM_F_MULTI,
618fd385855SPaul Moore 			   NLBL_MGMT_C_PROTOCOLS);
619fd385855SPaul Moore 	if (data == NULL)
620fd385855SPaul Moore 		goto protocols_cb_failure;
621d15c345fSPaul Moore 
622fd385855SPaul Moore 	ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL, protocol);
623d15c345fSPaul Moore 	if (ret_val != 0)
624fd385855SPaul Moore 		goto protocols_cb_failure;
625d15c345fSPaul Moore 
626fd385855SPaul Moore 	return genlmsg_end(skb, data);
627d15c345fSPaul Moore 
628fd385855SPaul Moore protocols_cb_failure:
629fd385855SPaul Moore 	genlmsg_cancel(skb, data);
630d15c345fSPaul Moore 	return ret_val;
631d15c345fSPaul Moore }
632d15c345fSPaul Moore 
633d15c345fSPaul Moore /**
634fd385855SPaul Moore  * netlbl_mgmt_protocols - Handle a PROTOCOLS message
635fd385855SPaul Moore  * @skb: the NETLINK buffer
636fd385855SPaul Moore  * @cb: the NETLINK callback
637fd385855SPaul Moore  *
638fd385855SPaul Moore  * Description:
639fd385855SPaul Moore  * Process a user generated PROTOCOLS message and respond accordingly.
640fd385855SPaul Moore  *
641fd385855SPaul Moore  */
642fd385855SPaul Moore static int netlbl_mgmt_protocols(struct sk_buff *skb,
643fd385855SPaul Moore 				 struct netlink_callback *cb)
644fd385855SPaul Moore {
645fd385855SPaul Moore 	u32 protos_sent = cb->args[0];
646fd385855SPaul Moore 
647fd385855SPaul Moore 	if (protos_sent == 0) {
648fd385855SPaul Moore 		if (netlbl_mgmt_protocols_cb(skb,
649fd385855SPaul Moore 					     cb,
650fd385855SPaul Moore 					     NETLBL_NLTYPE_UNLABELED) < 0)
651fd385855SPaul Moore 			goto protocols_return;
652fd385855SPaul Moore 		protos_sent++;
653fd385855SPaul Moore 	}
654fd385855SPaul Moore 	if (protos_sent == 1) {
655fd385855SPaul Moore 		if (netlbl_mgmt_protocols_cb(skb,
656fd385855SPaul Moore 					     cb,
657fd385855SPaul Moore 					     NETLBL_NLTYPE_CIPSOV4) < 0)
658fd385855SPaul Moore 			goto protocols_return;
659fd385855SPaul Moore 		protos_sent++;
660fd385855SPaul Moore 	}
661fd385855SPaul Moore 
662fd385855SPaul Moore protocols_return:
663fd385855SPaul Moore 	cb->args[0] = protos_sent;
664fd385855SPaul Moore 	return skb->len;
665fd385855SPaul Moore }
666fd385855SPaul Moore 
667fd385855SPaul Moore /**
668d15c345fSPaul Moore  * netlbl_mgmt_version - Handle a VERSION message
669d15c345fSPaul Moore  * @skb: the NETLINK buffer
670d15c345fSPaul Moore  * @info: the Generic NETLINK info block
671d15c345fSPaul Moore  *
672d15c345fSPaul Moore  * Description:
673d15c345fSPaul Moore  * Process a user generated VERSION message and respond accordingly.  Returns
674d15c345fSPaul Moore  * zero on success, negative values on failure.
675d15c345fSPaul Moore  *
676d15c345fSPaul Moore  */
677d15c345fSPaul Moore static int netlbl_mgmt_version(struct sk_buff *skb, struct genl_info *info)
678d15c345fSPaul Moore {
679d15c345fSPaul Moore 	int ret_val = -ENOMEM;
680d15c345fSPaul Moore 	struct sk_buff *ans_skb = NULL;
681fd385855SPaul Moore 	void *data;
682d15c345fSPaul Moore 
683339bf98fSThomas Graf 	ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
684d15c345fSPaul Moore 	if (ans_skb == NULL)
685fd385855SPaul Moore 		return -ENOMEM;
68617c157c8SThomas Graf 	data = genlmsg_put_reply(ans_skb, info, &netlbl_mgmt_gnl_family,
68717c157c8SThomas Graf 				 0, NLBL_MGMT_C_VERSION);
688fd385855SPaul Moore 	if (data == NULL)
689d15c345fSPaul Moore 		goto version_failure;
690d15c345fSPaul Moore 
691fd385855SPaul Moore 	ret_val = nla_put_u32(ans_skb,
692fd385855SPaul Moore 			      NLBL_MGMT_A_VERSION,
693fd385855SPaul Moore 			      NETLBL_PROTO_VERSION);
694d15c345fSPaul Moore 	if (ret_val != 0)
695d15c345fSPaul Moore 		goto version_failure;
696d15c345fSPaul Moore 
697fd385855SPaul Moore 	genlmsg_end(ans_skb, data);
698fe785beeSDenis V. Lunev 	return genlmsg_reply(ans_skb, info);
699d15c345fSPaul Moore 
700d15c345fSPaul Moore version_failure:
701d15c345fSPaul Moore 	kfree_skb(ans_skb);
702d15c345fSPaul Moore 	return ret_val;
703d15c345fSPaul Moore }
704d15c345fSPaul Moore 
705d15c345fSPaul Moore 
706d15c345fSPaul Moore /*
707d15c345fSPaul Moore  * NetLabel Generic NETLINK Command Definitions
708d15c345fSPaul Moore  */
709d15c345fSPaul Moore 
710227c43c3SPavel Emelyanov static struct genl_ops netlbl_mgmt_genl_ops[] = {
711227c43c3SPavel Emelyanov 	{
712d15c345fSPaul Moore 	.cmd = NLBL_MGMT_C_ADD,
713fd385855SPaul Moore 	.flags = GENL_ADMIN_PERM,
714fd385855SPaul Moore 	.policy = netlbl_mgmt_genl_policy,
715d15c345fSPaul Moore 	.doit = netlbl_mgmt_add,
716d15c345fSPaul Moore 	.dumpit = NULL,
717227c43c3SPavel Emelyanov 	},
718227c43c3SPavel Emelyanov 	{
719d15c345fSPaul Moore 	.cmd = NLBL_MGMT_C_REMOVE,
720fd385855SPaul Moore 	.flags = GENL_ADMIN_PERM,
721fd385855SPaul Moore 	.policy = netlbl_mgmt_genl_policy,
722d15c345fSPaul Moore 	.doit = netlbl_mgmt_remove,
723d15c345fSPaul Moore 	.dumpit = NULL,
724227c43c3SPavel Emelyanov 	},
725227c43c3SPavel Emelyanov 	{
726fd385855SPaul Moore 	.cmd = NLBL_MGMT_C_LISTALL,
727d15c345fSPaul Moore 	.flags = 0,
728fd385855SPaul Moore 	.policy = netlbl_mgmt_genl_policy,
729fd385855SPaul Moore 	.doit = NULL,
730fd385855SPaul Moore 	.dumpit = netlbl_mgmt_listall,
731227c43c3SPavel Emelyanov 	},
732227c43c3SPavel Emelyanov 	{
733d15c345fSPaul Moore 	.cmd = NLBL_MGMT_C_ADDDEF,
734fd385855SPaul Moore 	.flags = GENL_ADMIN_PERM,
735fd385855SPaul Moore 	.policy = netlbl_mgmt_genl_policy,
736d15c345fSPaul Moore 	.doit = netlbl_mgmt_adddef,
737d15c345fSPaul Moore 	.dumpit = NULL,
738227c43c3SPavel Emelyanov 	},
739227c43c3SPavel Emelyanov 	{
740d15c345fSPaul Moore 	.cmd = NLBL_MGMT_C_REMOVEDEF,
741fd385855SPaul Moore 	.flags = GENL_ADMIN_PERM,
742fd385855SPaul Moore 	.policy = netlbl_mgmt_genl_policy,
743d15c345fSPaul Moore 	.doit = netlbl_mgmt_removedef,
744d15c345fSPaul Moore 	.dumpit = NULL,
745227c43c3SPavel Emelyanov 	},
746227c43c3SPavel Emelyanov 	{
747d15c345fSPaul Moore 	.cmd = NLBL_MGMT_C_LISTDEF,
748d15c345fSPaul Moore 	.flags = 0,
749fd385855SPaul Moore 	.policy = netlbl_mgmt_genl_policy,
750d15c345fSPaul Moore 	.doit = netlbl_mgmt_listdef,
751d15c345fSPaul Moore 	.dumpit = NULL,
752227c43c3SPavel Emelyanov 	},
753227c43c3SPavel Emelyanov 	{
754fd385855SPaul Moore 	.cmd = NLBL_MGMT_C_PROTOCOLS,
755d15c345fSPaul Moore 	.flags = 0,
756fd385855SPaul Moore 	.policy = netlbl_mgmt_genl_policy,
757fd385855SPaul Moore 	.doit = NULL,
758fd385855SPaul Moore 	.dumpit = netlbl_mgmt_protocols,
759227c43c3SPavel Emelyanov 	},
760227c43c3SPavel Emelyanov 	{
761d15c345fSPaul Moore 	.cmd = NLBL_MGMT_C_VERSION,
762d15c345fSPaul Moore 	.flags = 0,
763fd385855SPaul Moore 	.policy = netlbl_mgmt_genl_policy,
764d15c345fSPaul Moore 	.doit = netlbl_mgmt_version,
765d15c345fSPaul Moore 	.dumpit = NULL,
766227c43c3SPavel Emelyanov 	},
767d15c345fSPaul Moore };
768d15c345fSPaul Moore 
769d15c345fSPaul Moore /*
770d15c345fSPaul Moore  * NetLabel Generic NETLINK Protocol Functions
771d15c345fSPaul Moore  */
772d15c345fSPaul Moore 
773d15c345fSPaul Moore /**
774d15c345fSPaul Moore  * netlbl_mgmt_genl_init - Register the NetLabel management component
775d15c345fSPaul Moore  *
776d15c345fSPaul Moore  * Description:
777d15c345fSPaul Moore  * Register the NetLabel management component with the Generic NETLINK
778d15c345fSPaul Moore  * mechanism.  Returns zero on success, negative values on failure.
779d15c345fSPaul Moore  *
780d15c345fSPaul Moore  */
78105705e4eSPavel Emelyanov int __init netlbl_mgmt_genl_init(void)
782d15c345fSPaul Moore {
7837ae740dfSMichał Mirosław 	return genl_register_family_with_ops(&netlbl_mgmt_gnl_family,
7847ae740dfSMichał Mirosław 		netlbl_mgmt_genl_ops, ARRAY_SIZE(netlbl_mgmt_genl_ops));
785d15c345fSPaul Moore }
786