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