196cb8e33SPaul Moore /* 296cb8e33SPaul Moore * NetLabel CIPSO/IPv4 Support 396cb8e33SPaul Moore * 496cb8e33SPaul Moore * This file defines the CIPSO/IPv4 functions for the NetLabel system. The 596cb8e33SPaul Moore * NetLabel system manages static and dynamic label mappings for network 696cb8e33SPaul Moore * protocols such as CIPSO and RIPSO. 796cb8e33SPaul Moore * 896cb8e33SPaul Moore * Author: Paul Moore <paul.moore@hp.com> 996cb8e33SPaul Moore * 1096cb8e33SPaul Moore */ 1196cb8e33SPaul Moore 1296cb8e33SPaul Moore /* 1396cb8e33SPaul Moore * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 1496cb8e33SPaul Moore * 1596cb8e33SPaul Moore * This program is free software; you can redistribute it and/or modify 1696cb8e33SPaul Moore * it under the terms of the GNU General Public License as published by 1796cb8e33SPaul Moore * the Free Software Foundation; either version 2 of the License, or 1896cb8e33SPaul Moore * (at your option) any later version. 1996cb8e33SPaul Moore * 2096cb8e33SPaul Moore * This program is distributed in the hope that it will be useful, 2196cb8e33SPaul Moore * but WITHOUT ANY WARRANTY; without even the implied warranty of 2296cb8e33SPaul Moore * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 2396cb8e33SPaul Moore * the GNU General Public License for more details. 2496cb8e33SPaul Moore * 2596cb8e33SPaul Moore * You should have received a copy of the GNU General Public License 2696cb8e33SPaul Moore * along with this program; if not, write to the Free Software 2796cb8e33SPaul Moore * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 2896cb8e33SPaul Moore * 2996cb8e33SPaul Moore */ 3096cb8e33SPaul Moore 3196cb8e33SPaul Moore #include <linux/types.h> 3296cb8e33SPaul Moore #include <linux/socket.h> 3396cb8e33SPaul Moore #include <linux/string.h> 3496cb8e33SPaul Moore #include <linux/skbuff.h> 3532f50cdeSPaul Moore #include <linux/audit.h> 3696cb8e33SPaul Moore #include <net/sock.h> 3796cb8e33SPaul Moore #include <net/netlink.h> 3896cb8e33SPaul Moore #include <net/genetlink.h> 3996cb8e33SPaul Moore #include <net/netlabel.h> 4096cb8e33SPaul Moore #include <net/cipso_ipv4.h> 41c783f1ceSPaul Moore #include <asm/atomic.h> 4296cb8e33SPaul Moore 4396cb8e33SPaul Moore #include "netlabel_user.h" 4496cb8e33SPaul Moore #include "netlabel_cipso_v4.h" 4523bcdc1aSPaul Moore #include "netlabel_mgmt.h" 46b1edeb10SPaul Moore #include "netlabel_domainhash.h" 4796cb8e33SPaul Moore 48fd385855SPaul Moore /* Argument struct for cipso_v4_doi_walk() */ 49fd385855SPaul Moore struct netlbl_cipsov4_doiwalk_arg { 50fd385855SPaul Moore struct netlink_callback *nl_cb; 51fd385855SPaul Moore struct sk_buff *skb; 52fd385855SPaul Moore u32 seq; 53fd385855SPaul Moore }; 54fd385855SPaul Moore 55b1edeb10SPaul Moore /* Argument struct for netlbl_domhsh_walk() */ 56b1edeb10SPaul Moore struct netlbl_domhsh_walk_arg { 57b1edeb10SPaul Moore struct netlbl_audit *audit_info; 58b1edeb10SPaul Moore u32 doi; 59b1edeb10SPaul Moore }; 60b1edeb10SPaul Moore 6196cb8e33SPaul Moore /* NetLabel Generic NETLINK CIPSOv4 family */ 6296cb8e33SPaul Moore static struct genl_family netlbl_cipsov4_gnl_family = { 6396cb8e33SPaul Moore .id = GENL_ID_GENERATE, 6496cb8e33SPaul Moore .hdrsize = 0, 6596cb8e33SPaul Moore .name = NETLBL_NLTYPE_CIPSOV4_NAME, 6696cb8e33SPaul Moore .version = NETLBL_PROTO_VERSION, 67fd385855SPaul Moore .maxattr = NLBL_CIPSOV4_A_MAX, 6896cb8e33SPaul Moore }; 6996cb8e33SPaul Moore 70fd385855SPaul Moore /* NetLabel Netlink attribute policy */ 71ef7c79edSPatrick McHardy static const struct nla_policy netlbl_cipsov4_genl_policy[NLBL_CIPSOV4_A_MAX + 1] = { 72fd385855SPaul Moore [NLBL_CIPSOV4_A_DOI] = { .type = NLA_U32 }, 73fd385855SPaul Moore [NLBL_CIPSOV4_A_MTYPE] = { .type = NLA_U32 }, 74fd385855SPaul Moore [NLBL_CIPSOV4_A_TAG] = { .type = NLA_U8 }, 75fd385855SPaul Moore [NLBL_CIPSOV4_A_TAGLST] = { .type = NLA_NESTED }, 76fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSLVLLOC] = { .type = NLA_U32 }, 77fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSLVLREM] = { .type = NLA_U32 }, 78fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSLVL] = { .type = NLA_NESTED }, 79fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSLVLLST] = { .type = NLA_NESTED }, 80fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSCATLOC] = { .type = NLA_U32 }, 81fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSCATREM] = { .type = NLA_U32 }, 82fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSCAT] = { .type = NLA_NESTED }, 83fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSCATLST] = { .type = NLA_NESTED }, 84fd385855SPaul Moore }; 8596cb8e33SPaul Moore 8696cb8e33SPaul Moore /* 8796cb8e33SPaul Moore * Helper Functions 8896cb8e33SPaul Moore */ 8996cb8e33SPaul Moore 9096cb8e33SPaul Moore /** 91fd385855SPaul Moore * netlbl_cipsov4_add_common - Parse the common sections of a ADD message 92fd385855SPaul Moore * @info: the Generic NETLINK info block 93fd385855SPaul Moore * @doi_def: the CIPSO V4 DOI definition 94fd385855SPaul Moore * 95fd385855SPaul Moore * Description: 96fd385855SPaul Moore * Parse the common sections of a ADD message and fill in the related values 97fd385855SPaul Moore * in @doi_def. Returns zero on success, negative values on failure. 98fd385855SPaul Moore * 99fd385855SPaul Moore */ 100fd385855SPaul Moore static int netlbl_cipsov4_add_common(struct genl_info *info, 101fd385855SPaul Moore struct cipso_v4_doi *doi_def) 102fd385855SPaul Moore { 103fd385855SPaul Moore struct nlattr *nla; 104fd385855SPaul Moore int nla_rem; 105fd385855SPaul Moore u32 iter = 0; 106fd385855SPaul Moore 107fd385855SPaul Moore doi_def->doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]); 108fd385855SPaul Moore 109fd385855SPaul Moore if (nla_validate_nested(info->attrs[NLBL_CIPSOV4_A_TAGLST], 110fd385855SPaul Moore NLBL_CIPSOV4_A_MAX, 111fd385855SPaul Moore netlbl_cipsov4_genl_policy) != 0) 112fd385855SPaul Moore return -EINVAL; 113fd385855SPaul Moore 114fd385855SPaul Moore nla_for_each_nested(nla, info->attrs[NLBL_CIPSOV4_A_TAGLST], nla_rem) 1158f4c1f9bSThomas Graf if (nla_type(nla) == NLBL_CIPSOV4_A_TAG) { 1162a2f11c2SPaul Moore if (iter >= CIPSO_V4_TAG_MAXCNT) 117fd385855SPaul Moore return -EINVAL; 118fd385855SPaul Moore doi_def->tags[iter++] = nla_get_u8(nla); 119fd385855SPaul Moore } 1202a2f11c2SPaul Moore while (iter < CIPSO_V4_TAG_MAXCNT) 1212a2f11c2SPaul Moore doi_def->tags[iter++] = CIPSO_V4_TAG_INVALID; 122fd385855SPaul Moore 123fd385855SPaul Moore return 0; 124fd385855SPaul Moore } 12596cb8e33SPaul Moore 12696cb8e33SPaul Moore /* 12796cb8e33SPaul Moore * NetLabel Command Handlers 12896cb8e33SPaul Moore */ 12996cb8e33SPaul Moore 13096cb8e33SPaul Moore /** 13196cb8e33SPaul Moore * netlbl_cipsov4_add_std - Adds a CIPSO V4 DOI definition 132fd385855SPaul Moore * @info: the Generic NETLINK info block 13396cb8e33SPaul Moore * 13496cb8e33SPaul Moore * Description: 13515c45f7bSPaul Moore * Create a new CIPSO_V4_MAP_TRANS DOI definition based on the given ADD 13615c45f7bSPaul Moore * message and add it to the CIPSO V4 engine. Return zero on success and 13715c45f7bSPaul Moore * non-zero on error. 13896cb8e33SPaul Moore * 13996cb8e33SPaul Moore */ 140fd385855SPaul Moore static int netlbl_cipsov4_add_std(struct genl_info *info) 14196cb8e33SPaul Moore { 14296cb8e33SPaul Moore int ret_val = -EINVAL; 14396cb8e33SPaul Moore struct cipso_v4_doi *doi_def = NULL; 144fd385855SPaul Moore struct nlattr *nla_a; 145fd385855SPaul Moore struct nlattr *nla_b; 146fd385855SPaul Moore int nla_a_rem; 147fd385855SPaul Moore int nla_b_rem; 148caff5b6aSPaul Moore u32 iter; 14996cb8e33SPaul Moore 15032f50cdeSPaul Moore if (!info->attrs[NLBL_CIPSOV4_A_TAGLST] || 151fd385855SPaul Moore !info->attrs[NLBL_CIPSOV4_A_MLSLVLLST]) 152fd385855SPaul Moore return -EINVAL; 153fd385855SPaul Moore 154fd385855SPaul Moore if (nla_validate_nested(info->attrs[NLBL_CIPSOV4_A_MLSLVLLST], 155fd385855SPaul Moore NLBL_CIPSOV4_A_MAX, 156fd385855SPaul Moore netlbl_cipsov4_genl_policy) != 0) 157fd385855SPaul Moore return -EINVAL; 15896cb8e33SPaul Moore 15996cb8e33SPaul Moore doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL); 160fd385855SPaul Moore if (doi_def == NULL) 161fd385855SPaul Moore return -ENOMEM; 16296cb8e33SPaul Moore doi_def->map.std = kzalloc(sizeof(*doi_def->map.std), GFP_KERNEL); 16396cb8e33SPaul Moore if (doi_def->map.std == NULL) { 16496cb8e33SPaul Moore ret_val = -ENOMEM; 16596cb8e33SPaul Moore goto add_std_failure; 16696cb8e33SPaul Moore } 16715c45f7bSPaul Moore doi_def->type = CIPSO_V4_MAP_TRANS; 16896cb8e33SPaul Moore 169fd385855SPaul Moore ret_val = netlbl_cipsov4_add_common(info, doi_def); 170fd385855SPaul Moore if (ret_val != 0) 17196cb8e33SPaul Moore goto add_std_failure; 1721fd2a25bSPaul Moore ret_val = -EINVAL; 173fd385855SPaul Moore 174fd385855SPaul Moore nla_for_each_nested(nla_a, 175fd385855SPaul Moore info->attrs[NLBL_CIPSOV4_A_MLSLVLLST], 176fd385855SPaul Moore nla_a_rem) 1778f4c1f9bSThomas Graf if (nla_type(nla_a) == NLBL_CIPSOV4_A_MLSLVL) { 1781fd2a25bSPaul Moore if (nla_validate_nested(nla_a, 1791fd2a25bSPaul Moore NLBL_CIPSOV4_A_MAX, 1801fd2a25bSPaul Moore netlbl_cipsov4_genl_policy) != 0) 1811fd2a25bSPaul Moore goto add_std_failure; 182fd385855SPaul Moore nla_for_each_nested(nla_b, nla_a, nla_b_rem) 1838f4c1f9bSThomas Graf switch (nla_type(nla_b)) { 184fd385855SPaul Moore case NLBL_CIPSOV4_A_MLSLVLLOC: 1851fd2a25bSPaul Moore if (nla_get_u32(nla_b) > 1861fd2a25bSPaul Moore CIPSO_V4_MAX_LOC_LVLS) 1871fd2a25bSPaul Moore goto add_std_failure; 188fd385855SPaul Moore if (nla_get_u32(nla_b) >= 189fd385855SPaul Moore doi_def->map.std->lvl.local_size) 190fd385855SPaul Moore doi_def->map.std->lvl.local_size = 191fd385855SPaul Moore nla_get_u32(nla_b) + 1; 19296cb8e33SPaul Moore break; 193fd385855SPaul Moore case NLBL_CIPSOV4_A_MLSLVLREM: 1941fd2a25bSPaul Moore if (nla_get_u32(nla_b) > 1951fd2a25bSPaul Moore CIPSO_V4_MAX_REM_LVLS) 1961fd2a25bSPaul Moore goto add_std_failure; 197fd385855SPaul Moore if (nla_get_u32(nla_b) >= 198fd385855SPaul Moore doi_def->map.std->lvl.cipso_size) 199fd385855SPaul Moore doi_def->map.std->lvl.cipso_size = 200fd385855SPaul Moore nla_get_u32(nla_b) + 1; 201fd385855SPaul Moore break; 20296cb8e33SPaul Moore } 20396cb8e33SPaul Moore } 20496cb8e33SPaul Moore doi_def->map.std->lvl.local = kcalloc(doi_def->map.std->lvl.local_size, 20596cb8e33SPaul Moore sizeof(u32), 20696cb8e33SPaul Moore GFP_KERNEL); 20796cb8e33SPaul Moore if (doi_def->map.std->lvl.local == NULL) { 20896cb8e33SPaul Moore ret_val = -ENOMEM; 20996cb8e33SPaul Moore goto add_std_failure; 21096cb8e33SPaul Moore } 21196cb8e33SPaul Moore doi_def->map.std->lvl.cipso = kcalloc(doi_def->map.std->lvl.cipso_size, 21296cb8e33SPaul Moore sizeof(u32), 21396cb8e33SPaul Moore GFP_KERNEL); 21496cb8e33SPaul Moore if (doi_def->map.std->lvl.cipso == NULL) { 21596cb8e33SPaul Moore ret_val = -ENOMEM; 21696cb8e33SPaul Moore goto add_std_failure; 21796cb8e33SPaul Moore } 218caff5b6aSPaul Moore for (iter = 0; iter < doi_def->map.std->lvl.local_size; iter++) 219caff5b6aSPaul Moore doi_def->map.std->lvl.local[iter] = CIPSO_V4_INV_LVL; 220caff5b6aSPaul Moore for (iter = 0; iter < doi_def->map.std->lvl.cipso_size; iter++) 221caff5b6aSPaul Moore doi_def->map.std->lvl.cipso[iter] = CIPSO_V4_INV_LVL; 222fd385855SPaul Moore nla_for_each_nested(nla_a, 223fd385855SPaul Moore info->attrs[NLBL_CIPSOV4_A_MLSLVLLST], 224fd385855SPaul Moore nla_a_rem) 2258f4c1f9bSThomas Graf if (nla_type(nla_a) == NLBL_CIPSOV4_A_MLSLVL) { 226fd385855SPaul Moore struct nlattr *lvl_loc; 227fd385855SPaul Moore struct nlattr *lvl_rem; 22896cb8e33SPaul Moore 229fd385855SPaul Moore lvl_loc = nla_find_nested(nla_a, 230fd385855SPaul Moore NLBL_CIPSOV4_A_MLSLVLLOC); 231fd385855SPaul Moore lvl_rem = nla_find_nested(nla_a, 232fd385855SPaul Moore NLBL_CIPSOV4_A_MLSLVLREM); 233fd385855SPaul Moore if (lvl_loc == NULL || lvl_rem == NULL) 234fd385855SPaul Moore goto add_std_failure; 235fd385855SPaul Moore doi_def->map.std->lvl.local[nla_get_u32(lvl_loc)] = 236fd385855SPaul Moore nla_get_u32(lvl_rem); 237fd385855SPaul Moore doi_def->map.std->lvl.cipso[nla_get_u32(lvl_rem)] = 238fd385855SPaul Moore nla_get_u32(lvl_loc); 239fd385855SPaul Moore } 240fd385855SPaul Moore 241fd385855SPaul Moore if (info->attrs[NLBL_CIPSOV4_A_MLSCATLST]) { 242fd385855SPaul Moore if (nla_validate_nested(info->attrs[NLBL_CIPSOV4_A_MLSCATLST], 243fd385855SPaul Moore NLBL_CIPSOV4_A_MAX, 244fd385855SPaul Moore netlbl_cipsov4_genl_policy) != 0) 245fd385855SPaul Moore goto add_std_failure; 246fd385855SPaul Moore 247fd385855SPaul Moore nla_for_each_nested(nla_a, 248fd385855SPaul Moore info->attrs[NLBL_CIPSOV4_A_MLSCATLST], 249fd385855SPaul Moore nla_a_rem) 2508f4c1f9bSThomas Graf if (nla_type(nla_a) == NLBL_CIPSOV4_A_MLSCAT) { 251fd385855SPaul Moore if (nla_validate_nested(nla_a, 252fd385855SPaul Moore NLBL_CIPSOV4_A_MAX, 253fd385855SPaul Moore netlbl_cipsov4_genl_policy) != 0) 254fd385855SPaul Moore goto add_std_failure; 255fd385855SPaul Moore nla_for_each_nested(nla_b, nla_a, nla_b_rem) 2568f4c1f9bSThomas Graf switch (nla_type(nla_b)) { 257fd385855SPaul Moore case NLBL_CIPSOV4_A_MLSCATLOC: 2581fd2a25bSPaul Moore if (nla_get_u32(nla_b) > 2591fd2a25bSPaul Moore CIPSO_V4_MAX_LOC_CATS) 2601fd2a25bSPaul Moore goto add_std_failure; 261fd385855SPaul Moore if (nla_get_u32(nla_b) >= 262fd385855SPaul Moore doi_def->map.std->cat.local_size) 263fd385855SPaul Moore doi_def->map.std->cat.local_size = 264fd385855SPaul Moore nla_get_u32(nla_b) + 1; 265fd385855SPaul Moore break; 266fd385855SPaul Moore case NLBL_CIPSOV4_A_MLSCATREM: 2671fd2a25bSPaul Moore if (nla_get_u32(nla_b) > 2681fd2a25bSPaul Moore CIPSO_V4_MAX_REM_CATS) 2691fd2a25bSPaul Moore goto add_std_failure; 270fd385855SPaul Moore if (nla_get_u32(nla_b) >= 271fd385855SPaul Moore doi_def->map.std->cat.cipso_size) 272fd385855SPaul Moore doi_def->map.std->cat.cipso_size = 273fd385855SPaul Moore nla_get_u32(nla_b) + 1; 274fd385855SPaul Moore break; 275fd385855SPaul Moore } 276fd385855SPaul Moore } 277fd385855SPaul Moore doi_def->map.std->cat.local = kcalloc( 278fd385855SPaul Moore doi_def->map.std->cat.local_size, 27996cb8e33SPaul Moore sizeof(u32), 28096cb8e33SPaul Moore GFP_KERNEL); 28196cb8e33SPaul Moore if (doi_def->map.std->cat.local == NULL) { 28296cb8e33SPaul Moore ret_val = -ENOMEM; 28396cb8e33SPaul Moore goto add_std_failure; 28496cb8e33SPaul Moore } 285fd385855SPaul Moore doi_def->map.std->cat.cipso = kcalloc( 286fd385855SPaul Moore doi_def->map.std->cat.cipso_size, 28796cb8e33SPaul Moore sizeof(u32), 28896cb8e33SPaul Moore GFP_KERNEL); 28996cb8e33SPaul Moore if (doi_def->map.std->cat.cipso == NULL) { 29096cb8e33SPaul Moore ret_val = -ENOMEM; 29196cb8e33SPaul Moore goto add_std_failure; 29296cb8e33SPaul Moore } 293caff5b6aSPaul Moore for (iter = 0; iter < doi_def->map.std->cat.local_size; iter++) 294caff5b6aSPaul Moore doi_def->map.std->cat.local[iter] = CIPSO_V4_INV_CAT; 295caff5b6aSPaul Moore for (iter = 0; iter < doi_def->map.std->cat.cipso_size; iter++) 296caff5b6aSPaul Moore doi_def->map.std->cat.cipso[iter] = CIPSO_V4_INV_CAT; 297fd385855SPaul Moore nla_for_each_nested(nla_a, 298fd385855SPaul Moore info->attrs[NLBL_CIPSOV4_A_MLSCATLST], 299fd385855SPaul Moore nla_a_rem) 3008f4c1f9bSThomas Graf if (nla_type(nla_a) == NLBL_CIPSOV4_A_MLSCAT) { 301fd385855SPaul Moore struct nlattr *cat_loc; 302fd385855SPaul Moore struct nlattr *cat_rem; 30396cb8e33SPaul Moore 304fd385855SPaul Moore cat_loc = nla_find_nested(nla_a, 305fd385855SPaul Moore NLBL_CIPSOV4_A_MLSCATLOC); 306fd385855SPaul Moore cat_rem = nla_find_nested(nla_a, 307fd385855SPaul Moore NLBL_CIPSOV4_A_MLSCATREM); 308fd385855SPaul Moore if (cat_loc == NULL || cat_rem == NULL) 30996cb8e33SPaul Moore goto add_std_failure; 310fd385855SPaul Moore doi_def->map.std->cat.local[ 311fd385855SPaul Moore nla_get_u32(cat_loc)] = 312fd385855SPaul Moore nla_get_u32(cat_rem); 313fd385855SPaul Moore doi_def->map.std->cat.cipso[ 314fd385855SPaul Moore nla_get_u32(cat_rem)] = 315fd385855SPaul Moore nla_get_u32(cat_loc); 316fd385855SPaul Moore } 31796cb8e33SPaul Moore } 31896cb8e33SPaul Moore 31996cb8e33SPaul Moore ret_val = cipso_v4_doi_add(doi_def); 32096cb8e33SPaul Moore if (ret_val != 0) 32196cb8e33SPaul Moore goto add_std_failure; 32296cb8e33SPaul Moore return 0; 32396cb8e33SPaul Moore 32496cb8e33SPaul Moore add_std_failure: 32596cb8e33SPaul Moore if (doi_def) 326b1edeb10SPaul Moore cipso_v4_doi_free(doi_def); 32796cb8e33SPaul Moore return ret_val; 32896cb8e33SPaul Moore } 32996cb8e33SPaul Moore 33096cb8e33SPaul Moore /** 33196cb8e33SPaul Moore * netlbl_cipsov4_add_pass - Adds a CIPSO V4 DOI definition 332fd385855SPaul Moore * @info: the Generic NETLINK info block 33396cb8e33SPaul Moore * 33496cb8e33SPaul Moore * Description: 33596cb8e33SPaul Moore * Create a new CIPSO_V4_MAP_PASS DOI definition based on the given ADD message 33696cb8e33SPaul Moore * and add it to the CIPSO V4 engine. Return zero on success and non-zero on 33796cb8e33SPaul Moore * error. 33896cb8e33SPaul Moore * 33996cb8e33SPaul Moore */ 340fd385855SPaul Moore static int netlbl_cipsov4_add_pass(struct genl_info *info) 34196cb8e33SPaul Moore { 342fd385855SPaul Moore int ret_val; 34396cb8e33SPaul Moore struct cipso_v4_doi *doi_def = NULL; 34496cb8e33SPaul Moore 34532f50cdeSPaul Moore if (!info->attrs[NLBL_CIPSOV4_A_TAGLST]) 346fd385855SPaul Moore return -EINVAL; 34796cb8e33SPaul Moore 34896cb8e33SPaul Moore doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL); 349fd385855SPaul Moore if (doi_def == NULL) 350fd385855SPaul Moore return -ENOMEM; 35196cb8e33SPaul Moore doi_def->type = CIPSO_V4_MAP_PASS; 35296cb8e33SPaul Moore 353fd385855SPaul Moore ret_val = netlbl_cipsov4_add_common(info, doi_def); 354fd385855SPaul Moore if (ret_val != 0) 35596cb8e33SPaul Moore goto add_pass_failure; 35696cb8e33SPaul Moore 35796cb8e33SPaul Moore ret_val = cipso_v4_doi_add(doi_def); 35896cb8e33SPaul Moore if (ret_val != 0) 35996cb8e33SPaul Moore goto add_pass_failure; 36096cb8e33SPaul Moore return 0; 36196cb8e33SPaul Moore 36296cb8e33SPaul Moore add_pass_failure: 363b1edeb10SPaul Moore cipso_v4_doi_free(doi_def); 36496cb8e33SPaul Moore return ret_val; 36596cb8e33SPaul Moore } 36696cb8e33SPaul Moore 36796cb8e33SPaul Moore /** 368*d91d4079SPaul Moore * netlbl_cipsov4_add_local - Adds a CIPSO V4 DOI definition 369*d91d4079SPaul Moore * @info: the Generic NETLINK info block 370*d91d4079SPaul Moore * 371*d91d4079SPaul Moore * Description: 372*d91d4079SPaul Moore * Create a new CIPSO_V4_MAP_LOCAL DOI definition based on the given ADD 373*d91d4079SPaul Moore * message and add it to the CIPSO V4 engine. Return zero on success and 374*d91d4079SPaul Moore * non-zero on error. 375*d91d4079SPaul Moore * 376*d91d4079SPaul Moore */ 377*d91d4079SPaul Moore static int netlbl_cipsov4_add_local(struct genl_info *info) 378*d91d4079SPaul Moore { 379*d91d4079SPaul Moore int ret_val; 380*d91d4079SPaul Moore struct cipso_v4_doi *doi_def = NULL; 381*d91d4079SPaul Moore 382*d91d4079SPaul Moore if (!info->attrs[NLBL_CIPSOV4_A_TAGLST]) 383*d91d4079SPaul Moore return -EINVAL; 384*d91d4079SPaul Moore 385*d91d4079SPaul Moore doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL); 386*d91d4079SPaul Moore if (doi_def == NULL) 387*d91d4079SPaul Moore return -ENOMEM; 388*d91d4079SPaul Moore doi_def->type = CIPSO_V4_MAP_LOCAL; 389*d91d4079SPaul Moore 390*d91d4079SPaul Moore ret_val = netlbl_cipsov4_add_common(info, doi_def); 391*d91d4079SPaul Moore if (ret_val != 0) 392*d91d4079SPaul Moore goto add_local_failure; 393*d91d4079SPaul Moore 394*d91d4079SPaul Moore ret_val = cipso_v4_doi_add(doi_def); 395*d91d4079SPaul Moore if (ret_val != 0) 396*d91d4079SPaul Moore goto add_local_failure; 397*d91d4079SPaul Moore return 0; 398*d91d4079SPaul Moore 399*d91d4079SPaul Moore add_local_failure: 400*d91d4079SPaul Moore cipso_v4_doi_free(doi_def); 401*d91d4079SPaul Moore return ret_val; 402*d91d4079SPaul Moore } 403*d91d4079SPaul Moore 404*d91d4079SPaul Moore /** 40596cb8e33SPaul Moore * netlbl_cipsov4_add - Handle an ADD message 40696cb8e33SPaul Moore * @skb: the NETLINK buffer 40796cb8e33SPaul Moore * @info: the Generic NETLINK info block 40896cb8e33SPaul Moore * 40996cb8e33SPaul Moore * Description: 41096cb8e33SPaul Moore * Create a new DOI definition based on the given ADD message and add it to the 41196cb8e33SPaul Moore * CIPSO V4 engine. Returns zero on success, negative values on failure. 41296cb8e33SPaul Moore * 41396cb8e33SPaul Moore */ 41496cb8e33SPaul Moore static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info) 41596cb8e33SPaul Moore 41696cb8e33SPaul Moore { 41796cb8e33SPaul Moore int ret_val = -EINVAL; 41832f50cdeSPaul Moore u32 type; 41932f50cdeSPaul Moore u32 doi; 42032f50cdeSPaul Moore const char *type_str = "(unknown)"; 42132f50cdeSPaul Moore struct audit_buffer *audit_buf; 42295d4e6beSPaul Moore struct netlbl_audit audit_info; 42396cb8e33SPaul Moore 42432f50cdeSPaul Moore if (!info->attrs[NLBL_CIPSOV4_A_DOI] || 42532f50cdeSPaul Moore !info->attrs[NLBL_CIPSOV4_A_MTYPE]) 426fd385855SPaul Moore return -EINVAL; 42796cb8e33SPaul Moore 42895d4e6beSPaul Moore doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]); 42995d4e6beSPaul Moore netlbl_netlink_auditinfo(skb, &audit_info); 43095d4e6beSPaul Moore 43132f50cdeSPaul Moore type = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_MTYPE]); 43232f50cdeSPaul Moore switch (type) { 43315c45f7bSPaul Moore case CIPSO_V4_MAP_TRANS: 43415c45f7bSPaul Moore type_str = "trans"; 435fd385855SPaul Moore ret_val = netlbl_cipsov4_add_std(info); 43696cb8e33SPaul Moore break; 43796cb8e33SPaul Moore case CIPSO_V4_MAP_PASS: 43832f50cdeSPaul Moore type_str = "pass"; 439fd385855SPaul Moore ret_val = netlbl_cipsov4_add_pass(info); 44096cb8e33SPaul Moore break; 441*d91d4079SPaul Moore case CIPSO_V4_MAP_LOCAL: 442*d91d4079SPaul Moore type_str = "local"; 443*d91d4079SPaul Moore ret_val = netlbl_cipsov4_add_local(info); 444*d91d4079SPaul Moore break; 44596cb8e33SPaul Moore } 44623bcdc1aSPaul Moore if (ret_val == 0) 447c783f1ceSPaul Moore atomic_inc(&netlabel_mgmt_protocount); 44896cb8e33SPaul Moore 44932f50cdeSPaul Moore audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_ADD, 45095d4e6beSPaul Moore &audit_info); 451de64688fSPaul Moore if (audit_buf != NULL) { 45295d4e6beSPaul Moore audit_log_format(audit_buf, 45395d4e6beSPaul Moore " cipso_doi=%u cipso_type=%s res=%u", 45495d4e6beSPaul Moore doi, 45595d4e6beSPaul Moore type_str, 45695d4e6beSPaul Moore ret_val == 0 ? 1 : 0); 45732f50cdeSPaul Moore audit_log_end(audit_buf); 458de64688fSPaul Moore } 45932f50cdeSPaul Moore 46096cb8e33SPaul Moore return ret_val; 46196cb8e33SPaul Moore } 46296cb8e33SPaul Moore 46396cb8e33SPaul Moore /** 46496cb8e33SPaul Moore * netlbl_cipsov4_list - Handle a LIST message 46596cb8e33SPaul Moore * @skb: the NETLINK buffer 46696cb8e33SPaul Moore * @info: the Generic NETLINK info block 46796cb8e33SPaul Moore * 46896cb8e33SPaul Moore * Description: 469fd385855SPaul Moore * Process a user generated LIST message and respond accordingly. While the 470fd385855SPaul Moore * response message generated by the kernel is straightforward, determining 471fd385855SPaul Moore * before hand the size of the buffer to allocate is not (we have to generate 472fd385855SPaul Moore * the message to know the size). In order to keep this function sane what we 473fd385855SPaul Moore * do is allocate a buffer of NLMSG_GOODSIZE and try to fit the response in 474fd385855SPaul Moore * that size, if we fail then we restart with a larger buffer and try again. 475fd385855SPaul Moore * We continue in this manner until we hit a limit of failed attempts then we 476fd385855SPaul Moore * give up and just send an error message. Returns zero on success and 477fd385855SPaul Moore * negative values on error. 47896cb8e33SPaul Moore * 47996cb8e33SPaul Moore */ 48096cb8e33SPaul Moore static int netlbl_cipsov4_list(struct sk_buff *skb, struct genl_info *info) 48196cb8e33SPaul Moore { 482fd385855SPaul Moore int ret_val; 483fd385855SPaul Moore struct sk_buff *ans_skb = NULL; 484fd385855SPaul Moore u32 nlsze_mult = 1; 485fd385855SPaul Moore void *data; 48696cb8e33SPaul Moore u32 doi; 487fd385855SPaul Moore struct nlattr *nla_a; 488fd385855SPaul Moore struct nlattr *nla_b; 489fd385855SPaul Moore struct cipso_v4_doi *doi_def; 490fd385855SPaul Moore u32 iter; 49196cb8e33SPaul Moore 492fd385855SPaul Moore if (!info->attrs[NLBL_CIPSOV4_A_DOI]) { 493fd385855SPaul Moore ret_val = -EINVAL; 49496cb8e33SPaul Moore goto list_failure; 495fd385855SPaul Moore } 49696cb8e33SPaul Moore 497fd385855SPaul Moore list_start: 498339bf98fSThomas Graf ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE * nlsze_mult, GFP_KERNEL); 49996cb8e33SPaul Moore if (ans_skb == NULL) { 50096cb8e33SPaul Moore ret_val = -ENOMEM; 50196cb8e33SPaul Moore goto list_failure; 50296cb8e33SPaul Moore } 50317c157c8SThomas Graf data = genlmsg_put_reply(ans_skb, info, &netlbl_cipsov4_gnl_family, 50417c157c8SThomas Graf 0, NLBL_CIPSOV4_C_LIST); 505fd385855SPaul Moore if (data == NULL) { 506fd385855SPaul Moore ret_val = -ENOMEM; 507fd385855SPaul Moore goto list_failure; 508fd385855SPaul Moore } 50996cb8e33SPaul Moore 510fd385855SPaul Moore doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]); 511fd385855SPaul Moore 512fd385855SPaul Moore rcu_read_lock(); 513fd385855SPaul Moore doi_def = cipso_v4_doi_getdef(doi); 514fd385855SPaul Moore if (doi_def == NULL) { 515fd385855SPaul Moore ret_val = -EINVAL; 51656196701SPaul Moore goto list_failure_lock; 517fd385855SPaul Moore } 518fd385855SPaul Moore 519fd385855SPaul Moore ret_val = nla_put_u32(ans_skb, NLBL_CIPSOV4_A_MTYPE, doi_def->type); 520fd385855SPaul Moore if (ret_val != 0) 521fd385855SPaul Moore goto list_failure_lock; 522fd385855SPaul Moore 523fd385855SPaul Moore nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_TAGLST); 524fd385855SPaul Moore if (nla_a == NULL) { 525fd385855SPaul Moore ret_val = -ENOMEM; 526fd385855SPaul Moore goto list_failure_lock; 527fd385855SPaul Moore } 528fd385855SPaul Moore for (iter = 0; 529fd385855SPaul Moore iter < CIPSO_V4_TAG_MAXCNT && 530fd385855SPaul Moore doi_def->tags[iter] != CIPSO_V4_TAG_INVALID; 531fd385855SPaul Moore iter++) { 532fd385855SPaul Moore ret_val = nla_put_u8(ans_skb, 533fd385855SPaul Moore NLBL_CIPSOV4_A_TAG, 534fd385855SPaul Moore doi_def->tags[iter]); 535fd385855SPaul Moore if (ret_val != 0) 536fd385855SPaul Moore goto list_failure_lock; 537fd385855SPaul Moore } 538fd385855SPaul Moore nla_nest_end(ans_skb, nla_a); 539fd385855SPaul Moore 540fd385855SPaul Moore switch (doi_def->type) { 54115c45f7bSPaul Moore case CIPSO_V4_MAP_TRANS: 542fd385855SPaul Moore nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSLVLLST); 543fd385855SPaul Moore if (nla_a == NULL) { 544fd385855SPaul Moore ret_val = -ENOMEM; 545fd385855SPaul Moore goto list_failure_lock; 546fd385855SPaul Moore } 547fd385855SPaul Moore for (iter = 0; 548fd385855SPaul Moore iter < doi_def->map.std->lvl.local_size; 549fd385855SPaul Moore iter++) { 550fd385855SPaul Moore if (doi_def->map.std->lvl.local[iter] == 551fd385855SPaul Moore CIPSO_V4_INV_LVL) 552fd385855SPaul Moore continue; 553fd385855SPaul Moore 554fd385855SPaul Moore nla_b = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSLVL); 555fd385855SPaul Moore if (nla_b == NULL) { 556fd385855SPaul Moore ret_val = -ENOMEM; 557fd385855SPaul Moore goto list_retry; 558fd385855SPaul Moore } 559fd385855SPaul Moore ret_val = nla_put_u32(ans_skb, 560fd385855SPaul Moore NLBL_CIPSOV4_A_MLSLVLLOC, 561fd385855SPaul Moore iter); 562fd385855SPaul Moore if (ret_val != 0) 563fd385855SPaul Moore goto list_retry; 564fd385855SPaul Moore ret_val = nla_put_u32(ans_skb, 565fd385855SPaul Moore NLBL_CIPSOV4_A_MLSLVLREM, 566fd385855SPaul Moore doi_def->map.std->lvl.local[iter]); 567fd385855SPaul Moore if (ret_val != 0) 568fd385855SPaul Moore goto list_retry; 569fd385855SPaul Moore nla_nest_end(ans_skb, nla_b); 570fd385855SPaul Moore } 571fd385855SPaul Moore nla_nest_end(ans_skb, nla_a); 572fd385855SPaul Moore 573fd385855SPaul Moore nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSCATLST); 574fd385855SPaul Moore if (nla_a == NULL) { 575fd385855SPaul Moore ret_val = -ENOMEM; 576fd385855SPaul Moore goto list_retry; 577fd385855SPaul Moore } 578fd385855SPaul Moore for (iter = 0; 579fd385855SPaul Moore iter < doi_def->map.std->cat.local_size; 580fd385855SPaul Moore iter++) { 581fd385855SPaul Moore if (doi_def->map.std->cat.local[iter] == 582fd385855SPaul Moore CIPSO_V4_INV_CAT) 583fd385855SPaul Moore continue; 584fd385855SPaul Moore 585fd385855SPaul Moore nla_b = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSCAT); 586fd385855SPaul Moore if (nla_b == NULL) { 587fd385855SPaul Moore ret_val = -ENOMEM; 588fd385855SPaul Moore goto list_retry; 589fd385855SPaul Moore } 590fd385855SPaul Moore ret_val = nla_put_u32(ans_skb, 591fd385855SPaul Moore NLBL_CIPSOV4_A_MLSCATLOC, 592fd385855SPaul Moore iter); 593fd385855SPaul Moore if (ret_val != 0) 594fd385855SPaul Moore goto list_retry; 595fd385855SPaul Moore ret_val = nla_put_u32(ans_skb, 596fd385855SPaul Moore NLBL_CIPSOV4_A_MLSCATREM, 597fd385855SPaul Moore doi_def->map.std->cat.local[iter]); 598fd385855SPaul Moore if (ret_val != 0) 599fd385855SPaul Moore goto list_retry; 600fd385855SPaul Moore nla_nest_end(ans_skb, nla_b); 601fd385855SPaul Moore } 602fd385855SPaul Moore nla_nest_end(ans_skb, nla_a); 603fd385855SPaul Moore 604fd385855SPaul Moore break; 605fd385855SPaul Moore } 606fd385855SPaul Moore rcu_read_unlock(); 607fd385855SPaul Moore 608fd385855SPaul Moore genlmsg_end(ans_skb, data); 609fe785beeSDenis V. Lunev return genlmsg_reply(ans_skb, info); 61096cb8e33SPaul Moore 611fd385855SPaul Moore list_retry: 612fd385855SPaul Moore /* XXX - this limit is a guesstimate */ 613fd385855SPaul Moore if (nlsze_mult < 4) { 614fd385855SPaul Moore rcu_read_unlock(); 615fd385855SPaul Moore kfree_skb(ans_skb); 61683aa2e96SDenis V. Lunev nlsze_mult *= 2; 617fd385855SPaul Moore goto list_start; 618fd385855SPaul Moore } 619fd385855SPaul Moore list_failure_lock: 620fd385855SPaul Moore rcu_read_unlock(); 62196cb8e33SPaul Moore list_failure: 622fd385855SPaul Moore kfree_skb(ans_skb); 623fd385855SPaul Moore return ret_val; 624fd385855SPaul Moore } 625fd385855SPaul Moore 626fd385855SPaul Moore /** 627fd385855SPaul Moore * netlbl_cipsov4_listall_cb - cipso_v4_doi_walk() callback for LISTALL 628fd385855SPaul Moore * @doi_def: the CIPSOv4 DOI definition 629fd385855SPaul Moore * @arg: the netlbl_cipsov4_doiwalk_arg structure 630fd385855SPaul Moore * 631fd385855SPaul Moore * Description: 632fd385855SPaul Moore * This function is designed to be used as a callback to the 633fd385855SPaul Moore * cipso_v4_doi_walk() function for use in generating a response for a LISTALL 634fd385855SPaul Moore * message. Returns the size of the message on success, negative values on 635fd385855SPaul Moore * failure. 636fd385855SPaul Moore * 637fd385855SPaul Moore */ 638fd385855SPaul Moore static int netlbl_cipsov4_listall_cb(struct cipso_v4_doi *doi_def, void *arg) 639fd385855SPaul Moore { 640fd385855SPaul Moore int ret_val = -ENOMEM; 641fd385855SPaul Moore struct netlbl_cipsov4_doiwalk_arg *cb_arg = arg; 642fd385855SPaul Moore void *data; 643fd385855SPaul Moore 64417c157c8SThomas Graf data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).pid, 64517c157c8SThomas Graf cb_arg->seq, &netlbl_cipsov4_gnl_family, 64617c157c8SThomas Graf NLM_F_MULTI, NLBL_CIPSOV4_C_LISTALL); 647fd385855SPaul Moore if (data == NULL) 648fd385855SPaul Moore goto listall_cb_failure; 649fd385855SPaul Moore 650fd385855SPaul Moore ret_val = nla_put_u32(cb_arg->skb, NLBL_CIPSOV4_A_DOI, doi_def->doi); 651fd385855SPaul Moore if (ret_val != 0) 652fd385855SPaul Moore goto listall_cb_failure; 653fd385855SPaul Moore ret_val = nla_put_u32(cb_arg->skb, 654fd385855SPaul Moore NLBL_CIPSOV4_A_MTYPE, 655fd385855SPaul Moore doi_def->type); 656fd385855SPaul Moore if (ret_val != 0) 657fd385855SPaul Moore goto listall_cb_failure; 658fd385855SPaul Moore 659fd385855SPaul Moore return genlmsg_end(cb_arg->skb, data); 660fd385855SPaul Moore 661fd385855SPaul Moore listall_cb_failure: 662fd385855SPaul Moore genlmsg_cancel(cb_arg->skb, data); 66396cb8e33SPaul Moore return ret_val; 66496cb8e33SPaul Moore } 66596cb8e33SPaul Moore 66696cb8e33SPaul Moore /** 66796cb8e33SPaul Moore * netlbl_cipsov4_listall - Handle a LISTALL message 66896cb8e33SPaul Moore * @skb: the NETLINK buffer 669fd385855SPaul Moore * @cb: the NETLINK callback 67096cb8e33SPaul Moore * 67196cb8e33SPaul Moore * Description: 67296cb8e33SPaul Moore * Process a user generated LISTALL message and respond accordingly. Returns 67396cb8e33SPaul Moore * zero on success and negative values on error. 67496cb8e33SPaul Moore * 67596cb8e33SPaul Moore */ 676fd385855SPaul Moore static int netlbl_cipsov4_listall(struct sk_buff *skb, 677fd385855SPaul Moore struct netlink_callback *cb) 67896cb8e33SPaul Moore { 679fd385855SPaul Moore struct netlbl_cipsov4_doiwalk_arg cb_arg; 68056196701SPaul Moore u32 doi_skip = cb->args[0]; 68196cb8e33SPaul Moore 682fd385855SPaul Moore cb_arg.nl_cb = cb; 683fd385855SPaul Moore cb_arg.skb = skb; 684fd385855SPaul Moore cb_arg.seq = cb->nlh->nlmsg_seq; 68596cb8e33SPaul Moore 686fd385855SPaul Moore cipso_v4_doi_walk(&doi_skip, netlbl_cipsov4_listall_cb, &cb_arg); 68796cb8e33SPaul Moore 688fd385855SPaul Moore cb->args[0] = doi_skip; 689fd385855SPaul Moore return skb->len; 69096cb8e33SPaul Moore } 69196cb8e33SPaul Moore 69296cb8e33SPaul Moore /** 693b1edeb10SPaul Moore * netlbl_cipsov4_remove_cb - netlbl_cipsov4_remove() callback for REMOVE 694b1edeb10SPaul Moore * @entry: LSM domain mapping entry 695b1edeb10SPaul Moore * @arg: the netlbl_domhsh_walk_arg structure 696b1edeb10SPaul Moore * 697b1edeb10SPaul Moore * Description: 698b1edeb10SPaul Moore * This function is intended for use by netlbl_cipsov4_remove() as the callback 699b1edeb10SPaul Moore * for the netlbl_domhsh_walk() function; it removes LSM domain map entries 700b1edeb10SPaul Moore * which are associated with the CIPSO DOI specified in @arg. Returns zero on 701b1edeb10SPaul Moore * success, negative values on failure. 702b1edeb10SPaul Moore * 703b1edeb10SPaul Moore */ 704b1edeb10SPaul Moore static int netlbl_cipsov4_remove_cb(struct netlbl_dom_map *entry, void *arg) 705b1edeb10SPaul Moore { 706b1edeb10SPaul Moore struct netlbl_domhsh_walk_arg *cb_arg = arg; 707b1edeb10SPaul Moore 708b1edeb10SPaul Moore if (entry->type == NETLBL_NLTYPE_CIPSOV4 && 709b1edeb10SPaul Moore entry->type_def.cipsov4->doi == cb_arg->doi) 710b1edeb10SPaul Moore return netlbl_domhsh_remove_entry(entry, cb_arg->audit_info); 711b1edeb10SPaul Moore 712b1edeb10SPaul Moore return 0; 713b1edeb10SPaul Moore } 714b1edeb10SPaul Moore 715b1edeb10SPaul Moore /** 71696cb8e33SPaul Moore * netlbl_cipsov4_remove - Handle a REMOVE message 71796cb8e33SPaul Moore * @skb: the NETLINK buffer 71896cb8e33SPaul Moore * @info: the Generic NETLINK info block 71996cb8e33SPaul Moore * 72096cb8e33SPaul Moore * Description: 72196cb8e33SPaul Moore * Process a user generated REMOVE message and respond accordingly. Returns 72296cb8e33SPaul Moore * zero on success, negative values on failure. 72396cb8e33SPaul Moore * 72496cb8e33SPaul Moore */ 72596cb8e33SPaul Moore static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info) 72696cb8e33SPaul Moore { 727fd385855SPaul Moore int ret_val = -EINVAL; 72832f50cdeSPaul Moore u32 doi = 0; 729b1edeb10SPaul Moore struct netlbl_domhsh_walk_arg cb_arg; 73032f50cdeSPaul Moore struct audit_buffer *audit_buf; 73195d4e6beSPaul Moore struct netlbl_audit audit_info; 732b1edeb10SPaul Moore u32 skip_bkt = 0; 733b1edeb10SPaul Moore u32 skip_chain = 0; 73496cb8e33SPaul Moore 73595d4e6beSPaul Moore if (!info->attrs[NLBL_CIPSOV4_A_DOI]) 73695d4e6beSPaul Moore return -EINVAL; 73795d4e6beSPaul Moore 738fd385855SPaul Moore doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]); 73995d4e6beSPaul Moore netlbl_netlink_auditinfo(skb, &audit_info); 74032f50cdeSPaul Moore 741b1edeb10SPaul Moore cb_arg.doi = doi; 742b1edeb10SPaul Moore cb_arg.audit_info = &audit_info; 743b1edeb10SPaul Moore ret_val = netlbl_domhsh_walk(&skip_bkt, &skip_chain, 744b1edeb10SPaul Moore netlbl_cipsov4_remove_cb, &cb_arg); 745b1edeb10SPaul Moore if (ret_val == 0 || ret_val == -ENOENT) { 746b1edeb10SPaul Moore ret_val = cipso_v4_doi_remove(doi, &audit_info); 74723bcdc1aSPaul Moore if (ret_val == 0) 748c783f1ceSPaul Moore atomic_dec(&netlabel_mgmt_protocount); 749b1edeb10SPaul Moore } 75095d4e6beSPaul Moore 75132f50cdeSPaul Moore audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_DEL, 75295d4e6beSPaul Moore &audit_info); 753de64688fSPaul Moore if (audit_buf != NULL) { 75495d4e6beSPaul Moore audit_log_format(audit_buf, 75595d4e6beSPaul Moore " cipso_doi=%u res=%u", 75695d4e6beSPaul Moore doi, 75795d4e6beSPaul Moore ret_val == 0 ? 1 : 0); 75832f50cdeSPaul Moore audit_log_end(audit_buf); 759de64688fSPaul Moore } 76096cb8e33SPaul Moore 76196cb8e33SPaul Moore return ret_val; 76296cb8e33SPaul Moore } 76396cb8e33SPaul Moore 76496cb8e33SPaul Moore /* 76596cb8e33SPaul Moore * NetLabel Generic NETLINK Command Definitions 76696cb8e33SPaul Moore */ 76796cb8e33SPaul Moore 768227c43c3SPavel Emelyanov static struct genl_ops netlbl_cipsov4_ops[] = { 769227c43c3SPavel Emelyanov { 77096cb8e33SPaul Moore .cmd = NLBL_CIPSOV4_C_ADD, 771fd385855SPaul Moore .flags = GENL_ADMIN_PERM, 772fd385855SPaul Moore .policy = netlbl_cipsov4_genl_policy, 77396cb8e33SPaul Moore .doit = netlbl_cipsov4_add, 77496cb8e33SPaul Moore .dumpit = NULL, 775227c43c3SPavel Emelyanov }, 776227c43c3SPavel Emelyanov { 77796cb8e33SPaul Moore .cmd = NLBL_CIPSOV4_C_REMOVE, 778fd385855SPaul Moore .flags = GENL_ADMIN_PERM, 779fd385855SPaul Moore .policy = netlbl_cipsov4_genl_policy, 78096cb8e33SPaul Moore .doit = netlbl_cipsov4_remove, 78196cb8e33SPaul Moore .dumpit = NULL, 782227c43c3SPavel Emelyanov }, 783227c43c3SPavel Emelyanov { 78496cb8e33SPaul Moore .cmd = NLBL_CIPSOV4_C_LIST, 78596cb8e33SPaul Moore .flags = 0, 786fd385855SPaul Moore .policy = netlbl_cipsov4_genl_policy, 78796cb8e33SPaul Moore .doit = netlbl_cipsov4_list, 78896cb8e33SPaul Moore .dumpit = NULL, 789227c43c3SPavel Emelyanov }, 790227c43c3SPavel Emelyanov { 79196cb8e33SPaul Moore .cmd = NLBL_CIPSOV4_C_LISTALL, 79296cb8e33SPaul Moore .flags = 0, 793fd385855SPaul Moore .policy = netlbl_cipsov4_genl_policy, 794fd385855SPaul Moore .doit = NULL, 795fd385855SPaul Moore .dumpit = netlbl_cipsov4_listall, 796227c43c3SPavel Emelyanov }, 79796cb8e33SPaul Moore }; 79896cb8e33SPaul Moore 79996cb8e33SPaul Moore /* 80096cb8e33SPaul Moore * NetLabel Generic NETLINK Protocol Functions 80196cb8e33SPaul Moore */ 80296cb8e33SPaul Moore 80396cb8e33SPaul Moore /** 80496cb8e33SPaul Moore * netlbl_cipsov4_genl_init - Register the CIPSOv4 NetLabel component 80596cb8e33SPaul Moore * 80696cb8e33SPaul Moore * Description: 80796cb8e33SPaul Moore * Register the CIPSOv4 packet NetLabel component with the Generic NETLINK 80896cb8e33SPaul Moore * mechanism. Returns zero on success, negative values on failure. 80996cb8e33SPaul Moore * 81096cb8e33SPaul Moore */ 81105705e4eSPavel Emelyanov int __init netlbl_cipsov4_genl_init(void) 81296cb8e33SPaul Moore { 813227c43c3SPavel Emelyanov int ret_val, i; 81496cb8e33SPaul Moore 81596cb8e33SPaul Moore ret_val = genl_register_family(&netlbl_cipsov4_gnl_family); 81696cb8e33SPaul Moore if (ret_val != 0) 81796cb8e33SPaul Moore return ret_val; 81896cb8e33SPaul Moore 819227c43c3SPavel Emelyanov for (i = 0; i < ARRAY_SIZE(netlbl_cipsov4_ops); i++) { 82096cb8e33SPaul Moore ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family, 821227c43c3SPavel Emelyanov &netlbl_cipsov4_ops[i]); 82296cb8e33SPaul Moore if (ret_val != 0) 82396cb8e33SPaul Moore return ret_val; 824227c43c3SPavel Emelyanov } 82596cb8e33SPaul Moore 82696cb8e33SPaul Moore return 0; 82796cb8e33SPaul Moore } 828