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> 3596cb8e33SPaul Moore #include <net/sock.h> 3696cb8e33SPaul Moore #include <net/netlink.h> 3796cb8e33SPaul Moore #include <net/genetlink.h> 3896cb8e33SPaul Moore #include <net/netlabel.h> 3996cb8e33SPaul Moore #include <net/cipso_ipv4.h> 4096cb8e33SPaul Moore 4196cb8e33SPaul Moore #include "netlabel_user.h" 4296cb8e33SPaul Moore #include "netlabel_cipso_v4.h" 4396cb8e33SPaul Moore 44*fd385855SPaul Moore /* Argument struct for cipso_v4_doi_walk() */ 45*fd385855SPaul Moore struct netlbl_cipsov4_doiwalk_arg { 46*fd385855SPaul Moore struct netlink_callback *nl_cb; 47*fd385855SPaul Moore struct sk_buff *skb; 48*fd385855SPaul Moore u32 seq; 49*fd385855SPaul Moore }; 50*fd385855SPaul Moore 5196cb8e33SPaul Moore /* NetLabel Generic NETLINK CIPSOv4 family */ 5296cb8e33SPaul Moore static struct genl_family netlbl_cipsov4_gnl_family = { 5396cb8e33SPaul Moore .id = GENL_ID_GENERATE, 5496cb8e33SPaul Moore .hdrsize = 0, 5596cb8e33SPaul Moore .name = NETLBL_NLTYPE_CIPSOV4_NAME, 5696cb8e33SPaul Moore .version = NETLBL_PROTO_VERSION, 57*fd385855SPaul Moore .maxattr = NLBL_CIPSOV4_A_MAX, 5896cb8e33SPaul Moore }; 5996cb8e33SPaul Moore 60*fd385855SPaul Moore /* NetLabel Netlink attribute policy */ 61*fd385855SPaul Moore static struct nla_policy netlbl_cipsov4_genl_policy[NLBL_CIPSOV4_A_MAX + 1] = { 62*fd385855SPaul Moore [NLBL_CIPSOV4_A_DOI] = { .type = NLA_U32 }, 63*fd385855SPaul Moore [NLBL_CIPSOV4_A_MTYPE] = { .type = NLA_U32 }, 64*fd385855SPaul Moore [NLBL_CIPSOV4_A_TAG] = { .type = NLA_U8 }, 65*fd385855SPaul Moore [NLBL_CIPSOV4_A_TAGLST] = { .type = NLA_NESTED }, 66*fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSLVLLOC] = { .type = NLA_U32 }, 67*fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSLVLREM] = { .type = NLA_U32 }, 68*fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSLVL] = { .type = NLA_NESTED }, 69*fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSLVLLST] = { .type = NLA_NESTED }, 70*fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSCATLOC] = { .type = NLA_U32 }, 71*fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSCATREM] = { .type = NLA_U32 }, 72*fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSCAT] = { .type = NLA_NESTED }, 73*fd385855SPaul Moore [NLBL_CIPSOV4_A_MLSCATLST] = { .type = NLA_NESTED }, 74*fd385855SPaul Moore }; 7596cb8e33SPaul Moore 7696cb8e33SPaul Moore /* 7796cb8e33SPaul Moore * Helper Functions 7896cb8e33SPaul Moore */ 7996cb8e33SPaul Moore 8096cb8e33SPaul Moore /** 8196cb8e33SPaul Moore * netlbl_cipsov4_doi_free - Frees a CIPSO V4 DOI definition 8296cb8e33SPaul Moore * @entry: the entry's RCU field 8396cb8e33SPaul Moore * 8496cb8e33SPaul Moore * Description: 8596cb8e33SPaul Moore * This function is designed to be used as a callback to the call_rcu() 8696cb8e33SPaul Moore * function so that the memory allocated to the DOI definition can be released 8796cb8e33SPaul Moore * safely. 8896cb8e33SPaul Moore * 8996cb8e33SPaul Moore */ 9096cb8e33SPaul Moore static void netlbl_cipsov4_doi_free(struct rcu_head *entry) 9196cb8e33SPaul Moore { 9296cb8e33SPaul Moore struct cipso_v4_doi *ptr; 9396cb8e33SPaul Moore 9496cb8e33SPaul Moore ptr = container_of(entry, struct cipso_v4_doi, rcu); 9596cb8e33SPaul Moore switch (ptr->type) { 9696cb8e33SPaul Moore case CIPSO_V4_MAP_STD: 9796cb8e33SPaul Moore kfree(ptr->map.std->lvl.cipso); 9896cb8e33SPaul Moore kfree(ptr->map.std->lvl.local); 9996cb8e33SPaul Moore kfree(ptr->map.std->cat.cipso); 10096cb8e33SPaul Moore kfree(ptr->map.std->cat.local); 10196cb8e33SPaul Moore break; 10296cb8e33SPaul Moore } 10396cb8e33SPaul Moore kfree(ptr); 10496cb8e33SPaul Moore } 10596cb8e33SPaul Moore 106*fd385855SPaul Moore /** 107*fd385855SPaul Moore * netlbl_cipsov4_add_common - Parse the common sections of a ADD message 108*fd385855SPaul Moore * @info: the Generic NETLINK info block 109*fd385855SPaul Moore * @doi_def: the CIPSO V4 DOI definition 110*fd385855SPaul Moore * 111*fd385855SPaul Moore * Description: 112*fd385855SPaul Moore * Parse the common sections of a ADD message and fill in the related values 113*fd385855SPaul Moore * in @doi_def. Returns zero on success, negative values on failure. 114*fd385855SPaul Moore * 115*fd385855SPaul Moore */ 116*fd385855SPaul Moore static int netlbl_cipsov4_add_common(struct genl_info *info, 117*fd385855SPaul Moore struct cipso_v4_doi *doi_def) 118*fd385855SPaul Moore { 119*fd385855SPaul Moore struct nlattr *nla; 120*fd385855SPaul Moore int nla_rem; 121*fd385855SPaul Moore u32 iter = 0; 122*fd385855SPaul Moore 123*fd385855SPaul Moore doi_def->doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]); 124*fd385855SPaul Moore 125*fd385855SPaul Moore if (nla_validate_nested(info->attrs[NLBL_CIPSOV4_A_TAGLST], 126*fd385855SPaul Moore NLBL_CIPSOV4_A_MAX, 127*fd385855SPaul Moore netlbl_cipsov4_genl_policy) != 0) 128*fd385855SPaul Moore return -EINVAL; 129*fd385855SPaul Moore 130*fd385855SPaul Moore nla_for_each_nested(nla, info->attrs[NLBL_CIPSOV4_A_TAGLST], nla_rem) 131*fd385855SPaul Moore if (nla->nla_type == NLBL_CIPSOV4_A_TAG) { 132*fd385855SPaul Moore if (iter > CIPSO_V4_TAG_MAXCNT) 133*fd385855SPaul Moore return -EINVAL; 134*fd385855SPaul Moore doi_def->tags[iter++] = nla_get_u8(nla); 135*fd385855SPaul Moore } 136*fd385855SPaul Moore if (iter < CIPSO_V4_TAG_MAXCNT) 137*fd385855SPaul Moore doi_def->tags[iter] = CIPSO_V4_TAG_INVALID; 138*fd385855SPaul Moore 139*fd385855SPaul Moore return 0; 140*fd385855SPaul Moore } 14196cb8e33SPaul Moore 14296cb8e33SPaul Moore /* 14396cb8e33SPaul Moore * NetLabel Command Handlers 14496cb8e33SPaul Moore */ 14596cb8e33SPaul Moore 14696cb8e33SPaul Moore /** 14796cb8e33SPaul Moore * netlbl_cipsov4_add_std - Adds a CIPSO V4 DOI definition 148*fd385855SPaul Moore * @info: the Generic NETLINK info block 14996cb8e33SPaul Moore * 15096cb8e33SPaul Moore * Description: 15196cb8e33SPaul Moore * Create a new CIPSO_V4_MAP_STD DOI definition based on the given ADD message 15296cb8e33SPaul Moore * and add it to the CIPSO V4 engine. Return zero on success and non-zero on 15396cb8e33SPaul Moore * error. 15496cb8e33SPaul Moore * 15596cb8e33SPaul Moore */ 156*fd385855SPaul Moore static int netlbl_cipsov4_add_std(struct genl_info *info) 15796cb8e33SPaul Moore { 15896cb8e33SPaul Moore int ret_val = -EINVAL; 15996cb8e33SPaul Moore struct cipso_v4_doi *doi_def = NULL; 160*fd385855SPaul Moore struct nlattr *nla_a; 161*fd385855SPaul Moore struct nlattr *nla_b; 162*fd385855SPaul Moore int nla_a_rem; 163*fd385855SPaul Moore int nla_b_rem; 16496cb8e33SPaul Moore 165*fd385855SPaul Moore if (!info->attrs[NLBL_CIPSOV4_A_DOI] || 166*fd385855SPaul Moore !info->attrs[NLBL_CIPSOV4_A_TAGLST] || 167*fd385855SPaul Moore !info->attrs[NLBL_CIPSOV4_A_MLSLVLLST]) 168*fd385855SPaul Moore return -EINVAL; 169*fd385855SPaul Moore 170*fd385855SPaul Moore if (nla_validate_nested(info->attrs[NLBL_CIPSOV4_A_MLSLVLLST], 171*fd385855SPaul Moore NLBL_CIPSOV4_A_MAX, 172*fd385855SPaul Moore netlbl_cipsov4_genl_policy) != 0) 173*fd385855SPaul Moore return -EINVAL; 17496cb8e33SPaul Moore 17596cb8e33SPaul Moore doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL); 176*fd385855SPaul Moore if (doi_def == NULL) 177*fd385855SPaul Moore return -ENOMEM; 17896cb8e33SPaul Moore doi_def->map.std = kzalloc(sizeof(*doi_def->map.std), GFP_KERNEL); 17996cb8e33SPaul Moore if (doi_def->map.std == NULL) { 18096cb8e33SPaul Moore ret_val = -ENOMEM; 18196cb8e33SPaul Moore goto add_std_failure; 18296cb8e33SPaul Moore } 18396cb8e33SPaul Moore doi_def->type = CIPSO_V4_MAP_STD; 18496cb8e33SPaul Moore 185*fd385855SPaul Moore ret_val = netlbl_cipsov4_add_common(info, doi_def); 186*fd385855SPaul Moore if (ret_val != 0) 18796cb8e33SPaul Moore goto add_std_failure; 188*fd385855SPaul Moore 189*fd385855SPaul Moore nla_for_each_nested(nla_a, 190*fd385855SPaul Moore info->attrs[NLBL_CIPSOV4_A_MLSLVLLST], 191*fd385855SPaul Moore nla_a_rem) 192*fd385855SPaul Moore if (nla_a->nla_type == NLBL_CIPSOV4_A_MLSLVL) { 193*fd385855SPaul Moore nla_for_each_nested(nla_b, nla_a, nla_b_rem) 194*fd385855SPaul Moore switch (nla_b->nla_type) { 195*fd385855SPaul Moore case NLBL_CIPSOV4_A_MLSLVLLOC: 196*fd385855SPaul Moore if (nla_get_u32(nla_b) >= 197*fd385855SPaul Moore doi_def->map.std->lvl.local_size) 198*fd385855SPaul Moore doi_def->map.std->lvl.local_size = 199*fd385855SPaul Moore nla_get_u32(nla_b) + 1; 20096cb8e33SPaul Moore break; 201*fd385855SPaul Moore case NLBL_CIPSOV4_A_MLSLVLREM: 202*fd385855SPaul Moore if (nla_get_u32(nla_b) >= 203*fd385855SPaul Moore doi_def->map.std->lvl.cipso_size) 204*fd385855SPaul Moore doi_def->map.std->lvl.cipso_size = 205*fd385855SPaul Moore nla_get_u32(nla_b) + 1; 206*fd385855SPaul Moore break; 20796cb8e33SPaul Moore } 20896cb8e33SPaul Moore } 209*fd385855SPaul Moore if (doi_def->map.std->lvl.local_size > CIPSO_V4_MAX_LOC_LVLS || 210*fd385855SPaul Moore doi_def->map.std->lvl.cipso_size > CIPSO_V4_MAX_REM_LVLS) 21196cb8e33SPaul Moore goto add_std_failure; 21296cb8e33SPaul Moore doi_def->map.std->lvl.local = kcalloc(doi_def->map.std->lvl.local_size, 21396cb8e33SPaul Moore sizeof(u32), 21496cb8e33SPaul Moore GFP_KERNEL); 21596cb8e33SPaul Moore if (doi_def->map.std->lvl.local == NULL) { 21696cb8e33SPaul Moore ret_val = -ENOMEM; 21796cb8e33SPaul Moore goto add_std_failure; 21896cb8e33SPaul Moore } 21996cb8e33SPaul Moore doi_def->map.std->lvl.cipso = kcalloc(doi_def->map.std->lvl.cipso_size, 22096cb8e33SPaul Moore sizeof(u32), 22196cb8e33SPaul Moore GFP_KERNEL); 22296cb8e33SPaul Moore if (doi_def->map.std->lvl.cipso == NULL) { 22396cb8e33SPaul Moore ret_val = -ENOMEM; 22496cb8e33SPaul Moore goto add_std_failure; 22596cb8e33SPaul Moore } 226*fd385855SPaul Moore nla_for_each_nested(nla_a, 227*fd385855SPaul Moore info->attrs[NLBL_CIPSOV4_A_MLSLVLLST], 228*fd385855SPaul Moore nla_a_rem) 229*fd385855SPaul Moore if (nla_a->nla_type == NLBL_CIPSOV4_A_MLSLVL) { 230*fd385855SPaul Moore struct nlattr *lvl_loc; 231*fd385855SPaul Moore struct nlattr *lvl_rem; 23296cb8e33SPaul Moore 233*fd385855SPaul Moore if (nla_validate_nested(nla_a, 234*fd385855SPaul Moore NLBL_CIPSOV4_A_MAX, 235*fd385855SPaul Moore netlbl_cipsov4_genl_policy) != 0) 23696cb8e33SPaul Moore goto add_std_failure; 237*fd385855SPaul Moore 238*fd385855SPaul Moore lvl_loc = nla_find_nested(nla_a, 239*fd385855SPaul Moore NLBL_CIPSOV4_A_MLSLVLLOC); 240*fd385855SPaul Moore lvl_rem = nla_find_nested(nla_a, 241*fd385855SPaul Moore NLBL_CIPSOV4_A_MLSLVLREM); 242*fd385855SPaul Moore if (lvl_loc == NULL || lvl_rem == NULL) 243*fd385855SPaul Moore goto add_std_failure; 244*fd385855SPaul Moore doi_def->map.std->lvl.local[nla_get_u32(lvl_loc)] = 245*fd385855SPaul Moore nla_get_u32(lvl_rem); 246*fd385855SPaul Moore doi_def->map.std->lvl.cipso[nla_get_u32(lvl_rem)] = 247*fd385855SPaul Moore nla_get_u32(lvl_loc); 248*fd385855SPaul Moore } 249*fd385855SPaul Moore 250*fd385855SPaul Moore if (info->attrs[NLBL_CIPSOV4_A_MLSCATLST]) { 251*fd385855SPaul Moore if (nla_validate_nested(info->attrs[NLBL_CIPSOV4_A_MLSCATLST], 252*fd385855SPaul Moore NLBL_CIPSOV4_A_MAX, 253*fd385855SPaul Moore netlbl_cipsov4_genl_policy) != 0) 254*fd385855SPaul Moore goto add_std_failure; 255*fd385855SPaul Moore 256*fd385855SPaul Moore nla_for_each_nested(nla_a, 257*fd385855SPaul Moore info->attrs[NLBL_CIPSOV4_A_MLSCATLST], 258*fd385855SPaul Moore nla_a_rem) 259*fd385855SPaul Moore if (nla_a->nla_type == NLBL_CIPSOV4_A_MLSCAT) { 260*fd385855SPaul Moore if (nla_validate_nested(nla_a, 261*fd385855SPaul Moore NLBL_CIPSOV4_A_MAX, 262*fd385855SPaul Moore netlbl_cipsov4_genl_policy) != 0) 263*fd385855SPaul Moore goto add_std_failure; 264*fd385855SPaul Moore nla_for_each_nested(nla_b, nla_a, nla_b_rem) 265*fd385855SPaul Moore switch (nla_b->nla_type) { 266*fd385855SPaul Moore case NLBL_CIPSOV4_A_MLSCATLOC: 267*fd385855SPaul Moore if (nla_get_u32(nla_b) >= 268*fd385855SPaul Moore doi_def->map.std->cat.local_size) 269*fd385855SPaul Moore doi_def->map.std->cat.local_size = 270*fd385855SPaul Moore nla_get_u32(nla_b) + 1; 271*fd385855SPaul Moore break; 272*fd385855SPaul Moore case NLBL_CIPSOV4_A_MLSCATREM: 273*fd385855SPaul Moore if (nla_get_u32(nla_b) >= 274*fd385855SPaul Moore doi_def->map.std->cat.cipso_size) 275*fd385855SPaul Moore doi_def->map.std->cat.cipso_size = 276*fd385855SPaul Moore nla_get_u32(nla_b) + 1; 277*fd385855SPaul Moore break; 278*fd385855SPaul Moore } 279*fd385855SPaul Moore } 280*fd385855SPaul Moore if (doi_def->map.std->cat.local_size > CIPSO_V4_MAX_LOC_CATS || 281*fd385855SPaul Moore doi_def->map.std->cat.cipso_size > CIPSO_V4_MAX_REM_CATS) 282*fd385855SPaul Moore goto add_std_failure; 283*fd385855SPaul Moore doi_def->map.std->cat.local = kcalloc( 284*fd385855SPaul Moore doi_def->map.std->cat.local_size, 28596cb8e33SPaul Moore sizeof(u32), 28696cb8e33SPaul Moore GFP_KERNEL); 28796cb8e33SPaul Moore if (doi_def->map.std->cat.local == NULL) { 28896cb8e33SPaul Moore ret_val = -ENOMEM; 28996cb8e33SPaul Moore goto add_std_failure; 29096cb8e33SPaul Moore } 291*fd385855SPaul Moore doi_def->map.std->cat.cipso = kcalloc( 292*fd385855SPaul Moore doi_def->map.std->cat.cipso_size, 29396cb8e33SPaul Moore sizeof(u32), 29496cb8e33SPaul Moore GFP_KERNEL); 29596cb8e33SPaul Moore if (doi_def->map.std->cat.cipso == NULL) { 29696cb8e33SPaul Moore ret_val = -ENOMEM; 29796cb8e33SPaul Moore goto add_std_failure; 29896cb8e33SPaul Moore } 299*fd385855SPaul Moore nla_for_each_nested(nla_a, 300*fd385855SPaul Moore info->attrs[NLBL_CIPSOV4_A_MLSCATLST], 301*fd385855SPaul Moore nla_a_rem) 302*fd385855SPaul Moore if (nla_a->nla_type == NLBL_CIPSOV4_A_MLSCAT) { 303*fd385855SPaul Moore struct nlattr *cat_loc; 304*fd385855SPaul Moore struct nlattr *cat_rem; 30596cb8e33SPaul Moore 306*fd385855SPaul Moore cat_loc = nla_find_nested(nla_a, 307*fd385855SPaul Moore NLBL_CIPSOV4_A_MLSCATLOC); 308*fd385855SPaul Moore cat_rem = nla_find_nested(nla_a, 309*fd385855SPaul Moore NLBL_CIPSOV4_A_MLSCATREM); 310*fd385855SPaul Moore if (cat_loc == NULL || cat_rem == NULL) 31196cb8e33SPaul Moore goto add_std_failure; 312*fd385855SPaul Moore doi_def->map.std->cat.local[ 313*fd385855SPaul Moore nla_get_u32(cat_loc)] = 314*fd385855SPaul Moore nla_get_u32(cat_rem); 315*fd385855SPaul Moore doi_def->map.std->cat.cipso[ 316*fd385855SPaul Moore nla_get_u32(cat_rem)] = 317*fd385855SPaul Moore nla_get_u32(cat_loc); 318*fd385855SPaul Moore } 31996cb8e33SPaul Moore } 32096cb8e33SPaul Moore 32196cb8e33SPaul Moore ret_val = cipso_v4_doi_add(doi_def); 32296cb8e33SPaul Moore if (ret_val != 0) 32396cb8e33SPaul Moore goto add_std_failure; 32496cb8e33SPaul Moore return 0; 32596cb8e33SPaul Moore 32696cb8e33SPaul Moore add_std_failure: 32796cb8e33SPaul Moore if (doi_def) 32896cb8e33SPaul Moore netlbl_cipsov4_doi_free(&doi_def->rcu); 32996cb8e33SPaul Moore return ret_val; 33096cb8e33SPaul Moore } 33196cb8e33SPaul Moore 33296cb8e33SPaul Moore /** 33396cb8e33SPaul Moore * netlbl_cipsov4_add_pass - Adds a CIPSO V4 DOI definition 334*fd385855SPaul Moore * @info: the Generic NETLINK info block 33596cb8e33SPaul Moore * 33696cb8e33SPaul Moore * Description: 33796cb8e33SPaul Moore * Create a new CIPSO_V4_MAP_PASS DOI definition based on the given ADD message 33896cb8e33SPaul Moore * and add it to the CIPSO V4 engine. Return zero on success and non-zero on 33996cb8e33SPaul Moore * error. 34096cb8e33SPaul Moore * 34196cb8e33SPaul Moore */ 342*fd385855SPaul Moore static int netlbl_cipsov4_add_pass(struct genl_info *info) 34396cb8e33SPaul Moore { 344*fd385855SPaul Moore int ret_val; 34596cb8e33SPaul Moore struct cipso_v4_doi *doi_def = NULL; 34696cb8e33SPaul Moore 347*fd385855SPaul Moore if (!info->attrs[NLBL_CIPSOV4_A_DOI] || 348*fd385855SPaul Moore !info->attrs[NLBL_CIPSOV4_A_TAGLST]) 349*fd385855SPaul Moore return -EINVAL; 35096cb8e33SPaul Moore 35196cb8e33SPaul Moore doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL); 352*fd385855SPaul Moore if (doi_def == NULL) 353*fd385855SPaul Moore return -ENOMEM; 35496cb8e33SPaul Moore doi_def->type = CIPSO_V4_MAP_PASS; 35596cb8e33SPaul Moore 356*fd385855SPaul Moore ret_val = netlbl_cipsov4_add_common(info, doi_def); 357*fd385855SPaul Moore if (ret_val != 0) 35896cb8e33SPaul Moore goto add_pass_failure; 35996cb8e33SPaul Moore 36096cb8e33SPaul Moore ret_val = cipso_v4_doi_add(doi_def); 36196cb8e33SPaul Moore if (ret_val != 0) 36296cb8e33SPaul Moore goto add_pass_failure; 36396cb8e33SPaul Moore return 0; 36496cb8e33SPaul Moore 36596cb8e33SPaul Moore add_pass_failure: 36696cb8e33SPaul Moore netlbl_cipsov4_doi_free(&doi_def->rcu); 36796cb8e33SPaul Moore return ret_val; 36896cb8e33SPaul Moore } 36996cb8e33SPaul Moore 37096cb8e33SPaul Moore /** 37196cb8e33SPaul Moore * netlbl_cipsov4_add - Handle an ADD message 37296cb8e33SPaul Moore * @skb: the NETLINK buffer 37396cb8e33SPaul Moore * @info: the Generic NETLINK info block 37496cb8e33SPaul Moore * 37596cb8e33SPaul Moore * Description: 37696cb8e33SPaul Moore * Create a new DOI definition based on the given ADD message and add it to the 37796cb8e33SPaul Moore * CIPSO V4 engine. Returns zero on success, negative values on failure. 37896cb8e33SPaul Moore * 37996cb8e33SPaul Moore */ 38096cb8e33SPaul Moore static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info) 38196cb8e33SPaul Moore 38296cb8e33SPaul Moore { 38396cb8e33SPaul Moore int ret_val = -EINVAL; 38496cb8e33SPaul Moore u32 map_type; 38596cb8e33SPaul Moore 386*fd385855SPaul Moore if (!info->attrs[NLBL_CIPSOV4_A_MTYPE]) 387*fd385855SPaul Moore return -EINVAL; 38896cb8e33SPaul Moore 389*fd385855SPaul Moore map_type = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_MTYPE]); 39096cb8e33SPaul Moore switch (map_type) { 39196cb8e33SPaul Moore case CIPSO_V4_MAP_STD: 392*fd385855SPaul Moore ret_val = netlbl_cipsov4_add_std(info); 39396cb8e33SPaul Moore break; 39496cb8e33SPaul Moore case CIPSO_V4_MAP_PASS: 395*fd385855SPaul Moore ret_val = netlbl_cipsov4_add_pass(info); 39696cb8e33SPaul Moore break; 39796cb8e33SPaul Moore } 39896cb8e33SPaul Moore 39996cb8e33SPaul Moore return ret_val; 40096cb8e33SPaul Moore } 40196cb8e33SPaul Moore 40296cb8e33SPaul Moore /** 40396cb8e33SPaul Moore * netlbl_cipsov4_list - Handle a LIST message 40496cb8e33SPaul Moore * @skb: the NETLINK buffer 40596cb8e33SPaul Moore * @info: the Generic NETLINK info block 40696cb8e33SPaul Moore * 40796cb8e33SPaul Moore * Description: 408*fd385855SPaul Moore * Process a user generated LIST message and respond accordingly. While the 409*fd385855SPaul Moore * response message generated by the kernel is straightforward, determining 410*fd385855SPaul Moore * before hand the size of the buffer to allocate is not (we have to generate 411*fd385855SPaul Moore * the message to know the size). In order to keep this function sane what we 412*fd385855SPaul Moore * do is allocate a buffer of NLMSG_GOODSIZE and try to fit the response in 413*fd385855SPaul Moore * that size, if we fail then we restart with a larger buffer and try again. 414*fd385855SPaul Moore * We continue in this manner until we hit a limit of failed attempts then we 415*fd385855SPaul Moore * give up and just send an error message. Returns zero on success and 416*fd385855SPaul Moore * negative values on error. 41796cb8e33SPaul Moore * 41896cb8e33SPaul Moore */ 41996cb8e33SPaul Moore static int netlbl_cipsov4_list(struct sk_buff *skb, struct genl_info *info) 42096cb8e33SPaul Moore { 421*fd385855SPaul Moore int ret_val; 422*fd385855SPaul Moore struct sk_buff *ans_skb = NULL; 423*fd385855SPaul Moore u32 nlsze_mult = 1; 424*fd385855SPaul Moore void *data; 42596cb8e33SPaul Moore u32 doi; 426*fd385855SPaul Moore struct nlattr *nla_a; 427*fd385855SPaul Moore struct nlattr *nla_b; 428*fd385855SPaul Moore struct cipso_v4_doi *doi_def; 429*fd385855SPaul Moore u32 iter; 43096cb8e33SPaul Moore 431*fd385855SPaul Moore if (!info->attrs[NLBL_CIPSOV4_A_DOI]) { 432*fd385855SPaul Moore ret_val = -EINVAL; 43396cb8e33SPaul Moore goto list_failure; 434*fd385855SPaul Moore } 43596cb8e33SPaul Moore 436*fd385855SPaul Moore list_start: 437*fd385855SPaul Moore ans_skb = nlmsg_new(NLMSG_GOODSIZE * nlsze_mult, GFP_KERNEL); 43896cb8e33SPaul Moore if (ans_skb == NULL) { 43996cb8e33SPaul Moore ret_val = -ENOMEM; 44096cb8e33SPaul Moore goto list_failure; 44196cb8e33SPaul Moore } 442*fd385855SPaul Moore data = netlbl_netlink_hdr_put(ans_skb, 44396cb8e33SPaul Moore info->snd_pid, 444*fd385855SPaul Moore info->snd_seq, 44596cb8e33SPaul Moore netlbl_cipsov4_gnl_family.id, 446*fd385855SPaul Moore 0, 44796cb8e33SPaul Moore NLBL_CIPSOV4_C_LIST); 448*fd385855SPaul Moore if (data == NULL) { 449*fd385855SPaul Moore ret_val = -ENOMEM; 450*fd385855SPaul Moore goto list_failure; 451*fd385855SPaul Moore } 45296cb8e33SPaul Moore 453*fd385855SPaul Moore doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]); 454*fd385855SPaul Moore 455*fd385855SPaul Moore rcu_read_lock(); 456*fd385855SPaul Moore doi_def = cipso_v4_doi_getdef(doi); 457*fd385855SPaul Moore if (doi_def == NULL) { 458*fd385855SPaul Moore ret_val = -EINVAL; 459*fd385855SPaul Moore goto list_failure; 460*fd385855SPaul Moore } 461*fd385855SPaul Moore 462*fd385855SPaul Moore ret_val = nla_put_u32(ans_skb, NLBL_CIPSOV4_A_MTYPE, doi_def->type); 463*fd385855SPaul Moore if (ret_val != 0) 464*fd385855SPaul Moore goto list_failure_lock; 465*fd385855SPaul Moore 466*fd385855SPaul Moore nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_TAGLST); 467*fd385855SPaul Moore if (nla_a == NULL) { 468*fd385855SPaul Moore ret_val = -ENOMEM; 469*fd385855SPaul Moore goto list_failure_lock; 470*fd385855SPaul Moore } 471*fd385855SPaul Moore for (iter = 0; 472*fd385855SPaul Moore iter < CIPSO_V4_TAG_MAXCNT && 473*fd385855SPaul Moore doi_def->tags[iter] != CIPSO_V4_TAG_INVALID; 474*fd385855SPaul Moore iter++) { 475*fd385855SPaul Moore ret_val = nla_put_u8(ans_skb, 476*fd385855SPaul Moore NLBL_CIPSOV4_A_TAG, 477*fd385855SPaul Moore doi_def->tags[iter]); 478*fd385855SPaul Moore if (ret_val != 0) 479*fd385855SPaul Moore goto list_failure_lock; 480*fd385855SPaul Moore } 481*fd385855SPaul Moore nla_nest_end(ans_skb, nla_a); 482*fd385855SPaul Moore 483*fd385855SPaul Moore switch (doi_def->type) { 484*fd385855SPaul Moore case CIPSO_V4_MAP_STD: 485*fd385855SPaul Moore nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSLVLLST); 486*fd385855SPaul Moore if (nla_a == NULL) { 487*fd385855SPaul Moore ret_val = -ENOMEM; 488*fd385855SPaul Moore goto list_failure_lock; 489*fd385855SPaul Moore } 490*fd385855SPaul Moore for (iter = 0; 491*fd385855SPaul Moore iter < doi_def->map.std->lvl.local_size; 492*fd385855SPaul Moore iter++) { 493*fd385855SPaul Moore if (doi_def->map.std->lvl.local[iter] == 494*fd385855SPaul Moore CIPSO_V4_INV_LVL) 495*fd385855SPaul Moore continue; 496*fd385855SPaul Moore 497*fd385855SPaul Moore nla_b = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSLVL); 498*fd385855SPaul Moore if (nla_b == NULL) { 499*fd385855SPaul Moore ret_val = -ENOMEM; 500*fd385855SPaul Moore goto list_retry; 501*fd385855SPaul Moore } 502*fd385855SPaul Moore ret_val = nla_put_u32(ans_skb, 503*fd385855SPaul Moore NLBL_CIPSOV4_A_MLSLVLLOC, 504*fd385855SPaul Moore iter); 505*fd385855SPaul Moore if (ret_val != 0) 506*fd385855SPaul Moore goto list_retry; 507*fd385855SPaul Moore ret_val = nla_put_u32(ans_skb, 508*fd385855SPaul Moore NLBL_CIPSOV4_A_MLSLVLREM, 509*fd385855SPaul Moore doi_def->map.std->lvl.local[iter]); 510*fd385855SPaul Moore if (ret_val != 0) 511*fd385855SPaul Moore goto list_retry; 512*fd385855SPaul Moore nla_nest_end(ans_skb, nla_b); 513*fd385855SPaul Moore } 514*fd385855SPaul Moore nla_nest_end(ans_skb, nla_a); 515*fd385855SPaul Moore 516*fd385855SPaul Moore nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSCATLST); 517*fd385855SPaul Moore if (nla_a == NULL) { 518*fd385855SPaul Moore ret_val = -ENOMEM; 519*fd385855SPaul Moore goto list_retry; 520*fd385855SPaul Moore } 521*fd385855SPaul Moore for (iter = 0; 522*fd385855SPaul Moore iter < doi_def->map.std->cat.local_size; 523*fd385855SPaul Moore iter++) { 524*fd385855SPaul Moore if (doi_def->map.std->cat.local[iter] == 525*fd385855SPaul Moore CIPSO_V4_INV_CAT) 526*fd385855SPaul Moore continue; 527*fd385855SPaul Moore 528*fd385855SPaul Moore nla_b = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSCAT); 529*fd385855SPaul Moore if (nla_b == NULL) { 530*fd385855SPaul Moore ret_val = -ENOMEM; 531*fd385855SPaul Moore goto list_retry; 532*fd385855SPaul Moore } 533*fd385855SPaul Moore ret_val = nla_put_u32(ans_skb, 534*fd385855SPaul Moore NLBL_CIPSOV4_A_MLSCATLOC, 535*fd385855SPaul Moore iter); 536*fd385855SPaul Moore if (ret_val != 0) 537*fd385855SPaul Moore goto list_retry; 538*fd385855SPaul Moore ret_val = nla_put_u32(ans_skb, 539*fd385855SPaul Moore NLBL_CIPSOV4_A_MLSCATREM, 540*fd385855SPaul Moore doi_def->map.std->cat.local[iter]); 541*fd385855SPaul Moore if (ret_val != 0) 542*fd385855SPaul Moore goto list_retry; 543*fd385855SPaul Moore nla_nest_end(ans_skb, nla_b); 544*fd385855SPaul Moore } 545*fd385855SPaul Moore nla_nest_end(ans_skb, nla_a); 546*fd385855SPaul Moore 547*fd385855SPaul Moore break; 548*fd385855SPaul Moore } 549*fd385855SPaul Moore rcu_read_unlock(); 550*fd385855SPaul Moore 551*fd385855SPaul Moore genlmsg_end(ans_skb, data); 552*fd385855SPaul Moore 553*fd385855SPaul Moore ret_val = genlmsg_unicast(ans_skb, info->snd_pid); 55496cb8e33SPaul Moore if (ret_val != 0) 55596cb8e33SPaul Moore goto list_failure; 55696cb8e33SPaul Moore 55796cb8e33SPaul Moore return 0; 55896cb8e33SPaul Moore 559*fd385855SPaul Moore list_retry: 560*fd385855SPaul Moore /* XXX - this limit is a guesstimate */ 561*fd385855SPaul Moore if (nlsze_mult < 4) { 562*fd385855SPaul Moore rcu_read_unlock(); 563*fd385855SPaul Moore kfree_skb(ans_skb); 564*fd385855SPaul Moore nlsze_mult++; 565*fd385855SPaul Moore goto list_start; 566*fd385855SPaul Moore } 567*fd385855SPaul Moore list_failure_lock: 568*fd385855SPaul Moore rcu_read_unlock(); 56996cb8e33SPaul Moore list_failure: 570*fd385855SPaul Moore kfree_skb(ans_skb); 571*fd385855SPaul Moore return ret_val; 572*fd385855SPaul Moore } 573*fd385855SPaul Moore 574*fd385855SPaul Moore /** 575*fd385855SPaul Moore * netlbl_cipsov4_listall_cb - cipso_v4_doi_walk() callback for LISTALL 576*fd385855SPaul Moore * @doi_def: the CIPSOv4 DOI definition 577*fd385855SPaul Moore * @arg: the netlbl_cipsov4_doiwalk_arg structure 578*fd385855SPaul Moore * 579*fd385855SPaul Moore * Description: 580*fd385855SPaul Moore * This function is designed to be used as a callback to the 581*fd385855SPaul Moore * cipso_v4_doi_walk() function for use in generating a response for a LISTALL 582*fd385855SPaul Moore * message. Returns the size of the message on success, negative values on 583*fd385855SPaul Moore * failure. 584*fd385855SPaul Moore * 585*fd385855SPaul Moore */ 586*fd385855SPaul Moore static int netlbl_cipsov4_listall_cb(struct cipso_v4_doi *doi_def, void *arg) 587*fd385855SPaul Moore { 588*fd385855SPaul Moore int ret_val = -ENOMEM; 589*fd385855SPaul Moore struct netlbl_cipsov4_doiwalk_arg *cb_arg = arg; 590*fd385855SPaul Moore void *data; 591*fd385855SPaul Moore 592*fd385855SPaul Moore data = netlbl_netlink_hdr_put(cb_arg->skb, 593*fd385855SPaul Moore NETLINK_CB(cb_arg->nl_cb->skb).pid, 594*fd385855SPaul Moore cb_arg->seq, 59596cb8e33SPaul Moore netlbl_cipsov4_gnl_family.id, 596*fd385855SPaul Moore NLM_F_MULTI, 597*fd385855SPaul Moore NLBL_CIPSOV4_C_LISTALL); 598*fd385855SPaul Moore if (data == NULL) 599*fd385855SPaul Moore goto listall_cb_failure; 600*fd385855SPaul Moore 601*fd385855SPaul Moore ret_val = nla_put_u32(cb_arg->skb, NLBL_CIPSOV4_A_DOI, doi_def->doi); 602*fd385855SPaul Moore if (ret_val != 0) 603*fd385855SPaul Moore goto listall_cb_failure; 604*fd385855SPaul Moore ret_val = nla_put_u32(cb_arg->skb, 605*fd385855SPaul Moore NLBL_CIPSOV4_A_MTYPE, 606*fd385855SPaul Moore doi_def->type); 607*fd385855SPaul Moore if (ret_val != 0) 608*fd385855SPaul Moore goto listall_cb_failure; 609*fd385855SPaul Moore 610*fd385855SPaul Moore return genlmsg_end(cb_arg->skb, data); 611*fd385855SPaul Moore 612*fd385855SPaul Moore listall_cb_failure: 613*fd385855SPaul Moore genlmsg_cancel(cb_arg->skb, data); 61496cb8e33SPaul Moore return ret_val; 61596cb8e33SPaul Moore } 61696cb8e33SPaul Moore 61796cb8e33SPaul Moore /** 61896cb8e33SPaul Moore * netlbl_cipsov4_listall - Handle a LISTALL message 61996cb8e33SPaul Moore * @skb: the NETLINK buffer 620*fd385855SPaul Moore * @cb: the NETLINK callback 62196cb8e33SPaul Moore * 62296cb8e33SPaul Moore * Description: 62396cb8e33SPaul Moore * Process a user generated LISTALL message and respond accordingly. Returns 62496cb8e33SPaul Moore * zero on success and negative values on error. 62596cb8e33SPaul Moore * 62696cb8e33SPaul Moore */ 627*fd385855SPaul Moore static int netlbl_cipsov4_listall(struct sk_buff *skb, 628*fd385855SPaul Moore struct netlink_callback *cb) 62996cb8e33SPaul Moore { 630*fd385855SPaul Moore struct netlbl_cipsov4_doiwalk_arg cb_arg; 631*fd385855SPaul Moore int doi_skip = cb->args[0]; 63296cb8e33SPaul Moore 633*fd385855SPaul Moore cb_arg.nl_cb = cb; 634*fd385855SPaul Moore cb_arg.skb = skb; 635*fd385855SPaul Moore cb_arg.seq = cb->nlh->nlmsg_seq; 63696cb8e33SPaul Moore 637*fd385855SPaul Moore cipso_v4_doi_walk(&doi_skip, netlbl_cipsov4_listall_cb, &cb_arg); 63896cb8e33SPaul Moore 639*fd385855SPaul Moore cb->args[0] = doi_skip; 640*fd385855SPaul Moore return skb->len; 64196cb8e33SPaul Moore } 64296cb8e33SPaul Moore 64396cb8e33SPaul Moore /** 64496cb8e33SPaul Moore * netlbl_cipsov4_remove - Handle a REMOVE message 64596cb8e33SPaul Moore * @skb: the NETLINK buffer 64696cb8e33SPaul Moore * @info: the Generic NETLINK info block 64796cb8e33SPaul Moore * 64896cb8e33SPaul Moore * Description: 64996cb8e33SPaul Moore * Process a user generated REMOVE message and respond accordingly. Returns 65096cb8e33SPaul Moore * zero on success, negative values on failure. 65196cb8e33SPaul Moore * 65296cb8e33SPaul Moore */ 65396cb8e33SPaul Moore static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info) 65496cb8e33SPaul Moore { 655*fd385855SPaul Moore int ret_val = -EINVAL; 65696cb8e33SPaul Moore u32 doi; 65796cb8e33SPaul Moore 658*fd385855SPaul Moore if (info->attrs[NLBL_CIPSOV4_A_DOI]) { 659*fd385855SPaul Moore doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]); 660*fd385855SPaul Moore ret_val = cipso_v4_doi_remove(doi, netlbl_cipsov4_doi_free); 66196cb8e33SPaul Moore } 66296cb8e33SPaul Moore 66396cb8e33SPaul Moore return ret_val; 66496cb8e33SPaul Moore } 66596cb8e33SPaul Moore 66696cb8e33SPaul Moore /* 66796cb8e33SPaul Moore * NetLabel Generic NETLINK Command Definitions 66896cb8e33SPaul Moore */ 66996cb8e33SPaul Moore 67096cb8e33SPaul Moore static struct genl_ops netlbl_cipsov4_genl_c_add = { 67196cb8e33SPaul Moore .cmd = NLBL_CIPSOV4_C_ADD, 672*fd385855SPaul Moore .flags = GENL_ADMIN_PERM, 673*fd385855SPaul Moore .policy = netlbl_cipsov4_genl_policy, 67496cb8e33SPaul Moore .doit = netlbl_cipsov4_add, 67596cb8e33SPaul Moore .dumpit = NULL, 67696cb8e33SPaul Moore }; 67796cb8e33SPaul Moore 67896cb8e33SPaul Moore static struct genl_ops netlbl_cipsov4_genl_c_remove = { 67996cb8e33SPaul Moore .cmd = NLBL_CIPSOV4_C_REMOVE, 680*fd385855SPaul Moore .flags = GENL_ADMIN_PERM, 681*fd385855SPaul Moore .policy = netlbl_cipsov4_genl_policy, 68296cb8e33SPaul Moore .doit = netlbl_cipsov4_remove, 68396cb8e33SPaul Moore .dumpit = NULL, 68496cb8e33SPaul Moore }; 68596cb8e33SPaul Moore 68696cb8e33SPaul Moore static struct genl_ops netlbl_cipsov4_genl_c_list = { 68796cb8e33SPaul Moore .cmd = NLBL_CIPSOV4_C_LIST, 68896cb8e33SPaul Moore .flags = 0, 689*fd385855SPaul Moore .policy = netlbl_cipsov4_genl_policy, 69096cb8e33SPaul Moore .doit = netlbl_cipsov4_list, 69196cb8e33SPaul Moore .dumpit = NULL, 69296cb8e33SPaul Moore }; 69396cb8e33SPaul Moore 69496cb8e33SPaul Moore static struct genl_ops netlbl_cipsov4_genl_c_listall = { 69596cb8e33SPaul Moore .cmd = NLBL_CIPSOV4_C_LISTALL, 69696cb8e33SPaul Moore .flags = 0, 697*fd385855SPaul Moore .policy = netlbl_cipsov4_genl_policy, 698*fd385855SPaul Moore .doit = NULL, 699*fd385855SPaul Moore .dumpit = netlbl_cipsov4_listall, 70096cb8e33SPaul Moore }; 70196cb8e33SPaul Moore 70296cb8e33SPaul Moore /* 70396cb8e33SPaul Moore * NetLabel Generic NETLINK Protocol Functions 70496cb8e33SPaul Moore */ 70596cb8e33SPaul Moore 70696cb8e33SPaul Moore /** 70796cb8e33SPaul Moore * netlbl_cipsov4_genl_init - Register the CIPSOv4 NetLabel component 70896cb8e33SPaul Moore * 70996cb8e33SPaul Moore * Description: 71096cb8e33SPaul Moore * Register the CIPSOv4 packet NetLabel component with the Generic NETLINK 71196cb8e33SPaul Moore * mechanism. Returns zero on success, negative values on failure. 71296cb8e33SPaul Moore * 71396cb8e33SPaul Moore */ 71496cb8e33SPaul Moore int netlbl_cipsov4_genl_init(void) 71596cb8e33SPaul Moore { 71696cb8e33SPaul Moore int ret_val; 71796cb8e33SPaul Moore 71896cb8e33SPaul Moore ret_val = genl_register_family(&netlbl_cipsov4_gnl_family); 71996cb8e33SPaul Moore if (ret_val != 0) 72096cb8e33SPaul Moore return ret_val; 72196cb8e33SPaul Moore 72296cb8e33SPaul Moore ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family, 72396cb8e33SPaul Moore &netlbl_cipsov4_genl_c_add); 72496cb8e33SPaul Moore if (ret_val != 0) 72596cb8e33SPaul Moore return ret_val; 72696cb8e33SPaul Moore ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family, 72796cb8e33SPaul Moore &netlbl_cipsov4_genl_c_remove); 72896cb8e33SPaul Moore if (ret_val != 0) 72996cb8e33SPaul Moore return ret_val; 73096cb8e33SPaul Moore ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family, 73196cb8e33SPaul Moore &netlbl_cipsov4_genl_c_list); 73296cb8e33SPaul Moore if (ret_val != 0) 73396cb8e33SPaul Moore return ret_val; 73496cb8e33SPaul Moore ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family, 73596cb8e33SPaul Moore &netlbl_cipsov4_genl_c_listall); 73696cb8e33SPaul Moore if (ret_val != 0) 73796cb8e33SPaul Moore return ret_val; 73896cb8e33SPaul Moore 73996cb8e33SPaul Moore return 0; 74096cb8e33SPaul Moore } 741