11ccea77eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
296cb8e33SPaul Moore /*
396cb8e33SPaul Moore * NetLabel CIPSO/IPv4 Support
496cb8e33SPaul Moore *
596cb8e33SPaul Moore * This file defines the CIPSO/IPv4 functions for the NetLabel system. The
696cb8e33SPaul Moore * NetLabel system manages static and dynamic label mappings for network
796cb8e33SPaul Moore * protocols such as CIPSO and RIPSO.
896cb8e33SPaul Moore *
982c21bfaSPaul Moore * Author: Paul Moore <paul@paul-moore.com>
1096cb8e33SPaul Moore */
1196cb8e33SPaul Moore
1296cb8e33SPaul Moore /*
1396cb8e33SPaul Moore * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
1496cb8e33SPaul Moore */
1596cb8e33SPaul Moore
1696cb8e33SPaul Moore #include <linux/types.h>
1796cb8e33SPaul Moore #include <linux/socket.h>
1896cb8e33SPaul Moore #include <linux/string.h>
1996cb8e33SPaul Moore #include <linux/skbuff.h>
2032f50cdeSPaul Moore #include <linux/audit.h>
215a0e3ad6STejun Heo #include <linux/slab.h>
2296cb8e33SPaul Moore #include <net/sock.h>
2396cb8e33SPaul Moore #include <net/netlink.h>
2496cb8e33SPaul Moore #include <net/genetlink.h>
2596cb8e33SPaul Moore #include <net/netlabel.h>
2696cb8e33SPaul Moore #include <net/cipso_ipv4.h>
2760063497SArun Sharma #include <linux/atomic.h>
2896cb8e33SPaul Moore
2996cb8e33SPaul Moore #include "netlabel_user.h"
3096cb8e33SPaul Moore #include "netlabel_cipso_v4.h"
3123bcdc1aSPaul Moore #include "netlabel_mgmt.h"
32b1edeb10SPaul Moore #include "netlabel_domainhash.h"
3396cb8e33SPaul Moore
34fd385855SPaul Moore /* Argument struct for cipso_v4_doi_walk() */
35fd385855SPaul Moore struct netlbl_cipsov4_doiwalk_arg {
36fd385855SPaul Moore struct netlink_callback *nl_cb;
37fd385855SPaul Moore struct sk_buff *skb;
38fd385855SPaul Moore u32 seq;
39fd385855SPaul Moore };
40fd385855SPaul Moore
41b1edeb10SPaul Moore /* Argument struct for netlbl_domhsh_walk() */
42b1edeb10SPaul Moore struct netlbl_domhsh_walk_arg {
43b1edeb10SPaul Moore struct netlbl_audit *audit_info;
44b1edeb10SPaul Moore u32 doi;
45b1edeb10SPaul Moore };
46b1edeb10SPaul Moore
4796cb8e33SPaul Moore /* NetLabel Generic NETLINK CIPSOv4 family */
48489111e5SJohannes Berg static struct genl_family netlbl_cipsov4_gnl_family;
49fd385855SPaul Moore /* NetLabel Netlink attribute policy */
50ef7c79edSPatrick McHardy static const struct nla_policy netlbl_cipsov4_genl_policy[NLBL_CIPSOV4_A_MAX + 1] = {
51fd385855SPaul Moore [NLBL_CIPSOV4_A_DOI] = { .type = NLA_U32 },
52fd385855SPaul Moore [NLBL_CIPSOV4_A_MTYPE] = { .type = NLA_U32 },
53fd385855SPaul Moore [NLBL_CIPSOV4_A_TAG] = { .type = NLA_U8 },
54fd385855SPaul Moore [NLBL_CIPSOV4_A_TAGLST] = { .type = NLA_NESTED },
55fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSLVLLOC] = { .type = NLA_U32 },
56fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSLVLREM] = { .type = NLA_U32 },
57fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSLVL] = { .type = NLA_NESTED },
58fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSLVLLST] = { .type = NLA_NESTED },
59fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSCATLOC] = { .type = NLA_U32 },
60fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSCATREM] = { .type = NLA_U32 },
61fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSCAT] = { .type = NLA_NESTED },
62fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSCATLST] = { .type = NLA_NESTED },
63fd385855SPaul Moore };
6496cb8e33SPaul Moore
6596cb8e33SPaul Moore /*
6696cb8e33SPaul Moore * Helper Functions
6796cb8e33SPaul Moore */
6896cb8e33SPaul Moore
6996cb8e33SPaul Moore /**
70fd385855SPaul Moore * netlbl_cipsov4_add_common - Parse the common sections of a ADD message
71fd385855SPaul Moore * @info: the Generic NETLINK info block
72fd385855SPaul Moore * @doi_def: the CIPSO V4 DOI definition
73fd385855SPaul Moore *
74fd385855SPaul Moore * Description:
75fd385855SPaul Moore * Parse the common sections of a ADD message and fill in the related values
76fd385855SPaul Moore * in @doi_def. Returns zero on success, negative values on failure.
77fd385855SPaul Moore *
78fd385855SPaul Moore */
netlbl_cipsov4_add_common(struct genl_info * info,struct cipso_v4_doi * doi_def)79fd385855SPaul Moore static int netlbl_cipsov4_add_common(struct genl_info *info,
80fd385855SPaul Moore struct cipso_v4_doi *doi_def)
81fd385855SPaul Moore {
82fd385855SPaul Moore struct nlattr *nla;
83fd385855SPaul Moore int nla_rem;
84fd385855SPaul Moore u32 iter = 0;
85fd385855SPaul Moore
86fd385855SPaul Moore doi_def->doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
87fd385855SPaul Moore
888cb08174SJohannes Berg if (nla_validate_nested_deprecated(info->attrs[NLBL_CIPSOV4_A_TAGLST],
89fd385855SPaul Moore NLBL_CIPSOV4_A_MAX,
908cb08174SJohannes Berg netlbl_cipsov4_genl_policy,
918cb08174SJohannes Berg NULL) != 0)
92fd385855SPaul Moore return -EINVAL;
93fd385855SPaul Moore
94fd385855SPaul Moore nla_for_each_nested(nla, info->attrs[NLBL_CIPSOV4_A_TAGLST], nla_rem)
958f4c1f9bSThomas Graf if (nla_type(nla) == NLBL_CIPSOV4_A_TAG) {
962a2f11c2SPaul Moore if (iter >= CIPSO_V4_TAG_MAXCNT)
97fd385855SPaul Moore return -EINVAL;
98fd385855SPaul Moore doi_def->tags[iter++] = nla_get_u8(nla);
99fd385855SPaul Moore }
1002a2f11c2SPaul Moore while (iter < CIPSO_V4_TAG_MAXCNT)
1012a2f11c2SPaul Moore doi_def->tags[iter++] = CIPSO_V4_TAG_INVALID;
102fd385855SPaul Moore
103fd385855SPaul Moore return 0;
104fd385855SPaul Moore }
10596cb8e33SPaul Moore
10696cb8e33SPaul Moore /*
10796cb8e33SPaul Moore * NetLabel Command Handlers
10896cb8e33SPaul Moore */
10996cb8e33SPaul Moore
11096cb8e33SPaul Moore /**
11196cb8e33SPaul Moore * netlbl_cipsov4_add_std - Adds a CIPSO V4 DOI definition
112fd385855SPaul Moore * @info: the Generic NETLINK info block
1136c2e8ac0SPaul Moore * @audit_info: NetLabel audit information
11496cb8e33SPaul Moore *
11596cb8e33SPaul Moore * Description:
11615c45f7bSPaul Moore * Create a new CIPSO_V4_MAP_TRANS DOI definition based on the given ADD
11715c45f7bSPaul Moore * message and add it to the CIPSO V4 engine. Return zero on success and
11815c45f7bSPaul Moore * non-zero on error.
11996cb8e33SPaul Moore *
12096cb8e33SPaul Moore */
netlbl_cipsov4_add_std(struct genl_info * info,struct netlbl_audit * audit_info)1216c2e8ac0SPaul Moore static int netlbl_cipsov4_add_std(struct genl_info *info,
1226c2e8ac0SPaul Moore struct netlbl_audit *audit_info)
12396cb8e33SPaul Moore {
12496cb8e33SPaul Moore int ret_val = -EINVAL;
12596cb8e33SPaul Moore struct cipso_v4_doi *doi_def = NULL;
126fd385855SPaul Moore struct nlattr *nla_a;
127fd385855SPaul Moore struct nlattr *nla_b;
128fd385855SPaul Moore int nla_a_rem;
129fd385855SPaul Moore int nla_b_rem;
130caff5b6aSPaul Moore u32 iter;
13196cb8e33SPaul Moore
13232f50cdeSPaul Moore if (!info->attrs[NLBL_CIPSOV4_A_TAGLST] ||
133fd385855SPaul Moore !info->attrs[NLBL_CIPSOV4_A_MLSLVLLST])
134fd385855SPaul Moore return -EINVAL;
135fd385855SPaul Moore
1368cb08174SJohannes Berg if (nla_validate_nested_deprecated(info->attrs[NLBL_CIPSOV4_A_MLSLVLLST],
137fd385855SPaul Moore NLBL_CIPSOV4_A_MAX,
1388cb08174SJohannes Berg netlbl_cipsov4_genl_policy,
1398cb08174SJohannes Berg NULL) != 0)
140fd385855SPaul Moore return -EINVAL;
14196cb8e33SPaul Moore
14296cb8e33SPaul Moore doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL);
143fd385855SPaul Moore if (doi_def == NULL)
144fd385855SPaul Moore return -ENOMEM;
14596cb8e33SPaul Moore doi_def->map.std = kzalloc(sizeof(*doi_def->map.std), GFP_KERNEL);
14696cb8e33SPaul Moore if (doi_def->map.std == NULL) {
147e842cb60S王贇 kfree(doi_def);
148e842cb60S王贇 return -ENOMEM;
14996cb8e33SPaul Moore }
15015c45f7bSPaul Moore doi_def->type = CIPSO_V4_MAP_TRANS;
15196cb8e33SPaul Moore
152fd385855SPaul Moore ret_val = netlbl_cipsov4_add_common(info, doi_def);
153fd385855SPaul Moore if (ret_val != 0)
15496cb8e33SPaul Moore goto add_std_failure;
1551fd2a25bSPaul Moore ret_val = -EINVAL;
156fd385855SPaul Moore
157fd385855SPaul Moore nla_for_each_nested(nla_a,
158fd385855SPaul Moore info->attrs[NLBL_CIPSOV4_A_MLSLVLLST],
159fd385855SPaul Moore nla_a_rem)
1608f4c1f9bSThomas Graf if (nla_type(nla_a) == NLBL_CIPSOV4_A_MLSLVL) {
1618cb08174SJohannes Berg if (nla_validate_nested_deprecated(nla_a,
1628cb08174SJohannes Berg NLBL_CIPSOV4_A_MAX,
163fceb6435SJohannes Berg netlbl_cipsov4_genl_policy,
164fceb6435SJohannes Berg NULL) != 0)
1651fd2a25bSPaul Moore goto add_std_failure;
166fd385855SPaul Moore nla_for_each_nested(nla_b, nla_a, nla_b_rem)
1678f4c1f9bSThomas Graf switch (nla_type(nla_b)) {
168fd385855SPaul Moore case NLBL_CIPSOV4_A_MLSLVLLOC:
1691fd2a25bSPaul Moore if (nla_get_u32(nla_b) >
1701fd2a25bSPaul Moore CIPSO_V4_MAX_LOC_LVLS)
1711fd2a25bSPaul Moore goto add_std_failure;
172fd385855SPaul Moore if (nla_get_u32(nla_b) >=
173fd385855SPaul Moore doi_def->map.std->lvl.local_size)
174fd385855SPaul Moore doi_def->map.std->lvl.local_size =
175fd385855SPaul Moore nla_get_u32(nla_b) + 1;
17696cb8e33SPaul Moore break;
177fd385855SPaul Moore case NLBL_CIPSOV4_A_MLSLVLREM:
1781fd2a25bSPaul Moore if (nla_get_u32(nla_b) >
1791fd2a25bSPaul Moore CIPSO_V4_MAX_REM_LVLS)
1801fd2a25bSPaul Moore goto add_std_failure;
181fd385855SPaul Moore if (nla_get_u32(nla_b) >=
182fd385855SPaul Moore doi_def->map.std->lvl.cipso_size)
183fd385855SPaul Moore doi_def->map.std->lvl.cipso_size =
184fd385855SPaul Moore nla_get_u32(nla_b) + 1;
185fd385855SPaul Moore break;
18696cb8e33SPaul Moore }
18796cb8e33SPaul Moore }
18896cb8e33SPaul Moore doi_def->map.std->lvl.local = kcalloc(doi_def->map.std->lvl.local_size,
18996cb8e33SPaul Moore sizeof(u32),
1908ca34a13SPavel Skripkin GFP_KERNEL | __GFP_NOWARN);
19196cb8e33SPaul Moore if (doi_def->map.std->lvl.local == NULL) {
19296cb8e33SPaul Moore ret_val = -ENOMEM;
19396cb8e33SPaul Moore goto add_std_failure;
19496cb8e33SPaul Moore }
19596cb8e33SPaul Moore doi_def->map.std->lvl.cipso = kcalloc(doi_def->map.std->lvl.cipso_size,
19696cb8e33SPaul Moore sizeof(u32),
1978ca34a13SPavel Skripkin GFP_KERNEL | __GFP_NOWARN);
19896cb8e33SPaul Moore if (doi_def->map.std->lvl.cipso == NULL) {
19996cb8e33SPaul Moore ret_val = -ENOMEM;
20096cb8e33SPaul Moore goto add_std_failure;
20196cb8e33SPaul Moore }
202caff5b6aSPaul Moore for (iter = 0; iter < doi_def->map.std->lvl.local_size; iter++)
203caff5b6aSPaul Moore doi_def->map.std->lvl.local[iter] = CIPSO_V4_INV_LVL;
204caff5b6aSPaul Moore for (iter = 0; iter < doi_def->map.std->lvl.cipso_size; iter++)
205caff5b6aSPaul Moore doi_def->map.std->lvl.cipso[iter] = CIPSO_V4_INV_LVL;
206fd385855SPaul Moore nla_for_each_nested(nla_a,
207fd385855SPaul Moore info->attrs[NLBL_CIPSOV4_A_MLSLVLLST],
208fd385855SPaul Moore nla_a_rem)
2098f4c1f9bSThomas Graf if (nla_type(nla_a) == NLBL_CIPSOV4_A_MLSLVL) {
210fd385855SPaul Moore struct nlattr *lvl_loc;
211fd385855SPaul Moore struct nlattr *lvl_rem;
21296cb8e33SPaul Moore
213fd385855SPaul Moore lvl_loc = nla_find_nested(nla_a,
214fd385855SPaul Moore NLBL_CIPSOV4_A_MLSLVLLOC);
215fd385855SPaul Moore lvl_rem = nla_find_nested(nla_a,
216fd385855SPaul Moore NLBL_CIPSOV4_A_MLSLVLREM);
217fd385855SPaul Moore if (lvl_loc == NULL || lvl_rem == NULL)
218fd385855SPaul Moore goto add_std_failure;
219fd385855SPaul Moore doi_def->map.std->lvl.local[nla_get_u32(lvl_loc)] =
220fd385855SPaul Moore nla_get_u32(lvl_rem);
221fd385855SPaul Moore doi_def->map.std->lvl.cipso[nla_get_u32(lvl_rem)] =
222fd385855SPaul Moore nla_get_u32(lvl_loc);
223fd385855SPaul Moore }
224fd385855SPaul Moore
225fd385855SPaul Moore if (info->attrs[NLBL_CIPSOV4_A_MLSCATLST]) {
2268cb08174SJohannes Berg if (nla_validate_nested_deprecated(info->attrs[NLBL_CIPSOV4_A_MLSCATLST],
227fd385855SPaul Moore NLBL_CIPSOV4_A_MAX,
2288cb08174SJohannes Berg netlbl_cipsov4_genl_policy,
2298cb08174SJohannes Berg NULL) != 0)
230fd385855SPaul Moore goto add_std_failure;
231fd385855SPaul Moore
232fd385855SPaul Moore nla_for_each_nested(nla_a,
233fd385855SPaul Moore info->attrs[NLBL_CIPSOV4_A_MLSCATLST],
234fd385855SPaul Moore nla_a_rem)
2358f4c1f9bSThomas Graf if (nla_type(nla_a) == NLBL_CIPSOV4_A_MLSCAT) {
2368cb08174SJohannes Berg if (nla_validate_nested_deprecated(nla_a,
237fd385855SPaul Moore NLBL_CIPSOV4_A_MAX,
238fceb6435SJohannes Berg netlbl_cipsov4_genl_policy,
239fceb6435SJohannes Berg NULL) != 0)
240fd385855SPaul Moore goto add_std_failure;
241fd385855SPaul Moore nla_for_each_nested(nla_b, nla_a, nla_b_rem)
2428f4c1f9bSThomas Graf switch (nla_type(nla_b)) {
243fd385855SPaul Moore case NLBL_CIPSOV4_A_MLSCATLOC:
2441fd2a25bSPaul Moore if (nla_get_u32(nla_b) >
2451fd2a25bSPaul Moore CIPSO_V4_MAX_LOC_CATS)
2461fd2a25bSPaul Moore goto add_std_failure;
247fd385855SPaul Moore if (nla_get_u32(nla_b) >=
248fd385855SPaul Moore doi_def->map.std->cat.local_size)
249fd385855SPaul Moore doi_def->map.std->cat.local_size =
250fd385855SPaul Moore nla_get_u32(nla_b) + 1;
251fd385855SPaul Moore break;
252fd385855SPaul Moore case NLBL_CIPSOV4_A_MLSCATREM:
2531fd2a25bSPaul Moore if (nla_get_u32(nla_b) >
2541fd2a25bSPaul Moore CIPSO_V4_MAX_REM_CATS)
2551fd2a25bSPaul Moore goto add_std_failure;
256fd385855SPaul Moore if (nla_get_u32(nla_b) >=
257fd385855SPaul Moore doi_def->map.std->cat.cipso_size)
258fd385855SPaul Moore doi_def->map.std->cat.cipso_size =
259fd385855SPaul Moore nla_get_u32(nla_b) + 1;
260fd385855SPaul Moore break;
261fd385855SPaul Moore }
262fd385855SPaul Moore }
263fd385855SPaul Moore doi_def->map.std->cat.local = kcalloc(
264fd385855SPaul Moore doi_def->map.std->cat.local_size,
26596cb8e33SPaul Moore sizeof(u32),
2668ca34a13SPavel Skripkin GFP_KERNEL | __GFP_NOWARN);
26796cb8e33SPaul Moore if (doi_def->map.std->cat.local == NULL) {
26896cb8e33SPaul Moore ret_val = -ENOMEM;
26996cb8e33SPaul Moore goto add_std_failure;
27096cb8e33SPaul Moore }
271fd385855SPaul Moore doi_def->map.std->cat.cipso = kcalloc(
272fd385855SPaul Moore doi_def->map.std->cat.cipso_size,
27396cb8e33SPaul Moore sizeof(u32),
2748ca34a13SPavel Skripkin GFP_KERNEL | __GFP_NOWARN);
27596cb8e33SPaul Moore if (doi_def->map.std->cat.cipso == NULL) {
27696cb8e33SPaul Moore ret_val = -ENOMEM;
27796cb8e33SPaul Moore goto add_std_failure;
27896cb8e33SPaul Moore }
279caff5b6aSPaul Moore for (iter = 0; iter < doi_def->map.std->cat.local_size; iter++)
280caff5b6aSPaul Moore doi_def->map.std->cat.local[iter] = CIPSO_V4_INV_CAT;
281caff5b6aSPaul Moore for (iter = 0; iter < doi_def->map.std->cat.cipso_size; iter++)
282caff5b6aSPaul Moore doi_def->map.std->cat.cipso[iter] = CIPSO_V4_INV_CAT;
283fd385855SPaul Moore nla_for_each_nested(nla_a,
284fd385855SPaul Moore info->attrs[NLBL_CIPSOV4_A_MLSCATLST],
285fd385855SPaul Moore nla_a_rem)
2868f4c1f9bSThomas Graf if (nla_type(nla_a) == NLBL_CIPSOV4_A_MLSCAT) {
287fd385855SPaul Moore struct nlattr *cat_loc;
288fd385855SPaul Moore struct nlattr *cat_rem;
28996cb8e33SPaul Moore
290fd385855SPaul Moore cat_loc = nla_find_nested(nla_a,
291fd385855SPaul Moore NLBL_CIPSOV4_A_MLSCATLOC);
292fd385855SPaul Moore cat_rem = nla_find_nested(nla_a,
293fd385855SPaul Moore NLBL_CIPSOV4_A_MLSCATREM);
294fd385855SPaul Moore if (cat_loc == NULL || cat_rem == NULL)
29596cb8e33SPaul Moore goto add_std_failure;
296fd385855SPaul Moore doi_def->map.std->cat.local[
297fd385855SPaul Moore nla_get_u32(cat_loc)] =
298fd385855SPaul Moore nla_get_u32(cat_rem);
299fd385855SPaul Moore doi_def->map.std->cat.cipso[
300fd385855SPaul Moore nla_get_u32(cat_rem)] =
301fd385855SPaul Moore nla_get_u32(cat_loc);
302fd385855SPaul Moore }
30396cb8e33SPaul Moore }
30496cb8e33SPaul Moore
3056c2e8ac0SPaul Moore ret_val = cipso_v4_doi_add(doi_def, audit_info);
30696cb8e33SPaul Moore if (ret_val != 0)
30796cb8e33SPaul Moore goto add_std_failure;
30896cb8e33SPaul Moore return 0;
30996cb8e33SPaul Moore
31096cb8e33SPaul Moore add_std_failure:
311b1edeb10SPaul Moore cipso_v4_doi_free(doi_def);
31296cb8e33SPaul Moore return ret_val;
31396cb8e33SPaul Moore }
31496cb8e33SPaul Moore
31596cb8e33SPaul Moore /**
31696cb8e33SPaul Moore * netlbl_cipsov4_add_pass - Adds a CIPSO V4 DOI definition
317fd385855SPaul Moore * @info: the Generic NETLINK info block
3186c2e8ac0SPaul Moore * @audit_info: NetLabel audit information
31996cb8e33SPaul Moore *
32096cb8e33SPaul Moore * Description:
32196cb8e33SPaul Moore * Create a new CIPSO_V4_MAP_PASS DOI definition based on the given ADD message
32296cb8e33SPaul Moore * and add it to the CIPSO V4 engine. Return zero on success and non-zero on
32396cb8e33SPaul Moore * error.
32496cb8e33SPaul Moore *
32596cb8e33SPaul Moore */
netlbl_cipsov4_add_pass(struct genl_info * info,struct netlbl_audit * audit_info)3266c2e8ac0SPaul Moore static int netlbl_cipsov4_add_pass(struct genl_info *info,
3276c2e8ac0SPaul Moore struct netlbl_audit *audit_info)
32896cb8e33SPaul Moore {
329fd385855SPaul Moore int ret_val;
33096cb8e33SPaul Moore struct cipso_v4_doi *doi_def = NULL;
33196cb8e33SPaul Moore
33232f50cdeSPaul Moore if (!info->attrs[NLBL_CIPSOV4_A_TAGLST])
333fd385855SPaul Moore return -EINVAL;
33496cb8e33SPaul Moore
33596cb8e33SPaul Moore doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL);
336fd385855SPaul Moore if (doi_def == NULL)
337fd385855SPaul Moore return -ENOMEM;
33896cb8e33SPaul Moore doi_def->type = CIPSO_V4_MAP_PASS;
33996cb8e33SPaul Moore
340fd385855SPaul Moore ret_val = netlbl_cipsov4_add_common(info, doi_def);
341fd385855SPaul Moore if (ret_val != 0)
34296cb8e33SPaul Moore goto add_pass_failure;
34396cb8e33SPaul Moore
3446c2e8ac0SPaul Moore ret_val = cipso_v4_doi_add(doi_def, audit_info);
34596cb8e33SPaul Moore if (ret_val != 0)
34696cb8e33SPaul Moore goto add_pass_failure;
34796cb8e33SPaul Moore return 0;
34896cb8e33SPaul Moore
34996cb8e33SPaul Moore add_pass_failure:
350b1edeb10SPaul Moore cipso_v4_doi_free(doi_def);
35196cb8e33SPaul Moore return ret_val;
35296cb8e33SPaul Moore }
35396cb8e33SPaul Moore
35496cb8e33SPaul Moore /**
355d91d4079SPaul Moore * netlbl_cipsov4_add_local - Adds a CIPSO V4 DOI definition
356d91d4079SPaul Moore * @info: the Generic NETLINK info block
3576c2e8ac0SPaul Moore * @audit_info: NetLabel audit information
358d91d4079SPaul Moore *
359d91d4079SPaul Moore * Description:
360d91d4079SPaul Moore * Create a new CIPSO_V4_MAP_LOCAL DOI definition based on the given ADD
361d91d4079SPaul Moore * message and add it to the CIPSO V4 engine. Return zero on success and
362d91d4079SPaul Moore * non-zero on error.
363d91d4079SPaul Moore *
364d91d4079SPaul Moore */
netlbl_cipsov4_add_local(struct genl_info * info,struct netlbl_audit * audit_info)3656c2e8ac0SPaul Moore static int netlbl_cipsov4_add_local(struct genl_info *info,
3666c2e8ac0SPaul Moore struct netlbl_audit *audit_info)
367d91d4079SPaul Moore {
368d91d4079SPaul Moore int ret_val;
369d91d4079SPaul Moore struct cipso_v4_doi *doi_def = NULL;
370d91d4079SPaul Moore
371d91d4079SPaul Moore if (!info->attrs[NLBL_CIPSOV4_A_TAGLST])
372d91d4079SPaul Moore return -EINVAL;
373d91d4079SPaul Moore
374d91d4079SPaul Moore doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL);
375d91d4079SPaul Moore if (doi_def == NULL)
376d91d4079SPaul Moore return -ENOMEM;
377d91d4079SPaul Moore doi_def->type = CIPSO_V4_MAP_LOCAL;
378d91d4079SPaul Moore
379d91d4079SPaul Moore ret_val = netlbl_cipsov4_add_common(info, doi_def);
380d91d4079SPaul Moore if (ret_val != 0)
381d91d4079SPaul Moore goto add_local_failure;
382d91d4079SPaul Moore
3836c2e8ac0SPaul Moore ret_val = cipso_v4_doi_add(doi_def, audit_info);
384d91d4079SPaul Moore if (ret_val != 0)
385d91d4079SPaul Moore goto add_local_failure;
386d91d4079SPaul Moore return 0;
387d91d4079SPaul Moore
388d91d4079SPaul Moore add_local_failure:
389d91d4079SPaul Moore cipso_v4_doi_free(doi_def);
390d91d4079SPaul Moore return ret_val;
391d91d4079SPaul Moore }
392d91d4079SPaul Moore
393d91d4079SPaul Moore /**
39496cb8e33SPaul Moore * netlbl_cipsov4_add - Handle an ADD message
39596cb8e33SPaul Moore * @skb: the NETLINK buffer
39696cb8e33SPaul Moore * @info: the Generic NETLINK info block
39796cb8e33SPaul Moore *
39896cb8e33SPaul Moore * Description:
39996cb8e33SPaul Moore * Create a new DOI definition based on the given ADD message and add it to the
40096cb8e33SPaul Moore * CIPSO V4 engine. Returns zero on success, negative values on failure.
40196cb8e33SPaul Moore *
40296cb8e33SPaul Moore */
netlbl_cipsov4_add(struct sk_buff * skb,struct genl_info * info)40396cb8e33SPaul Moore static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info)
40496cb8e33SPaul Moore
40596cb8e33SPaul Moore {
40696cb8e33SPaul Moore int ret_val = -EINVAL;
40795d4e6beSPaul Moore struct netlbl_audit audit_info;
40896cb8e33SPaul Moore
40932f50cdeSPaul Moore if (!info->attrs[NLBL_CIPSOV4_A_DOI] ||
41032f50cdeSPaul Moore !info->attrs[NLBL_CIPSOV4_A_MTYPE])
411fd385855SPaul Moore return -EINVAL;
41296cb8e33SPaul Moore
413f7e0318aSZheng Yejian netlbl_netlink_auditinfo(&audit_info);
4146c2e8ac0SPaul Moore switch (nla_get_u32(info->attrs[NLBL_CIPSOV4_A_MTYPE])) {
41515c45f7bSPaul Moore case CIPSO_V4_MAP_TRANS:
4166c2e8ac0SPaul Moore ret_val = netlbl_cipsov4_add_std(info, &audit_info);
41796cb8e33SPaul Moore break;
41896cb8e33SPaul Moore case CIPSO_V4_MAP_PASS:
4196c2e8ac0SPaul Moore ret_val = netlbl_cipsov4_add_pass(info, &audit_info);
42096cb8e33SPaul Moore break;
421d91d4079SPaul Moore case CIPSO_V4_MAP_LOCAL:
4226c2e8ac0SPaul Moore ret_val = netlbl_cipsov4_add_local(info, &audit_info);
423d91d4079SPaul Moore break;
42496cb8e33SPaul Moore }
42523bcdc1aSPaul Moore if (ret_val == 0)
426c783f1ceSPaul Moore atomic_inc(&netlabel_mgmt_protocount);
42796cb8e33SPaul Moore
42896cb8e33SPaul Moore return ret_val;
42996cb8e33SPaul Moore }
43096cb8e33SPaul Moore
43196cb8e33SPaul Moore /**
43296cb8e33SPaul Moore * netlbl_cipsov4_list - Handle a LIST message
43396cb8e33SPaul Moore * @skb: the NETLINK buffer
43496cb8e33SPaul Moore * @info: the Generic NETLINK info block
43596cb8e33SPaul Moore *
43696cb8e33SPaul Moore * Description:
437fd385855SPaul Moore * Process a user generated LIST message and respond accordingly. While the
438fd385855SPaul Moore * response message generated by the kernel is straightforward, determining
439fd385855SPaul Moore * before hand the size of the buffer to allocate is not (we have to generate
440fd385855SPaul Moore * the message to know the size). In order to keep this function sane what we
441fd385855SPaul Moore * do is allocate a buffer of NLMSG_GOODSIZE and try to fit the response in
442fd385855SPaul Moore * that size, if we fail then we restart with a larger buffer and try again.
443fd385855SPaul Moore * We continue in this manner until we hit a limit of failed attempts then we
444fd385855SPaul Moore * give up and just send an error message. Returns zero on success and
445fd385855SPaul Moore * negative values on error.
44696cb8e33SPaul Moore *
44796cb8e33SPaul Moore */
netlbl_cipsov4_list(struct sk_buff * skb,struct genl_info * info)44896cb8e33SPaul Moore static int netlbl_cipsov4_list(struct sk_buff *skb, struct genl_info *info)
44996cb8e33SPaul Moore {
450fd385855SPaul Moore int ret_val;
451fd385855SPaul Moore struct sk_buff *ans_skb = NULL;
452fd385855SPaul Moore u32 nlsze_mult = 1;
453fd385855SPaul Moore void *data;
45496cb8e33SPaul Moore u32 doi;
455fd385855SPaul Moore struct nlattr *nla_a;
456fd385855SPaul Moore struct nlattr *nla_b;
457fd385855SPaul Moore struct cipso_v4_doi *doi_def;
458fd385855SPaul Moore u32 iter;
45996cb8e33SPaul Moore
460fd385855SPaul Moore if (!info->attrs[NLBL_CIPSOV4_A_DOI]) {
461fd385855SPaul Moore ret_val = -EINVAL;
46296cb8e33SPaul Moore goto list_failure;
463fd385855SPaul Moore }
46496cb8e33SPaul Moore
465fd385855SPaul Moore list_start:
466339bf98fSThomas Graf ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE * nlsze_mult, GFP_KERNEL);
46796cb8e33SPaul Moore if (ans_skb == NULL) {
46896cb8e33SPaul Moore ret_val = -ENOMEM;
46996cb8e33SPaul Moore goto list_failure;
47096cb8e33SPaul Moore }
47117c157c8SThomas Graf data = genlmsg_put_reply(ans_skb, info, &netlbl_cipsov4_gnl_family,
47217c157c8SThomas Graf 0, NLBL_CIPSOV4_C_LIST);
473fd385855SPaul Moore if (data == NULL) {
474fd385855SPaul Moore ret_val = -ENOMEM;
475fd385855SPaul Moore goto list_failure;
476fd385855SPaul Moore }
47796cb8e33SPaul Moore
478fd385855SPaul Moore doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
479fd385855SPaul Moore
480fd385855SPaul Moore rcu_read_lock();
481fd385855SPaul Moore doi_def = cipso_v4_doi_getdef(doi);
482fd385855SPaul Moore if (doi_def == NULL) {
483fd385855SPaul Moore ret_val = -EINVAL;
48456196701SPaul Moore goto list_failure_lock;
485fd385855SPaul Moore }
486fd385855SPaul Moore
487fd385855SPaul Moore ret_val = nla_put_u32(ans_skb, NLBL_CIPSOV4_A_MTYPE, doi_def->type);
488fd385855SPaul Moore if (ret_val != 0)
489fd385855SPaul Moore goto list_failure_lock;
490fd385855SPaul Moore
491ae0be8deSMichal Kubecek nla_a = nla_nest_start_noflag(ans_skb, NLBL_CIPSOV4_A_TAGLST);
492fd385855SPaul Moore if (nla_a == NULL) {
493fd385855SPaul Moore ret_val = -ENOMEM;
494fd385855SPaul Moore goto list_failure_lock;
495fd385855SPaul Moore }
496fd385855SPaul Moore for (iter = 0;
497fd385855SPaul Moore iter < CIPSO_V4_TAG_MAXCNT &&
498fd385855SPaul Moore doi_def->tags[iter] != CIPSO_V4_TAG_INVALID;
499fd385855SPaul Moore iter++) {
500fd385855SPaul Moore ret_val = nla_put_u8(ans_skb,
501fd385855SPaul Moore NLBL_CIPSOV4_A_TAG,
502fd385855SPaul Moore doi_def->tags[iter]);
503fd385855SPaul Moore if (ret_val != 0)
504fd385855SPaul Moore goto list_failure_lock;
505fd385855SPaul Moore }
506fd385855SPaul Moore nla_nest_end(ans_skb, nla_a);
507fd385855SPaul Moore
508fd385855SPaul Moore switch (doi_def->type) {
50915c45f7bSPaul Moore case CIPSO_V4_MAP_TRANS:
510ae0be8deSMichal Kubecek nla_a = nla_nest_start_noflag(ans_skb,
511ae0be8deSMichal Kubecek NLBL_CIPSOV4_A_MLSLVLLST);
512fd385855SPaul Moore if (nla_a == NULL) {
513fd385855SPaul Moore ret_val = -ENOMEM;
514fd385855SPaul Moore goto list_failure_lock;
515fd385855SPaul Moore }
516fd385855SPaul Moore for (iter = 0;
517fd385855SPaul Moore iter < doi_def->map.std->lvl.local_size;
518fd385855SPaul Moore iter++) {
519fd385855SPaul Moore if (doi_def->map.std->lvl.local[iter] ==
520fd385855SPaul Moore CIPSO_V4_INV_LVL)
521fd385855SPaul Moore continue;
522fd385855SPaul Moore
523ae0be8deSMichal Kubecek nla_b = nla_nest_start_noflag(ans_skb,
524ae0be8deSMichal Kubecek NLBL_CIPSOV4_A_MLSLVL);
525fd385855SPaul Moore if (nla_b == NULL) {
526fd385855SPaul Moore ret_val = -ENOMEM;
527fd385855SPaul Moore goto list_retry;
528fd385855SPaul Moore }
529fd385855SPaul Moore ret_val = nla_put_u32(ans_skb,
530fd385855SPaul Moore NLBL_CIPSOV4_A_MLSLVLLOC,
531fd385855SPaul Moore iter);
532fd385855SPaul Moore if (ret_val != 0)
533fd385855SPaul Moore goto list_retry;
534fd385855SPaul Moore ret_val = nla_put_u32(ans_skb,
535fd385855SPaul Moore NLBL_CIPSOV4_A_MLSLVLREM,
536fd385855SPaul Moore doi_def->map.std->lvl.local[iter]);
537fd385855SPaul Moore if (ret_val != 0)
538fd385855SPaul Moore goto list_retry;
539fd385855SPaul Moore nla_nest_end(ans_skb, nla_b);
540fd385855SPaul Moore }
541fd385855SPaul Moore nla_nest_end(ans_skb, nla_a);
542fd385855SPaul Moore
543ae0be8deSMichal Kubecek nla_a = nla_nest_start_noflag(ans_skb,
544ae0be8deSMichal Kubecek NLBL_CIPSOV4_A_MLSCATLST);
545fd385855SPaul Moore if (nla_a == NULL) {
546fd385855SPaul Moore ret_val = -ENOMEM;
547fd385855SPaul Moore goto list_retry;
548fd385855SPaul Moore }
549fd385855SPaul Moore for (iter = 0;
550fd385855SPaul Moore iter < doi_def->map.std->cat.local_size;
551fd385855SPaul Moore iter++) {
552fd385855SPaul Moore if (doi_def->map.std->cat.local[iter] ==
553fd385855SPaul Moore CIPSO_V4_INV_CAT)
554fd385855SPaul Moore continue;
555fd385855SPaul Moore
556ae0be8deSMichal Kubecek nla_b = nla_nest_start_noflag(ans_skb,
557ae0be8deSMichal Kubecek NLBL_CIPSOV4_A_MLSCAT);
558fd385855SPaul Moore if (nla_b == NULL) {
559fd385855SPaul Moore ret_val = -ENOMEM;
560fd385855SPaul Moore goto list_retry;
561fd385855SPaul Moore }
562fd385855SPaul Moore ret_val = nla_put_u32(ans_skb,
563fd385855SPaul Moore NLBL_CIPSOV4_A_MLSCATLOC,
564fd385855SPaul Moore iter);
565fd385855SPaul Moore if (ret_val != 0)
566fd385855SPaul Moore goto list_retry;
567fd385855SPaul Moore ret_val = nla_put_u32(ans_skb,
568fd385855SPaul Moore NLBL_CIPSOV4_A_MLSCATREM,
569fd385855SPaul Moore doi_def->map.std->cat.local[iter]);
570fd385855SPaul Moore if (ret_val != 0)
571fd385855SPaul Moore goto list_retry;
572fd385855SPaul Moore nla_nest_end(ans_skb, nla_b);
573fd385855SPaul Moore }
574fd385855SPaul Moore nla_nest_end(ans_skb, nla_a);
575fd385855SPaul Moore
576fd385855SPaul Moore break;
577fd385855SPaul Moore }
578ad5d07f4SPaul Moore cipso_v4_doi_putdef(doi_def);
579fd385855SPaul Moore rcu_read_unlock();
580fd385855SPaul Moore
581fd385855SPaul Moore genlmsg_end(ans_skb, data);
582fe785beeSDenis V. Lunev return genlmsg_reply(ans_skb, info);
58396cb8e33SPaul Moore
584fd385855SPaul Moore list_retry:
585fd385855SPaul Moore /* XXX - this limit is a guesstimate */
586fd385855SPaul Moore if (nlsze_mult < 4) {
587ad5d07f4SPaul Moore cipso_v4_doi_putdef(doi_def);
588fd385855SPaul Moore rcu_read_unlock();
589fd385855SPaul Moore kfree_skb(ans_skb);
59083aa2e96SDenis V. Lunev nlsze_mult *= 2;
591fd385855SPaul Moore goto list_start;
592fd385855SPaul Moore }
593fd385855SPaul Moore list_failure_lock:
594ad5d07f4SPaul Moore cipso_v4_doi_putdef(doi_def);
595fd385855SPaul Moore rcu_read_unlock();
59696cb8e33SPaul Moore list_failure:
597fd385855SPaul Moore kfree_skb(ans_skb);
598fd385855SPaul Moore return ret_val;
599fd385855SPaul Moore }
600fd385855SPaul Moore
601fd385855SPaul Moore /**
602fd385855SPaul Moore * netlbl_cipsov4_listall_cb - cipso_v4_doi_walk() callback for LISTALL
603fd385855SPaul Moore * @doi_def: the CIPSOv4 DOI definition
604fd385855SPaul Moore * @arg: the netlbl_cipsov4_doiwalk_arg structure
605fd385855SPaul Moore *
606fd385855SPaul Moore * Description:
607fd385855SPaul Moore * This function is designed to be used as a callback to the
608fd385855SPaul Moore * cipso_v4_doi_walk() function for use in generating a response for a LISTALL
609fd385855SPaul Moore * message. Returns the size of the message on success, negative values on
610fd385855SPaul Moore * failure.
611fd385855SPaul Moore *
612fd385855SPaul Moore */
netlbl_cipsov4_listall_cb(struct cipso_v4_doi * doi_def,void * arg)613fd385855SPaul Moore static int netlbl_cipsov4_listall_cb(struct cipso_v4_doi *doi_def, void *arg)
614fd385855SPaul Moore {
615fd385855SPaul Moore int ret_val = -ENOMEM;
616fd385855SPaul Moore struct netlbl_cipsov4_doiwalk_arg *cb_arg = arg;
617fd385855SPaul Moore void *data;
618fd385855SPaul Moore
61915e47304SEric W. Biederman data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).portid,
62017c157c8SThomas Graf cb_arg->seq, &netlbl_cipsov4_gnl_family,
62117c157c8SThomas Graf NLM_F_MULTI, NLBL_CIPSOV4_C_LISTALL);
622fd385855SPaul Moore if (data == NULL)
623fd385855SPaul Moore goto listall_cb_failure;
624fd385855SPaul Moore
625fd385855SPaul Moore ret_val = nla_put_u32(cb_arg->skb, NLBL_CIPSOV4_A_DOI, doi_def->doi);
626fd385855SPaul Moore if (ret_val != 0)
627fd385855SPaul Moore goto listall_cb_failure;
628fd385855SPaul Moore ret_val = nla_put_u32(cb_arg->skb,
629fd385855SPaul Moore NLBL_CIPSOV4_A_MTYPE,
630fd385855SPaul Moore doi_def->type);
631fd385855SPaul Moore if (ret_val != 0)
632fd385855SPaul Moore goto listall_cb_failure;
633fd385855SPaul Moore
634053c095aSJohannes Berg genlmsg_end(cb_arg->skb, data);
635053c095aSJohannes Berg return 0;
636fd385855SPaul Moore
637fd385855SPaul Moore listall_cb_failure:
638fd385855SPaul Moore genlmsg_cancel(cb_arg->skb, data);
63996cb8e33SPaul Moore return ret_val;
64096cb8e33SPaul Moore }
64196cb8e33SPaul Moore
64296cb8e33SPaul Moore /**
64396cb8e33SPaul Moore * netlbl_cipsov4_listall - Handle a LISTALL message
64496cb8e33SPaul Moore * @skb: the NETLINK buffer
645fd385855SPaul Moore * @cb: the NETLINK callback
64696cb8e33SPaul Moore *
64796cb8e33SPaul Moore * Description:
64896cb8e33SPaul Moore * Process a user generated LISTALL message and respond accordingly. Returns
64996cb8e33SPaul Moore * zero on success and negative values on error.
65096cb8e33SPaul Moore *
65196cb8e33SPaul Moore */
netlbl_cipsov4_listall(struct sk_buff * skb,struct netlink_callback * cb)652fd385855SPaul Moore static int netlbl_cipsov4_listall(struct sk_buff *skb,
653fd385855SPaul Moore struct netlink_callback *cb)
65496cb8e33SPaul Moore {
655fd385855SPaul Moore struct netlbl_cipsov4_doiwalk_arg cb_arg;
65656196701SPaul Moore u32 doi_skip = cb->args[0];
65796cb8e33SPaul Moore
658fd385855SPaul Moore cb_arg.nl_cb = cb;
659fd385855SPaul Moore cb_arg.skb = skb;
660fd385855SPaul Moore cb_arg.seq = cb->nlh->nlmsg_seq;
66196cb8e33SPaul Moore
662fd385855SPaul Moore cipso_v4_doi_walk(&doi_skip, netlbl_cipsov4_listall_cb, &cb_arg);
66396cb8e33SPaul Moore
664fd385855SPaul Moore cb->args[0] = doi_skip;
665fd385855SPaul Moore return skb->len;
66696cb8e33SPaul Moore }
66796cb8e33SPaul Moore
66896cb8e33SPaul Moore /**
669b1edeb10SPaul Moore * netlbl_cipsov4_remove_cb - netlbl_cipsov4_remove() callback for REMOVE
670b1edeb10SPaul Moore * @entry: LSM domain mapping entry
671b1edeb10SPaul Moore * @arg: the netlbl_domhsh_walk_arg structure
672b1edeb10SPaul Moore *
673b1edeb10SPaul Moore * Description:
674b1edeb10SPaul Moore * This function is intended for use by netlbl_cipsov4_remove() as the callback
675b1edeb10SPaul Moore * for the netlbl_domhsh_walk() function; it removes LSM domain map entries
676b1edeb10SPaul Moore * which are associated with the CIPSO DOI specified in @arg. Returns zero on
677b1edeb10SPaul Moore * success, negative values on failure.
678b1edeb10SPaul Moore *
679b1edeb10SPaul Moore */
netlbl_cipsov4_remove_cb(struct netlbl_dom_map * entry,void * arg)680b1edeb10SPaul Moore static int netlbl_cipsov4_remove_cb(struct netlbl_dom_map *entry, void *arg)
681b1edeb10SPaul Moore {
682b1edeb10SPaul Moore struct netlbl_domhsh_walk_arg *cb_arg = arg;
683b1edeb10SPaul Moore
6846a8b7f0cSPaul Moore if (entry->def.type == NETLBL_NLTYPE_CIPSOV4 &&
6856a8b7f0cSPaul Moore entry->def.cipso->doi == cb_arg->doi)
686b1edeb10SPaul Moore return netlbl_domhsh_remove_entry(entry, cb_arg->audit_info);
687b1edeb10SPaul Moore
688b1edeb10SPaul Moore return 0;
689b1edeb10SPaul Moore }
690b1edeb10SPaul Moore
691b1edeb10SPaul Moore /**
69296cb8e33SPaul Moore * netlbl_cipsov4_remove - Handle a REMOVE message
69396cb8e33SPaul Moore * @skb: the NETLINK buffer
69496cb8e33SPaul Moore * @info: the Generic NETLINK info block
69596cb8e33SPaul Moore *
69696cb8e33SPaul Moore * Description:
69796cb8e33SPaul Moore * Process a user generated REMOVE message and respond accordingly. Returns
69896cb8e33SPaul Moore * zero on success, negative values on failure.
69996cb8e33SPaul Moore *
70096cb8e33SPaul Moore */
netlbl_cipsov4_remove(struct sk_buff * skb,struct genl_info * info)70196cb8e33SPaul Moore static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info)
70296cb8e33SPaul Moore {
703fd385855SPaul Moore int ret_val = -EINVAL;
704b1edeb10SPaul Moore struct netlbl_domhsh_walk_arg cb_arg;
70595d4e6beSPaul Moore struct netlbl_audit audit_info;
706b1edeb10SPaul Moore u32 skip_bkt = 0;
707b1edeb10SPaul Moore u32 skip_chain = 0;
70896cb8e33SPaul Moore
70995d4e6beSPaul Moore if (!info->attrs[NLBL_CIPSOV4_A_DOI])
71095d4e6beSPaul Moore return -EINVAL;
71195d4e6beSPaul Moore
712f7e0318aSZheng Yejian netlbl_netlink_auditinfo(&audit_info);
7136c2e8ac0SPaul Moore cb_arg.doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
714b1edeb10SPaul Moore cb_arg.audit_info = &audit_info;
715b1edeb10SPaul Moore ret_val = netlbl_domhsh_walk(&skip_bkt, &skip_chain,
716b1edeb10SPaul Moore netlbl_cipsov4_remove_cb, &cb_arg);
717b1edeb10SPaul Moore if (ret_val == 0 || ret_val == -ENOENT) {
7186c2e8ac0SPaul Moore ret_val = cipso_v4_doi_remove(cb_arg.doi, &audit_info);
71923bcdc1aSPaul Moore if (ret_val == 0)
720c783f1ceSPaul Moore atomic_dec(&netlabel_mgmt_protocount);
721b1edeb10SPaul Moore }
72295d4e6beSPaul Moore
72396cb8e33SPaul Moore return ret_val;
72496cb8e33SPaul Moore }
72596cb8e33SPaul Moore
72696cb8e33SPaul Moore /*
72796cb8e33SPaul Moore * NetLabel Generic NETLINK Command Definitions
72896cb8e33SPaul Moore */
72996cb8e33SPaul Moore
73066a9b928SJakub Kicinski static const struct genl_small_ops netlbl_cipsov4_ops[] = {
731227c43c3SPavel Emelyanov {
73296cb8e33SPaul Moore .cmd = NLBL_CIPSOV4_C_ADD,
733ef6243acSJohannes Berg .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
734fd385855SPaul Moore .flags = GENL_ADMIN_PERM,
73596cb8e33SPaul Moore .doit = netlbl_cipsov4_add,
73696cb8e33SPaul Moore .dumpit = NULL,
737227c43c3SPavel Emelyanov },
738227c43c3SPavel Emelyanov {
73996cb8e33SPaul Moore .cmd = NLBL_CIPSOV4_C_REMOVE,
740ef6243acSJohannes Berg .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
741fd385855SPaul Moore .flags = GENL_ADMIN_PERM,
74296cb8e33SPaul Moore .doit = netlbl_cipsov4_remove,
74396cb8e33SPaul Moore .dumpit = NULL,
744227c43c3SPavel Emelyanov },
745227c43c3SPavel Emelyanov {
74696cb8e33SPaul Moore .cmd = NLBL_CIPSOV4_C_LIST,
747ef6243acSJohannes Berg .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
74896cb8e33SPaul Moore .flags = 0,
74996cb8e33SPaul Moore .doit = netlbl_cipsov4_list,
75096cb8e33SPaul Moore .dumpit = NULL,
751227c43c3SPavel Emelyanov },
752227c43c3SPavel Emelyanov {
75396cb8e33SPaul Moore .cmd = NLBL_CIPSOV4_C_LISTALL,
754ef6243acSJohannes Berg .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
75596cb8e33SPaul Moore .flags = 0,
756fd385855SPaul Moore .doit = NULL,
757fd385855SPaul Moore .dumpit = netlbl_cipsov4_listall,
758227c43c3SPavel Emelyanov },
75996cb8e33SPaul Moore };
76096cb8e33SPaul Moore
76156989f6dSJohannes Berg static struct genl_family netlbl_cipsov4_gnl_family __ro_after_init = {
762489111e5SJohannes Berg .hdrsize = 0,
763489111e5SJohannes Berg .name = NETLBL_NLTYPE_CIPSOV4_NAME,
764489111e5SJohannes Berg .version = NETLBL_PROTO_VERSION,
765489111e5SJohannes Berg .maxattr = NLBL_CIPSOV4_A_MAX,
7663b0f31f2SJohannes Berg .policy = netlbl_cipsov4_genl_policy,
767489111e5SJohannes Berg .module = THIS_MODULE,
76866a9b928SJakub Kicinski .small_ops = netlbl_cipsov4_ops,
76966a9b928SJakub Kicinski .n_small_ops = ARRAY_SIZE(netlbl_cipsov4_ops),
770*9c5d03d3SJakub Kicinski .resv_start_op = NLBL_CIPSOV4_C_LISTALL + 1,
771489111e5SJohannes Berg };
772489111e5SJohannes Berg
77396cb8e33SPaul Moore /*
77496cb8e33SPaul Moore * NetLabel Generic NETLINK Protocol Functions
77596cb8e33SPaul Moore */
77696cb8e33SPaul Moore
77796cb8e33SPaul Moore /**
77896cb8e33SPaul Moore * netlbl_cipsov4_genl_init - Register the CIPSOv4 NetLabel component
77996cb8e33SPaul Moore *
78096cb8e33SPaul Moore * Description:
78196cb8e33SPaul Moore * Register the CIPSOv4 packet NetLabel component with the Generic NETLINK
78296cb8e33SPaul Moore * mechanism. Returns zero on success, negative values on failure.
78396cb8e33SPaul Moore *
78496cb8e33SPaul Moore */
netlbl_cipsov4_genl_init(void)78505705e4eSPavel Emelyanov int __init netlbl_cipsov4_genl_init(void)
78696cb8e33SPaul Moore {
787489111e5SJohannes Berg return genl_register_family(&netlbl_cipsov4_gnl_family);
78896cb8e33SPaul Moore }
789