xref: /openbmc/linux/net/netlabel/netlabel_mgmt.c (revision 4de46d5e)
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  *
882c21bfaSPaul Moore  * Author: Paul Moore <paul@paul-moore.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
26d484ff15SJeff Kirsher  * along with this program;  if not, see <http://www.gnu.org/licenses/>.
27d15c345fSPaul Moore  *
28d15c345fSPaul Moore  */
29d15c345fSPaul Moore 
30d15c345fSPaul Moore #include <linux/types.h>
31d15c345fSPaul Moore #include <linux/socket.h>
32d15c345fSPaul Moore #include <linux/string.h>
33d15c345fSPaul Moore #include <linux/skbuff.h>
3463c41688SPaul Moore #include <linux/in.h>
3563c41688SPaul Moore #include <linux/in6.h>
365a0e3ad6STejun Heo #include <linux/slab.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>
4460063497SArun Sharma #include <linux/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_domaddr_map *addrmap = NULL;
9763c41688SPaul Moore 	struct cipso_v4_doi *cipsov4 = NULL;
9863c41688SPaul Moore 	u32 tmp_val;
994de46d5eSMarkus Elfring 	struct netlbl_dom_map *entry = kzalloc(sizeof(*entry), GFP_KERNEL);
10063c41688SPaul Moore 
1014de46d5eSMarkus Elfring 	if (!entry)
1024de46d5eSMarkus Elfring 		return -ENOMEM;
1036a8b7f0cSPaul Moore 	entry->def.type = nla_get_u32(info->attrs[NLBL_MGMT_A_PROTOCOL]);
10463c41688SPaul Moore 	if (info->attrs[NLBL_MGMT_A_DOMAIN]) {
10563c41688SPaul Moore 		size_t tmp_size = nla_len(info->attrs[NLBL_MGMT_A_DOMAIN]);
10663c41688SPaul Moore 		entry->domain = kmalloc(tmp_size, GFP_KERNEL);
10763c41688SPaul Moore 		if (entry->domain == NULL) {
10863c41688SPaul Moore 			ret_val = -ENOMEM;
1094de46d5eSMarkus Elfring 			goto add_free_entry;
11063c41688SPaul Moore 		}
11163c41688SPaul Moore 		nla_strlcpy(entry->domain,
11263c41688SPaul Moore 			    info->attrs[NLBL_MGMT_A_DOMAIN], tmp_size);
11363c41688SPaul Moore 	}
11463c41688SPaul Moore 
1156a8b7f0cSPaul Moore 	/* NOTE: internally we allow/use a entry->def.type value of
11663c41688SPaul Moore 	 *       NETLBL_NLTYPE_ADDRSELECT but we don't currently allow users
11763c41688SPaul Moore 	 *       to pass that as a protocol value because we need to know the
11863c41688SPaul Moore 	 *       "real" protocol */
11963c41688SPaul Moore 
1206a8b7f0cSPaul Moore 	switch (entry->def.type) {
12163c41688SPaul Moore 	case NETLBL_NLTYPE_UNLABELED:
12263c41688SPaul Moore 		break;
12363c41688SPaul Moore 	case NETLBL_NLTYPE_CIPSOV4:
12463c41688SPaul Moore 		if (!info->attrs[NLBL_MGMT_A_CV4DOI])
1254de46d5eSMarkus Elfring 			goto add_free_domain;
12663c41688SPaul Moore 
12763c41688SPaul Moore 		tmp_val = nla_get_u32(info->attrs[NLBL_MGMT_A_CV4DOI]);
12863c41688SPaul Moore 		cipsov4 = cipso_v4_doi_getdef(tmp_val);
12963c41688SPaul Moore 		if (cipsov4 == NULL)
1304de46d5eSMarkus Elfring 			goto add_free_domain;
1316a8b7f0cSPaul Moore 		entry->def.cipso = cipsov4;
13263c41688SPaul Moore 		break;
13363c41688SPaul Moore 	default:
1344de46d5eSMarkus Elfring 		goto add_free_domain;
13563c41688SPaul Moore 	}
13663c41688SPaul Moore 
13763c41688SPaul Moore 	if (info->attrs[NLBL_MGMT_A_IPV4ADDR]) {
13863c41688SPaul Moore 		struct in_addr *addr;
13963c41688SPaul Moore 		struct in_addr *mask;
14063c41688SPaul Moore 		struct netlbl_domaddr4_map *map;
14163c41688SPaul Moore 
14263c41688SPaul Moore 		addrmap = kzalloc(sizeof(*addrmap), GFP_KERNEL);
14363c41688SPaul Moore 		if (addrmap == NULL) {
14463c41688SPaul Moore 			ret_val = -ENOMEM;
1454de46d5eSMarkus Elfring 			goto add_doi_put_def;
14663c41688SPaul Moore 		}
14763c41688SPaul Moore 		INIT_LIST_HEAD(&addrmap->list4);
14863c41688SPaul Moore 		INIT_LIST_HEAD(&addrmap->list6);
14963c41688SPaul Moore 
15063c41688SPaul Moore 		if (nla_len(info->attrs[NLBL_MGMT_A_IPV4ADDR]) !=
15163c41688SPaul Moore 		    sizeof(struct in_addr)) {
15263c41688SPaul Moore 			ret_val = -EINVAL;
1534de46d5eSMarkus Elfring 			goto add_free_addrmap;
15463c41688SPaul Moore 		}
15563c41688SPaul Moore 		if (nla_len(info->attrs[NLBL_MGMT_A_IPV4MASK]) !=
15663c41688SPaul Moore 		    sizeof(struct in_addr)) {
15763c41688SPaul Moore 			ret_val = -EINVAL;
1584de46d5eSMarkus Elfring 			goto add_free_addrmap;
15963c41688SPaul Moore 		}
16063c41688SPaul Moore 		addr = nla_data(info->attrs[NLBL_MGMT_A_IPV4ADDR]);
16163c41688SPaul Moore 		mask = nla_data(info->attrs[NLBL_MGMT_A_IPV4MASK]);
16263c41688SPaul Moore 
16363c41688SPaul Moore 		map = kzalloc(sizeof(*map), GFP_KERNEL);
16463c41688SPaul Moore 		if (map == NULL) {
16563c41688SPaul Moore 			ret_val = -ENOMEM;
1664de46d5eSMarkus Elfring 			goto add_free_addrmap;
16763c41688SPaul Moore 		}
16863c41688SPaul Moore 		map->list.addr = addr->s_addr & mask->s_addr;
16963c41688SPaul Moore 		map->list.mask = mask->s_addr;
17063c41688SPaul Moore 		map->list.valid = 1;
1716a8b7f0cSPaul Moore 		map->def.type = entry->def.type;
17263c41688SPaul Moore 		if (cipsov4)
1736a8b7f0cSPaul Moore 			map->def.cipso = cipsov4;
17463c41688SPaul Moore 
17563c41688SPaul Moore 		ret_val = netlbl_af4list_add(&map->list, &addrmap->list4);
17663c41688SPaul Moore 		if (ret_val != 0) {
17763c41688SPaul Moore 			kfree(map);
1784de46d5eSMarkus Elfring 			goto add_free_addrmap;
17963c41688SPaul Moore 		}
18063c41688SPaul Moore 
1816a8b7f0cSPaul Moore 		entry->def.type = NETLBL_NLTYPE_ADDRSELECT;
1826a8b7f0cSPaul Moore 		entry->def.addrsel = addrmap;
183dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6)
18463c41688SPaul Moore 	} else if (info->attrs[NLBL_MGMT_A_IPV6ADDR]) {
18563c41688SPaul Moore 		struct in6_addr *addr;
18663c41688SPaul Moore 		struct in6_addr *mask;
18763c41688SPaul Moore 		struct netlbl_domaddr6_map *map;
18863c41688SPaul Moore 
18963c41688SPaul Moore 		addrmap = kzalloc(sizeof(*addrmap), GFP_KERNEL);
19063c41688SPaul Moore 		if (addrmap == NULL) {
19163c41688SPaul Moore 			ret_val = -ENOMEM;
1924de46d5eSMarkus Elfring 			goto add_doi_put_def;
19363c41688SPaul Moore 		}
19463c41688SPaul Moore 		INIT_LIST_HEAD(&addrmap->list4);
19563c41688SPaul Moore 		INIT_LIST_HEAD(&addrmap->list6);
19663c41688SPaul Moore 
19763c41688SPaul Moore 		if (nla_len(info->attrs[NLBL_MGMT_A_IPV6ADDR]) !=
19863c41688SPaul Moore 		    sizeof(struct in6_addr)) {
19963c41688SPaul Moore 			ret_val = -EINVAL;
2004de46d5eSMarkus Elfring 			goto add_free_addrmap;
20163c41688SPaul Moore 		}
20263c41688SPaul Moore 		if (nla_len(info->attrs[NLBL_MGMT_A_IPV6MASK]) !=
20363c41688SPaul Moore 		    sizeof(struct in6_addr)) {
20463c41688SPaul Moore 			ret_val = -EINVAL;
2054de46d5eSMarkus Elfring 			goto add_free_addrmap;
20663c41688SPaul Moore 		}
20763c41688SPaul Moore 		addr = nla_data(info->attrs[NLBL_MGMT_A_IPV6ADDR]);
20863c41688SPaul Moore 		mask = nla_data(info->attrs[NLBL_MGMT_A_IPV6MASK]);
20963c41688SPaul Moore 
21063c41688SPaul Moore 		map = kzalloc(sizeof(*map), GFP_KERNEL);
21163c41688SPaul Moore 		if (map == NULL) {
21263c41688SPaul Moore 			ret_val = -ENOMEM;
2134de46d5eSMarkus Elfring 			goto add_free_addrmap;
21463c41688SPaul Moore 		}
2154e3fd7a0SAlexey Dobriyan 		map->list.addr = *addr;
21663c41688SPaul Moore 		map->list.addr.s6_addr32[0] &= mask->s6_addr32[0];
21763c41688SPaul Moore 		map->list.addr.s6_addr32[1] &= mask->s6_addr32[1];
21863c41688SPaul Moore 		map->list.addr.s6_addr32[2] &= mask->s6_addr32[2];
21963c41688SPaul Moore 		map->list.addr.s6_addr32[3] &= mask->s6_addr32[3];
2204e3fd7a0SAlexey Dobriyan 		map->list.mask = *mask;
22163c41688SPaul Moore 		map->list.valid = 1;
2226a8b7f0cSPaul Moore 		map->def.type = entry->def.type;
22363c41688SPaul Moore 
22463c41688SPaul Moore 		ret_val = netlbl_af6list_add(&map->list, &addrmap->list6);
22563c41688SPaul Moore 		if (ret_val != 0) {
22663c41688SPaul Moore 			kfree(map);
2274de46d5eSMarkus Elfring 			goto add_free_addrmap;
22863c41688SPaul Moore 		}
22963c41688SPaul Moore 
2306a8b7f0cSPaul Moore 		entry->def.type = NETLBL_NLTYPE_ADDRSELECT;
2316a8b7f0cSPaul Moore 		entry->def.addrsel = addrmap;
23263c41688SPaul Moore #endif /* IPv6 */
23363c41688SPaul Moore 	}
23463c41688SPaul Moore 
23563c41688SPaul Moore 	ret_val = netlbl_domhsh_add(entry, audit_info);
23663c41688SPaul Moore 	if (ret_val != 0)
2374de46d5eSMarkus Elfring 		goto add_free_addrmap;
23863c41688SPaul Moore 
23963c41688SPaul Moore 	return 0;
24063c41688SPaul Moore 
2414de46d5eSMarkus Elfring add_free_addrmap:
24263c41688SPaul Moore 	kfree(addrmap);
2434de46d5eSMarkus Elfring add_doi_put_def:
2444de46d5eSMarkus Elfring 	cipso_v4_doi_putdef(cipsov4);
2454de46d5eSMarkus Elfring add_free_domain:
2464de46d5eSMarkus Elfring 	kfree(entry->domain);
2474de46d5eSMarkus Elfring add_free_entry:
24863c41688SPaul Moore 	kfree(entry);
24963c41688SPaul Moore 	return ret_val;
25063c41688SPaul Moore }
25163c41688SPaul Moore 
25263c41688SPaul Moore /**
25363c41688SPaul Moore  * netlbl_mgmt_listentry - List a NetLabel/LSM domain map entry
25463c41688SPaul Moore  * @skb: the NETLINK buffer
25563c41688SPaul Moore  * @entry: the map entry
25663c41688SPaul Moore  *
25763c41688SPaul Moore  * Description:
25863c41688SPaul Moore  * This function is a helper function used by the LISTALL and LISTDEF command
25925985edcSLucas De Marchi  * handlers.  The caller is responsible for ensuring that the RCU read lock
26063c41688SPaul Moore  * is held.  Returns zero on success, negative values on failure.
26163c41688SPaul Moore  *
26263c41688SPaul Moore  */
26363c41688SPaul Moore static int netlbl_mgmt_listentry(struct sk_buff *skb,
26463c41688SPaul Moore 				 struct netlbl_dom_map *entry)
26563c41688SPaul Moore {
266f8a02479SPaul Moore 	int ret_val = 0;
26763c41688SPaul Moore 	struct nlattr *nla_a;
26863c41688SPaul Moore 	struct nlattr *nla_b;
26963c41688SPaul Moore 	struct netlbl_af4list *iter4;
270dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6)
27163c41688SPaul Moore 	struct netlbl_af6list *iter6;
27263c41688SPaul Moore #endif
27363c41688SPaul Moore 
27463c41688SPaul Moore 	if (entry->domain != NULL) {
27563c41688SPaul Moore 		ret_val = nla_put_string(skb,
27663c41688SPaul Moore 					 NLBL_MGMT_A_DOMAIN, entry->domain);
27763c41688SPaul Moore 		if (ret_val != 0)
27863c41688SPaul Moore 			return ret_val;
27963c41688SPaul Moore 	}
28063c41688SPaul Moore 
2816a8b7f0cSPaul Moore 	switch (entry->def.type) {
28263c41688SPaul Moore 	case NETLBL_NLTYPE_ADDRSELECT:
28363c41688SPaul Moore 		nla_a = nla_nest_start(skb, NLBL_MGMT_A_SELECTORLIST);
28463c41688SPaul Moore 		if (nla_a == NULL)
28563c41688SPaul Moore 			return -ENOMEM;
28663c41688SPaul Moore 
2876a8b7f0cSPaul Moore 		netlbl_af4list_foreach_rcu(iter4, &entry->def.addrsel->list4) {
28863c41688SPaul Moore 			struct netlbl_domaddr4_map *map4;
28963c41688SPaul Moore 			struct in_addr addr_struct;
29063c41688SPaul Moore 
29163c41688SPaul Moore 			nla_b = nla_nest_start(skb, NLBL_MGMT_A_ADDRSELECTOR);
29263c41688SPaul Moore 			if (nla_b == NULL)
29363c41688SPaul Moore 				return -ENOMEM;
29463c41688SPaul Moore 
29563c41688SPaul Moore 			addr_struct.s_addr = iter4->addr;
29663c41688SPaul Moore 			ret_val = nla_put(skb, NLBL_MGMT_A_IPV4ADDR,
29763c41688SPaul Moore 					  sizeof(struct in_addr),
29863c41688SPaul Moore 					  &addr_struct);
29963c41688SPaul Moore 			if (ret_val != 0)
30063c41688SPaul Moore 				return ret_val;
30163c41688SPaul Moore 			addr_struct.s_addr = iter4->mask;
30263c41688SPaul Moore 			ret_val = nla_put(skb, NLBL_MGMT_A_IPV4MASK,
30363c41688SPaul Moore 					  sizeof(struct in_addr),
30463c41688SPaul Moore 					  &addr_struct);
30563c41688SPaul Moore 			if (ret_val != 0)
30663c41688SPaul Moore 				return ret_val;
30763c41688SPaul Moore 			map4 = netlbl_domhsh_addr4_entry(iter4);
30863c41688SPaul Moore 			ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL,
3096a8b7f0cSPaul Moore 					      map4->def.type);
31063c41688SPaul Moore 			if (ret_val != 0)
31163c41688SPaul Moore 				return ret_val;
3126a8b7f0cSPaul Moore 			switch (map4->def.type) {
31363c41688SPaul Moore 			case NETLBL_NLTYPE_CIPSOV4:
31463c41688SPaul Moore 				ret_val = nla_put_u32(skb, NLBL_MGMT_A_CV4DOI,
3156a8b7f0cSPaul Moore 						      map4->def.cipso->doi);
31663c41688SPaul Moore 				if (ret_val != 0)
31763c41688SPaul Moore 					return ret_val;
31863c41688SPaul Moore 				break;
31963c41688SPaul Moore 			}
32063c41688SPaul Moore 
32163c41688SPaul Moore 			nla_nest_end(skb, nla_b);
32263c41688SPaul Moore 		}
323dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6)
3246a8b7f0cSPaul Moore 		netlbl_af6list_foreach_rcu(iter6, &entry->def.addrsel->list6) {
32563c41688SPaul Moore 			struct netlbl_domaddr6_map *map6;
32663c41688SPaul Moore 
32763c41688SPaul Moore 			nla_b = nla_nest_start(skb, NLBL_MGMT_A_ADDRSELECTOR);
32863c41688SPaul Moore 			if (nla_b == NULL)
32963c41688SPaul Moore 				return -ENOMEM;
33063c41688SPaul Moore 
33163c41688SPaul Moore 			ret_val = nla_put(skb, NLBL_MGMT_A_IPV6ADDR,
33263c41688SPaul Moore 					  sizeof(struct in6_addr),
33363c41688SPaul Moore 					  &iter6->addr);
33463c41688SPaul Moore 			if (ret_val != 0)
33563c41688SPaul Moore 				return ret_val;
33663c41688SPaul Moore 			ret_val = nla_put(skb, NLBL_MGMT_A_IPV6MASK,
33763c41688SPaul Moore 					  sizeof(struct in6_addr),
33863c41688SPaul Moore 					  &iter6->mask);
33963c41688SPaul Moore 			if (ret_val != 0)
34063c41688SPaul Moore 				return ret_val;
34163c41688SPaul Moore 			map6 = netlbl_domhsh_addr6_entry(iter6);
34263c41688SPaul Moore 			ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL,
3436a8b7f0cSPaul Moore 					      map6->def.type);
34463c41688SPaul Moore 			if (ret_val != 0)
34563c41688SPaul Moore 				return ret_val;
34663c41688SPaul Moore 
34763c41688SPaul Moore 			nla_nest_end(skb, nla_b);
34863c41688SPaul Moore 		}
34963c41688SPaul Moore #endif /* IPv6 */
35063c41688SPaul Moore 
35163c41688SPaul Moore 		nla_nest_end(skb, nla_a);
35263c41688SPaul Moore 		break;
35363c41688SPaul Moore 	case NETLBL_NLTYPE_UNLABELED:
3546a8b7f0cSPaul Moore 		ret_val = nla_put_u32(skb,NLBL_MGMT_A_PROTOCOL,entry->def.type);
35563c41688SPaul Moore 		break;
35663c41688SPaul Moore 	case NETLBL_NLTYPE_CIPSOV4:
3576a8b7f0cSPaul Moore 		ret_val = nla_put_u32(skb,NLBL_MGMT_A_PROTOCOL,entry->def.type);
35863c41688SPaul Moore 		if (ret_val != 0)
35963c41688SPaul Moore 			return ret_val;
36063c41688SPaul Moore 		ret_val = nla_put_u32(skb, NLBL_MGMT_A_CV4DOI,
3616a8b7f0cSPaul Moore 				      entry->def.cipso->doi);
36263c41688SPaul Moore 		break;
36363c41688SPaul Moore 	}
36463c41688SPaul Moore 
36563c41688SPaul Moore 	return ret_val;
36663c41688SPaul Moore }
36763c41688SPaul Moore 
36863c41688SPaul Moore /*
369d15c345fSPaul Moore  * NetLabel Command Handlers
370d15c345fSPaul Moore  */
371d15c345fSPaul Moore 
372d15c345fSPaul Moore /**
373d15c345fSPaul Moore  * netlbl_mgmt_add - Handle an ADD message
374d15c345fSPaul Moore  * @skb: the NETLINK buffer
375d15c345fSPaul Moore  * @info: the Generic NETLINK info block
376d15c345fSPaul Moore  *
377d15c345fSPaul Moore  * Description:
378d15c345fSPaul Moore  * Process a user generated ADD message and add the domains from the message
379d15c345fSPaul Moore  * to the hash table.  See netlabel.h for a description of the message format.
380d15c345fSPaul Moore  * Returns zero on success, negative values on failure.
381d15c345fSPaul Moore  *
382d15c345fSPaul Moore  */
383d15c345fSPaul Moore static int netlbl_mgmt_add(struct sk_buff *skb, struct genl_info *info)
384d15c345fSPaul Moore {
38595d4e6beSPaul Moore 	struct netlbl_audit audit_info;
386d15c345fSPaul Moore 
38763c41688SPaul Moore 	if ((!info->attrs[NLBL_MGMT_A_DOMAIN]) ||
38863c41688SPaul Moore 	    (!info->attrs[NLBL_MGMT_A_PROTOCOL]) ||
38963c41688SPaul Moore 	    (info->attrs[NLBL_MGMT_A_IPV4ADDR] &&
39063c41688SPaul Moore 	     info->attrs[NLBL_MGMT_A_IPV6ADDR]) ||
39163c41688SPaul Moore 	    (info->attrs[NLBL_MGMT_A_IPV4MASK] &&
39263c41688SPaul Moore 	     info->attrs[NLBL_MGMT_A_IPV6MASK]) ||
39363c41688SPaul Moore 	    ((info->attrs[NLBL_MGMT_A_IPV4ADDR] != NULL) ^
39463c41688SPaul Moore 	     (info->attrs[NLBL_MGMT_A_IPV4MASK] != NULL)) ||
39563c41688SPaul Moore 	    ((info->attrs[NLBL_MGMT_A_IPV6ADDR] != NULL) ^
39663c41688SPaul Moore 	     (info->attrs[NLBL_MGMT_A_IPV6MASK] != NULL)))
39763c41688SPaul Moore 		return -EINVAL;
398d15c345fSPaul Moore 
39995d4e6beSPaul Moore 	netlbl_netlink_auditinfo(skb, &audit_info);
40095d4e6beSPaul Moore 
40163c41688SPaul Moore 	return netlbl_mgmt_add_common(info, &audit_info);
402d15c345fSPaul Moore }
403d15c345fSPaul Moore 
404d15c345fSPaul Moore /**
405d15c345fSPaul Moore  * netlbl_mgmt_remove - Handle a REMOVE message
406d15c345fSPaul Moore  * @skb: the NETLINK buffer
407d15c345fSPaul Moore  * @info: the Generic NETLINK info block
408d15c345fSPaul Moore  *
409d15c345fSPaul Moore  * Description:
410d15c345fSPaul Moore  * Process a user generated REMOVE message and remove the specified domain
411d15c345fSPaul Moore  * mappings.  Returns zero on success, negative values on failure.
412d15c345fSPaul Moore  *
413d15c345fSPaul Moore  */
414d15c345fSPaul Moore static int netlbl_mgmt_remove(struct sk_buff *skb, struct genl_info *info)
415d15c345fSPaul Moore {
416fd385855SPaul Moore 	char *domain;
41795d4e6beSPaul Moore 	struct netlbl_audit audit_info;
418d15c345fSPaul Moore 
419fd385855SPaul Moore 	if (!info->attrs[NLBL_MGMT_A_DOMAIN])
420fd385855SPaul Moore 		return -EINVAL;
421d15c345fSPaul Moore 
42295d4e6beSPaul Moore 	netlbl_netlink_auditinfo(skb, &audit_info);
42395d4e6beSPaul Moore 
424fd385855SPaul Moore 	domain = nla_data(info->attrs[NLBL_MGMT_A_DOMAIN]);
42595d4e6beSPaul Moore 	return netlbl_domhsh_remove(domain, &audit_info);
426d15c345fSPaul Moore }
427d15c345fSPaul Moore 
428fd385855SPaul Moore /**
429fd385855SPaul Moore  * netlbl_mgmt_listall_cb - netlbl_domhsh_walk() callback for LISTALL
430fd385855SPaul Moore  * @entry: the domain mapping hash table entry
431fd385855SPaul Moore  * @arg: the netlbl_domhsh_walk_arg structure
432fd385855SPaul Moore  *
433fd385855SPaul Moore  * Description:
434fd385855SPaul Moore  * This function is designed to be used as a callback to the
435fd385855SPaul Moore  * netlbl_domhsh_walk() function for use in generating a response for a LISTALL
436fd385855SPaul Moore  * message.  Returns the size of the message on success, negative values on
437fd385855SPaul Moore  * failure.
438fd385855SPaul Moore  *
439fd385855SPaul Moore  */
440fd385855SPaul Moore static int netlbl_mgmt_listall_cb(struct netlbl_dom_map *entry, void *arg)
441fd385855SPaul Moore {
442fd385855SPaul Moore 	int ret_val = -ENOMEM;
443fd385855SPaul Moore 	struct netlbl_domhsh_walk_arg *cb_arg = arg;
444fd385855SPaul Moore 	void *data;
445d15c345fSPaul Moore 
44615e47304SEric W. Biederman 	data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).portid,
44717c157c8SThomas Graf 			   cb_arg->seq, &netlbl_mgmt_gnl_family,
44817c157c8SThomas Graf 			   NLM_F_MULTI, NLBL_MGMT_C_LISTALL);
449fd385855SPaul Moore 	if (data == NULL)
450fd385855SPaul Moore 		goto listall_cb_failure;
451fd385855SPaul Moore 
45263c41688SPaul Moore 	ret_val = netlbl_mgmt_listentry(cb_arg->skb, entry);
453fd385855SPaul Moore 	if (ret_val != 0)
454fd385855SPaul Moore 		goto listall_cb_failure;
455fd385855SPaul Moore 
456fd385855SPaul Moore 	cb_arg->seq++;
457053c095aSJohannes Berg 	genlmsg_end(cb_arg->skb, data);
458053c095aSJohannes Berg 	return 0;
459fd385855SPaul Moore 
460fd385855SPaul Moore listall_cb_failure:
461fd385855SPaul Moore 	genlmsg_cancel(cb_arg->skb, data);
462d15c345fSPaul Moore 	return ret_val;
463d15c345fSPaul Moore }
464d15c345fSPaul Moore 
465d15c345fSPaul Moore /**
466fd385855SPaul Moore  * netlbl_mgmt_listall - Handle a LISTALL message
467d15c345fSPaul Moore  * @skb: the NETLINK buffer
468fd385855SPaul Moore  * @cb: the NETLINK callback
469d15c345fSPaul Moore  *
470d15c345fSPaul Moore  * Description:
471fd385855SPaul Moore  * Process a user generated LISTALL message and dumps the domain hash table in
472fd385855SPaul Moore  * a form suitable for use in a kernel generated LISTALL message.  Returns zero
473fd385855SPaul Moore  * on success, negative values on failure.
474d15c345fSPaul Moore  *
475d15c345fSPaul Moore  */
476fd385855SPaul Moore static int netlbl_mgmt_listall(struct sk_buff *skb,
477fd385855SPaul Moore 			       struct netlink_callback *cb)
478d15c345fSPaul Moore {
479fd385855SPaul Moore 	struct netlbl_domhsh_walk_arg cb_arg;
480fd385855SPaul Moore 	u32 skip_bkt = cb->args[0];
481fd385855SPaul Moore 	u32 skip_chain = cb->args[1];
482d15c345fSPaul Moore 
483fd385855SPaul Moore 	cb_arg.nl_cb = cb;
484fd385855SPaul Moore 	cb_arg.skb = skb;
485fd385855SPaul Moore 	cb_arg.seq = cb->nlh->nlmsg_seq;
486d15c345fSPaul Moore 
487fd385855SPaul Moore 	netlbl_domhsh_walk(&skip_bkt,
488fd385855SPaul Moore 			   &skip_chain,
489fd385855SPaul Moore 			   netlbl_mgmt_listall_cb,
490fd385855SPaul Moore 			   &cb_arg);
491d15c345fSPaul Moore 
492fd385855SPaul Moore 	cb->args[0] = skip_bkt;
493fd385855SPaul Moore 	cb->args[1] = skip_chain;
494fd385855SPaul Moore 	return skb->len;
495d15c345fSPaul Moore }
496d15c345fSPaul Moore 
497d15c345fSPaul Moore /**
498d15c345fSPaul Moore  * netlbl_mgmt_adddef - Handle an ADDDEF message
499d15c345fSPaul Moore  * @skb: the NETLINK buffer
500d15c345fSPaul Moore  * @info: the Generic NETLINK info block
501d15c345fSPaul Moore  *
502d15c345fSPaul Moore  * Description:
503d15c345fSPaul Moore  * Process a user generated ADDDEF message and respond accordingly.  Returns
504d15c345fSPaul Moore  * zero on success, negative values on failure.
505d15c345fSPaul Moore  *
506d15c345fSPaul Moore  */
507d15c345fSPaul Moore static int netlbl_mgmt_adddef(struct sk_buff *skb, struct genl_info *info)
508d15c345fSPaul Moore {
50995d4e6beSPaul Moore 	struct netlbl_audit audit_info;
510d15c345fSPaul Moore 
51163c41688SPaul Moore 	if ((!info->attrs[NLBL_MGMT_A_PROTOCOL]) ||
51263c41688SPaul Moore 	    (info->attrs[NLBL_MGMT_A_IPV4ADDR] &&
51363c41688SPaul Moore 	     info->attrs[NLBL_MGMT_A_IPV6ADDR]) ||
51463c41688SPaul Moore 	    (info->attrs[NLBL_MGMT_A_IPV4MASK] &&
51563c41688SPaul Moore 	     info->attrs[NLBL_MGMT_A_IPV6MASK]) ||
51663c41688SPaul Moore 	    ((info->attrs[NLBL_MGMT_A_IPV4ADDR] != NULL) ^
51763c41688SPaul Moore 	     (info->attrs[NLBL_MGMT_A_IPV4MASK] != NULL)) ||
51863c41688SPaul Moore 	    ((info->attrs[NLBL_MGMT_A_IPV6ADDR] != NULL) ^
51963c41688SPaul Moore 	     (info->attrs[NLBL_MGMT_A_IPV6MASK] != NULL)))
52063c41688SPaul Moore 		return -EINVAL;
521d15c345fSPaul Moore 
52295d4e6beSPaul Moore 	netlbl_netlink_auditinfo(skb, &audit_info);
52395d4e6beSPaul Moore 
52463c41688SPaul Moore 	return netlbl_mgmt_add_common(info, &audit_info);
525d15c345fSPaul Moore }
526d15c345fSPaul Moore 
527d15c345fSPaul Moore /**
528d15c345fSPaul Moore  * netlbl_mgmt_removedef - Handle a REMOVEDEF message
529d15c345fSPaul Moore  * @skb: the NETLINK buffer
530d15c345fSPaul Moore  * @info: the Generic NETLINK info block
531d15c345fSPaul Moore  *
532d15c345fSPaul Moore  * Description:
533d15c345fSPaul Moore  * Process a user generated REMOVEDEF message and remove the default domain
534d15c345fSPaul Moore  * mapping.  Returns zero on success, negative values on failure.
535d15c345fSPaul Moore  *
536d15c345fSPaul Moore  */
537d15c345fSPaul Moore static int netlbl_mgmt_removedef(struct sk_buff *skb, struct genl_info *info)
538d15c345fSPaul Moore {
53995d4e6beSPaul Moore 	struct netlbl_audit audit_info;
54095d4e6beSPaul Moore 
54195d4e6beSPaul Moore 	netlbl_netlink_auditinfo(skb, &audit_info);
54295d4e6beSPaul Moore 
54395d4e6beSPaul Moore 	return netlbl_domhsh_remove_default(&audit_info);
544d15c345fSPaul Moore }
545d15c345fSPaul Moore 
546d15c345fSPaul Moore /**
547d15c345fSPaul Moore  * netlbl_mgmt_listdef - Handle a LISTDEF message
548d15c345fSPaul Moore  * @skb: the NETLINK buffer
549d15c345fSPaul Moore  * @info: the Generic NETLINK info block
550d15c345fSPaul Moore  *
551d15c345fSPaul Moore  * Description:
552d15c345fSPaul Moore  * Process a user generated LISTDEF message and dumps the default domain
553d15c345fSPaul Moore  * mapping in a form suitable for use in a kernel generated LISTDEF message.
554d15c345fSPaul Moore  * Returns zero on success, negative values on failure.
555d15c345fSPaul Moore  *
556d15c345fSPaul Moore  */
557d15c345fSPaul Moore static int netlbl_mgmt_listdef(struct sk_buff *skb, struct genl_info *info)
558d15c345fSPaul Moore {
559d15c345fSPaul Moore 	int ret_val = -ENOMEM;
560fd385855SPaul Moore 	struct sk_buff *ans_skb = NULL;
561fd385855SPaul Moore 	void *data;
562fd385855SPaul Moore 	struct netlbl_dom_map *entry;
563d15c345fSPaul Moore 
564339bf98fSThomas Graf 	ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
565d15c345fSPaul Moore 	if (ans_skb == NULL)
566fd385855SPaul Moore 		return -ENOMEM;
56717c157c8SThomas Graf 	data = genlmsg_put_reply(ans_skb, info, &netlbl_mgmt_gnl_family,
56817c157c8SThomas Graf 				 0, NLBL_MGMT_C_LISTDEF);
569fd385855SPaul Moore 	if (data == NULL)
570fd385855SPaul Moore 		goto listdef_failure;
571d15c345fSPaul Moore 
572fd385855SPaul Moore 	rcu_read_lock();
573fd385855SPaul Moore 	entry = netlbl_domhsh_getentry(NULL);
574fd385855SPaul Moore 	if (entry == NULL) {
575fd385855SPaul Moore 		ret_val = -ENOENT;
576fd385855SPaul Moore 		goto listdef_failure_lock;
577fd385855SPaul Moore 	}
57863c41688SPaul Moore 	ret_val = netlbl_mgmt_listentry(ans_skb, entry);
579fd385855SPaul Moore 	rcu_read_unlock();
58063c41688SPaul Moore 	if (ret_val != 0)
58163c41688SPaul Moore 		goto listdef_failure;
582fd385855SPaul Moore 
583fd385855SPaul Moore 	genlmsg_end(ans_skb, data);
584fe785beeSDenis V. Lunev 	return genlmsg_reply(ans_skb, info);
585d15c345fSPaul Moore 
586fd385855SPaul Moore listdef_failure_lock:
587fd385855SPaul Moore 	rcu_read_unlock();
588d15c345fSPaul Moore listdef_failure:
589fd385855SPaul Moore 	kfree_skb(ans_skb);
590d15c345fSPaul Moore 	return ret_val;
591d15c345fSPaul Moore }
592d15c345fSPaul Moore 
593d15c345fSPaul Moore /**
594fd385855SPaul Moore  * netlbl_mgmt_protocols_cb - Write an individual PROTOCOL message response
595fd385855SPaul Moore  * @skb: the skb to write to
596fd385855SPaul Moore  * @cb: the NETLINK callback
597fd385855SPaul Moore  * @protocol: the NetLabel protocol to use in the message
598d15c345fSPaul Moore  *
599d15c345fSPaul Moore  * Description:
600fd385855SPaul Moore  * This function is to be used in conjunction with netlbl_mgmt_protocols() to
601fd385855SPaul Moore  * answer a application's PROTOCOLS message.  Returns the size of the message
602fd385855SPaul Moore  * on success, negative values on failure.
603d15c345fSPaul Moore  *
604d15c345fSPaul Moore  */
605fd385855SPaul Moore static int netlbl_mgmt_protocols_cb(struct sk_buff *skb,
606fd385855SPaul Moore 				    struct netlink_callback *cb,
607fd385855SPaul Moore 				    u32 protocol)
608d15c345fSPaul Moore {
609d15c345fSPaul Moore 	int ret_val = -ENOMEM;
610fd385855SPaul Moore 	void *data;
611d15c345fSPaul Moore 
61215e47304SEric W. Biederman 	data = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
61317c157c8SThomas Graf 			   &netlbl_mgmt_gnl_family, NLM_F_MULTI,
614fd385855SPaul Moore 			   NLBL_MGMT_C_PROTOCOLS);
615fd385855SPaul Moore 	if (data == NULL)
616fd385855SPaul Moore 		goto protocols_cb_failure;
617d15c345fSPaul Moore 
618fd385855SPaul Moore 	ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL, protocol);
619d15c345fSPaul Moore 	if (ret_val != 0)
620fd385855SPaul Moore 		goto protocols_cb_failure;
621d15c345fSPaul Moore 
622053c095aSJohannes Berg 	genlmsg_end(skb, data);
623053c095aSJohannes Berg 	return 0;
624d15c345fSPaul Moore 
625fd385855SPaul Moore protocols_cb_failure:
626fd385855SPaul Moore 	genlmsg_cancel(skb, data);
627d15c345fSPaul Moore 	return ret_val;
628d15c345fSPaul Moore }
629d15c345fSPaul Moore 
630d15c345fSPaul Moore /**
631fd385855SPaul Moore  * netlbl_mgmt_protocols - Handle a PROTOCOLS message
632fd385855SPaul Moore  * @skb: the NETLINK buffer
633fd385855SPaul Moore  * @cb: the NETLINK callback
634fd385855SPaul Moore  *
635fd385855SPaul Moore  * Description:
636fd385855SPaul Moore  * Process a user generated PROTOCOLS message and respond accordingly.
637fd385855SPaul Moore  *
638fd385855SPaul Moore  */
639fd385855SPaul Moore static int netlbl_mgmt_protocols(struct sk_buff *skb,
640fd385855SPaul Moore 				 struct netlink_callback *cb)
641fd385855SPaul Moore {
642fd385855SPaul Moore 	u32 protos_sent = cb->args[0];
643fd385855SPaul Moore 
644fd385855SPaul Moore 	if (protos_sent == 0) {
645fd385855SPaul Moore 		if (netlbl_mgmt_protocols_cb(skb,
646fd385855SPaul Moore 					     cb,
647fd385855SPaul Moore 					     NETLBL_NLTYPE_UNLABELED) < 0)
648fd385855SPaul Moore 			goto protocols_return;
649fd385855SPaul Moore 		protos_sent++;
650fd385855SPaul Moore 	}
651fd385855SPaul Moore 	if (protos_sent == 1) {
652fd385855SPaul Moore 		if (netlbl_mgmt_protocols_cb(skb,
653fd385855SPaul Moore 					     cb,
654fd385855SPaul Moore 					     NETLBL_NLTYPE_CIPSOV4) < 0)
655fd385855SPaul Moore 			goto protocols_return;
656fd385855SPaul Moore 		protos_sent++;
657fd385855SPaul Moore 	}
658fd385855SPaul Moore 
659fd385855SPaul Moore protocols_return:
660fd385855SPaul Moore 	cb->args[0] = protos_sent;
661fd385855SPaul Moore 	return skb->len;
662fd385855SPaul Moore }
663fd385855SPaul Moore 
664fd385855SPaul Moore /**
665d15c345fSPaul Moore  * netlbl_mgmt_version - Handle a VERSION message
666d15c345fSPaul Moore  * @skb: the NETLINK buffer
667d15c345fSPaul Moore  * @info: the Generic NETLINK info block
668d15c345fSPaul Moore  *
669d15c345fSPaul Moore  * Description:
670d15c345fSPaul Moore  * Process a user generated VERSION message and respond accordingly.  Returns
671d15c345fSPaul Moore  * zero on success, negative values on failure.
672d15c345fSPaul Moore  *
673d15c345fSPaul Moore  */
674d15c345fSPaul Moore static int netlbl_mgmt_version(struct sk_buff *skb, struct genl_info *info)
675d15c345fSPaul Moore {
676d15c345fSPaul Moore 	int ret_val = -ENOMEM;
677d15c345fSPaul Moore 	struct sk_buff *ans_skb = NULL;
678fd385855SPaul Moore 	void *data;
679d15c345fSPaul Moore 
680339bf98fSThomas Graf 	ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
681d15c345fSPaul Moore 	if (ans_skb == NULL)
682fd385855SPaul Moore 		return -ENOMEM;
68317c157c8SThomas Graf 	data = genlmsg_put_reply(ans_skb, info, &netlbl_mgmt_gnl_family,
68417c157c8SThomas Graf 				 0, NLBL_MGMT_C_VERSION);
685fd385855SPaul Moore 	if (data == NULL)
686d15c345fSPaul Moore 		goto version_failure;
687d15c345fSPaul Moore 
688fd385855SPaul Moore 	ret_val = nla_put_u32(ans_skb,
689fd385855SPaul Moore 			      NLBL_MGMT_A_VERSION,
690fd385855SPaul Moore 			      NETLBL_PROTO_VERSION);
691d15c345fSPaul Moore 	if (ret_val != 0)
692d15c345fSPaul Moore 		goto version_failure;
693d15c345fSPaul Moore 
694fd385855SPaul Moore 	genlmsg_end(ans_skb, data);
695fe785beeSDenis V. Lunev 	return genlmsg_reply(ans_skb, info);
696d15c345fSPaul Moore 
697d15c345fSPaul Moore version_failure:
698d15c345fSPaul Moore 	kfree_skb(ans_skb);
699d15c345fSPaul Moore 	return ret_val;
700d15c345fSPaul Moore }
701d15c345fSPaul Moore 
702d15c345fSPaul Moore 
703d15c345fSPaul Moore /*
704d15c345fSPaul Moore  * NetLabel Generic NETLINK Command Definitions
705d15c345fSPaul Moore  */
706d15c345fSPaul Moore 
7074534de83SJohannes Berg static const struct genl_ops netlbl_mgmt_genl_ops[] = {
708227c43c3SPavel Emelyanov 	{
709d15c345fSPaul Moore 	.cmd = NLBL_MGMT_C_ADD,
710fd385855SPaul Moore 	.flags = GENL_ADMIN_PERM,
711fd385855SPaul Moore 	.policy = netlbl_mgmt_genl_policy,
712d15c345fSPaul Moore 	.doit = netlbl_mgmt_add,
713d15c345fSPaul Moore 	.dumpit = NULL,
714227c43c3SPavel Emelyanov 	},
715227c43c3SPavel Emelyanov 	{
716d15c345fSPaul Moore 	.cmd = NLBL_MGMT_C_REMOVE,
717fd385855SPaul Moore 	.flags = GENL_ADMIN_PERM,
718fd385855SPaul Moore 	.policy = netlbl_mgmt_genl_policy,
719d15c345fSPaul Moore 	.doit = netlbl_mgmt_remove,
720d15c345fSPaul Moore 	.dumpit = NULL,
721227c43c3SPavel Emelyanov 	},
722227c43c3SPavel Emelyanov 	{
723fd385855SPaul Moore 	.cmd = NLBL_MGMT_C_LISTALL,
724d15c345fSPaul Moore 	.flags = 0,
725fd385855SPaul Moore 	.policy = netlbl_mgmt_genl_policy,
726fd385855SPaul Moore 	.doit = NULL,
727fd385855SPaul Moore 	.dumpit = netlbl_mgmt_listall,
728227c43c3SPavel Emelyanov 	},
729227c43c3SPavel Emelyanov 	{
730d15c345fSPaul Moore 	.cmd = NLBL_MGMT_C_ADDDEF,
731fd385855SPaul Moore 	.flags = GENL_ADMIN_PERM,
732fd385855SPaul Moore 	.policy = netlbl_mgmt_genl_policy,
733d15c345fSPaul Moore 	.doit = netlbl_mgmt_adddef,
734d15c345fSPaul Moore 	.dumpit = NULL,
735227c43c3SPavel Emelyanov 	},
736227c43c3SPavel Emelyanov 	{
737d15c345fSPaul Moore 	.cmd = NLBL_MGMT_C_REMOVEDEF,
738fd385855SPaul Moore 	.flags = GENL_ADMIN_PERM,
739fd385855SPaul Moore 	.policy = netlbl_mgmt_genl_policy,
740d15c345fSPaul Moore 	.doit = netlbl_mgmt_removedef,
741d15c345fSPaul Moore 	.dumpit = NULL,
742227c43c3SPavel Emelyanov 	},
743227c43c3SPavel Emelyanov 	{
744d15c345fSPaul Moore 	.cmd = NLBL_MGMT_C_LISTDEF,
745d15c345fSPaul Moore 	.flags = 0,
746fd385855SPaul Moore 	.policy = netlbl_mgmt_genl_policy,
747d15c345fSPaul Moore 	.doit = netlbl_mgmt_listdef,
748d15c345fSPaul Moore 	.dumpit = NULL,
749227c43c3SPavel Emelyanov 	},
750227c43c3SPavel Emelyanov 	{
751fd385855SPaul Moore 	.cmd = NLBL_MGMT_C_PROTOCOLS,
752d15c345fSPaul Moore 	.flags = 0,
753fd385855SPaul Moore 	.policy = netlbl_mgmt_genl_policy,
754fd385855SPaul Moore 	.doit = NULL,
755fd385855SPaul Moore 	.dumpit = netlbl_mgmt_protocols,
756227c43c3SPavel Emelyanov 	},
757227c43c3SPavel Emelyanov 	{
758d15c345fSPaul Moore 	.cmd = NLBL_MGMT_C_VERSION,
759d15c345fSPaul Moore 	.flags = 0,
760fd385855SPaul Moore 	.policy = netlbl_mgmt_genl_policy,
761d15c345fSPaul Moore 	.doit = netlbl_mgmt_version,
762d15c345fSPaul Moore 	.dumpit = NULL,
763227c43c3SPavel Emelyanov 	},
764d15c345fSPaul Moore };
765d15c345fSPaul Moore 
766d15c345fSPaul Moore /*
767d15c345fSPaul Moore  * NetLabel Generic NETLINK Protocol Functions
768d15c345fSPaul Moore  */
769d15c345fSPaul Moore 
770d15c345fSPaul Moore /**
771d15c345fSPaul Moore  * netlbl_mgmt_genl_init - Register the NetLabel management component
772d15c345fSPaul Moore  *
773d15c345fSPaul Moore  * Description:
774d15c345fSPaul Moore  * Register the NetLabel management component with the Generic NETLINK
775d15c345fSPaul Moore  * mechanism.  Returns zero on success, negative values on failure.
776d15c345fSPaul Moore  *
777d15c345fSPaul Moore  */
77805705e4eSPavel Emelyanov int __init netlbl_mgmt_genl_init(void)
779d15c345fSPaul Moore {
7807ae740dfSMichał Mirosław 	return genl_register_family_with_ops(&netlbl_mgmt_gnl_family,
781c53ed742SJohannes Berg 					     netlbl_mgmt_genl_ops);
782d15c345fSPaul Moore }
783