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 * 882c21bfaSPaul Moore * Author: Paul Moore <paul@paul-moore.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 26d484ff15SJeff Kirsher * along with this program; if not, see <http://www.gnu.org/licenses/>. 2796cb8e33SPaul Moore * 2896cb8e33SPaul Moore */ 2996cb8e33SPaul Moore 3096cb8e33SPaul Moore #include <linux/types.h> 3196cb8e33SPaul Moore #include <linux/socket.h> 3296cb8e33SPaul Moore #include <linux/string.h> 3396cb8e33SPaul Moore #include <linux/skbuff.h> 3432f50cdeSPaul Moore #include <linux/audit.h> 355a0e3ad6STejun Heo #include <linux/slab.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> 4160063497SArun Sharma #include <linux/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 */ 62*489111e5SJohannes Berg static struct genl_family netlbl_cipsov4_gnl_family; 63fd385855SPaul Moore /* NetLabel Netlink attribute policy */ 64ef7c79edSPatrick McHardy static const struct nla_policy netlbl_cipsov4_genl_policy[NLBL_CIPSOV4_A_MAX + 1] = { 65fd385855SPaul Moore [NLBL_CIPSOV4_A_DOI] = { .type = NLA_U32 }, 66fd385855SPaul Moore [NLBL_CIPSOV4_A_MTYPE] = { .type = NLA_U32 }, 67fd385855SPaul Moore [NLBL_CIPSOV4_A_TAG] = { .type = NLA_U8 }, 68fd385855SPaul Moore [NLBL_CIPSOV4_A_TAGLST] = { .type = NLA_NESTED }, 69fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSLVLLOC] = { .type = NLA_U32 }, 70fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSLVLREM] = { .type = NLA_U32 }, 71fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSLVL] = { .type = NLA_NESTED }, 72fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSLVLLST] = { .type = NLA_NESTED }, 73fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSCATLOC] = { .type = NLA_U32 }, 74fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSCATREM] = { .type = NLA_U32 }, 75fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSCAT] = { .type = NLA_NESTED }, 76fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSCATLST] = { .type = NLA_NESTED }, 77fd385855SPaul Moore }; 7896cb8e33SPaul Moore 7996cb8e33SPaul Moore /* 8096cb8e33SPaul Moore * Helper Functions 8196cb8e33SPaul Moore */ 8296cb8e33SPaul Moore 8396cb8e33SPaul Moore /** 84fd385855SPaul Moore * netlbl_cipsov4_add_common - Parse the common sections of a ADD message 85fd385855SPaul Moore * @info: the Generic NETLINK info block 86fd385855SPaul Moore * @doi_def: the CIPSO V4 DOI definition 87fd385855SPaul Moore * 88fd385855SPaul Moore * Description: 89fd385855SPaul Moore * Parse the common sections of a ADD message and fill in the related values 90fd385855SPaul Moore * in @doi_def. Returns zero on success, negative values on failure. 91fd385855SPaul Moore * 92fd385855SPaul Moore */ 93fd385855SPaul Moore static int netlbl_cipsov4_add_common(struct genl_info *info, 94fd385855SPaul Moore struct cipso_v4_doi *doi_def) 95fd385855SPaul Moore { 96fd385855SPaul Moore struct nlattr *nla; 97fd385855SPaul Moore int nla_rem; 98fd385855SPaul Moore u32 iter = 0; 99fd385855SPaul Moore 100fd385855SPaul Moore doi_def->doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]); 101fd385855SPaul Moore 102fd385855SPaul Moore if (nla_validate_nested(info->attrs[NLBL_CIPSOV4_A_TAGLST], 103fd385855SPaul Moore NLBL_CIPSOV4_A_MAX, 104fd385855SPaul Moore netlbl_cipsov4_genl_policy) != 0) 105fd385855SPaul Moore return -EINVAL; 106fd385855SPaul Moore 107fd385855SPaul Moore nla_for_each_nested(nla, info->attrs[NLBL_CIPSOV4_A_TAGLST], nla_rem) 1088f4c1f9bSThomas Graf if (nla_type(nla) == NLBL_CIPSOV4_A_TAG) { 1092a2f11c2SPaul Moore if (iter >= CIPSO_V4_TAG_MAXCNT) 110fd385855SPaul Moore return -EINVAL; 111fd385855SPaul Moore doi_def->tags[iter++] = nla_get_u8(nla); 112fd385855SPaul Moore } 1132a2f11c2SPaul Moore while (iter < CIPSO_V4_TAG_MAXCNT) 1142a2f11c2SPaul Moore doi_def->tags[iter++] = CIPSO_V4_TAG_INVALID; 115fd385855SPaul Moore 116fd385855SPaul Moore return 0; 117fd385855SPaul Moore } 11896cb8e33SPaul Moore 11996cb8e33SPaul Moore /* 12096cb8e33SPaul Moore * NetLabel Command Handlers 12196cb8e33SPaul Moore */ 12296cb8e33SPaul Moore 12396cb8e33SPaul Moore /** 12496cb8e33SPaul Moore * netlbl_cipsov4_add_std - Adds a CIPSO V4 DOI definition 125fd385855SPaul Moore * @info: the Generic NETLINK info block 1266c2e8ac0SPaul Moore * @audit_info: NetLabel audit information 12796cb8e33SPaul Moore * 12896cb8e33SPaul Moore * Description: 12915c45f7bSPaul Moore * Create a new CIPSO_V4_MAP_TRANS DOI definition based on the given ADD 13015c45f7bSPaul Moore * message and add it to the CIPSO V4 engine. Return zero on success and 13115c45f7bSPaul Moore * non-zero on error. 13296cb8e33SPaul Moore * 13396cb8e33SPaul Moore */ 1346c2e8ac0SPaul Moore static int netlbl_cipsov4_add_std(struct genl_info *info, 1356c2e8ac0SPaul Moore struct netlbl_audit *audit_info) 13696cb8e33SPaul Moore { 13796cb8e33SPaul Moore int ret_val = -EINVAL; 13896cb8e33SPaul Moore struct cipso_v4_doi *doi_def = NULL; 139fd385855SPaul Moore struct nlattr *nla_a; 140fd385855SPaul Moore struct nlattr *nla_b; 141fd385855SPaul Moore int nla_a_rem; 142fd385855SPaul Moore int nla_b_rem; 143caff5b6aSPaul Moore u32 iter; 14496cb8e33SPaul Moore 14532f50cdeSPaul Moore if (!info->attrs[NLBL_CIPSOV4_A_TAGLST] || 146fd385855SPaul Moore !info->attrs[NLBL_CIPSOV4_A_MLSLVLLST]) 147fd385855SPaul Moore return -EINVAL; 148fd385855SPaul Moore 149fd385855SPaul Moore if (nla_validate_nested(info->attrs[NLBL_CIPSOV4_A_MLSLVLLST], 150fd385855SPaul Moore NLBL_CIPSOV4_A_MAX, 151fd385855SPaul Moore netlbl_cipsov4_genl_policy) != 0) 152fd385855SPaul Moore return -EINVAL; 15396cb8e33SPaul Moore 15496cb8e33SPaul Moore doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL); 155fd385855SPaul Moore if (doi_def == NULL) 156fd385855SPaul Moore return -ENOMEM; 15796cb8e33SPaul Moore doi_def->map.std = kzalloc(sizeof(*doi_def->map.std), GFP_KERNEL); 15896cb8e33SPaul Moore if (doi_def->map.std == NULL) { 15996cb8e33SPaul Moore ret_val = -ENOMEM; 16096cb8e33SPaul Moore goto add_std_failure; 16196cb8e33SPaul Moore } 16215c45f7bSPaul Moore doi_def->type = CIPSO_V4_MAP_TRANS; 16396cb8e33SPaul Moore 164fd385855SPaul Moore ret_val = netlbl_cipsov4_add_common(info, doi_def); 165fd385855SPaul Moore if (ret_val != 0) 16696cb8e33SPaul Moore goto add_std_failure; 1671fd2a25bSPaul Moore ret_val = -EINVAL; 168fd385855SPaul Moore 169fd385855SPaul Moore nla_for_each_nested(nla_a, 170fd385855SPaul Moore info->attrs[NLBL_CIPSOV4_A_MLSLVLLST], 171fd385855SPaul Moore nla_a_rem) 1728f4c1f9bSThomas Graf if (nla_type(nla_a) == NLBL_CIPSOV4_A_MLSLVL) { 1731fd2a25bSPaul Moore if (nla_validate_nested(nla_a, 1741fd2a25bSPaul Moore NLBL_CIPSOV4_A_MAX, 1751fd2a25bSPaul Moore netlbl_cipsov4_genl_policy) != 0) 1761fd2a25bSPaul Moore goto add_std_failure; 177fd385855SPaul Moore nla_for_each_nested(nla_b, nla_a, nla_b_rem) 1788f4c1f9bSThomas Graf switch (nla_type(nla_b)) { 179fd385855SPaul Moore case NLBL_CIPSOV4_A_MLSLVLLOC: 1801fd2a25bSPaul Moore if (nla_get_u32(nla_b) > 1811fd2a25bSPaul Moore CIPSO_V4_MAX_LOC_LVLS) 1821fd2a25bSPaul Moore goto add_std_failure; 183fd385855SPaul Moore if (nla_get_u32(nla_b) >= 184fd385855SPaul Moore doi_def->map.std->lvl.local_size) 185fd385855SPaul Moore doi_def->map.std->lvl.local_size = 186fd385855SPaul Moore nla_get_u32(nla_b) + 1; 18796cb8e33SPaul Moore break; 188fd385855SPaul Moore case NLBL_CIPSOV4_A_MLSLVLREM: 1891fd2a25bSPaul Moore if (nla_get_u32(nla_b) > 1901fd2a25bSPaul Moore CIPSO_V4_MAX_REM_LVLS) 1911fd2a25bSPaul Moore goto add_std_failure; 192fd385855SPaul Moore if (nla_get_u32(nla_b) >= 193fd385855SPaul Moore doi_def->map.std->lvl.cipso_size) 194fd385855SPaul Moore doi_def->map.std->lvl.cipso_size = 195fd385855SPaul Moore nla_get_u32(nla_b) + 1; 196fd385855SPaul Moore break; 19796cb8e33SPaul Moore } 19896cb8e33SPaul Moore } 19996cb8e33SPaul Moore doi_def->map.std->lvl.local = kcalloc(doi_def->map.std->lvl.local_size, 20096cb8e33SPaul Moore sizeof(u32), 20196cb8e33SPaul Moore GFP_KERNEL); 20296cb8e33SPaul Moore if (doi_def->map.std->lvl.local == NULL) { 20396cb8e33SPaul Moore ret_val = -ENOMEM; 20496cb8e33SPaul Moore goto add_std_failure; 20596cb8e33SPaul Moore } 20696cb8e33SPaul Moore doi_def->map.std->lvl.cipso = kcalloc(doi_def->map.std->lvl.cipso_size, 20796cb8e33SPaul Moore sizeof(u32), 20896cb8e33SPaul Moore GFP_KERNEL); 20996cb8e33SPaul Moore if (doi_def->map.std->lvl.cipso == NULL) { 21096cb8e33SPaul Moore ret_val = -ENOMEM; 21196cb8e33SPaul Moore goto add_std_failure; 21296cb8e33SPaul Moore } 213caff5b6aSPaul Moore for (iter = 0; iter < doi_def->map.std->lvl.local_size; iter++) 214caff5b6aSPaul Moore doi_def->map.std->lvl.local[iter] = CIPSO_V4_INV_LVL; 215caff5b6aSPaul Moore for (iter = 0; iter < doi_def->map.std->lvl.cipso_size; iter++) 216caff5b6aSPaul Moore doi_def->map.std->lvl.cipso[iter] = CIPSO_V4_INV_LVL; 217fd385855SPaul Moore nla_for_each_nested(nla_a, 218fd385855SPaul Moore info->attrs[NLBL_CIPSOV4_A_MLSLVLLST], 219fd385855SPaul Moore nla_a_rem) 2208f4c1f9bSThomas Graf if (nla_type(nla_a) == NLBL_CIPSOV4_A_MLSLVL) { 221fd385855SPaul Moore struct nlattr *lvl_loc; 222fd385855SPaul Moore struct nlattr *lvl_rem; 22396cb8e33SPaul Moore 224fd385855SPaul Moore lvl_loc = nla_find_nested(nla_a, 225fd385855SPaul Moore NLBL_CIPSOV4_A_MLSLVLLOC); 226fd385855SPaul Moore lvl_rem = nla_find_nested(nla_a, 227fd385855SPaul Moore NLBL_CIPSOV4_A_MLSLVLREM); 228fd385855SPaul Moore if (lvl_loc == NULL || lvl_rem == NULL) 229fd385855SPaul Moore goto add_std_failure; 230fd385855SPaul Moore doi_def->map.std->lvl.local[nla_get_u32(lvl_loc)] = 231fd385855SPaul Moore nla_get_u32(lvl_rem); 232fd385855SPaul Moore doi_def->map.std->lvl.cipso[nla_get_u32(lvl_rem)] = 233fd385855SPaul Moore nla_get_u32(lvl_loc); 234fd385855SPaul Moore } 235fd385855SPaul Moore 236fd385855SPaul Moore if (info->attrs[NLBL_CIPSOV4_A_MLSCATLST]) { 237fd385855SPaul Moore if (nla_validate_nested(info->attrs[NLBL_CIPSOV4_A_MLSCATLST], 238fd385855SPaul Moore NLBL_CIPSOV4_A_MAX, 239fd385855SPaul Moore netlbl_cipsov4_genl_policy) != 0) 240fd385855SPaul Moore goto add_std_failure; 241fd385855SPaul Moore 242fd385855SPaul Moore nla_for_each_nested(nla_a, 243fd385855SPaul Moore info->attrs[NLBL_CIPSOV4_A_MLSCATLST], 244fd385855SPaul Moore nla_a_rem) 2458f4c1f9bSThomas Graf if (nla_type(nla_a) == NLBL_CIPSOV4_A_MLSCAT) { 246fd385855SPaul Moore if (nla_validate_nested(nla_a, 247fd385855SPaul Moore NLBL_CIPSOV4_A_MAX, 248fd385855SPaul Moore netlbl_cipsov4_genl_policy) != 0) 249fd385855SPaul Moore goto add_std_failure; 250fd385855SPaul Moore nla_for_each_nested(nla_b, nla_a, nla_b_rem) 2518f4c1f9bSThomas Graf switch (nla_type(nla_b)) { 252fd385855SPaul Moore case NLBL_CIPSOV4_A_MLSCATLOC: 2531fd2a25bSPaul Moore if (nla_get_u32(nla_b) > 2541fd2a25bSPaul Moore CIPSO_V4_MAX_LOC_CATS) 2551fd2a25bSPaul Moore goto add_std_failure; 256fd385855SPaul Moore if (nla_get_u32(nla_b) >= 257fd385855SPaul Moore doi_def->map.std->cat.local_size) 258fd385855SPaul Moore doi_def->map.std->cat.local_size = 259fd385855SPaul Moore nla_get_u32(nla_b) + 1; 260fd385855SPaul Moore break; 261fd385855SPaul Moore case NLBL_CIPSOV4_A_MLSCATREM: 2621fd2a25bSPaul Moore if (nla_get_u32(nla_b) > 2631fd2a25bSPaul Moore CIPSO_V4_MAX_REM_CATS) 2641fd2a25bSPaul Moore goto add_std_failure; 265fd385855SPaul Moore if (nla_get_u32(nla_b) >= 266fd385855SPaul Moore doi_def->map.std->cat.cipso_size) 267fd385855SPaul Moore doi_def->map.std->cat.cipso_size = 268fd385855SPaul Moore nla_get_u32(nla_b) + 1; 269fd385855SPaul Moore break; 270fd385855SPaul Moore } 271fd385855SPaul Moore } 272fd385855SPaul Moore doi_def->map.std->cat.local = kcalloc( 273fd385855SPaul Moore doi_def->map.std->cat.local_size, 27496cb8e33SPaul Moore sizeof(u32), 27596cb8e33SPaul Moore GFP_KERNEL); 27696cb8e33SPaul Moore if (doi_def->map.std->cat.local == NULL) { 27796cb8e33SPaul Moore ret_val = -ENOMEM; 27896cb8e33SPaul Moore goto add_std_failure; 27996cb8e33SPaul Moore } 280fd385855SPaul Moore doi_def->map.std->cat.cipso = kcalloc( 281fd385855SPaul Moore doi_def->map.std->cat.cipso_size, 28296cb8e33SPaul Moore sizeof(u32), 28396cb8e33SPaul Moore GFP_KERNEL); 28496cb8e33SPaul Moore if (doi_def->map.std->cat.cipso == NULL) { 28596cb8e33SPaul Moore ret_val = -ENOMEM; 28696cb8e33SPaul Moore goto add_std_failure; 28796cb8e33SPaul Moore } 288caff5b6aSPaul Moore for (iter = 0; iter < doi_def->map.std->cat.local_size; iter++) 289caff5b6aSPaul Moore doi_def->map.std->cat.local[iter] = CIPSO_V4_INV_CAT; 290caff5b6aSPaul Moore for (iter = 0; iter < doi_def->map.std->cat.cipso_size; iter++) 291caff5b6aSPaul Moore doi_def->map.std->cat.cipso[iter] = CIPSO_V4_INV_CAT; 292fd385855SPaul Moore nla_for_each_nested(nla_a, 293fd385855SPaul Moore info->attrs[NLBL_CIPSOV4_A_MLSCATLST], 294fd385855SPaul Moore nla_a_rem) 2958f4c1f9bSThomas Graf if (nla_type(nla_a) == NLBL_CIPSOV4_A_MLSCAT) { 296fd385855SPaul Moore struct nlattr *cat_loc; 297fd385855SPaul Moore struct nlattr *cat_rem; 29896cb8e33SPaul Moore 299fd385855SPaul Moore cat_loc = nla_find_nested(nla_a, 300fd385855SPaul Moore NLBL_CIPSOV4_A_MLSCATLOC); 301fd385855SPaul Moore cat_rem = nla_find_nested(nla_a, 302fd385855SPaul Moore NLBL_CIPSOV4_A_MLSCATREM); 303fd385855SPaul Moore if (cat_loc == NULL || cat_rem == NULL) 30496cb8e33SPaul Moore goto add_std_failure; 305fd385855SPaul Moore doi_def->map.std->cat.local[ 306fd385855SPaul Moore nla_get_u32(cat_loc)] = 307fd385855SPaul Moore nla_get_u32(cat_rem); 308fd385855SPaul Moore doi_def->map.std->cat.cipso[ 309fd385855SPaul Moore nla_get_u32(cat_rem)] = 310fd385855SPaul Moore nla_get_u32(cat_loc); 311fd385855SPaul Moore } 31296cb8e33SPaul Moore } 31396cb8e33SPaul Moore 3146c2e8ac0SPaul Moore ret_val = cipso_v4_doi_add(doi_def, audit_info); 31596cb8e33SPaul Moore if (ret_val != 0) 31696cb8e33SPaul Moore goto add_std_failure; 31796cb8e33SPaul Moore return 0; 31896cb8e33SPaul Moore 31996cb8e33SPaul Moore add_std_failure: 320b1edeb10SPaul Moore cipso_v4_doi_free(doi_def); 32196cb8e33SPaul Moore return ret_val; 32296cb8e33SPaul Moore } 32396cb8e33SPaul Moore 32496cb8e33SPaul Moore /** 32596cb8e33SPaul Moore * netlbl_cipsov4_add_pass - Adds a CIPSO V4 DOI definition 326fd385855SPaul Moore * @info: the Generic NETLINK info block 3276c2e8ac0SPaul Moore * @audit_info: NetLabel audit information 32896cb8e33SPaul Moore * 32996cb8e33SPaul Moore * Description: 33096cb8e33SPaul Moore * Create a new CIPSO_V4_MAP_PASS DOI definition based on the given ADD message 33196cb8e33SPaul Moore * and add it to the CIPSO V4 engine. Return zero on success and non-zero on 33296cb8e33SPaul Moore * error. 33396cb8e33SPaul Moore * 33496cb8e33SPaul Moore */ 3356c2e8ac0SPaul Moore static int netlbl_cipsov4_add_pass(struct genl_info *info, 3366c2e8ac0SPaul Moore struct netlbl_audit *audit_info) 33796cb8e33SPaul Moore { 338fd385855SPaul Moore int ret_val; 33996cb8e33SPaul Moore struct cipso_v4_doi *doi_def = NULL; 34096cb8e33SPaul Moore 34132f50cdeSPaul Moore if (!info->attrs[NLBL_CIPSOV4_A_TAGLST]) 342fd385855SPaul Moore return -EINVAL; 34396cb8e33SPaul Moore 34496cb8e33SPaul Moore doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL); 345fd385855SPaul Moore if (doi_def == NULL) 346fd385855SPaul Moore return -ENOMEM; 34796cb8e33SPaul Moore doi_def->type = CIPSO_V4_MAP_PASS; 34896cb8e33SPaul Moore 349fd385855SPaul Moore ret_val = netlbl_cipsov4_add_common(info, doi_def); 350fd385855SPaul Moore if (ret_val != 0) 35196cb8e33SPaul Moore goto add_pass_failure; 35296cb8e33SPaul Moore 3536c2e8ac0SPaul Moore ret_val = cipso_v4_doi_add(doi_def, audit_info); 35496cb8e33SPaul Moore if (ret_val != 0) 35596cb8e33SPaul Moore goto add_pass_failure; 35696cb8e33SPaul Moore return 0; 35796cb8e33SPaul Moore 35896cb8e33SPaul Moore add_pass_failure: 359b1edeb10SPaul Moore cipso_v4_doi_free(doi_def); 36096cb8e33SPaul Moore return ret_val; 36196cb8e33SPaul Moore } 36296cb8e33SPaul Moore 36396cb8e33SPaul Moore /** 364d91d4079SPaul Moore * netlbl_cipsov4_add_local - Adds a CIPSO V4 DOI definition 365d91d4079SPaul Moore * @info: the Generic NETLINK info block 3666c2e8ac0SPaul Moore * @audit_info: NetLabel audit information 367d91d4079SPaul Moore * 368d91d4079SPaul Moore * Description: 369d91d4079SPaul Moore * Create a new CIPSO_V4_MAP_LOCAL DOI definition based on the given ADD 370d91d4079SPaul Moore * message and add it to the CIPSO V4 engine. Return zero on success and 371d91d4079SPaul Moore * non-zero on error. 372d91d4079SPaul Moore * 373d91d4079SPaul Moore */ 3746c2e8ac0SPaul Moore static int netlbl_cipsov4_add_local(struct genl_info *info, 3756c2e8ac0SPaul Moore struct netlbl_audit *audit_info) 376d91d4079SPaul Moore { 377d91d4079SPaul Moore int ret_val; 378d91d4079SPaul Moore struct cipso_v4_doi *doi_def = NULL; 379d91d4079SPaul Moore 380d91d4079SPaul Moore if (!info->attrs[NLBL_CIPSOV4_A_TAGLST]) 381d91d4079SPaul Moore return -EINVAL; 382d91d4079SPaul Moore 383d91d4079SPaul Moore doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL); 384d91d4079SPaul Moore if (doi_def == NULL) 385d91d4079SPaul Moore return -ENOMEM; 386d91d4079SPaul Moore doi_def->type = CIPSO_V4_MAP_LOCAL; 387d91d4079SPaul Moore 388d91d4079SPaul Moore ret_val = netlbl_cipsov4_add_common(info, doi_def); 389d91d4079SPaul Moore if (ret_val != 0) 390d91d4079SPaul Moore goto add_local_failure; 391d91d4079SPaul Moore 3926c2e8ac0SPaul Moore ret_val = cipso_v4_doi_add(doi_def, audit_info); 393d91d4079SPaul Moore if (ret_val != 0) 394d91d4079SPaul Moore goto add_local_failure; 395d91d4079SPaul Moore return 0; 396d91d4079SPaul Moore 397d91d4079SPaul Moore add_local_failure: 398d91d4079SPaul Moore cipso_v4_doi_free(doi_def); 399d91d4079SPaul Moore return ret_val; 400d91d4079SPaul Moore } 401d91d4079SPaul Moore 402d91d4079SPaul Moore /** 40396cb8e33SPaul Moore * netlbl_cipsov4_add - Handle an ADD message 40496cb8e33SPaul Moore * @skb: the NETLINK buffer 40596cb8e33SPaul Moore * @info: the Generic NETLINK info block 40696cb8e33SPaul Moore * 40796cb8e33SPaul Moore * Description: 40896cb8e33SPaul Moore * Create a new DOI definition based on the given ADD message and add it to the 40996cb8e33SPaul Moore * CIPSO V4 engine. Returns zero on success, negative values on failure. 41096cb8e33SPaul Moore * 41196cb8e33SPaul Moore */ 41296cb8e33SPaul Moore static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info) 41396cb8e33SPaul Moore 41496cb8e33SPaul Moore { 41596cb8e33SPaul Moore int ret_val = -EINVAL; 41695d4e6beSPaul Moore struct netlbl_audit audit_info; 41796cb8e33SPaul Moore 41832f50cdeSPaul Moore if (!info->attrs[NLBL_CIPSOV4_A_DOI] || 41932f50cdeSPaul Moore !info->attrs[NLBL_CIPSOV4_A_MTYPE]) 420fd385855SPaul Moore return -EINVAL; 42196cb8e33SPaul Moore 42295d4e6beSPaul Moore netlbl_netlink_auditinfo(skb, &audit_info); 4236c2e8ac0SPaul Moore switch (nla_get_u32(info->attrs[NLBL_CIPSOV4_A_MTYPE])) { 42415c45f7bSPaul Moore case CIPSO_V4_MAP_TRANS: 4256c2e8ac0SPaul Moore ret_val = netlbl_cipsov4_add_std(info, &audit_info); 42696cb8e33SPaul Moore break; 42796cb8e33SPaul Moore case CIPSO_V4_MAP_PASS: 4286c2e8ac0SPaul Moore ret_val = netlbl_cipsov4_add_pass(info, &audit_info); 42996cb8e33SPaul Moore break; 430d91d4079SPaul Moore case CIPSO_V4_MAP_LOCAL: 4316c2e8ac0SPaul Moore ret_val = netlbl_cipsov4_add_local(info, &audit_info); 432d91d4079SPaul Moore break; 43396cb8e33SPaul Moore } 43423bcdc1aSPaul Moore if (ret_val == 0) 435c783f1ceSPaul Moore atomic_inc(&netlabel_mgmt_protocount); 43696cb8e33SPaul Moore 43796cb8e33SPaul Moore return ret_val; 43896cb8e33SPaul Moore } 43996cb8e33SPaul Moore 44096cb8e33SPaul Moore /** 44196cb8e33SPaul Moore * netlbl_cipsov4_list - Handle a LIST message 44296cb8e33SPaul Moore * @skb: the NETLINK buffer 44396cb8e33SPaul Moore * @info: the Generic NETLINK info block 44496cb8e33SPaul Moore * 44596cb8e33SPaul Moore * Description: 446fd385855SPaul Moore * Process a user generated LIST message and respond accordingly. While the 447fd385855SPaul Moore * response message generated by the kernel is straightforward, determining 448fd385855SPaul Moore * before hand the size of the buffer to allocate is not (we have to generate 449fd385855SPaul Moore * the message to know the size). In order to keep this function sane what we 450fd385855SPaul Moore * do is allocate a buffer of NLMSG_GOODSIZE and try to fit the response in 451fd385855SPaul Moore * that size, if we fail then we restart with a larger buffer and try again. 452fd385855SPaul Moore * We continue in this manner until we hit a limit of failed attempts then we 453fd385855SPaul Moore * give up and just send an error message. Returns zero on success and 454fd385855SPaul Moore * negative values on error. 45596cb8e33SPaul Moore * 45696cb8e33SPaul Moore */ 45796cb8e33SPaul Moore static int netlbl_cipsov4_list(struct sk_buff *skb, struct genl_info *info) 45896cb8e33SPaul Moore { 459fd385855SPaul Moore int ret_val; 460fd385855SPaul Moore struct sk_buff *ans_skb = NULL; 461fd385855SPaul Moore u32 nlsze_mult = 1; 462fd385855SPaul Moore void *data; 46396cb8e33SPaul Moore u32 doi; 464fd385855SPaul Moore struct nlattr *nla_a; 465fd385855SPaul Moore struct nlattr *nla_b; 466fd385855SPaul Moore struct cipso_v4_doi *doi_def; 467fd385855SPaul Moore u32 iter; 46896cb8e33SPaul Moore 469fd385855SPaul Moore if (!info->attrs[NLBL_CIPSOV4_A_DOI]) { 470fd385855SPaul Moore ret_val = -EINVAL; 47196cb8e33SPaul Moore goto list_failure; 472fd385855SPaul Moore } 47396cb8e33SPaul Moore 474fd385855SPaul Moore list_start: 475339bf98fSThomas Graf ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE * nlsze_mult, GFP_KERNEL); 47696cb8e33SPaul Moore if (ans_skb == NULL) { 47796cb8e33SPaul Moore ret_val = -ENOMEM; 47896cb8e33SPaul Moore goto list_failure; 47996cb8e33SPaul Moore } 48017c157c8SThomas Graf data = genlmsg_put_reply(ans_skb, info, &netlbl_cipsov4_gnl_family, 48117c157c8SThomas Graf 0, NLBL_CIPSOV4_C_LIST); 482fd385855SPaul Moore if (data == NULL) { 483fd385855SPaul Moore ret_val = -ENOMEM; 484fd385855SPaul Moore goto list_failure; 485fd385855SPaul Moore } 48696cb8e33SPaul Moore 487fd385855SPaul Moore doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]); 488fd385855SPaul Moore 489fd385855SPaul Moore rcu_read_lock(); 490fd385855SPaul Moore doi_def = cipso_v4_doi_getdef(doi); 491fd385855SPaul Moore if (doi_def == NULL) { 492fd385855SPaul Moore ret_val = -EINVAL; 49356196701SPaul Moore goto list_failure_lock; 494fd385855SPaul Moore } 495fd385855SPaul Moore 496fd385855SPaul Moore ret_val = nla_put_u32(ans_skb, NLBL_CIPSOV4_A_MTYPE, doi_def->type); 497fd385855SPaul Moore if (ret_val != 0) 498fd385855SPaul Moore goto list_failure_lock; 499fd385855SPaul Moore 500fd385855SPaul Moore nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_TAGLST); 501fd385855SPaul Moore if (nla_a == NULL) { 502fd385855SPaul Moore ret_val = -ENOMEM; 503fd385855SPaul Moore goto list_failure_lock; 504fd385855SPaul Moore } 505fd385855SPaul Moore for (iter = 0; 506fd385855SPaul Moore iter < CIPSO_V4_TAG_MAXCNT && 507fd385855SPaul Moore doi_def->tags[iter] != CIPSO_V4_TAG_INVALID; 508fd385855SPaul Moore iter++) { 509fd385855SPaul Moore ret_val = nla_put_u8(ans_skb, 510fd385855SPaul Moore NLBL_CIPSOV4_A_TAG, 511fd385855SPaul Moore doi_def->tags[iter]); 512fd385855SPaul Moore if (ret_val != 0) 513fd385855SPaul Moore goto list_failure_lock; 514fd385855SPaul Moore } 515fd385855SPaul Moore nla_nest_end(ans_skb, nla_a); 516fd385855SPaul Moore 517fd385855SPaul Moore switch (doi_def->type) { 51815c45f7bSPaul Moore case CIPSO_V4_MAP_TRANS: 519fd385855SPaul Moore nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSLVLLST); 520fd385855SPaul Moore if (nla_a == NULL) { 521fd385855SPaul Moore ret_val = -ENOMEM; 522fd385855SPaul Moore goto list_failure_lock; 523fd385855SPaul Moore } 524fd385855SPaul Moore for (iter = 0; 525fd385855SPaul Moore iter < doi_def->map.std->lvl.local_size; 526fd385855SPaul Moore iter++) { 527fd385855SPaul Moore if (doi_def->map.std->lvl.local[iter] == 528fd385855SPaul Moore CIPSO_V4_INV_LVL) 529fd385855SPaul Moore continue; 530fd385855SPaul Moore 531fd385855SPaul Moore nla_b = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSLVL); 532fd385855SPaul Moore if (nla_b == NULL) { 533fd385855SPaul Moore ret_val = -ENOMEM; 534fd385855SPaul Moore goto list_retry; 535fd385855SPaul Moore } 536fd385855SPaul Moore ret_val = nla_put_u32(ans_skb, 537fd385855SPaul Moore NLBL_CIPSOV4_A_MLSLVLLOC, 538fd385855SPaul Moore iter); 539fd385855SPaul Moore if (ret_val != 0) 540fd385855SPaul Moore goto list_retry; 541fd385855SPaul Moore ret_val = nla_put_u32(ans_skb, 542fd385855SPaul Moore NLBL_CIPSOV4_A_MLSLVLREM, 543fd385855SPaul Moore doi_def->map.std->lvl.local[iter]); 544fd385855SPaul Moore if (ret_val != 0) 545fd385855SPaul Moore goto list_retry; 546fd385855SPaul Moore nla_nest_end(ans_skb, nla_b); 547fd385855SPaul Moore } 548fd385855SPaul Moore nla_nest_end(ans_skb, nla_a); 549fd385855SPaul Moore 550fd385855SPaul Moore nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSCATLST); 551fd385855SPaul Moore if (nla_a == NULL) { 552fd385855SPaul Moore ret_val = -ENOMEM; 553fd385855SPaul Moore goto list_retry; 554fd385855SPaul Moore } 555fd385855SPaul Moore for (iter = 0; 556fd385855SPaul Moore iter < doi_def->map.std->cat.local_size; 557fd385855SPaul Moore iter++) { 558fd385855SPaul Moore if (doi_def->map.std->cat.local[iter] == 559fd385855SPaul Moore CIPSO_V4_INV_CAT) 560fd385855SPaul Moore continue; 561fd385855SPaul Moore 562fd385855SPaul Moore nla_b = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSCAT); 563fd385855SPaul Moore if (nla_b == NULL) { 564fd385855SPaul Moore ret_val = -ENOMEM; 565fd385855SPaul Moore goto list_retry; 566fd385855SPaul Moore } 567fd385855SPaul Moore ret_val = nla_put_u32(ans_skb, 568fd385855SPaul Moore NLBL_CIPSOV4_A_MLSCATLOC, 569fd385855SPaul Moore iter); 570fd385855SPaul Moore if (ret_val != 0) 571fd385855SPaul Moore goto list_retry; 572fd385855SPaul Moore ret_val = nla_put_u32(ans_skb, 573fd385855SPaul Moore NLBL_CIPSOV4_A_MLSCATREM, 574fd385855SPaul Moore doi_def->map.std->cat.local[iter]); 575fd385855SPaul Moore if (ret_val != 0) 576fd385855SPaul Moore goto list_retry; 577fd385855SPaul Moore nla_nest_end(ans_skb, nla_b); 578fd385855SPaul Moore } 579fd385855SPaul Moore nla_nest_end(ans_skb, nla_a); 580fd385855SPaul Moore 581fd385855SPaul Moore break; 582fd385855SPaul Moore } 583fd385855SPaul Moore rcu_read_unlock(); 584fd385855SPaul Moore 585fd385855SPaul Moore genlmsg_end(ans_skb, data); 586fe785beeSDenis V. Lunev return genlmsg_reply(ans_skb, info); 58796cb8e33SPaul Moore 588fd385855SPaul Moore list_retry: 589fd385855SPaul Moore /* XXX - this limit is a guesstimate */ 590fd385855SPaul Moore if (nlsze_mult < 4) { 591fd385855SPaul Moore rcu_read_unlock(); 592fd385855SPaul Moore kfree_skb(ans_skb); 59383aa2e96SDenis V. Lunev nlsze_mult *= 2; 594fd385855SPaul Moore goto list_start; 595fd385855SPaul Moore } 596fd385855SPaul Moore list_failure_lock: 597fd385855SPaul Moore rcu_read_unlock(); 59896cb8e33SPaul Moore list_failure: 599fd385855SPaul Moore kfree_skb(ans_skb); 600fd385855SPaul Moore return ret_val; 601fd385855SPaul Moore } 602fd385855SPaul Moore 603fd385855SPaul Moore /** 604fd385855SPaul Moore * netlbl_cipsov4_listall_cb - cipso_v4_doi_walk() callback for LISTALL 605fd385855SPaul Moore * @doi_def: the CIPSOv4 DOI definition 606fd385855SPaul Moore * @arg: the netlbl_cipsov4_doiwalk_arg structure 607fd385855SPaul Moore * 608fd385855SPaul Moore * Description: 609fd385855SPaul Moore * This function is designed to be used as a callback to the 610fd385855SPaul Moore * cipso_v4_doi_walk() function for use in generating a response for a LISTALL 611fd385855SPaul Moore * message. Returns the size of the message on success, negative values on 612fd385855SPaul Moore * failure. 613fd385855SPaul Moore * 614fd385855SPaul Moore */ 615fd385855SPaul Moore static int netlbl_cipsov4_listall_cb(struct cipso_v4_doi *doi_def, void *arg) 616fd385855SPaul Moore { 617fd385855SPaul Moore int ret_val = -ENOMEM; 618fd385855SPaul Moore struct netlbl_cipsov4_doiwalk_arg *cb_arg = arg; 619fd385855SPaul Moore void *data; 620fd385855SPaul Moore 62115e47304SEric W. Biederman data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).portid, 62217c157c8SThomas Graf cb_arg->seq, &netlbl_cipsov4_gnl_family, 62317c157c8SThomas Graf NLM_F_MULTI, NLBL_CIPSOV4_C_LISTALL); 624fd385855SPaul Moore if (data == NULL) 625fd385855SPaul Moore goto listall_cb_failure; 626fd385855SPaul Moore 627fd385855SPaul Moore ret_val = nla_put_u32(cb_arg->skb, NLBL_CIPSOV4_A_DOI, doi_def->doi); 628fd385855SPaul Moore if (ret_val != 0) 629fd385855SPaul Moore goto listall_cb_failure; 630fd385855SPaul Moore ret_val = nla_put_u32(cb_arg->skb, 631fd385855SPaul Moore NLBL_CIPSOV4_A_MTYPE, 632fd385855SPaul Moore doi_def->type); 633fd385855SPaul Moore if (ret_val != 0) 634fd385855SPaul Moore goto listall_cb_failure; 635fd385855SPaul Moore 636053c095aSJohannes Berg genlmsg_end(cb_arg->skb, data); 637053c095aSJohannes Berg return 0; 638fd385855SPaul Moore 639fd385855SPaul Moore listall_cb_failure: 640fd385855SPaul Moore genlmsg_cancel(cb_arg->skb, data); 64196cb8e33SPaul Moore return ret_val; 64296cb8e33SPaul Moore } 64396cb8e33SPaul Moore 64496cb8e33SPaul Moore /** 64596cb8e33SPaul Moore * netlbl_cipsov4_listall - Handle a LISTALL message 64696cb8e33SPaul Moore * @skb: the NETLINK buffer 647fd385855SPaul Moore * @cb: the NETLINK callback 64896cb8e33SPaul Moore * 64996cb8e33SPaul Moore * Description: 65096cb8e33SPaul Moore * Process a user generated LISTALL message and respond accordingly. Returns 65196cb8e33SPaul Moore * zero on success and negative values on error. 65296cb8e33SPaul Moore * 65396cb8e33SPaul Moore */ 654fd385855SPaul Moore static int netlbl_cipsov4_listall(struct sk_buff *skb, 655fd385855SPaul Moore struct netlink_callback *cb) 65696cb8e33SPaul Moore { 657fd385855SPaul Moore struct netlbl_cipsov4_doiwalk_arg cb_arg; 65856196701SPaul Moore u32 doi_skip = cb->args[0]; 65996cb8e33SPaul Moore 660fd385855SPaul Moore cb_arg.nl_cb = cb; 661fd385855SPaul Moore cb_arg.skb = skb; 662fd385855SPaul Moore cb_arg.seq = cb->nlh->nlmsg_seq; 66396cb8e33SPaul Moore 664fd385855SPaul Moore cipso_v4_doi_walk(&doi_skip, netlbl_cipsov4_listall_cb, &cb_arg); 66596cb8e33SPaul Moore 666fd385855SPaul Moore cb->args[0] = doi_skip; 667fd385855SPaul Moore return skb->len; 66896cb8e33SPaul Moore } 66996cb8e33SPaul Moore 67096cb8e33SPaul Moore /** 671b1edeb10SPaul Moore * netlbl_cipsov4_remove_cb - netlbl_cipsov4_remove() callback for REMOVE 672b1edeb10SPaul Moore * @entry: LSM domain mapping entry 673b1edeb10SPaul Moore * @arg: the netlbl_domhsh_walk_arg structure 674b1edeb10SPaul Moore * 675b1edeb10SPaul Moore * Description: 676b1edeb10SPaul Moore * This function is intended for use by netlbl_cipsov4_remove() as the callback 677b1edeb10SPaul Moore * for the netlbl_domhsh_walk() function; it removes LSM domain map entries 678b1edeb10SPaul Moore * which are associated with the CIPSO DOI specified in @arg. Returns zero on 679b1edeb10SPaul Moore * success, negative values on failure. 680b1edeb10SPaul Moore * 681b1edeb10SPaul Moore */ 682b1edeb10SPaul Moore static int netlbl_cipsov4_remove_cb(struct netlbl_dom_map *entry, void *arg) 683b1edeb10SPaul Moore { 684b1edeb10SPaul Moore struct netlbl_domhsh_walk_arg *cb_arg = arg; 685b1edeb10SPaul Moore 6866a8b7f0cSPaul Moore if (entry->def.type == NETLBL_NLTYPE_CIPSOV4 && 6876a8b7f0cSPaul Moore entry->def.cipso->doi == cb_arg->doi) 688b1edeb10SPaul Moore return netlbl_domhsh_remove_entry(entry, cb_arg->audit_info); 689b1edeb10SPaul Moore 690b1edeb10SPaul Moore return 0; 691b1edeb10SPaul Moore } 692b1edeb10SPaul Moore 693b1edeb10SPaul Moore /** 69496cb8e33SPaul Moore * netlbl_cipsov4_remove - Handle a REMOVE message 69596cb8e33SPaul Moore * @skb: the NETLINK buffer 69696cb8e33SPaul Moore * @info: the Generic NETLINK info block 69796cb8e33SPaul Moore * 69896cb8e33SPaul Moore * Description: 69996cb8e33SPaul Moore * Process a user generated REMOVE message and respond accordingly. Returns 70096cb8e33SPaul Moore * zero on success, negative values on failure. 70196cb8e33SPaul Moore * 70296cb8e33SPaul Moore */ 70396cb8e33SPaul Moore static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info) 70496cb8e33SPaul Moore { 705fd385855SPaul Moore int ret_val = -EINVAL; 706b1edeb10SPaul Moore struct netlbl_domhsh_walk_arg cb_arg; 70795d4e6beSPaul Moore struct netlbl_audit audit_info; 708b1edeb10SPaul Moore u32 skip_bkt = 0; 709b1edeb10SPaul Moore u32 skip_chain = 0; 71096cb8e33SPaul Moore 71195d4e6beSPaul Moore if (!info->attrs[NLBL_CIPSOV4_A_DOI]) 71295d4e6beSPaul Moore return -EINVAL; 71395d4e6beSPaul Moore 71495d4e6beSPaul Moore netlbl_netlink_auditinfo(skb, &audit_info); 7156c2e8ac0SPaul Moore cb_arg.doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]); 716b1edeb10SPaul Moore cb_arg.audit_info = &audit_info; 717b1edeb10SPaul Moore ret_val = netlbl_domhsh_walk(&skip_bkt, &skip_chain, 718b1edeb10SPaul Moore netlbl_cipsov4_remove_cb, &cb_arg); 719b1edeb10SPaul Moore if (ret_val == 0 || ret_val == -ENOENT) { 7206c2e8ac0SPaul Moore ret_val = cipso_v4_doi_remove(cb_arg.doi, &audit_info); 72123bcdc1aSPaul Moore if (ret_val == 0) 722c783f1ceSPaul Moore atomic_dec(&netlabel_mgmt_protocount); 723b1edeb10SPaul Moore } 72495d4e6beSPaul Moore 72596cb8e33SPaul Moore return ret_val; 72696cb8e33SPaul Moore } 72796cb8e33SPaul Moore 72896cb8e33SPaul Moore /* 72996cb8e33SPaul Moore * NetLabel Generic NETLINK Command Definitions 73096cb8e33SPaul Moore */ 73196cb8e33SPaul Moore 7324534de83SJohannes Berg static const struct genl_ops netlbl_cipsov4_ops[] = { 733227c43c3SPavel Emelyanov { 73496cb8e33SPaul Moore .cmd = NLBL_CIPSOV4_C_ADD, 735fd385855SPaul Moore .flags = GENL_ADMIN_PERM, 736fd385855SPaul Moore .policy = netlbl_cipsov4_genl_policy, 73796cb8e33SPaul Moore .doit = netlbl_cipsov4_add, 73896cb8e33SPaul Moore .dumpit = NULL, 739227c43c3SPavel Emelyanov }, 740227c43c3SPavel Emelyanov { 74196cb8e33SPaul Moore .cmd = NLBL_CIPSOV4_C_REMOVE, 742fd385855SPaul Moore .flags = GENL_ADMIN_PERM, 743fd385855SPaul Moore .policy = netlbl_cipsov4_genl_policy, 74496cb8e33SPaul Moore .doit = netlbl_cipsov4_remove, 74596cb8e33SPaul Moore .dumpit = NULL, 746227c43c3SPavel Emelyanov }, 747227c43c3SPavel Emelyanov { 74896cb8e33SPaul Moore .cmd = NLBL_CIPSOV4_C_LIST, 74996cb8e33SPaul Moore .flags = 0, 750fd385855SPaul Moore .policy = netlbl_cipsov4_genl_policy, 75196cb8e33SPaul Moore .doit = netlbl_cipsov4_list, 75296cb8e33SPaul Moore .dumpit = NULL, 753227c43c3SPavel Emelyanov }, 754227c43c3SPavel Emelyanov { 75596cb8e33SPaul Moore .cmd = NLBL_CIPSOV4_C_LISTALL, 75696cb8e33SPaul Moore .flags = 0, 757fd385855SPaul Moore .policy = netlbl_cipsov4_genl_policy, 758fd385855SPaul Moore .doit = NULL, 759fd385855SPaul Moore .dumpit = netlbl_cipsov4_listall, 760227c43c3SPavel Emelyanov }, 76196cb8e33SPaul Moore }; 76296cb8e33SPaul Moore 763*489111e5SJohannes Berg static struct genl_family netlbl_cipsov4_gnl_family = { 764*489111e5SJohannes Berg .hdrsize = 0, 765*489111e5SJohannes Berg .name = NETLBL_NLTYPE_CIPSOV4_NAME, 766*489111e5SJohannes Berg .version = NETLBL_PROTO_VERSION, 767*489111e5SJohannes Berg .maxattr = NLBL_CIPSOV4_A_MAX, 768*489111e5SJohannes Berg .module = THIS_MODULE, 769*489111e5SJohannes Berg .ops = netlbl_cipsov4_ops, 770*489111e5SJohannes Berg .n_ops = ARRAY_SIZE(netlbl_cipsov4_ops), 771*489111e5SJohannes Berg }; 772*489111e5SJohannes 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 */ 78505705e4eSPavel Emelyanov int __init netlbl_cipsov4_genl_init(void) 78696cb8e33SPaul Moore { 787*489111e5SJohannes Berg return genl_register_family(&netlbl_cipsov4_gnl_family); 78896cb8e33SPaul Moore } 789