1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * NetLabel CALIPSO/IPv6 Support
4  *
5  * This file defines the CALIPSO/IPv6 functions for the NetLabel system.  The
6  * NetLabel system manages static and dynamic label mappings for network
7  * protocols such as CIPSO and CALIPSO.
8  *
9  * Authors: Paul Moore <paul@paul-moore.com>
10  *          Huw Davies <huw@codeweavers.com>
11  */
12 
13 /* (c) Copyright Hewlett-Packard Development Company, L.P., 2006
14  * (c) Copyright Huw Davies <huw@codeweavers.com>, 2015
15  */
16 
17 #include <linux/types.h>
18 #include <linux/socket.h>
19 #include <linux/string.h>
20 #include <linux/skbuff.h>
21 #include <linux/audit.h>
22 #include <linux/slab.h>
23 #include <net/sock.h>
24 #include <net/netlink.h>
25 #include <net/genetlink.h>
26 #include <net/netlabel.h>
27 #include <net/calipso.h>
28 #include <linux/atomic.h>
29 
30 #include "netlabel_user.h"
31 #include "netlabel_calipso.h"
32 #include "netlabel_mgmt.h"
33 #include "netlabel_domainhash.h"
34 
35 /* Argument struct for calipso_doi_walk() */
36 struct netlbl_calipso_doiwalk_arg {
37 	struct netlink_callback *nl_cb;
38 	struct sk_buff *skb;
39 	u32 seq;
40 };
41 
42 /* Argument struct for netlbl_domhsh_walk() */
43 struct netlbl_domhsh_walk_arg {
44 	struct netlbl_audit *audit_info;
45 	u32 doi;
46 };
47 
48 /* NetLabel Generic NETLINK CALIPSO family */
49 static struct genl_family netlbl_calipso_gnl_family;
50 
51 /* NetLabel Netlink attribute policy */
52 static const struct nla_policy calipso_genl_policy[NLBL_CALIPSO_A_MAX + 1] = {
53 	[NLBL_CALIPSO_A_DOI] = { .type = NLA_U32 },
54 	[NLBL_CALIPSO_A_MTYPE] = { .type = NLA_U32 },
55 };
56 
57 /* NetLabel Command Handlers
58  */
59 /**
60  * netlbl_calipso_add_pass - Adds a CALIPSO pass DOI definition
61  * @info: the Generic NETLINK info block
62  * @audit_info: NetLabel audit information
63  *
64  * Description:
65  * Create a new CALIPSO_MAP_PASS DOI definition based on the given ADD message
66  * and add it to the CALIPSO engine.  Return zero on success and non-zero on
67  * error.
68  *
69  */
70 static int netlbl_calipso_add_pass(struct genl_info *info,
71 				   struct netlbl_audit *audit_info)
72 {
73 	int ret_val;
74 	struct calipso_doi *doi_def = NULL;
75 
76 	doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL);
77 	if (!doi_def)
78 		return -ENOMEM;
79 	doi_def->type = CALIPSO_MAP_PASS;
80 	doi_def->doi = nla_get_u32(info->attrs[NLBL_CALIPSO_A_DOI]);
81 	ret_val = calipso_doi_add(doi_def, audit_info);
82 	if (ret_val != 0)
83 		calipso_doi_free(doi_def);
84 
85 	return ret_val;
86 }
87 
88 /**
89  * netlbl_calipso_add - Handle an ADD message
90  * @skb: the NETLINK buffer
91  * @info: the Generic NETLINK info block
92  *
93  * Description:
94  * Create a new DOI definition based on the given ADD message and add it to the
95  * CALIPSO engine.  Returns zero on success, negative values on failure.
96  *
97  */
98 static int netlbl_calipso_add(struct sk_buff *skb, struct genl_info *info)
99 
100 {
101 	int ret_val = -EINVAL;
102 	struct netlbl_audit audit_info;
103 
104 	if (!info->attrs[NLBL_CALIPSO_A_DOI] ||
105 	    !info->attrs[NLBL_CALIPSO_A_MTYPE])
106 		return -EINVAL;
107 
108 	netlbl_netlink_auditinfo(&audit_info);
109 	switch (nla_get_u32(info->attrs[NLBL_CALIPSO_A_MTYPE])) {
110 	case CALIPSO_MAP_PASS:
111 		ret_val = netlbl_calipso_add_pass(info, &audit_info);
112 		break;
113 	}
114 	if (ret_val == 0)
115 		atomic_inc(&netlabel_mgmt_protocount);
116 
117 	return ret_val;
118 }
119 
120 /**
121  * netlbl_calipso_list - Handle a LIST message
122  * @skb: the NETLINK buffer
123  * @info: the Generic NETLINK info block
124  *
125  * Description:
126  * Process a user generated LIST message and respond accordingly.
127  * Returns zero on success and negative values on error.
128  *
129  */
130 static int netlbl_calipso_list(struct sk_buff *skb, struct genl_info *info)
131 {
132 	int ret_val;
133 	struct sk_buff *ans_skb = NULL;
134 	void *data;
135 	u32 doi;
136 	struct calipso_doi *doi_def;
137 
138 	if (!info->attrs[NLBL_CALIPSO_A_DOI]) {
139 		ret_val = -EINVAL;
140 		goto list_failure;
141 	}
142 
143 	doi = nla_get_u32(info->attrs[NLBL_CALIPSO_A_DOI]);
144 
145 	doi_def = calipso_doi_getdef(doi);
146 	if (!doi_def) {
147 		ret_val = -EINVAL;
148 		goto list_failure;
149 	}
150 
151 	ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
152 	if (!ans_skb) {
153 		ret_val = -ENOMEM;
154 		goto list_failure_put;
155 	}
156 	data = genlmsg_put_reply(ans_skb, info, &netlbl_calipso_gnl_family,
157 				 0, NLBL_CALIPSO_C_LIST);
158 	if (!data) {
159 		ret_val = -ENOMEM;
160 		goto list_failure_put;
161 	}
162 
163 	ret_val = nla_put_u32(ans_skb, NLBL_CALIPSO_A_MTYPE, doi_def->type);
164 	if (ret_val != 0)
165 		goto list_failure_put;
166 
167 	calipso_doi_putdef(doi_def);
168 
169 	genlmsg_end(ans_skb, data);
170 	return genlmsg_reply(ans_skb, info);
171 
172 list_failure_put:
173 	calipso_doi_putdef(doi_def);
174 list_failure:
175 	kfree_skb(ans_skb);
176 	return ret_val;
177 }
178 
179 /**
180  * netlbl_calipso_listall_cb - calipso_doi_walk() callback for LISTALL
181  * @doi_def: the CALIPSO DOI definition
182  * @arg: the netlbl_calipso_doiwalk_arg structure
183  *
184  * Description:
185  * This function is designed to be used as a callback to the
186  * calipso_doi_walk() function for use in generating a response for a LISTALL
187  * message.  Returns the size of the message on success, negative values on
188  * failure.
189  *
190  */
191 static int netlbl_calipso_listall_cb(struct calipso_doi *doi_def, void *arg)
192 {
193 	int ret_val = -ENOMEM;
194 	struct netlbl_calipso_doiwalk_arg *cb_arg = arg;
195 	void *data;
196 
197 	data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).portid,
198 			   cb_arg->seq, &netlbl_calipso_gnl_family,
199 			   NLM_F_MULTI, NLBL_CALIPSO_C_LISTALL);
200 	if (!data)
201 		goto listall_cb_failure;
202 
203 	ret_val = nla_put_u32(cb_arg->skb, NLBL_CALIPSO_A_DOI, doi_def->doi);
204 	if (ret_val != 0)
205 		goto listall_cb_failure;
206 	ret_val = nla_put_u32(cb_arg->skb,
207 			      NLBL_CALIPSO_A_MTYPE,
208 			      doi_def->type);
209 	if (ret_val != 0)
210 		goto listall_cb_failure;
211 
212 	genlmsg_end(cb_arg->skb, data);
213 	return 0;
214 
215 listall_cb_failure:
216 	genlmsg_cancel(cb_arg->skb, data);
217 	return ret_val;
218 }
219 
220 /**
221  * netlbl_calipso_listall - Handle a LISTALL message
222  * @skb: the NETLINK buffer
223  * @cb: the NETLINK callback
224  *
225  * Description:
226  * Process a user generated LISTALL message and respond accordingly.  Returns
227  * zero on success and negative values on error.
228  *
229  */
230 static int netlbl_calipso_listall(struct sk_buff *skb,
231 				  struct netlink_callback *cb)
232 {
233 	struct netlbl_calipso_doiwalk_arg cb_arg;
234 	u32 doi_skip = cb->args[0];
235 
236 	cb_arg.nl_cb = cb;
237 	cb_arg.skb = skb;
238 	cb_arg.seq = cb->nlh->nlmsg_seq;
239 
240 	calipso_doi_walk(&doi_skip, netlbl_calipso_listall_cb, &cb_arg);
241 
242 	cb->args[0] = doi_skip;
243 	return skb->len;
244 }
245 
246 /**
247  * netlbl_calipso_remove_cb - netlbl_calipso_remove() callback for REMOVE
248  * @entry: LSM domain mapping entry
249  * @arg: the netlbl_domhsh_walk_arg structure
250  *
251  * Description:
252  * This function is intended for use by netlbl_calipso_remove() as the callback
253  * for the netlbl_domhsh_walk() function; it removes LSM domain map entries
254  * which are associated with the CALIPSO DOI specified in @arg.  Returns zero on
255  * success, negative values on failure.
256  *
257  */
258 static int netlbl_calipso_remove_cb(struct netlbl_dom_map *entry, void *arg)
259 {
260 	struct netlbl_domhsh_walk_arg *cb_arg = arg;
261 
262 	if (entry->def.type == NETLBL_NLTYPE_CALIPSO &&
263 	    entry->def.calipso->doi == cb_arg->doi)
264 		return netlbl_domhsh_remove_entry(entry, cb_arg->audit_info);
265 
266 	return 0;
267 }
268 
269 /**
270  * netlbl_calipso_remove - Handle a REMOVE message
271  * @skb: the NETLINK buffer
272  * @info: the Generic NETLINK info block
273  *
274  * Description:
275  * Process a user generated REMOVE message and respond accordingly.  Returns
276  * zero on success, negative values on failure.
277  *
278  */
279 static int netlbl_calipso_remove(struct sk_buff *skb, struct genl_info *info)
280 {
281 	int ret_val = -EINVAL;
282 	struct netlbl_domhsh_walk_arg cb_arg;
283 	struct netlbl_audit audit_info;
284 	u32 skip_bkt = 0;
285 	u32 skip_chain = 0;
286 
287 	if (!info->attrs[NLBL_CALIPSO_A_DOI])
288 		return -EINVAL;
289 
290 	netlbl_netlink_auditinfo(&audit_info);
291 	cb_arg.doi = nla_get_u32(info->attrs[NLBL_CALIPSO_A_DOI]);
292 	cb_arg.audit_info = &audit_info;
293 	ret_val = netlbl_domhsh_walk(&skip_bkt, &skip_chain,
294 				     netlbl_calipso_remove_cb, &cb_arg);
295 	if (ret_val == 0 || ret_val == -ENOENT) {
296 		ret_val = calipso_doi_remove(cb_arg.doi, &audit_info);
297 		if (ret_val == 0)
298 			atomic_dec(&netlabel_mgmt_protocount);
299 	}
300 
301 	return ret_val;
302 }
303 
304 /* NetLabel Generic NETLINK Command Definitions
305  */
306 
307 static const struct genl_small_ops netlbl_calipso_ops[] = {
308 	{
309 	.cmd = NLBL_CALIPSO_C_ADD,
310 	.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
311 	.flags = GENL_ADMIN_PERM,
312 	.doit = netlbl_calipso_add,
313 	.dumpit = NULL,
314 	},
315 	{
316 	.cmd = NLBL_CALIPSO_C_REMOVE,
317 	.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
318 	.flags = GENL_ADMIN_PERM,
319 	.doit = netlbl_calipso_remove,
320 	.dumpit = NULL,
321 	},
322 	{
323 	.cmd = NLBL_CALIPSO_C_LIST,
324 	.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
325 	.flags = 0,
326 	.doit = netlbl_calipso_list,
327 	.dumpit = NULL,
328 	},
329 	{
330 	.cmd = NLBL_CALIPSO_C_LISTALL,
331 	.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
332 	.flags = 0,
333 	.doit = NULL,
334 	.dumpit = netlbl_calipso_listall,
335 	},
336 };
337 
338 static struct genl_family netlbl_calipso_gnl_family __ro_after_init = {
339 	.hdrsize = 0,
340 	.name = NETLBL_NLTYPE_CALIPSO_NAME,
341 	.version = NETLBL_PROTO_VERSION,
342 	.maxattr = NLBL_CALIPSO_A_MAX,
343 	.policy = calipso_genl_policy,
344 	.module = THIS_MODULE,
345 	.small_ops = netlbl_calipso_ops,
346 	.n_small_ops = ARRAY_SIZE(netlbl_calipso_ops),
347 	.resv_start_op = NLBL_CALIPSO_C_LISTALL + 1,
348 };
349 
350 /* NetLabel Generic NETLINK Protocol Functions
351  */
352 
353 /**
354  * netlbl_calipso_genl_init - Register the CALIPSO NetLabel component
355  *
356  * Description:
357  * Register the CALIPSO packet NetLabel component with the Generic NETLINK
358  * mechanism.  Returns zero on success, negative values on failure.
359  *
360  */
361 int __init netlbl_calipso_genl_init(void)
362 {
363 	return genl_register_family(&netlbl_calipso_gnl_family);
364 }
365 
366 static const struct netlbl_calipso_ops *calipso_ops;
367 
368 /**
369  * netlbl_calipso_ops_register - Register the CALIPSO operations
370  * @ops: ops to register
371  *
372  * Description:
373  * Register the CALIPSO packet engine operations.
374  *
375  */
376 const struct netlbl_calipso_ops *
377 netlbl_calipso_ops_register(const struct netlbl_calipso_ops *ops)
378 {
379 	return xchg(&calipso_ops, ops);
380 }
381 EXPORT_SYMBOL(netlbl_calipso_ops_register);
382 
383 static const struct netlbl_calipso_ops *netlbl_calipso_ops_get(void)
384 {
385 	return READ_ONCE(calipso_ops);
386 }
387 
388 /**
389  * calipso_doi_add - Add a new DOI to the CALIPSO protocol engine
390  * @doi_def: the DOI structure
391  * @audit_info: NetLabel audit information
392  *
393  * Description:
394  * The caller defines a new DOI for use by the CALIPSO engine and calls this
395  * function to add it to the list of acceptable domains.  The caller must
396  * ensure that the mapping table specified in @doi_def->map meets all of the
397  * requirements of the mapping type (see calipso.h for details).  Returns
398  * zero on success and non-zero on failure.
399  *
400  */
401 int calipso_doi_add(struct calipso_doi *doi_def,
402 		    struct netlbl_audit *audit_info)
403 {
404 	int ret_val = -ENOMSG;
405 	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
406 
407 	if (ops)
408 		ret_val = ops->doi_add(doi_def, audit_info);
409 	return ret_val;
410 }
411 
412 /**
413  * calipso_doi_free - Frees a DOI definition
414  * @doi_def: the DOI definition
415  *
416  * Description:
417  * This function frees all of the memory associated with a DOI definition.
418  *
419  */
420 void calipso_doi_free(struct calipso_doi *doi_def)
421 {
422 	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
423 
424 	if (ops)
425 		ops->doi_free(doi_def);
426 }
427 
428 /**
429  * calipso_doi_remove - Remove an existing DOI from the CALIPSO protocol engine
430  * @doi: the DOI value
431  * @audit_info: NetLabel audit information
432  *
433  * Description:
434  * Removes a DOI definition from the CALIPSO engine.  The NetLabel routines will
435  * be called to release their own LSM domain mappings as well as our own
436  * domain list.  Returns zero on success and negative values on failure.
437  *
438  */
439 int calipso_doi_remove(u32 doi, struct netlbl_audit *audit_info)
440 {
441 	int ret_val = -ENOMSG;
442 	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
443 
444 	if (ops)
445 		ret_val = ops->doi_remove(doi, audit_info);
446 	return ret_val;
447 }
448 
449 /**
450  * calipso_doi_getdef - Returns a reference to a valid DOI definition
451  * @doi: the DOI value
452  *
453  * Description:
454  * Searches for a valid DOI definition and if one is found it is returned to
455  * the caller.  Otherwise NULL is returned.  The caller must ensure that
456  * calipso_doi_putdef() is called when the caller is done.
457  *
458  */
459 struct calipso_doi *calipso_doi_getdef(u32 doi)
460 {
461 	struct calipso_doi *ret_val = NULL;
462 	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
463 
464 	if (ops)
465 		ret_val = ops->doi_getdef(doi);
466 	return ret_val;
467 }
468 
469 /**
470  * calipso_doi_putdef - Releases a reference for the given DOI definition
471  * @doi_def: the DOI definition
472  *
473  * Description:
474  * Releases a DOI definition reference obtained from calipso_doi_getdef().
475  *
476  */
477 void calipso_doi_putdef(struct calipso_doi *doi_def)
478 {
479 	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
480 
481 	if (ops)
482 		ops->doi_putdef(doi_def);
483 }
484 
485 /**
486  * calipso_doi_walk - Iterate through the DOI definitions
487  * @skip_cnt: skip past this number of DOI definitions, updated
488  * @callback: callback for each DOI definition
489  * @cb_arg: argument for the callback function
490  *
491  * Description:
492  * Iterate over the DOI definition list, skipping the first @skip_cnt entries.
493  * For each entry call @callback, if @callback returns a negative value stop
494  * 'walking' through the list and return.  Updates the value in @skip_cnt upon
495  * return.  Returns zero on success, negative values on failure.
496  *
497  */
498 int calipso_doi_walk(u32 *skip_cnt,
499 		     int (*callback)(struct calipso_doi *doi_def, void *arg),
500 		     void *cb_arg)
501 {
502 	int ret_val = -ENOMSG;
503 	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
504 
505 	if (ops)
506 		ret_val = ops->doi_walk(skip_cnt, callback, cb_arg);
507 	return ret_val;
508 }
509 
510 /**
511  * calipso_sock_getattr - Get the security attributes from a sock
512  * @sk: the sock
513  * @secattr: the security attributes
514  *
515  * Description:
516  * Query @sk to see if there is a CALIPSO option attached to the sock and if
517  * there is return the CALIPSO security attributes in @secattr.  This function
518  * requires that @sk be locked, or privately held, but it does not do any
519  * locking itself.  Returns zero on success and negative values on failure.
520  *
521  */
522 int calipso_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
523 {
524 	int ret_val = -ENOMSG;
525 	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
526 
527 	if (ops)
528 		ret_val = ops->sock_getattr(sk, secattr);
529 	return ret_val;
530 }
531 
532 /**
533  * calipso_sock_setattr - Add a CALIPSO option to a socket
534  * @sk: the socket
535  * @doi_def: the CALIPSO DOI to use
536  * @secattr: the specific security attributes of the socket
537  *
538  * Description:
539  * Set the CALIPSO option on the given socket using the DOI definition and
540  * security attributes passed to the function.  This function requires
541  * exclusive access to @sk, which means it either needs to be in the
542  * process of being created or locked.  Returns zero on success and negative
543  * values on failure.
544  *
545  */
546 int calipso_sock_setattr(struct sock *sk,
547 			 const struct calipso_doi *doi_def,
548 			 const struct netlbl_lsm_secattr *secattr)
549 {
550 	int ret_val = -ENOMSG;
551 	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
552 
553 	if (ops)
554 		ret_val = ops->sock_setattr(sk, doi_def, secattr);
555 	return ret_val;
556 }
557 
558 /**
559  * calipso_sock_delattr - Delete the CALIPSO option from a socket
560  * @sk: the socket
561  *
562  * Description:
563  * Removes the CALIPSO option from a socket, if present.
564  *
565  */
566 void calipso_sock_delattr(struct sock *sk)
567 {
568 	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
569 
570 	if (ops)
571 		ops->sock_delattr(sk);
572 }
573 
574 /**
575  * calipso_req_setattr - Add a CALIPSO option to a connection request socket
576  * @req: the connection request socket
577  * @doi_def: the CALIPSO DOI to use
578  * @secattr: the specific security attributes of the socket
579  *
580  * Description:
581  * Set the CALIPSO option on the given socket using the DOI definition and
582  * security attributes passed to the function.  Returns zero on success and
583  * negative values on failure.
584  *
585  */
586 int calipso_req_setattr(struct request_sock *req,
587 			const struct calipso_doi *doi_def,
588 			const struct netlbl_lsm_secattr *secattr)
589 {
590 	int ret_val = -ENOMSG;
591 	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
592 
593 	if (ops)
594 		ret_val = ops->req_setattr(req, doi_def, secattr);
595 	return ret_val;
596 }
597 
598 /**
599  * calipso_req_delattr - Delete the CALIPSO option from a request socket
600  * @req: the request socket
601  *
602  * Description:
603  * Removes the CALIPSO option from a request socket, if present.
604  *
605  */
606 void calipso_req_delattr(struct request_sock *req)
607 {
608 	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
609 
610 	if (ops)
611 		ops->req_delattr(req);
612 }
613 
614 /**
615  * calipso_optptr - Find the CALIPSO option in the packet
616  * @skb: the packet
617  *
618  * Description:
619  * Parse the packet's IP header looking for a CALIPSO option.  Returns a pointer
620  * to the start of the CALIPSO option on success, NULL if one if not found.
621  *
622  */
623 unsigned char *calipso_optptr(const struct sk_buff *skb)
624 {
625 	unsigned char *ret_val = NULL;
626 	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
627 
628 	if (ops)
629 		ret_val = ops->skbuff_optptr(skb);
630 	return ret_val;
631 }
632 
633 /**
634  * calipso_getattr - Get the security attributes from a memory block.
635  * @calipso: the CALIPSO option
636  * @secattr: the security attributes
637  *
638  * Description:
639  * Inspect @calipso and return the security attributes in @secattr.
640  * Returns zero on success and negative values on failure.
641  *
642  */
643 int calipso_getattr(const unsigned char *calipso,
644 		    struct netlbl_lsm_secattr *secattr)
645 {
646 	int ret_val = -ENOMSG;
647 	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
648 
649 	if (ops)
650 		ret_val = ops->opt_getattr(calipso, secattr);
651 	return ret_val;
652 }
653 
654 /**
655  * calipso_skbuff_setattr - Set the CALIPSO option on a packet
656  * @skb: the packet
657  * @doi_def: the CALIPSO DOI to use
658  * @secattr: the security attributes
659  *
660  * Description:
661  * Set the CALIPSO option on the given packet based on the security attributes.
662  * Returns a pointer to the IP header on success and NULL on failure.
663  *
664  */
665 int calipso_skbuff_setattr(struct sk_buff *skb,
666 			   const struct calipso_doi *doi_def,
667 			   const struct netlbl_lsm_secattr *secattr)
668 {
669 	int ret_val = -ENOMSG;
670 	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
671 
672 	if (ops)
673 		ret_val = ops->skbuff_setattr(skb, doi_def, secattr);
674 	return ret_val;
675 }
676 
677 /**
678  * calipso_skbuff_delattr - Delete any CALIPSO options from a packet
679  * @skb: the packet
680  *
681  * Description:
682  * Removes any and all CALIPSO options from the given packet.  Returns zero on
683  * success, negative values on failure.
684  *
685  */
686 int calipso_skbuff_delattr(struct sk_buff *skb)
687 {
688 	int ret_val = -ENOMSG;
689 	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
690 
691 	if (ops)
692 		ret_val = ops->skbuff_delattr(skb);
693 	return ret_val;
694 }
695 
696 /**
697  * calipso_cache_invalidate - Invalidates the current CALIPSO cache
698  *
699  * Description:
700  * Invalidates and frees any entries in the CALIPSO cache.  Returns zero on
701  * success and negative values on failure.
702  *
703  */
704 void calipso_cache_invalidate(void)
705 {
706 	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
707 
708 	if (ops)
709 		ops->cache_invalidate();
710 }
711 
712 /**
713  * calipso_cache_add - Add an entry to the CALIPSO cache
714  * @calipso_ptr: the CALIPSO option
715  * @secattr: the packet's security attributes
716  *
717  * Description:
718  * Add a new entry into the CALIPSO label mapping cache.
719  * Returns zero on success, negative values on failure.
720  *
721  */
722 int calipso_cache_add(const unsigned char *calipso_ptr,
723 		      const struct netlbl_lsm_secattr *secattr)
724 
725 {
726 	int ret_val = -ENOMSG;
727 	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
728 
729 	if (ops)
730 		ret_val = ops->cache_add(calipso_ptr, secattr);
731 	return ret_val;
732 }
733