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 */ 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 */ 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) { 14796cb8e33SPaul Moore ret_val = -ENOMEM; 14896cb8e33SPaul Moore goto add_std_failure; 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), 190*8ca34a13SPavel 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), 197*8ca34a13SPavel 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), 266*8ca34a13SPavel 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), 274*8ca34a13SPavel 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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), 770489111e5SJohannes Berg }; 771489111e5SJohannes Berg 77296cb8e33SPaul Moore /* 77396cb8e33SPaul Moore * NetLabel Generic NETLINK Protocol Functions 77496cb8e33SPaul Moore */ 77596cb8e33SPaul Moore 77696cb8e33SPaul Moore /** 77796cb8e33SPaul Moore * netlbl_cipsov4_genl_init - Register the CIPSOv4 NetLabel component 77896cb8e33SPaul Moore * 77996cb8e33SPaul Moore * Description: 78096cb8e33SPaul Moore * Register the CIPSOv4 packet NetLabel component with the Generic NETLINK 78196cb8e33SPaul Moore * mechanism. Returns zero on success, negative values on failure. 78296cb8e33SPaul Moore * 78396cb8e33SPaul Moore */ 78405705e4eSPavel Emelyanov int __init netlbl_cipsov4_genl_init(void) 78596cb8e33SPaul Moore { 786489111e5SJohannes Berg return genl_register_family(&netlbl_cipsov4_gnl_family); 78796cb8e33SPaul Moore } 788