18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * NetLabel CALIPSO/IPv6 Support
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * This file defines the CALIPSO/IPv6 functions for the NetLabel system.  The
68c2ecf20Sopenharmony_ci * NetLabel system manages static and dynamic label mappings for network
78c2ecf20Sopenharmony_ci * protocols such as CIPSO and CALIPSO.
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * Authors: Paul Moore <paul@paul-moore.com>
108c2ecf20Sopenharmony_ci *          Huw Davies <huw@codeweavers.com>
118c2ecf20Sopenharmony_ci */
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci/* (c) Copyright Hewlett-Packard Development Company, L.P., 2006
148c2ecf20Sopenharmony_ci * (c) Copyright Huw Davies <huw@codeweavers.com>, 2015
158c2ecf20Sopenharmony_ci */
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#include <linux/types.h>
188c2ecf20Sopenharmony_ci#include <linux/socket.h>
198c2ecf20Sopenharmony_ci#include <linux/string.h>
208c2ecf20Sopenharmony_ci#include <linux/skbuff.h>
218c2ecf20Sopenharmony_ci#include <linux/audit.h>
228c2ecf20Sopenharmony_ci#include <linux/slab.h>
238c2ecf20Sopenharmony_ci#include <net/sock.h>
248c2ecf20Sopenharmony_ci#include <net/netlink.h>
258c2ecf20Sopenharmony_ci#include <net/genetlink.h>
268c2ecf20Sopenharmony_ci#include <net/netlabel.h>
278c2ecf20Sopenharmony_ci#include <net/calipso.h>
288c2ecf20Sopenharmony_ci#include <linux/atomic.h>
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci#include "netlabel_user.h"
318c2ecf20Sopenharmony_ci#include "netlabel_calipso.h"
328c2ecf20Sopenharmony_ci#include "netlabel_mgmt.h"
338c2ecf20Sopenharmony_ci#include "netlabel_domainhash.h"
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci/* Argument struct for calipso_doi_walk() */
368c2ecf20Sopenharmony_cistruct netlbl_calipso_doiwalk_arg {
378c2ecf20Sopenharmony_ci	struct netlink_callback *nl_cb;
388c2ecf20Sopenharmony_ci	struct sk_buff *skb;
398c2ecf20Sopenharmony_ci	u32 seq;
408c2ecf20Sopenharmony_ci};
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci/* Argument struct for netlbl_domhsh_walk() */
438c2ecf20Sopenharmony_cistruct netlbl_domhsh_walk_arg {
448c2ecf20Sopenharmony_ci	struct netlbl_audit *audit_info;
458c2ecf20Sopenharmony_ci	u32 doi;
468c2ecf20Sopenharmony_ci};
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci/* NetLabel Generic NETLINK CALIPSO family */
498c2ecf20Sopenharmony_cistatic struct genl_family netlbl_calipso_gnl_family;
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci/* NetLabel Netlink attribute policy */
528c2ecf20Sopenharmony_cistatic const struct nla_policy calipso_genl_policy[NLBL_CALIPSO_A_MAX + 1] = {
538c2ecf20Sopenharmony_ci	[NLBL_CALIPSO_A_DOI] = { .type = NLA_U32 },
548c2ecf20Sopenharmony_ci	[NLBL_CALIPSO_A_MTYPE] = { .type = NLA_U32 },
558c2ecf20Sopenharmony_ci};
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_cistatic const struct netlbl_calipso_ops *calipso_ops;
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci/**
608c2ecf20Sopenharmony_ci * netlbl_calipso_ops_register - Register the CALIPSO operations
618c2ecf20Sopenharmony_ci * @ops: ops to register
628c2ecf20Sopenharmony_ci *
638c2ecf20Sopenharmony_ci * Description:
648c2ecf20Sopenharmony_ci * Register the CALIPSO packet engine operations.
658c2ecf20Sopenharmony_ci *
668c2ecf20Sopenharmony_ci */
678c2ecf20Sopenharmony_ciconst struct netlbl_calipso_ops *
688c2ecf20Sopenharmony_cinetlbl_calipso_ops_register(const struct netlbl_calipso_ops *ops)
698c2ecf20Sopenharmony_ci{
708c2ecf20Sopenharmony_ci	return xchg(&calipso_ops, ops);
718c2ecf20Sopenharmony_ci}
728c2ecf20Sopenharmony_ciEXPORT_SYMBOL(netlbl_calipso_ops_register);
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_cistatic const struct netlbl_calipso_ops *netlbl_calipso_ops_get(void)
758c2ecf20Sopenharmony_ci{
768c2ecf20Sopenharmony_ci	return READ_ONCE(calipso_ops);
778c2ecf20Sopenharmony_ci}
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci/* NetLabel Command Handlers
808c2ecf20Sopenharmony_ci */
818c2ecf20Sopenharmony_ci/**
828c2ecf20Sopenharmony_ci * netlbl_calipso_add_pass - Adds a CALIPSO pass DOI definition
838c2ecf20Sopenharmony_ci * @info: the Generic NETLINK info block
848c2ecf20Sopenharmony_ci * @audit_info: NetLabel audit information
858c2ecf20Sopenharmony_ci *
868c2ecf20Sopenharmony_ci * Description:
878c2ecf20Sopenharmony_ci * Create a new CALIPSO_MAP_PASS DOI definition based on the given ADD message
888c2ecf20Sopenharmony_ci * and add it to the CALIPSO engine.  Return zero on success and non-zero on
898c2ecf20Sopenharmony_ci * error.
908c2ecf20Sopenharmony_ci *
918c2ecf20Sopenharmony_ci */
928c2ecf20Sopenharmony_cistatic int netlbl_calipso_add_pass(struct genl_info *info,
938c2ecf20Sopenharmony_ci				   struct netlbl_audit *audit_info)
948c2ecf20Sopenharmony_ci{
958c2ecf20Sopenharmony_ci	int ret_val;
968c2ecf20Sopenharmony_ci	struct calipso_doi *doi_def = NULL;
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci	doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL);
998c2ecf20Sopenharmony_ci	if (!doi_def)
1008c2ecf20Sopenharmony_ci		return -ENOMEM;
1018c2ecf20Sopenharmony_ci	doi_def->type = CALIPSO_MAP_PASS;
1028c2ecf20Sopenharmony_ci	doi_def->doi = nla_get_u32(info->attrs[NLBL_CALIPSO_A_DOI]);
1038c2ecf20Sopenharmony_ci	ret_val = calipso_doi_add(doi_def, audit_info);
1048c2ecf20Sopenharmony_ci	if (ret_val != 0)
1058c2ecf20Sopenharmony_ci		calipso_doi_free(doi_def);
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci	return ret_val;
1088c2ecf20Sopenharmony_ci}
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci/**
1118c2ecf20Sopenharmony_ci * netlbl_calipso_add - Handle an ADD message
1128c2ecf20Sopenharmony_ci * @skb: the NETLINK buffer
1138c2ecf20Sopenharmony_ci * @info: the Generic NETLINK info block
1148c2ecf20Sopenharmony_ci *
1158c2ecf20Sopenharmony_ci * Description:
1168c2ecf20Sopenharmony_ci * Create a new DOI definition based on the given ADD message and add it to the
1178c2ecf20Sopenharmony_ci * CALIPSO engine.  Returns zero on success, negative values on failure.
1188c2ecf20Sopenharmony_ci *
1198c2ecf20Sopenharmony_ci */
1208c2ecf20Sopenharmony_cistatic int netlbl_calipso_add(struct sk_buff *skb, struct genl_info *info)
1218c2ecf20Sopenharmony_ci{
1228c2ecf20Sopenharmony_ci	int ret_val = -EINVAL;
1238c2ecf20Sopenharmony_ci	struct netlbl_audit audit_info;
1248c2ecf20Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci	if (!info->attrs[NLBL_CALIPSO_A_DOI] ||
1278c2ecf20Sopenharmony_ci	    !info->attrs[NLBL_CALIPSO_A_MTYPE])
1288c2ecf20Sopenharmony_ci		return -EINVAL;
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci	if (!ops)
1318c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci	netlbl_netlink_auditinfo(&audit_info);
1348c2ecf20Sopenharmony_ci	switch (nla_get_u32(info->attrs[NLBL_CALIPSO_A_MTYPE])) {
1358c2ecf20Sopenharmony_ci	case CALIPSO_MAP_PASS:
1368c2ecf20Sopenharmony_ci		ret_val = netlbl_calipso_add_pass(info, &audit_info);
1378c2ecf20Sopenharmony_ci		break;
1388c2ecf20Sopenharmony_ci	}
1398c2ecf20Sopenharmony_ci	if (ret_val == 0)
1408c2ecf20Sopenharmony_ci		atomic_inc(&netlabel_mgmt_protocount);
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci	return ret_val;
1438c2ecf20Sopenharmony_ci}
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci/**
1468c2ecf20Sopenharmony_ci * netlbl_calipso_list - Handle a LIST message
1478c2ecf20Sopenharmony_ci * @skb: the NETLINK buffer
1488c2ecf20Sopenharmony_ci * @info: the Generic NETLINK info block
1498c2ecf20Sopenharmony_ci *
1508c2ecf20Sopenharmony_ci * Description:
1518c2ecf20Sopenharmony_ci * Process a user generated LIST message and respond accordingly.
1528c2ecf20Sopenharmony_ci * Returns zero on success and negative values on error.
1538c2ecf20Sopenharmony_ci *
1548c2ecf20Sopenharmony_ci */
1558c2ecf20Sopenharmony_cistatic int netlbl_calipso_list(struct sk_buff *skb, struct genl_info *info)
1568c2ecf20Sopenharmony_ci{
1578c2ecf20Sopenharmony_ci	int ret_val;
1588c2ecf20Sopenharmony_ci	struct sk_buff *ans_skb = NULL;
1598c2ecf20Sopenharmony_ci	void *data;
1608c2ecf20Sopenharmony_ci	u32 doi;
1618c2ecf20Sopenharmony_ci	struct calipso_doi *doi_def;
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	if (!info->attrs[NLBL_CALIPSO_A_DOI]) {
1648c2ecf20Sopenharmony_ci		ret_val = -EINVAL;
1658c2ecf20Sopenharmony_ci		goto list_failure;
1668c2ecf20Sopenharmony_ci	}
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci	doi = nla_get_u32(info->attrs[NLBL_CALIPSO_A_DOI]);
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci	doi_def = calipso_doi_getdef(doi);
1718c2ecf20Sopenharmony_ci	if (!doi_def) {
1728c2ecf20Sopenharmony_ci		ret_val = -EINVAL;
1738c2ecf20Sopenharmony_ci		goto list_failure;
1748c2ecf20Sopenharmony_ci	}
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1778c2ecf20Sopenharmony_ci	if (!ans_skb) {
1788c2ecf20Sopenharmony_ci		ret_val = -ENOMEM;
1798c2ecf20Sopenharmony_ci		goto list_failure_put;
1808c2ecf20Sopenharmony_ci	}
1818c2ecf20Sopenharmony_ci	data = genlmsg_put_reply(ans_skb, info, &netlbl_calipso_gnl_family,
1828c2ecf20Sopenharmony_ci				 0, NLBL_CALIPSO_C_LIST);
1838c2ecf20Sopenharmony_ci	if (!data) {
1848c2ecf20Sopenharmony_ci		ret_val = -ENOMEM;
1858c2ecf20Sopenharmony_ci		goto list_failure_put;
1868c2ecf20Sopenharmony_ci	}
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	ret_val = nla_put_u32(ans_skb, NLBL_CALIPSO_A_MTYPE, doi_def->type);
1898c2ecf20Sopenharmony_ci	if (ret_val != 0)
1908c2ecf20Sopenharmony_ci		goto list_failure_put;
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci	calipso_doi_putdef(doi_def);
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci	genlmsg_end(ans_skb, data);
1958c2ecf20Sopenharmony_ci	return genlmsg_reply(ans_skb, info);
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_cilist_failure_put:
1988c2ecf20Sopenharmony_ci	calipso_doi_putdef(doi_def);
1998c2ecf20Sopenharmony_cilist_failure:
2008c2ecf20Sopenharmony_ci	kfree_skb(ans_skb);
2018c2ecf20Sopenharmony_ci	return ret_val;
2028c2ecf20Sopenharmony_ci}
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci/**
2058c2ecf20Sopenharmony_ci * netlbl_calipso_listall_cb - calipso_doi_walk() callback for LISTALL
2068c2ecf20Sopenharmony_ci * @doi_def: the CALIPSO DOI definition
2078c2ecf20Sopenharmony_ci * @arg: the netlbl_calipso_doiwalk_arg structure
2088c2ecf20Sopenharmony_ci *
2098c2ecf20Sopenharmony_ci * Description:
2108c2ecf20Sopenharmony_ci * This function is designed to be used as a callback to the
2118c2ecf20Sopenharmony_ci * calipso_doi_walk() function for use in generating a response for a LISTALL
2128c2ecf20Sopenharmony_ci * message.  Returns the size of the message on success, negative values on
2138c2ecf20Sopenharmony_ci * failure.
2148c2ecf20Sopenharmony_ci *
2158c2ecf20Sopenharmony_ci */
2168c2ecf20Sopenharmony_cistatic int netlbl_calipso_listall_cb(struct calipso_doi *doi_def, void *arg)
2178c2ecf20Sopenharmony_ci{
2188c2ecf20Sopenharmony_ci	int ret_val = -ENOMEM;
2198c2ecf20Sopenharmony_ci	struct netlbl_calipso_doiwalk_arg *cb_arg = arg;
2208c2ecf20Sopenharmony_ci	void *data;
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).portid,
2238c2ecf20Sopenharmony_ci			   cb_arg->seq, &netlbl_calipso_gnl_family,
2248c2ecf20Sopenharmony_ci			   NLM_F_MULTI, NLBL_CALIPSO_C_LISTALL);
2258c2ecf20Sopenharmony_ci	if (!data)
2268c2ecf20Sopenharmony_ci		goto listall_cb_failure;
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci	ret_val = nla_put_u32(cb_arg->skb, NLBL_CALIPSO_A_DOI, doi_def->doi);
2298c2ecf20Sopenharmony_ci	if (ret_val != 0)
2308c2ecf20Sopenharmony_ci		goto listall_cb_failure;
2318c2ecf20Sopenharmony_ci	ret_val = nla_put_u32(cb_arg->skb,
2328c2ecf20Sopenharmony_ci			      NLBL_CALIPSO_A_MTYPE,
2338c2ecf20Sopenharmony_ci			      doi_def->type);
2348c2ecf20Sopenharmony_ci	if (ret_val != 0)
2358c2ecf20Sopenharmony_ci		goto listall_cb_failure;
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci	genlmsg_end(cb_arg->skb, data);
2388c2ecf20Sopenharmony_ci	return 0;
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_cilistall_cb_failure:
2418c2ecf20Sopenharmony_ci	genlmsg_cancel(cb_arg->skb, data);
2428c2ecf20Sopenharmony_ci	return ret_val;
2438c2ecf20Sopenharmony_ci}
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci/**
2468c2ecf20Sopenharmony_ci * netlbl_calipso_listall - Handle a LISTALL message
2478c2ecf20Sopenharmony_ci * @skb: the NETLINK buffer
2488c2ecf20Sopenharmony_ci * @cb: the NETLINK callback
2498c2ecf20Sopenharmony_ci *
2508c2ecf20Sopenharmony_ci * Description:
2518c2ecf20Sopenharmony_ci * Process a user generated LISTALL message and respond accordingly.  Returns
2528c2ecf20Sopenharmony_ci * zero on success and negative values on error.
2538c2ecf20Sopenharmony_ci *
2548c2ecf20Sopenharmony_ci */
2558c2ecf20Sopenharmony_cistatic int netlbl_calipso_listall(struct sk_buff *skb,
2568c2ecf20Sopenharmony_ci				  struct netlink_callback *cb)
2578c2ecf20Sopenharmony_ci{
2588c2ecf20Sopenharmony_ci	struct netlbl_calipso_doiwalk_arg cb_arg;
2598c2ecf20Sopenharmony_ci	u32 doi_skip = cb->args[0];
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	cb_arg.nl_cb = cb;
2628c2ecf20Sopenharmony_ci	cb_arg.skb = skb;
2638c2ecf20Sopenharmony_ci	cb_arg.seq = cb->nlh->nlmsg_seq;
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci	calipso_doi_walk(&doi_skip, netlbl_calipso_listall_cb, &cb_arg);
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci	cb->args[0] = doi_skip;
2688c2ecf20Sopenharmony_ci	return skb->len;
2698c2ecf20Sopenharmony_ci}
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci/**
2728c2ecf20Sopenharmony_ci * netlbl_calipso_remove_cb - netlbl_calipso_remove() callback for REMOVE
2738c2ecf20Sopenharmony_ci * @entry: LSM domain mapping entry
2748c2ecf20Sopenharmony_ci * @arg: the netlbl_domhsh_walk_arg structure
2758c2ecf20Sopenharmony_ci *
2768c2ecf20Sopenharmony_ci * Description:
2778c2ecf20Sopenharmony_ci * This function is intended for use by netlbl_calipso_remove() as the callback
2788c2ecf20Sopenharmony_ci * for the netlbl_domhsh_walk() function; it removes LSM domain map entries
2798c2ecf20Sopenharmony_ci * which are associated with the CALIPSO DOI specified in @arg.  Returns zero on
2808c2ecf20Sopenharmony_ci * success, negative values on failure.
2818c2ecf20Sopenharmony_ci *
2828c2ecf20Sopenharmony_ci */
2838c2ecf20Sopenharmony_cistatic int netlbl_calipso_remove_cb(struct netlbl_dom_map *entry, void *arg)
2848c2ecf20Sopenharmony_ci{
2858c2ecf20Sopenharmony_ci	struct netlbl_domhsh_walk_arg *cb_arg = arg;
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci	if (entry->def.type == NETLBL_NLTYPE_CALIPSO &&
2888c2ecf20Sopenharmony_ci	    entry->def.calipso->doi == cb_arg->doi)
2898c2ecf20Sopenharmony_ci		return netlbl_domhsh_remove_entry(entry, cb_arg->audit_info);
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci	return 0;
2928c2ecf20Sopenharmony_ci}
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci/**
2958c2ecf20Sopenharmony_ci * netlbl_calipso_remove - Handle a REMOVE message
2968c2ecf20Sopenharmony_ci * @skb: the NETLINK buffer
2978c2ecf20Sopenharmony_ci * @info: the Generic NETLINK info block
2988c2ecf20Sopenharmony_ci *
2998c2ecf20Sopenharmony_ci * Description:
3008c2ecf20Sopenharmony_ci * Process a user generated REMOVE message and respond accordingly.  Returns
3018c2ecf20Sopenharmony_ci * zero on success, negative values on failure.
3028c2ecf20Sopenharmony_ci *
3038c2ecf20Sopenharmony_ci */
3048c2ecf20Sopenharmony_cistatic int netlbl_calipso_remove(struct sk_buff *skb, struct genl_info *info)
3058c2ecf20Sopenharmony_ci{
3068c2ecf20Sopenharmony_ci	int ret_val = -EINVAL;
3078c2ecf20Sopenharmony_ci	struct netlbl_domhsh_walk_arg cb_arg;
3088c2ecf20Sopenharmony_ci	struct netlbl_audit audit_info;
3098c2ecf20Sopenharmony_ci	u32 skip_bkt = 0;
3108c2ecf20Sopenharmony_ci	u32 skip_chain = 0;
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	if (!info->attrs[NLBL_CALIPSO_A_DOI])
3138c2ecf20Sopenharmony_ci		return -EINVAL;
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci	netlbl_netlink_auditinfo(&audit_info);
3168c2ecf20Sopenharmony_ci	cb_arg.doi = nla_get_u32(info->attrs[NLBL_CALIPSO_A_DOI]);
3178c2ecf20Sopenharmony_ci	cb_arg.audit_info = &audit_info;
3188c2ecf20Sopenharmony_ci	ret_val = netlbl_domhsh_walk(&skip_bkt, &skip_chain,
3198c2ecf20Sopenharmony_ci				     netlbl_calipso_remove_cb, &cb_arg);
3208c2ecf20Sopenharmony_ci	if (ret_val == 0 || ret_val == -ENOENT) {
3218c2ecf20Sopenharmony_ci		ret_val = calipso_doi_remove(cb_arg.doi, &audit_info);
3228c2ecf20Sopenharmony_ci		if (ret_val == 0)
3238c2ecf20Sopenharmony_ci			atomic_dec(&netlabel_mgmt_protocount);
3248c2ecf20Sopenharmony_ci	}
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci	return ret_val;
3278c2ecf20Sopenharmony_ci}
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci/* NetLabel Generic NETLINK Command Definitions
3308c2ecf20Sopenharmony_ci */
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_cistatic const struct genl_small_ops netlbl_calipso_ops[] = {
3338c2ecf20Sopenharmony_ci	{
3348c2ecf20Sopenharmony_ci	.cmd = NLBL_CALIPSO_C_ADD,
3358c2ecf20Sopenharmony_ci	.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
3368c2ecf20Sopenharmony_ci	.flags = GENL_ADMIN_PERM,
3378c2ecf20Sopenharmony_ci	.doit = netlbl_calipso_add,
3388c2ecf20Sopenharmony_ci	.dumpit = NULL,
3398c2ecf20Sopenharmony_ci	},
3408c2ecf20Sopenharmony_ci	{
3418c2ecf20Sopenharmony_ci	.cmd = NLBL_CALIPSO_C_REMOVE,
3428c2ecf20Sopenharmony_ci	.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
3438c2ecf20Sopenharmony_ci	.flags = GENL_ADMIN_PERM,
3448c2ecf20Sopenharmony_ci	.doit = netlbl_calipso_remove,
3458c2ecf20Sopenharmony_ci	.dumpit = NULL,
3468c2ecf20Sopenharmony_ci	},
3478c2ecf20Sopenharmony_ci	{
3488c2ecf20Sopenharmony_ci	.cmd = NLBL_CALIPSO_C_LIST,
3498c2ecf20Sopenharmony_ci	.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
3508c2ecf20Sopenharmony_ci	.flags = 0,
3518c2ecf20Sopenharmony_ci	.doit = netlbl_calipso_list,
3528c2ecf20Sopenharmony_ci	.dumpit = NULL,
3538c2ecf20Sopenharmony_ci	},
3548c2ecf20Sopenharmony_ci	{
3558c2ecf20Sopenharmony_ci	.cmd = NLBL_CALIPSO_C_LISTALL,
3568c2ecf20Sopenharmony_ci	.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
3578c2ecf20Sopenharmony_ci	.flags = 0,
3588c2ecf20Sopenharmony_ci	.doit = NULL,
3598c2ecf20Sopenharmony_ci	.dumpit = netlbl_calipso_listall,
3608c2ecf20Sopenharmony_ci	},
3618c2ecf20Sopenharmony_ci};
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_cistatic struct genl_family netlbl_calipso_gnl_family __ro_after_init = {
3648c2ecf20Sopenharmony_ci	.hdrsize = 0,
3658c2ecf20Sopenharmony_ci	.name = NETLBL_NLTYPE_CALIPSO_NAME,
3668c2ecf20Sopenharmony_ci	.version = NETLBL_PROTO_VERSION,
3678c2ecf20Sopenharmony_ci	.maxattr = NLBL_CALIPSO_A_MAX,
3688c2ecf20Sopenharmony_ci	.policy = calipso_genl_policy,
3698c2ecf20Sopenharmony_ci	.module = THIS_MODULE,
3708c2ecf20Sopenharmony_ci	.small_ops = netlbl_calipso_ops,
3718c2ecf20Sopenharmony_ci	.n_small_ops = ARRAY_SIZE(netlbl_calipso_ops),
3728c2ecf20Sopenharmony_ci};
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci/* NetLabel Generic NETLINK Protocol Functions
3758c2ecf20Sopenharmony_ci */
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci/**
3788c2ecf20Sopenharmony_ci * netlbl_calipso_genl_init - Register the CALIPSO NetLabel component
3798c2ecf20Sopenharmony_ci *
3808c2ecf20Sopenharmony_ci * Description:
3818c2ecf20Sopenharmony_ci * Register the CALIPSO packet NetLabel component with the Generic NETLINK
3828c2ecf20Sopenharmony_ci * mechanism.  Returns zero on success, negative values on failure.
3838c2ecf20Sopenharmony_ci *
3848c2ecf20Sopenharmony_ci */
3858c2ecf20Sopenharmony_ciint __init netlbl_calipso_genl_init(void)
3868c2ecf20Sopenharmony_ci{
3878c2ecf20Sopenharmony_ci	return genl_register_family(&netlbl_calipso_gnl_family);
3888c2ecf20Sopenharmony_ci}
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci/**
3918c2ecf20Sopenharmony_ci * calipso_doi_add - Add a new DOI to the CALIPSO protocol engine
3928c2ecf20Sopenharmony_ci * @doi_def: the DOI structure
3938c2ecf20Sopenharmony_ci * @audit_info: NetLabel audit information
3948c2ecf20Sopenharmony_ci *
3958c2ecf20Sopenharmony_ci * Description:
3968c2ecf20Sopenharmony_ci * The caller defines a new DOI for use by the CALIPSO engine and calls this
3978c2ecf20Sopenharmony_ci * function to add it to the list of acceptable domains.  The caller must
3988c2ecf20Sopenharmony_ci * ensure that the mapping table specified in @doi_def->map meets all of the
3998c2ecf20Sopenharmony_ci * requirements of the mapping type (see calipso.h for details).  Returns
4008c2ecf20Sopenharmony_ci * zero on success and non-zero on failure.
4018c2ecf20Sopenharmony_ci *
4028c2ecf20Sopenharmony_ci */
4038c2ecf20Sopenharmony_ciint calipso_doi_add(struct calipso_doi *doi_def,
4048c2ecf20Sopenharmony_ci		    struct netlbl_audit *audit_info)
4058c2ecf20Sopenharmony_ci{
4068c2ecf20Sopenharmony_ci	int ret_val = -ENOMSG;
4078c2ecf20Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci	if (ops)
4108c2ecf20Sopenharmony_ci		ret_val = ops->doi_add(doi_def, audit_info);
4118c2ecf20Sopenharmony_ci	return ret_val;
4128c2ecf20Sopenharmony_ci}
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci/**
4158c2ecf20Sopenharmony_ci * calipso_doi_free - Frees a DOI definition
4168c2ecf20Sopenharmony_ci * @doi_def: the DOI definition
4178c2ecf20Sopenharmony_ci *
4188c2ecf20Sopenharmony_ci * Description:
4198c2ecf20Sopenharmony_ci * This function frees all of the memory associated with a DOI definition.
4208c2ecf20Sopenharmony_ci *
4218c2ecf20Sopenharmony_ci */
4228c2ecf20Sopenharmony_civoid calipso_doi_free(struct calipso_doi *doi_def)
4238c2ecf20Sopenharmony_ci{
4248c2ecf20Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci	if (ops)
4278c2ecf20Sopenharmony_ci		ops->doi_free(doi_def);
4288c2ecf20Sopenharmony_ci}
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_ci/**
4318c2ecf20Sopenharmony_ci * calipso_doi_remove - Remove an existing DOI from the CALIPSO protocol engine
4328c2ecf20Sopenharmony_ci * @doi: the DOI value
4338c2ecf20Sopenharmony_ci * @audit_info: NetLabel audit information
4348c2ecf20Sopenharmony_ci *
4358c2ecf20Sopenharmony_ci * Description:
4368c2ecf20Sopenharmony_ci * Removes a DOI definition from the CALIPSO engine.  The NetLabel routines will
4378c2ecf20Sopenharmony_ci * be called to release their own LSM domain mappings as well as our own
4388c2ecf20Sopenharmony_ci * domain list.  Returns zero on success and negative values on failure.
4398c2ecf20Sopenharmony_ci *
4408c2ecf20Sopenharmony_ci */
4418c2ecf20Sopenharmony_ciint calipso_doi_remove(u32 doi, struct netlbl_audit *audit_info)
4428c2ecf20Sopenharmony_ci{
4438c2ecf20Sopenharmony_ci	int ret_val = -ENOMSG;
4448c2ecf20Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
4458c2ecf20Sopenharmony_ci
4468c2ecf20Sopenharmony_ci	if (ops)
4478c2ecf20Sopenharmony_ci		ret_val = ops->doi_remove(doi, audit_info);
4488c2ecf20Sopenharmony_ci	return ret_val;
4498c2ecf20Sopenharmony_ci}
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_ci/**
4528c2ecf20Sopenharmony_ci * calipso_doi_getdef - Returns a reference to a valid DOI definition
4538c2ecf20Sopenharmony_ci * @doi: the DOI value
4548c2ecf20Sopenharmony_ci *
4558c2ecf20Sopenharmony_ci * Description:
4568c2ecf20Sopenharmony_ci * Searches for a valid DOI definition and if one is found it is returned to
4578c2ecf20Sopenharmony_ci * the caller.  Otherwise NULL is returned.  The caller must ensure that
4588c2ecf20Sopenharmony_ci * calipso_doi_putdef() is called when the caller is done.
4598c2ecf20Sopenharmony_ci *
4608c2ecf20Sopenharmony_ci */
4618c2ecf20Sopenharmony_cistruct calipso_doi *calipso_doi_getdef(u32 doi)
4628c2ecf20Sopenharmony_ci{
4638c2ecf20Sopenharmony_ci	struct calipso_doi *ret_val = NULL;
4648c2ecf20Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
4658c2ecf20Sopenharmony_ci
4668c2ecf20Sopenharmony_ci	if (ops)
4678c2ecf20Sopenharmony_ci		ret_val = ops->doi_getdef(doi);
4688c2ecf20Sopenharmony_ci	return ret_val;
4698c2ecf20Sopenharmony_ci}
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci/**
4728c2ecf20Sopenharmony_ci * calipso_doi_putdef - Releases a reference for the given DOI definition
4738c2ecf20Sopenharmony_ci * @doi_def: the DOI definition
4748c2ecf20Sopenharmony_ci *
4758c2ecf20Sopenharmony_ci * Description:
4768c2ecf20Sopenharmony_ci * Releases a DOI definition reference obtained from calipso_doi_getdef().
4778c2ecf20Sopenharmony_ci *
4788c2ecf20Sopenharmony_ci */
4798c2ecf20Sopenharmony_civoid calipso_doi_putdef(struct calipso_doi *doi_def)
4808c2ecf20Sopenharmony_ci{
4818c2ecf20Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ci	if (ops)
4848c2ecf20Sopenharmony_ci		ops->doi_putdef(doi_def);
4858c2ecf20Sopenharmony_ci}
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_ci/**
4888c2ecf20Sopenharmony_ci * calipso_doi_walk - Iterate through the DOI definitions
4898c2ecf20Sopenharmony_ci * @skip_cnt: skip past this number of DOI definitions, updated
4908c2ecf20Sopenharmony_ci * @callback: callback for each DOI definition
4918c2ecf20Sopenharmony_ci * @cb_arg: argument for the callback function
4928c2ecf20Sopenharmony_ci *
4938c2ecf20Sopenharmony_ci * Description:
4948c2ecf20Sopenharmony_ci * Iterate over the DOI definition list, skipping the first @skip_cnt entries.
4958c2ecf20Sopenharmony_ci * For each entry call @callback, if @callback returns a negative value stop
4968c2ecf20Sopenharmony_ci * 'walking' through the list and return.  Updates the value in @skip_cnt upon
4978c2ecf20Sopenharmony_ci * return.  Returns zero on success, negative values on failure.
4988c2ecf20Sopenharmony_ci *
4998c2ecf20Sopenharmony_ci */
5008c2ecf20Sopenharmony_ciint calipso_doi_walk(u32 *skip_cnt,
5018c2ecf20Sopenharmony_ci		     int (*callback)(struct calipso_doi *doi_def, void *arg),
5028c2ecf20Sopenharmony_ci		     void *cb_arg)
5038c2ecf20Sopenharmony_ci{
5048c2ecf20Sopenharmony_ci	int ret_val = -ENOMSG;
5058c2ecf20Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
5068c2ecf20Sopenharmony_ci
5078c2ecf20Sopenharmony_ci	if (ops)
5088c2ecf20Sopenharmony_ci		ret_val = ops->doi_walk(skip_cnt, callback, cb_arg);
5098c2ecf20Sopenharmony_ci	return ret_val;
5108c2ecf20Sopenharmony_ci}
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_ci/**
5138c2ecf20Sopenharmony_ci * calipso_sock_getattr - Get the security attributes from a sock
5148c2ecf20Sopenharmony_ci * @sk: the sock
5158c2ecf20Sopenharmony_ci * @secattr: the security attributes
5168c2ecf20Sopenharmony_ci *
5178c2ecf20Sopenharmony_ci * Description:
5188c2ecf20Sopenharmony_ci * Query @sk to see if there is a CALIPSO option attached to the sock and if
5198c2ecf20Sopenharmony_ci * there is return the CALIPSO security attributes in @secattr.  This function
5208c2ecf20Sopenharmony_ci * requires that @sk be locked, or privately held, but it does not do any
5218c2ecf20Sopenharmony_ci * locking itself.  Returns zero on success and negative values on failure.
5228c2ecf20Sopenharmony_ci *
5238c2ecf20Sopenharmony_ci */
5248c2ecf20Sopenharmony_ciint calipso_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
5258c2ecf20Sopenharmony_ci{
5268c2ecf20Sopenharmony_ci	int ret_val = -ENOMSG;
5278c2ecf20Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci	if (ops)
5308c2ecf20Sopenharmony_ci		ret_val = ops->sock_getattr(sk, secattr);
5318c2ecf20Sopenharmony_ci	return ret_val;
5328c2ecf20Sopenharmony_ci}
5338c2ecf20Sopenharmony_ci
5348c2ecf20Sopenharmony_ci/**
5358c2ecf20Sopenharmony_ci * calipso_sock_setattr - Add a CALIPSO option to a socket
5368c2ecf20Sopenharmony_ci * @sk: the socket
5378c2ecf20Sopenharmony_ci * @doi_def: the CALIPSO DOI to use
5388c2ecf20Sopenharmony_ci * @secattr: the specific security attributes of the socket
5398c2ecf20Sopenharmony_ci *
5408c2ecf20Sopenharmony_ci * Description:
5418c2ecf20Sopenharmony_ci * Set the CALIPSO option on the given socket using the DOI definition and
5428c2ecf20Sopenharmony_ci * security attributes passed to the function.  This function requires
5438c2ecf20Sopenharmony_ci * exclusive access to @sk, which means it either needs to be in the
5448c2ecf20Sopenharmony_ci * process of being created or locked.  Returns zero on success and negative
5458c2ecf20Sopenharmony_ci * values on failure.
5468c2ecf20Sopenharmony_ci *
5478c2ecf20Sopenharmony_ci */
5488c2ecf20Sopenharmony_ciint calipso_sock_setattr(struct sock *sk,
5498c2ecf20Sopenharmony_ci			 const struct calipso_doi *doi_def,
5508c2ecf20Sopenharmony_ci			 const struct netlbl_lsm_secattr *secattr)
5518c2ecf20Sopenharmony_ci{
5528c2ecf20Sopenharmony_ci	int ret_val = -ENOMSG;
5538c2ecf20Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_ci	if (ops)
5568c2ecf20Sopenharmony_ci		ret_val = ops->sock_setattr(sk, doi_def, secattr);
5578c2ecf20Sopenharmony_ci	return ret_val;
5588c2ecf20Sopenharmony_ci}
5598c2ecf20Sopenharmony_ci
5608c2ecf20Sopenharmony_ci/**
5618c2ecf20Sopenharmony_ci * calipso_sock_delattr - Delete the CALIPSO option from a socket
5628c2ecf20Sopenharmony_ci * @sk: the socket
5638c2ecf20Sopenharmony_ci *
5648c2ecf20Sopenharmony_ci * Description:
5658c2ecf20Sopenharmony_ci * Removes the CALIPSO option from a socket, if present.
5668c2ecf20Sopenharmony_ci *
5678c2ecf20Sopenharmony_ci */
5688c2ecf20Sopenharmony_civoid calipso_sock_delattr(struct sock *sk)
5698c2ecf20Sopenharmony_ci{
5708c2ecf20Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_ci	if (ops)
5738c2ecf20Sopenharmony_ci		ops->sock_delattr(sk);
5748c2ecf20Sopenharmony_ci}
5758c2ecf20Sopenharmony_ci
5768c2ecf20Sopenharmony_ci/**
5778c2ecf20Sopenharmony_ci * calipso_req_setattr - Add a CALIPSO option to a connection request socket
5788c2ecf20Sopenharmony_ci * @req: the connection request socket
5798c2ecf20Sopenharmony_ci * @doi_def: the CALIPSO DOI to use
5808c2ecf20Sopenharmony_ci * @secattr: the specific security attributes of the socket
5818c2ecf20Sopenharmony_ci *
5828c2ecf20Sopenharmony_ci * Description:
5838c2ecf20Sopenharmony_ci * Set the CALIPSO option on the given socket using the DOI definition and
5848c2ecf20Sopenharmony_ci * security attributes passed to the function.  Returns zero on success and
5858c2ecf20Sopenharmony_ci * negative values on failure.
5868c2ecf20Sopenharmony_ci *
5878c2ecf20Sopenharmony_ci */
5888c2ecf20Sopenharmony_ciint calipso_req_setattr(struct request_sock *req,
5898c2ecf20Sopenharmony_ci			const struct calipso_doi *doi_def,
5908c2ecf20Sopenharmony_ci			const struct netlbl_lsm_secattr *secattr)
5918c2ecf20Sopenharmony_ci{
5928c2ecf20Sopenharmony_ci	int ret_val = -ENOMSG;
5938c2ecf20Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci	if (ops)
5968c2ecf20Sopenharmony_ci		ret_val = ops->req_setattr(req, doi_def, secattr);
5978c2ecf20Sopenharmony_ci	return ret_val;
5988c2ecf20Sopenharmony_ci}
5998c2ecf20Sopenharmony_ci
6008c2ecf20Sopenharmony_ci/**
6018c2ecf20Sopenharmony_ci * calipso_req_delattr - Delete the CALIPSO option from a request socket
6028c2ecf20Sopenharmony_ci * @req: the request socket
6038c2ecf20Sopenharmony_ci *
6048c2ecf20Sopenharmony_ci * Description:
6058c2ecf20Sopenharmony_ci * Removes the CALIPSO option from a request socket, if present.
6068c2ecf20Sopenharmony_ci *
6078c2ecf20Sopenharmony_ci */
6088c2ecf20Sopenharmony_civoid calipso_req_delattr(struct request_sock *req)
6098c2ecf20Sopenharmony_ci{
6108c2ecf20Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_ci	if (ops)
6138c2ecf20Sopenharmony_ci		ops->req_delattr(req);
6148c2ecf20Sopenharmony_ci}
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_ci/**
6178c2ecf20Sopenharmony_ci * calipso_optptr - Find the CALIPSO option in the packet
6188c2ecf20Sopenharmony_ci * @skb: the packet
6198c2ecf20Sopenharmony_ci *
6208c2ecf20Sopenharmony_ci * Description:
6218c2ecf20Sopenharmony_ci * Parse the packet's IP header looking for a CALIPSO option.  Returns a pointer
6228c2ecf20Sopenharmony_ci * to the start of the CALIPSO option on success, NULL if one if not found.
6238c2ecf20Sopenharmony_ci *
6248c2ecf20Sopenharmony_ci */
6258c2ecf20Sopenharmony_ciunsigned char *calipso_optptr(const struct sk_buff *skb)
6268c2ecf20Sopenharmony_ci{
6278c2ecf20Sopenharmony_ci	unsigned char *ret_val = NULL;
6288c2ecf20Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_ci	if (ops)
6318c2ecf20Sopenharmony_ci		ret_val = ops->skbuff_optptr(skb);
6328c2ecf20Sopenharmony_ci	return ret_val;
6338c2ecf20Sopenharmony_ci}
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_ci/**
6368c2ecf20Sopenharmony_ci * calipso_getattr - Get the security attributes from a memory block.
6378c2ecf20Sopenharmony_ci * @calipso: the CALIPSO option
6388c2ecf20Sopenharmony_ci * @secattr: the security attributes
6398c2ecf20Sopenharmony_ci *
6408c2ecf20Sopenharmony_ci * Description:
6418c2ecf20Sopenharmony_ci * Inspect @calipso and return the security attributes in @secattr.
6428c2ecf20Sopenharmony_ci * Returns zero on success and negative values on failure.
6438c2ecf20Sopenharmony_ci *
6448c2ecf20Sopenharmony_ci */
6458c2ecf20Sopenharmony_ciint calipso_getattr(const unsigned char *calipso,
6468c2ecf20Sopenharmony_ci		    struct netlbl_lsm_secattr *secattr)
6478c2ecf20Sopenharmony_ci{
6488c2ecf20Sopenharmony_ci	int ret_val = -ENOMSG;
6498c2ecf20Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_ci	if (ops)
6528c2ecf20Sopenharmony_ci		ret_val = ops->opt_getattr(calipso, secattr);
6538c2ecf20Sopenharmony_ci	return ret_val;
6548c2ecf20Sopenharmony_ci}
6558c2ecf20Sopenharmony_ci
6568c2ecf20Sopenharmony_ci/**
6578c2ecf20Sopenharmony_ci * calipso_skbuff_setattr - Set the CALIPSO option on a packet
6588c2ecf20Sopenharmony_ci * @skb: the packet
6598c2ecf20Sopenharmony_ci * @doi_def: the CALIPSO DOI to use
6608c2ecf20Sopenharmony_ci * @secattr: the security attributes
6618c2ecf20Sopenharmony_ci *
6628c2ecf20Sopenharmony_ci * Description:
6638c2ecf20Sopenharmony_ci * Set the CALIPSO option on the given packet based on the security attributes.
6648c2ecf20Sopenharmony_ci * Returns a pointer to the IP header on success and NULL on failure.
6658c2ecf20Sopenharmony_ci *
6668c2ecf20Sopenharmony_ci */
6678c2ecf20Sopenharmony_ciint calipso_skbuff_setattr(struct sk_buff *skb,
6688c2ecf20Sopenharmony_ci			   const struct calipso_doi *doi_def,
6698c2ecf20Sopenharmony_ci			   const struct netlbl_lsm_secattr *secattr)
6708c2ecf20Sopenharmony_ci{
6718c2ecf20Sopenharmony_ci	int ret_val = -ENOMSG;
6728c2ecf20Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
6738c2ecf20Sopenharmony_ci
6748c2ecf20Sopenharmony_ci	if (ops)
6758c2ecf20Sopenharmony_ci		ret_val = ops->skbuff_setattr(skb, doi_def, secattr);
6768c2ecf20Sopenharmony_ci	return ret_val;
6778c2ecf20Sopenharmony_ci}
6788c2ecf20Sopenharmony_ci
6798c2ecf20Sopenharmony_ci/**
6808c2ecf20Sopenharmony_ci * calipso_skbuff_delattr - Delete any CALIPSO options from a packet
6818c2ecf20Sopenharmony_ci * @skb: the packet
6828c2ecf20Sopenharmony_ci *
6838c2ecf20Sopenharmony_ci * Description:
6848c2ecf20Sopenharmony_ci * Removes any and all CALIPSO options from the given packet.  Returns zero on
6858c2ecf20Sopenharmony_ci * success, negative values on failure.
6868c2ecf20Sopenharmony_ci *
6878c2ecf20Sopenharmony_ci */
6888c2ecf20Sopenharmony_ciint calipso_skbuff_delattr(struct sk_buff *skb)
6898c2ecf20Sopenharmony_ci{
6908c2ecf20Sopenharmony_ci	int ret_val = -ENOMSG;
6918c2ecf20Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
6928c2ecf20Sopenharmony_ci
6938c2ecf20Sopenharmony_ci	if (ops)
6948c2ecf20Sopenharmony_ci		ret_val = ops->skbuff_delattr(skb);
6958c2ecf20Sopenharmony_ci	return ret_val;
6968c2ecf20Sopenharmony_ci}
6978c2ecf20Sopenharmony_ci
6988c2ecf20Sopenharmony_ci/**
6998c2ecf20Sopenharmony_ci * calipso_cache_invalidate - Invalidates the current CALIPSO cache
7008c2ecf20Sopenharmony_ci *
7018c2ecf20Sopenharmony_ci * Description:
7028c2ecf20Sopenharmony_ci * Invalidates and frees any entries in the CALIPSO cache.  Returns zero on
7038c2ecf20Sopenharmony_ci * success and negative values on failure.
7048c2ecf20Sopenharmony_ci *
7058c2ecf20Sopenharmony_ci */
7068c2ecf20Sopenharmony_civoid calipso_cache_invalidate(void)
7078c2ecf20Sopenharmony_ci{
7088c2ecf20Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
7098c2ecf20Sopenharmony_ci
7108c2ecf20Sopenharmony_ci	if (ops)
7118c2ecf20Sopenharmony_ci		ops->cache_invalidate();
7128c2ecf20Sopenharmony_ci}
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_ci/**
7158c2ecf20Sopenharmony_ci * calipso_cache_add - Add an entry to the CALIPSO cache
7168c2ecf20Sopenharmony_ci * @calipso_ptr: the CALIPSO option
7178c2ecf20Sopenharmony_ci * @secattr: the packet's security attributes
7188c2ecf20Sopenharmony_ci *
7198c2ecf20Sopenharmony_ci * Description:
7208c2ecf20Sopenharmony_ci * Add a new entry into the CALIPSO label mapping cache.
7218c2ecf20Sopenharmony_ci * Returns zero on success, negative values on failure.
7228c2ecf20Sopenharmony_ci *
7238c2ecf20Sopenharmony_ci */
7248c2ecf20Sopenharmony_ciint calipso_cache_add(const unsigned char *calipso_ptr,
7258c2ecf20Sopenharmony_ci		      const struct netlbl_lsm_secattr *secattr)
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_ci{
7288c2ecf20Sopenharmony_ci	int ret_val = -ENOMSG;
7298c2ecf20Sopenharmony_ci	const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
7308c2ecf20Sopenharmony_ci
7318c2ecf20Sopenharmony_ci	if (ops)
7328c2ecf20Sopenharmony_ci		ret_val = ops->cache_add(calipso_ptr, secattr);
7338c2ecf20Sopenharmony_ci	return ret_val;
7348c2ecf20Sopenharmony_ci}
735