xref: /openbmc/linux/net/netlabel/netlabel_mgmt.c (revision 63c41688)
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>
37d15c345fSPaul Moore #include <net/sock.h>
38d15c345fSPaul Moore #include <net/netlink.h>
39d15c345fSPaul Moore #include <net/genetlink.h>
4063c41688SPaul Moore #include <net/ip.h>
4163c41688SPaul Moore #include <net/ipv6.h>
42d15c345fSPaul Moore #include <net/netlabel.h>
43d15c345fSPaul Moore #include <net/cipso_ipv4.h>
44c783f1ceSPaul Moore #include <asm/atomic.h>
45d15c345fSPaul Moore 
46d15c345fSPaul Moore #include "netlabel_domainhash.h"
47d15c345fSPaul Moore #include "netlabel_user.h"
48d15c345fSPaul Moore #include "netlabel_mgmt.h"
49d15c345fSPaul Moore 
50c783f1ceSPaul Moore /* NetLabel configured protocol counter */
51c783f1ceSPaul Moore atomic_t netlabel_mgmt_protocount = ATOMIC_INIT(0);
5223bcdc1aSPaul Moore 
53fd385855SPaul Moore /* Argument struct for netlbl_domhsh_walk() */
54fd385855SPaul Moore struct netlbl_domhsh_walk_arg {
55fd385855SPaul Moore 	struct netlink_callback *nl_cb;
56fd385855SPaul Moore 	struct sk_buff *skb;
57fd385855SPaul Moore 	u32 seq;
58fd385855SPaul Moore };
59fd385855SPaul Moore 
60d15c345fSPaul Moore /* NetLabel Generic NETLINK CIPSOv4 family */
61d15c345fSPaul Moore static struct genl_family netlbl_mgmt_gnl_family = {
62d15c345fSPaul Moore 	.id = GENL_ID_GENERATE,
63d15c345fSPaul Moore 	.hdrsize = 0,
64d15c345fSPaul Moore 	.name = NETLBL_NLTYPE_MGMT_NAME,
65d15c345fSPaul Moore 	.version = NETLBL_PROTO_VERSION,
66fd385855SPaul Moore 	.maxattr = NLBL_MGMT_A_MAX,
67d15c345fSPaul Moore };
68d15c345fSPaul Moore 
69fd385855SPaul Moore /* NetLabel Netlink attribute policy */
70ef7c79edSPatrick McHardy static const struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = {
71fd385855SPaul Moore 	[NLBL_MGMT_A_DOMAIN] = { .type = NLA_NUL_STRING },
72fd385855SPaul Moore 	[NLBL_MGMT_A_PROTOCOL] = { .type = NLA_U32 },
73fd385855SPaul Moore 	[NLBL_MGMT_A_VERSION] = { .type = NLA_U32 },
74fd385855SPaul Moore 	[NLBL_MGMT_A_CV4DOI] = { .type = NLA_U32 },
75fd385855SPaul Moore };
76d15c345fSPaul Moore 
77d15c345fSPaul Moore /*
7863c41688SPaul Moore  * Helper Functions
7963c41688SPaul Moore  */
8063c41688SPaul Moore 
8163c41688SPaul Moore /**
8263c41688SPaul Moore  * netlbl_mgmt_add - Handle an ADD message
8363c41688SPaul Moore  * @info: the Generic NETLINK info block
8463c41688SPaul Moore  * @audit_info: NetLabel audit information
8563c41688SPaul Moore  *
8663c41688SPaul Moore  * Description:
8763c41688SPaul Moore  * Helper function for the ADD and ADDDEF messages to add the domain mappings
8863c41688SPaul Moore  * from the message to the hash table.  See netlabel.h for a description of the
8963c41688SPaul Moore  * message format.  Returns zero on success, negative values on failure.
9063c41688SPaul Moore  *
9163c41688SPaul Moore  */
9263c41688SPaul Moore static int netlbl_mgmt_add_common(struct genl_info *info,
9363c41688SPaul Moore 				  struct netlbl_audit *audit_info)
9463c41688SPaul Moore {
9563c41688SPaul Moore 	int ret_val = -EINVAL;
9663c41688SPaul Moore 	struct netlbl_dom_map *entry = NULL;
9763c41688SPaul Moore 	struct netlbl_domaddr_map *addrmap = NULL;
9863c41688SPaul Moore 	struct cipso_v4_doi *cipsov4 = NULL;
9963c41688SPaul Moore 	u32 tmp_val;
10063c41688SPaul Moore 
10163c41688SPaul Moore 	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
10263c41688SPaul Moore 	if (entry == NULL) {
10363c41688SPaul Moore 		ret_val = -ENOMEM;
10463c41688SPaul Moore 		goto add_failure;
10563c41688SPaul Moore 	}
10663c41688SPaul Moore 	entry->type = nla_get_u32(info->attrs[NLBL_MGMT_A_PROTOCOL]);
10763c41688SPaul Moore 	if (info->attrs[NLBL_MGMT_A_DOMAIN]) {
10863c41688SPaul Moore 		size_t tmp_size = nla_len(info->attrs[NLBL_MGMT_A_DOMAIN]);
10963c41688SPaul Moore 		entry->domain = kmalloc(tmp_size, GFP_KERNEL);
11063c41688SPaul Moore 		if (entry->domain == NULL) {
11163c41688SPaul Moore 			ret_val = -ENOMEM;
11263c41688SPaul Moore 			goto add_failure;
11363c41688SPaul Moore 		}
11463c41688SPaul Moore 		nla_strlcpy(entry->domain,
11563c41688SPaul Moore 			    info->attrs[NLBL_MGMT_A_DOMAIN], tmp_size);
11663c41688SPaul Moore 	}
11763c41688SPaul Moore 
11863c41688SPaul Moore 	/* NOTE: internally we allow/use a entry->type value of
11963c41688SPaul Moore 	 *       NETLBL_NLTYPE_ADDRSELECT but we don't currently allow users
12063c41688SPaul Moore 	 *       to pass that as a protocol value because we need to know the
12163c41688SPaul Moore 	 *       "real" protocol */
12263c41688SPaul Moore 
12363c41688SPaul Moore 	switch (entry->type) {
12463c41688SPaul Moore 	case NETLBL_NLTYPE_UNLABELED:
12563c41688SPaul Moore 		break;
12663c41688SPaul Moore 	case NETLBL_NLTYPE_CIPSOV4:
12763c41688SPaul Moore 		if (!info->attrs[NLBL_MGMT_A_CV4DOI])
12863c41688SPaul Moore 			goto add_failure;
12963c41688SPaul Moore 
13063c41688SPaul Moore 		tmp_val = nla_get_u32(info->attrs[NLBL_MGMT_A_CV4DOI]);
13163c41688SPaul Moore 		cipsov4 = cipso_v4_doi_getdef(tmp_val);
13263c41688SPaul Moore 		if (cipsov4 == NULL)
13363c41688SPaul Moore 			goto add_failure;
13463c41688SPaul Moore 		entry->type_def.cipsov4 = cipsov4;
13563c41688SPaul Moore 		break;
13663c41688SPaul Moore 	default:
13763c41688SPaul Moore 		goto add_failure;
13863c41688SPaul Moore 	}
13963c41688SPaul Moore 
14063c41688SPaul Moore 	if (info->attrs[NLBL_MGMT_A_IPV4ADDR]) {
14163c41688SPaul Moore 		struct in_addr *addr;
14263c41688SPaul Moore 		struct in_addr *mask;
14363c41688SPaul Moore 		struct netlbl_domaddr4_map *map;
14463c41688SPaul Moore 
14563c41688SPaul Moore 		addrmap = kzalloc(sizeof(*addrmap), GFP_KERNEL);
14663c41688SPaul Moore 		if (addrmap == NULL) {
14763c41688SPaul Moore 			ret_val = -ENOMEM;
14863c41688SPaul Moore 			goto add_failure;
14963c41688SPaul Moore 		}
15063c41688SPaul Moore 		INIT_LIST_HEAD(&addrmap->list4);
15163c41688SPaul Moore 		INIT_LIST_HEAD(&addrmap->list6);
15263c41688SPaul Moore 
15363c41688SPaul Moore 		if (nla_len(info->attrs[NLBL_MGMT_A_IPV4ADDR]) !=
15463c41688SPaul Moore 		    sizeof(struct in_addr)) {
15563c41688SPaul Moore 			ret_val = -EINVAL;
15663c41688SPaul Moore 			goto add_failure;
15763c41688SPaul Moore 		}
15863c41688SPaul Moore 		if (nla_len(info->attrs[NLBL_MGMT_A_IPV4MASK]) !=
15963c41688SPaul Moore 		    sizeof(struct in_addr)) {
16063c41688SPaul Moore 			ret_val = -EINVAL;
16163c41688SPaul Moore 			goto add_failure;
16263c41688SPaul Moore 		}
16363c41688SPaul Moore 		addr = nla_data(info->attrs[NLBL_MGMT_A_IPV4ADDR]);
16463c41688SPaul Moore 		mask = nla_data(info->attrs[NLBL_MGMT_A_IPV4MASK]);
16563c41688SPaul Moore 
16663c41688SPaul Moore 		map = kzalloc(sizeof(*map), GFP_KERNEL);
16763c41688SPaul Moore 		if (map == NULL) {
16863c41688SPaul Moore 			ret_val = -ENOMEM;
16963c41688SPaul Moore 			goto add_failure;
17063c41688SPaul Moore 		}
17163c41688SPaul Moore 		map->list.addr = addr->s_addr & mask->s_addr;
17263c41688SPaul Moore 		map->list.mask = mask->s_addr;
17363c41688SPaul Moore 		map->list.valid = 1;
17463c41688SPaul Moore 		map->type = entry->type;
17563c41688SPaul Moore 		if (cipsov4)
17663c41688SPaul Moore 			map->type_def.cipsov4 = cipsov4;
17763c41688SPaul Moore 
17863c41688SPaul Moore 		ret_val = netlbl_af4list_add(&map->list, &addrmap->list4);
17963c41688SPaul Moore 		if (ret_val != 0) {
18063c41688SPaul Moore 			kfree(map);
18163c41688SPaul Moore 			goto add_failure;
18263c41688SPaul Moore 		}
18363c41688SPaul Moore 
18463c41688SPaul Moore 		entry->type = NETLBL_NLTYPE_ADDRSELECT;
18563c41688SPaul Moore 		entry->type_def.addrsel = addrmap;
18663c41688SPaul Moore #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
18763c41688SPaul Moore 	} else if (info->attrs[NLBL_MGMT_A_IPV6ADDR]) {
18863c41688SPaul Moore 		struct in6_addr *addr;
18963c41688SPaul Moore 		struct in6_addr *mask;
19063c41688SPaul Moore 		struct netlbl_domaddr6_map *map;
19163c41688SPaul Moore 
19263c41688SPaul Moore 		addrmap = kzalloc(sizeof(*addrmap), GFP_KERNEL);
19363c41688SPaul Moore 		if (addrmap == NULL) {
19463c41688SPaul Moore 			ret_val = -ENOMEM;
19563c41688SPaul Moore 			goto add_failure;
19663c41688SPaul Moore 		}
19763c41688SPaul Moore 		INIT_LIST_HEAD(&addrmap->list4);
19863c41688SPaul Moore 		INIT_LIST_HEAD(&addrmap->list6);
19963c41688SPaul Moore 
20063c41688SPaul Moore 		if (nla_len(info->attrs[NLBL_MGMT_A_IPV6ADDR]) !=
20163c41688SPaul Moore 		    sizeof(struct in6_addr)) {
20263c41688SPaul Moore 			ret_val = -EINVAL;
20363c41688SPaul Moore 			goto add_failure;
20463c41688SPaul Moore 		}
20563c41688SPaul Moore 		if (nla_len(info->attrs[NLBL_MGMT_A_IPV6MASK]) !=
20663c41688SPaul Moore 		    sizeof(struct in6_addr)) {
20763c41688SPaul Moore 			ret_val = -EINVAL;
20863c41688SPaul Moore 			goto add_failure;
20963c41688SPaul Moore 		}
21063c41688SPaul Moore 		addr = nla_data(info->attrs[NLBL_MGMT_A_IPV6ADDR]);
21163c41688SPaul Moore 		mask = nla_data(info->attrs[NLBL_MGMT_A_IPV6MASK]);
21263c41688SPaul Moore 
21363c41688SPaul Moore 		map = kzalloc(sizeof(*map), GFP_KERNEL);
21463c41688SPaul Moore 		if (map == NULL) {
21563c41688SPaul Moore 			ret_val = -ENOMEM;
21663c41688SPaul Moore 			goto add_failure;
21763c41688SPaul Moore 		}
21863c41688SPaul Moore 		ipv6_addr_copy(&map->list.addr, addr);
21963c41688SPaul Moore 		map->list.addr.s6_addr32[0] &= mask->s6_addr32[0];
22063c41688SPaul Moore 		map->list.addr.s6_addr32[1] &= mask->s6_addr32[1];
22163c41688SPaul Moore 		map->list.addr.s6_addr32[2] &= mask->s6_addr32[2];
22263c41688SPaul Moore 		map->list.addr.s6_addr32[3] &= mask->s6_addr32[3];
22363c41688SPaul Moore 		ipv6_addr_copy(&map->list.mask, mask);
22463c41688SPaul Moore 		map->list.valid = 1;
22563c41688SPaul Moore 		map->type = entry->type;
22663c41688SPaul Moore 
22763c41688SPaul Moore 		ret_val = netlbl_af6list_add(&map->list, &addrmap->list6);
22863c41688SPaul Moore 		if (ret_val != 0) {
22963c41688SPaul Moore 			kfree(map);
23063c41688SPaul Moore 			goto add_failure;
23163c41688SPaul Moore 		}
23263c41688SPaul Moore 
23363c41688SPaul Moore 		entry->type = NETLBL_NLTYPE_ADDRSELECT;
23463c41688SPaul Moore 		entry->type_def.addrsel = addrmap;
23563c41688SPaul Moore #endif /* IPv6 */
23663c41688SPaul Moore 	}
23763c41688SPaul Moore 
23863c41688SPaul Moore 	ret_val = netlbl_domhsh_add(entry, audit_info);
23963c41688SPaul Moore 	if (ret_val != 0)
24063c41688SPaul Moore 		goto add_failure;
24163c41688SPaul Moore 
24263c41688SPaul Moore 	return 0;
24363c41688SPaul Moore 
24463c41688SPaul Moore add_failure:
24563c41688SPaul Moore 	if (cipsov4)
24663c41688SPaul Moore 		cipso_v4_doi_putdef(cipsov4);
24763c41688SPaul Moore 	if (entry)
24863c41688SPaul Moore 		kfree(entry->domain);
24963c41688SPaul Moore 	kfree(addrmap);
25063c41688SPaul Moore 	kfree(entry);
25163c41688SPaul Moore 	return ret_val;
25263c41688SPaul Moore }
25363c41688SPaul Moore 
25463c41688SPaul Moore /**
25563c41688SPaul Moore  * netlbl_mgmt_listentry - List a NetLabel/LSM domain map entry
25663c41688SPaul Moore  * @skb: the NETLINK buffer
25763c41688SPaul Moore  * @entry: the map entry
25863c41688SPaul Moore  *
25963c41688SPaul Moore  * Description:
26063c41688SPaul Moore  * This function is a helper function used by the LISTALL and LISTDEF command
26163c41688SPaul Moore  * handlers.  The caller is responsibile for ensuring that the RCU read lock
26263c41688SPaul Moore  * is held.  Returns zero on success, negative values on failure.
26363c41688SPaul Moore  *
26463c41688SPaul Moore  */
26563c41688SPaul Moore static int netlbl_mgmt_listentry(struct sk_buff *skb,
26663c41688SPaul Moore 				 struct netlbl_dom_map *entry)
26763c41688SPaul Moore {
26863c41688SPaul Moore 	int ret_val;
26963c41688SPaul Moore 	struct nlattr *nla_a;
27063c41688SPaul Moore 	struct nlattr *nla_b;
27163c41688SPaul Moore 	struct netlbl_af4list *iter4;
27263c41688SPaul Moore #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
27363c41688SPaul Moore 	struct netlbl_af6list *iter6;
27463c41688SPaul Moore #endif
27563c41688SPaul Moore 
27663c41688SPaul Moore 	if (entry->domain != NULL) {
27763c41688SPaul Moore 		ret_val = nla_put_string(skb,
27863c41688SPaul Moore 					 NLBL_MGMT_A_DOMAIN, entry->domain);
27963c41688SPaul Moore 		if (ret_val != 0)
28063c41688SPaul Moore 			return ret_val;
28163c41688SPaul Moore 	}
28263c41688SPaul Moore 
28363c41688SPaul Moore 	switch (entry->type) {
28463c41688SPaul Moore 	case NETLBL_NLTYPE_ADDRSELECT:
28563c41688SPaul Moore 		nla_a = nla_nest_start(skb, NLBL_MGMT_A_SELECTORLIST);
28663c41688SPaul Moore 		if (nla_a == NULL)
28763c41688SPaul Moore 			return -ENOMEM;
28863c41688SPaul Moore 
28963c41688SPaul Moore 		netlbl_af4list_foreach_rcu(iter4,
29063c41688SPaul Moore 					   &entry->type_def.addrsel->list4) {
29163c41688SPaul Moore 			struct netlbl_domaddr4_map *map4;
29263c41688SPaul Moore 			struct in_addr addr_struct;
29363c41688SPaul Moore 
29463c41688SPaul Moore 			nla_b = nla_nest_start(skb, NLBL_MGMT_A_ADDRSELECTOR);
29563c41688SPaul Moore 			if (nla_b == NULL)
29663c41688SPaul Moore 				return -ENOMEM;
29763c41688SPaul Moore 
29863c41688SPaul Moore 			addr_struct.s_addr = iter4->addr;
29963c41688SPaul Moore 			ret_val = nla_put(skb, NLBL_MGMT_A_IPV4ADDR,
30063c41688SPaul Moore 					  sizeof(struct in_addr),
30163c41688SPaul Moore 					  &addr_struct);
30263c41688SPaul Moore 			if (ret_val != 0)
30363c41688SPaul Moore 				return ret_val;
30463c41688SPaul Moore 			addr_struct.s_addr = iter4->mask;
30563c41688SPaul Moore 			ret_val = nla_put(skb, NLBL_MGMT_A_IPV4MASK,
30663c41688SPaul Moore 					  sizeof(struct in_addr),
30763c41688SPaul Moore 					  &addr_struct);
30863c41688SPaul Moore 			if (ret_val != 0)
30963c41688SPaul Moore 				return ret_val;
31063c41688SPaul Moore 			map4 = netlbl_domhsh_addr4_entry(iter4);
31163c41688SPaul Moore 			ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL,
31263c41688SPaul Moore 					      map4->type);
31363c41688SPaul Moore 			if (ret_val != 0)
31463c41688SPaul Moore 				return ret_val;
31563c41688SPaul Moore 			switch (map4->type) {
31663c41688SPaul Moore 			case NETLBL_NLTYPE_CIPSOV4:
31763c41688SPaul Moore 				ret_val = nla_put_u32(skb, NLBL_MGMT_A_CV4DOI,
31863c41688SPaul Moore 						  map4->type_def.cipsov4->doi);
31963c41688SPaul Moore 				if (ret_val != 0)
32063c41688SPaul Moore 					return ret_val;
32163c41688SPaul Moore 				break;
32263c41688SPaul Moore 			}
32363c41688SPaul Moore 
32463c41688SPaul Moore 			nla_nest_end(skb, nla_b);
32563c41688SPaul Moore 		}
32663c41688SPaul Moore #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
32763c41688SPaul Moore 		netlbl_af6list_foreach_rcu(iter6,
32863c41688SPaul Moore 					   &entry->type_def.addrsel->list6) {
32963c41688SPaul Moore 			struct netlbl_domaddr6_map *map6;
33063c41688SPaul Moore 
33163c41688SPaul Moore 			nla_b = nla_nest_start(skb, NLBL_MGMT_A_ADDRSELECTOR);
33263c41688SPaul Moore 			if (nla_b == NULL)
33363c41688SPaul Moore 				return -ENOMEM;
33463c41688SPaul Moore 
33563c41688SPaul Moore 			ret_val = nla_put(skb, NLBL_MGMT_A_IPV6ADDR,
33663c41688SPaul Moore 					  sizeof(struct in6_addr),
33763c41688SPaul Moore 					  &iter6->addr);
33863c41688SPaul Moore 			if (ret_val != 0)
33963c41688SPaul Moore 				return ret_val;
34063c41688SPaul Moore 			ret_val = nla_put(skb, NLBL_MGMT_A_IPV6MASK,
34163c41688SPaul Moore 					  sizeof(struct in6_addr),
34263c41688SPaul Moore 					  &iter6->mask);
34363c41688SPaul Moore 			if (ret_val != 0)
34463c41688SPaul Moore 				return ret_val;
34563c41688SPaul Moore 			map6 = netlbl_domhsh_addr6_entry(iter6);
34663c41688SPaul Moore 			ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL,
34763c41688SPaul Moore 					      map6->type);
34863c41688SPaul Moore 			if (ret_val != 0)
34963c41688SPaul Moore 				return ret_val;
35063c41688SPaul Moore 
35163c41688SPaul Moore 			nla_nest_end(skb, nla_b);
35263c41688SPaul Moore 		}
35363c41688SPaul Moore #endif /* IPv6 */
35463c41688SPaul Moore 
35563c41688SPaul Moore 		nla_nest_end(skb, nla_a);
35663c41688SPaul Moore 		break;
35763c41688SPaul Moore 	case NETLBL_NLTYPE_UNLABELED:
35863c41688SPaul Moore 		ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL, entry->type);
35963c41688SPaul Moore 		break;
36063c41688SPaul Moore 	case NETLBL_NLTYPE_CIPSOV4:
36163c41688SPaul Moore 		ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL, entry->type);
36263c41688SPaul Moore 		if (ret_val != 0)
36363c41688SPaul Moore 			return ret_val;
36463c41688SPaul Moore 		ret_val = nla_put_u32(skb, NLBL_MGMT_A_CV4DOI,
36563c41688SPaul Moore 				      entry->type_def.cipsov4->doi);
36663c41688SPaul Moore 		break;
36763c41688SPaul Moore 	}
36863c41688SPaul Moore 
36963c41688SPaul Moore 	return ret_val;
37063c41688SPaul Moore }
37163c41688SPaul Moore 
37263c41688SPaul Moore /*
373d15c345fSPaul Moore  * NetLabel Command Handlers
374d15c345fSPaul Moore  */
375d15c345fSPaul Moore 
376d15c345fSPaul Moore /**
377d15c345fSPaul Moore  * netlbl_mgmt_add - Handle an ADD message
378d15c345fSPaul Moore  * @skb: the NETLINK buffer
379d15c345fSPaul Moore  * @info: the Generic NETLINK info block
380d15c345fSPaul Moore  *
381d15c345fSPaul Moore  * Description:
382d15c345fSPaul Moore  * Process a user generated ADD message and add the domains from the message
383d15c345fSPaul Moore  * to the hash table.  See netlabel.h for a description of the message format.
384d15c345fSPaul Moore  * Returns zero on success, negative values on failure.
385d15c345fSPaul Moore  *
386d15c345fSPaul Moore  */
387d15c345fSPaul Moore static int netlbl_mgmt_add(struct sk_buff *skb, struct genl_info *info)
388d15c345fSPaul Moore {
38995d4e6beSPaul Moore 	struct netlbl_audit audit_info;
390d15c345fSPaul Moore 
39163c41688SPaul Moore 	if ((!info->attrs[NLBL_MGMT_A_DOMAIN]) ||
39263c41688SPaul Moore 	    (!info->attrs[NLBL_MGMT_A_PROTOCOL]) ||
39363c41688SPaul Moore 	    (info->attrs[NLBL_MGMT_A_IPV4ADDR] &&
39463c41688SPaul Moore 	     info->attrs[NLBL_MGMT_A_IPV6ADDR]) ||
39563c41688SPaul Moore 	    (info->attrs[NLBL_MGMT_A_IPV4MASK] &&
39663c41688SPaul Moore 	     info->attrs[NLBL_MGMT_A_IPV6MASK]) ||
39763c41688SPaul Moore 	    ((info->attrs[NLBL_MGMT_A_IPV4ADDR] != NULL) ^
39863c41688SPaul Moore 	     (info->attrs[NLBL_MGMT_A_IPV4MASK] != NULL)) ||
39963c41688SPaul Moore 	    ((info->attrs[NLBL_MGMT_A_IPV6ADDR] != NULL) ^
40063c41688SPaul Moore 	     (info->attrs[NLBL_MGMT_A_IPV6MASK] != NULL)))
40163c41688SPaul Moore 		return -EINVAL;
402d15c345fSPaul Moore 
40395d4e6beSPaul Moore 	netlbl_netlink_auditinfo(skb, &audit_info);
40495d4e6beSPaul Moore 
40563c41688SPaul Moore 	return netlbl_mgmt_add_common(info, &audit_info);
406d15c345fSPaul Moore }
407d15c345fSPaul Moore 
408d15c345fSPaul Moore /**
409d15c345fSPaul Moore  * netlbl_mgmt_remove - Handle a REMOVE message
410d15c345fSPaul Moore  * @skb: the NETLINK buffer
411d15c345fSPaul Moore  * @info: the Generic NETLINK info block
412d15c345fSPaul Moore  *
413d15c345fSPaul Moore  * Description:
414d15c345fSPaul Moore  * Process a user generated REMOVE message and remove the specified domain
415d15c345fSPaul Moore  * mappings.  Returns zero on success, negative values on failure.
416d15c345fSPaul Moore  *
417d15c345fSPaul Moore  */
418d15c345fSPaul Moore static int netlbl_mgmt_remove(struct sk_buff *skb, struct genl_info *info)
419d15c345fSPaul Moore {
420fd385855SPaul Moore 	char *domain;
42195d4e6beSPaul Moore 	struct netlbl_audit audit_info;
422d15c345fSPaul Moore 
423fd385855SPaul Moore 	if (!info->attrs[NLBL_MGMT_A_DOMAIN])
424fd385855SPaul Moore 		return -EINVAL;
425d15c345fSPaul Moore 
42695d4e6beSPaul Moore 	netlbl_netlink_auditinfo(skb, &audit_info);
42795d4e6beSPaul Moore 
428fd385855SPaul Moore 	domain = nla_data(info->attrs[NLBL_MGMT_A_DOMAIN]);
42995d4e6beSPaul Moore 	return netlbl_domhsh_remove(domain, &audit_info);
430d15c345fSPaul Moore }
431d15c345fSPaul Moore 
432fd385855SPaul Moore /**
433fd385855SPaul Moore  * netlbl_mgmt_listall_cb - netlbl_domhsh_walk() callback for LISTALL
434fd385855SPaul Moore  * @entry: the domain mapping hash table entry
435fd385855SPaul Moore  * @arg: the netlbl_domhsh_walk_arg structure
436fd385855SPaul Moore  *
437fd385855SPaul Moore  * Description:
438fd385855SPaul Moore  * This function is designed to be used as a callback to the
439fd385855SPaul Moore  * netlbl_domhsh_walk() function for use in generating a response for a LISTALL
440fd385855SPaul Moore  * message.  Returns the size of the message on success, negative values on
441fd385855SPaul Moore  * failure.
442fd385855SPaul Moore  *
443fd385855SPaul Moore  */
444fd385855SPaul Moore static int netlbl_mgmt_listall_cb(struct netlbl_dom_map *entry, void *arg)
445fd385855SPaul Moore {
446fd385855SPaul Moore 	int ret_val = -ENOMEM;
447fd385855SPaul Moore 	struct netlbl_domhsh_walk_arg *cb_arg = arg;
448fd385855SPaul Moore 	void *data;
449d15c345fSPaul Moore 
45017c157c8SThomas Graf 	data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).pid,
45117c157c8SThomas Graf 			   cb_arg->seq, &netlbl_mgmt_gnl_family,
45217c157c8SThomas Graf 			   NLM_F_MULTI, NLBL_MGMT_C_LISTALL);
453fd385855SPaul Moore 	if (data == NULL)
454fd385855SPaul Moore 		goto listall_cb_failure;
455fd385855SPaul Moore 
45663c41688SPaul Moore 	ret_val = netlbl_mgmt_listentry(cb_arg->skb, entry);
457fd385855SPaul Moore 	if (ret_val != 0)
458fd385855SPaul Moore 		goto listall_cb_failure;
459fd385855SPaul Moore 
460fd385855SPaul Moore 	cb_arg->seq++;
461fd385855SPaul Moore 	return genlmsg_end(cb_arg->skb, data);
462fd385855SPaul Moore 
463fd385855SPaul Moore listall_cb_failure:
464fd385855SPaul Moore 	genlmsg_cancel(cb_arg->skb, data);
465d15c345fSPaul Moore 	return ret_val;
466d15c345fSPaul Moore }
467d15c345fSPaul Moore 
468d15c345fSPaul Moore /**
469fd385855SPaul Moore  * netlbl_mgmt_listall - Handle a LISTALL message
470d15c345fSPaul Moore  * @skb: the NETLINK buffer
471fd385855SPaul Moore  * @cb: the NETLINK callback
472d15c345fSPaul Moore  *
473d15c345fSPaul Moore  * Description:
474fd385855SPaul Moore  * Process a user generated LISTALL message and dumps the domain hash table in
475fd385855SPaul Moore  * a form suitable for use in a kernel generated LISTALL message.  Returns zero
476fd385855SPaul Moore  * on success, negative values on failure.
477d15c345fSPaul Moore  *
478d15c345fSPaul Moore  */
479fd385855SPaul Moore static int netlbl_mgmt_listall(struct sk_buff *skb,
480fd385855SPaul Moore 			       struct netlink_callback *cb)
481d15c345fSPaul Moore {
482fd385855SPaul Moore 	struct netlbl_domhsh_walk_arg cb_arg;
483fd385855SPaul Moore 	u32 skip_bkt = cb->args[0];
484fd385855SPaul Moore 	u32 skip_chain = cb->args[1];
485d15c345fSPaul Moore 
486fd385855SPaul Moore 	cb_arg.nl_cb = cb;
487fd385855SPaul Moore 	cb_arg.skb = skb;
488fd385855SPaul Moore 	cb_arg.seq = cb->nlh->nlmsg_seq;
489d15c345fSPaul Moore 
490fd385855SPaul Moore 	netlbl_domhsh_walk(&skip_bkt,
491fd385855SPaul Moore 			   &skip_chain,
492fd385855SPaul Moore 			   netlbl_mgmt_listall_cb,
493fd385855SPaul Moore 			   &cb_arg);
494d15c345fSPaul Moore 
495fd385855SPaul Moore 	cb->args[0] = skip_bkt;
496fd385855SPaul Moore 	cb->args[1] = skip_chain;
497fd385855SPaul Moore 	return skb->len;
498d15c345fSPaul Moore }
499d15c345fSPaul Moore 
500d15c345fSPaul Moore /**
501d15c345fSPaul Moore  * netlbl_mgmt_adddef - Handle an ADDDEF message
502d15c345fSPaul Moore  * @skb: the NETLINK buffer
503d15c345fSPaul Moore  * @info: the Generic NETLINK info block
504d15c345fSPaul Moore  *
505d15c345fSPaul Moore  * Description:
506d15c345fSPaul Moore  * Process a user generated ADDDEF message and respond accordingly.  Returns
507d15c345fSPaul Moore  * zero on success, negative values on failure.
508d15c345fSPaul Moore  *
509d15c345fSPaul Moore  */
510d15c345fSPaul Moore static int netlbl_mgmt_adddef(struct sk_buff *skb, struct genl_info *info)
511d15c345fSPaul Moore {
51295d4e6beSPaul Moore 	struct netlbl_audit audit_info;
513d15c345fSPaul Moore 
51463c41688SPaul Moore 	if ((!info->attrs[NLBL_MGMT_A_PROTOCOL]) ||
51563c41688SPaul Moore 	    (info->attrs[NLBL_MGMT_A_IPV4ADDR] &&
51663c41688SPaul Moore 	     info->attrs[NLBL_MGMT_A_IPV6ADDR]) ||
51763c41688SPaul Moore 	    (info->attrs[NLBL_MGMT_A_IPV4MASK] &&
51863c41688SPaul Moore 	     info->attrs[NLBL_MGMT_A_IPV6MASK]) ||
51963c41688SPaul Moore 	    ((info->attrs[NLBL_MGMT_A_IPV4ADDR] != NULL) ^
52063c41688SPaul Moore 	     (info->attrs[NLBL_MGMT_A_IPV4MASK] != NULL)) ||
52163c41688SPaul Moore 	    ((info->attrs[NLBL_MGMT_A_IPV6ADDR] != NULL) ^
52263c41688SPaul Moore 	     (info->attrs[NLBL_MGMT_A_IPV6MASK] != NULL)))
52363c41688SPaul Moore 		return -EINVAL;
524d15c345fSPaul Moore 
52595d4e6beSPaul Moore 	netlbl_netlink_auditinfo(skb, &audit_info);
52695d4e6beSPaul Moore 
52763c41688SPaul Moore 	return netlbl_mgmt_add_common(info, &audit_info);
528d15c345fSPaul Moore }
529d15c345fSPaul Moore 
530d15c345fSPaul Moore /**
531d15c345fSPaul Moore  * netlbl_mgmt_removedef - Handle a REMOVEDEF message
532d15c345fSPaul Moore  * @skb: the NETLINK buffer
533d15c345fSPaul Moore  * @info: the Generic NETLINK info block
534d15c345fSPaul Moore  *
535d15c345fSPaul Moore  * Description:
536d15c345fSPaul Moore  * Process a user generated REMOVEDEF message and remove the default domain
537d15c345fSPaul Moore  * mapping.  Returns zero on success, negative values on failure.
538d15c345fSPaul Moore  *
539d15c345fSPaul Moore  */
540d15c345fSPaul Moore static int netlbl_mgmt_removedef(struct sk_buff *skb, struct genl_info *info)
541d15c345fSPaul Moore {
54295d4e6beSPaul Moore 	struct netlbl_audit audit_info;
54395d4e6beSPaul Moore 
54495d4e6beSPaul Moore 	netlbl_netlink_auditinfo(skb, &audit_info);
54595d4e6beSPaul Moore 
54695d4e6beSPaul Moore 	return netlbl_domhsh_remove_default(&audit_info);
547d15c345fSPaul Moore }
548d15c345fSPaul Moore 
549d15c345fSPaul Moore /**
550d15c345fSPaul Moore  * netlbl_mgmt_listdef - Handle a LISTDEF message
551d15c345fSPaul Moore  * @skb: the NETLINK buffer
552d15c345fSPaul Moore  * @info: the Generic NETLINK info block
553d15c345fSPaul Moore  *
554d15c345fSPaul Moore  * Description:
555d15c345fSPaul Moore  * Process a user generated LISTDEF message and dumps the default domain
556d15c345fSPaul Moore  * mapping in a form suitable for use in a kernel generated LISTDEF message.
557d15c345fSPaul Moore  * Returns zero on success, negative values on failure.
558d15c345fSPaul Moore  *
559d15c345fSPaul Moore  */
560d15c345fSPaul Moore static int netlbl_mgmt_listdef(struct sk_buff *skb, struct genl_info *info)
561d15c345fSPaul Moore {
562d15c345fSPaul Moore 	int ret_val = -ENOMEM;
563fd385855SPaul Moore 	struct sk_buff *ans_skb = NULL;
564fd385855SPaul Moore 	void *data;
565fd385855SPaul Moore 	struct netlbl_dom_map *entry;
566d15c345fSPaul Moore 
567339bf98fSThomas Graf 	ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
568d15c345fSPaul Moore 	if (ans_skb == NULL)
569fd385855SPaul Moore 		return -ENOMEM;
57017c157c8SThomas Graf 	data = genlmsg_put_reply(ans_skb, info, &netlbl_mgmt_gnl_family,
57117c157c8SThomas Graf 				 0, NLBL_MGMT_C_LISTDEF);
572fd385855SPaul Moore 	if (data == NULL)
573fd385855SPaul Moore 		goto listdef_failure;
574d15c345fSPaul Moore 
575fd385855SPaul Moore 	rcu_read_lock();
576fd385855SPaul Moore 	entry = netlbl_domhsh_getentry(NULL);
577fd385855SPaul Moore 	if (entry == NULL) {
578fd385855SPaul Moore 		ret_val = -ENOENT;
579fd385855SPaul Moore 		goto listdef_failure_lock;
580fd385855SPaul Moore 	}
58163c41688SPaul Moore 	ret_val = netlbl_mgmt_listentry(ans_skb, entry);
582fd385855SPaul Moore 	rcu_read_unlock();
58363c41688SPaul Moore 	if (ret_val != 0)
58463c41688SPaul Moore 		goto listdef_failure;
585fd385855SPaul Moore 
586fd385855SPaul Moore 	genlmsg_end(ans_skb, data);
587fe785beeSDenis V. Lunev 	return genlmsg_reply(ans_skb, info);
588d15c345fSPaul Moore 
589fd385855SPaul Moore listdef_failure_lock:
590fd385855SPaul Moore 	rcu_read_unlock();
591d15c345fSPaul Moore listdef_failure:
592fd385855SPaul Moore 	kfree_skb(ans_skb);
593d15c345fSPaul Moore 	return ret_val;
594d15c345fSPaul Moore }
595d15c345fSPaul Moore 
596d15c345fSPaul Moore /**
597fd385855SPaul Moore  * netlbl_mgmt_protocols_cb - Write an individual PROTOCOL message response
598fd385855SPaul Moore  * @skb: the skb to write to
599fd385855SPaul Moore  * @seq: the NETLINK sequence number
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 {
783227c43c3SPavel Emelyanov 	int ret_val, i;
784d15c345fSPaul Moore 
785d15c345fSPaul Moore 	ret_val = genl_register_family(&netlbl_mgmt_gnl_family);
786d15c345fSPaul Moore 	if (ret_val != 0)
787d15c345fSPaul Moore 		return ret_val;
788d15c345fSPaul Moore 
789227c43c3SPavel Emelyanov 	for (i = 0; i < ARRAY_SIZE(netlbl_mgmt_genl_ops); i++) {
790d15c345fSPaul Moore 		ret_val = genl_register_ops(&netlbl_mgmt_gnl_family,
791227c43c3SPavel Emelyanov 				&netlbl_mgmt_genl_ops[i]);
792d15c345fSPaul Moore 		if (ret_val != 0)
793d15c345fSPaul Moore 			return ret_val;
794227c43c3SPavel Emelyanov 	}
795d15c345fSPaul Moore 
796d15c345fSPaul Moore 	return 0;
797d15c345fSPaul Moore }
798