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(size: 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(nla: 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: &audit_info); |
109 | switch (nla_get_u32(nla: info->attrs[NLBL_CALIPSO_A_MTYPE])) { |
110 | case CALIPSO_MAP_PASS: |
111 | ret_val = netlbl_calipso_add_pass(info, audit_info: &audit_info); |
112 | break; |
113 | } |
114 | if (ret_val == 0) |
115 | atomic_inc(v: &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(nla: 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(skb: ans_skb, info, family: &netlbl_calipso_gnl_family, |
157 | flags: 0, cmd: NLBL_CALIPSO_C_LIST); |
158 | if (!data) { |
159 | ret_val = -ENOMEM; |
160 | goto list_failure_put; |
161 | } |
162 | |
163 | ret_val = nla_put_u32(skb: ans_skb, attrtype: NLBL_CALIPSO_A_MTYPE, value: doi_def->type); |
164 | if (ret_val != 0) |
165 | goto list_failure_put; |
166 | |
167 | calipso_doi_putdef(doi_def); |
168 | |
169 | genlmsg_end(skb: ans_skb, hdr: data); |
170 | return genlmsg_reply(skb: ans_skb, info); |
171 | |
172 | list_failure_put: |
173 | calipso_doi_putdef(doi_def); |
174 | list_failure: |
175 | kfree_skb(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(skb: cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).portid, |
198 | seq: cb_arg->seq, family: &netlbl_calipso_gnl_family, |
199 | NLM_F_MULTI, cmd: NLBL_CALIPSO_C_LISTALL); |
200 | if (!data) |
201 | goto listall_cb_failure; |
202 | |
203 | ret_val = nla_put_u32(skb: cb_arg->skb, attrtype: NLBL_CALIPSO_A_DOI, value: doi_def->doi); |
204 | if (ret_val != 0) |
205 | goto listall_cb_failure; |
206 | ret_val = nla_put_u32(skb: cb_arg->skb, |
207 | attrtype: NLBL_CALIPSO_A_MTYPE, |
208 | value: doi_def->type); |
209 | if (ret_val != 0) |
210 | goto listall_cb_failure; |
211 | |
212 | genlmsg_end(skb: cb_arg->skb, hdr: data); |
213 | return 0; |
214 | |
215 | listall_cb_failure: |
216 | genlmsg_cancel(skb: cb_arg->skb, hdr: 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(skip_cnt: &doi_skip, callback: netlbl_calipso_listall_cb, cb_arg: &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, audit_info: 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: &audit_info); |
291 | cb_arg.doi = nla_get_u32(nla: info->attrs[NLBL_CALIPSO_A_DOI]); |
292 | cb_arg.audit_info = &audit_info; |
293 | ret_val = netlbl_domhsh_walk(skip_bkt: &skip_bkt, skip_chain: &skip_chain, |
294 | callback: netlbl_calipso_remove_cb, cb_arg: &cb_arg); |
295 | if (ret_val == 0 || ret_val == -ENOENT) { |
296 | ret_val = calipso_doi_remove(doi: cb_arg.doi, audit_info: &audit_info); |
297 | if (ret_val == 0) |
298 | atomic_dec(v: &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(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 | |