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