blob: 3b00f2368fcd49eee521caf917bdd276c6584d20 [file] [log] [blame]
Paul Moored15c3452006-08-03 16:48:37 -07001/*
2 * NetLabel Management Support
3 *
4 * This file defines the management functions for the NetLabel system. The
5 * NetLabel system manages static and dynamic label mappings for network
6 * protocols such as CIPSO and RIPSO.
7 *
Paul Moore82c21bf2011-08-01 11:10:33 +00008 * Author: Paul Moore <paul@paul-moore.com>
Paul Moored15c3452006-08-03 16:48:37 -07009 *
10 */
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 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
23 * the GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
Jeff Kirsherd484ff12013-12-06 09:13:41 -080026 * along with this program; if not, see <http://www.gnu.org/licenses/>.
Paul Moored15c3452006-08-03 16:48:37 -070027 *
28 */
29
30#include <linux/types.h>
31#include <linux/socket.h>
32#include <linux/string.h>
33#include <linux/skbuff.h>
Paul Moore63c41682008-10-10 10:16:32 -040034#include <linux/in.h>
35#include <linux/in6.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090036#include <linux/slab.h>
Paul Moored15c3452006-08-03 16:48:37 -070037#include <net/sock.h>
38#include <net/netlink.h>
39#include <net/genetlink.h>
Paul Moore63c41682008-10-10 10:16:32 -040040#include <net/ip.h>
41#include <net/ipv6.h>
Paul Moored15c3452006-08-03 16:48:37 -070042#include <net/netlabel.h>
43#include <net/cipso_ipv4.h>
Huw Daviesdc7de732016-06-27 15:02:49 -040044#include <net/calipso.h>
Arun Sharma600634972011-07-26 16:09:06 -070045#include <linux/atomic.h>
Paul Moored15c3452006-08-03 16:48:37 -070046
Huw Daviesdc7de732016-06-27 15:02:49 -040047#include "netlabel_calipso.h"
Paul Moored15c3452006-08-03 16:48:37 -070048#include "netlabel_domainhash.h"
49#include "netlabel_user.h"
50#include "netlabel_mgmt.h"
51
Paul Moorec783f1c2008-01-29 08:37:52 -050052/* NetLabel configured protocol counter */
53atomic_t netlabel_mgmt_protocount = ATOMIC_INIT(0);
Paul Moore23bcdc12007-07-18 12:28:45 -040054
Paul Moorefd385852006-09-25 15:56:37 -070055/* Argument struct for netlbl_domhsh_walk() */
56struct netlbl_domhsh_walk_arg {
57 struct netlink_callback *nl_cb;
58 struct sk_buff *skb;
59 u32 seq;
60};
61
Paul Moored15c3452006-08-03 16:48:37 -070062/* NetLabel Generic NETLINK CIPSOv4 family */
63static struct genl_family netlbl_mgmt_gnl_family = {
Paul Moored15c3452006-08-03 16:48:37 -070064 .hdrsize = 0,
65 .name = NETLBL_NLTYPE_MGMT_NAME,
66 .version = NETLBL_PROTO_VERSION,
Paul Moorefd385852006-09-25 15:56:37 -070067 .maxattr = NLBL_MGMT_A_MAX,
Paul Moored15c3452006-08-03 16:48:37 -070068};
69
Paul Moorefd385852006-09-25 15:56:37 -070070/* NetLabel Netlink attribute policy */
Patrick McHardyef7c79e2007-06-05 12:38:30 -070071static const struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = {
Paul Moorefd385852006-09-25 15:56:37 -070072 [NLBL_MGMT_A_DOMAIN] = { .type = NLA_NUL_STRING },
73 [NLBL_MGMT_A_PROTOCOL] = { .type = NLA_U32 },
74 [NLBL_MGMT_A_VERSION] = { .type = NLA_U32 },
75 [NLBL_MGMT_A_CV4DOI] = { .type = NLA_U32 },
Huw Davies8f18e672016-06-27 15:02:46 -040076 [NLBL_MGMT_A_FAMILY] = { .type = NLA_U16 },
Huw Daviesdc7de732016-06-27 15:02:49 -040077 [NLBL_MGMT_A_CLPDOI] = { .type = NLA_U32 },
Paul Moorefd385852006-09-25 15:56:37 -070078};
Paul Moored15c3452006-08-03 16:48:37 -070079
80/*
Paul Moore63c41682008-10-10 10:16:32 -040081 * Helper Functions
82 */
83
84/**
85 * netlbl_mgmt_add - Handle an ADD message
86 * @info: the Generic NETLINK info block
87 * @audit_info: NetLabel audit information
88 *
89 * Description:
90 * Helper function for the ADD and ADDDEF messages to add the domain mappings
91 * from the message to the hash table. See netlabel.h for a description of the
92 * message format. Returns zero on success, negative values on failure.
93 *
94 */
95static int netlbl_mgmt_add_common(struct genl_info *info,
96 struct netlbl_audit *audit_info)
97{
98 int ret_val = -EINVAL;
Paul Moore63c41682008-10-10 10:16:32 -040099 struct netlbl_domaddr_map *addrmap = NULL;
100 struct cipso_v4_doi *cipsov4 = NULL;
Huw Daviesdc7de732016-06-27 15:02:49 -0400101#if IS_ENABLED(CONFIG_IPV6)
102 struct calipso_doi *calipso = NULL;
103#endif
Paul Moore63c41682008-10-10 10:16:32 -0400104 u32 tmp_val;
Markus Elfring4de46d52015-02-02 11:00:24 +0100105 struct netlbl_dom_map *entry = kzalloc(sizeof(*entry), GFP_KERNEL);
Paul Moore63c41682008-10-10 10:16:32 -0400106
Markus Elfring4de46d52015-02-02 11:00:24 +0100107 if (!entry)
108 return -ENOMEM;
Paul Moore6a8b7f02013-08-02 14:45:08 -0400109 entry->def.type = nla_get_u32(info->attrs[NLBL_MGMT_A_PROTOCOL]);
Paul Moore63c41682008-10-10 10:16:32 -0400110 if (info->attrs[NLBL_MGMT_A_DOMAIN]) {
111 size_t tmp_size = nla_len(info->attrs[NLBL_MGMT_A_DOMAIN]);
112 entry->domain = kmalloc(tmp_size, GFP_KERNEL);
113 if (entry->domain == NULL) {
114 ret_val = -ENOMEM;
Markus Elfring4de46d52015-02-02 11:00:24 +0100115 goto add_free_entry;
Paul Moore63c41682008-10-10 10:16:32 -0400116 }
117 nla_strlcpy(entry->domain,
118 info->attrs[NLBL_MGMT_A_DOMAIN], tmp_size);
119 }
120
Paul Moore6a8b7f02013-08-02 14:45:08 -0400121 /* NOTE: internally we allow/use a entry->def.type value of
Paul Moore63c41682008-10-10 10:16:32 -0400122 * NETLBL_NLTYPE_ADDRSELECT but we don't currently allow users
123 * to pass that as a protocol value because we need to know the
124 * "real" protocol */
125
Paul Moore6a8b7f02013-08-02 14:45:08 -0400126 switch (entry->def.type) {
Paul Moore63c41682008-10-10 10:16:32 -0400127 case NETLBL_NLTYPE_UNLABELED:
Huw Davies8f18e672016-06-27 15:02:46 -0400128 if (info->attrs[NLBL_MGMT_A_FAMILY])
129 entry->family =
130 nla_get_u16(info->attrs[NLBL_MGMT_A_FAMILY]);
131 else
132 entry->family = AF_UNSPEC;
Paul Moore63c41682008-10-10 10:16:32 -0400133 break;
134 case NETLBL_NLTYPE_CIPSOV4:
135 if (!info->attrs[NLBL_MGMT_A_CV4DOI])
Markus Elfring4de46d52015-02-02 11:00:24 +0100136 goto add_free_domain;
Paul Moore63c41682008-10-10 10:16:32 -0400137
138 tmp_val = nla_get_u32(info->attrs[NLBL_MGMT_A_CV4DOI]);
139 cipsov4 = cipso_v4_doi_getdef(tmp_val);
140 if (cipsov4 == NULL)
Markus Elfring4de46d52015-02-02 11:00:24 +0100141 goto add_free_domain;
Huw Davies8f18e672016-06-27 15:02:46 -0400142 entry->family = AF_INET;
Paul Moore6a8b7f02013-08-02 14:45:08 -0400143 entry->def.cipso = cipsov4;
Paul Moore63c41682008-10-10 10:16:32 -0400144 break;
Huw Daviesdc7de732016-06-27 15:02:49 -0400145#if IS_ENABLED(CONFIG_IPV6)
146 case NETLBL_NLTYPE_CALIPSO:
147 if (!info->attrs[NLBL_MGMT_A_CLPDOI])
148 goto add_free_domain;
149
150 tmp_val = nla_get_u32(info->attrs[NLBL_MGMT_A_CLPDOI]);
151 calipso = calipso_doi_getdef(tmp_val);
152 if (calipso == NULL)
153 goto add_free_domain;
154 entry->family = AF_INET6;
155 entry->def.calipso = calipso;
156 break;
157#endif /* IPv6 */
Paul Moore63c41682008-10-10 10:16:32 -0400158 default:
Markus Elfring4de46d52015-02-02 11:00:24 +0100159 goto add_free_domain;
Paul Moore63c41682008-10-10 10:16:32 -0400160 }
161
Huw Davies8f18e672016-06-27 15:02:46 -0400162 if ((entry->family == AF_INET && info->attrs[NLBL_MGMT_A_IPV6ADDR]) ||
163 (entry->family == AF_INET6 && info->attrs[NLBL_MGMT_A_IPV4ADDR]))
164 goto add_doi_put_def;
165
Paul Moore63c41682008-10-10 10:16:32 -0400166 if (info->attrs[NLBL_MGMT_A_IPV4ADDR]) {
167 struct in_addr *addr;
168 struct in_addr *mask;
169 struct netlbl_domaddr4_map *map;
170
171 addrmap = kzalloc(sizeof(*addrmap), GFP_KERNEL);
172 if (addrmap == NULL) {
173 ret_val = -ENOMEM;
Markus Elfring4de46d52015-02-02 11:00:24 +0100174 goto add_doi_put_def;
Paul Moore63c41682008-10-10 10:16:32 -0400175 }
176 INIT_LIST_HEAD(&addrmap->list4);
177 INIT_LIST_HEAD(&addrmap->list6);
178
179 if (nla_len(info->attrs[NLBL_MGMT_A_IPV4ADDR]) !=
180 sizeof(struct in_addr)) {
181 ret_val = -EINVAL;
Markus Elfring4de46d52015-02-02 11:00:24 +0100182 goto add_free_addrmap;
Paul Moore63c41682008-10-10 10:16:32 -0400183 }
184 if (nla_len(info->attrs[NLBL_MGMT_A_IPV4MASK]) !=
185 sizeof(struct in_addr)) {
186 ret_val = -EINVAL;
Markus Elfring4de46d52015-02-02 11:00:24 +0100187 goto add_free_addrmap;
Paul Moore63c41682008-10-10 10:16:32 -0400188 }
189 addr = nla_data(info->attrs[NLBL_MGMT_A_IPV4ADDR]);
190 mask = nla_data(info->attrs[NLBL_MGMT_A_IPV4MASK]);
191
192 map = kzalloc(sizeof(*map), GFP_KERNEL);
193 if (map == NULL) {
194 ret_val = -ENOMEM;
Markus Elfring4de46d52015-02-02 11:00:24 +0100195 goto add_free_addrmap;
Paul Moore63c41682008-10-10 10:16:32 -0400196 }
197 map->list.addr = addr->s_addr & mask->s_addr;
198 map->list.mask = mask->s_addr;
199 map->list.valid = 1;
Paul Moore6a8b7f02013-08-02 14:45:08 -0400200 map->def.type = entry->def.type;
Paul Moore63c41682008-10-10 10:16:32 -0400201 if (cipsov4)
Paul Moore6a8b7f02013-08-02 14:45:08 -0400202 map->def.cipso = cipsov4;
Paul Moore63c41682008-10-10 10:16:32 -0400203
204 ret_val = netlbl_af4list_add(&map->list, &addrmap->list4);
205 if (ret_val != 0) {
206 kfree(map);
Markus Elfring4de46d52015-02-02 11:00:24 +0100207 goto add_free_addrmap;
Paul Moore63c41682008-10-10 10:16:32 -0400208 }
209
Huw Davies8f18e672016-06-27 15:02:46 -0400210 entry->family = AF_INET;
Paul Moore6a8b7f02013-08-02 14:45:08 -0400211 entry->def.type = NETLBL_NLTYPE_ADDRSELECT;
212 entry->def.addrsel = addrmap;
Eric Dumazetdfd56b82011-12-10 09:48:31 +0000213#if IS_ENABLED(CONFIG_IPV6)
Paul Moore63c41682008-10-10 10:16:32 -0400214 } else if (info->attrs[NLBL_MGMT_A_IPV6ADDR]) {
215 struct in6_addr *addr;
216 struct in6_addr *mask;
217 struct netlbl_domaddr6_map *map;
218
219 addrmap = kzalloc(sizeof(*addrmap), GFP_KERNEL);
220 if (addrmap == NULL) {
221 ret_val = -ENOMEM;
Markus Elfring4de46d52015-02-02 11:00:24 +0100222 goto add_doi_put_def;
Paul Moore63c41682008-10-10 10:16:32 -0400223 }
224 INIT_LIST_HEAD(&addrmap->list4);
225 INIT_LIST_HEAD(&addrmap->list6);
226
227 if (nla_len(info->attrs[NLBL_MGMT_A_IPV6ADDR]) !=
228 sizeof(struct in6_addr)) {
229 ret_val = -EINVAL;
Markus Elfring4de46d52015-02-02 11:00:24 +0100230 goto add_free_addrmap;
Paul Moore63c41682008-10-10 10:16:32 -0400231 }
232 if (nla_len(info->attrs[NLBL_MGMT_A_IPV6MASK]) !=
233 sizeof(struct in6_addr)) {
234 ret_val = -EINVAL;
Markus Elfring4de46d52015-02-02 11:00:24 +0100235 goto add_free_addrmap;
Paul Moore63c41682008-10-10 10:16:32 -0400236 }
237 addr = nla_data(info->attrs[NLBL_MGMT_A_IPV6ADDR]);
238 mask = nla_data(info->attrs[NLBL_MGMT_A_IPV6MASK]);
239
240 map = kzalloc(sizeof(*map), GFP_KERNEL);
241 if (map == NULL) {
242 ret_val = -ENOMEM;
Markus Elfring4de46d52015-02-02 11:00:24 +0100243 goto add_free_addrmap;
Paul Moore63c41682008-10-10 10:16:32 -0400244 }
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +0000245 map->list.addr = *addr;
Paul Moore63c41682008-10-10 10:16:32 -0400246 map->list.addr.s6_addr32[0] &= mask->s6_addr32[0];
247 map->list.addr.s6_addr32[1] &= mask->s6_addr32[1];
248 map->list.addr.s6_addr32[2] &= mask->s6_addr32[2];
249 map->list.addr.s6_addr32[3] &= mask->s6_addr32[3];
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +0000250 map->list.mask = *mask;
Paul Moore63c41682008-10-10 10:16:32 -0400251 map->list.valid = 1;
Paul Moore6a8b7f02013-08-02 14:45:08 -0400252 map->def.type = entry->def.type;
Huw Daviesdc7de732016-06-27 15:02:49 -0400253 if (calipso)
254 map->def.calipso = calipso;
Paul Moore63c41682008-10-10 10:16:32 -0400255
256 ret_val = netlbl_af6list_add(&map->list, &addrmap->list6);
257 if (ret_val != 0) {
258 kfree(map);
Markus Elfring4de46d52015-02-02 11:00:24 +0100259 goto add_free_addrmap;
Paul Moore63c41682008-10-10 10:16:32 -0400260 }
261
Huw Davies8f18e672016-06-27 15:02:46 -0400262 entry->family = AF_INET6;
Paul Moore6a8b7f02013-08-02 14:45:08 -0400263 entry->def.type = NETLBL_NLTYPE_ADDRSELECT;
264 entry->def.addrsel = addrmap;
Paul Moore63c41682008-10-10 10:16:32 -0400265#endif /* IPv6 */
266 }
267
268 ret_val = netlbl_domhsh_add(entry, audit_info);
269 if (ret_val != 0)
Markus Elfring4de46d52015-02-02 11:00:24 +0100270 goto add_free_addrmap;
Paul Moore63c41682008-10-10 10:16:32 -0400271
272 return 0;
273
Markus Elfring4de46d52015-02-02 11:00:24 +0100274add_free_addrmap:
Paul Moore63c41682008-10-10 10:16:32 -0400275 kfree(addrmap);
Markus Elfring4de46d52015-02-02 11:00:24 +0100276add_doi_put_def:
277 cipso_v4_doi_putdef(cipsov4);
Huw Daviesdc7de732016-06-27 15:02:49 -0400278#if IS_ENABLED(CONFIG_IPV6)
279 calipso_doi_putdef(calipso);
280#endif
Markus Elfring4de46d52015-02-02 11:00:24 +0100281add_free_domain:
282 kfree(entry->domain);
283add_free_entry:
Paul Moore63c41682008-10-10 10:16:32 -0400284 kfree(entry);
285 return ret_val;
286}
287
288/**
289 * netlbl_mgmt_listentry - List a NetLabel/LSM domain map entry
290 * @skb: the NETLINK buffer
291 * @entry: the map entry
292 *
293 * Description:
294 * This function is a helper function used by the LISTALL and LISTDEF command
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300295 * handlers. The caller is responsible for ensuring that the RCU read lock
Paul Moore63c41682008-10-10 10:16:32 -0400296 * is held. Returns zero on success, negative values on failure.
297 *
298 */
299static int netlbl_mgmt_listentry(struct sk_buff *skb,
300 struct netlbl_dom_map *entry)
301{
Paul Mooref8a02472008-10-29 16:09:12 -0400302 int ret_val = 0;
Paul Moore63c41682008-10-10 10:16:32 -0400303 struct nlattr *nla_a;
304 struct nlattr *nla_b;
305 struct netlbl_af4list *iter4;
Eric Dumazetdfd56b82011-12-10 09:48:31 +0000306#if IS_ENABLED(CONFIG_IPV6)
Paul Moore63c41682008-10-10 10:16:32 -0400307 struct netlbl_af6list *iter6;
308#endif
309
310 if (entry->domain != NULL) {
311 ret_val = nla_put_string(skb,
312 NLBL_MGMT_A_DOMAIN, entry->domain);
313 if (ret_val != 0)
314 return ret_val;
315 }
316
Huw Davies8f18e672016-06-27 15:02:46 -0400317 ret_val = nla_put_u16(skb, NLBL_MGMT_A_FAMILY, entry->family);
318 if (ret_val != 0)
319 return ret_val;
320
Paul Moore6a8b7f02013-08-02 14:45:08 -0400321 switch (entry->def.type) {
Paul Moore63c41682008-10-10 10:16:32 -0400322 case NETLBL_NLTYPE_ADDRSELECT:
323 nla_a = nla_nest_start(skb, NLBL_MGMT_A_SELECTORLIST);
324 if (nla_a == NULL)
325 return -ENOMEM;
326
Paul Moore6a8b7f02013-08-02 14:45:08 -0400327 netlbl_af4list_foreach_rcu(iter4, &entry->def.addrsel->list4) {
Paul Moore63c41682008-10-10 10:16:32 -0400328 struct netlbl_domaddr4_map *map4;
329 struct in_addr addr_struct;
330
331 nla_b = nla_nest_start(skb, NLBL_MGMT_A_ADDRSELECTOR);
332 if (nla_b == NULL)
333 return -ENOMEM;
334
335 addr_struct.s_addr = iter4->addr;
Jiri Benc930345e2015-03-29 16:59:25 +0200336 ret_val = nla_put_in_addr(skb, NLBL_MGMT_A_IPV4ADDR,
337 addr_struct.s_addr);
Paul Moore63c41682008-10-10 10:16:32 -0400338 if (ret_val != 0)
339 return ret_val;
340 addr_struct.s_addr = iter4->mask;
Jiri Benc930345e2015-03-29 16:59:25 +0200341 ret_val = nla_put_in_addr(skb, NLBL_MGMT_A_IPV4MASK,
342 addr_struct.s_addr);
Paul Moore63c41682008-10-10 10:16:32 -0400343 if (ret_val != 0)
344 return ret_val;
345 map4 = netlbl_domhsh_addr4_entry(iter4);
346 ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL,
Paul Moore6a8b7f02013-08-02 14:45:08 -0400347 map4->def.type);
Paul Moore63c41682008-10-10 10:16:32 -0400348 if (ret_val != 0)
349 return ret_val;
Paul Moore6a8b7f02013-08-02 14:45:08 -0400350 switch (map4->def.type) {
Paul Moore63c41682008-10-10 10:16:32 -0400351 case NETLBL_NLTYPE_CIPSOV4:
352 ret_val = nla_put_u32(skb, NLBL_MGMT_A_CV4DOI,
Paul Moore6a8b7f02013-08-02 14:45:08 -0400353 map4->def.cipso->doi);
Paul Moore63c41682008-10-10 10:16:32 -0400354 if (ret_val != 0)
355 return ret_val;
356 break;
357 }
358
359 nla_nest_end(skb, nla_b);
360 }
Eric Dumazetdfd56b82011-12-10 09:48:31 +0000361#if IS_ENABLED(CONFIG_IPV6)
Paul Moore6a8b7f02013-08-02 14:45:08 -0400362 netlbl_af6list_foreach_rcu(iter6, &entry->def.addrsel->list6) {
Paul Moore63c41682008-10-10 10:16:32 -0400363 struct netlbl_domaddr6_map *map6;
364
365 nla_b = nla_nest_start(skb, NLBL_MGMT_A_ADDRSELECTOR);
366 if (nla_b == NULL)
367 return -ENOMEM;
368
Jiri Benc930345e2015-03-29 16:59:25 +0200369 ret_val = nla_put_in6_addr(skb, NLBL_MGMT_A_IPV6ADDR,
370 &iter6->addr);
Paul Moore63c41682008-10-10 10:16:32 -0400371 if (ret_val != 0)
372 return ret_val;
Jiri Benc930345e2015-03-29 16:59:25 +0200373 ret_val = nla_put_in6_addr(skb, NLBL_MGMT_A_IPV6MASK,
374 &iter6->mask);
Paul Moore63c41682008-10-10 10:16:32 -0400375 if (ret_val != 0)
376 return ret_val;
377 map6 = netlbl_domhsh_addr6_entry(iter6);
378 ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL,
Paul Moore6a8b7f02013-08-02 14:45:08 -0400379 map6->def.type);
Paul Moore63c41682008-10-10 10:16:32 -0400380 if (ret_val != 0)
381 return ret_val;
382
Huw Daviesdc7de732016-06-27 15:02:49 -0400383 switch (map6->def.type) {
384 case NETLBL_NLTYPE_CALIPSO:
385 ret_val = nla_put_u32(skb, NLBL_MGMT_A_CLPDOI,
386 map6->def.calipso->doi);
387 if (ret_val != 0)
388 return ret_val;
389 break;
390 }
391
Paul Moore63c41682008-10-10 10:16:32 -0400392 nla_nest_end(skb, nla_b);
393 }
394#endif /* IPv6 */
395
396 nla_nest_end(skb, nla_a);
397 break;
398 case NETLBL_NLTYPE_UNLABELED:
Huw Daviesdc7de732016-06-27 15:02:49 -0400399 ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL,
400 entry->def.type);
Paul Moore63c41682008-10-10 10:16:32 -0400401 break;
402 case NETLBL_NLTYPE_CIPSOV4:
Huw Daviesdc7de732016-06-27 15:02:49 -0400403 ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL,
404 entry->def.type);
Paul Moore63c41682008-10-10 10:16:32 -0400405 if (ret_val != 0)
406 return ret_val;
407 ret_val = nla_put_u32(skb, NLBL_MGMT_A_CV4DOI,
Paul Moore6a8b7f02013-08-02 14:45:08 -0400408 entry->def.cipso->doi);
Paul Moore63c41682008-10-10 10:16:32 -0400409 break;
Huw Daviesdc7de732016-06-27 15:02:49 -0400410 case NETLBL_NLTYPE_CALIPSO:
411 ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL,
412 entry->def.type);
413 if (ret_val != 0)
414 return ret_val;
415 ret_val = nla_put_u32(skb, NLBL_MGMT_A_CLPDOI,
416 entry->def.calipso->doi);
417 break;
Paul Moore63c41682008-10-10 10:16:32 -0400418 }
419
420 return ret_val;
421}
422
423/*
Paul Moored15c3452006-08-03 16:48:37 -0700424 * NetLabel Command Handlers
425 */
426
427/**
428 * netlbl_mgmt_add - Handle an ADD message
429 * @skb: the NETLINK buffer
430 * @info: the Generic NETLINK info block
431 *
432 * Description:
433 * Process a user generated ADD message and add the domains from the message
434 * to the hash table. See netlabel.h for a description of the message format.
435 * Returns zero on success, negative values on failure.
436 *
437 */
438static int netlbl_mgmt_add(struct sk_buff *skb, struct genl_info *info)
439{
Paul Moore95d4e6b2006-09-29 17:05:05 -0700440 struct netlbl_audit audit_info;
Paul Moored15c3452006-08-03 16:48:37 -0700441
Paul Moore63c41682008-10-10 10:16:32 -0400442 if ((!info->attrs[NLBL_MGMT_A_DOMAIN]) ||
443 (!info->attrs[NLBL_MGMT_A_PROTOCOL]) ||
444 (info->attrs[NLBL_MGMT_A_IPV4ADDR] &&
445 info->attrs[NLBL_MGMT_A_IPV6ADDR]) ||
446 (info->attrs[NLBL_MGMT_A_IPV4MASK] &&
447 info->attrs[NLBL_MGMT_A_IPV6MASK]) ||
448 ((info->attrs[NLBL_MGMT_A_IPV4ADDR] != NULL) ^
449 (info->attrs[NLBL_MGMT_A_IPV4MASK] != NULL)) ||
450 ((info->attrs[NLBL_MGMT_A_IPV6ADDR] != NULL) ^
451 (info->attrs[NLBL_MGMT_A_IPV6MASK] != NULL)))
452 return -EINVAL;
Paul Moorefd385852006-09-25 15:56:37 -0700453
Paul Moore95d4e6b2006-09-29 17:05:05 -0700454 netlbl_netlink_auditinfo(skb, &audit_info);
455
Paul Moore63c41682008-10-10 10:16:32 -0400456 return netlbl_mgmt_add_common(info, &audit_info);
Paul Moored15c3452006-08-03 16:48:37 -0700457}
458
459/**
460 * netlbl_mgmt_remove - Handle a REMOVE message
461 * @skb: the NETLINK buffer
462 * @info: the Generic NETLINK info block
463 *
464 * Description:
465 * Process a user generated REMOVE message and remove the specified domain
466 * mappings. Returns zero on success, negative values on failure.
467 *
468 */
469static int netlbl_mgmt_remove(struct sk_buff *skb, struct genl_info *info)
470{
Paul Moorefd385852006-09-25 15:56:37 -0700471 char *domain;
Paul Moore95d4e6b2006-09-29 17:05:05 -0700472 struct netlbl_audit audit_info;
Paul Moored15c3452006-08-03 16:48:37 -0700473
Paul Moorefd385852006-09-25 15:56:37 -0700474 if (!info->attrs[NLBL_MGMT_A_DOMAIN])
475 return -EINVAL;
476
Paul Moore95d4e6b2006-09-29 17:05:05 -0700477 netlbl_netlink_auditinfo(skb, &audit_info);
478
Paul Moorefd385852006-09-25 15:56:37 -0700479 domain = nla_data(info->attrs[NLBL_MGMT_A_DOMAIN]);
Huw Davies8f18e672016-06-27 15:02:46 -0400480 return netlbl_domhsh_remove(domain, AF_UNSPEC, &audit_info);
Paul Moorefd385852006-09-25 15:56:37 -0700481}
482
483/**
484 * netlbl_mgmt_listall_cb - netlbl_domhsh_walk() callback for LISTALL
485 * @entry: the domain mapping hash table entry
486 * @arg: the netlbl_domhsh_walk_arg structure
487 *
488 * Description:
489 * This function is designed to be used as a callback to the
490 * netlbl_domhsh_walk() function for use in generating a response for a LISTALL
491 * message. Returns the size of the message on success, negative values on
492 * failure.
493 *
494 */
495static int netlbl_mgmt_listall_cb(struct netlbl_dom_map *entry, void *arg)
496{
497 int ret_val = -ENOMEM;
498 struct netlbl_domhsh_walk_arg *cb_arg = arg;
499 void *data;
500
Eric W. Biederman15e47302012-09-07 20:12:54 +0000501 data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).portid,
Thomas Graf17c157c2006-11-14 19:46:02 -0800502 cb_arg->seq, &netlbl_mgmt_gnl_family,
503 NLM_F_MULTI, NLBL_MGMT_C_LISTALL);
Paul Moorefd385852006-09-25 15:56:37 -0700504 if (data == NULL)
505 goto listall_cb_failure;
506
Paul Moore63c41682008-10-10 10:16:32 -0400507 ret_val = netlbl_mgmt_listentry(cb_arg->skb, entry);
Paul Moored15c3452006-08-03 16:48:37 -0700508 if (ret_val != 0)
Paul Moorefd385852006-09-25 15:56:37 -0700509 goto listall_cb_failure;
Paul Moored15c3452006-08-03 16:48:37 -0700510
Paul Moorefd385852006-09-25 15:56:37 -0700511 cb_arg->seq++;
Johannes Berg053c0952015-01-16 22:09:00 +0100512 genlmsg_end(cb_arg->skb, data);
513 return 0;
Paul Moored15c3452006-08-03 16:48:37 -0700514
Paul Moorefd385852006-09-25 15:56:37 -0700515listall_cb_failure:
516 genlmsg_cancel(cb_arg->skb, data);
Paul Moored15c3452006-08-03 16:48:37 -0700517 return ret_val;
518}
519
520/**
Paul Moorefd385852006-09-25 15:56:37 -0700521 * netlbl_mgmt_listall - Handle a LISTALL message
Paul Moored15c3452006-08-03 16:48:37 -0700522 * @skb: the NETLINK buffer
Paul Moorefd385852006-09-25 15:56:37 -0700523 * @cb: the NETLINK callback
Paul Moored15c3452006-08-03 16:48:37 -0700524 *
525 * Description:
Paul Moorefd385852006-09-25 15:56:37 -0700526 * Process a user generated LISTALL message and dumps the domain hash table in
527 * a form suitable for use in a kernel generated LISTALL message. Returns zero
528 * on success, negative values on failure.
Paul Moored15c3452006-08-03 16:48:37 -0700529 *
530 */
Paul Moorefd385852006-09-25 15:56:37 -0700531static int netlbl_mgmt_listall(struct sk_buff *skb,
532 struct netlink_callback *cb)
Paul Moored15c3452006-08-03 16:48:37 -0700533{
Paul Moorefd385852006-09-25 15:56:37 -0700534 struct netlbl_domhsh_walk_arg cb_arg;
535 u32 skip_bkt = cb->args[0];
536 u32 skip_chain = cb->args[1];
Paul Moored15c3452006-08-03 16:48:37 -0700537
Paul Moorefd385852006-09-25 15:56:37 -0700538 cb_arg.nl_cb = cb;
539 cb_arg.skb = skb;
540 cb_arg.seq = cb->nlh->nlmsg_seq;
Paul Moored15c3452006-08-03 16:48:37 -0700541
Paul Moorefd385852006-09-25 15:56:37 -0700542 netlbl_domhsh_walk(&skip_bkt,
543 &skip_chain,
544 netlbl_mgmt_listall_cb,
545 &cb_arg);
Paul Moored15c3452006-08-03 16:48:37 -0700546
Paul Moorefd385852006-09-25 15:56:37 -0700547 cb->args[0] = skip_bkt;
548 cb->args[1] = skip_chain;
549 return skb->len;
Paul Moored15c3452006-08-03 16:48:37 -0700550}
551
552/**
553 * netlbl_mgmt_adddef - Handle an ADDDEF message
554 * @skb: the NETLINK buffer
555 * @info: the Generic NETLINK info block
556 *
557 * Description:
558 * Process a user generated ADDDEF message and respond accordingly. Returns
559 * zero on success, negative values on failure.
560 *
561 */
562static int netlbl_mgmt_adddef(struct sk_buff *skb, struct genl_info *info)
563{
Paul Moore95d4e6b2006-09-29 17:05:05 -0700564 struct netlbl_audit audit_info;
Paul Moored15c3452006-08-03 16:48:37 -0700565
Paul Moore63c41682008-10-10 10:16:32 -0400566 if ((!info->attrs[NLBL_MGMT_A_PROTOCOL]) ||
567 (info->attrs[NLBL_MGMT_A_IPV4ADDR] &&
568 info->attrs[NLBL_MGMT_A_IPV6ADDR]) ||
569 (info->attrs[NLBL_MGMT_A_IPV4MASK] &&
570 info->attrs[NLBL_MGMT_A_IPV6MASK]) ||
571 ((info->attrs[NLBL_MGMT_A_IPV4ADDR] != NULL) ^
572 (info->attrs[NLBL_MGMT_A_IPV4MASK] != NULL)) ||
573 ((info->attrs[NLBL_MGMT_A_IPV6ADDR] != NULL) ^
574 (info->attrs[NLBL_MGMT_A_IPV6MASK] != NULL)))
575 return -EINVAL;
Paul Moored15c3452006-08-03 16:48:37 -0700576
Paul Moore95d4e6b2006-09-29 17:05:05 -0700577 netlbl_netlink_auditinfo(skb, &audit_info);
578
Paul Moore63c41682008-10-10 10:16:32 -0400579 return netlbl_mgmt_add_common(info, &audit_info);
Paul Moored15c3452006-08-03 16:48:37 -0700580}
581
582/**
583 * netlbl_mgmt_removedef - Handle a REMOVEDEF message
584 * @skb: the NETLINK buffer
585 * @info: the Generic NETLINK info block
586 *
587 * Description:
588 * Process a user generated REMOVEDEF message and remove the default domain
589 * mapping. Returns zero on success, negative values on failure.
590 *
591 */
592static int netlbl_mgmt_removedef(struct sk_buff *skb, struct genl_info *info)
593{
Paul Moore95d4e6b2006-09-29 17:05:05 -0700594 struct netlbl_audit audit_info;
595
596 netlbl_netlink_auditinfo(skb, &audit_info);
597
Huw Davies8f18e672016-06-27 15:02:46 -0400598 return netlbl_domhsh_remove_default(AF_UNSPEC, &audit_info);
Paul Moored15c3452006-08-03 16:48:37 -0700599}
600
601/**
602 * netlbl_mgmt_listdef - Handle a LISTDEF message
603 * @skb: the NETLINK buffer
604 * @info: the Generic NETLINK info block
605 *
606 * Description:
607 * Process a user generated LISTDEF message and dumps the default domain
608 * mapping in a form suitable for use in a kernel generated LISTDEF message.
609 * Returns zero on success, negative values on failure.
610 *
611 */
612static int netlbl_mgmt_listdef(struct sk_buff *skb, struct genl_info *info)
613{
614 int ret_val = -ENOMEM;
Paul Moorefd385852006-09-25 15:56:37 -0700615 struct sk_buff *ans_skb = NULL;
616 void *data;
617 struct netlbl_dom_map *entry;
Huw Davies8f18e672016-06-27 15:02:46 -0400618 u16 family;
619
620 if (info->attrs[NLBL_MGMT_A_FAMILY])
621 family = nla_get_u16(info->attrs[NLBL_MGMT_A_FAMILY]);
622 else
623 family = AF_INET;
Paul Moored15c3452006-08-03 16:48:37 -0700624
Thomas Graf339bf982006-11-10 14:10:15 -0800625 ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
Paul Moored15c3452006-08-03 16:48:37 -0700626 if (ans_skb == NULL)
Paul Moorefd385852006-09-25 15:56:37 -0700627 return -ENOMEM;
Thomas Graf17c157c2006-11-14 19:46:02 -0800628 data = genlmsg_put_reply(ans_skb, info, &netlbl_mgmt_gnl_family,
629 0, NLBL_MGMT_C_LISTDEF);
Paul Moorefd385852006-09-25 15:56:37 -0700630 if (data == NULL)
Paul Moored15c3452006-08-03 16:48:37 -0700631 goto listdef_failure;
Paul Moored15c3452006-08-03 16:48:37 -0700632
Paul Moorefd385852006-09-25 15:56:37 -0700633 rcu_read_lock();
Huw Davies8f18e672016-06-27 15:02:46 -0400634 entry = netlbl_domhsh_getentry(NULL, family);
Paul Moorefd385852006-09-25 15:56:37 -0700635 if (entry == NULL) {
636 ret_val = -ENOENT;
637 goto listdef_failure_lock;
638 }
Paul Moore63c41682008-10-10 10:16:32 -0400639 ret_val = netlbl_mgmt_listentry(ans_skb, entry);
Paul Moorefd385852006-09-25 15:56:37 -0700640 rcu_read_unlock();
Paul Moore63c41682008-10-10 10:16:32 -0400641 if (ret_val != 0)
642 goto listdef_failure;
Paul Moorefd385852006-09-25 15:56:37 -0700643
644 genlmsg_end(ans_skb, data);
Denis V. Lunevfe785be2008-07-10 16:53:39 -0700645 return genlmsg_reply(ans_skb, info);
Paul Moored15c3452006-08-03 16:48:37 -0700646
Paul Moorefd385852006-09-25 15:56:37 -0700647listdef_failure_lock:
648 rcu_read_unlock();
Paul Moored15c3452006-08-03 16:48:37 -0700649listdef_failure:
Paul Moorefd385852006-09-25 15:56:37 -0700650 kfree_skb(ans_skb);
Paul Moored15c3452006-08-03 16:48:37 -0700651 return ret_val;
652}
653
654/**
Paul Moorefd385852006-09-25 15:56:37 -0700655 * netlbl_mgmt_protocols_cb - Write an individual PROTOCOL message response
656 * @skb: the skb to write to
Paul Moorefd385852006-09-25 15:56:37 -0700657 * @cb: the NETLINK callback
658 * @protocol: the NetLabel protocol to use in the message
Paul Moored15c3452006-08-03 16:48:37 -0700659 *
660 * Description:
Paul Moorefd385852006-09-25 15:56:37 -0700661 * This function is to be used in conjunction with netlbl_mgmt_protocols() to
662 * answer a application's PROTOCOLS message. Returns the size of the message
663 * on success, negative values on failure.
Paul Moored15c3452006-08-03 16:48:37 -0700664 *
665 */
Paul Moorefd385852006-09-25 15:56:37 -0700666static int netlbl_mgmt_protocols_cb(struct sk_buff *skb,
667 struct netlink_callback *cb,
668 u32 protocol)
Paul Moored15c3452006-08-03 16:48:37 -0700669{
670 int ret_val = -ENOMEM;
Paul Moorefd385852006-09-25 15:56:37 -0700671 void *data;
Paul Moored15c3452006-08-03 16:48:37 -0700672
Eric W. Biederman15e47302012-09-07 20:12:54 +0000673 data = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
Thomas Graf17c157c2006-11-14 19:46:02 -0800674 &netlbl_mgmt_gnl_family, NLM_F_MULTI,
675 NLBL_MGMT_C_PROTOCOLS);
Paul Moorefd385852006-09-25 15:56:37 -0700676 if (data == NULL)
677 goto protocols_cb_failure;
Paul Moored15c3452006-08-03 16:48:37 -0700678
Paul Moorefd385852006-09-25 15:56:37 -0700679 ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL, protocol);
Paul Moored15c3452006-08-03 16:48:37 -0700680 if (ret_val != 0)
Paul Moorefd385852006-09-25 15:56:37 -0700681 goto protocols_cb_failure;
Paul Moored15c3452006-08-03 16:48:37 -0700682
Johannes Berg053c0952015-01-16 22:09:00 +0100683 genlmsg_end(skb, data);
684 return 0;
Paul Moored15c3452006-08-03 16:48:37 -0700685
Paul Moorefd385852006-09-25 15:56:37 -0700686protocols_cb_failure:
687 genlmsg_cancel(skb, data);
Paul Moored15c3452006-08-03 16:48:37 -0700688 return ret_val;
689}
690
691/**
Paul Moorefd385852006-09-25 15:56:37 -0700692 * netlbl_mgmt_protocols - Handle a PROTOCOLS message
693 * @skb: the NETLINK buffer
694 * @cb: the NETLINK callback
695 *
696 * Description:
697 * Process a user generated PROTOCOLS message and respond accordingly.
698 *
699 */
700static int netlbl_mgmt_protocols(struct sk_buff *skb,
701 struct netlink_callback *cb)
702{
703 u32 protos_sent = cb->args[0];
704
705 if (protos_sent == 0) {
706 if (netlbl_mgmt_protocols_cb(skb,
707 cb,
708 NETLBL_NLTYPE_UNLABELED) < 0)
709 goto protocols_return;
710 protos_sent++;
711 }
712 if (protos_sent == 1) {
713 if (netlbl_mgmt_protocols_cb(skb,
714 cb,
715 NETLBL_NLTYPE_CIPSOV4) < 0)
716 goto protocols_return;
717 protos_sent++;
718 }
Huw Daviescb72d382016-06-27 15:02:46 -0400719#if IS_ENABLED(CONFIG_IPV6)
720 if (protos_sent == 2) {
721 if (netlbl_mgmt_protocols_cb(skb,
722 cb,
723 NETLBL_NLTYPE_CALIPSO) < 0)
724 goto protocols_return;
725 protos_sent++;
726 }
727#endif
Paul Moorefd385852006-09-25 15:56:37 -0700728
729protocols_return:
730 cb->args[0] = protos_sent;
731 return skb->len;
732}
733
734/**
Paul Moored15c3452006-08-03 16:48:37 -0700735 * netlbl_mgmt_version - Handle a VERSION message
736 * @skb: the NETLINK buffer
737 * @info: the Generic NETLINK info block
738 *
739 * Description:
740 * Process a user generated VERSION message and respond accordingly. Returns
741 * zero on success, negative values on failure.
742 *
743 */
744static int netlbl_mgmt_version(struct sk_buff *skb, struct genl_info *info)
745{
746 int ret_val = -ENOMEM;
747 struct sk_buff *ans_skb = NULL;
Paul Moorefd385852006-09-25 15:56:37 -0700748 void *data;
Paul Moored15c3452006-08-03 16:48:37 -0700749
Thomas Graf339bf982006-11-10 14:10:15 -0800750 ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
Paul Moored15c3452006-08-03 16:48:37 -0700751 if (ans_skb == NULL)
Paul Moorefd385852006-09-25 15:56:37 -0700752 return -ENOMEM;
Thomas Graf17c157c2006-11-14 19:46:02 -0800753 data = genlmsg_put_reply(ans_skb, info, &netlbl_mgmt_gnl_family,
754 0, NLBL_MGMT_C_VERSION);
Paul Moorefd385852006-09-25 15:56:37 -0700755 if (data == NULL)
Paul Moored15c3452006-08-03 16:48:37 -0700756 goto version_failure;
757
Paul Moorefd385852006-09-25 15:56:37 -0700758 ret_val = nla_put_u32(ans_skb,
759 NLBL_MGMT_A_VERSION,
760 NETLBL_PROTO_VERSION);
Paul Moored15c3452006-08-03 16:48:37 -0700761 if (ret_val != 0)
762 goto version_failure;
763
Paul Moorefd385852006-09-25 15:56:37 -0700764 genlmsg_end(ans_skb, data);
Denis V. Lunevfe785be2008-07-10 16:53:39 -0700765 return genlmsg_reply(ans_skb, info);
Paul Moored15c3452006-08-03 16:48:37 -0700766
767version_failure:
768 kfree_skb(ans_skb);
Paul Moored15c3452006-08-03 16:48:37 -0700769 return ret_val;
770}
771
772
773/*
774 * NetLabel Generic NETLINK Command Definitions
775 */
776
Johannes Berg4534de82013-11-14 17:14:46 +0100777static const struct genl_ops netlbl_mgmt_genl_ops[] = {
Pavel Emelyanov227c43c2008-02-17 22:33:16 -0800778 {
Paul Moored15c3452006-08-03 16:48:37 -0700779 .cmd = NLBL_MGMT_C_ADD,
Paul Moorefd385852006-09-25 15:56:37 -0700780 .flags = GENL_ADMIN_PERM,
781 .policy = netlbl_mgmt_genl_policy,
Paul Moored15c3452006-08-03 16:48:37 -0700782 .doit = netlbl_mgmt_add,
783 .dumpit = NULL,
Pavel Emelyanov227c43c2008-02-17 22:33:16 -0800784 },
785 {
Paul Moored15c3452006-08-03 16:48:37 -0700786 .cmd = NLBL_MGMT_C_REMOVE,
Paul Moorefd385852006-09-25 15:56:37 -0700787 .flags = GENL_ADMIN_PERM,
788 .policy = netlbl_mgmt_genl_policy,
Paul Moored15c3452006-08-03 16:48:37 -0700789 .doit = netlbl_mgmt_remove,
790 .dumpit = NULL,
Pavel Emelyanov227c43c2008-02-17 22:33:16 -0800791 },
792 {
Paul Moorefd385852006-09-25 15:56:37 -0700793 .cmd = NLBL_MGMT_C_LISTALL,
Paul Moored15c3452006-08-03 16:48:37 -0700794 .flags = 0,
Paul Moorefd385852006-09-25 15:56:37 -0700795 .policy = netlbl_mgmt_genl_policy,
796 .doit = NULL,
797 .dumpit = netlbl_mgmt_listall,
Pavel Emelyanov227c43c2008-02-17 22:33:16 -0800798 },
799 {
Paul Moored15c3452006-08-03 16:48:37 -0700800 .cmd = NLBL_MGMT_C_ADDDEF,
Paul Moorefd385852006-09-25 15:56:37 -0700801 .flags = GENL_ADMIN_PERM,
802 .policy = netlbl_mgmt_genl_policy,
Paul Moored15c3452006-08-03 16:48:37 -0700803 .doit = netlbl_mgmt_adddef,
804 .dumpit = NULL,
Pavel Emelyanov227c43c2008-02-17 22:33:16 -0800805 },
806 {
Paul Moored15c3452006-08-03 16:48:37 -0700807 .cmd = NLBL_MGMT_C_REMOVEDEF,
Paul Moorefd385852006-09-25 15:56:37 -0700808 .flags = GENL_ADMIN_PERM,
809 .policy = netlbl_mgmt_genl_policy,
Paul Moored15c3452006-08-03 16:48:37 -0700810 .doit = netlbl_mgmt_removedef,
811 .dumpit = NULL,
Pavel Emelyanov227c43c2008-02-17 22:33:16 -0800812 },
813 {
Paul Moored15c3452006-08-03 16:48:37 -0700814 .cmd = NLBL_MGMT_C_LISTDEF,
815 .flags = 0,
Paul Moorefd385852006-09-25 15:56:37 -0700816 .policy = netlbl_mgmt_genl_policy,
Paul Moored15c3452006-08-03 16:48:37 -0700817 .doit = netlbl_mgmt_listdef,
818 .dumpit = NULL,
Pavel Emelyanov227c43c2008-02-17 22:33:16 -0800819 },
820 {
Paul Moorefd385852006-09-25 15:56:37 -0700821 .cmd = NLBL_MGMT_C_PROTOCOLS,
Paul Moored15c3452006-08-03 16:48:37 -0700822 .flags = 0,
Paul Moorefd385852006-09-25 15:56:37 -0700823 .policy = netlbl_mgmt_genl_policy,
824 .doit = NULL,
825 .dumpit = netlbl_mgmt_protocols,
Pavel Emelyanov227c43c2008-02-17 22:33:16 -0800826 },
827 {
Paul Moored15c3452006-08-03 16:48:37 -0700828 .cmd = NLBL_MGMT_C_VERSION,
829 .flags = 0,
Paul Moorefd385852006-09-25 15:56:37 -0700830 .policy = netlbl_mgmt_genl_policy,
Paul Moored15c3452006-08-03 16:48:37 -0700831 .doit = netlbl_mgmt_version,
832 .dumpit = NULL,
Pavel Emelyanov227c43c2008-02-17 22:33:16 -0800833 },
Paul Moored15c3452006-08-03 16:48:37 -0700834};
835
836/*
837 * NetLabel Generic NETLINK Protocol Functions
838 */
839
840/**
841 * netlbl_mgmt_genl_init - Register the NetLabel management component
842 *
843 * Description:
844 * Register the NetLabel management component with the Generic NETLINK
845 * mechanism. Returns zero on success, negative values on failure.
846 *
847 */
Pavel Emelyanov05705e42008-02-17 22:33:57 -0800848int __init netlbl_mgmt_genl_init(void)
Paul Moored15c3452006-08-03 16:48:37 -0700849{
Michał Mirosław7ae740d2009-05-21 10:34:05 +0000850 return genl_register_family_with_ops(&netlbl_mgmt_gnl_family,
Johannes Bergc53ed742013-11-19 15:19:31 +0100851 netlbl_mgmt_genl_ops);
Paul Moored15c3452006-08-03 16:48:37 -0700852}