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> 4196cb8e33SPaul Moore 4296cb8e33SPaul Moore #include "netlabel_user.h" 4396cb8e33SPaul Moore #include "netlabel_cipso_v4.h" 4423bcdc1aSPaul Moore #include "netlabel_mgmt.h" 4596cb8e33SPaul Moore 46fd385855SPaul Moore /* Argument struct for cipso_v4_doi_walk() */ 47fd385855SPaul Moore struct netlbl_cipsov4_doiwalk_arg { 48fd385855SPaul Moore struct netlink_callback *nl_cb; 49fd385855SPaul Moore struct sk_buff *skb; 50fd385855SPaul Moore u32 seq; 51fd385855SPaul Moore }; 52fd385855SPaul Moore 5396cb8e33SPaul Moore /* NetLabel Generic NETLINK CIPSOv4 family */ 5496cb8e33SPaul Moore static struct genl_family netlbl_cipsov4_gnl_family = { 5596cb8e33SPaul Moore .id = GENL_ID_GENERATE, 5696cb8e33SPaul Moore .hdrsize = 0, 5796cb8e33SPaul Moore .name = NETLBL_NLTYPE_CIPSOV4_NAME, 5896cb8e33SPaul Moore .version = NETLBL_PROTO_VERSION, 59fd385855SPaul Moore .maxattr = NLBL_CIPSOV4_A_MAX, 6096cb8e33SPaul Moore }; 6196cb8e33SPaul Moore 62fd385855SPaul Moore /* NetLabel Netlink attribute policy */ 63ef7c79edSPatrick McHardy static const struct nla_policy netlbl_cipsov4_genl_policy[NLBL_CIPSOV4_A_MAX + 1] = { 64fd385855SPaul Moore [NLBL_CIPSOV4_A_DOI] = { .type = NLA_U32 }, 65fd385855SPaul Moore [NLBL_CIPSOV4_A_MTYPE] = { .type = NLA_U32 }, 66fd385855SPaul Moore [NLBL_CIPSOV4_A_TAG] = { .type = NLA_U8 }, 67fd385855SPaul Moore [NLBL_CIPSOV4_A_TAGLST] = { .type = NLA_NESTED }, 68fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSLVLLOC] = { .type = NLA_U32 }, 69fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSLVLREM] = { .type = NLA_U32 }, 70fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSLVL] = { .type = NLA_NESTED }, 71fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSLVLLST] = { .type = NLA_NESTED }, 72fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSCATLOC] = { .type = NLA_U32 }, 73fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSCATREM] = { .type = NLA_U32 }, 74fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSCAT] = { .type = NLA_NESTED }, 75fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSCATLST] = { .type = NLA_NESTED }, 76fd385855SPaul Moore }; 7796cb8e33SPaul Moore 7896cb8e33SPaul Moore /* 7996cb8e33SPaul Moore * Helper Functions 8096cb8e33SPaul Moore */ 8196cb8e33SPaul Moore 8296cb8e33SPaul Moore /** 8396cb8e33SPaul Moore * netlbl_cipsov4_doi_free - Frees a CIPSO V4 DOI definition 8496cb8e33SPaul Moore * @entry: the entry's RCU field 8596cb8e33SPaul Moore * 8696cb8e33SPaul Moore * Description: 8796cb8e33SPaul Moore * This function is designed to be used as a callback to the call_rcu() 8896cb8e33SPaul Moore * function so that the memory allocated to the DOI definition can be released 8996cb8e33SPaul Moore * safely. 9096cb8e33SPaul Moore * 9196cb8e33SPaul Moore */ 9296cb8e33SPaul Moore static void netlbl_cipsov4_doi_free(struct rcu_head *entry) 9396cb8e33SPaul Moore { 9496cb8e33SPaul Moore struct cipso_v4_doi *ptr; 9596cb8e33SPaul Moore 9696cb8e33SPaul Moore ptr = container_of(entry, struct cipso_v4_doi, rcu); 9796cb8e33SPaul Moore switch (ptr->type) { 9896cb8e33SPaul Moore case CIPSO_V4_MAP_STD: 9996cb8e33SPaul Moore kfree(ptr->map.std->lvl.cipso); 10096cb8e33SPaul Moore kfree(ptr->map.std->lvl.local); 10196cb8e33SPaul Moore kfree(ptr->map.std->cat.cipso); 10296cb8e33SPaul Moore kfree(ptr->map.std->cat.local); 10396cb8e33SPaul Moore break; 10496cb8e33SPaul Moore } 10596cb8e33SPaul Moore kfree(ptr); 10696cb8e33SPaul Moore } 10796cb8e33SPaul Moore 108fd385855SPaul Moore /** 109fd385855SPaul Moore * netlbl_cipsov4_add_common - Parse the common sections of a ADD message 110fd385855SPaul Moore * @info: the Generic NETLINK info block 111fd385855SPaul Moore * @doi_def: the CIPSO V4 DOI definition 112fd385855SPaul Moore * 113fd385855SPaul Moore * Description: 114fd385855SPaul Moore * Parse the common sections of a ADD message and fill in the related values 115fd385855SPaul Moore * in @doi_def. Returns zero on success, negative values on failure. 116fd385855SPaul Moore * 117fd385855SPaul Moore */ 118fd385855SPaul Moore static int netlbl_cipsov4_add_common(struct genl_info *info, 119fd385855SPaul Moore struct cipso_v4_doi *doi_def) 120fd385855SPaul Moore { 121fd385855SPaul Moore struct nlattr *nla; 122fd385855SPaul Moore int nla_rem; 123fd385855SPaul Moore u32 iter = 0; 124fd385855SPaul Moore 125fd385855SPaul Moore doi_def->doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]); 126fd385855SPaul Moore 127fd385855SPaul Moore if (nla_validate_nested(info->attrs[NLBL_CIPSOV4_A_TAGLST], 128fd385855SPaul Moore NLBL_CIPSOV4_A_MAX, 129fd385855SPaul Moore netlbl_cipsov4_genl_policy) != 0) 130fd385855SPaul Moore return -EINVAL; 131fd385855SPaul Moore 132fd385855SPaul Moore nla_for_each_nested(nla, info->attrs[NLBL_CIPSOV4_A_TAGLST], nla_rem) 133*8f4c1f9bSThomas Graf if (nla_type(nla) == NLBL_CIPSOV4_A_TAG) { 1342a2f11c2SPaul Moore if (iter >= CIPSO_V4_TAG_MAXCNT) 135fd385855SPaul Moore return -EINVAL; 136fd385855SPaul Moore doi_def->tags[iter++] = nla_get_u8(nla); 137fd385855SPaul Moore } 1382a2f11c2SPaul Moore while (iter < CIPSO_V4_TAG_MAXCNT) 1392a2f11c2SPaul Moore doi_def->tags[iter++] = CIPSO_V4_TAG_INVALID; 140fd385855SPaul Moore 141fd385855SPaul Moore return 0; 142fd385855SPaul Moore } 14396cb8e33SPaul Moore 14496cb8e33SPaul Moore /* 14596cb8e33SPaul Moore * NetLabel Command Handlers 14696cb8e33SPaul Moore */ 14796cb8e33SPaul Moore 14896cb8e33SPaul Moore /** 14996cb8e33SPaul Moore * netlbl_cipsov4_add_std - Adds a CIPSO V4 DOI definition 150fd385855SPaul Moore * @info: the Generic NETLINK info block 15196cb8e33SPaul Moore * 15296cb8e33SPaul Moore * Description: 15396cb8e33SPaul Moore * Create a new CIPSO_V4_MAP_STD DOI definition based on the given ADD message 15496cb8e33SPaul Moore * and add it to the CIPSO V4 engine. Return zero on success and non-zero on 15596cb8e33SPaul Moore * error. 15696cb8e33SPaul Moore * 15796cb8e33SPaul Moore */ 158fd385855SPaul Moore static int netlbl_cipsov4_add_std(struct genl_info *info) 15996cb8e33SPaul Moore { 16096cb8e33SPaul Moore int ret_val = -EINVAL; 16196cb8e33SPaul Moore struct cipso_v4_doi *doi_def = NULL; 162fd385855SPaul Moore struct nlattr *nla_a; 163fd385855SPaul Moore struct nlattr *nla_b; 164fd385855SPaul Moore int nla_a_rem; 165fd385855SPaul Moore int nla_b_rem; 166caff5b6aSPaul Moore u32 iter; 16796cb8e33SPaul Moore 16832f50cdeSPaul Moore if (!info->attrs[NLBL_CIPSOV4_A_TAGLST] || 169fd385855SPaul Moore !info->attrs[NLBL_CIPSOV4_A_MLSLVLLST]) 170fd385855SPaul Moore return -EINVAL; 171fd385855SPaul Moore 172fd385855SPaul Moore if (nla_validate_nested(info->attrs[NLBL_CIPSOV4_A_MLSLVLLST], 173fd385855SPaul Moore NLBL_CIPSOV4_A_MAX, 174fd385855SPaul Moore netlbl_cipsov4_genl_policy) != 0) 175fd385855SPaul Moore return -EINVAL; 17696cb8e33SPaul Moore 17796cb8e33SPaul Moore doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL); 178fd385855SPaul Moore if (doi_def == NULL) 179fd385855SPaul Moore return -ENOMEM; 18096cb8e33SPaul Moore doi_def->map.std = kzalloc(sizeof(*doi_def->map.std), GFP_KERNEL); 18196cb8e33SPaul Moore if (doi_def->map.std == NULL) { 18296cb8e33SPaul Moore ret_val = -ENOMEM; 18396cb8e33SPaul Moore goto add_std_failure; 18496cb8e33SPaul Moore } 18596cb8e33SPaul Moore doi_def->type = CIPSO_V4_MAP_STD; 18696cb8e33SPaul Moore 187fd385855SPaul Moore ret_val = netlbl_cipsov4_add_common(info, doi_def); 188fd385855SPaul Moore if (ret_val != 0) 18996cb8e33SPaul Moore goto add_std_failure; 1901fd2a25bSPaul Moore ret_val = -EINVAL; 191fd385855SPaul Moore 192fd385855SPaul Moore nla_for_each_nested(nla_a, 193fd385855SPaul Moore info->attrs[NLBL_CIPSOV4_A_MLSLVLLST], 194fd385855SPaul Moore nla_a_rem) 195*8f4c1f9bSThomas Graf if (nla_type(nla_a) == NLBL_CIPSOV4_A_MLSLVL) { 1961fd2a25bSPaul Moore if (nla_validate_nested(nla_a, 1971fd2a25bSPaul Moore NLBL_CIPSOV4_A_MAX, 1981fd2a25bSPaul Moore netlbl_cipsov4_genl_policy) != 0) 1991fd2a25bSPaul Moore goto add_std_failure; 200fd385855SPaul Moore nla_for_each_nested(nla_b, nla_a, nla_b_rem) 201*8f4c1f9bSThomas Graf switch (nla_type(nla_b)) { 202fd385855SPaul Moore case NLBL_CIPSOV4_A_MLSLVLLOC: 2031fd2a25bSPaul Moore if (nla_get_u32(nla_b) > 2041fd2a25bSPaul Moore CIPSO_V4_MAX_LOC_LVLS) 2051fd2a25bSPaul Moore goto add_std_failure; 206fd385855SPaul Moore if (nla_get_u32(nla_b) >= 207fd385855SPaul Moore doi_def->map.std->lvl.local_size) 208fd385855SPaul Moore doi_def->map.std->lvl.local_size = 209fd385855SPaul Moore nla_get_u32(nla_b) + 1; 21096cb8e33SPaul Moore break; 211fd385855SPaul Moore case NLBL_CIPSOV4_A_MLSLVLREM: 2121fd2a25bSPaul Moore if (nla_get_u32(nla_b) > 2131fd2a25bSPaul Moore CIPSO_V4_MAX_REM_LVLS) 2141fd2a25bSPaul Moore goto add_std_failure; 215fd385855SPaul Moore if (nla_get_u32(nla_b) >= 216fd385855SPaul Moore doi_def->map.std->lvl.cipso_size) 217fd385855SPaul Moore doi_def->map.std->lvl.cipso_size = 218fd385855SPaul Moore nla_get_u32(nla_b) + 1; 219fd385855SPaul Moore break; 22096cb8e33SPaul Moore } 22196cb8e33SPaul Moore } 22296cb8e33SPaul Moore doi_def->map.std->lvl.local = kcalloc(doi_def->map.std->lvl.local_size, 22396cb8e33SPaul Moore sizeof(u32), 22496cb8e33SPaul Moore GFP_KERNEL); 22596cb8e33SPaul Moore if (doi_def->map.std->lvl.local == NULL) { 22696cb8e33SPaul Moore ret_val = -ENOMEM; 22796cb8e33SPaul Moore goto add_std_failure; 22896cb8e33SPaul Moore } 22996cb8e33SPaul Moore doi_def->map.std->lvl.cipso = kcalloc(doi_def->map.std->lvl.cipso_size, 23096cb8e33SPaul Moore sizeof(u32), 23196cb8e33SPaul Moore GFP_KERNEL); 23296cb8e33SPaul Moore if (doi_def->map.std->lvl.cipso == NULL) { 23396cb8e33SPaul Moore ret_val = -ENOMEM; 23496cb8e33SPaul Moore goto add_std_failure; 23596cb8e33SPaul Moore } 236caff5b6aSPaul Moore for (iter = 0; iter < doi_def->map.std->lvl.local_size; iter++) 237caff5b6aSPaul Moore doi_def->map.std->lvl.local[iter] = CIPSO_V4_INV_LVL; 238caff5b6aSPaul Moore for (iter = 0; iter < doi_def->map.std->lvl.cipso_size; iter++) 239caff5b6aSPaul Moore doi_def->map.std->lvl.cipso[iter] = CIPSO_V4_INV_LVL; 240fd385855SPaul Moore nla_for_each_nested(nla_a, 241fd385855SPaul Moore info->attrs[NLBL_CIPSOV4_A_MLSLVLLST], 242fd385855SPaul Moore nla_a_rem) 243*8f4c1f9bSThomas Graf if (nla_type(nla_a) == NLBL_CIPSOV4_A_MLSLVL) { 244fd385855SPaul Moore struct nlattr *lvl_loc; 245fd385855SPaul Moore struct nlattr *lvl_rem; 24696cb8e33SPaul Moore 247fd385855SPaul Moore lvl_loc = nla_find_nested(nla_a, 248fd385855SPaul Moore NLBL_CIPSOV4_A_MLSLVLLOC); 249fd385855SPaul Moore lvl_rem = nla_find_nested(nla_a, 250fd385855SPaul Moore NLBL_CIPSOV4_A_MLSLVLREM); 251fd385855SPaul Moore if (lvl_loc == NULL || lvl_rem == NULL) 252fd385855SPaul Moore goto add_std_failure; 253fd385855SPaul Moore doi_def->map.std->lvl.local[nla_get_u32(lvl_loc)] = 254fd385855SPaul Moore nla_get_u32(lvl_rem); 255fd385855SPaul Moore doi_def->map.std->lvl.cipso[nla_get_u32(lvl_rem)] = 256fd385855SPaul Moore nla_get_u32(lvl_loc); 257fd385855SPaul Moore } 258fd385855SPaul Moore 259fd385855SPaul Moore if (info->attrs[NLBL_CIPSOV4_A_MLSCATLST]) { 260fd385855SPaul Moore if (nla_validate_nested(info->attrs[NLBL_CIPSOV4_A_MLSCATLST], 261fd385855SPaul Moore NLBL_CIPSOV4_A_MAX, 262fd385855SPaul Moore netlbl_cipsov4_genl_policy) != 0) 263fd385855SPaul Moore goto add_std_failure; 264fd385855SPaul Moore 265fd385855SPaul Moore nla_for_each_nested(nla_a, 266fd385855SPaul Moore info->attrs[NLBL_CIPSOV4_A_MLSCATLST], 267fd385855SPaul Moore nla_a_rem) 268*8f4c1f9bSThomas Graf if (nla_type(nla_a) == NLBL_CIPSOV4_A_MLSCAT) { 269fd385855SPaul Moore if (nla_validate_nested(nla_a, 270fd385855SPaul Moore NLBL_CIPSOV4_A_MAX, 271fd385855SPaul Moore netlbl_cipsov4_genl_policy) != 0) 272fd385855SPaul Moore goto add_std_failure; 273fd385855SPaul Moore nla_for_each_nested(nla_b, nla_a, nla_b_rem) 274*8f4c1f9bSThomas Graf switch (nla_type(nla_b)) { 275fd385855SPaul Moore case NLBL_CIPSOV4_A_MLSCATLOC: 2761fd2a25bSPaul Moore if (nla_get_u32(nla_b) > 2771fd2a25bSPaul Moore CIPSO_V4_MAX_LOC_CATS) 2781fd2a25bSPaul Moore goto add_std_failure; 279fd385855SPaul Moore if (nla_get_u32(nla_b) >= 280fd385855SPaul Moore doi_def->map.std->cat.local_size) 281fd385855SPaul Moore doi_def->map.std->cat.local_size = 282fd385855SPaul Moore nla_get_u32(nla_b) + 1; 283fd385855SPaul Moore break; 284fd385855SPaul Moore case NLBL_CIPSOV4_A_MLSCATREM: 2851fd2a25bSPaul Moore if (nla_get_u32(nla_b) > 2861fd2a25bSPaul Moore CIPSO_V4_MAX_REM_CATS) 2871fd2a25bSPaul Moore goto add_std_failure; 288fd385855SPaul Moore if (nla_get_u32(nla_b) >= 289fd385855SPaul Moore doi_def->map.std->cat.cipso_size) 290fd385855SPaul Moore doi_def->map.std->cat.cipso_size = 291fd385855SPaul Moore nla_get_u32(nla_b) + 1; 292fd385855SPaul Moore break; 293fd385855SPaul Moore } 294fd385855SPaul Moore } 295fd385855SPaul Moore doi_def->map.std->cat.local = kcalloc( 296fd385855SPaul Moore doi_def->map.std->cat.local_size, 29796cb8e33SPaul Moore sizeof(u32), 29896cb8e33SPaul Moore GFP_KERNEL); 29996cb8e33SPaul Moore if (doi_def->map.std->cat.local == NULL) { 30096cb8e33SPaul Moore ret_val = -ENOMEM; 30196cb8e33SPaul Moore goto add_std_failure; 30296cb8e33SPaul Moore } 303fd385855SPaul Moore doi_def->map.std->cat.cipso = kcalloc( 304fd385855SPaul Moore doi_def->map.std->cat.cipso_size, 30596cb8e33SPaul Moore sizeof(u32), 30696cb8e33SPaul Moore GFP_KERNEL); 30796cb8e33SPaul Moore if (doi_def->map.std->cat.cipso == NULL) { 30896cb8e33SPaul Moore ret_val = -ENOMEM; 30996cb8e33SPaul Moore goto add_std_failure; 31096cb8e33SPaul Moore } 311caff5b6aSPaul Moore for (iter = 0; iter < doi_def->map.std->cat.local_size; iter++) 312caff5b6aSPaul Moore doi_def->map.std->cat.local[iter] = CIPSO_V4_INV_CAT; 313caff5b6aSPaul Moore for (iter = 0; iter < doi_def->map.std->cat.cipso_size; iter++) 314caff5b6aSPaul Moore doi_def->map.std->cat.cipso[iter] = CIPSO_V4_INV_CAT; 315fd385855SPaul Moore nla_for_each_nested(nla_a, 316fd385855SPaul Moore info->attrs[NLBL_CIPSOV4_A_MLSCATLST], 317fd385855SPaul Moore nla_a_rem) 318*8f4c1f9bSThomas Graf if (nla_type(nla_a) == NLBL_CIPSOV4_A_MLSCAT) { 319fd385855SPaul Moore struct nlattr *cat_loc; 320fd385855SPaul Moore struct nlattr *cat_rem; 32196cb8e33SPaul Moore 322fd385855SPaul Moore cat_loc = nla_find_nested(nla_a, 323fd385855SPaul Moore NLBL_CIPSOV4_A_MLSCATLOC); 324fd385855SPaul Moore cat_rem = nla_find_nested(nla_a, 325fd385855SPaul Moore NLBL_CIPSOV4_A_MLSCATREM); 326fd385855SPaul Moore if (cat_loc == NULL || cat_rem == NULL) 32796cb8e33SPaul Moore goto add_std_failure; 328fd385855SPaul Moore doi_def->map.std->cat.local[ 329fd385855SPaul Moore nla_get_u32(cat_loc)] = 330fd385855SPaul Moore nla_get_u32(cat_rem); 331fd385855SPaul Moore doi_def->map.std->cat.cipso[ 332fd385855SPaul Moore nla_get_u32(cat_rem)] = 333fd385855SPaul Moore nla_get_u32(cat_loc); 334fd385855SPaul Moore } 33596cb8e33SPaul Moore } 33696cb8e33SPaul Moore 33796cb8e33SPaul Moore ret_val = cipso_v4_doi_add(doi_def); 33896cb8e33SPaul Moore if (ret_val != 0) 33996cb8e33SPaul Moore goto add_std_failure; 34096cb8e33SPaul Moore return 0; 34196cb8e33SPaul Moore 34296cb8e33SPaul Moore add_std_failure: 34396cb8e33SPaul Moore if (doi_def) 34496cb8e33SPaul Moore netlbl_cipsov4_doi_free(&doi_def->rcu); 34596cb8e33SPaul Moore return ret_val; 34696cb8e33SPaul Moore } 34796cb8e33SPaul Moore 34896cb8e33SPaul Moore /** 34996cb8e33SPaul Moore * netlbl_cipsov4_add_pass - Adds a CIPSO V4 DOI definition 350fd385855SPaul Moore * @info: the Generic NETLINK info block 35196cb8e33SPaul Moore * 35296cb8e33SPaul Moore * Description: 35396cb8e33SPaul Moore * Create a new CIPSO_V4_MAP_PASS DOI definition based on the given ADD message 35496cb8e33SPaul Moore * and add it to the CIPSO V4 engine. Return zero on success and non-zero on 35596cb8e33SPaul Moore * error. 35696cb8e33SPaul Moore * 35796cb8e33SPaul Moore */ 358fd385855SPaul Moore static int netlbl_cipsov4_add_pass(struct genl_info *info) 35996cb8e33SPaul Moore { 360fd385855SPaul Moore int ret_val; 36196cb8e33SPaul Moore struct cipso_v4_doi *doi_def = NULL; 36296cb8e33SPaul Moore 36332f50cdeSPaul Moore if (!info->attrs[NLBL_CIPSOV4_A_TAGLST]) 364fd385855SPaul Moore return -EINVAL; 36596cb8e33SPaul Moore 36696cb8e33SPaul Moore doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL); 367fd385855SPaul Moore if (doi_def == NULL) 368fd385855SPaul Moore return -ENOMEM; 36996cb8e33SPaul Moore doi_def->type = CIPSO_V4_MAP_PASS; 37096cb8e33SPaul Moore 371fd385855SPaul Moore ret_val = netlbl_cipsov4_add_common(info, doi_def); 372fd385855SPaul Moore if (ret_val != 0) 37396cb8e33SPaul Moore goto add_pass_failure; 37496cb8e33SPaul Moore 37596cb8e33SPaul Moore ret_val = cipso_v4_doi_add(doi_def); 37696cb8e33SPaul Moore if (ret_val != 0) 37796cb8e33SPaul Moore goto add_pass_failure; 37896cb8e33SPaul Moore return 0; 37996cb8e33SPaul Moore 38096cb8e33SPaul Moore add_pass_failure: 38196cb8e33SPaul Moore netlbl_cipsov4_doi_free(&doi_def->rcu); 38296cb8e33SPaul Moore return ret_val; 38396cb8e33SPaul Moore } 38496cb8e33SPaul Moore 38596cb8e33SPaul Moore /** 38696cb8e33SPaul Moore * netlbl_cipsov4_add - Handle an ADD message 38796cb8e33SPaul Moore * @skb: the NETLINK buffer 38896cb8e33SPaul Moore * @info: the Generic NETLINK info block 38996cb8e33SPaul Moore * 39096cb8e33SPaul Moore * Description: 39196cb8e33SPaul Moore * Create a new DOI definition based on the given ADD message and add it to the 39296cb8e33SPaul Moore * CIPSO V4 engine. Returns zero on success, negative values on failure. 39396cb8e33SPaul Moore * 39496cb8e33SPaul Moore */ 39596cb8e33SPaul Moore static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info) 39696cb8e33SPaul Moore 39796cb8e33SPaul Moore { 39896cb8e33SPaul Moore int ret_val = -EINVAL; 39932f50cdeSPaul Moore u32 type; 40032f50cdeSPaul Moore u32 doi; 40132f50cdeSPaul Moore const char *type_str = "(unknown)"; 40232f50cdeSPaul Moore struct audit_buffer *audit_buf; 40395d4e6beSPaul Moore struct netlbl_audit audit_info; 40496cb8e33SPaul Moore 40532f50cdeSPaul Moore if (!info->attrs[NLBL_CIPSOV4_A_DOI] || 40632f50cdeSPaul Moore !info->attrs[NLBL_CIPSOV4_A_MTYPE]) 407fd385855SPaul Moore return -EINVAL; 40896cb8e33SPaul Moore 40995d4e6beSPaul Moore doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]); 41095d4e6beSPaul Moore netlbl_netlink_auditinfo(skb, &audit_info); 41195d4e6beSPaul Moore 41232f50cdeSPaul Moore type = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_MTYPE]); 41332f50cdeSPaul Moore switch (type) { 41496cb8e33SPaul Moore case CIPSO_V4_MAP_STD: 41532f50cdeSPaul Moore type_str = "std"; 416fd385855SPaul Moore ret_val = netlbl_cipsov4_add_std(info); 41796cb8e33SPaul Moore break; 41896cb8e33SPaul Moore case CIPSO_V4_MAP_PASS: 41932f50cdeSPaul Moore type_str = "pass"; 420fd385855SPaul Moore ret_val = netlbl_cipsov4_add_pass(info); 42196cb8e33SPaul Moore break; 42296cb8e33SPaul Moore } 42323bcdc1aSPaul Moore if (ret_val == 0) 42423bcdc1aSPaul Moore netlbl_mgmt_protocount_inc(); 42596cb8e33SPaul Moore 42632f50cdeSPaul Moore audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_ADD, 42795d4e6beSPaul Moore &audit_info); 428de64688fSPaul Moore if (audit_buf != NULL) { 42995d4e6beSPaul Moore audit_log_format(audit_buf, 43095d4e6beSPaul Moore " cipso_doi=%u cipso_type=%s res=%u", 43195d4e6beSPaul Moore doi, 43295d4e6beSPaul Moore type_str, 43395d4e6beSPaul Moore ret_val == 0 ? 1 : 0); 43432f50cdeSPaul Moore audit_log_end(audit_buf); 435de64688fSPaul Moore } 43632f50cdeSPaul 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; 493fd385855SPaul Moore goto list_failure; 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) { 518fd385855SPaul Moore case CIPSO_V4_MAP_STD: 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); 586fd385855SPaul Moore 58781878d27SThomas Graf ret_val = genlmsg_reply(ans_skb, info); 58896cb8e33SPaul Moore if (ret_val != 0) 58996cb8e33SPaul Moore goto list_failure; 59096cb8e33SPaul Moore 59196cb8e33SPaul Moore return 0; 59296cb8e33SPaul Moore 593fd385855SPaul Moore list_retry: 594fd385855SPaul Moore /* XXX - this limit is a guesstimate */ 595fd385855SPaul Moore if (nlsze_mult < 4) { 596fd385855SPaul Moore rcu_read_unlock(); 597fd385855SPaul Moore kfree_skb(ans_skb); 598fd385855SPaul Moore nlsze_mult++; 599fd385855SPaul Moore goto list_start; 600fd385855SPaul Moore } 601fd385855SPaul Moore list_failure_lock: 602fd385855SPaul Moore rcu_read_unlock(); 60396cb8e33SPaul Moore list_failure: 604fd385855SPaul Moore kfree_skb(ans_skb); 605fd385855SPaul Moore return ret_val; 606fd385855SPaul Moore } 607fd385855SPaul Moore 608fd385855SPaul Moore /** 609fd385855SPaul Moore * netlbl_cipsov4_listall_cb - cipso_v4_doi_walk() callback for LISTALL 610fd385855SPaul Moore * @doi_def: the CIPSOv4 DOI definition 611fd385855SPaul Moore * @arg: the netlbl_cipsov4_doiwalk_arg structure 612fd385855SPaul Moore * 613fd385855SPaul Moore * Description: 614fd385855SPaul Moore * This function is designed to be used as a callback to the 615fd385855SPaul Moore * cipso_v4_doi_walk() function for use in generating a response for a LISTALL 616fd385855SPaul Moore * message. Returns the size of the message on success, negative values on 617fd385855SPaul Moore * failure. 618fd385855SPaul Moore * 619fd385855SPaul Moore */ 620fd385855SPaul Moore static int netlbl_cipsov4_listall_cb(struct cipso_v4_doi *doi_def, void *arg) 621fd385855SPaul Moore { 622fd385855SPaul Moore int ret_val = -ENOMEM; 623fd385855SPaul Moore struct netlbl_cipsov4_doiwalk_arg *cb_arg = arg; 624fd385855SPaul Moore void *data; 625fd385855SPaul Moore 62617c157c8SThomas Graf data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).pid, 62717c157c8SThomas Graf cb_arg->seq, &netlbl_cipsov4_gnl_family, 62817c157c8SThomas Graf NLM_F_MULTI, NLBL_CIPSOV4_C_LISTALL); 629fd385855SPaul Moore if (data == NULL) 630fd385855SPaul Moore goto listall_cb_failure; 631fd385855SPaul Moore 632fd385855SPaul Moore ret_val = nla_put_u32(cb_arg->skb, NLBL_CIPSOV4_A_DOI, doi_def->doi); 633fd385855SPaul Moore if (ret_val != 0) 634fd385855SPaul Moore goto listall_cb_failure; 635fd385855SPaul Moore ret_val = nla_put_u32(cb_arg->skb, 636fd385855SPaul Moore NLBL_CIPSOV4_A_MTYPE, 637fd385855SPaul Moore doi_def->type); 638fd385855SPaul Moore if (ret_val != 0) 639fd385855SPaul Moore goto listall_cb_failure; 640fd385855SPaul Moore 641fd385855SPaul Moore return genlmsg_end(cb_arg->skb, data); 642fd385855SPaul Moore 643fd385855SPaul Moore listall_cb_failure: 644fd385855SPaul Moore genlmsg_cancel(cb_arg->skb, data); 64596cb8e33SPaul Moore return ret_val; 64696cb8e33SPaul Moore } 64796cb8e33SPaul Moore 64896cb8e33SPaul Moore /** 64996cb8e33SPaul Moore * netlbl_cipsov4_listall - Handle a LISTALL message 65096cb8e33SPaul Moore * @skb: the NETLINK buffer 651fd385855SPaul Moore * @cb: the NETLINK callback 65296cb8e33SPaul Moore * 65396cb8e33SPaul Moore * Description: 65496cb8e33SPaul Moore * Process a user generated LISTALL message and respond accordingly. Returns 65596cb8e33SPaul Moore * zero on success and negative values on error. 65696cb8e33SPaul Moore * 65796cb8e33SPaul Moore */ 658fd385855SPaul Moore static int netlbl_cipsov4_listall(struct sk_buff *skb, 659fd385855SPaul Moore struct netlink_callback *cb) 66096cb8e33SPaul Moore { 661fd385855SPaul Moore struct netlbl_cipsov4_doiwalk_arg cb_arg; 662fd385855SPaul Moore int doi_skip = cb->args[0]; 66396cb8e33SPaul Moore 664fd385855SPaul Moore cb_arg.nl_cb = cb; 665fd385855SPaul Moore cb_arg.skb = skb; 666fd385855SPaul Moore cb_arg.seq = cb->nlh->nlmsg_seq; 66796cb8e33SPaul Moore 668fd385855SPaul Moore cipso_v4_doi_walk(&doi_skip, netlbl_cipsov4_listall_cb, &cb_arg); 66996cb8e33SPaul Moore 670fd385855SPaul Moore cb->args[0] = doi_skip; 671fd385855SPaul Moore return skb->len; 67296cb8e33SPaul Moore } 67396cb8e33SPaul Moore 67496cb8e33SPaul Moore /** 67596cb8e33SPaul Moore * netlbl_cipsov4_remove - Handle a REMOVE message 67696cb8e33SPaul Moore * @skb: the NETLINK buffer 67796cb8e33SPaul Moore * @info: the Generic NETLINK info block 67896cb8e33SPaul Moore * 67996cb8e33SPaul Moore * Description: 68096cb8e33SPaul Moore * Process a user generated REMOVE message and respond accordingly. Returns 68196cb8e33SPaul Moore * zero on success, negative values on failure. 68296cb8e33SPaul Moore * 68396cb8e33SPaul Moore */ 68496cb8e33SPaul Moore static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info) 68596cb8e33SPaul Moore { 686fd385855SPaul Moore int ret_val = -EINVAL; 68732f50cdeSPaul Moore u32 doi = 0; 68832f50cdeSPaul Moore struct audit_buffer *audit_buf; 68995d4e6beSPaul Moore struct netlbl_audit audit_info; 69096cb8e33SPaul Moore 69195d4e6beSPaul Moore if (!info->attrs[NLBL_CIPSOV4_A_DOI]) 69295d4e6beSPaul Moore return -EINVAL; 69395d4e6beSPaul Moore 694fd385855SPaul Moore doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]); 69595d4e6beSPaul Moore netlbl_netlink_auditinfo(skb, &audit_info); 69632f50cdeSPaul Moore 69795d4e6beSPaul Moore ret_val = cipso_v4_doi_remove(doi, 69895d4e6beSPaul Moore &audit_info, 69995d4e6beSPaul Moore netlbl_cipsov4_doi_free); 70023bcdc1aSPaul Moore if (ret_val == 0) 70123bcdc1aSPaul Moore netlbl_mgmt_protocount_dec(); 70295d4e6beSPaul Moore 70332f50cdeSPaul Moore audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_DEL, 70495d4e6beSPaul Moore &audit_info); 705de64688fSPaul Moore if (audit_buf != NULL) { 70695d4e6beSPaul Moore audit_log_format(audit_buf, 70795d4e6beSPaul Moore " cipso_doi=%u res=%u", 70895d4e6beSPaul Moore doi, 70995d4e6beSPaul Moore ret_val == 0 ? 1 : 0); 71032f50cdeSPaul Moore audit_log_end(audit_buf); 711de64688fSPaul Moore } 71296cb8e33SPaul Moore 71396cb8e33SPaul Moore return ret_val; 71496cb8e33SPaul Moore } 71596cb8e33SPaul Moore 71696cb8e33SPaul Moore /* 71796cb8e33SPaul Moore * NetLabel Generic NETLINK Command Definitions 71896cb8e33SPaul Moore */ 71996cb8e33SPaul Moore 72096cb8e33SPaul Moore static struct genl_ops netlbl_cipsov4_genl_c_add = { 72196cb8e33SPaul Moore .cmd = NLBL_CIPSOV4_C_ADD, 722fd385855SPaul Moore .flags = GENL_ADMIN_PERM, 723fd385855SPaul Moore .policy = netlbl_cipsov4_genl_policy, 72496cb8e33SPaul Moore .doit = netlbl_cipsov4_add, 72596cb8e33SPaul Moore .dumpit = NULL, 72696cb8e33SPaul Moore }; 72796cb8e33SPaul Moore 72896cb8e33SPaul Moore static struct genl_ops netlbl_cipsov4_genl_c_remove = { 72996cb8e33SPaul Moore .cmd = NLBL_CIPSOV4_C_REMOVE, 730fd385855SPaul Moore .flags = GENL_ADMIN_PERM, 731fd385855SPaul Moore .policy = netlbl_cipsov4_genl_policy, 73296cb8e33SPaul Moore .doit = netlbl_cipsov4_remove, 73396cb8e33SPaul Moore .dumpit = NULL, 73496cb8e33SPaul Moore }; 73596cb8e33SPaul Moore 73696cb8e33SPaul Moore static struct genl_ops netlbl_cipsov4_genl_c_list = { 73796cb8e33SPaul Moore .cmd = NLBL_CIPSOV4_C_LIST, 73896cb8e33SPaul Moore .flags = 0, 739fd385855SPaul Moore .policy = netlbl_cipsov4_genl_policy, 74096cb8e33SPaul Moore .doit = netlbl_cipsov4_list, 74196cb8e33SPaul Moore .dumpit = NULL, 74296cb8e33SPaul Moore }; 74396cb8e33SPaul Moore 74496cb8e33SPaul Moore static struct genl_ops netlbl_cipsov4_genl_c_listall = { 74596cb8e33SPaul Moore .cmd = NLBL_CIPSOV4_C_LISTALL, 74696cb8e33SPaul Moore .flags = 0, 747fd385855SPaul Moore .policy = netlbl_cipsov4_genl_policy, 748fd385855SPaul Moore .doit = NULL, 749fd385855SPaul Moore .dumpit = netlbl_cipsov4_listall, 75096cb8e33SPaul Moore }; 75196cb8e33SPaul Moore 75296cb8e33SPaul Moore /* 75396cb8e33SPaul Moore * NetLabel Generic NETLINK Protocol Functions 75496cb8e33SPaul Moore */ 75596cb8e33SPaul Moore 75696cb8e33SPaul Moore /** 75796cb8e33SPaul Moore * netlbl_cipsov4_genl_init - Register the CIPSOv4 NetLabel component 75896cb8e33SPaul Moore * 75996cb8e33SPaul Moore * Description: 76096cb8e33SPaul Moore * Register the CIPSOv4 packet NetLabel component with the Generic NETLINK 76196cb8e33SPaul Moore * mechanism. Returns zero on success, negative values on failure. 76296cb8e33SPaul Moore * 76396cb8e33SPaul Moore */ 76496cb8e33SPaul Moore int netlbl_cipsov4_genl_init(void) 76596cb8e33SPaul Moore { 76696cb8e33SPaul Moore int ret_val; 76796cb8e33SPaul Moore 76896cb8e33SPaul Moore ret_val = genl_register_family(&netlbl_cipsov4_gnl_family); 76996cb8e33SPaul Moore if (ret_val != 0) 77096cb8e33SPaul Moore return ret_val; 77196cb8e33SPaul Moore 77296cb8e33SPaul Moore ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family, 77396cb8e33SPaul Moore &netlbl_cipsov4_genl_c_add); 77496cb8e33SPaul Moore if (ret_val != 0) 77596cb8e33SPaul Moore return ret_val; 77696cb8e33SPaul Moore ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family, 77796cb8e33SPaul Moore &netlbl_cipsov4_genl_c_remove); 77896cb8e33SPaul Moore if (ret_val != 0) 77996cb8e33SPaul Moore return ret_val; 78096cb8e33SPaul Moore ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family, 78196cb8e33SPaul Moore &netlbl_cipsov4_genl_c_list); 78296cb8e33SPaul Moore if (ret_val != 0) 78396cb8e33SPaul Moore return ret_val; 78496cb8e33SPaul Moore ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family, 78596cb8e33SPaul Moore &netlbl_cipsov4_genl_c_listall); 78696cb8e33SPaul Moore if (ret_val != 0) 78796cb8e33SPaul Moore return ret_val; 78896cb8e33SPaul Moore 78996cb8e33SPaul Moore return 0; 79096cb8e33SPaul Moore } 791