1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * NetLabel Management Support
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.
9 * Author: Paul Moore <paul@paul-moore.com>
13 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008
16 #include <linux/types.h>
17 #include <linux/socket.h>
18 #include <linux/string.h>
19 #include <linux/skbuff.h>
21 #include <linux/in6.h>
22 #include <linux/slab.h>
24 #include <net/netlink.h>
25 #include <net/genetlink.h>
28 #include <net/netlabel.h>
29 #include <net/cipso_ipv4.h>
30 #include <net/calipso.h>
31 #include <linux/atomic.h>
33 #include "netlabel_calipso.h"
34 #include "netlabel_domainhash.h"
35 #include "netlabel_user.h"
36 #include "netlabel_mgmt.h"
38 /* NetLabel configured protocol counter */
39 atomic_t netlabel_mgmt_protocount
= ATOMIC_INIT(0);
41 /* Argument struct for netlbl_domhsh_walk() */
42 struct netlbl_domhsh_walk_arg
{
43 struct netlink_callback
*nl_cb
;
48 /* NetLabel Generic NETLINK CIPSOv4 family */
49 static struct genl_family netlbl_mgmt_gnl_family
;
51 /* NetLabel Netlink attribute policy */
52 static const struct nla_policy netlbl_mgmt_genl_policy
[NLBL_MGMT_A_MAX
+ 1] = {
53 [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
},
57 [NLBL_MGMT_A_FAMILY
] = { .type
= NLA_U16
},
58 [NLBL_MGMT_A_CLPDOI
] = { .type
= NLA_U32
},
66 * netlbl_mgmt_add_common - Handle an ADD message
67 * @info: the Generic NETLINK info block
68 * @audit_info: NetLabel audit information
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.
76 static int netlbl_mgmt_add_common(struct genl_info
*info
,
77 struct netlbl_audit
*audit_info
)
80 int ret_val
= -EINVAL
;
81 struct netlbl_domaddr_map
*addrmap
= NULL
;
82 struct cipso_v4_doi
*cipsov4
= NULL
;
83 #if IS_ENABLED(CONFIG_IPV6)
84 struct calipso_doi
*calipso
= NULL
;
87 struct netlbl_dom_map
*entry
= kzalloc(sizeof(*entry
), GFP_KERNEL
);
91 entry
->def
.type
= nla_get_u32(info
->attrs
[NLBL_MGMT_A_PROTOCOL
]);
92 if (info
->attrs
[NLBL_MGMT_A_DOMAIN
]) {
93 size_t tmp_size
= nla_len(info
->attrs
[NLBL_MGMT_A_DOMAIN
]);
94 entry
->domain
= kmalloc(tmp_size
, GFP_KERNEL
);
95 if (entry
->domain
== NULL
) {
99 nla_strscpy(entry
->domain
,
100 info
->attrs
[NLBL_MGMT_A_DOMAIN
], tmp_size
);
103 /* NOTE: internally we allow/use a entry->def.type value of
104 * NETLBL_NLTYPE_ADDRSELECT but we don't currently allow users
105 * to pass that as a protocol value because we need to know the
108 switch (entry
->def
.type
) {
109 case NETLBL_NLTYPE_UNLABELED
:
110 if (info
->attrs
[NLBL_MGMT_A_FAMILY
])
112 nla_get_u16(info
->attrs
[NLBL_MGMT_A_FAMILY
]);
114 entry
->family
= AF_UNSPEC
;
116 case NETLBL_NLTYPE_CIPSOV4
:
117 if (!info
->attrs
[NLBL_MGMT_A_CV4DOI
])
118 goto add_free_domain
;
120 tmp_val
= nla_get_u32(info
->attrs
[NLBL_MGMT_A_CV4DOI
]);
121 cipsov4
= cipso_v4_doi_getdef(tmp_val
);
123 goto add_free_domain
;
124 entry
->family
= AF_INET
;
125 entry
->def
.cipso
= cipsov4
;
127 #if IS_ENABLED(CONFIG_IPV6)
128 case NETLBL_NLTYPE_CALIPSO
:
129 if (!info
->attrs
[NLBL_MGMT_A_CLPDOI
])
130 goto add_free_domain
;
132 tmp_val
= nla_get_u32(info
->attrs
[NLBL_MGMT_A_CLPDOI
]);
133 calipso
= calipso_doi_getdef(tmp_val
);
135 goto add_free_domain
;
136 entry
->family
= AF_INET6
;
137 entry
->def
.calipso
= calipso
;
141 goto add_free_domain
;
144 if ((entry
->family
== AF_INET
&& info
->attrs
[NLBL_MGMT_A_IPV6ADDR
]) ||
145 (entry
->family
== AF_INET6
&& info
->attrs
[NLBL_MGMT_A_IPV4ADDR
]))
146 goto add_doi_put_def
;
148 if (info
->attrs
[NLBL_MGMT_A_IPV4ADDR
]) {
149 struct in_addr
*addr
;
150 struct in_addr
*mask
;
151 struct netlbl_domaddr4_map
*map
;
153 addrmap
= kzalloc(sizeof(*addrmap
), GFP_KERNEL
);
154 if (addrmap
== NULL
) {
156 goto add_doi_put_def
;
158 INIT_LIST_HEAD(&addrmap
->list4
);
159 INIT_LIST_HEAD(&addrmap
->list6
);
161 if (nla_len(info
->attrs
[NLBL_MGMT_A_IPV4ADDR
]) !=
162 sizeof(struct in_addr
)) {
164 goto add_free_addrmap
;
166 if (nla_len(info
->attrs
[NLBL_MGMT_A_IPV4MASK
]) !=
167 sizeof(struct in_addr
)) {
169 goto add_free_addrmap
;
171 addr
= nla_data(info
->attrs
[NLBL_MGMT_A_IPV4ADDR
]);
172 mask
= nla_data(info
->attrs
[NLBL_MGMT_A_IPV4MASK
]);
174 map
= kzalloc(sizeof(*map
), GFP_KERNEL
);
177 goto add_free_addrmap
;
180 map
->list
.addr
= addr
->s_addr
& mask
->s_addr
;
181 map
->list
.mask
= mask
->s_addr
;
183 map
->def
.type
= entry
->def
.type
;
185 map
->def
.cipso
= cipsov4
;
187 ret_val
= netlbl_af4list_add(&map
->list
, &addrmap
->list4
);
191 entry
->family
= AF_INET
;
192 entry
->def
.type
= NETLBL_NLTYPE_ADDRSELECT
;
193 entry
->def
.addrsel
= addrmap
;
194 #if IS_ENABLED(CONFIG_IPV6)
195 } else if (info
->attrs
[NLBL_MGMT_A_IPV6ADDR
]) {
196 struct in6_addr
*addr
;
197 struct in6_addr
*mask
;
198 struct netlbl_domaddr6_map
*map
;
200 addrmap
= kzalloc(sizeof(*addrmap
), GFP_KERNEL
);
201 if (addrmap
== NULL
) {
203 goto add_doi_put_def
;
205 INIT_LIST_HEAD(&addrmap
->list4
);
206 INIT_LIST_HEAD(&addrmap
->list6
);
208 if (nla_len(info
->attrs
[NLBL_MGMT_A_IPV6ADDR
]) !=
209 sizeof(struct in6_addr
)) {
211 goto add_free_addrmap
;
213 if (nla_len(info
->attrs
[NLBL_MGMT_A_IPV6MASK
]) !=
214 sizeof(struct in6_addr
)) {
216 goto add_free_addrmap
;
218 addr
= nla_data(info
->attrs
[NLBL_MGMT_A_IPV6ADDR
]);
219 mask
= nla_data(info
->attrs
[NLBL_MGMT_A_IPV6MASK
]);
221 map
= kzalloc(sizeof(*map
), GFP_KERNEL
);
224 goto add_free_addrmap
;
227 map
->list
.addr
= *addr
;
228 map
->list
.addr
.s6_addr32
[0] &= mask
->s6_addr32
[0];
229 map
->list
.addr
.s6_addr32
[1] &= mask
->s6_addr32
[1];
230 map
->list
.addr
.s6_addr32
[2] &= mask
->s6_addr32
[2];
231 map
->list
.addr
.s6_addr32
[3] &= mask
->s6_addr32
[3];
232 map
->list
.mask
= *mask
;
234 map
->def
.type
= entry
->def
.type
;
236 map
->def
.calipso
= calipso
;
238 ret_val
= netlbl_af6list_add(&map
->list
, &addrmap
->list6
);
242 entry
->family
= AF_INET6
;
243 entry
->def
.type
= NETLBL_NLTYPE_ADDRSELECT
;
244 entry
->def
.addrsel
= addrmap
;
248 ret_val
= netlbl_domhsh_add(entry
, audit_info
);
259 cipso_v4_doi_putdef(cipsov4
);
260 #if IS_ENABLED(CONFIG_IPV6)
261 calipso_doi_putdef(calipso
);
264 kfree(entry
->domain
);
271 * netlbl_mgmt_listentry - List a NetLabel/LSM domain map entry
272 * @skb: the NETLINK buffer
273 * @entry: the map entry
276 * This function is a helper function used by the LISTALL and LISTDEF command
277 * handlers. The caller is responsible for ensuring that the RCU read lock
278 * is held. Returns zero on success, negative values on failure.
281 static int netlbl_mgmt_listentry(struct sk_buff
*skb
,
282 struct netlbl_dom_map
*entry
)
285 struct nlattr
*nla_a
;
286 struct nlattr
*nla_b
;
287 struct netlbl_af4list
*iter4
;
288 #if IS_ENABLED(CONFIG_IPV6)
289 struct netlbl_af6list
*iter6
;
292 if (entry
->domain
!= NULL
) {
293 ret_val
= nla_put_string(skb
,
294 NLBL_MGMT_A_DOMAIN
, entry
->domain
);
299 ret_val
= nla_put_u16(skb
, NLBL_MGMT_A_FAMILY
, entry
->family
);
303 switch (entry
->def
.type
) {
304 case NETLBL_NLTYPE_ADDRSELECT
:
305 nla_a
= nla_nest_start_noflag(skb
, NLBL_MGMT_A_SELECTORLIST
);
309 netlbl_af4list_foreach_rcu(iter4
, &entry
->def
.addrsel
->list4
) {
310 struct netlbl_domaddr4_map
*map4
;
311 struct in_addr addr_struct
;
313 nla_b
= nla_nest_start_noflag(skb
,
314 NLBL_MGMT_A_ADDRSELECTOR
);
318 addr_struct
.s_addr
= iter4
->addr
;
319 ret_val
= nla_put_in_addr(skb
, NLBL_MGMT_A_IPV4ADDR
,
323 addr_struct
.s_addr
= iter4
->mask
;
324 ret_val
= nla_put_in_addr(skb
, NLBL_MGMT_A_IPV4MASK
,
328 map4
= netlbl_domhsh_addr4_entry(iter4
);
329 ret_val
= nla_put_u32(skb
, NLBL_MGMT_A_PROTOCOL
,
333 switch (map4
->def
.type
) {
334 case NETLBL_NLTYPE_CIPSOV4
:
335 ret_val
= nla_put_u32(skb
, NLBL_MGMT_A_CV4DOI
,
336 map4
->def
.cipso
->doi
);
342 nla_nest_end(skb
, nla_b
);
344 #if IS_ENABLED(CONFIG_IPV6)
345 netlbl_af6list_foreach_rcu(iter6
, &entry
->def
.addrsel
->list6
) {
346 struct netlbl_domaddr6_map
*map6
;
348 nla_b
= nla_nest_start_noflag(skb
,
349 NLBL_MGMT_A_ADDRSELECTOR
);
353 ret_val
= nla_put_in6_addr(skb
, NLBL_MGMT_A_IPV6ADDR
,
357 ret_val
= nla_put_in6_addr(skb
, NLBL_MGMT_A_IPV6MASK
,
361 map6
= netlbl_domhsh_addr6_entry(iter6
);
362 ret_val
= nla_put_u32(skb
, NLBL_MGMT_A_PROTOCOL
,
367 switch (map6
->def
.type
) {
368 case NETLBL_NLTYPE_CALIPSO
:
369 ret_val
= nla_put_u32(skb
, NLBL_MGMT_A_CLPDOI
,
370 map6
->def
.calipso
->doi
);
376 nla_nest_end(skb
, nla_b
);
380 nla_nest_end(skb
, nla_a
);
382 case NETLBL_NLTYPE_UNLABELED
:
383 ret_val
= nla_put_u32(skb
, NLBL_MGMT_A_PROTOCOL
,
386 case NETLBL_NLTYPE_CIPSOV4
:
387 ret_val
= nla_put_u32(skb
, NLBL_MGMT_A_PROTOCOL
,
391 ret_val
= nla_put_u32(skb
, NLBL_MGMT_A_CV4DOI
,
392 entry
->def
.cipso
->doi
);
394 case NETLBL_NLTYPE_CALIPSO
:
395 ret_val
= nla_put_u32(skb
, NLBL_MGMT_A_PROTOCOL
,
399 ret_val
= nla_put_u32(skb
, NLBL_MGMT_A_CLPDOI
,
400 entry
->def
.calipso
->doi
);
408 * NetLabel Command Handlers
412 * netlbl_mgmt_add - Handle an ADD message
413 * @skb: the NETLINK buffer
414 * @info: the Generic NETLINK info block
417 * Process a user generated ADD message and add the domains from the message
418 * to the hash table. See netlabel.h for a description of the message format.
419 * Returns zero on success, negative values on failure.
422 static int netlbl_mgmt_add(struct sk_buff
*skb
, struct genl_info
*info
)
424 struct netlbl_audit audit_info
;
426 if ((!info
->attrs
[NLBL_MGMT_A_DOMAIN
]) ||
427 (!info
->attrs
[NLBL_MGMT_A_PROTOCOL
]) ||
428 (info
->attrs
[NLBL_MGMT_A_IPV4ADDR
] &&
429 info
->attrs
[NLBL_MGMT_A_IPV6ADDR
]) ||
430 (info
->attrs
[NLBL_MGMT_A_IPV4MASK
] &&
431 info
->attrs
[NLBL_MGMT_A_IPV6MASK
]) ||
432 ((info
->attrs
[NLBL_MGMT_A_IPV4ADDR
] != NULL
) ^
433 (info
->attrs
[NLBL_MGMT_A_IPV4MASK
] != NULL
)) ||
434 ((info
->attrs
[NLBL_MGMT_A_IPV6ADDR
] != NULL
) ^
435 (info
->attrs
[NLBL_MGMT_A_IPV6MASK
] != NULL
)))
438 netlbl_netlink_auditinfo(&audit_info
);
440 return netlbl_mgmt_add_common(info
, &audit_info
);
444 * netlbl_mgmt_remove - Handle a REMOVE message
445 * @skb: the NETLINK buffer
446 * @info: the Generic NETLINK info block
449 * Process a user generated REMOVE message and remove the specified domain
450 * mappings. Returns zero on success, negative values on failure.
453 static int netlbl_mgmt_remove(struct sk_buff
*skb
, struct genl_info
*info
)
456 struct netlbl_audit audit_info
;
458 if (!info
->attrs
[NLBL_MGMT_A_DOMAIN
])
461 netlbl_netlink_auditinfo(&audit_info
);
463 domain
= nla_data(info
->attrs
[NLBL_MGMT_A_DOMAIN
]);
464 return netlbl_domhsh_remove(domain
, AF_UNSPEC
, &audit_info
);
468 * netlbl_mgmt_listall_cb - netlbl_domhsh_walk() callback for LISTALL
469 * @entry: the domain mapping hash table entry
470 * @arg: the netlbl_domhsh_walk_arg structure
473 * This function is designed to be used as a callback to the
474 * netlbl_domhsh_walk() function for use in generating a response for a LISTALL
475 * message. Returns the size of the message on success, negative values on
479 static int netlbl_mgmt_listall_cb(struct netlbl_dom_map
*entry
, void *arg
)
481 int ret_val
= -ENOMEM
;
482 struct netlbl_domhsh_walk_arg
*cb_arg
= arg
;
485 data
= genlmsg_put(cb_arg
->skb
, NETLINK_CB(cb_arg
->nl_cb
->skb
).portid
,
486 cb_arg
->seq
, &netlbl_mgmt_gnl_family
,
487 NLM_F_MULTI
, NLBL_MGMT_C_LISTALL
);
489 goto listall_cb_failure
;
491 ret_val
= netlbl_mgmt_listentry(cb_arg
->skb
, entry
);
493 goto listall_cb_failure
;
496 genlmsg_end(cb_arg
->skb
, data
);
500 genlmsg_cancel(cb_arg
->skb
, data
);
505 * netlbl_mgmt_listall - Handle a LISTALL message
506 * @skb: the NETLINK buffer
507 * @cb: the NETLINK callback
510 * Process a user generated LISTALL message and dumps the domain hash table in
511 * a form suitable for use in a kernel generated LISTALL message. Returns zero
512 * on success, negative values on failure.
515 static int netlbl_mgmt_listall(struct sk_buff
*skb
,
516 struct netlink_callback
*cb
)
518 struct netlbl_domhsh_walk_arg cb_arg
;
519 u32 skip_bkt
= cb
->args
[0];
520 u32 skip_chain
= cb
->args
[1];
524 cb_arg
.seq
= cb
->nlh
->nlmsg_seq
;
526 netlbl_domhsh_walk(&skip_bkt
,
528 netlbl_mgmt_listall_cb
,
531 cb
->args
[0] = skip_bkt
;
532 cb
->args
[1] = skip_chain
;
537 * netlbl_mgmt_adddef - Handle an ADDDEF message
538 * @skb: the NETLINK buffer
539 * @info: the Generic NETLINK info block
542 * Process a user generated ADDDEF message and respond accordingly. Returns
543 * zero on success, negative values on failure.
546 static int netlbl_mgmt_adddef(struct sk_buff
*skb
, struct genl_info
*info
)
548 struct netlbl_audit audit_info
;
550 if ((!info
->attrs
[NLBL_MGMT_A_PROTOCOL
]) ||
551 (info
->attrs
[NLBL_MGMT_A_IPV4ADDR
] &&
552 info
->attrs
[NLBL_MGMT_A_IPV6ADDR
]) ||
553 (info
->attrs
[NLBL_MGMT_A_IPV4MASK
] &&
554 info
->attrs
[NLBL_MGMT_A_IPV6MASK
]) ||
555 ((info
->attrs
[NLBL_MGMT_A_IPV4ADDR
] != NULL
) ^
556 (info
->attrs
[NLBL_MGMT_A_IPV4MASK
] != NULL
)) ||
557 ((info
->attrs
[NLBL_MGMT_A_IPV6ADDR
] != NULL
) ^
558 (info
->attrs
[NLBL_MGMT_A_IPV6MASK
] != NULL
)))
561 netlbl_netlink_auditinfo(&audit_info
);
563 return netlbl_mgmt_add_common(info
, &audit_info
);
567 * netlbl_mgmt_removedef - Handle a REMOVEDEF message
568 * @skb: the NETLINK buffer
569 * @info: the Generic NETLINK info block
572 * Process a user generated REMOVEDEF message and remove the default domain
573 * mapping. Returns zero on success, negative values on failure.
576 static int netlbl_mgmt_removedef(struct sk_buff
*skb
, struct genl_info
*info
)
578 struct netlbl_audit audit_info
;
580 netlbl_netlink_auditinfo(&audit_info
);
582 return netlbl_domhsh_remove_default(AF_UNSPEC
, &audit_info
);
586 * netlbl_mgmt_listdef - Handle a LISTDEF message
587 * @skb: the NETLINK buffer
588 * @info: the Generic NETLINK info block
591 * Process a user generated LISTDEF message and dumps the default domain
592 * mapping in a form suitable for use in a kernel generated LISTDEF message.
593 * Returns zero on success, negative values on failure.
596 static int netlbl_mgmt_listdef(struct sk_buff
*skb
, struct genl_info
*info
)
598 int ret_val
= -ENOMEM
;
599 struct sk_buff
*ans_skb
= NULL
;
601 struct netlbl_dom_map
*entry
;
604 if (info
->attrs
[NLBL_MGMT_A_FAMILY
])
605 family
= nla_get_u16(info
->attrs
[NLBL_MGMT_A_FAMILY
]);
609 ans_skb
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
612 data
= genlmsg_put_reply(ans_skb
, info
, &netlbl_mgmt_gnl_family
,
613 0, NLBL_MGMT_C_LISTDEF
);
615 goto listdef_failure
;
618 entry
= netlbl_domhsh_getentry(NULL
, family
);
621 goto listdef_failure_lock
;
623 ret_val
= netlbl_mgmt_listentry(ans_skb
, entry
);
626 goto listdef_failure
;
628 genlmsg_end(ans_skb
, data
);
629 return genlmsg_reply(ans_skb
, info
);
631 listdef_failure_lock
:
639 * netlbl_mgmt_protocols_cb - Write an individual PROTOCOL message response
640 * @skb: the skb to write to
641 * @cb: the NETLINK callback
642 * @protocol: the NetLabel protocol to use in the message
645 * This function is to be used in conjunction with netlbl_mgmt_protocols() to
646 * answer a application's PROTOCOLS message. Returns the size of the message
647 * on success, negative values on failure.
650 static int netlbl_mgmt_protocols_cb(struct sk_buff
*skb
,
651 struct netlink_callback
*cb
,
654 int ret_val
= -ENOMEM
;
657 data
= genlmsg_put(skb
, NETLINK_CB(cb
->skb
).portid
, cb
->nlh
->nlmsg_seq
,
658 &netlbl_mgmt_gnl_family
, NLM_F_MULTI
,
659 NLBL_MGMT_C_PROTOCOLS
);
661 goto protocols_cb_failure
;
663 ret_val
= nla_put_u32(skb
, NLBL_MGMT_A_PROTOCOL
, protocol
);
665 goto protocols_cb_failure
;
667 genlmsg_end(skb
, data
);
670 protocols_cb_failure
:
671 genlmsg_cancel(skb
, data
);
676 * netlbl_mgmt_protocols - Handle a PROTOCOLS message
677 * @skb: the NETLINK buffer
678 * @cb: the NETLINK callback
681 * Process a user generated PROTOCOLS message and respond accordingly.
684 static int netlbl_mgmt_protocols(struct sk_buff
*skb
,
685 struct netlink_callback
*cb
)
687 u32 protos_sent
= cb
->args
[0];
689 if (protos_sent
== 0) {
690 if (netlbl_mgmt_protocols_cb(skb
,
692 NETLBL_NLTYPE_UNLABELED
) < 0)
693 goto protocols_return
;
696 if (protos_sent
== 1) {
697 if (netlbl_mgmt_protocols_cb(skb
,
699 NETLBL_NLTYPE_CIPSOV4
) < 0)
700 goto protocols_return
;
703 #if IS_ENABLED(CONFIG_IPV6)
704 if (protos_sent
== 2) {
705 if (netlbl_mgmt_protocols_cb(skb
,
707 NETLBL_NLTYPE_CALIPSO
) < 0)
708 goto protocols_return
;
714 cb
->args
[0] = protos_sent
;
719 * netlbl_mgmt_version - Handle a VERSION message
720 * @skb: the NETLINK buffer
721 * @info: the Generic NETLINK info block
724 * Process a user generated VERSION message and respond accordingly. Returns
725 * zero on success, negative values on failure.
728 static int netlbl_mgmt_version(struct sk_buff
*skb
, struct genl_info
*info
)
730 int ret_val
= -ENOMEM
;
731 struct sk_buff
*ans_skb
= NULL
;
734 ans_skb
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
737 data
= genlmsg_put_reply(ans_skb
, info
, &netlbl_mgmt_gnl_family
,
738 0, NLBL_MGMT_C_VERSION
);
740 goto version_failure
;
742 ret_val
= nla_put_u32(ans_skb
,
744 NETLBL_PROTO_VERSION
);
746 goto version_failure
;
748 genlmsg_end(ans_skb
, data
);
749 return genlmsg_reply(ans_skb
, info
);
758 * NetLabel Generic NETLINK Command Definitions
761 static const struct genl_small_ops netlbl_mgmt_genl_ops
[] = {
763 .cmd
= NLBL_MGMT_C_ADD
,
764 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
765 .flags
= GENL_ADMIN_PERM
,
766 .doit
= netlbl_mgmt_add
,
770 .cmd
= NLBL_MGMT_C_REMOVE
,
771 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
772 .flags
= GENL_ADMIN_PERM
,
773 .doit
= netlbl_mgmt_remove
,
777 .cmd
= NLBL_MGMT_C_LISTALL
,
778 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
781 .dumpit
= netlbl_mgmt_listall
,
784 .cmd
= NLBL_MGMT_C_ADDDEF
,
785 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
786 .flags
= GENL_ADMIN_PERM
,
787 .doit
= netlbl_mgmt_adddef
,
791 .cmd
= NLBL_MGMT_C_REMOVEDEF
,
792 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
793 .flags
= GENL_ADMIN_PERM
,
794 .doit
= netlbl_mgmt_removedef
,
798 .cmd
= NLBL_MGMT_C_LISTDEF
,
799 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
801 .doit
= netlbl_mgmt_listdef
,
805 .cmd
= NLBL_MGMT_C_PROTOCOLS
,
806 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
809 .dumpit
= netlbl_mgmt_protocols
,
812 .cmd
= NLBL_MGMT_C_VERSION
,
813 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
815 .doit
= netlbl_mgmt_version
,
820 static struct genl_family netlbl_mgmt_gnl_family __ro_after_init
= {
822 .name
= NETLBL_NLTYPE_MGMT_NAME
,
823 .version
= NETLBL_PROTO_VERSION
,
824 .maxattr
= NLBL_MGMT_A_MAX
,
825 .policy
= netlbl_mgmt_genl_policy
,
826 .module
= THIS_MODULE
,
827 .small_ops
= netlbl_mgmt_genl_ops
,
828 .n_small_ops
= ARRAY_SIZE(netlbl_mgmt_genl_ops
),
829 .resv_start_op
= NLBL_MGMT_C_VERSION
+ 1,
833 * NetLabel Generic NETLINK Protocol Functions
837 * netlbl_mgmt_genl_init - Register the NetLabel management component
840 * Register the NetLabel management component with the Generic NETLINK
841 * mechanism. Returns zero on success, negative values on failure.
844 int __init
netlbl_mgmt_genl_init(void)
846 return genl_register_family(&netlbl_mgmt_gnl_family
);