1*96cb8e33SPaul Moore /* 2*96cb8e33SPaul Moore * NetLabel CIPSO/IPv4 Support 3*96cb8e33SPaul Moore * 4*96cb8e33SPaul Moore * This file defines the CIPSO/IPv4 functions for the NetLabel system. The 5*96cb8e33SPaul Moore * NetLabel system manages static and dynamic label mappings for network 6*96cb8e33SPaul Moore * protocols such as CIPSO and RIPSO. 7*96cb8e33SPaul Moore * 8*96cb8e33SPaul Moore * Author: Paul Moore <paul.moore@hp.com> 9*96cb8e33SPaul Moore * 10*96cb8e33SPaul Moore */ 11*96cb8e33SPaul Moore 12*96cb8e33SPaul Moore /* 13*96cb8e33SPaul Moore * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 14*96cb8e33SPaul Moore * 15*96cb8e33SPaul Moore * This program is free software; you can redistribute it and/or modify 16*96cb8e33SPaul Moore * it under the terms of the GNU General Public License as published by 17*96cb8e33SPaul Moore * the Free Software Foundation; either version 2 of the License, or 18*96cb8e33SPaul Moore * (at your option) any later version. 19*96cb8e33SPaul Moore * 20*96cb8e33SPaul Moore * This program is distributed in the hope that it will be useful, 21*96cb8e33SPaul Moore * but WITHOUT ANY WARRANTY; without even the implied warranty of 22*96cb8e33SPaul Moore * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 23*96cb8e33SPaul Moore * the GNU General Public License for more details. 24*96cb8e33SPaul Moore * 25*96cb8e33SPaul Moore * You should have received a copy of the GNU General Public License 26*96cb8e33SPaul Moore * along with this program; if not, write to the Free Software 27*96cb8e33SPaul Moore * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 28*96cb8e33SPaul Moore * 29*96cb8e33SPaul Moore */ 30*96cb8e33SPaul Moore 31*96cb8e33SPaul Moore #include <linux/types.h> 32*96cb8e33SPaul Moore #include <linux/socket.h> 33*96cb8e33SPaul Moore #include <linux/string.h> 34*96cb8e33SPaul Moore #include <linux/skbuff.h> 35*96cb8e33SPaul Moore #include <net/sock.h> 36*96cb8e33SPaul Moore #include <net/netlink.h> 37*96cb8e33SPaul Moore #include <net/genetlink.h> 38*96cb8e33SPaul Moore #include <net/netlabel.h> 39*96cb8e33SPaul Moore #include <net/cipso_ipv4.h> 40*96cb8e33SPaul Moore 41*96cb8e33SPaul Moore #include "netlabel_user.h" 42*96cb8e33SPaul Moore #include "netlabel_cipso_v4.h" 43*96cb8e33SPaul Moore 44*96cb8e33SPaul Moore /* NetLabel Generic NETLINK CIPSOv4 family */ 45*96cb8e33SPaul Moore static struct genl_family netlbl_cipsov4_gnl_family = { 46*96cb8e33SPaul Moore .id = GENL_ID_GENERATE, 47*96cb8e33SPaul Moore .hdrsize = 0, 48*96cb8e33SPaul Moore .name = NETLBL_NLTYPE_CIPSOV4_NAME, 49*96cb8e33SPaul Moore .version = NETLBL_PROTO_VERSION, 50*96cb8e33SPaul Moore .maxattr = 0, 51*96cb8e33SPaul Moore }; 52*96cb8e33SPaul Moore 53*96cb8e33SPaul Moore 54*96cb8e33SPaul Moore /* 55*96cb8e33SPaul Moore * Helper Functions 56*96cb8e33SPaul Moore */ 57*96cb8e33SPaul Moore 58*96cb8e33SPaul Moore /** 59*96cb8e33SPaul Moore * netlbl_cipsov4_doi_free - Frees a CIPSO V4 DOI definition 60*96cb8e33SPaul Moore * @entry: the entry's RCU field 61*96cb8e33SPaul Moore * 62*96cb8e33SPaul Moore * Description: 63*96cb8e33SPaul Moore * This function is designed to be used as a callback to the call_rcu() 64*96cb8e33SPaul Moore * function so that the memory allocated to the DOI definition can be released 65*96cb8e33SPaul Moore * safely. 66*96cb8e33SPaul Moore * 67*96cb8e33SPaul Moore */ 68*96cb8e33SPaul Moore static void netlbl_cipsov4_doi_free(struct rcu_head *entry) 69*96cb8e33SPaul Moore { 70*96cb8e33SPaul Moore struct cipso_v4_doi *ptr; 71*96cb8e33SPaul Moore 72*96cb8e33SPaul Moore ptr = container_of(entry, struct cipso_v4_doi, rcu); 73*96cb8e33SPaul Moore switch (ptr->type) { 74*96cb8e33SPaul Moore case CIPSO_V4_MAP_STD: 75*96cb8e33SPaul Moore kfree(ptr->map.std->lvl.cipso); 76*96cb8e33SPaul Moore kfree(ptr->map.std->lvl.local); 77*96cb8e33SPaul Moore kfree(ptr->map.std->cat.cipso); 78*96cb8e33SPaul Moore kfree(ptr->map.std->cat.local); 79*96cb8e33SPaul Moore break; 80*96cb8e33SPaul Moore } 81*96cb8e33SPaul Moore kfree(ptr); 82*96cb8e33SPaul Moore } 83*96cb8e33SPaul Moore 84*96cb8e33SPaul Moore 85*96cb8e33SPaul Moore /* 86*96cb8e33SPaul Moore * NetLabel Command Handlers 87*96cb8e33SPaul Moore */ 88*96cb8e33SPaul Moore 89*96cb8e33SPaul Moore /** 90*96cb8e33SPaul Moore * netlbl_cipsov4_add_std - Adds a CIPSO V4 DOI definition 91*96cb8e33SPaul Moore * @doi: the DOI value 92*96cb8e33SPaul Moore * @msg: the ADD message data 93*96cb8e33SPaul Moore * @msg_size: the size of the ADD message buffer 94*96cb8e33SPaul Moore * 95*96cb8e33SPaul Moore * Description: 96*96cb8e33SPaul Moore * Create a new CIPSO_V4_MAP_STD DOI definition based on the given ADD message 97*96cb8e33SPaul Moore * and add it to the CIPSO V4 engine. Return zero on success and non-zero on 98*96cb8e33SPaul Moore * error. 99*96cb8e33SPaul Moore * 100*96cb8e33SPaul Moore */ 101*96cb8e33SPaul Moore static int netlbl_cipsov4_add_std(u32 doi, struct nlattr *msg, size_t msg_size) 102*96cb8e33SPaul Moore { 103*96cb8e33SPaul Moore int ret_val = -EINVAL; 104*96cb8e33SPaul Moore int msg_len = msg_size; 105*96cb8e33SPaul Moore u32 num_tags; 106*96cb8e33SPaul Moore u32 num_lvls; 107*96cb8e33SPaul Moore u32 num_cats; 108*96cb8e33SPaul Moore struct cipso_v4_doi *doi_def = NULL; 109*96cb8e33SPaul Moore u32 iter; 110*96cb8e33SPaul Moore u32 tmp_val_a; 111*96cb8e33SPaul Moore u32 tmp_val_b; 112*96cb8e33SPaul Moore 113*96cb8e33SPaul Moore if (msg_len < NETLBL_LEN_U32) 114*96cb8e33SPaul Moore goto add_std_failure; 115*96cb8e33SPaul Moore num_tags = netlbl_getinc_u32(&msg, &msg_len); 116*96cb8e33SPaul Moore if (num_tags == 0 || num_tags > CIPSO_V4_TAG_MAXCNT) 117*96cb8e33SPaul Moore goto add_std_failure; 118*96cb8e33SPaul Moore 119*96cb8e33SPaul Moore doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL); 120*96cb8e33SPaul Moore if (doi_def == NULL) { 121*96cb8e33SPaul Moore ret_val = -ENOMEM; 122*96cb8e33SPaul Moore goto add_std_failure; 123*96cb8e33SPaul Moore } 124*96cb8e33SPaul Moore doi_def->map.std = kzalloc(sizeof(*doi_def->map.std), GFP_KERNEL); 125*96cb8e33SPaul Moore if (doi_def->map.std == NULL) { 126*96cb8e33SPaul Moore ret_val = -ENOMEM; 127*96cb8e33SPaul Moore goto add_std_failure; 128*96cb8e33SPaul Moore } 129*96cb8e33SPaul Moore doi_def->type = CIPSO_V4_MAP_STD; 130*96cb8e33SPaul Moore 131*96cb8e33SPaul Moore for (iter = 0; iter < num_tags; iter++) { 132*96cb8e33SPaul Moore if (msg_len < NETLBL_LEN_U8) 133*96cb8e33SPaul Moore goto add_std_failure; 134*96cb8e33SPaul Moore doi_def->tags[iter] = netlbl_getinc_u8(&msg, &msg_len); 135*96cb8e33SPaul Moore switch (doi_def->tags[iter]) { 136*96cb8e33SPaul Moore case CIPSO_V4_TAG_RBITMAP: 137*96cb8e33SPaul Moore break; 138*96cb8e33SPaul Moore default: 139*96cb8e33SPaul Moore goto add_std_failure; 140*96cb8e33SPaul Moore } 141*96cb8e33SPaul Moore } 142*96cb8e33SPaul Moore if (iter < CIPSO_V4_TAG_MAXCNT) 143*96cb8e33SPaul Moore doi_def->tags[iter] = CIPSO_V4_TAG_INVALID; 144*96cb8e33SPaul Moore 145*96cb8e33SPaul Moore if (msg_len < 6 * NETLBL_LEN_U32) 146*96cb8e33SPaul Moore goto add_std_failure; 147*96cb8e33SPaul Moore 148*96cb8e33SPaul Moore num_lvls = netlbl_getinc_u32(&msg, &msg_len); 149*96cb8e33SPaul Moore if (num_lvls == 0) 150*96cb8e33SPaul Moore goto add_std_failure; 151*96cb8e33SPaul Moore doi_def->map.std->lvl.local_size = netlbl_getinc_u32(&msg, &msg_len); 152*96cb8e33SPaul Moore if (doi_def->map.std->lvl.local_size > CIPSO_V4_MAX_LOC_LVLS) 153*96cb8e33SPaul Moore goto add_std_failure; 154*96cb8e33SPaul Moore doi_def->map.std->lvl.local = kcalloc(doi_def->map.std->lvl.local_size, 155*96cb8e33SPaul Moore sizeof(u32), 156*96cb8e33SPaul Moore GFP_KERNEL); 157*96cb8e33SPaul Moore if (doi_def->map.std->lvl.local == NULL) { 158*96cb8e33SPaul Moore ret_val = -ENOMEM; 159*96cb8e33SPaul Moore goto add_std_failure; 160*96cb8e33SPaul Moore } 161*96cb8e33SPaul Moore doi_def->map.std->lvl.cipso_size = netlbl_getinc_u8(&msg, &msg_len); 162*96cb8e33SPaul Moore if (doi_def->map.std->lvl.cipso_size > CIPSO_V4_MAX_REM_LVLS) 163*96cb8e33SPaul Moore goto add_std_failure; 164*96cb8e33SPaul Moore doi_def->map.std->lvl.cipso = kcalloc(doi_def->map.std->lvl.cipso_size, 165*96cb8e33SPaul Moore sizeof(u32), 166*96cb8e33SPaul Moore GFP_KERNEL); 167*96cb8e33SPaul Moore if (doi_def->map.std->lvl.cipso == NULL) { 168*96cb8e33SPaul Moore ret_val = -ENOMEM; 169*96cb8e33SPaul Moore goto add_std_failure; 170*96cb8e33SPaul Moore } 171*96cb8e33SPaul Moore 172*96cb8e33SPaul Moore num_cats = netlbl_getinc_u32(&msg, &msg_len); 173*96cb8e33SPaul Moore doi_def->map.std->cat.local_size = netlbl_getinc_u32(&msg, &msg_len); 174*96cb8e33SPaul Moore if (doi_def->map.std->cat.local_size > CIPSO_V4_MAX_LOC_CATS) 175*96cb8e33SPaul Moore goto add_std_failure; 176*96cb8e33SPaul Moore doi_def->map.std->cat.local = kcalloc(doi_def->map.std->cat.local_size, 177*96cb8e33SPaul Moore sizeof(u32), 178*96cb8e33SPaul Moore GFP_KERNEL); 179*96cb8e33SPaul Moore if (doi_def->map.std->cat.local == NULL) { 180*96cb8e33SPaul Moore ret_val = -ENOMEM; 181*96cb8e33SPaul Moore goto add_std_failure; 182*96cb8e33SPaul Moore } 183*96cb8e33SPaul Moore doi_def->map.std->cat.cipso_size = netlbl_getinc_u16(&msg, &msg_len); 184*96cb8e33SPaul Moore if (doi_def->map.std->cat.cipso_size > CIPSO_V4_MAX_REM_CATS) 185*96cb8e33SPaul Moore goto add_std_failure; 186*96cb8e33SPaul Moore doi_def->map.std->cat.cipso = kcalloc(doi_def->map.std->cat.cipso_size, 187*96cb8e33SPaul Moore sizeof(u32), 188*96cb8e33SPaul Moore GFP_KERNEL); 189*96cb8e33SPaul Moore if (doi_def->map.std->cat.cipso == NULL) { 190*96cb8e33SPaul Moore ret_val = -ENOMEM; 191*96cb8e33SPaul Moore goto add_std_failure; 192*96cb8e33SPaul Moore } 193*96cb8e33SPaul Moore 194*96cb8e33SPaul Moore if (msg_len < 195*96cb8e33SPaul Moore num_lvls * (NETLBL_LEN_U32 + NETLBL_LEN_U8) + 196*96cb8e33SPaul Moore num_cats * (NETLBL_LEN_U32 + NETLBL_LEN_U16)) 197*96cb8e33SPaul Moore goto add_std_failure; 198*96cb8e33SPaul Moore 199*96cb8e33SPaul Moore for (iter = 0; iter < doi_def->map.std->lvl.cipso_size; iter++) 200*96cb8e33SPaul Moore doi_def->map.std->lvl.cipso[iter] = CIPSO_V4_INV_LVL; 201*96cb8e33SPaul Moore for (iter = 0; iter < doi_def->map.std->lvl.local_size; iter++) 202*96cb8e33SPaul Moore doi_def->map.std->lvl.local[iter] = CIPSO_V4_INV_LVL; 203*96cb8e33SPaul Moore for (iter = 0; iter < doi_def->map.std->cat.cipso_size; iter++) 204*96cb8e33SPaul Moore doi_def->map.std->cat.cipso[iter] = CIPSO_V4_INV_CAT; 205*96cb8e33SPaul Moore for (iter = 0; iter < doi_def->map.std->cat.local_size; iter++) 206*96cb8e33SPaul Moore doi_def->map.std->cat.local[iter] = CIPSO_V4_INV_CAT; 207*96cb8e33SPaul Moore 208*96cb8e33SPaul Moore for (iter = 0; iter < num_lvls; iter++) { 209*96cb8e33SPaul Moore tmp_val_a = netlbl_getinc_u32(&msg, &msg_len); 210*96cb8e33SPaul Moore tmp_val_b = netlbl_getinc_u8(&msg, &msg_len); 211*96cb8e33SPaul Moore 212*96cb8e33SPaul Moore if (tmp_val_a >= doi_def->map.std->lvl.local_size || 213*96cb8e33SPaul Moore tmp_val_b >= doi_def->map.std->lvl.cipso_size) 214*96cb8e33SPaul Moore goto add_std_failure; 215*96cb8e33SPaul Moore 216*96cb8e33SPaul Moore doi_def->map.std->lvl.cipso[tmp_val_b] = tmp_val_a; 217*96cb8e33SPaul Moore doi_def->map.std->lvl.local[tmp_val_a] = tmp_val_b; 218*96cb8e33SPaul Moore } 219*96cb8e33SPaul Moore 220*96cb8e33SPaul Moore for (iter = 0; iter < num_cats; iter++) { 221*96cb8e33SPaul Moore tmp_val_a = netlbl_getinc_u32(&msg, &msg_len); 222*96cb8e33SPaul Moore tmp_val_b = netlbl_getinc_u16(&msg, &msg_len); 223*96cb8e33SPaul Moore 224*96cb8e33SPaul Moore if (tmp_val_a >= doi_def->map.std->cat.local_size || 225*96cb8e33SPaul Moore tmp_val_b >= doi_def->map.std->cat.cipso_size) 226*96cb8e33SPaul Moore goto add_std_failure; 227*96cb8e33SPaul Moore 228*96cb8e33SPaul Moore doi_def->map.std->cat.cipso[tmp_val_b] = tmp_val_a; 229*96cb8e33SPaul Moore doi_def->map.std->cat.local[tmp_val_a] = tmp_val_b; 230*96cb8e33SPaul Moore } 231*96cb8e33SPaul Moore 232*96cb8e33SPaul Moore doi_def->doi = doi; 233*96cb8e33SPaul Moore ret_val = cipso_v4_doi_add(doi_def); 234*96cb8e33SPaul Moore if (ret_val != 0) 235*96cb8e33SPaul Moore goto add_std_failure; 236*96cb8e33SPaul Moore return 0; 237*96cb8e33SPaul Moore 238*96cb8e33SPaul Moore add_std_failure: 239*96cb8e33SPaul Moore if (doi_def) 240*96cb8e33SPaul Moore netlbl_cipsov4_doi_free(&doi_def->rcu); 241*96cb8e33SPaul Moore return ret_val; 242*96cb8e33SPaul Moore } 243*96cb8e33SPaul Moore 244*96cb8e33SPaul Moore /** 245*96cb8e33SPaul Moore * netlbl_cipsov4_add_pass - Adds a CIPSO V4 DOI definition 246*96cb8e33SPaul Moore * @doi: the DOI value 247*96cb8e33SPaul Moore * @msg: the ADD message data 248*96cb8e33SPaul Moore * @msg_size: the size of the ADD message buffer 249*96cb8e33SPaul Moore * 250*96cb8e33SPaul Moore * Description: 251*96cb8e33SPaul Moore * Create a new CIPSO_V4_MAP_PASS DOI definition based on the given ADD message 252*96cb8e33SPaul Moore * and add it to the CIPSO V4 engine. Return zero on success and non-zero on 253*96cb8e33SPaul Moore * error. 254*96cb8e33SPaul Moore * 255*96cb8e33SPaul Moore */ 256*96cb8e33SPaul Moore static int netlbl_cipsov4_add_pass(u32 doi, 257*96cb8e33SPaul Moore struct nlattr *msg, 258*96cb8e33SPaul Moore size_t msg_size) 259*96cb8e33SPaul Moore { 260*96cb8e33SPaul Moore int ret_val = -EINVAL; 261*96cb8e33SPaul Moore int msg_len = msg_size; 262*96cb8e33SPaul Moore u32 num_tags; 263*96cb8e33SPaul Moore struct cipso_v4_doi *doi_def = NULL; 264*96cb8e33SPaul Moore u32 iter; 265*96cb8e33SPaul Moore 266*96cb8e33SPaul Moore if (msg_len < NETLBL_LEN_U32) 267*96cb8e33SPaul Moore goto add_pass_failure; 268*96cb8e33SPaul Moore num_tags = netlbl_getinc_u32(&msg, &msg_len); 269*96cb8e33SPaul Moore if (num_tags == 0 || num_tags > CIPSO_V4_TAG_MAXCNT) 270*96cb8e33SPaul Moore goto add_pass_failure; 271*96cb8e33SPaul Moore 272*96cb8e33SPaul Moore doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL); 273*96cb8e33SPaul Moore if (doi_def == NULL) { 274*96cb8e33SPaul Moore ret_val = -ENOMEM; 275*96cb8e33SPaul Moore goto add_pass_failure; 276*96cb8e33SPaul Moore } 277*96cb8e33SPaul Moore doi_def->type = CIPSO_V4_MAP_PASS; 278*96cb8e33SPaul Moore 279*96cb8e33SPaul Moore for (iter = 0; iter < num_tags; iter++) { 280*96cb8e33SPaul Moore if (msg_len < NETLBL_LEN_U8) 281*96cb8e33SPaul Moore goto add_pass_failure; 282*96cb8e33SPaul Moore doi_def->tags[iter] = netlbl_getinc_u8(&msg, &msg_len); 283*96cb8e33SPaul Moore switch (doi_def->tags[iter]) { 284*96cb8e33SPaul Moore case CIPSO_V4_TAG_RBITMAP: 285*96cb8e33SPaul Moore break; 286*96cb8e33SPaul Moore default: 287*96cb8e33SPaul Moore goto add_pass_failure; 288*96cb8e33SPaul Moore } 289*96cb8e33SPaul Moore } 290*96cb8e33SPaul Moore if (iter < CIPSO_V4_TAG_MAXCNT) 291*96cb8e33SPaul Moore doi_def->tags[iter] = CIPSO_V4_TAG_INVALID; 292*96cb8e33SPaul Moore 293*96cb8e33SPaul Moore doi_def->doi = doi; 294*96cb8e33SPaul Moore ret_val = cipso_v4_doi_add(doi_def); 295*96cb8e33SPaul Moore if (ret_val != 0) 296*96cb8e33SPaul Moore goto add_pass_failure; 297*96cb8e33SPaul Moore return 0; 298*96cb8e33SPaul Moore 299*96cb8e33SPaul Moore add_pass_failure: 300*96cb8e33SPaul Moore if (doi_def) 301*96cb8e33SPaul Moore netlbl_cipsov4_doi_free(&doi_def->rcu); 302*96cb8e33SPaul Moore return ret_val; 303*96cb8e33SPaul Moore } 304*96cb8e33SPaul Moore 305*96cb8e33SPaul Moore /** 306*96cb8e33SPaul Moore * netlbl_cipsov4_add - Handle an ADD message 307*96cb8e33SPaul Moore * @skb: the NETLINK buffer 308*96cb8e33SPaul Moore * @info: the Generic NETLINK info block 309*96cb8e33SPaul Moore * 310*96cb8e33SPaul Moore * Description: 311*96cb8e33SPaul Moore * Create a new DOI definition based on the given ADD message and add it to the 312*96cb8e33SPaul Moore * CIPSO V4 engine. Returns zero on success, negative values on failure. 313*96cb8e33SPaul Moore * 314*96cb8e33SPaul Moore */ 315*96cb8e33SPaul Moore static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info) 316*96cb8e33SPaul Moore 317*96cb8e33SPaul Moore { 318*96cb8e33SPaul Moore int ret_val = -EINVAL; 319*96cb8e33SPaul Moore u32 doi; 320*96cb8e33SPaul Moore u32 map_type; 321*96cb8e33SPaul Moore int msg_len = netlbl_netlink_payload_len(skb); 322*96cb8e33SPaul Moore struct nlattr *msg = netlbl_netlink_payload_data(skb); 323*96cb8e33SPaul Moore 324*96cb8e33SPaul Moore ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN); 325*96cb8e33SPaul Moore if (ret_val != 0) 326*96cb8e33SPaul Moore goto add_return; 327*96cb8e33SPaul Moore 328*96cb8e33SPaul Moore if (msg_len < 2 * NETLBL_LEN_U32) 329*96cb8e33SPaul Moore goto add_return; 330*96cb8e33SPaul Moore 331*96cb8e33SPaul Moore doi = netlbl_getinc_u32(&msg, &msg_len); 332*96cb8e33SPaul Moore map_type = netlbl_getinc_u32(&msg, &msg_len); 333*96cb8e33SPaul Moore switch (map_type) { 334*96cb8e33SPaul Moore case CIPSO_V4_MAP_STD: 335*96cb8e33SPaul Moore ret_val = netlbl_cipsov4_add_std(doi, msg, msg_len); 336*96cb8e33SPaul Moore break; 337*96cb8e33SPaul Moore case CIPSO_V4_MAP_PASS: 338*96cb8e33SPaul Moore ret_val = netlbl_cipsov4_add_pass(doi, msg, msg_len); 339*96cb8e33SPaul Moore break; 340*96cb8e33SPaul Moore } 341*96cb8e33SPaul Moore 342*96cb8e33SPaul Moore add_return: 343*96cb8e33SPaul Moore netlbl_netlink_send_ack(info, 344*96cb8e33SPaul Moore netlbl_cipsov4_gnl_family.id, 345*96cb8e33SPaul Moore NLBL_CIPSOV4_C_ACK, 346*96cb8e33SPaul Moore -ret_val); 347*96cb8e33SPaul Moore return ret_val; 348*96cb8e33SPaul Moore } 349*96cb8e33SPaul Moore 350*96cb8e33SPaul Moore /** 351*96cb8e33SPaul Moore * netlbl_cipsov4_list - Handle a LIST message 352*96cb8e33SPaul Moore * @skb: the NETLINK buffer 353*96cb8e33SPaul Moore * @info: the Generic NETLINK info block 354*96cb8e33SPaul Moore * 355*96cb8e33SPaul Moore * Description: 356*96cb8e33SPaul Moore * Process a user generated LIST message and respond accordingly. Returns 357*96cb8e33SPaul Moore * zero on success and negative values on error. 358*96cb8e33SPaul Moore * 359*96cb8e33SPaul Moore */ 360*96cb8e33SPaul Moore static int netlbl_cipsov4_list(struct sk_buff *skb, struct genl_info *info) 361*96cb8e33SPaul Moore { 362*96cb8e33SPaul Moore int ret_val = -EINVAL; 363*96cb8e33SPaul Moore u32 doi; 364*96cb8e33SPaul Moore struct nlattr *msg = netlbl_netlink_payload_data(skb); 365*96cb8e33SPaul Moore struct sk_buff *ans_skb; 366*96cb8e33SPaul Moore 367*96cb8e33SPaul Moore if (netlbl_netlink_payload_len(skb) != NETLBL_LEN_U32) 368*96cb8e33SPaul Moore goto list_failure; 369*96cb8e33SPaul Moore 370*96cb8e33SPaul Moore doi = nla_get_u32(msg); 371*96cb8e33SPaul Moore ans_skb = cipso_v4_doi_dump(doi, NLMSG_SPACE(GENL_HDRLEN)); 372*96cb8e33SPaul Moore if (ans_skb == NULL) { 373*96cb8e33SPaul Moore ret_val = -ENOMEM; 374*96cb8e33SPaul Moore goto list_failure; 375*96cb8e33SPaul Moore } 376*96cb8e33SPaul Moore netlbl_netlink_hdr_push(ans_skb, 377*96cb8e33SPaul Moore info->snd_pid, 378*96cb8e33SPaul Moore 0, 379*96cb8e33SPaul Moore netlbl_cipsov4_gnl_family.id, 380*96cb8e33SPaul Moore NLBL_CIPSOV4_C_LIST); 381*96cb8e33SPaul Moore 382*96cb8e33SPaul Moore ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid); 383*96cb8e33SPaul Moore if (ret_val != 0) 384*96cb8e33SPaul Moore goto list_failure; 385*96cb8e33SPaul Moore 386*96cb8e33SPaul Moore return 0; 387*96cb8e33SPaul Moore 388*96cb8e33SPaul Moore list_failure: 389*96cb8e33SPaul Moore netlbl_netlink_send_ack(info, 390*96cb8e33SPaul Moore netlbl_cipsov4_gnl_family.id, 391*96cb8e33SPaul Moore NLBL_CIPSOV4_C_ACK, 392*96cb8e33SPaul Moore -ret_val); 393*96cb8e33SPaul Moore return ret_val; 394*96cb8e33SPaul Moore } 395*96cb8e33SPaul Moore 396*96cb8e33SPaul Moore /** 397*96cb8e33SPaul Moore * netlbl_cipsov4_listall - Handle a LISTALL message 398*96cb8e33SPaul Moore * @skb: the NETLINK buffer 399*96cb8e33SPaul Moore * @info: the Generic NETLINK info block 400*96cb8e33SPaul Moore * 401*96cb8e33SPaul Moore * Description: 402*96cb8e33SPaul Moore * Process a user generated LISTALL message and respond accordingly. Returns 403*96cb8e33SPaul Moore * zero on success and negative values on error. 404*96cb8e33SPaul Moore * 405*96cb8e33SPaul Moore */ 406*96cb8e33SPaul Moore static int netlbl_cipsov4_listall(struct sk_buff *skb, struct genl_info *info) 407*96cb8e33SPaul Moore { 408*96cb8e33SPaul Moore int ret_val = -EINVAL; 409*96cb8e33SPaul Moore struct sk_buff *ans_skb; 410*96cb8e33SPaul Moore 411*96cb8e33SPaul Moore ans_skb = cipso_v4_doi_dump_all(NLMSG_SPACE(GENL_HDRLEN)); 412*96cb8e33SPaul Moore if (ans_skb == NULL) { 413*96cb8e33SPaul Moore ret_val = -ENOMEM; 414*96cb8e33SPaul Moore goto listall_failure; 415*96cb8e33SPaul Moore } 416*96cb8e33SPaul Moore netlbl_netlink_hdr_push(ans_skb, 417*96cb8e33SPaul Moore info->snd_pid, 418*96cb8e33SPaul Moore 0, 419*96cb8e33SPaul Moore netlbl_cipsov4_gnl_family.id, 420*96cb8e33SPaul Moore NLBL_CIPSOV4_C_LISTALL); 421*96cb8e33SPaul Moore 422*96cb8e33SPaul Moore ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid); 423*96cb8e33SPaul Moore if (ret_val != 0) 424*96cb8e33SPaul Moore goto listall_failure; 425*96cb8e33SPaul Moore 426*96cb8e33SPaul Moore return 0; 427*96cb8e33SPaul Moore 428*96cb8e33SPaul Moore listall_failure: 429*96cb8e33SPaul Moore netlbl_netlink_send_ack(info, 430*96cb8e33SPaul Moore netlbl_cipsov4_gnl_family.id, 431*96cb8e33SPaul Moore NLBL_CIPSOV4_C_ACK, 432*96cb8e33SPaul Moore -ret_val); 433*96cb8e33SPaul Moore return ret_val; 434*96cb8e33SPaul Moore } 435*96cb8e33SPaul Moore 436*96cb8e33SPaul Moore /** 437*96cb8e33SPaul Moore * netlbl_cipsov4_remove - Handle a REMOVE message 438*96cb8e33SPaul Moore * @skb: the NETLINK buffer 439*96cb8e33SPaul Moore * @info: the Generic NETLINK info block 440*96cb8e33SPaul Moore * 441*96cb8e33SPaul Moore * Description: 442*96cb8e33SPaul Moore * Process a user generated REMOVE message and respond accordingly. Returns 443*96cb8e33SPaul Moore * zero on success, negative values on failure. 444*96cb8e33SPaul Moore * 445*96cb8e33SPaul Moore */ 446*96cb8e33SPaul Moore static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info) 447*96cb8e33SPaul Moore { 448*96cb8e33SPaul Moore int ret_val; 449*96cb8e33SPaul Moore u32 doi; 450*96cb8e33SPaul Moore struct nlattr *msg = netlbl_netlink_payload_data(skb); 451*96cb8e33SPaul Moore 452*96cb8e33SPaul Moore ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN); 453*96cb8e33SPaul Moore if (ret_val != 0) 454*96cb8e33SPaul Moore goto remove_return; 455*96cb8e33SPaul Moore 456*96cb8e33SPaul Moore if (netlbl_netlink_payload_len(skb) != NETLBL_LEN_U32) { 457*96cb8e33SPaul Moore ret_val = -EINVAL; 458*96cb8e33SPaul Moore goto remove_return; 459*96cb8e33SPaul Moore } 460*96cb8e33SPaul Moore 461*96cb8e33SPaul Moore doi = nla_get_u32(msg); 462*96cb8e33SPaul Moore ret_val = cipso_v4_doi_remove(doi, netlbl_cipsov4_doi_free); 463*96cb8e33SPaul Moore 464*96cb8e33SPaul Moore remove_return: 465*96cb8e33SPaul Moore netlbl_netlink_send_ack(info, 466*96cb8e33SPaul Moore netlbl_cipsov4_gnl_family.id, 467*96cb8e33SPaul Moore NLBL_CIPSOV4_C_ACK, 468*96cb8e33SPaul Moore -ret_val); 469*96cb8e33SPaul Moore return ret_val; 470*96cb8e33SPaul Moore } 471*96cb8e33SPaul Moore 472*96cb8e33SPaul Moore /* 473*96cb8e33SPaul Moore * NetLabel Generic NETLINK Command Definitions 474*96cb8e33SPaul Moore */ 475*96cb8e33SPaul Moore 476*96cb8e33SPaul Moore static struct genl_ops netlbl_cipsov4_genl_c_add = { 477*96cb8e33SPaul Moore .cmd = NLBL_CIPSOV4_C_ADD, 478*96cb8e33SPaul Moore .flags = 0, 479*96cb8e33SPaul Moore .doit = netlbl_cipsov4_add, 480*96cb8e33SPaul Moore .dumpit = NULL, 481*96cb8e33SPaul Moore }; 482*96cb8e33SPaul Moore 483*96cb8e33SPaul Moore static struct genl_ops netlbl_cipsov4_genl_c_remove = { 484*96cb8e33SPaul Moore .cmd = NLBL_CIPSOV4_C_REMOVE, 485*96cb8e33SPaul Moore .flags = 0, 486*96cb8e33SPaul Moore .doit = netlbl_cipsov4_remove, 487*96cb8e33SPaul Moore .dumpit = NULL, 488*96cb8e33SPaul Moore }; 489*96cb8e33SPaul Moore 490*96cb8e33SPaul Moore static struct genl_ops netlbl_cipsov4_genl_c_list = { 491*96cb8e33SPaul Moore .cmd = NLBL_CIPSOV4_C_LIST, 492*96cb8e33SPaul Moore .flags = 0, 493*96cb8e33SPaul Moore .doit = netlbl_cipsov4_list, 494*96cb8e33SPaul Moore .dumpit = NULL, 495*96cb8e33SPaul Moore }; 496*96cb8e33SPaul Moore 497*96cb8e33SPaul Moore static struct genl_ops netlbl_cipsov4_genl_c_listall = { 498*96cb8e33SPaul Moore .cmd = NLBL_CIPSOV4_C_LISTALL, 499*96cb8e33SPaul Moore .flags = 0, 500*96cb8e33SPaul Moore .doit = netlbl_cipsov4_listall, 501*96cb8e33SPaul Moore .dumpit = NULL, 502*96cb8e33SPaul Moore }; 503*96cb8e33SPaul Moore 504*96cb8e33SPaul Moore /* 505*96cb8e33SPaul Moore * NetLabel Generic NETLINK Protocol Functions 506*96cb8e33SPaul Moore */ 507*96cb8e33SPaul Moore 508*96cb8e33SPaul Moore /** 509*96cb8e33SPaul Moore * netlbl_cipsov4_genl_init - Register the CIPSOv4 NetLabel component 510*96cb8e33SPaul Moore * 511*96cb8e33SPaul Moore * Description: 512*96cb8e33SPaul Moore * Register the CIPSOv4 packet NetLabel component with the Generic NETLINK 513*96cb8e33SPaul Moore * mechanism. Returns zero on success, negative values on failure. 514*96cb8e33SPaul Moore * 515*96cb8e33SPaul Moore */ 516*96cb8e33SPaul Moore int netlbl_cipsov4_genl_init(void) 517*96cb8e33SPaul Moore { 518*96cb8e33SPaul Moore int ret_val; 519*96cb8e33SPaul Moore 520*96cb8e33SPaul Moore ret_val = genl_register_family(&netlbl_cipsov4_gnl_family); 521*96cb8e33SPaul Moore if (ret_val != 0) 522*96cb8e33SPaul Moore return ret_val; 523*96cb8e33SPaul Moore 524*96cb8e33SPaul Moore ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family, 525*96cb8e33SPaul Moore &netlbl_cipsov4_genl_c_add); 526*96cb8e33SPaul Moore if (ret_val != 0) 527*96cb8e33SPaul Moore return ret_val; 528*96cb8e33SPaul Moore ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family, 529*96cb8e33SPaul Moore &netlbl_cipsov4_genl_c_remove); 530*96cb8e33SPaul Moore if (ret_val != 0) 531*96cb8e33SPaul Moore return ret_val; 532*96cb8e33SPaul Moore ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family, 533*96cb8e33SPaul Moore &netlbl_cipsov4_genl_c_list); 534*96cb8e33SPaul Moore if (ret_val != 0) 535*96cb8e33SPaul Moore return ret_val; 536*96cb8e33SPaul Moore ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family, 537*96cb8e33SPaul Moore &netlbl_cipsov4_genl_c_listall); 538*96cb8e33SPaul Moore if (ret_val != 0) 539*96cb8e33SPaul Moore return ret_val; 540*96cb8e33SPaul Moore 541*96cb8e33SPaul Moore return 0; 542*96cb8e33SPaul Moore } 543