1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * NetLabel CIPSO/IPv4 Support
5 * This file defines the CIPSO/IPv4 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
16 #include <linux/types.h>
17 #include <linux/socket.h>
18 #include <linux/string.h>
19 #include <linux/skbuff.h>
20 #include <linux/audit.h>
21 #include <linux/slab.h>
23 #include <net/netlink.h>
24 #include <net/genetlink.h>
25 #include <net/netlabel.h>
26 #include <net/cipso_ipv4.h>
27 #include <linux/atomic.h>
29 #include "netlabel_user.h"
30 #include "netlabel_cipso_v4.h"
31 #include "netlabel_mgmt.h"
32 #include "netlabel_domainhash.h"
34 /* Argument struct for cipso_v4_doi_walk() */
35 struct netlbl_cipsov4_doiwalk_arg
{
36 struct netlink_callback
*nl_cb
;
41 /* Argument struct for netlbl_domhsh_walk() */
42 struct netlbl_domhsh_walk_arg
{
43 struct netlbl_audit
*audit_info
;
47 /* NetLabel Generic NETLINK CIPSOv4 family */
48 static struct genl_family netlbl_cipsov4_gnl_family
;
49 /* NetLabel Netlink attribute policy */
50 static const struct nla_policy netlbl_cipsov4_genl_policy
[NLBL_CIPSOV4_A_MAX
+ 1] = {
51 [NLBL_CIPSOV4_A_DOI
] = { .type
= NLA_U32
},
52 [NLBL_CIPSOV4_A_MTYPE
] = { .type
= NLA_U32
},
53 [NLBL_CIPSOV4_A_TAG
] = { .type
= NLA_U8
},
54 [NLBL_CIPSOV4_A_TAGLST
] = { .type
= NLA_NESTED
},
55 [NLBL_CIPSOV4_A_MLSLVLLOC
] = { .type
= NLA_U32
},
56 [NLBL_CIPSOV4_A_MLSLVLREM
] = { .type
= NLA_U32
},
57 [NLBL_CIPSOV4_A_MLSLVL
] = { .type
= NLA_NESTED
},
58 [NLBL_CIPSOV4_A_MLSLVLLST
] = { .type
= NLA_NESTED
},
59 [NLBL_CIPSOV4_A_MLSCATLOC
] = { .type
= NLA_U32
},
60 [NLBL_CIPSOV4_A_MLSCATREM
] = { .type
= NLA_U32
},
61 [NLBL_CIPSOV4_A_MLSCAT
] = { .type
= NLA_NESTED
},
62 [NLBL_CIPSOV4_A_MLSCATLST
] = { .type
= NLA_NESTED
},
70 * netlbl_cipsov4_add_common - Parse the common sections of a ADD message
71 * @info: the Generic NETLINK info block
72 * @doi_def: the CIPSO V4 DOI definition
75 * Parse the common sections of a ADD message and fill in the related values
76 * in @doi_def. Returns zero on success, negative values on failure.
79 static int netlbl_cipsov4_add_common(struct genl_info
*info
,
80 struct cipso_v4_doi
*doi_def
)
86 doi_def
->doi
= nla_get_u32(info
->attrs
[NLBL_CIPSOV4_A_DOI
]);
88 if (nla_validate_nested_deprecated(info
->attrs
[NLBL_CIPSOV4_A_TAGLST
],
90 netlbl_cipsov4_genl_policy
,
94 nla_for_each_nested(nla
, info
->attrs
[NLBL_CIPSOV4_A_TAGLST
], nla_rem
)
95 if (nla_type(nla
) == NLBL_CIPSOV4_A_TAG
) {
96 if (iter
>= CIPSO_V4_TAG_MAXCNT
)
98 doi_def
->tags
[iter
++] = nla_get_u8(nla
);
100 while (iter
< CIPSO_V4_TAG_MAXCNT
)
101 doi_def
->tags
[iter
++] = CIPSO_V4_TAG_INVALID
;
107 * NetLabel Command Handlers
111 * netlbl_cipsov4_add_std - Adds a CIPSO V4 DOI definition
112 * @info: the Generic NETLINK info block
113 * @audit_info: NetLabel audit information
116 * Create a new CIPSO_V4_MAP_TRANS DOI definition based on the given ADD
117 * message and add it to the CIPSO V4 engine. Return zero on success and
121 static int netlbl_cipsov4_add_std(struct genl_info
*info
,
122 struct netlbl_audit
*audit_info
)
124 int ret_val
= -EINVAL
;
125 struct cipso_v4_doi
*doi_def
= NULL
;
126 struct nlattr
*nla_a
;
127 struct nlattr
*nla_b
;
132 if (!info
->attrs
[NLBL_CIPSOV4_A_TAGLST
] ||
133 !info
->attrs
[NLBL_CIPSOV4_A_MLSLVLLST
])
136 if (nla_validate_nested_deprecated(info
->attrs
[NLBL_CIPSOV4_A_MLSLVLLST
],
138 netlbl_cipsov4_genl_policy
,
142 doi_def
= kmalloc(sizeof(*doi_def
), GFP_KERNEL
);
145 doi_def
->map
.std
= kzalloc(sizeof(*doi_def
->map
.std
), GFP_KERNEL
);
146 if (doi_def
->map
.std
== NULL
) {
148 goto add_std_failure
;
150 doi_def
->type
= CIPSO_V4_MAP_TRANS
;
152 ret_val
= netlbl_cipsov4_add_common(info
, doi_def
);
154 goto add_std_failure
;
157 nla_for_each_nested(nla_a
,
158 info
->attrs
[NLBL_CIPSOV4_A_MLSLVLLST
],
160 if (nla_type(nla_a
) == NLBL_CIPSOV4_A_MLSLVL
) {
161 if (nla_validate_nested_deprecated(nla_a
,
163 netlbl_cipsov4_genl_policy
,
165 goto add_std_failure
;
166 nla_for_each_nested(nla_b
, nla_a
, nla_b_rem
)
167 switch (nla_type(nla_b
)) {
168 case NLBL_CIPSOV4_A_MLSLVLLOC
:
169 if (nla_get_u32(nla_b
) >
170 CIPSO_V4_MAX_LOC_LVLS
)
171 goto add_std_failure
;
172 if (nla_get_u32(nla_b
) >=
173 doi_def
->map
.std
->lvl
.local_size
)
174 doi_def
->map
.std
->lvl
.local_size
=
175 nla_get_u32(nla_b
) + 1;
177 case NLBL_CIPSOV4_A_MLSLVLREM
:
178 if (nla_get_u32(nla_b
) >
179 CIPSO_V4_MAX_REM_LVLS
)
180 goto add_std_failure
;
181 if (nla_get_u32(nla_b
) >=
182 doi_def
->map
.std
->lvl
.cipso_size
)
183 doi_def
->map
.std
->lvl
.cipso_size
=
184 nla_get_u32(nla_b
) + 1;
188 doi_def
->map
.std
->lvl
.local
= kcalloc(doi_def
->map
.std
->lvl
.local_size
,
191 if (doi_def
->map
.std
->lvl
.local
== NULL
) {
193 goto add_std_failure
;
195 doi_def
->map
.std
->lvl
.cipso
= kcalloc(doi_def
->map
.std
->lvl
.cipso_size
,
198 if (doi_def
->map
.std
->lvl
.cipso
== NULL
) {
200 goto add_std_failure
;
202 for (iter
= 0; iter
< doi_def
->map
.std
->lvl
.local_size
; iter
++)
203 doi_def
->map
.std
->lvl
.local
[iter
] = CIPSO_V4_INV_LVL
;
204 for (iter
= 0; iter
< doi_def
->map
.std
->lvl
.cipso_size
; iter
++)
205 doi_def
->map
.std
->lvl
.cipso
[iter
] = CIPSO_V4_INV_LVL
;
206 nla_for_each_nested(nla_a
,
207 info
->attrs
[NLBL_CIPSOV4_A_MLSLVLLST
],
209 if (nla_type(nla_a
) == NLBL_CIPSOV4_A_MLSLVL
) {
210 struct nlattr
*lvl_loc
;
211 struct nlattr
*lvl_rem
;
213 lvl_loc
= nla_find_nested(nla_a
,
214 NLBL_CIPSOV4_A_MLSLVLLOC
);
215 lvl_rem
= nla_find_nested(nla_a
,
216 NLBL_CIPSOV4_A_MLSLVLREM
);
217 if (lvl_loc
== NULL
|| lvl_rem
== NULL
)
218 goto add_std_failure
;
219 doi_def
->map
.std
->lvl
.local
[nla_get_u32(lvl_loc
)] =
220 nla_get_u32(lvl_rem
);
221 doi_def
->map
.std
->lvl
.cipso
[nla_get_u32(lvl_rem
)] =
222 nla_get_u32(lvl_loc
);
225 if (info
->attrs
[NLBL_CIPSOV4_A_MLSCATLST
]) {
226 if (nla_validate_nested_deprecated(info
->attrs
[NLBL_CIPSOV4_A_MLSCATLST
],
228 netlbl_cipsov4_genl_policy
,
230 goto add_std_failure
;
232 nla_for_each_nested(nla_a
,
233 info
->attrs
[NLBL_CIPSOV4_A_MLSCATLST
],
235 if (nla_type(nla_a
) == NLBL_CIPSOV4_A_MLSCAT
) {
236 if (nla_validate_nested_deprecated(nla_a
,
238 netlbl_cipsov4_genl_policy
,
240 goto add_std_failure
;
241 nla_for_each_nested(nla_b
, nla_a
, nla_b_rem
)
242 switch (nla_type(nla_b
)) {
243 case NLBL_CIPSOV4_A_MLSCATLOC
:
244 if (nla_get_u32(nla_b
) >
245 CIPSO_V4_MAX_LOC_CATS
)
246 goto add_std_failure
;
247 if (nla_get_u32(nla_b
) >=
248 doi_def
->map
.std
->cat
.local_size
)
249 doi_def
->map
.std
->cat
.local_size
=
250 nla_get_u32(nla_b
) + 1;
252 case NLBL_CIPSOV4_A_MLSCATREM
:
253 if (nla_get_u32(nla_b
) >
254 CIPSO_V4_MAX_REM_CATS
)
255 goto add_std_failure
;
256 if (nla_get_u32(nla_b
) >=
257 doi_def
->map
.std
->cat
.cipso_size
)
258 doi_def
->map
.std
->cat
.cipso_size
=
259 nla_get_u32(nla_b
) + 1;
263 doi_def
->map
.std
->cat
.local
= kcalloc(
264 doi_def
->map
.std
->cat
.local_size
,
267 if (doi_def
->map
.std
->cat
.local
== NULL
) {
269 goto add_std_failure
;
271 doi_def
->map
.std
->cat
.cipso
= kcalloc(
272 doi_def
->map
.std
->cat
.cipso_size
,
275 if (doi_def
->map
.std
->cat
.cipso
== NULL
) {
277 goto add_std_failure
;
279 for (iter
= 0; iter
< doi_def
->map
.std
->cat
.local_size
; iter
++)
280 doi_def
->map
.std
->cat
.local
[iter
] = CIPSO_V4_INV_CAT
;
281 for (iter
= 0; iter
< doi_def
->map
.std
->cat
.cipso_size
; iter
++)
282 doi_def
->map
.std
->cat
.cipso
[iter
] = CIPSO_V4_INV_CAT
;
283 nla_for_each_nested(nla_a
,
284 info
->attrs
[NLBL_CIPSOV4_A_MLSCATLST
],
286 if (nla_type(nla_a
) == NLBL_CIPSOV4_A_MLSCAT
) {
287 struct nlattr
*cat_loc
;
288 struct nlattr
*cat_rem
;
290 cat_loc
= nla_find_nested(nla_a
,
291 NLBL_CIPSOV4_A_MLSCATLOC
);
292 cat_rem
= nla_find_nested(nla_a
,
293 NLBL_CIPSOV4_A_MLSCATREM
);
294 if (cat_loc
== NULL
|| cat_rem
== NULL
)
295 goto add_std_failure
;
296 doi_def
->map
.std
->cat
.local
[
297 nla_get_u32(cat_loc
)] =
298 nla_get_u32(cat_rem
);
299 doi_def
->map
.std
->cat
.cipso
[
300 nla_get_u32(cat_rem
)] =
301 nla_get_u32(cat_loc
);
305 ret_val
= cipso_v4_doi_add(doi_def
, audit_info
);
307 goto add_std_failure
;
311 cipso_v4_doi_free(doi_def
);
316 * netlbl_cipsov4_add_pass - Adds a CIPSO V4 DOI definition
317 * @info: the Generic NETLINK info block
318 * @audit_info: NetLabel audit information
321 * Create a new CIPSO_V4_MAP_PASS DOI definition based on the given ADD message
322 * and add it to the CIPSO V4 engine. Return zero on success and non-zero on
326 static int netlbl_cipsov4_add_pass(struct genl_info
*info
,
327 struct netlbl_audit
*audit_info
)
330 struct cipso_v4_doi
*doi_def
= NULL
;
332 if (!info
->attrs
[NLBL_CIPSOV4_A_TAGLST
])
335 doi_def
= kmalloc(sizeof(*doi_def
), GFP_KERNEL
);
338 doi_def
->type
= CIPSO_V4_MAP_PASS
;
340 ret_val
= netlbl_cipsov4_add_common(info
, doi_def
);
342 goto add_pass_failure
;
344 ret_val
= cipso_v4_doi_add(doi_def
, audit_info
);
346 goto add_pass_failure
;
350 cipso_v4_doi_free(doi_def
);
355 * netlbl_cipsov4_add_local - Adds a CIPSO V4 DOI definition
356 * @info: the Generic NETLINK info block
357 * @audit_info: NetLabel audit information
360 * Create a new CIPSO_V4_MAP_LOCAL DOI definition based on the given ADD
361 * message and add it to the CIPSO V4 engine. Return zero on success and
365 static int netlbl_cipsov4_add_local(struct genl_info
*info
,
366 struct netlbl_audit
*audit_info
)
369 struct cipso_v4_doi
*doi_def
= NULL
;
371 if (!info
->attrs
[NLBL_CIPSOV4_A_TAGLST
])
374 doi_def
= kmalloc(sizeof(*doi_def
), GFP_KERNEL
);
377 doi_def
->type
= CIPSO_V4_MAP_LOCAL
;
379 ret_val
= netlbl_cipsov4_add_common(info
, doi_def
);
381 goto add_local_failure
;
383 ret_val
= cipso_v4_doi_add(doi_def
, audit_info
);
385 goto add_local_failure
;
389 cipso_v4_doi_free(doi_def
);
394 * netlbl_cipsov4_add - Handle an ADD message
395 * @skb: the NETLINK buffer
396 * @info: the Generic NETLINK info block
399 * Create a new DOI definition based on the given ADD message and add it to the
400 * CIPSO V4 engine. Returns zero on success, negative values on failure.
403 static int netlbl_cipsov4_add(struct sk_buff
*skb
, struct genl_info
*info
)
406 int ret_val
= -EINVAL
;
407 struct netlbl_audit audit_info
;
409 if (!info
->attrs
[NLBL_CIPSOV4_A_DOI
] ||
410 !info
->attrs
[NLBL_CIPSOV4_A_MTYPE
])
413 netlbl_netlink_auditinfo(skb
, &audit_info
);
414 switch (nla_get_u32(info
->attrs
[NLBL_CIPSOV4_A_MTYPE
])) {
415 case CIPSO_V4_MAP_TRANS
:
416 ret_val
= netlbl_cipsov4_add_std(info
, &audit_info
);
418 case CIPSO_V4_MAP_PASS
:
419 ret_val
= netlbl_cipsov4_add_pass(info
, &audit_info
);
421 case CIPSO_V4_MAP_LOCAL
:
422 ret_val
= netlbl_cipsov4_add_local(info
, &audit_info
);
426 atomic_inc(&netlabel_mgmt_protocount
);
432 * netlbl_cipsov4_list - Handle a LIST message
433 * @skb: the NETLINK buffer
434 * @info: the Generic NETLINK info block
437 * Process a user generated LIST message and respond accordingly. While the
438 * response message generated by the kernel is straightforward, determining
439 * before hand the size of the buffer to allocate is not (we have to generate
440 * the message to know the size). In order to keep this function sane what we
441 * do is allocate a buffer of NLMSG_GOODSIZE and try to fit the response in
442 * that size, if we fail then we restart with a larger buffer and try again.
443 * We continue in this manner until we hit a limit of failed attempts then we
444 * give up and just send an error message. Returns zero on success and
445 * negative values on error.
448 static int netlbl_cipsov4_list(struct sk_buff
*skb
, struct genl_info
*info
)
451 struct sk_buff
*ans_skb
= NULL
;
455 struct nlattr
*nla_a
;
456 struct nlattr
*nla_b
;
457 struct cipso_v4_doi
*doi_def
;
460 if (!info
->attrs
[NLBL_CIPSOV4_A_DOI
]) {
466 ans_skb
= nlmsg_new(NLMSG_DEFAULT_SIZE
* nlsze_mult
, GFP_KERNEL
);
467 if (ans_skb
== NULL
) {
471 data
= genlmsg_put_reply(ans_skb
, info
, &netlbl_cipsov4_gnl_family
,
472 0, NLBL_CIPSOV4_C_LIST
);
478 doi
= nla_get_u32(info
->attrs
[NLBL_CIPSOV4_A_DOI
]);
481 doi_def
= cipso_v4_doi_getdef(doi
);
482 if (doi_def
== NULL
) {
484 goto list_failure_lock
;
487 ret_val
= nla_put_u32(ans_skb
, NLBL_CIPSOV4_A_MTYPE
, doi_def
->type
);
489 goto list_failure_lock
;
491 nla_a
= nla_nest_start_noflag(ans_skb
, NLBL_CIPSOV4_A_TAGLST
);
494 goto list_failure_lock
;
497 iter
< CIPSO_V4_TAG_MAXCNT
&&
498 doi_def
->tags
[iter
] != CIPSO_V4_TAG_INVALID
;
500 ret_val
= nla_put_u8(ans_skb
,
502 doi_def
->tags
[iter
]);
504 goto list_failure_lock
;
506 nla_nest_end(ans_skb
, nla_a
);
508 switch (doi_def
->type
) {
509 case CIPSO_V4_MAP_TRANS
:
510 nla_a
= nla_nest_start_noflag(ans_skb
,
511 NLBL_CIPSOV4_A_MLSLVLLST
);
514 goto list_failure_lock
;
517 iter
< doi_def
->map
.std
->lvl
.local_size
;
519 if (doi_def
->map
.std
->lvl
.local
[iter
] ==
523 nla_b
= nla_nest_start_noflag(ans_skb
,
524 NLBL_CIPSOV4_A_MLSLVL
);
529 ret_val
= nla_put_u32(ans_skb
,
530 NLBL_CIPSOV4_A_MLSLVLLOC
,
534 ret_val
= nla_put_u32(ans_skb
,
535 NLBL_CIPSOV4_A_MLSLVLREM
,
536 doi_def
->map
.std
->lvl
.local
[iter
]);
539 nla_nest_end(ans_skb
, nla_b
);
541 nla_nest_end(ans_skb
, nla_a
);
543 nla_a
= nla_nest_start_noflag(ans_skb
,
544 NLBL_CIPSOV4_A_MLSCATLST
);
550 iter
< doi_def
->map
.std
->cat
.local_size
;
552 if (doi_def
->map
.std
->cat
.local
[iter
] ==
556 nla_b
= nla_nest_start_noflag(ans_skb
,
557 NLBL_CIPSOV4_A_MLSCAT
);
562 ret_val
= nla_put_u32(ans_skb
,
563 NLBL_CIPSOV4_A_MLSCATLOC
,
567 ret_val
= nla_put_u32(ans_skb
,
568 NLBL_CIPSOV4_A_MLSCATREM
,
569 doi_def
->map
.std
->cat
.local
[iter
]);
572 nla_nest_end(ans_skb
, nla_b
);
574 nla_nest_end(ans_skb
, nla_a
);
580 genlmsg_end(ans_skb
, data
);
581 return genlmsg_reply(ans_skb
, info
);
584 /* XXX - this limit is a guesstimate */
585 if (nlsze_mult
< 4) {
599 * netlbl_cipsov4_listall_cb - cipso_v4_doi_walk() callback for LISTALL
600 * @doi_def: the CIPSOv4 DOI definition
601 * @arg: the netlbl_cipsov4_doiwalk_arg structure
604 * This function is designed to be used as a callback to the
605 * cipso_v4_doi_walk() function for use in generating a response for a LISTALL
606 * message. Returns the size of the message on success, negative values on
610 static int netlbl_cipsov4_listall_cb(struct cipso_v4_doi
*doi_def
, void *arg
)
612 int ret_val
= -ENOMEM
;
613 struct netlbl_cipsov4_doiwalk_arg
*cb_arg
= arg
;
616 data
= genlmsg_put(cb_arg
->skb
, NETLINK_CB(cb_arg
->nl_cb
->skb
).portid
,
617 cb_arg
->seq
, &netlbl_cipsov4_gnl_family
,
618 NLM_F_MULTI
, NLBL_CIPSOV4_C_LISTALL
);
620 goto listall_cb_failure
;
622 ret_val
= nla_put_u32(cb_arg
->skb
, NLBL_CIPSOV4_A_DOI
, doi_def
->doi
);
624 goto listall_cb_failure
;
625 ret_val
= nla_put_u32(cb_arg
->skb
,
626 NLBL_CIPSOV4_A_MTYPE
,
629 goto listall_cb_failure
;
631 genlmsg_end(cb_arg
->skb
, data
);
635 genlmsg_cancel(cb_arg
->skb
, data
);
640 * netlbl_cipsov4_listall - Handle a LISTALL message
641 * @skb: the NETLINK buffer
642 * @cb: the NETLINK callback
645 * Process a user generated LISTALL message and respond accordingly. Returns
646 * zero on success and negative values on error.
649 static int netlbl_cipsov4_listall(struct sk_buff
*skb
,
650 struct netlink_callback
*cb
)
652 struct netlbl_cipsov4_doiwalk_arg cb_arg
;
653 u32 doi_skip
= cb
->args
[0];
657 cb_arg
.seq
= cb
->nlh
->nlmsg_seq
;
659 cipso_v4_doi_walk(&doi_skip
, netlbl_cipsov4_listall_cb
, &cb_arg
);
661 cb
->args
[0] = doi_skip
;
666 * netlbl_cipsov4_remove_cb - netlbl_cipsov4_remove() callback for REMOVE
667 * @entry: LSM domain mapping entry
668 * @arg: the netlbl_domhsh_walk_arg structure
671 * This function is intended for use by netlbl_cipsov4_remove() as the callback
672 * for the netlbl_domhsh_walk() function; it removes LSM domain map entries
673 * which are associated with the CIPSO DOI specified in @arg. Returns zero on
674 * success, negative values on failure.
677 static int netlbl_cipsov4_remove_cb(struct netlbl_dom_map
*entry
, void *arg
)
679 struct netlbl_domhsh_walk_arg
*cb_arg
= arg
;
681 if (entry
->def
.type
== NETLBL_NLTYPE_CIPSOV4
&&
682 entry
->def
.cipso
->doi
== cb_arg
->doi
)
683 return netlbl_domhsh_remove_entry(entry
, cb_arg
->audit_info
);
689 * netlbl_cipsov4_remove - Handle a REMOVE message
690 * @skb: the NETLINK buffer
691 * @info: the Generic NETLINK info block
694 * Process a user generated REMOVE message and respond accordingly. Returns
695 * zero on success, negative values on failure.
698 static int netlbl_cipsov4_remove(struct sk_buff
*skb
, struct genl_info
*info
)
700 int ret_val
= -EINVAL
;
701 struct netlbl_domhsh_walk_arg cb_arg
;
702 struct netlbl_audit audit_info
;
706 if (!info
->attrs
[NLBL_CIPSOV4_A_DOI
])
709 netlbl_netlink_auditinfo(skb
, &audit_info
);
710 cb_arg
.doi
= nla_get_u32(info
->attrs
[NLBL_CIPSOV4_A_DOI
]);
711 cb_arg
.audit_info
= &audit_info
;
712 ret_val
= netlbl_domhsh_walk(&skip_bkt
, &skip_chain
,
713 netlbl_cipsov4_remove_cb
, &cb_arg
);
714 if (ret_val
== 0 || ret_val
== -ENOENT
) {
715 ret_val
= cipso_v4_doi_remove(cb_arg
.doi
, &audit_info
);
717 atomic_dec(&netlabel_mgmt_protocount
);
724 * NetLabel Generic NETLINK Command Definitions
727 static const struct genl_small_ops netlbl_cipsov4_ops
[] = {
729 .cmd
= NLBL_CIPSOV4_C_ADD
,
730 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
731 .flags
= GENL_ADMIN_PERM
,
732 .doit
= netlbl_cipsov4_add
,
736 .cmd
= NLBL_CIPSOV4_C_REMOVE
,
737 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
738 .flags
= GENL_ADMIN_PERM
,
739 .doit
= netlbl_cipsov4_remove
,
743 .cmd
= NLBL_CIPSOV4_C_LIST
,
744 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
746 .doit
= netlbl_cipsov4_list
,
750 .cmd
= NLBL_CIPSOV4_C_LISTALL
,
751 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
754 .dumpit
= netlbl_cipsov4_listall
,
758 static struct genl_family netlbl_cipsov4_gnl_family __ro_after_init
= {
760 .name
= NETLBL_NLTYPE_CIPSOV4_NAME
,
761 .version
= NETLBL_PROTO_VERSION
,
762 .maxattr
= NLBL_CIPSOV4_A_MAX
,
763 .policy
= netlbl_cipsov4_genl_policy
,
764 .module
= THIS_MODULE
,
765 .small_ops
= netlbl_cipsov4_ops
,
766 .n_small_ops
= ARRAY_SIZE(netlbl_cipsov4_ops
),
770 * NetLabel Generic NETLINK Protocol Functions
774 * netlbl_cipsov4_genl_init - Register the CIPSOv4 NetLabel component
777 * Register the CIPSOv4 packet NetLabel component with the Generic NETLINK
778 * mechanism. Returns zero on success, negative values on failure.
781 int __init
netlbl_cipsov4_genl_init(void)
783 return genl_register_family(&netlbl_cipsov4_gnl_family
);