Merge branch 'work.iov_iter' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[platform/kernel/linux-starfive.git] / net / netlabel / netlabel_calipso.c
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 };
348
349 /* NetLabel Generic NETLINK Protocol Functions
350  */
351
352 /**
353  * netlbl_calipso_genl_init - Register the CALIPSO NetLabel component
354  *
355  * Description:
356  * Register the CALIPSO packet NetLabel component with the Generic NETLINK
357  * mechanism.  Returns zero on success, negative values on failure.
358  *
359  */
360 int __init netlbl_calipso_genl_init(void)
361 {
362         return genl_register_family(&netlbl_calipso_gnl_family);
363 }
364
365 static const struct netlbl_calipso_ops *calipso_ops;
366
367 /**
368  * netlbl_calipso_ops_register - Register the CALIPSO operations
369  * @ops: ops to register
370  *
371  * Description:
372  * Register the CALIPSO packet engine operations.
373  *
374  */
375 const struct netlbl_calipso_ops *
376 netlbl_calipso_ops_register(const struct netlbl_calipso_ops *ops)
377 {
378         return xchg(&calipso_ops, ops);
379 }
380 EXPORT_SYMBOL(netlbl_calipso_ops_register);
381
382 static const struct netlbl_calipso_ops *netlbl_calipso_ops_get(void)
383 {
384         return READ_ONCE(calipso_ops);
385 }
386
387 /**
388  * calipso_doi_add - Add a new DOI to the CALIPSO protocol engine
389  * @doi_def: the DOI structure
390  * @audit_info: NetLabel audit information
391  *
392  * Description:
393  * The caller defines a new DOI for use by the CALIPSO engine and calls this
394  * function to add it to the list of acceptable domains.  The caller must
395  * ensure that the mapping table specified in @doi_def->map meets all of the
396  * requirements of the mapping type (see calipso.h for details).  Returns
397  * zero on success and non-zero on failure.
398  *
399  */
400 int calipso_doi_add(struct calipso_doi *doi_def,
401                     struct netlbl_audit *audit_info)
402 {
403         int ret_val = -ENOMSG;
404         const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
405
406         if (ops)
407                 ret_val = ops->doi_add(doi_def, audit_info);
408         return ret_val;
409 }
410
411 /**
412  * calipso_doi_free - Frees a DOI definition
413  * @doi_def: the DOI definition
414  *
415  * Description:
416  * This function frees all of the memory associated with a DOI definition.
417  *
418  */
419 void calipso_doi_free(struct calipso_doi *doi_def)
420 {
421         const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
422
423         if (ops)
424                 ops->doi_free(doi_def);
425 }
426
427 /**
428  * calipso_doi_remove - Remove an existing DOI from the CALIPSO protocol engine
429  * @doi: the DOI value
430  * @audit_info: NetLabel audit information
431  *
432  * Description:
433  * Removes a DOI definition from the CALIPSO engine.  The NetLabel routines will
434  * be called to release their own LSM domain mappings as well as our own
435  * domain list.  Returns zero on success and negative values on failure.
436  *
437  */
438 int calipso_doi_remove(u32 doi, struct netlbl_audit *audit_info)
439 {
440         int ret_val = -ENOMSG;
441         const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
442
443         if (ops)
444                 ret_val = ops->doi_remove(doi, audit_info);
445         return ret_val;
446 }
447
448 /**
449  * calipso_doi_getdef - Returns a reference to a valid DOI definition
450  * @doi: the DOI value
451  *
452  * Description:
453  * Searches for a valid DOI definition and if one is found it is returned to
454  * the caller.  Otherwise NULL is returned.  The caller must ensure that
455  * calipso_doi_putdef() is called when the caller is done.
456  *
457  */
458 struct calipso_doi *calipso_doi_getdef(u32 doi)
459 {
460         struct calipso_doi *ret_val = NULL;
461         const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
462
463         if (ops)
464                 ret_val = ops->doi_getdef(doi);
465         return ret_val;
466 }
467
468 /**
469  * calipso_doi_putdef - Releases a reference for the given DOI definition
470  * @doi_def: the DOI definition
471  *
472  * Description:
473  * Releases a DOI definition reference obtained from calipso_doi_getdef().
474  *
475  */
476 void calipso_doi_putdef(struct calipso_doi *doi_def)
477 {
478         const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
479
480         if (ops)
481                 ops->doi_putdef(doi_def);
482 }
483
484 /**
485  * calipso_doi_walk - Iterate through the DOI definitions
486  * @skip_cnt: skip past this number of DOI definitions, updated
487  * @callback: callback for each DOI definition
488  * @cb_arg: argument for the callback function
489  *
490  * Description:
491  * Iterate over the DOI definition list, skipping the first @skip_cnt entries.
492  * For each entry call @callback, if @callback returns a negative value stop
493  * 'walking' through the list and return.  Updates the value in @skip_cnt upon
494  * return.  Returns zero on success, negative values on failure.
495  *
496  */
497 int calipso_doi_walk(u32 *skip_cnt,
498                      int (*callback)(struct calipso_doi *doi_def, void *arg),
499                      void *cb_arg)
500 {
501         int ret_val = -ENOMSG;
502         const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
503
504         if (ops)
505                 ret_val = ops->doi_walk(skip_cnt, callback, cb_arg);
506         return ret_val;
507 }
508
509 /**
510  * calipso_sock_getattr - Get the security attributes from a sock
511  * @sk: the sock
512  * @secattr: the security attributes
513  *
514  * Description:
515  * Query @sk to see if there is a CALIPSO option attached to the sock and if
516  * there is return the CALIPSO security attributes in @secattr.  This function
517  * requires that @sk be locked, or privately held, but it does not do any
518  * locking itself.  Returns zero on success and negative values on failure.
519  *
520  */
521 int calipso_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
522 {
523         int ret_val = -ENOMSG;
524         const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
525
526         if (ops)
527                 ret_val = ops->sock_getattr(sk, secattr);
528         return ret_val;
529 }
530
531 /**
532  * calipso_sock_setattr - Add a CALIPSO option to a socket
533  * @sk: the socket
534  * @doi_def: the CALIPSO DOI to use
535  * @secattr: the specific security attributes of the socket
536  *
537  * Description:
538  * Set the CALIPSO option on the given socket using the DOI definition and
539  * security attributes passed to the function.  This function requires
540  * exclusive access to @sk, which means it either needs to be in the
541  * process of being created or locked.  Returns zero on success and negative
542  * values on failure.
543  *
544  */
545 int calipso_sock_setattr(struct sock *sk,
546                          const struct calipso_doi *doi_def,
547                          const struct netlbl_lsm_secattr *secattr)
548 {
549         int ret_val = -ENOMSG;
550         const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
551
552         if (ops)
553                 ret_val = ops->sock_setattr(sk, doi_def, secattr);
554         return ret_val;
555 }
556
557 /**
558  * calipso_sock_delattr - Delete the CALIPSO option from a socket
559  * @sk: the socket
560  *
561  * Description:
562  * Removes the CALIPSO option from a socket, if present.
563  *
564  */
565 void calipso_sock_delattr(struct sock *sk)
566 {
567         const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
568
569         if (ops)
570                 ops->sock_delattr(sk);
571 }
572
573 /**
574  * calipso_req_setattr - Add a CALIPSO option to a connection request socket
575  * @req: the connection request socket
576  * @doi_def: the CALIPSO DOI to use
577  * @secattr: the specific security attributes of the socket
578  *
579  * Description:
580  * Set the CALIPSO option on the given socket using the DOI definition and
581  * security attributes passed to the function.  Returns zero on success and
582  * negative values on failure.
583  *
584  */
585 int calipso_req_setattr(struct request_sock *req,
586                         const struct calipso_doi *doi_def,
587                         const struct netlbl_lsm_secattr *secattr)
588 {
589         int ret_val = -ENOMSG;
590         const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
591
592         if (ops)
593                 ret_val = ops->req_setattr(req, doi_def, secattr);
594         return ret_val;
595 }
596
597 /**
598  * calipso_req_delattr - Delete the CALIPSO option from a request socket
599  * @req: the request socket
600  *
601  * Description:
602  * Removes the CALIPSO option from a request socket, if present.
603  *
604  */
605 void calipso_req_delattr(struct request_sock *req)
606 {
607         const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
608
609         if (ops)
610                 ops->req_delattr(req);
611 }
612
613 /**
614  * calipso_optptr - Find the CALIPSO option in the packet
615  * @skb: the packet
616  *
617  * Description:
618  * Parse the packet's IP header looking for a CALIPSO option.  Returns a pointer
619  * to the start of the CALIPSO option on success, NULL if one if not found.
620  *
621  */
622 unsigned char *calipso_optptr(const struct sk_buff *skb)
623 {
624         unsigned char *ret_val = NULL;
625         const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
626
627         if (ops)
628                 ret_val = ops->skbuff_optptr(skb);
629         return ret_val;
630 }
631
632 /**
633  * calipso_getattr - Get the security attributes from a memory block.
634  * @calipso: the CALIPSO option
635  * @secattr: the security attributes
636  *
637  * Description:
638  * Inspect @calipso and return the security attributes in @secattr.
639  * Returns zero on success and negative values on failure.
640  *
641  */
642 int calipso_getattr(const unsigned char *calipso,
643                     struct netlbl_lsm_secattr *secattr)
644 {
645         int ret_val = -ENOMSG;
646         const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
647
648         if (ops)
649                 ret_val = ops->opt_getattr(calipso, secattr);
650         return ret_val;
651 }
652
653 /**
654  * calipso_skbuff_setattr - Set the CALIPSO option on a packet
655  * @skb: the packet
656  * @doi_def: the CALIPSO DOI to use
657  * @secattr: the security attributes
658  *
659  * Description:
660  * Set the CALIPSO option on the given packet based on the security attributes.
661  * Returns a pointer to the IP header on success and NULL on failure.
662  *
663  */
664 int calipso_skbuff_setattr(struct sk_buff *skb,
665                            const struct calipso_doi *doi_def,
666                            const struct netlbl_lsm_secattr *secattr)
667 {
668         int ret_val = -ENOMSG;
669         const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
670
671         if (ops)
672                 ret_val = ops->skbuff_setattr(skb, doi_def, secattr);
673         return ret_val;
674 }
675
676 /**
677  * calipso_skbuff_delattr - Delete any CALIPSO options from a packet
678  * @skb: the packet
679  *
680  * Description:
681  * Removes any and all CALIPSO options from the given packet.  Returns zero on
682  * success, negative values on failure.
683  *
684  */
685 int calipso_skbuff_delattr(struct sk_buff *skb)
686 {
687         int ret_val = -ENOMSG;
688         const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
689
690         if (ops)
691                 ret_val = ops->skbuff_delattr(skb);
692         return ret_val;
693 }
694
695 /**
696  * calipso_cache_invalidate - Invalidates the current CALIPSO cache
697  *
698  * Description:
699  * Invalidates and frees any entries in the CALIPSO cache.  Returns zero on
700  * success and negative values on failure.
701  *
702  */
703 void calipso_cache_invalidate(void)
704 {
705         const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
706
707         if (ops)
708                 ops->cache_invalidate();
709 }
710
711 /**
712  * calipso_cache_add - Add an entry to the CALIPSO cache
713  * @calipso_ptr: the CALIPSO option
714  * @secattr: the packet's security attributes
715  *
716  * Description:
717  * Add a new entry into the CALIPSO label mapping cache.
718  * Returns zero on success, negative values on failure.
719  *
720  */
721 int calipso_cache_add(const unsigned char *calipso_ptr,
722                       const struct netlbl_lsm_secattr *secattr)
723
724 {
725         int ret_val = -ENOMSG;
726         const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
727
728         if (ops)
729                 ret_val = ops->cache_add(calipso_ptr, secattr);
730         return ret_val;
731 }