162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * NetLabel CALIPSO/IPv6 Support
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * This file defines the CALIPSO/IPv6 functions for the NetLabel system.  The
662306a36Sopenharmony_ci * NetLabel system manages static and dynamic label mappings for network
762306a36Sopenharmony_ci * protocols such as CIPSO and CALIPSO.
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * Authors: Paul Moore <paul@paul-moore.com>
1062306a36Sopenharmony_ci *          Huw Davies <huw@codeweavers.com>
1162306a36Sopenharmony_ci */
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci/* (c) Copyright Hewlett-Packard Development Company, L.P., 2006
1462306a36Sopenharmony_ci * (c) Copyright Huw Davies <huw@codeweavers.com>, 2015
1562306a36Sopenharmony_ci */
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#include <linux/types.h>
1862306a36Sopenharmony_ci#include <linux/socket.h>
1962306a36Sopenharmony_ci#include <linux/string.h>
2062306a36Sopenharmony_ci#include <linux/skbuff.h>
2162306a36Sopenharmony_ci#include <linux/audit.h>
2262306a36Sopenharmony_ci#include <linux/slab.h>
2362306a36Sopenharmony_ci#include <net/sock.h>
2462306a36Sopenharmony_ci#include <net/netlink.h>
2562306a36Sopenharmony_ci#include <net/genetlink.h>
2662306a36Sopenharmony_ci#include <net/netlabel.h>
2762306a36Sopenharmony_ci#include <net/calipso.h>
2862306a36Sopenharmony_ci#include <linux/atomic.h>
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci#include "netlabel_user.h"
3162306a36Sopenharmony_ci#include "netlabel_calipso.h"
3262306a36Sopenharmony_ci#include "netlabel_mgmt.h"
3362306a36Sopenharmony_ci#include "netlabel_domainhash.h"
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci/* Argument struct for calipso_doi_walk() */
3662306a36Sopenharmony_cistruct netlbl_calipso_doiwalk_arg {
3762306a36Sopenharmony_ci	struct netlink_callback *nl_cb;
3862306a36Sopenharmony_ci	struct sk_buff *skb;
3962306a36Sopenharmony_ci	u32 seq;
4062306a36Sopenharmony_ci};
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci/* Argument struct for netlbl_domhsh_walk() */
4362306a36Sopenharmony_cistruct netlbl_domhsh_walk_arg {
4462306a36Sopenharmony_ci	struct netlbl_audit *audit_info;
4562306a36Sopenharmony_ci	u32 doi;
4662306a36Sopenharmony_ci};
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci/* NetLabel Generic NETLINK CALIPSO family */
4962306a36Sopenharmony_cistatic struct genl_family netlbl_calipso_gnl_family;
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci/* NetLabel Netlink attribute policy */
5262306a36Sopenharmony_cistatic const struct nla_policy calipso_genl_policy[NLBL_CALIPSO_A_MAX + 1] = {
5362306a36Sopenharmony_ci	[NLBL_CALIPSO_A_DOI] = { .type = NLA_U32 },
5462306a36Sopenharmony_ci	[NLBL_CALIPSO_A_MTYPE] = { .type = NLA_U32 },
5562306a36Sopenharmony_ci};
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_cistatic const struct netlbl_calipso_ops *calipso_ops;
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci/**
6062306a36Sopenharmony_ci * netlbl_calipso_ops_register - Register the CALIPSO operations
6162306a36Sopenharmony_ci * @ops: ops to register
6262306a36Sopenharmony_ci *
6362306a36Sopenharmony_ci * Description:
6462306a36Sopenharmony_ci * Register the CALIPSO packet engine operations.
6562306a36Sopenharmony_ci *
6662306a36Sopenharmony_ci */
6762306a36Sopenharmony_ciconst struct netlbl_calipso_ops *
6862306a36Sopenharmony_cinetlbl_calipso_ops_register(const struct netlbl_calipso_ops *ops)
6962306a36Sopenharmony_ci{
7062306a36Sopenharmony_ci	return xchg(&calipso_ops, ops);
7162306a36Sopenharmony_ci}
7262306a36Sopenharmony_ciEXPORT_SYMBOL(netlbl_calipso_ops_register);
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_cistatic const struct netlbl_calipso_ops *netlbl_calipso_ops_get(void)
7562306a36Sopenharmony_ci{
7662306a36Sopenharmony_ci	return READ_ONCE(calipso_ops);
7762306a36Sopenharmony_ci}
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci/* NetLabel Command Handlers
8062306a36Sopenharmony_ci */
8162306a36Sopenharmony_ci/**
8262306a36Sopenharmony_ci * netlbl_calipso_add_pass - Adds a CALIPSO pass DOI definition
8362306a36Sopenharmony_ci * @info: the Generic NETLINK info block
8462306a36Sopenharmony_ci * @audit_info: NetLabel audit information
8562306a36Sopenharmony_ci *
8662306a36Sopenharmony_ci * Description:
8762306a36Sopenharmony_ci * Create a new CALIPSO_MAP_PASS DOI definition based on the given ADD message
8862306a36Sopenharmony_ci * and add it to the CALIPSO engine.  Return zero on success and non-zero on
8962306a36Sopenharmony_ci * error.
9062306a36Sopenharmony_ci *
9162306a36Sopenharmony_ci */
9262306a36Sopenharmony_cistatic int netlbl_calipso_add_pass(struct genl_info *info,
9362306a36Sopenharmony_ci				   struct netlbl_audit *audit_info)
9462306a36Sopenharmony_ci{
9562306a36Sopenharmony_ci	int ret_val;
9662306a36Sopenharmony_ci	struct calipso_doi *doi_def = NULL;
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL);
9962306a36Sopenharmony_ci	if (!doi_def)
10062306a36Sopenharmony_ci		return -ENOMEM;
10162306a36Sopenharmony_ci	doi_def->type = CALIPSO_MAP_PASS;
10262306a36Sopenharmony_ci	doi_def->doi = nla_get_u32(info->attrs[NLBL_CALIPSO_A_DOI]);
10362306a36Sopenharmony_ci	ret_val = calipso_doi_add(doi_def, audit_info);
10462306a36Sopenharmony_ci	if (ret_val != 0)
10562306a36Sopenharmony_ci		calipso_doi_free(doi_def);
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	return ret_val;
10862306a36Sopenharmony_ci}
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci/**
11162306a36Sopenharmony_ci * netlbl_calipso_add - Handle an ADD message
11262306a36Sopenharmony_ci * @skb: the NETLINK buffer
11362306a36Sopenharmony_ci * @info: the Generic NETLINK info block
11462306a36Sopenharmony_ci *
11562306a36Sopenharmony_ci * Description:
11662306a36Sopenharmony_ci * Create a new DOI definition based on the given ADD message and add it to the
11762306a36Sopenharmony_ci * CALIPSO engine.  Returns zero on success, negative values on failure.
11862306a36Sopenharmony_ci *
11962306a36Sopenharmony_ci */
12062306a36Sopenharmony_cistatic int netlbl_calipso_add(struct sk_buff *skb, struct genl_info *info)
12162306a36Sopenharmony_ci{
12262306a36Sopenharmony_ci	int ret_val = -EINVAL;
12362306a36Sopenharmony_ci	struct netlbl_audit audit_info;
12462306a36Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	if (!info->attrs[NLBL_CALIPSO_A_DOI] ||
12762306a36Sopenharmony_ci	    !info->attrs[NLBL_CALIPSO_A_MTYPE])
12862306a36Sopenharmony_ci		return -EINVAL;
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci	if (!ops)
13162306a36Sopenharmony_ci		return -EOPNOTSUPP;
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	netlbl_netlink_auditinfo(&audit_info);
13462306a36Sopenharmony_ci	switch (nla_get_u32(info->attrs[NLBL_CALIPSO_A_MTYPE])) {
13562306a36Sopenharmony_ci	case CALIPSO_MAP_PASS:
13662306a36Sopenharmony_ci		ret_val = netlbl_calipso_add_pass(info, &audit_info);
13762306a36Sopenharmony_ci		break;
13862306a36Sopenharmony_ci	}
13962306a36Sopenharmony_ci	if (ret_val == 0)
14062306a36Sopenharmony_ci		atomic_inc(&netlabel_mgmt_protocount);
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci	return ret_val;
14362306a36Sopenharmony_ci}
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci/**
14662306a36Sopenharmony_ci * netlbl_calipso_list - Handle a LIST message
14762306a36Sopenharmony_ci * @skb: the NETLINK buffer
14862306a36Sopenharmony_ci * @info: the Generic NETLINK info block
14962306a36Sopenharmony_ci *
15062306a36Sopenharmony_ci * Description:
15162306a36Sopenharmony_ci * Process a user generated LIST message and respond accordingly.
15262306a36Sopenharmony_ci * Returns zero on success and negative values on error.
15362306a36Sopenharmony_ci *
15462306a36Sopenharmony_ci */
15562306a36Sopenharmony_cistatic int netlbl_calipso_list(struct sk_buff *skb, struct genl_info *info)
15662306a36Sopenharmony_ci{
15762306a36Sopenharmony_ci	int ret_val;
15862306a36Sopenharmony_ci	struct sk_buff *ans_skb = NULL;
15962306a36Sopenharmony_ci	void *data;
16062306a36Sopenharmony_ci	u32 doi;
16162306a36Sopenharmony_ci	struct calipso_doi *doi_def;
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci	if (!info->attrs[NLBL_CALIPSO_A_DOI]) {
16462306a36Sopenharmony_ci		ret_val = -EINVAL;
16562306a36Sopenharmony_ci		goto list_failure;
16662306a36Sopenharmony_ci	}
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	doi = nla_get_u32(info->attrs[NLBL_CALIPSO_A_DOI]);
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci	doi_def = calipso_doi_getdef(doi);
17162306a36Sopenharmony_ci	if (!doi_def) {
17262306a36Sopenharmony_ci		ret_val = -EINVAL;
17362306a36Sopenharmony_ci		goto list_failure;
17462306a36Sopenharmony_ci	}
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
17762306a36Sopenharmony_ci	if (!ans_skb) {
17862306a36Sopenharmony_ci		ret_val = -ENOMEM;
17962306a36Sopenharmony_ci		goto list_failure_put;
18062306a36Sopenharmony_ci	}
18162306a36Sopenharmony_ci	data = genlmsg_put_reply(ans_skb, info, &netlbl_calipso_gnl_family,
18262306a36Sopenharmony_ci				 0, NLBL_CALIPSO_C_LIST);
18362306a36Sopenharmony_ci	if (!data) {
18462306a36Sopenharmony_ci		ret_val = -ENOMEM;
18562306a36Sopenharmony_ci		goto list_failure_put;
18662306a36Sopenharmony_ci	}
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci	ret_val = nla_put_u32(ans_skb, NLBL_CALIPSO_A_MTYPE, doi_def->type);
18962306a36Sopenharmony_ci	if (ret_val != 0)
19062306a36Sopenharmony_ci		goto list_failure_put;
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci	calipso_doi_putdef(doi_def);
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci	genlmsg_end(ans_skb, data);
19562306a36Sopenharmony_ci	return genlmsg_reply(ans_skb, info);
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_cilist_failure_put:
19862306a36Sopenharmony_ci	calipso_doi_putdef(doi_def);
19962306a36Sopenharmony_cilist_failure:
20062306a36Sopenharmony_ci	kfree_skb(ans_skb);
20162306a36Sopenharmony_ci	return ret_val;
20262306a36Sopenharmony_ci}
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci/**
20562306a36Sopenharmony_ci * netlbl_calipso_listall_cb - calipso_doi_walk() callback for LISTALL
20662306a36Sopenharmony_ci * @doi_def: the CALIPSO DOI definition
20762306a36Sopenharmony_ci * @arg: the netlbl_calipso_doiwalk_arg structure
20862306a36Sopenharmony_ci *
20962306a36Sopenharmony_ci * Description:
21062306a36Sopenharmony_ci * This function is designed to be used as a callback to the
21162306a36Sopenharmony_ci * calipso_doi_walk() function for use in generating a response for a LISTALL
21262306a36Sopenharmony_ci * message.  Returns the size of the message on success, negative values on
21362306a36Sopenharmony_ci * failure.
21462306a36Sopenharmony_ci *
21562306a36Sopenharmony_ci */
21662306a36Sopenharmony_cistatic int netlbl_calipso_listall_cb(struct calipso_doi *doi_def, void *arg)
21762306a36Sopenharmony_ci{
21862306a36Sopenharmony_ci	int ret_val = -ENOMEM;
21962306a36Sopenharmony_ci	struct netlbl_calipso_doiwalk_arg *cb_arg = arg;
22062306a36Sopenharmony_ci	void *data;
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci	data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).portid,
22362306a36Sopenharmony_ci			   cb_arg->seq, &netlbl_calipso_gnl_family,
22462306a36Sopenharmony_ci			   NLM_F_MULTI, NLBL_CALIPSO_C_LISTALL);
22562306a36Sopenharmony_ci	if (!data)
22662306a36Sopenharmony_ci		goto listall_cb_failure;
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci	ret_val = nla_put_u32(cb_arg->skb, NLBL_CALIPSO_A_DOI, doi_def->doi);
22962306a36Sopenharmony_ci	if (ret_val != 0)
23062306a36Sopenharmony_ci		goto listall_cb_failure;
23162306a36Sopenharmony_ci	ret_val = nla_put_u32(cb_arg->skb,
23262306a36Sopenharmony_ci			      NLBL_CALIPSO_A_MTYPE,
23362306a36Sopenharmony_ci			      doi_def->type);
23462306a36Sopenharmony_ci	if (ret_val != 0)
23562306a36Sopenharmony_ci		goto listall_cb_failure;
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	genlmsg_end(cb_arg->skb, data);
23862306a36Sopenharmony_ci	return 0;
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_cilistall_cb_failure:
24162306a36Sopenharmony_ci	genlmsg_cancel(cb_arg->skb, data);
24262306a36Sopenharmony_ci	return ret_val;
24362306a36Sopenharmony_ci}
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ci/**
24662306a36Sopenharmony_ci * netlbl_calipso_listall - Handle a LISTALL message
24762306a36Sopenharmony_ci * @skb: the NETLINK buffer
24862306a36Sopenharmony_ci * @cb: the NETLINK callback
24962306a36Sopenharmony_ci *
25062306a36Sopenharmony_ci * Description:
25162306a36Sopenharmony_ci * Process a user generated LISTALL message and respond accordingly.  Returns
25262306a36Sopenharmony_ci * zero on success and negative values on error.
25362306a36Sopenharmony_ci *
25462306a36Sopenharmony_ci */
25562306a36Sopenharmony_cistatic int netlbl_calipso_listall(struct sk_buff *skb,
25662306a36Sopenharmony_ci				  struct netlink_callback *cb)
25762306a36Sopenharmony_ci{
25862306a36Sopenharmony_ci	struct netlbl_calipso_doiwalk_arg cb_arg;
25962306a36Sopenharmony_ci	u32 doi_skip = cb->args[0];
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci	cb_arg.nl_cb = cb;
26262306a36Sopenharmony_ci	cb_arg.skb = skb;
26362306a36Sopenharmony_ci	cb_arg.seq = cb->nlh->nlmsg_seq;
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci	calipso_doi_walk(&doi_skip, netlbl_calipso_listall_cb, &cb_arg);
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci	cb->args[0] = doi_skip;
26862306a36Sopenharmony_ci	return skb->len;
26962306a36Sopenharmony_ci}
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci/**
27262306a36Sopenharmony_ci * netlbl_calipso_remove_cb - netlbl_calipso_remove() callback for REMOVE
27362306a36Sopenharmony_ci * @entry: LSM domain mapping entry
27462306a36Sopenharmony_ci * @arg: the netlbl_domhsh_walk_arg structure
27562306a36Sopenharmony_ci *
27662306a36Sopenharmony_ci * Description:
27762306a36Sopenharmony_ci * This function is intended for use by netlbl_calipso_remove() as the callback
27862306a36Sopenharmony_ci * for the netlbl_domhsh_walk() function; it removes LSM domain map entries
27962306a36Sopenharmony_ci * which are associated with the CALIPSO DOI specified in @arg.  Returns zero on
28062306a36Sopenharmony_ci * success, negative values on failure.
28162306a36Sopenharmony_ci *
28262306a36Sopenharmony_ci */
28362306a36Sopenharmony_cistatic int netlbl_calipso_remove_cb(struct netlbl_dom_map *entry, void *arg)
28462306a36Sopenharmony_ci{
28562306a36Sopenharmony_ci	struct netlbl_domhsh_walk_arg *cb_arg = arg;
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci	if (entry->def.type == NETLBL_NLTYPE_CALIPSO &&
28862306a36Sopenharmony_ci	    entry->def.calipso->doi == cb_arg->doi)
28962306a36Sopenharmony_ci		return netlbl_domhsh_remove_entry(entry, cb_arg->audit_info);
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci	return 0;
29262306a36Sopenharmony_ci}
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci/**
29562306a36Sopenharmony_ci * netlbl_calipso_remove - Handle a REMOVE message
29662306a36Sopenharmony_ci * @skb: the NETLINK buffer
29762306a36Sopenharmony_ci * @info: the Generic NETLINK info block
29862306a36Sopenharmony_ci *
29962306a36Sopenharmony_ci * Description:
30062306a36Sopenharmony_ci * Process a user generated REMOVE message and respond accordingly.  Returns
30162306a36Sopenharmony_ci * zero on success, negative values on failure.
30262306a36Sopenharmony_ci *
30362306a36Sopenharmony_ci */
30462306a36Sopenharmony_cistatic int netlbl_calipso_remove(struct sk_buff *skb, struct genl_info *info)
30562306a36Sopenharmony_ci{
30662306a36Sopenharmony_ci	int ret_val = -EINVAL;
30762306a36Sopenharmony_ci	struct netlbl_domhsh_walk_arg cb_arg;
30862306a36Sopenharmony_ci	struct netlbl_audit audit_info;
30962306a36Sopenharmony_ci	u32 skip_bkt = 0;
31062306a36Sopenharmony_ci	u32 skip_chain = 0;
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci	if (!info->attrs[NLBL_CALIPSO_A_DOI])
31362306a36Sopenharmony_ci		return -EINVAL;
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	netlbl_netlink_auditinfo(&audit_info);
31662306a36Sopenharmony_ci	cb_arg.doi = nla_get_u32(info->attrs[NLBL_CALIPSO_A_DOI]);
31762306a36Sopenharmony_ci	cb_arg.audit_info = &audit_info;
31862306a36Sopenharmony_ci	ret_val = netlbl_domhsh_walk(&skip_bkt, &skip_chain,
31962306a36Sopenharmony_ci				     netlbl_calipso_remove_cb, &cb_arg);
32062306a36Sopenharmony_ci	if (ret_val == 0 || ret_val == -ENOENT) {
32162306a36Sopenharmony_ci		ret_val = calipso_doi_remove(cb_arg.doi, &audit_info);
32262306a36Sopenharmony_ci		if (ret_val == 0)
32362306a36Sopenharmony_ci			atomic_dec(&netlabel_mgmt_protocount);
32462306a36Sopenharmony_ci	}
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci	return ret_val;
32762306a36Sopenharmony_ci}
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci/* NetLabel Generic NETLINK Command Definitions
33062306a36Sopenharmony_ci */
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_cistatic const struct genl_small_ops netlbl_calipso_ops[] = {
33362306a36Sopenharmony_ci	{
33462306a36Sopenharmony_ci	.cmd = NLBL_CALIPSO_C_ADD,
33562306a36Sopenharmony_ci	.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
33662306a36Sopenharmony_ci	.flags = GENL_ADMIN_PERM,
33762306a36Sopenharmony_ci	.doit = netlbl_calipso_add,
33862306a36Sopenharmony_ci	.dumpit = NULL,
33962306a36Sopenharmony_ci	},
34062306a36Sopenharmony_ci	{
34162306a36Sopenharmony_ci	.cmd = NLBL_CALIPSO_C_REMOVE,
34262306a36Sopenharmony_ci	.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
34362306a36Sopenharmony_ci	.flags = GENL_ADMIN_PERM,
34462306a36Sopenharmony_ci	.doit = netlbl_calipso_remove,
34562306a36Sopenharmony_ci	.dumpit = NULL,
34662306a36Sopenharmony_ci	},
34762306a36Sopenharmony_ci	{
34862306a36Sopenharmony_ci	.cmd = NLBL_CALIPSO_C_LIST,
34962306a36Sopenharmony_ci	.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
35062306a36Sopenharmony_ci	.flags = 0,
35162306a36Sopenharmony_ci	.doit = netlbl_calipso_list,
35262306a36Sopenharmony_ci	.dumpit = NULL,
35362306a36Sopenharmony_ci	},
35462306a36Sopenharmony_ci	{
35562306a36Sopenharmony_ci	.cmd = NLBL_CALIPSO_C_LISTALL,
35662306a36Sopenharmony_ci	.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
35762306a36Sopenharmony_ci	.flags = 0,
35862306a36Sopenharmony_ci	.doit = NULL,
35962306a36Sopenharmony_ci	.dumpit = netlbl_calipso_listall,
36062306a36Sopenharmony_ci	},
36162306a36Sopenharmony_ci};
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_cistatic struct genl_family netlbl_calipso_gnl_family __ro_after_init = {
36462306a36Sopenharmony_ci	.hdrsize = 0,
36562306a36Sopenharmony_ci	.name = NETLBL_NLTYPE_CALIPSO_NAME,
36662306a36Sopenharmony_ci	.version = NETLBL_PROTO_VERSION,
36762306a36Sopenharmony_ci	.maxattr = NLBL_CALIPSO_A_MAX,
36862306a36Sopenharmony_ci	.policy = calipso_genl_policy,
36962306a36Sopenharmony_ci	.module = THIS_MODULE,
37062306a36Sopenharmony_ci	.small_ops = netlbl_calipso_ops,
37162306a36Sopenharmony_ci	.n_small_ops = ARRAY_SIZE(netlbl_calipso_ops),
37262306a36Sopenharmony_ci	.resv_start_op = NLBL_CALIPSO_C_LISTALL + 1,
37362306a36Sopenharmony_ci};
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_ci/* NetLabel Generic NETLINK Protocol Functions
37662306a36Sopenharmony_ci */
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_ci/**
37962306a36Sopenharmony_ci * netlbl_calipso_genl_init - Register the CALIPSO NetLabel component
38062306a36Sopenharmony_ci *
38162306a36Sopenharmony_ci * Description:
38262306a36Sopenharmony_ci * Register the CALIPSO packet NetLabel component with the Generic NETLINK
38362306a36Sopenharmony_ci * mechanism.  Returns zero on success, negative values on failure.
38462306a36Sopenharmony_ci *
38562306a36Sopenharmony_ci */
38662306a36Sopenharmony_ciint __init netlbl_calipso_genl_init(void)
38762306a36Sopenharmony_ci{
38862306a36Sopenharmony_ci	return genl_register_family(&netlbl_calipso_gnl_family);
38962306a36Sopenharmony_ci}
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci/**
39262306a36Sopenharmony_ci * calipso_doi_add - Add a new DOI to the CALIPSO protocol engine
39362306a36Sopenharmony_ci * @doi_def: the DOI structure
39462306a36Sopenharmony_ci * @audit_info: NetLabel audit information
39562306a36Sopenharmony_ci *
39662306a36Sopenharmony_ci * Description:
39762306a36Sopenharmony_ci * The caller defines a new DOI for use by the CALIPSO engine and calls this
39862306a36Sopenharmony_ci * function to add it to the list of acceptable domains.  The caller must
39962306a36Sopenharmony_ci * ensure that the mapping table specified in @doi_def->map meets all of the
40062306a36Sopenharmony_ci * requirements of the mapping type (see calipso.h for details).  Returns
40162306a36Sopenharmony_ci * zero on success and non-zero on failure.
40262306a36Sopenharmony_ci *
40362306a36Sopenharmony_ci */
40462306a36Sopenharmony_ciint calipso_doi_add(struct calipso_doi *doi_def,
40562306a36Sopenharmony_ci		    struct netlbl_audit *audit_info)
40662306a36Sopenharmony_ci{
40762306a36Sopenharmony_ci	int ret_val = -ENOMSG;
40862306a36Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci	if (ops)
41162306a36Sopenharmony_ci		ret_val = ops->doi_add(doi_def, audit_info);
41262306a36Sopenharmony_ci	return ret_val;
41362306a36Sopenharmony_ci}
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_ci/**
41662306a36Sopenharmony_ci * calipso_doi_free - Frees a DOI definition
41762306a36Sopenharmony_ci * @doi_def: the DOI definition
41862306a36Sopenharmony_ci *
41962306a36Sopenharmony_ci * Description:
42062306a36Sopenharmony_ci * This function frees all of the memory associated with a DOI definition.
42162306a36Sopenharmony_ci *
42262306a36Sopenharmony_ci */
42362306a36Sopenharmony_civoid calipso_doi_free(struct calipso_doi *doi_def)
42462306a36Sopenharmony_ci{
42562306a36Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_ci	if (ops)
42862306a36Sopenharmony_ci		ops->doi_free(doi_def);
42962306a36Sopenharmony_ci}
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci/**
43262306a36Sopenharmony_ci * calipso_doi_remove - Remove an existing DOI from the CALIPSO protocol engine
43362306a36Sopenharmony_ci * @doi: the DOI value
43462306a36Sopenharmony_ci * @audit_info: NetLabel audit information
43562306a36Sopenharmony_ci *
43662306a36Sopenharmony_ci * Description:
43762306a36Sopenharmony_ci * Removes a DOI definition from the CALIPSO engine.  The NetLabel routines will
43862306a36Sopenharmony_ci * be called to release their own LSM domain mappings as well as our own
43962306a36Sopenharmony_ci * domain list.  Returns zero on success and negative values on failure.
44062306a36Sopenharmony_ci *
44162306a36Sopenharmony_ci */
44262306a36Sopenharmony_ciint calipso_doi_remove(u32 doi, struct netlbl_audit *audit_info)
44362306a36Sopenharmony_ci{
44462306a36Sopenharmony_ci	int ret_val = -ENOMSG;
44562306a36Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci	if (ops)
44862306a36Sopenharmony_ci		ret_val = ops->doi_remove(doi, audit_info);
44962306a36Sopenharmony_ci	return ret_val;
45062306a36Sopenharmony_ci}
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_ci/**
45362306a36Sopenharmony_ci * calipso_doi_getdef - Returns a reference to a valid DOI definition
45462306a36Sopenharmony_ci * @doi: the DOI value
45562306a36Sopenharmony_ci *
45662306a36Sopenharmony_ci * Description:
45762306a36Sopenharmony_ci * Searches for a valid DOI definition and if one is found it is returned to
45862306a36Sopenharmony_ci * the caller.  Otherwise NULL is returned.  The caller must ensure that
45962306a36Sopenharmony_ci * calipso_doi_putdef() is called when the caller is done.
46062306a36Sopenharmony_ci *
46162306a36Sopenharmony_ci */
46262306a36Sopenharmony_cistruct calipso_doi *calipso_doi_getdef(u32 doi)
46362306a36Sopenharmony_ci{
46462306a36Sopenharmony_ci	struct calipso_doi *ret_val = NULL;
46562306a36Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_ci	if (ops)
46862306a36Sopenharmony_ci		ret_val = ops->doi_getdef(doi);
46962306a36Sopenharmony_ci	return ret_val;
47062306a36Sopenharmony_ci}
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci/**
47362306a36Sopenharmony_ci * calipso_doi_putdef - Releases a reference for the given DOI definition
47462306a36Sopenharmony_ci * @doi_def: the DOI definition
47562306a36Sopenharmony_ci *
47662306a36Sopenharmony_ci * Description:
47762306a36Sopenharmony_ci * Releases a DOI definition reference obtained from calipso_doi_getdef().
47862306a36Sopenharmony_ci *
47962306a36Sopenharmony_ci */
48062306a36Sopenharmony_civoid calipso_doi_putdef(struct calipso_doi *doi_def)
48162306a36Sopenharmony_ci{
48262306a36Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_ci	if (ops)
48562306a36Sopenharmony_ci		ops->doi_putdef(doi_def);
48662306a36Sopenharmony_ci}
48762306a36Sopenharmony_ci
48862306a36Sopenharmony_ci/**
48962306a36Sopenharmony_ci * calipso_doi_walk - Iterate through the DOI definitions
49062306a36Sopenharmony_ci * @skip_cnt: skip past this number of DOI definitions, updated
49162306a36Sopenharmony_ci * @callback: callback for each DOI definition
49262306a36Sopenharmony_ci * @cb_arg: argument for the callback function
49362306a36Sopenharmony_ci *
49462306a36Sopenharmony_ci * Description:
49562306a36Sopenharmony_ci * Iterate over the DOI definition list, skipping the first @skip_cnt entries.
49662306a36Sopenharmony_ci * For each entry call @callback, if @callback returns a negative value stop
49762306a36Sopenharmony_ci * 'walking' through the list and return.  Updates the value in @skip_cnt upon
49862306a36Sopenharmony_ci * return.  Returns zero on success, negative values on failure.
49962306a36Sopenharmony_ci *
50062306a36Sopenharmony_ci */
50162306a36Sopenharmony_ciint calipso_doi_walk(u32 *skip_cnt,
50262306a36Sopenharmony_ci		     int (*callback)(struct calipso_doi *doi_def, void *arg),
50362306a36Sopenharmony_ci		     void *cb_arg)
50462306a36Sopenharmony_ci{
50562306a36Sopenharmony_ci	int ret_val = -ENOMSG;
50662306a36Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_ci	if (ops)
50962306a36Sopenharmony_ci		ret_val = ops->doi_walk(skip_cnt, callback, cb_arg);
51062306a36Sopenharmony_ci	return ret_val;
51162306a36Sopenharmony_ci}
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci/**
51462306a36Sopenharmony_ci * calipso_sock_getattr - Get the security attributes from a sock
51562306a36Sopenharmony_ci * @sk: the sock
51662306a36Sopenharmony_ci * @secattr: the security attributes
51762306a36Sopenharmony_ci *
51862306a36Sopenharmony_ci * Description:
51962306a36Sopenharmony_ci * Query @sk to see if there is a CALIPSO option attached to the sock and if
52062306a36Sopenharmony_ci * there is return the CALIPSO security attributes in @secattr.  This function
52162306a36Sopenharmony_ci * requires that @sk be locked, or privately held, but it does not do any
52262306a36Sopenharmony_ci * locking itself.  Returns zero on success and negative values on failure.
52362306a36Sopenharmony_ci *
52462306a36Sopenharmony_ci */
52562306a36Sopenharmony_ciint calipso_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
52662306a36Sopenharmony_ci{
52762306a36Sopenharmony_ci	int ret_val = -ENOMSG;
52862306a36Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci	if (ops)
53162306a36Sopenharmony_ci		ret_val = ops->sock_getattr(sk, secattr);
53262306a36Sopenharmony_ci	return ret_val;
53362306a36Sopenharmony_ci}
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci/**
53662306a36Sopenharmony_ci * calipso_sock_setattr - Add a CALIPSO option to a socket
53762306a36Sopenharmony_ci * @sk: the socket
53862306a36Sopenharmony_ci * @doi_def: the CALIPSO DOI to use
53962306a36Sopenharmony_ci * @secattr: the specific security attributes of the socket
54062306a36Sopenharmony_ci *
54162306a36Sopenharmony_ci * Description:
54262306a36Sopenharmony_ci * Set the CALIPSO option on the given socket using the DOI definition and
54362306a36Sopenharmony_ci * security attributes passed to the function.  This function requires
54462306a36Sopenharmony_ci * exclusive access to @sk, which means it either needs to be in the
54562306a36Sopenharmony_ci * process of being created or locked.  Returns zero on success and negative
54662306a36Sopenharmony_ci * values on failure.
54762306a36Sopenharmony_ci *
54862306a36Sopenharmony_ci */
54962306a36Sopenharmony_ciint calipso_sock_setattr(struct sock *sk,
55062306a36Sopenharmony_ci			 const struct calipso_doi *doi_def,
55162306a36Sopenharmony_ci			 const struct netlbl_lsm_secattr *secattr)
55262306a36Sopenharmony_ci{
55362306a36Sopenharmony_ci	int ret_val = -ENOMSG;
55462306a36Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_ci	if (ops)
55762306a36Sopenharmony_ci		ret_val = ops->sock_setattr(sk, doi_def, secattr);
55862306a36Sopenharmony_ci	return ret_val;
55962306a36Sopenharmony_ci}
56062306a36Sopenharmony_ci
56162306a36Sopenharmony_ci/**
56262306a36Sopenharmony_ci * calipso_sock_delattr - Delete the CALIPSO option from a socket
56362306a36Sopenharmony_ci * @sk: the socket
56462306a36Sopenharmony_ci *
56562306a36Sopenharmony_ci * Description:
56662306a36Sopenharmony_ci * Removes the CALIPSO option from a socket, if present.
56762306a36Sopenharmony_ci *
56862306a36Sopenharmony_ci */
56962306a36Sopenharmony_civoid calipso_sock_delattr(struct sock *sk)
57062306a36Sopenharmony_ci{
57162306a36Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_ci	if (ops)
57462306a36Sopenharmony_ci		ops->sock_delattr(sk);
57562306a36Sopenharmony_ci}
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_ci/**
57862306a36Sopenharmony_ci * calipso_req_setattr - Add a CALIPSO option to a connection request socket
57962306a36Sopenharmony_ci * @req: the connection request socket
58062306a36Sopenharmony_ci * @doi_def: the CALIPSO DOI to use
58162306a36Sopenharmony_ci * @secattr: the specific security attributes of the socket
58262306a36Sopenharmony_ci *
58362306a36Sopenharmony_ci * Description:
58462306a36Sopenharmony_ci * Set the CALIPSO option on the given socket using the DOI definition and
58562306a36Sopenharmony_ci * security attributes passed to the function.  Returns zero on success and
58662306a36Sopenharmony_ci * negative values on failure.
58762306a36Sopenharmony_ci *
58862306a36Sopenharmony_ci */
58962306a36Sopenharmony_ciint calipso_req_setattr(struct request_sock *req,
59062306a36Sopenharmony_ci			const struct calipso_doi *doi_def,
59162306a36Sopenharmony_ci			const struct netlbl_lsm_secattr *secattr)
59262306a36Sopenharmony_ci{
59362306a36Sopenharmony_ci	int ret_val = -ENOMSG;
59462306a36Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
59562306a36Sopenharmony_ci
59662306a36Sopenharmony_ci	if (ops)
59762306a36Sopenharmony_ci		ret_val = ops->req_setattr(req, doi_def, secattr);
59862306a36Sopenharmony_ci	return ret_val;
59962306a36Sopenharmony_ci}
60062306a36Sopenharmony_ci
60162306a36Sopenharmony_ci/**
60262306a36Sopenharmony_ci * calipso_req_delattr - Delete the CALIPSO option from a request socket
60362306a36Sopenharmony_ci * @req: the request socket
60462306a36Sopenharmony_ci *
60562306a36Sopenharmony_ci * Description:
60662306a36Sopenharmony_ci * Removes the CALIPSO option from a request socket, if present.
60762306a36Sopenharmony_ci *
60862306a36Sopenharmony_ci */
60962306a36Sopenharmony_civoid calipso_req_delattr(struct request_sock *req)
61062306a36Sopenharmony_ci{
61162306a36Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_ci	if (ops)
61462306a36Sopenharmony_ci		ops->req_delattr(req);
61562306a36Sopenharmony_ci}
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci/**
61862306a36Sopenharmony_ci * calipso_optptr - Find the CALIPSO option in the packet
61962306a36Sopenharmony_ci * @skb: the packet
62062306a36Sopenharmony_ci *
62162306a36Sopenharmony_ci * Description:
62262306a36Sopenharmony_ci * Parse the packet's IP header looking for a CALIPSO option.  Returns a pointer
62362306a36Sopenharmony_ci * to the start of the CALIPSO option on success, NULL if one if not found.
62462306a36Sopenharmony_ci *
62562306a36Sopenharmony_ci */
62662306a36Sopenharmony_ciunsigned char *calipso_optptr(const struct sk_buff *skb)
62762306a36Sopenharmony_ci{
62862306a36Sopenharmony_ci	unsigned char *ret_val = NULL;
62962306a36Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_ci	if (ops)
63262306a36Sopenharmony_ci		ret_val = ops->skbuff_optptr(skb);
63362306a36Sopenharmony_ci	return ret_val;
63462306a36Sopenharmony_ci}
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_ci/**
63762306a36Sopenharmony_ci * calipso_getattr - Get the security attributes from a memory block.
63862306a36Sopenharmony_ci * @calipso: the CALIPSO option
63962306a36Sopenharmony_ci * @secattr: the security attributes
64062306a36Sopenharmony_ci *
64162306a36Sopenharmony_ci * Description:
64262306a36Sopenharmony_ci * Inspect @calipso and return the security attributes in @secattr.
64362306a36Sopenharmony_ci * Returns zero on success and negative values on failure.
64462306a36Sopenharmony_ci *
64562306a36Sopenharmony_ci */
64662306a36Sopenharmony_ciint calipso_getattr(const unsigned char *calipso,
64762306a36Sopenharmony_ci		    struct netlbl_lsm_secattr *secattr)
64862306a36Sopenharmony_ci{
64962306a36Sopenharmony_ci	int ret_val = -ENOMSG;
65062306a36Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
65162306a36Sopenharmony_ci
65262306a36Sopenharmony_ci	if (ops)
65362306a36Sopenharmony_ci		ret_val = ops->opt_getattr(calipso, secattr);
65462306a36Sopenharmony_ci	return ret_val;
65562306a36Sopenharmony_ci}
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_ci/**
65862306a36Sopenharmony_ci * calipso_skbuff_setattr - Set the CALIPSO option on a packet
65962306a36Sopenharmony_ci * @skb: the packet
66062306a36Sopenharmony_ci * @doi_def: the CALIPSO DOI to use
66162306a36Sopenharmony_ci * @secattr: the security attributes
66262306a36Sopenharmony_ci *
66362306a36Sopenharmony_ci * Description:
66462306a36Sopenharmony_ci * Set the CALIPSO option on the given packet based on the security attributes.
66562306a36Sopenharmony_ci * Returns a pointer to the IP header on success and NULL on failure.
66662306a36Sopenharmony_ci *
66762306a36Sopenharmony_ci */
66862306a36Sopenharmony_ciint calipso_skbuff_setattr(struct sk_buff *skb,
66962306a36Sopenharmony_ci			   const struct calipso_doi *doi_def,
67062306a36Sopenharmony_ci			   const struct netlbl_lsm_secattr *secattr)
67162306a36Sopenharmony_ci{
67262306a36Sopenharmony_ci	int ret_val = -ENOMSG;
67362306a36Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
67462306a36Sopenharmony_ci
67562306a36Sopenharmony_ci	if (ops)
67662306a36Sopenharmony_ci		ret_val = ops->skbuff_setattr(skb, doi_def, secattr);
67762306a36Sopenharmony_ci	return ret_val;
67862306a36Sopenharmony_ci}
67962306a36Sopenharmony_ci
68062306a36Sopenharmony_ci/**
68162306a36Sopenharmony_ci * calipso_skbuff_delattr - Delete any CALIPSO options from a packet
68262306a36Sopenharmony_ci * @skb: the packet
68362306a36Sopenharmony_ci *
68462306a36Sopenharmony_ci * Description:
68562306a36Sopenharmony_ci * Removes any and all CALIPSO options from the given packet.  Returns zero on
68662306a36Sopenharmony_ci * success, negative values on failure.
68762306a36Sopenharmony_ci *
68862306a36Sopenharmony_ci */
68962306a36Sopenharmony_ciint calipso_skbuff_delattr(struct sk_buff *skb)
69062306a36Sopenharmony_ci{
69162306a36Sopenharmony_ci	int ret_val = -ENOMSG;
69262306a36Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
69362306a36Sopenharmony_ci
69462306a36Sopenharmony_ci	if (ops)
69562306a36Sopenharmony_ci		ret_val = ops->skbuff_delattr(skb);
69662306a36Sopenharmony_ci	return ret_val;
69762306a36Sopenharmony_ci}
69862306a36Sopenharmony_ci
69962306a36Sopenharmony_ci/**
70062306a36Sopenharmony_ci * calipso_cache_invalidate - Invalidates the current CALIPSO cache
70162306a36Sopenharmony_ci *
70262306a36Sopenharmony_ci * Description:
70362306a36Sopenharmony_ci * Invalidates and frees any entries in the CALIPSO cache.  Returns zero on
70462306a36Sopenharmony_ci * success and negative values on failure.
70562306a36Sopenharmony_ci *
70662306a36Sopenharmony_ci */
70762306a36Sopenharmony_civoid calipso_cache_invalidate(void)
70862306a36Sopenharmony_ci{
70962306a36Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
71062306a36Sopenharmony_ci
71162306a36Sopenharmony_ci	if (ops)
71262306a36Sopenharmony_ci		ops->cache_invalidate();
71362306a36Sopenharmony_ci}
71462306a36Sopenharmony_ci
71562306a36Sopenharmony_ci/**
71662306a36Sopenharmony_ci * calipso_cache_add - Add an entry to the CALIPSO cache
71762306a36Sopenharmony_ci * @calipso_ptr: the CALIPSO option
71862306a36Sopenharmony_ci * @secattr: the packet's security attributes
71962306a36Sopenharmony_ci *
72062306a36Sopenharmony_ci * Description:
72162306a36Sopenharmony_ci * Add a new entry into the CALIPSO label mapping cache.
72262306a36Sopenharmony_ci * Returns zero on success, negative values on failure.
72362306a36Sopenharmony_ci *
72462306a36Sopenharmony_ci */
72562306a36Sopenharmony_ciint calipso_cache_add(const unsigned char *calipso_ptr,
72662306a36Sopenharmony_ci		      const struct netlbl_lsm_secattr *secattr)
72762306a36Sopenharmony_ci
72862306a36Sopenharmony_ci{
72962306a36Sopenharmony_ci	int ret_val = -ENOMSG;
73062306a36Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_ci	if (ops)
73362306a36Sopenharmony_ci		ret_val = ops->cache_add(calipso_ptr, secattr);
73462306a36Sopenharmony_ci	return ret_val;
73562306a36Sopenharmony_ci}
736