blob: e7a25fbfaf8b485d9e276542c477a88479a1061c [file] [log] [blame]
Thomas Gleixner1ccea772019-05-19 15:51:43 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Paul Moored15c3452006-08-03 16:48:37 -07002/*
3 * NetLabel Management Support
4 *
5 * This file defines the management functions for the NetLabel system. The
6 * NetLabel system manages static and dynamic label mappings for network
7 * protocols such as CIPSO and RIPSO.
8 *
Paul Moore82c21bf2011-08-01 11:10:33 +00009 * Author: Paul Moore <paul@paul-moore.com>
Paul Moored15c3452006-08-03 16:48:37 -070010 */
11
12/*
Paul Moore63c41682008-10-10 10:16:32 -040013 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008
Paul Moored15c3452006-08-03 16:48:37 -070014 */
15
16#include <linux/types.h>
17#include <linux/socket.h>
18#include <linux/string.h>
19#include <linux/skbuff.h>
Paul Moore63c41682008-10-10 10:16:32 -040020#include <linux/in.h>
21#include <linux/in6.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090022#include <linux/slab.h>
Paul Moored15c3452006-08-03 16:48:37 -070023#include <net/sock.h>
24#include <net/netlink.h>
25#include <net/genetlink.h>
Paul Moore63c41682008-10-10 10:16:32 -040026#include <net/ip.h>
27#include <net/ipv6.h>
Paul Moored15c3452006-08-03 16:48:37 -070028#include <net/netlabel.h>
29#include <net/cipso_ipv4.h>
Huw Daviesdc7de732016-06-27 15:02:49 -040030#include <net/calipso.h>
Arun Sharma600634972011-07-26 16:09:06 -070031#include <linux/atomic.h>
Paul Moored15c3452006-08-03 16:48:37 -070032
Huw Daviesdc7de732016-06-27 15:02:49 -040033#include "netlabel_calipso.h"
Paul Moored15c3452006-08-03 16:48:37 -070034#include "netlabel_domainhash.h"
35#include "netlabel_user.h"
36#include "netlabel_mgmt.h"
37
Paul Moorec783f1c2008-01-29 08:37:52 -050038/* NetLabel configured protocol counter */
39atomic_t netlabel_mgmt_protocount = ATOMIC_INIT(0);
Paul Moore23bcdc12007-07-18 12:28:45 -040040
Paul Moorefd385852006-09-25 15:56:37 -070041/* Argument struct for netlbl_domhsh_walk() */
42struct netlbl_domhsh_walk_arg {
43 struct netlink_callback *nl_cb;
44 struct sk_buff *skb;
45 u32 seq;
46};
47
Paul Moored15c3452006-08-03 16:48:37 -070048/* NetLabel Generic NETLINK CIPSOv4 family */
Johannes Berg489111e2016-10-24 14:40:03 +020049static struct genl_family netlbl_mgmt_gnl_family;
Paul Moored15c3452006-08-03 16:48:37 -070050
Paul Moorefd385852006-09-25 15:56:37 -070051/* NetLabel Netlink attribute policy */
Patrick McHardyef7c79e2007-06-05 12:38:30 -070052static const struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = {
Paul Moorefd385852006-09-25 15:56:37 -070053 [NLBL_MGMT_A_DOMAIN] = { .type = NLA_NUL_STRING },
54 [NLBL_MGMT_A_PROTOCOL] = { .type = NLA_U32 },
55 [NLBL_MGMT_A_VERSION] = { .type = NLA_U32 },
56 [NLBL_MGMT_A_CV4DOI] = { .type = NLA_U32 },
Huw Davies8f18e672016-06-27 15:02:46 -040057 [NLBL_MGMT_A_FAMILY] = { .type = NLA_U16 },
Huw Daviesdc7de732016-06-27 15:02:49 -040058 [NLBL_MGMT_A_CLPDOI] = { .type = NLA_U32 },
Paul Moorefd385852006-09-25 15:56:37 -070059};
Paul Moored15c3452006-08-03 16:48:37 -070060
61/*
Paul Moore63c41682008-10-10 10:16:32 -040062 * Helper Functions
63 */
64
65/**
66 * netlbl_mgmt_add - Handle an ADD message
67 * @info: the Generic NETLINK info block
68 * @audit_info: NetLabel audit information
69 *
70 * Description:
71 * Helper function for the ADD and ADDDEF messages to add the domain mappings
72 * from the message to the hash table. See netlabel.h for a description of the
73 * message format. Returns zero on success, negative values on failure.
74 *
75 */
76static int netlbl_mgmt_add_common(struct genl_info *info,
77 struct netlbl_audit *audit_info)
78{
79 int ret_val = -EINVAL;
Paul Moore63c41682008-10-10 10:16:32 -040080 struct netlbl_domaddr_map *addrmap = NULL;
81 struct cipso_v4_doi *cipsov4 = NULL;
Huw Daviesdc7de732016-06-27 15:02:49 -040082#if IS_ENABLED(CONFIG_IPV6)
83 struct calipso_doi *calipso = NULL;
84#endif
Paul Moore63c41682008-10-10 10:16:32 -040085 u32 tmp_val;
Markus Elfring4de46d52015-02-02 11:00:24 +010086 struct netlbl_dom_map *entry = kzalloc(sizeof(*entry), GFP_KERNEL);
Paul Moore63c41682008-10-10 10:16:32 -040087
Markus Elfring4de46d52015-02-02 11:00:24 +010088 if (!entry)
89 return -ENOMEM;
Paul Moore6a8b7f02013-08-02 14:45:08 -040090 entry->def.type = nla_get_u32(info->attrs[NLBL_MGMT_A_PROTOCOL]);
Paul Moore63c41682008-10-10 10:16:32 -040091 if (info->attrs[NLBL_MGMT_A_DOMAIN]) {
92 size_t tmp_size = nla_len(info->attrs[NLBL_MGMT_A_DOMAIN]);
93 entry->domain = kmalloc(tmp_size, GFP_KERNEL);
94 if (entry->domain == NULL) {
95 ret_val = -ENOMEM;
Markus Elfring4de46d52015-02-02 11:00:24 +010096 goto add_free_entry;
Paul Moore63c41682008-10-10 10:16:32 -040097 }
98 nla_strlcpy(entry->domain,
99 info->attrs[NLBL_MGMT_A_DOMAIN], tmp_size);
100 }
101
Paul Moore6a8b7f02013-08-02 14:45:08 -0400102 /* NOTE: internally we allow/use a entry->def.type value of
Paul Moore63c41682008-10-10 10:16:32 -0400103 * NETLBL_NLTYPE_ADDRSELECT but we don't currently allow users
104 * to pass that as a protocol value because we need to know the
105 * "real" protocol */
106
Paul Moore6a8b7f02013-08-02 14:45:08 -0400107 switch (entry->def.type) {
Paul Moore63c41682008-10-10 10:16:32 -0400108 case NETLBL_NLTYPE_UNLABELED:
Huw Davies8f18e672016-06-27 15:02:46 -0400109 if (info->attrs[NLBL_MGMT_A_FAMILY])
110 entry->family =
111 nla_get_u16(info->attrs[NLBL_MGMT_A_FAMILY]);
112 else
113 entry->family = AF_UNSPEC;
Paul Moore63c41682008-10-10 10:16:32 -0400114 break;
115 case NETLBL_NLTYPE_CIPSOV4:
116 if (!info->attrs[NLBL_MGMT_A_CV4DOI])
Markus Elfring4de46d52015-02-02 11:00:24 +0100117 goto add_free_domain;
Paul Moore63c41682008-10-10 10:16:32 -0400118
119 tmp_val = nla_get_u32(info->attrs[NLBL_MGMT_A_CV4DOI]);
120 cipsov4 = cipso_v4_doi_getdef(tmp_val);
121 if (cipsov4 == NULL)
Markus Elfring4de46d52015-02-02 11:00:24 +0100122 goto add_free_domain;
Huw Davies8f18e672016-06-27 15:02:46 -0400123 entry->family = AF_INET;
Paul Moore6a8b7f02013-08-02 14:45:08 -0400124 entry->def.cipso = cipsov4;
Paul Moore63c41682008-10-10 10:16:32 -0400125 break;
Huw Daviesdc7de732016-06-27 15:02:49 -0400126#if IS_ENABLED(CONFIG_IPV6)
127 case NETLBL_NLTYPE_CALIPSO:
128 if (!info->attrs[NLBL_MGMT_A_CLPDOI])
129 goto add_free_domain;
130
131 tmp_val = nla_get_u32(info->attrs[NLBL_MGMT_A_CLPDOI]);
132 calipso = calipso_doi_getdef(tmp_val);
133 if (calipso == NULL)
134 goto add_free_domain;
135 entry->family = AF_INET6;
136 entry->def.calipso = calipso;
137 break;
138#endif /* IPv6 */
Paul Moore63c41682008-10-10 10:16:32 -0400139 default:
Markus Elfring4de46d52015-02-02 11:00:24 +0100140 goto add_free_domain;
Paul Moore63c41682008-10-10 10:16:32 -0400141 }
142
Huw Davies8f18e672016-06-27 15:02:46 -0400143 if ((entry->family == AF_INET && info->attrs[NLBL_MGMT_A_IPV6ADDR]) ||
144 (entry->family == AF_INET6 && info->attrs[NLBL_MGMT_A_IPV4ADDR]))
145 goto add_doi_put_def;
146
Paul Moore63c41682008-10-10 10:16:32 -0400147 if (info->attrs[NLBL_MGMT_A_IPV4ADDR]) {
148 struct in_addr *addr;
149 struct in_addr *mask;
150 struct netlbl_domaddr4_map *map;
151
152 addrmap = kzalloc(sizeof(*addrmap), GFP_KERNEL);
153 if (addrmap == NULL) {
154 ret_val = -ENOMEM;
Markus Elfring4de46d52015-02-02 11:00:24 +0100155 goto add_doi_put_def;
Paul Moore63c41682008-10-10 10:16:32 -0400156 }
157 INIT_LIST_HEAD(&addrmap->list4);
158 INIT_LIST_HEAD(&addrmap->list6);
159
160 if (nla_len(info->attrs[NLBL_MGMT_A_IPV4ADDR]) !=
161 sizeof(struct in_addr)) {
162 ret_val = -EINVAL;
Markus Elfring4de46d52015-02-02 11:00:24 +0100163 goto add_free_addrmap;
Paul Moore63c41682008-10-10 10:16:32 -0400164 }
165 if (nla_len(info->attrs[NLBL_MGMT_A_IPV4MASK]) !=
166 sizeof(struct in_addr)) {
167 ret_val = -EINVAL;
Markus Elfring4de46d52015-02-02 11:00:24 +0100168 goto add_free_addrmap;
Paul Moore63c41682008-10-10 10:16:32 -0400169 }
170 addr = nla_data(info->attrs[NLBL_MGMT_A_IPV4ADDR]);
171 mask = nla_data(info->attrs[NLBL_MGMT_A_IPV4MASK]);
172
173 map = kzalloc(sizeof(*map), GFP_KERNEL);
174 if (map == NULL) {
175 ret_val = -ENOMEM;
Markus Elfring4de46d52015-02-02 11:00:24 +0100176 goto add_free_addrmap;
Paul Moore63c41682008-10-10 10:16:32 -0400177 }
178 map->list.addr = addr->s_addr & mask->s_addr;
179 map->list.mask = mask->s_addr;
180 map->list.valid = 1;
Paul Moore6a8b7f02013-08-02 14:45:08 -0400181 map->def.type = entry->def.type;
Paul Moore63c41682008-10-10 10:16:32 -0400182 if (cipsov4)
Paul Moore6a8b7f02013-08-02 14:45:08 -0400183 map->def.cipso = cipsov4;
Paul Moore63c41682008-10-10 10:16:32 -0400184
185 ret_val = netlbl_af4list_add(&map->list, &addrmap->list4);
186 if (ret_val != 0) {
187 kfree(map);
Markus Elfring4de46d52015-02-02 11:00:24 +0100188 goto add_free_addrmap;
Paul Moore63c41682008-10-10 10:16:32 -0400189 }
190
Huw Davies8f18e672016-06-27 15:02:46 -0400191 entry->family = AF_INET;
Paul Moore6a8b7f02013-08-02 14:45:08 -0400192 entry->def.type = NETLBL_NLTYPE_ADDRSELECT;
193 entry->def.addrsel = addrmap;
Eric Dumazetdfd56b82011-12-10 09:48:31 +0000194#if IS_ENABLED(CONFIG_IPV6)
Paul Moore63c41682008-10-10 10:16:32 -0400195 } else if (info->attrs[NLBL_MGMT_A_IPV6ADDR]) {
196 struct in6_addr *addr;
197 struct in6_addr *mask;
198 struct netlbl_domaddr6_map *map;
199
200 addrmap = kzalloc(sizeof(*addrmap), GFP_KERNEL);
201 if (addrmap == NULL) {
202 ret_val = -ENOMEM;
Markus Elfring4de46d52015-02-02 11:00:24 +0100203 goto add_doi_put_def;
Paul Moore63c41682008-10-10 10:16:32 -0400204 }
205 INIT_LIST_HEAD(&addrmap->list4);
206 INIT_LIST_HEAD(&addrmap->list6);
207
208 if (nla_len(info->attrs[NLBL_MGMT_A_IPV6ADDR]) !=
209 sizeof(struct in6_addr)) {
210 ret_val = -EINVAL;
Markus Elfring4de46d52015-02-02 11:00:24 +0100211 goto add_free_addrmap;
Paul Moore63c41682008-10-10 10:16:32 -0400212 }
213 if (nla_len(info->attrs[NLBL_MGMT_A_IPV6MASK]) !=
214 sizeof(struct in6_addr)) {
215 ret_val = -EINVAL;
Markus Elfring4de46d52015-02-02 11:00:24 +0100216 goto add_free_addrmap;
Paul Moore63c41682008-10-10 10:16:32 -0400217 }
218 addr = nla_data(info->attrs[NLBL_MGMT_A_IPV6ADDR]);
219 mask = nla_data(info->attrs[NLBL_MGMT_A_IPV6MASK]);
220
221 map = kzalloc(sizeof(*map), GFP_KERNEL);
222 if (map == NULL) {
223 ret_val = -ENOMEM;
Markus Elfring4de46d52015-02-02 11:00:24 +0100224 goto add_free_addrmap;
Paul Moore63c41682008-10-10 10:16:32 -0400225 }
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +0000226 map->list.addr = *addr;
Paul Moore63c41682008-10-10 10:16:32 -0400227 map->list.addr.s6_addr32[0] &= mask->s6_addr32[0];
228 map->list.addr.s6_addr32[1] &= mask->s6_addr32[1];
229 map->list.addr.s6_addr32[2] &= mask->s6_addr32[2];
230 map->list.addr.s6_addr32[3] &= mask->s6_addr32[3];
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +0000231 map->list.mask = *mask;
Paul Moore63c41682008-10-10 10:16:32 -0400232 map->list.valid = 1;
Paul Moore6a8b7f02013-08-02 14:45:08 -0400233 map->def.type = entry->def.type;
Huw Daviesdc7de732016-06-27 15:02:49 -0400234 if (calipso)
235 map->def.calipso = calipso;
Paul Moore63c41682008-10-10 10:16:32 -0400236
237 ret_val = netlbl_af6list_add(&map->list, &addrmap->list6);
238 if (ret_val != 0) {
239 kfree(map);
Markus Elfring4de46d52015-02-02 11:00:24 +0100240 goto add_free_addrmap;
Paul Moore63c41682008-10-10 10:16:32 -0400241 }
242
Huw Davies8f18e672016-06-27 15:02:46 -0400243 entry->family = AF_INET6;
Paul Moore6a8b7f02013-08-02 14:45:08 -0400244 entry->def.type = NETLBL_NLTYPE_ADDRSELECT;
245 entry->def.addrsel = addrmap;
Paul Moore63c41682008-10-10 10:16:32 -0400246#endif /* IPv6 */
247 }
248
249 ret_val = netlbl_domhsh_add(entry, audit_info);
250 if (ret_val != 0)
Markus Elfring4de46d52015-02-02 11:00:24 +0100251 goto add_free_addrmap;
Paul Moore63c41682008-10-10 10:16:32 -0400252
253 return 0;
254
Markus Elfring4de46d52015-02-02 11:00:24 +0100255add_free_addrmap:
Paul Moore63c41682008-10-10 10:16:32 -0400256 kfree(addrmap);
Markus Elfring4de46d52015-02-02 11:00:24 +0100257add_doi_put_def:
258 cipso_v4_doi_putdef(cipsov4);
Huw Daviesdc7de732016-06-27 15:02:49 -0400259#if IS_ENABLED(CONFIG_IPV6)
260 calipso_doi_putdef(calipso);
261#endif
Markus Elfring4de46d52015-02-02 11:00:24 +0100262add_free_domain:
263 kfree(entry->domain);
264add_free_entry:
Paul Moore63c41682008-10-10 10:16:32 -0400265 kfree(entry);
266 return ret_val;
267}
268
269/**
270 * netlbl_mgmt_listentry - List a NetLabel/LSM domain map entry
271 * @skb: the NETLINK buffer
272 * @entry: the map entry
273 *
274 * Description:
275 * This function is a helper function used by the LISTALL and LISTDEF command
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300276 * handlers. The caller is responsible for ensuring that the RCU read lock
Paul Moore63c41682008-10-10 10:16:32 -0400277 * is held. Returns zero on success, negative values on failure.
278 *
279 */
280static int netlbl_mgmt_listentry(struct sk_buff *skb,
281 struct netlbl_dom_map *entry)
282{
Paul Mooref8a02472008-10-29 16:09:12 -0400283 int ret_val = 0;
Paul Moore63c41682008-10-10 10:16:32 -0400284 struct nlattr *nla_a;
285 struct nlattr *nla_b;
286 struct netlbl_af4list *iter4;
Eric Dumazetdfd56b82011-12-10 09:48:31 +0000287#if IS_ENABLED(CONFIG_IPV6)
Paul Moore63c41682008-10-10 10:16:32 -0400288 struct netlbl_af6list *iter6;
289#endif
290
291 if (entry->domain != NULL) {
292 ret_val = nla_put_string(skb,
293 NLBL_MGMT_A_DOMAIN, entry->domain);
294 if (ret_val != 0)
295 return ret_val;
296 }
297
Huw Davies8f18e672016-06-27 15:02:46 -0400298 ret_val = nla_put_u16(skb, NLBL_MGMT_A_FAMILY, entry->family);
299 if (ret_val != 0)
300 return ret_val;
301
Paul Moore6a8b7f02013-08-02 14:45:08 -0400302 switch (entry->def.type) {
Paul Moore63c41682008-10-10 10:16:32 -0400303 case NETLBL_NLTYPE_ADDRSELECT:
Michal Kubecekae0be8d2019-04-26 11:13:06 +0200304 nla_a = nla_nest_start_noflag(skb, NLBL_MGMT_A_SELECTORLIST);
Paul Moore63c41682008-10-10 10:16:32 -0400305 if (nla_a == NULL)
306 return -ENOMEM;
307
Paul Moore6a8b7f02013-08-02 14:45:08 -0400308 netlbl_af4list_foreach_rcu(iter4, &entry->def.addrsel->list4) {
Paul Moore63c41682008-10-10 10:16:32 -0400309 struct netlbl_domaddr4_map *map4;
310 struct in_addr addr_struct;
311
Michal Kubecekae0be8d2019-04-26 11:13:06 +0200312 nla_b = nla_nest_start_noflag(skb,
313 NLBL_MGMT_A_ADDRSELECTOR);
Paul Moore63c41682008-10-10 10:16:32 -0400314 if (nla_b == NULL)
315 return -ENOMEM;
316
317 addr_struct.s_addr = iter4->addr;
Jiri Benc930345e2015-03-29 16:59:25 +0200318 ret_val = nla_put_in_addr(skb, NLBL_MGMT_A_IPV4ADDR,
319 addr_struct.s_addr);
Paul Moore63c41682008-10-10 10:16:32 -0400320 if (ret_val != 0)
321 return ret_val;
322 addr_struct.s_addr = iter4->mask;
Jiri Benc930345e2015-03-29 16:59:25 +0200323 ret_val = nla_put_in_addr(skb, NLBL_MGMT_A_IPV4MASK,
324 addr_struct.s_addr);
Paul Moore63c41682008-10-10 10:16:32 -0400325 if (ret_val != 0)
326 return ret_val;
327 map4 = netlbl_domhsh_addr4_entry(iter4);
328 ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL,
Paul Moore6a8b7f02013-08-02 14:45:08 -0400329 map4->def.type);
Paul Moore63c41682008-10-10 10:16:32 -0400330 if (ret_val != 0)
331 return ret_val;
Paul Moore6a8b7f02013-08-02 14:45:08 -0400332 switch (map4->def.type) {
Paul Moore63c41682008-10-10 10:16:32 -0400333 case NETLBL_NLTYPE_CIPSOV4:
334 ret_val = nla_put_u32(skb, NLBL_MGMT_A_CV4DOI,
Paul Moore6a8b7f02013-08-02 14:45:08 -0400335 map4->def.cipso->doi);
Paul Moore63c41682008-10-10 10:16:32 -0400336 if (ret_val != 0)
337 return ret_val;
338 break;
339 }
340
341 nla_nest_end(skb, nla_b);
342 }
Eric Dumazetdfd56b82011-12-10 09:48:31 +0000343#if IS_ENABLED(CONFIG_IPV6)
Paul Moore6a8b7f02013-08-02 14:45:08 -0400344 netlbl_af6list_foreach_rcu(iter6, &entry->def.addrsel->list6) {
Paul Moore63c41682008-10-10 10:16:32 -0400345 struct netlbl_domaddr6_map *map6;
346
Michal Kubecekae0be8d2019-04-26 11:13:06 +0200347 nla_b = nla_nest_start_noflag(skb,
348 NLBL_MGMT_A_ADDRSELECTOR);
Paul Moore63c41682008-10-10 10:16:32 -0400349 if (nla_b == NULL)
350 return -ENOMEM;
351
Jiri Benc930345e2015-03-29 16:59:25 +0200352 ret_val = nla_put_in6_addr(skb, NLBL_MGMT_A_IPV6ADDR,
353 &iter6->addr);
Paul Moore63c41682008-10-10 10:16:32 -0400354 if (ret_val != 0)
355 return ret_val;
Jiri Benc930345e2015-03-29 16:59:25 +0200356 ret_val = nla_put_in6_addr(skb, NLBL_MGMT_A_IPV6MASK,
357 &iter6->mask);
Paul Moore63c41682008-10-10 10:16:32 -0400358 if (ret_val != 0)
359 return ret_val;
360 map6 = netlbl_domhsh_addr6_entry(iter6);
361 ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL,
Paul Moore6a8b7f02013-08-02 14:45:08 -0400362 map6->def.type);
Paul Moore63c41682008-10-10 10:16:32 -0400363 if (ret_val != 0)
364 return ret_val;
365
Huw Daviesdc7de732016-06-27 15:02:49 -0400366 switch (map6->def.type) {
367 case NETLBL_NLTYPE_CALIPSO:
368 ret_val = nla_put_u32(skb, NLBL_MGMT_A_CLPDOI,
369 map6->def.calipso->doi);
370 if (ret_val != 0)
371 return ret_val;
372 break;
373 }
374
Paul Moore63c41682008-10-10 10:16:32 -0400375 nla_nest_end(skb, nla_b);
376 }
377#endif /* IPv6 */
378
379 nla_nest_end(skb, nla_a);
380 break;
381 case NETLBL_NLTYPE_UNLABELED:
Huw Daviesdc7de732016-06-27 15:02:49 -0400382 ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL,
383 entry->def.type);
Paul Moore63c41682008-10-10 10:16:32 -0400384 break;
385 case NETLBL_NLTYPE_CIPSOV4:
Huw Daviesdc7de732016-06-27 15:02:49 -0400386 ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL,
387 entry->def.type);
Paul Moore63c41682008-10-10 10:16:32 -0400388 if (ret_val != 0)
389 return ret_val;
390 ret_val = nla_put_u32(skb, NLBL_MGMT_A_CV4DOI,
Paul Moore6a8b7f02013-08-02 14:45:08 -0400391 entry->def.cipso->doi);
Paul Moore63c41682008-10-10 10:16:32 -0400392 break;
Huw Daviesdc7de732016-06-27 15:02:49 -0400393 case NETLBL_NLTYPE_CALIPSO:
394 ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL,
395 entry->def.type);
396 if (ret_val != 0)
397 return ret_val;
398 ret_val = nla_put_u32(skb, NLBL_MGMT_A_CLPDOI,
399 entry->def.calipso->doi);
400 break;
Paul Moore63c41682008-10-10 10:16:32 -0400401 }
402
403 return ret_val;
404}
405
406/*
Paul Moored15c3452006-08-03 16:48:37 -0700407 * NetLabel Command Handlers
408 */
409
410/**
411 * netlbl_mgmt_add - Handle an ADD message
412 * @skb: the NETLINK buffer
413 * @info: the Generic NETLINK info block
414 *
415 * Description:
416 * Process a user generated ADD message and add the domains from the message
417 * to the hash table. See netlabel.h for a description of the message format.
418 * Returns zero on success, negative values on failure.
419 *
420 */
421static int netlbl_mgmt_add(struct sk_buff *skb, struct genl_info *info)
422{
Paul Moore95d4e6b2006-09-29 17:05:05 -0700423 struct netlbl_audit audit_info;
Paul Moored15c3452006-08-03 16:48:37 -0700424
Paul Moore63c41682008-10-10 10:16:32 -0400425 if ((!info->attrs[NLBL_MGMT_A_DOMAIN]) ||
426 (!info->attrs[NLBL_MGMT_A_PROTOCOL]) ||
427 (info->attrs[NLBL_MGMT_A_IPV4ADDR] &&
428 info->attrs[NLBL_MGMT_A_IPV6ADDR]) ||
429 (info->attrs[NLBL_MGMT_A_IPV4MASK] &&
430 info->attrs[NLBL_MGMT_A_IPV6MASK]) ||
431 ((info->attrs[NLBL_MGMT_A_IPV4ADDR] != NULL) ^
432 (info->attrs[NLBL_MGMT_A_IPV4MASK] != NULL)) ||
433 ((info->attrs[NLBL_MGMT_A_IPV6ADDR] != NULL) ^
434 (info->attrs[NLBL_MGMT_A_IPV6MASK] != NULL)))
435 return -EINVAL;
Paul Moorefd385852006-09-25 15:56:37 -0700436
Paul Moore95d4e6b2006-09-29 17:05:05 -0700437 netlbl_netlink_auditinfo(skb, &audit_info);
438
Paul Moore63c41682008-10-10 10:16:32 -0400439 return netlbl_mgmt_add_common(info, &audit_info);
Paul Moored15c3452006-08-03 16:48:37 -0700440}
441
442/**
443 * netlbl_mgmt_remove - Handle a REMOVE message
444 * @skb: the NETLINK buffer
445 * @info: the Generic NETLINK info block
446 *
447 * Description:
448 * Process a user generated REMOVE message and remove the specified domain
449 * mappings. Returns zero on success, negative values on failure.
450 *
451 */
452static int netlbl_mgmt_remove(struct sk_buff *skb, struct genl_info *info)
453{
Paul Moorefd385852006-09-25 15:56:37 -0700454 char *domain;
Paul Moore95d4e6b2006-09-29 17:05:05 -0700455 struct netlbl_audit audit_info;
Paul Moored15c3452006-08-03 16:48:37 -0700456
Paul Moorefd385852006-09-25 15:56:37 -0700457 if (!info->attrs[NLBL_MGMT_A_DOMAIN])
458 return -EINVAL;
459
Paul Moore95d4e6b2006-09-29 17:05:05 -0700460 netlbl_netlink_auditinfo(skb, &audit_info);
461
Paul Moorefd385852006-09-25 15:56:37 -0700462 domain = nla_data(info->attrs[NLBL_MGMT_A_DOMAIN]);
Huw Davies8f18e672016-06-27 15:02:46 -0400463 return netlbl_domhsh_remove(domain, AF_UNSPEC, &audit_info);
Paul Moorefd385852006-09-25 15:56:37 -0700464}
465
466/**
467 * netlbl_mgmt_listall_cb - netlbl_domhsh_walk() callback for LISTALL
468 * @entry: the domain mapping hash table entry
469 * @arg: the netlbl_domhsh_walk_arg structure
470 *
471 * Description:
472 * This function is designed to be used as a callback to the
473 * netlbl_domhsh_walk() function for use in generating a response for a LISTALL
474 * message. Returns the size of the message on success, negative values on
475 * failure.
476 *
477 */
478static int netlbl_mgmt_listall_cb(struct netlbl_dom_map *entry, void *arg)
479{
480 int ret_val = -ENOMEM;
481 struct netlbl_domhsh_walk_arg *cb_arg = arg;
482 void *data;
483
Eric W. Biederman15e47302012-09-07 20:12:54 +0000484 data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).portid,
Thomas Graf17c157c2006-11-14 19:46:02 -0800485 cb_arg->seq, &netlbl_mgmt_gnl_family,
486 NLM_F_MULTI, NLBL_MGMT_C_LISTALL);
Paul Moorefd385852006-09-25 15:56:37 -0700487 if (data == NULL)
488 goto listall_cb_failure;
489
Paul Moore63c41682008-10-10 10:16:32 -0400490 ret_val = netlbl_mgmt_listentry(cb_arg->skb, entry);
Paul Moored15c3452006-08-03 16:48:37 -0700491 if (ret_val != 0)
Paul Moorefd385852006-09-25 15:56:37 -0700492 goto listall_cb_failure;
Paul Moored15c3452006-08-03 16:48:37 -0700493
Paul Moorefd385852006-09-25 15:56:37 -0700494 cb_arg->seq++;
Johannes Berg053c0952015-01-16 22:09:00 +0100495 genlmsg_end(cb_arg->skb, data);
496 return 0;
Paul Moored15c3452006-08-03 16:48:37 -0700497
Paul Moorefd385852006-09-25 15:56:37 -0700498listall_cb_failure:
499 genlmsg_cancel(cb_arg->skb, data);
Paul Moored15c3452006-08-03 16:48:37 -0700500 return ret_val;
501}
502
503/**
Paul Moorefd385852006-09-25 15:56:37 -0700504 * netlbl_mgmt_listall - Handle a LISTALL message
Paul Moored15c3452006-08-03 16:48:37 -0700505 * @skb: the NETLINK buffer
Paul Moorefd385852006-09-25 15:56:37 -0700506 * @cb: the NETLINK callback
Paul Moored15c3452006-08-03 16:48:37 -0700507 *
508 * Description:
Paul Moorefd385852006-09-25 15:56:37 -0700509 * Process a user generated LISTALL message and dumps the domain hash table in
510 * a form suitable for use in a kernel generated LISTALL message. Returns zero
511 * on success, negative values on failure.
Paul Moored15c3452006-08-03 16:48:37 -0700512 *
513 */
Paul Moorefd385852006-09-25 15:56:37 -0700514static int netlbl_mgmt_listall(struct sk_buff *skb,
515 struct netlink_callback *cb)
Paul Moored15c3452006-08-03 16:48:37 -0700516{
Paul Moorefd385852006-09-25 15:56:37 -0700517 struct netlbl_domhsh_walk_arg cb_arg;
518 u32 skip_bkt = cb->args[0];
519 u32 skip_chain = cb->args[1];
Paul Moored15c3452006-08-03 16:48:37 -0700520
Paul Moorefd385852006-09-25 15:56:37 -0700521 cb_arg.nl_cb = cb;
522 cb_arg.skb = skb;
523 cb_arg.seq = cb->nlh->nlmsg_seq;
Paul Moored15c3452006-08-03 16:48:37 -0700524
Paul Moorefd385852006-09-25 15:56:37 -0700525 netlbl_domhsh_walk(&skip_bkt,
526 &skip_chain,
527 netlbl_mgmt_listall_cb,
528 &cb_arg);
Paul Moored15c3452006-08-03 16:48:37 -0700529
Paul Moorefd385852006-09-25 15:56:37 -0700530 cb->args[0] = skip_bkt;
531 cb->args[1] = skip_chain;
532 return skb->len;
Paul Moored15c3452006-08-03 16:48:37 -0700533}
534
535/**
536 * netlbl_mgmt_adddef - Handle an ADDDEF message
537 * @skb: the NETLINK buffer
538 * @info: the Generic NETLINK info block
539 *
540 * Description:
541 * Process a user generated ADDDEF message and respond accordingly. Returns
542 * zero on success, negative values on failure.
543 *
544 */
545static int netlbl_mgmt_adddef(struct sk_buff *skb, struct genl_info *info)
546{
Paul Moore95d4e6b2006-09-29 17:05:05 -0700547 struct netlbl_audit audit_info;
Paul Moored15c3452006-08-03 16:48:37 -0700548
Paul Moore63c41682008-10-10 10:16:32 -0400549 if ((!info->attrs[NLBL_MGMT_A_PROTOCOL]) ||
550 (info->attrs[NLBL_MGMT_A_IPV4ADDR] &&
551 info->attrs[NLBL_MGMT_A_IPV6ADDR]) ||
552 (info->attrs[NLBL_MGMT_A_IPV4MASK] &&
553 info->attrs[NLBL_MGMT_A_IPV6MASK]) ||
554 ((info->attrs[NLBL_MGMT_A_IPV4ADDR] != NULL) ^
555 (info->attrs[NLBL_MGMT_A_IPV4MASK] != NULL)) ||
556 ((info->attrs[NLBL_MGMT_A_IPV6ADDR] != NULL) ^
557 (info->attrs[NLBL_MGMT_A_IPV6MASK] != NULL)))
558 return -EINVAL;
Paul Moored15c3452006-08-03 16:48:37 -0700559
Paul Moore95d4e6b2006-09-29 17:05:05 -0700560 netlbl_netlink_auditinfo(skb, &audit_info);
561
Paul Moore63c41682008-10-10 10:16:32 -0400562 return netlbl_mgmt_add_common(info, &audit_info);
Paul Moored15c3452006-08-03 16:48:37 -0700563}
564
565/**
566 * netlbl_mgmt_removedef - Handle a REMOVEDEF message
567 * @skb: the NETLINK buffer
568 * @info: the Generic NETLINK info block
569 *
570 * Description:
571 * Process a user generated REMOVEDEF message and remove the default domain
572 * mapping. Returns zero on success, negative values on failure.
573 *
574 */
575static int netlbl_mgmt_removedef(struct sk_buff *skb, struct genl_info *info)
576{
Paul Moore95d4e6b2006-09-29 17:05:05 -0700577 struct netlbl_audit audit_info;
578
579 netlbl_netlink_auditinfo(skb, &audit_info);
580
Huw Davies8f18e672016-06-27 15:02:46 -0400581 return netlbl_domhsh_remove_default(AF_UNSPEC, &audit_info);
Paul Moored15c3452006-08-03 16:48:37 -0700582}
583
584/**
585 * netlbl_mgmt_listdef - Handle a LISTDEF message
586 * @skb: the NETLINK buffer
587 * @info: the Generic NETLINK info block
588 *
589 * Description:
590 * Process a user generated LISTDEF message and dumps the default domain
591 * mapping in a form suitable for use in a kernel generated LISTDEF message.
592 * Returns zero on success, negative values on failure.
593 *
594 */
595static int netlbl_mgmt_listdef(struct sk_buff *skb, struct genl_info *info)
596{
597 int ret_val = -ENOMEM;
Paul Moorefd385852006-09-25 15:56:37 -0700598 struct sk_buff *ans_skb = NULL;
599 void *data;
600 struct netlbl_dom_map *entry;
Huw Davies8f18e672016-06-27 15:02:46 -0400601 u16 family;
602
603 if (info->attrs[NLBL_MGMT_A_FAMILY])
604 family = nla_get_u16(info->attrs[NLBL_MGMT_A_FAMILY]);
605 else
606 family = AF_INET;
Paul Moored15c3452006-08-03 16:48:37 -0700607
Thomas Graf339bf982006-11-10 14:10:15 -0800608 ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
Paul Moored15c3452006-08-03 16:48:37 -0700609 if (ans_skb == NULL)
Paul Moorefd385852006-09-25 15:56:37 -0700610 return -ENOMEM;
Thomas Graf17c157c2006-11-14 19:46:02 -0800611 data = genlmsg_put_reply(ans_skb, info, &netlbl_mgmt_gnl_family,
612 0, NLBL_MGMT_C_LISTDEF);
Paul Moorefd385852006-09-25 15:56:37 -0700613 if (data == NULL)
Paul Moored15c3452006-08-03 16:48:37 -0700614 goto listdef_failure;
Paul Moored15c3452006-08-03 16:48:37 -0700615
Paul Moorefd385852006-09-25 15:56:37 -0700616 rcu_read_lock();
Huw Davies8f18e672016-06-27 15:02:46 -0400617 entry = netlbl_domhsh_getentry(NULL, family);
Paul Moorefd385852006-09-25 15:56:37 -0700618 if (entry == NULL) {
619 ret_val = -ENOENT;
620 goto listdef_failure_lock;
621 }
Paul Moore63c41682008-10-10 10:16:32 -0400622 ret_val = netlbl_mgmt_listentry(ans_skb, entry);
Paul Moorefd385852006-09-25 15:56:37 -0700623 rcu_read_unlock();
Paul Moore63c41682008-10-10 10:16:32 -0400624 if (ret_val != 0)
625 goto listdef_failure;
Paul Moorefd385852006-09-25 15:56:37 -0700626
627 genlmsg_end(ans_skb, data);
Denis V. Lunevfe785be2008-07-10 16:53:39 -0700628 return genlmsg_reply(ans_skb, info);
Paul Moored15c3452006-08-03 16:48:37 -0700629
Paul Moorefd385852006-09-25 15:56:37 -0700630listdef_failure_lock:
631 rcu_read_unlock();
Paul Moored15c3452006-08-03 16:48:37 -0700632listdef_failure:
Paul Moorefd385852006-09-25 15:56:37 -0700633 kfree_skb(ans_skb);
Paul Moored15c3452006-08-03 16:48:37 -0700634 return ret_val;
635}
636
637/**
Paul Moorefd385852006-09-25 15:56:37 -0700638 * netlbl_mgmt_protocols_cb - Write an individual PROTOCOL message response
639 * @skb: the skb to write to
Paul Moorefd385852006-09-25 15:56:37 -0700640 * @cb: the NETLINK callback
641 * @protocol: the NetLabel protocol to use in the message
Paul Moored15c3452006-08-03 16:48:37 -0700642 *
643 * Description:
Paul Moorefd385852006-09-25 15:56:37 -0700644 * This function is to be used in conjunction with netlbl_mgmt_protocols() to
645 * answer a application's PROTOCOLS message. Returns the size of the message
646 * on success, negative values on failure.
Paul Moored15c3452006-08-03 16:48:37 -0700647 *
648 */
Paul Moorefd385852006-09-25 15:56:37 -0700649static int netlbl_mgmt_protocols_cb(struct sk_buff *skb,
650 struct netlink_callback *cb,
651 u32 protocol)
Paul Moored15c3452006-08-03 16:48:37 -0700652{
653 int ret_val = -ENOMEM;
Paul Moorefd385852006-09-25 15:56:37 -0700654 void *data;
Paul Moored15c3452006-08-03 16:48:37 -0700655
Eric W. Biederman15e47302012-09-07 20:12:54 +0000656 data = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
Thomas Graf17c157c2006-11-14 19:46:02 -0800657 &netlbl_mgmt_gnl_family, NLM_F_MULTI,
658 NLBL_MGMT_C_PROTOCOLS);
Paul Moorefd385852006-09-25 15:56:37 -0700659 if (data == NULL)
660 goto protocols_cb_failure;
Paul Moored15c3452006-08-03 16:48:37 -0700661
Paul Moorefd385852006-09-25 15:56:37 -0700662 ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL, protocol);
Paul Moored15c3452006-08-03 16:48:37 -0700663 if (ret_val != 0)
Paul Moorefd385852006-09-25 15:56:37 -0700664 goto protocols_cb_failure;
Paul Moored15c3452006-08-03 16:48:37 -0700665
Johannes Berg053c0952015-01-16 22:09:00 +0100666 genlmsg_end(skb, data);
667 return 0;
Paul Moored15c3452006-08-03 16:48:37 -0700668
Paul Moorefd385852006-09-25 15:56:37 -0700669protocols_cb_failure:
670 genlmsg_cancel(skb, data);
Paul Moored15c3452006-08-03 16:48:37 -0700671 return ret_val;
672}
673
674/**
Paul Moorefd385852006-09-25 15:56:37 -0700675 * netlbl_mgmt_protocols - Handle a PROTOCOLS message
676 * @skb: the NETLINK buffer
677 * @cb: the NETLINK callback
678 *
679 * Description:
680 * Process a user generated PROTOCOLS message and respond accordingly.
681 *
682 */
683static int netlbl_mgmt_protocols(struct sk_buff *skb,
684 struct netlink_callback *cb)
685{
686 u32 protos_sent = cb->args[0];
687
688 if (protos_sent == 0) {
689 if (netlbl_mgmt_protocols_cb(skb,
690 cb,
691 NETLBL_NLTYPE_UNLABELED) < 0)
692 goto protocols_return;
693 protos_sent++;
694 }
695 if (protos_sent == 1) {
696 if (netlbl_mgmt_protocols_cb(skb,
697 cb,
698 NETLBL_NLTYPE_CIPSOV4) < 0)
699 goto protocols_return;
700 protos_sent++;
701 }
Huw Daviescb72d382016-06-27 15:02:46 -0400702#if IS_ENABLED(CONFIG_IPV6)
703 if (protos_sent == 2) {
704 if (netlbl_mgmt_protocols_cb(skb,
705 cb,
706 NETLBL_NLTYPE_CALIPSO) < 0)
707 goto protocols_return;
708 protos_sent++;
709 }
710#endif
Paul Moorefd385852006-09-25 15:56:37 -0700711
712protocols_return:
713 cb->args[0] = protos_sent;
714 return skb->len;
715}
716
717/**
Paul Moored15c3452006-08-03 16:48:37 -0700718 * netlbl_mgmt_version - Handle a VERSION message
719 * @skb: the NETLINK buffer
720 * @info: the Generic NETLINK info block
721 *
722 * Description:
723 * Process a user generated VERSION message and respond accordingly. Returns
724 * zero on success, negative values on failure.
725 *
726 */
727static int netlbl_mgmt_version(struct sk_buff *skb, struct genl_info *info)
728{
729 int ret_val = -ENOMEM;
730 struct sk_buff *ans_skb = NULL;
Paul Moorefd385852006-09-25 15:56:37 -0700731 void *data;
Paul Moored15c3452006-08-03 16:48:37 -0700732
Thomas Graf339bf982006-11-10 14:10:15 -0800733 ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
Paul Moored15c3452006-08-03 16:48:37 -0700734 if (ans_skb == NULL)
Paul Moorefd385852006-09-25 15:56:37 -0700735 return -ENOMEM;
Thomas Graf17c157c2006-11-14 19:46:02 -0800736 data = genlmsg_put_reply(ans_skb, info, &netlbl_mgmt_gnl_family,
737 0, NLBL_MGMT_C_VERSION);
Paul Moorefd385852006-09-25 15:56:37 -0700738 if (data == NULL)
Paul Moored15c3452006-08-03 16:48:37 -0700739 goto version_failure;
740
Paul Moorefd385852006-09-25 15:56:37 -0700741 ret_val = nla_put_u32(ans_skb,
742 NLBL_MGMT_A_VERSION,
743 NETLBL_PROTO_VERSION);
Paul Moored15c3452006-08-03 16:48:37 -0700744 if (ret_val != 0)
745 goto version_failure;
746
Paul Moorefd385852006-09-25 15:56:37 -0700747 genlmsg_end(ans_skb, data);
Denis V. Lunevfe785be2008-07-10 16:53:39 -0700748 return genlmsg_reply(ans_skb, info);
Paul Moored15c3452006-08-03 16:48:37 -0700749
750version_failure:
751 kfree_skb(ans_skb);
Paul Moored15c3452006-08-03 16:48:37 -0700752 return ret_val;
753}
754
755
756/*
757 * NetLabel Generic NETLINK Command Definitions
758 */
759
Johannes Berg4534de82013-11-14 17:14:46 +0100760static const struct genl_ops netlbl_mgmt_genl_ops[] = {
Pavel Emelyanov227c43c2008-02-17 22:33:16 -0800761 {
Paul Moored15c3452006-08-03 16:48:37 -0700762 .cmd = NLBL_MGMT_C_ADD,
Johannes Bergef6243a2019-04-26 14:07:31 +0200763 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
Paul Moorefd385852006-09-25 15:56:37 -0700764 .flags = GENL_ADMIN_PERM,
Paul Moored15c3452006-08-03 16:48:37 -0700765 .doit = netlbl_mgmt_add,
766 .dumpit = NULL,
Pavel Emelyanov227c43c2008-02-17 22:33:16 -0800767 },
768 {
Paul Moored15c3452006-08-03 16:48:37 -0700769 .cmd = NLBL_MGMT_C_REMOVE,
Johannes Bergef6243a2019-04-26 14:07:31 +0200770 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
Paul Moorefd385852006-09-25 15:56:37 -0700771 .flags = GENL_ADMIN_PERM,
Paul Moored15c3452006-08-03 16:48:37 -0700772 .doit = netlbl_mgmt_remove,
773 .dumpit = NULL,
Pavel Emelyanov227c43c2008-02-17 22:33:16 -0800774 },
775 {
Paul Moorefd385852006-09-25 15:56:37 -0700776 .cmd = NLBL_MGMT_C_LISTALL,
Johannes Bergef6243a2019-04-26 14:07:31 +0200777 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
Paul Moored15c3452006-08-03 16:48:37 -0700778 .flags = 0,
Paul Moorefd385852006-09-25 15:56:37 -0700779 .doit = NULL,
780 .dumpit = netlbl_mgmt_listall,
Pavel Emelyanov227c43c2008-02-17 22:33:16 -0800781 },
782 {
Paul Moored15c3452006-08-03 16:48:37 -0700783 .cmd = NLBL_MGMT_C_ADDDEF,
Johannes Bergef6243a2019-04-26 14:07:31 +0200784 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
Paul Moorefd385852006-09-25 15:56:37 -0700785 .flags = GENL_ADMIN_PERM,
Paul Moored15c3452006-08-03 16:48:37 -0700786 .doit = netlbl_mgmt_adddef,
787 .dumpit = NULL,
Pavel Emelyanov227c43c2008-02-17 22:33:16 -0800788 },
789 {
Paul Moored15c3452006-08-03 16:48:37 -0700790 .cmd = NLBL_MGMT_C_REMOVEDEF,
Johannes Bergef6243a2019-04-26 14:07:31 +0200791 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
Paul Moorefd385852006-09-25 15:56:37 -0700792 .flags = GENL_ADMIN_PERM,
Paul Moored15c3452006-08-03 16:48:37 -0700793 .doit = netlbl_mgmt_removedef,
794 .dumpit = NULL,
Pavel Emelyanov227c43c2008-02-17 22:33:16 -0800795 },
796 {
Paul Moored15c3452006-08-03 16:48:37 -0700797 .cmd = NLBL_MGMT_C_LISTDEF,
Johannes Bergef6243a2019-04-26 14:07:31 +0200798 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
Paul Moored15c3452006-08-03 16:48:37 -0700799 .flags = 0,
800 .doit = netlbl_mgmt_listdef,
801 .dumpit = NULL,
Pavel Emelyanov227c43c2008-02-17 22:33:16 -0800802 },
803 {
Paul Moorefd385852006-09-25 15:56:37 -0700804 .cmd = NLBL_MGMT_C_PROTOCOLS,
Johannes Bergef6243a2019-04-26 14:07:31 +0200805 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
Paul Moored15c3452006-08-03 16:48:37 -0700806 .flags = 0,
Paul Moorefd385852006-09-25 15:56:37 -0700807 .doit = NULL,
808 .dumpit = netlbl_mgmt_protocols,
Pavel Emelyanov227c43c2008-02-17 22:33:16 -0800809 },
810 {
Paul Moored15c3452006-08-03 16:48:37 -0700811 .cmd = NLBL_MGMT_C_VERSION,
Johannes Bergef6243a2019-04-26 14:07:31 +0200812 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
Paul Moored15c3452006-08-03 16:48:37 -0700813 .flags = 0,
814 .doit = netlbl_mgmt_version,
815 .dumpit = NULL,
Pavel Emelyanov227c43c2008-02-17 22:33:16 -0800816 },
Paul Moored15c3452006-08-03 16:48:37 -0700817};
818
Johannes Berg56989f62016-10-24 14:40:05 +0200819static struct genl_family netlbl_mgmt_gnl_family __ro_after_init = {
Johannes Berg489111e2016-10-24 14:40:03 +0200820 .hdrsize = 0,
821 .name = NETLBL_NLTYPE_MGMT_NAME,
822 .version = NETLBL_PROTO_VERSION,
823 .maxattr = NLBL_MGMT_A_MAX,
Johannes Berg3b0f31f2019-03-21 22:51:02 +0100824 .policy = netlbl_mgmt_genl_policy,
Johannes Berg489111e2016-10-24 14:40:03 +0200825 .module = THIS_MODULE,
826 .ops = netlbl_mgmt_genl_ops,
827 .n_ops = ARRAY_SIZE(netlbl_mgmt_genl_ops),
828};
829
Paul Moored15c3452006-08-03 16:48:37 -0700830/*
831 * NetLabel Generic NETLINK Protocol Functions
832 */
833
834/**
835 * netlbl_mgmt_genl_init - Register the NetLabel management component
836 *
837 * Description:
838 * Register the NetLabel management component with the Generic NETLINK
839 * mechanism. Returns zero on success, negative values on failure.
840 *
841 */
Pavel Emelyanov05705e42008-02-17 22:33:57 -0800842int __init netlbl_mgmt_genl_init(void)
Paul Moored15c3452006-08-03 16:48:37 -0700843{
Johannes Berg489111e2016-10-24 14:40:03 +0200844 return genl_register_family(&netlbl_mgmt_gnl_family);
Paul Moored15c3452006-08-03 16:48:37 -0700845}