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 - 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
)
79 int ret_val
= -EINVAL
;
80 struct netlbl_domaddr_map
*addrmap
= NULL
;
81 struct cipso_v4_doi
*cipsov4
= NULL
;
82 #if IS_ENABLED(CONFIG_IPV6)
83 struct calipso_doi
*calipso
= NULL
;
86 struct netlbl_dom_map
*entry
= kzalloc(sizeof(*entry
), GFP_KERNEL
);
90 entry
->def
.type
= nla_get_u32(info
->attrs
[NLBL_MGMT_A_PROTOCOL
]);
91 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
) {
98 nla_strscpy(entry
->domain
,
99 info
->attrs
[NLBL_MGMT_A_DOMAIN
], tmp_size
);
102 /* NOTE: internally we allow/use a entry->def.type value of
103 * NETLBL_NLTYPE_ADDRSELECT but we don't currently allow users
104 * to pass that as a protocol value because we need to know the
107 switch (entry
->def
.type
) {
108 case NETLBL_NLTYPE_UNLABELED
:
109 if (info
->attrs
[NLBL_MGMT_A_FAMILY
])
111 nla_get_u16(info
->attrs
[NLBL_MGMT_A_FAMILY
]);
113 entry
->family
= AF_UNSPEC
;
115 case NETLBL_NLTYPE_CIPSOV4
:
116 if (!info
->attrs
[NLBL_MGMT_A_CV4DOI
])
117 goto add_free_domain
;
119 tmp_val
= nla_get_u32(info
->attrs
[NLBL_MGMT_A_CV4DOI
]);
120 cipsov4
= cipso_v4_doi_getdef(tmp_val
);
122 goto add_free_domain
;
123 entry
->family
= AF_INET
;
124 entry
->def
.cipso
= cipsov4
;
126 #if IS_ENABLED(CONFIG_IPV6)
127 case NETLBL_NLTYPE_CALIPSO
:
128 if (!info
->attrs
[NLBL_MGMT_A_CLPDOI
])
129 goto add_free_domain
;
131 tmp_val
= nla_get_u32(info
->attrs
[NLBL_MGMT_A_CLPDOI
]);
132 calipso
= calipso_doi_getdef(tmp_val
);
134 goto add_free_domain
;
135 entry
->family
= AF_INET6
;
136 entry
->def
.calipso
= calipso
;
140 goto add_free_domain
;
143 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
;
147 if (info
->attrs
[NLBL_MGMT_A_IPV4ADDR
]) {
148 struct in_addr
*addr
;
149 struct in_addr
*mask
;
150 struct netlbl_domaddr4_map
*map
;
152 addrmap
= kzalloc(sizeof(*addrmap
), GFP_KERNEL
);
153 if (addrmap
== NULL
) {
155 goto add_doi_put_def
;
157 INIT_LIST_HEAD(&addrmap
->list4
);
158 INIT_LIST_HEAD(&addrmap
->list6
);
160 if (nla_len(info
->attrs
[NLBL_MGMT_A_IPV4ADDR
]) !=
161 sizeof(struct in_addr
)) {
163 goto add_free_addrmap
;
165 if (nla_len(info
->attrs
[NLBL_MGMT_A_IPV4MASK
]) !=
166 sizeof(struct in_addr
)) {
168 goto add_free_addrmap
;
170 addr
= nla_data(info
->attrs
[NLBL_MGMT_A_IPV4ADDR
]);
171 mask
= nla_data(info
->attrs
[NLBL_MGMT_A_IPV4MASK
]);
173 map
= kzalloc(sizeof(*map
), GFP_KERNEL
);
176 goto add_free_addrmap
;
178 map
->list
.addr
= addr
->s_addr
& mask
->s_addr
;
179 map
->list
.mask
= mask
->s_addr
;
181 map
->def
.type
= entry
->def
.type
;
183 map
->def
.cipso
= cipsov4
;
185 ret_val
= netlbl_af4list_add(&map
->list
, &addrmap
->list4
);
188 goto add_free_addrmap
;
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
;
226 map
->list
.addr
= *addr
;
227 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];
231 map
->list
.mask
= *mask
;
233 map
->def
.type
= entry
->def
.type
;
235 map
->def
.calipso
= calipso
;
237 ret_val
= netlbl_af6list_add(&map
->list
, &addrmap
->list6
);
240 goto add_free_addrmap
;
243 entry
->family
= AF_INET6
;
244 entry
->def
.type
= NETLBL_NLTYPE_ADDRSELECT
;
245 entry
->def
.addrsel
= addrmap
;
249 ret_val
= netlbl_domhsh_add(entry
, audit_info
);
251 goto add_free_addrmap
;
258 cipso_v4_doi_putdef(cipsov4
);
259 #if IS_ENABLED(CONFIG_IPV6)
260 calipso_doi_putdef(calipso
);
263 kfree(entry
->domain
);
270 * netlbl_mgmt_listentry - List a NetLabel/LSM domain map entry
271 * @skb: the NETLINK buffer
272 * @entry: the map entry
275 * This function is a helper function used by the LISTALL and LISTDEF command
276 * handlers. The caller is responsible for ensuring that the RCU read lock
277 * is held. Returns zero on success, negative values on failure.
280 static int netlbl_mgmt_listentry(struct sk_buff
*skb
,
281 struct netlbl_dom_map
*entry
)
284 struct nlattr
*nla_a
;
285 struct nlattr
*nla_b
;
286 struct netlbl_af4list
*iter4
;
287 #if IS_ENABLED(CONFIG_IPV6)
288 struct netlbl_af6list
*iter6
;
291 if (entry
->domain
!= NULL
) {
292 ret_val
= nla_put_string(skb
,
293 NLBL_MGMT_A_DOMAIN
, entry
->domain
);
298 ret_val
= nla_put_u16(skb
, NLBL_MGMT_A_FAMILY
, entry
->family
);
302 switch (entry
->def
.type
) {
303 case NETLBL_NLTYPE_ADDRSELECT
:
304 nla_a
= nla_nest_start_noflag(skb
, NLBL_MGMT_A_SELECTORLIST
);
308 netlbl_af4list_foreach_rcu(iter4
, &entry
->def
.addrsel
->list4
) {
309 struct netlbl_domaddr4_map
*map4
;
310 struct in_addr addr_struct
;
312 nla_b
= nla_nest_start_noflag(skb
,
313 NLBL_MGMT_A_ADDRSELECTOR
);
317 addr_struct
.s_addr
= iter4
->addr
;
318 ret_val
= nla_put_in_addr(skb
, NLBL_MGMT_A_IPV4ADDR
,
322 addr_struct
.s_addr
= iter4
->mask
;
323 ret_val
= nla_put_in_addr(skb
, NLBL_MGMT_A_IPV4MASK
,
327 map4
= netlbl_domhsh_addr4_entry(iter4
);
328 ret_val
= nla_put_u32(skb
, NLBL_MGMT_A_PROTOCOL
,
332 switch (map4
->def
.type
) {
333 case NETLBL_NLTYPE_CIPSOV4
:
334 ret_val
= nla_put_u32(skb
, NLBL_MGMT_A_CV4DOI
,
335 map4
->def
.cipso
->doi
);
341 nla_nest_end(skb
, nla_b
);
343 #if IS_ENABLED(CONFIG_IPV6)
344 netlbl_af6list_foreach_rcu(iter6
, &entry
->def
.addrsel
->list6
) {
345 struct netlbl_domaddr6_map
*map6
;
347 nla_b
= nla_nest_start_noflag(skb
,
348 NLBL_MGMT_A_ADDRSELECTOR
);
352 ret_val
= nla_put_in6_addr(skb
, NLBL_MGMT_A_IPV6ADDR
,
356 ret_val
= nla_put_in6_addr(skb
, NLBL_MGMT_A_IPV6MASK
,
360 map6
= netlbl_domhsh_addr6_entry(iter6
);
361 ret_val
= nla_put_u32(skb
, NLBL_MGMT_A_PROTOCOL
,
366 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
);
375 nla_nest_end(skb
, nla_b
);
379 nla_nest_end(skb
, nla_a
);
381 case NETLBL_NLTYPE_UNLABELED
:
382 ret_val
= nla_put_u32(skb
, NLBL_MGMT_A_PROTOCOL
,
385 case NETLBL_NLTYPE_CIPSOV4
:
386 ret_val
= nla_put_u32(skb
, NLBL_MGMT_A_PROTOCOL
,
390 ret_val
= nla_put_u32(skb
, NLBL_MGMT_A_CV4DOI
,
391 entry
->def
.cipso
->doi
);
393 case NETLBL_NLTYPE_CALIPSO
:
394 ret_val
= nla_put_u32(skb
, NLBL_MGMT_A_PROTOCOL
,
398 ret_val
= nla_put_u32(skb
, NLBL_MGMT_A_CLPDOI
,
399 entry
->def
.calipso
->doi
);
407 * NetLabel Command Handlers
411 * netlbl_mgmt_add - Handle an ADD message
412 * @skb: the NETLINK buffer
413 * @info: the Generic NETLINK info block
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.
421 static int netlbl_mgmt_add(struct sk_buff
*skb
, struct genl_info
*info
)
423 struct netlbl_audit audit_info
;
425 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
)))
437 netlbl_netlink_auditinfo(skb
, &audit_info
);
439 return netlbl_mgmt_add_common(info
, &audit_info
);
443 * netlbl_mgmt_remove - Handle a REMOVE message
444 * @skb: the NETLINK buffer
445 * @info: the Generic NETLINK info block
448 * Process a user generated REMOVE message and remove the specified domain
449 * mappings. Returns zero on success, negative values on failure.
452 static int netlbl_mgmt_remove(struct sk_buff
*skb
, struct genl_info
*info
)
455 struct netlbl_audit audit_info
;
457 if (!info
->attrs
[NLBL_MGMT_A_DOMAIN
])
460 netlbl_netlink_auditinfo(skb
, &audit_info
);
462 domain
= nla_data(info
->attrs
[NLBL_MGMT_A_DOMAIN
]);
463 return netlbl_domhsh_remove(domain
, AF_UNSPEC
, &audit_info
);
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
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
478 static int netlbl_mgmt_listall_cb(struct netlbl_dom_map
*entry
, void *arg
)
480 int ret_val
= -ENOMEM
;
481 struct netlbl_domhsh_walk_arg
*cb_arg
= arg
;
484 data
= genlmsg_put(cb_arg
->skb
, NETLINK_CB(cb_arg
->nl_cb
->skb
).portid
,
485 cb_arg
->seq
, &netlbl_mgmt_gnl_family
,
486 NLM_F_MULTI
, NLBL_MGMT_C_LISTALL
);
488 goto listall_cb_failure
;
490 ret_val
= netlbl_mgmt_listentry(cb_arg
->skb
, entry
);
492 goto listall_cb_failure
;
495 genlmsg_end(cb_arg
->skb
, data
);
499 genlmsg_cancel(cb_arg
->skb
, data
);
504 * netlbl_mgmt_listall - Handle a LISTALL message
505 * @skb: the NETLINK buffer
506 * @cb: the NETLINK callback
509 * 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.
514 static int netlbl_mgmt_listall(struct sk_buff
*skb
,
515 struct netlink_callback
*cb
)
517 struct netlbl_domhsh_walk_arg cb_arg
;
518 u32 skip_bkt
= cb
->args
[0];
519 u32 skip_chain
= cb
->args
[1];
523 cb_arg
.seq
= cb
->nlh
->nlmsg_seq
;
525 netlbl_domhsh_walk(&skip_bkt
,
527 netlbl_mgmt_listall_cb
,
530 cb
->args
[0] = skip_bkt
;
531 cb
->args
[1] = skip_chain
;
536 * netlbl_mgmt_adddef - Handle an ADDDEF message
537 * @skb: the NETLINK buffer
538 * @info: the Generic NETLINK info block
541 * Process a user generated ADDDEF message and respond accordingly. Returns
542 * zero on success, negative values on failure.
545 static int netlbl_mgmt_adddef(struct sk_buff
*skb
, struct genl_info
*info
)
547 struct netlbl_audit audit_info
;
549 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
)))
560 netlbl_netlink_auditinfo(skb
, &audit_info
);
562 return netlbl_mgmt_add_common(info
, &audit_info
);
566 * netlbl_mgmt_removedef - Handle a REMOVEDEF message
567 * @skb: the NETLINK buffer
568 * @info: the Generic NETLINK info block
571 * Process a user generated REMOVEDEF message and remove the default domain
572 * mapping. Returns zero on success, negative values on failure.
575 static int netlbl_mgmt_removedef(struct sk_buff
*skb
, struct genl_info
*info
)
577 struct netlbl_audit audit_info
;
579 netlbl_netlink_auditinfo(skb
, &audit_info
);
581 return netlbl_domhsh_remove_default(AF_UNSPEC
, &audit_info
);
585 * netlbl_mgmt_listdef - Handle a LISTDEF message
586 * @skb: the NETLINK buffer
587 * @info: the Generic NETLINK info block
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.
595 static int netlbl_mgmt_listdef(struct sk_buff
*skb
, struct genl_info
*info
)
597 int ret_val
= -ENOMEM
;
598 struct sk_buff
*ans_skb
= NULL
;
600 struct netlbl_dom_map
*entry
;
603 if (info
->attrs
[NLBL_MGMT_A_FAMILY
])
604 family
= nla_get_u16(info
->attrs
[NLBL_MGMT_A_FAMILY
]);
608 ans_skb
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
611 data
= genlmsg_put_reply(ans_skb
, info
, &netlbl_mgmt_gnl_family
,
612 0, NLBL_MGMT_C_LISTDEF
);
614 goto listdef_failure
;
617 entry
= netlbl_domhsh_getentry(NULL
, family
);
620 goto listdef_failure_lock
;
622 ret_val
= netlbl_mgmt_listentry(ans_skb
, entry
);
625 goto listdef_failure
;
627 genlmsg_end(ans_skb
, data
);
628 return genlmsg_reply(ans_skb
, info
);
630 listdef_failure_lock
:
638 * netlbl_mgmt_protocols_cb - Write an individual PROTOCOL message response
639 * @skb: the skb to write to
640 * @cb: the NETLINK callback
641 * @protocol: the NetLabel protocol to use in the message
644 * 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.
649 static int netlbl_mgmt_protocols_cb(struct sk_buff
*skb
,
650 struct netlink_callback
*cb
,
653 int ret_val
= -ENOMEM
;
656 data
= genlmsg_put(skb
, NETLINK_CB(cb
->skb
).portid
, cb
->nlh
->nlmsg_seq
,
657 &netlbl_mgmt_gnl_family
, NLM_F_MULTI
,
658 NLBL_MGMT_C_PROTOCOLS
);
660 goto protocols_cb_failure
;
662 ret_val
= nla_put_u32(skb
, NLBL_MGMT_A_PROTOCOL
, protocol
);
664 goto protocols_cb_failure
;
666 genlmsg_end(skb
, data
);
669 protocols_cb_failure
:
670 genlmsg_cancel(skb
, data
);
675 * netlbl_mgmt_protocols - Handle a PROTOCOLS message
676 * @skb: the NETLINK buffer
677 * @cb: the NETLINK callback
680 * Process a user generated PROTOCOLS message and respond accordingly.
683 static int netlbl_mgmt_protocols(struct sk_buff
*skb
,
684 struct netlink_callback
*cb
)
686 u32 protos_sent
= cb
->args
[0];
688 if (protos_sent
== 0) {
689 if (netlbl_mgmt_protocols_cb(skb
,
691 NETLBL_NLTYPE_UNLABELED
) < 0)
692 goto protocols_return
;
695 if (protos_sent
== 1) {
696 if (netlbl_mgmt_protocols_cb(skb
,
698 NETLBL_NLTYPE_CIPSOV4
) < 0)
699 goto protocols_return
;
702 #if IS_ENABLED(CONFIG_IPV6)
703 if (protos_sent
== 2) {
704 if (netlbl_mgmt_protocols_cb(skb
,
706 NETLBL_NLTYPE_CALIPSO
) < 0)
707 goto protocols_return
;
713 cb
->args
[0] = protos_sent
;
718 * netlbl_mgmt_version - Handle a VERSION message
719 * @skb: the NETLINK buffer
720 * @info: the Generic NETLINK info block
723 * Process a user generated VERSION message and respond accordingly. Returns
724 * zero on success, negative values on failure.
727 static int netlbl_mgmt_version(struct sk_buff
*skb
, struct genl_info
*info
)
729 int ret_val
= -ENOMEM
;
730 struct sk_buff
*ans_skb
= NULL
;
733 ans_skb
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
736 data
= genlmsg_put_reply(ans_skb
, info
, &netlbl_mgmt_gnl_family
,
737 0, NLBL_MGMT_C_VERSION
);
739 goto version_failure
;
741 ret_val
= nla_put_u32(ans_skb
,
743 NETLBL_PROTO_VERSION
);
745 goto version_failure
;
747 genlmsg_end(ans_skb
, data
);
748 return genlmsg_reply(ans_skb
, info
);
757 * NetLabel Generic NETLINK Command Definitions
760 static const struct genl_small_ops netlbl_mgmt_genl_ops
[] = {
762 .cmd
= NLBL_MGMT_C_ADD
,
763 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
764 .flags
= GENL_ADMIN_PERM
,
765 .doit
= netlbl_mgmt_add
,
769 .cmd
= NLBL_MGMT_C_REMOVE
,
770 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
771 .flags
= GENL_ADMIN_PERM
,
772 .doit
= netlbl_mgmt_remove
,
776 .cmd
= NLBL_MGMT_C_LISTALL
,
777 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
780 .dumpit
= netlbl_mgmt_listall
,
783 .cmd
= NLBL_MGMT_C_ADDDEF
,
784 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
785 .flags
= GENL_ADMIN_PERM
,
786 .doit
= netlbl_mgmt_adddef
,
790 .cmd
= NLBL_MGMT_C_REMOVEDEF
,
791 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
792 .flags
= GENL_ADMIN_PERM
,
793 .doit
= netlbl_mgmt_removedef
,
797 .cmd
= NLBL_MGMT_C_LISTDEF
,
798 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
800 .doit
= netlbl_mgmt_listdef
,
804 .cmd
= NLBL_MGMT_C_PROTOCOLS
,
805 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
808 .dumpit
= netlbl_mgmt_protocols
,
811 .cmd
= NLBL_MGMT_C_VERSION
,
812 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
814 .doit
= netlbl_mgmt_version
,
819 static struct genl_family netlbl_mgmt_gnl_family __ro_after_init
= {
821 .name
= NETLBL_NLTYPE_MGMT_NAME
,
822 .version
= NETLBL_PROTO_VERSION
,
823 .maxattr
= NLBL_MGMT_A_MAX
,
824 .policy
= netlbl_mgmt_genl_policy
,
825 .module
= THIS_MODULE
,
826 .small_ops
= netlbl_mgmt_genl_ops
,
827 .n_small_ops
= ARRAY_SIZE(netlbl_mgmt_genl_ops
),
831 * NetLabel Generic NETLINK Protocol Functions
835 * netlbl_mgmt_genl_init - Register the NetLabel management component
838 * Register the NetLabel management component with the Generic NETLINK
839 * mechanism. Returns zero on success, negative values on failure.
842 int __init
netlbl_mgmt_genl_init(void)
844 return genl_register_family(&netlbl_mgmt_gnl_family
);