1d15c345fSPaul Moore /* 2d15c345fSPaul Moore * NetLabel Management Support 3d15c345fSPaul Moore * 4d15c345fSPaul Moore * This file defines the management functions for the NetLabel system. The 5d15c345fSPaul Moore * NetLabel system manages static and dynamic label mappings for network 6d15c345fSPaul Moore * protocols such as CIPSO and RIPSO. 7d15c345fSPaul Moore * 8d15c345fSPaul Moore * Author: Paul Moore <paul.moore@hp.com> 9d15c345fSPaul Moore * 10d15c345fSPaul Moore */ 11d15c345fSPaul Moore 12d15c345fSPaul Moore /* 13d15c345fSPaul Moore * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 14d15c345fSPaul Moore * 15d15c345fSPaul Moore * This program is free software; you can redistribute it and/or modify 16d15c345fSPaul Moore * it under the terms of the GNU General Public License as published by 17d15c345fSPaul Moore * the Free Software Foundation; either version 2 of the License, or 18d15c345fSPaul Moore * (at your option) any later version. 19d15c345fSPaul Moore * 20d15c345fSPaul Moore * This program is distributed in the hope that it will be useful, 21d15c345fSPaul Moore * but WITHOUT ANY WARRANTY; without even the implied warranty of 22d15c345fSPaul Moore * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 23d15c345fSPaul Moore * the GNU General Public License for more details. 24d15c345fSPaul Moore * 25d15c345fSPaul Moore * You should have received a copy of the GNU General Public License 26d15c345fSPaul Moore * along with this program; if not, write to the Free Software 27d15c345fSPaul Moore * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 28d15c345fSPaul Moore * 29d15c345fSPaul Moore */ 30d15c345fSPaul Moore 31d15c345fSPaul Moore #include <linux/types.h> 32d15c345fSPaul Moore #include <linux/socket.h> 33d15c345fSPaul Moore #include <linux/string.h> 34d15c345fSPaul Moore #include <linux/skbuff.h> 35d15c345fSPaul Moore #include <net/sock.h> 36d15c345fSPaul Moore #include <net/netlink.h> 37d15c345fSPaul Moore #include <net/genetlink.h> 38d15c345fSPaul Moore #include <net/netlabel.h> 39d15c345fSPaul Moore #include <net/cipso_ipv4.h> 40d15c345fSPaul Moore 41d15c345fSPaul Moore #include "netlabel_domainhash.h" 42d15c345fSPaul Moore #include "netlabel_user.h" 43d15c345fSPaul Moore #include "netlabel_mgmt.h" 44d15c345fSPaul Moore 4523bcdc1aSPaul Moore /* NetLabel configured protocol count */ 4623bcdc1aSPaul Moore static DEFINE_SPINLOCK(netlabel_mgmt_protocount_lock); 4723bcdc1aSPaul Moore static u32 netlabel_mgmt_protocount = 0; 4823bcdc1aSPaul Moore 49fd385855SPaul Moore /* Argument struct for netlbl_domhsh_walk() */ 50fd385855SPaul Moore struct netlbl_domhsh_walk_arg { 51fd385855SPaul Moore struct netlink_callback *nl_cb; 52fd385855SPaul Moore struct sk_buff *skb; 53fd385855SPaul Moore u32 seq; 54fd385855SPaul Moore }; 55fd385855SPaul Moore 56d15c345fSPaul Moore /* NetLabel Generic NETLINK CIPSOv4 family */ 57d15c345fSPaul Moore static struct genl_family netlbl_mgmt_gnl_family = { 58d15c345fSPaul Moore .id = GENL_ID_GENERATE, 59d15c345fSPaul Moore .hdrsize = 0, 60d15c345fSPaul Moore .name = NETLBL_NLTYPE_MGMT_NAME, 61d15c345fSPaul Moore .version = NETLBL_PROTO_VERSION, 62fd385855SPaul Moore .maxattr = NLBL_MGMT_A_MAX, 63d15c345fSPaul Moore }; 64d15c345fSPaul Moore 65fd385855SPaul Moore /* NetLabel Netlink attribute policy */ 66ef7c79edSPatrick McHardy static const struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = { 67fd385855SPaul Moore [NLBL_MGMT_A_DOMAIN] = { .type = NLA_NUL_STRING }, 68fd385855SPaul Moore [NLBL_MGMT_A_PROTOCOL] = { .type = NLA_U32 }, 69fd385855SPaul Moore [NLBL_MGMT_A_VERSION] = { .type = NLA_U32 }, 70fd385855SPaul Moore [NLBL_MGMT_A_CV4DOI] = { .type = NLA_U32 }, 71fd385855SPaul Moore }; 72d15c345fSPaul Moore 73d15c345fSPaul Moore /* 7423bcdc1aSPaul Moore * NetLabel Misc Managment Functions 7523bcdc1aSPaul Moore */ 7623bcdc1aSPaul Moore 7723bcdc1aSPaul Moore /** 7823bcdc1aSPaul Moore * netlbl_mgmt_protocount_inc - Increment the configured labeled protocol count 7923bcdc1aSPaul Moore * 8023bcdc1aSPaul Moore * Description: 8123bcdc1aSPaul Moore * Increment the number of labeled protocol configurations in the current 8223bcdc1aSPaul Moore * NetLabel configuration. Keep track of this for use in determining if 8323bcdc1aSPaul Moore * NetLabel label enforcement should be active/enabled or not in the LSM. 8423bcdc1aSPaul Moore * 8523bcdc1aSPaul Moore */ 8623bcdc1aSPaul Moore void netlbl_mgmt_protocount_inc(void) 8723bcdc1aSPaul Moore { 8823bcdc1aSPaul Moore rcu_read_lock(); 8923bcdc1aSPaul Moore spin_lock(&netlabel_mgmt_protocount_lock); 9023bcdc1aSPaul Moore netlabel_mgmt_protocount++; 9123bcdc1aSPaul Moore spin_unlock(&netlabel_mgmt_protocount_lock); 9223bcdc1aSPaul Moore rcu_read_unlock(); 9323bcdc1aSPaul Moore } 9423bcdc1aSPaul Moore 9523bcdc1aSPaul Moore /** 9623bcdc1aSPaul Moore * netlbl_mgmt_protocount_dec - Decrement the configured labeled protocol count 9723bcdc1aSPaul Moore * 9823bcdc1aSPaul Moore * Description: 9923bcdc1aSPaul Moore * Decrement the number of labeled protocol configurations in the current 10023bcdc1aSPaul Moore * NetLabel configuration. Keep track of this for use in determining if 10123bcdc1aSPaul Moore * NetLabel label enforcement should be active/enabled or not in the LSM. 10223bcdc1aSPaul Moore * 10323bcdc1aSPaul Moore */ 10423bcdc1aSPaul Moore void netlbl_mgmt_protocount_dec(void) 10523bcdc1aSPaul Moore { 10623bcdc1aSPaul Moore rcu_read_lock(); 10723bcdc1aSPaul Moore spin_lock(&netlabel_mgmt_protocount_lock); 10823bcdc1aSPaul Moore if (netlabel_mgmt_protocount > 0) 10923bcdc1aSPaul Moore netlabel_mgmt_protocount--; 11023bcdc1aSPaul Moore spin_unlock(&netlabel_mgmt_protocount_lock); 11123bcdc1aSPaul Moore rcu_read_unlock(); 11223bcdc1aSPaul Moore } 11323bcdc1aSPaul Moore 11423bcdc1aSPaul Moore /** 11523bcdc1aSPaul Moore * netlbl_mgmt_protocount_value - Return the number of configured protocols 11623bcdc1aSPaul Moore * 11723bcdc1aSPaul Moore * Description: 11823bcdc1aSPaul Moore * Return the number of labeled protocols in the current NetLabel 11923bcdc1aSPaul Moore * configuration. This value is useful in determining if NetLabel label 12023bcdc1aSPaul Moore * enforcement should be active/enabled or not in the LSM. 12123bcdc1aSPaul Moore * 12223bcdc1aSPaul Moore */ 12323bcdc1aSPaul Moore u32 netlbl_mgmt_protocount_value(void) 12423bcdc1aSPaul Moore { 12523bcdc1aSPaul Moore u32 val; 12623bcdc1aSPaul Moore 12723bcdc1aSPaul Moore rcu_read_lock(); 12823bcdc1aSPaul Moore val = netlabel_mgmt_protocount; 12923bcdc1aSPaul Moore rcu_read_unlock(); 13023bcdc1aSPaul Moore 13123bcdc1aSPaul Moore return val; 13223bcdc1aSPaul Moore } 13323bcdc1aSPaul Moore 13423bcdc1aSPaul Moore /* 135d15c345fSPaul Moore * NetLabel Command Handlers 136d15c345fSPaul Moore */ 137d15c345fSPaul Moore 138d15c345fSPaul Moore /** 139d15c345fSPaul Moore * netlbl_mgmt_add - Handle an ADD message 140d15c345fSPaul Moore * @skb: the NETLINK buffer 141d15c345fSPaul Moore * @info: the Generic NETLINK info block 142d15c345fSPaul Moore * 143d15c345fSPaul Moore * Description: 144d15c345fSPaul Moore * Process a user generated ADD message and add the domains from the message 145d15c345fSPaul Moore * to the hash table. See netlabel.h for a description of the message format. 146d15c345fSPaul Moore * Returns zero on success, negative values on failure. 147d15c345fSPaul Moore * 148d15c345fSPaul Moore */ 149d15c345fSPaul Moore static int netlbl_mgmt_add(struct sk_buff *skb, struct genl_info *info) 150d15c345fSPaul Moore { 151d15c345fSPaul Moore int ret_val = -EINVAL; 152d15c345fSPaul Moore struct netlbl_dom_map *entry = NULL; 153fd385855SPaul Moore size_t tmp_size; 154d15c345fSPaul Moore u32 tmp_val; 15595d4e6beSPaul Moore struct netlbl_audit audit_info; 156d15c345fSPaul Moore 157fd385855SPaul Moore if (!info->attrs[NLBL_MGMT_A_DOMAIN] || 158fd385855SPaul Moore !info->attrs[NLBL_MGMT_A_PROTOCOL]) 159d15c345fSPaul Moore goto add_failure; 160d15c345fSPaul Moore 16195d4e6beSPaul Moore netlbl_netlink_auditinfo(skb, &audit_info); 16295d4e6beSPaul Moore 163d15c345fSPaul Moore entry = kzalloc(sizeof(*entry), GFP_KERNEL); 164d15c345fSPaul Moore if (entry == NULL) { 165d15c345fSPaul Moore ret_val = -ENOMEM; 166d15c345fSPaul Moore goto add_failure; 167d15c345fSPaul Moore } 168fd385855SPaul Moore tmp_size = nla_len(info->attrs[NLBL_MGMT_A_DOMAIN]); 169d15c345fSPaul Moore entry->domain = kmalloc(tmp_size, GFP_KERNEL); 170d15c345fSPaul Moore if (entry->domain == NULL) { 171d15c345fSPaul Moore ret_val = -ENOMEM; 172d15c345fSPaul Moore goto add_failure; 173d15c345fSPaul Moore } 174fd385855SPaul Moore entry->type = nla_get_u32(info->attrs[NLBL_MGMT_A_PROTOCOL]); 175fd385855SPaul Moore nla_strlcpy(entry->domain, info->attrs[NLBL_MGMT_A_DOMAIN], tmp_size); 176d15c345fSPaul Moore 177fd385855SPaul Moore switch (entry->type) { 178d15c345fSPaul Moore case NETLBL_NLTYPE_UNLABELED: 17995d4e6beSPaul Moore ret_val = netlbl_domhsh_add(entry, &audit_info); 180d15c345fSPaul Moore break; 181d15c345fSPaul Moore case NETLBL_NLTYPE_CIPSOV4: 182fd385855SPaul Moore if (!info->attrs[NLBL_MGMT_A_CV4DOI]) 183d15c345fSPaul Moore goto add_failure; 184fd385855SPaul Moore 185fd385855SPaul Moore tmp_val = nla_get_u32(info->attrs[NLBL_MGMT_A_CV4DOI]); 186fd385855SPaul Moore /* We should be holding a rcu_read_lock() here while we hold 187fd385855SPaul Moore * the result but since the entry will always be deleted when 188fd385855SPaul Moore * the CIPSO DOI is deleted we aren't going to keep the 189fd385855SPaul Moore * lock. */ 190d15c345fSPaul Moore rcu_read_lock(); 191d15c345fSPaul Moore entry->type_def.cipsov4 = cipso_v4_doi_getdef(tmp_val); 192d15c345fSPaul Moore if (entry->type_def.cipsov4 == NULL) { 193d15c345fSPaul Moore rcu_read_unlock(); 194d15c345fSPaul Moore goto add_failure; 195d15c345fSPaul Moore } 19695d4e6beSPaul Moore ret_val = netlbl_domhsh_add(entry, &audit_info); 197d15c345fSPaul Moore rcu_read_unlock(); 198d15c345fSPaul Moore break; 199d15c345fSPaul Moore default: 200fd385855SPaul Moore goto add_failure; 201d15c345fSPaul Moore } 202d15c345fSPaul Moore if (ret_val != 0) 203d15c345fSPaul Moore goto add_failure; 204d15c345fSPaul Moore 205d15c345fSPaul Moore return 0; 206d15c345fSPaul Moore 207d15c345fSPaul Moore add_failure: 208d15c345fSPaul Moore if (entry) 209d15c345fSPaul Moore kfree(entry->domain); 210d15c345fSPaul Moore kfree(entry); 211d15c345fSPaul Moore return ret_val; 212d15c345fSPaul Moore } 213d15c345fSPaul Moore 214d15c345fSPaul Moore /** 215d15c345fSPaul Moore * netlbl_mgmt_remove - Handle a REMOVE message 216d15c345fSPaul Moore * @skb: the NETLINK buffer 217d15c345fSPaul Moore * @info: the Generic NETLINK info block 218d15c345fSPaul Moore * 219d15c345fSPaul Moore * Description: 220d15c345fSPaul Moore * Process a user generated REMOVE message and remove the specified domain 221d15c345fSPaul Moore * mappings. Returns zero on success, negative values on failure. 222d15c345fSPaul Moore * 223d15c345fSPaul Moore */ 224d15c345fSPaul Moore static int netlbl_mgmt_remove(struct sk_buff *skb, struct genl_info *info) 225d15c345fSPaul Moore { 226fd385855SPaul Moore char *domain; 22795d4e6beSPaul Moore struct netlbl_audit audit_info; 228d15c345fSPaul Moore 229fd385855SPaul Moore if (!info->attrs[NLBL_MGMT_A_DOMAIN]) 230fd385855SPaul Moore return -EINVAL; 231d15c345fSPaul Moore 23295d4e6beSPaul Moore netlbl_netlink_auditinfo(skb, &audit_info); 23395d4e6beSPaul Moore 234fd385855SPaul Moore domain = nla_data(info->attrs[NLBL_MGMT_A_DOMAIN]); 23595d4e6beSPaul Moore return netlbl_domhsh_remove(domain, &audit_info); 236d15c345fSPaul Moore } 237d15c345fSPaul Moore 238fd385855SPaul Moore /** 239fd385855SPaul Moore * netlbl_mgmt_listall_cb - netlbl_domhsh_walk() callback for LISTALL 240fd385855SPaul Moore * @entry: the domain mapping hash table entry 241fd385855SPaul Moore * @arg: the netlbl_domhsh_walk_arg structure 242fd385855SPaul Moore * 243fd385855SPaul Moore * Description: 244fd385855SPaul Moore * This function is designed to be used as a callback to the 245fd385855SPaul Moore * netlbl_domhsh_walk() function for use in generating a response for a LISTALL 246fd385855SPaul Moore * message. Returns the size of the message on success, negative values on 247fd385855SPaul Moore * failure. 248fd385855SPaul Moore * 249fd385855SPaul Moore */ 250fd385855SPaul Moore static int netlbl_mgmt_listall_cb(struct netlbl_dom_map *entry, void *arg) 251fd385855SPaul Moore { 252fd385855SPaul Moore int ret_val = -ENOMEM; 253fd385855SPaul Moore struct netlbl_domhsh_walk_arg *cb_arg = arg; 254fd385855SPaul Moore void *data; 255d15c345fSPaul Moore 25617c157c8SThomas Graf data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).pid, 25717c157c8SThomas Graf cb_arg->seq, &netlbl_mgmt_gnl_family, 25817c157c8SThomas Graf NLM_F_MULTI, NLBL_MGMT_C_LISTALL); 259fd385855SPaul Moore if (data == NULL) 260fd385855SPaul Moore goto listall_cb_failure; 261fd385855SPaul Moore 262fd385855SPaul Moore ret_val = nla_put_string(cb_arg->skb, 263fd385855SPaul Moore NLBL_MGMT_A_DOMAIN, 264fd385855SPaul Moore entry->domain); 265fd385855SPaul Moore if (ret_val != 0) 266fd385855SPaul Moore goto listall_cb_failure; 267fd385855SPaul Moore ret_val = nla_put_u32(cb_arg->skb, NLBL_MGMT_A_PROTOCOL, entry->type); 268fd385855SPaul Moore if (ret_val != 0) 269fd385855SPaul Moore goto listall_cb_failure; 270fd385855SPaul Moore switch (entry->type) { 271fd385855SPaul Moore case NETLBL_NLTYPE_CIPSOV4: 272fd385855SPaul Moore ret_val = nla_put_u32(cb_arg->skb, 273fd385855SPaul Moore NLBL_MGMT_A_CV4DOI, 274fd385855SPaul Moore entry->type_def.cipsov4->doi); 275fd385855SPaul Moore if (ret_val != 0) 276fd385855SPaul Moore goto listall_cb_failure; 277fd385855SPaul Moore break; 278fd385855SPaul Moore } 279fd385855SPaul Moore 280fd385855SPaul Moore cb_arg->seq++; 281fd385855SPaul Moore return genlmsg_end(cb_arg->skb, data); 282fd385855SPaul Moore 283fd385855SPaul Moore listall_cb_failure: 284fd385855SPaul Moore genlmsg_cancel(cb_arg->skb, data); 285d15c345fSPaul Moore return ret_val; 286d15c345fSPaul Moore } 287d15c345fSPaul Moore 288d15c345fSPaul Moore /** 289fd385855SPaul Moore * netlbl_mgmt_listall - Handle a LISTALL message 290d15c345fSPaul Moore * @skb: the NETLINK buffer 291fd385855SPaul Moore * @cb: the NETLINK callback 292d15c345fSPaul Moore * 293d15c345fSPaul Moore * Description: 294fd385855SPaul Moore * Process a user generated LISTALL message and dumps the domain hash table in 295fd385855SPaul Moore * a form suitable for use in a kernel generated LISTALL message. Returns zero 296fd385855SPaul Moore * on success, negative values on failure. 297d15c345fSPaul Moore * 298d15c345fSPaul Moore */ 299fd385855SPaul Moore static int netlbl_mgmt_listall(struct sk_buff *skb, 300fd385855SPaul Moore struct netlink_callback *cb) 301d15c345fSPaul Moore { 302fd385855SPaul Moore struct netlbl_domhsh_walk_arg cb_arg; 303fd385855SPaul Moore u32 skip_bkt = cb->args[0]; 304fd385855SPaul Moore u32 skip_chain = cb->args[1]; 305d15c345fSPaul Moore 306fd385855SPaul Moore cb_arg.nl_cb = cb; 307fd385855SPaul Moore cb_arg.skb = skb; 308fd385855SPaul Moore cb_arg.seq = cb->nlh->nlmsg_seq; 309d15c345fSPaul Moore 310fd385855SPaul Moore netlbl_domhsh_walk(&skip_bkt, 311fd385855SPaul Moore &skip_chain, 312fd385855SPaul Moore netlbl_mgmt_listall_cb, 313fd385855SPaul Moore &cb_arg); 314d15c345fSPaul Moore 315fd385855SPaul Moore cb->args[0] = skip_bkt; 316fd385855SPaul Moore cb->args[1] = skip_chain; 317fd385855SPaul Moore return skb->len; 318d15c345fSPaul Moore } 319d15c345fSPaul Moore 320d15c345fSPaul Moore /** 321d15c345fSPaul Moore * netlbl_mgmt_adddef - Handle an ADDDEF message 322d15c345fSPaul Moore * @skb: the NETLINK buffer 323d15c345fSPaul Moore * @info: the Generic NETLINK info block 324d15c345fSPaul Moore * 325d15c345fSPaul Moore * Description: 326d15c345fSPaul Moore * Process a user generated ADDDEF message and respond accordingly. Returns 327d15c345fSPaul Moore * zero on success, negative values on failure. 328d15c345fSPaul Moore * 329d15c345fSPaul Moore */ 330d15c345fSPaul Moore static int netlbl_mgmt_adddef(struct sk_buff *skb, struct genl_info *info) 331d15c345fSPaul Moore { 332d15c345fSPaul Moore int ret_val = -EINVAL; 333d15c345fSPaul Moore struct netlbl_dom_map *entry = NULL; 334d15c345fSPaul Moore u32 tmp_val; 33595d4e6beSPaul Moore struct netlbl_audit audit_info; 336d15c345fSPaul Moore 337fd385855SPaul Moore if (!info->attrs[NLBL_MGMT_A_PROTOCOL]) 338d15c345fSPaul Moore goto adddef_failure; 339d15c345fSPaul Moore 34095d4e6beSPaul Moore netlbl_netlink_auditinfo(skb, &audit_info); 34195d4e6beSPaul Moore 342d15c345fSPaul Moore entry = kzalloc(sizeof(*entry), GFP_KERNEL); 343d15c345fSPaul Moore if (entry == NULL) { 344d15c345fSPaul Moore ret_val = -ENOMEM; 345d15c345fSPaul Moore goto adddef_failure; 346d15c345fSPaul Moore } 347fd385855SPaul Moore entry->type = nla_get_u32(info->attrs[NLBL_MGMT_A_PROTOCOL]); 348d15c345fSPaul Moore 349d15c345fSPaul Moore switch (entry->type) { 350d15c345fSPaul Moore case NETLBL_NLTYPE_UNLABELED: 35195d4e6beSPaul Moore ret_val = netlbl_domhsh_add_default(entry, &audit_info); 352d15c345fSPaul Moore break; 353d15c345fSPaul Moore case NETLBL_NLTYPE_CIPSOV4: 354fd385855SPaul Moore if (!info->attrs[NLBL_MGMT_A_CV4DOI]) 355d15c345fSPaul Moore goto adddef_failure; 356fd385855SPaul Moore 357fd385855SPaul Moore tmp_val = nla_get_u32(info->attrs[NLBL_MGMT_A_CV4DOI]); 358fd385855SPaul Moore /* We should be holding a rcu_read_lock() here while we hold 359fd385855SPaul Moore * the result but since the entry will always be deleted when 360fd385855SPaul Moore * the CIPSO DOI is deleted we aren't going to keep the 361fd385855SPaul Moore * lock. */ 362d15c345fSPaul Moore rcu_read_lock(); 363d15c345fSPaul Moore entry->type_def.cipsov4 = cipso_v4_doi_getdef(tmp_val); 364d15c345fSPaul Moore if (entry->type_def.cipsov4 == NULL) { 365d15c345fSPaul Moore rcu_read_unlock(); 366d15c345fSPaul Moore goto adddef_failure; 367d15c345fSPaul Moore } 36895d4e6beSPaul Moore ret_val = netlbl_domhsh_add_default(entry, &audit_info); 369d15c345fSPaul Moore rcu_read_unlock(); 370d15c345fSPaul Moore break; 371d15c345fSPaul Moore default: 372fd385855SPaul Moore goto adddef_failure; 373d15c345fSPaul Moore } 374d15c345fSPaul Moore if (ret_val != 0) 375d15c345fSPaul Moore goto adddef_failure; 376d15c345fSPaul Moore 377d15c345fSPaul Moore return 0; 378d15c345fSPaul Moore 379d15c345fSPaul Moore adddef_failure: 380d15c345fSPaul Moore kfree(entry); 381d15c345fSPaul Moore return ret_val; 382d15c345fSPaul Moore } 383d15c345fSPaul Moore 384d15c345fSPaul Moore /** 385d15c345fSPaul Moore * netlbl_mgmt_removedef - Handle a REMOVEDEF message 386d15c345fSPaul Moore * @skb: the NETLINK buffer 387d15c345fSPaul Moore * @info: the Generic NETLINK info block 388d15c345fSPaul Moore * 389d15c345fSPaul Moore * Description: 390d15c345fSPaul Moore * Process a user generated REMOVEDEF message and remove the default domain 391d15c345fSPaul Moore * mapping. Returns zero on success, negative values on failure. 392d15c345fSPaul Moore * 393d15c345fSPaul Moore */ 394d15c345fSPaul Moore static int netlbl_mgmt_removedef(struct sk_buff *skb, struct genl_info *info) 395d15c345fSPaul Moore { 39695d4e6beSPaul Moore struct netlbl_audit audit_info; 39795d4e6beSPaul Moore 39895d4e6beSPaul Moore netlbl_netlink_auditinfo(skb, &audit_info); 39995d4e6beSPaul Moore 40095d4e6beSPaul Moore return netlbl_domhsh_remove_default(&audit_info); 401d15c345fSPaul Moore } 402d15c345fSPaul Moore 403d15c345fSPaul Moore /** 404d15c345fSPaul Moore * netlbl_mgmt_listdef - Handle a LISTDEF message 405d15c345fSPaul Moore * @skb: the NETLINK buffer 406d15c345fSPaul Moore * @info: the Generic NETLINK info block 407d15c345fSPaul Moore * 408d15c345fSPaul Moore * Description: 409d15c345fSPaul Moore * Process a user generated LISTDEF message and dumps the default domain 410d15c345fSPaul Moore * mapping in a form suitable for use in a kernel generated LISTDEF message. 411d15c345fSPaul Moore * Returns zero on success, negative values on failure. 412d15c345fSPaul Moore * 413d15c345fSPaul Moore */ 414d15c345fSPaul Moore static int netlbl_mgmt_listdef(struct sk_buff *skb, struct genl_info *info) 415d15c345fSPaul Moore { 416d15c345fSPaul Moore int ret_val = -ENOMEM; 417fd385855SPaul Moore struct sk_buff *ans_skb = NULL; 418fd385855SPaul Moore void *data; 419fd385855SPaul Moore struct netlbl_dom_map *entry; 420d15c345fSPaul Moore 421339bf98fSThomas Graf ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 422d15c345fSPaul Moore if (ans_skb == NULL) 423fd385855SPaul Moore return -ENOMEM; 42417c157c8SThomas Graf data = genlmsg_put_reply(ans_skb, info, &netlbl_mgmt_gnl_family, 42517c157c8SThomas Graf 0, NLBL_MGMT_C_LISTDEF); 426fd385855SPaul Moore if (data == NULL) 427fd385855SPaul Moore goto listdef_failure; 428d15c345fSPaul Moore 429fd385855SPaul Moore rcu_read_lock(); 430fd385855SPaul Moore entry = netlbl_domhsh_getentry(NULL); 431fd385855SPaul Moore if (entry == NULL) { 432fd385855SPaul Moore ret_val = -ENOENT; 433fd385855SPaul Moore goto listdef_failure_lock; 434fd385855SPaul Moore } 435fd385855SPaul Moore ret_val = nla_put_u32(ans_skb, NLBL_MGMT_A_PROTOCOL, entry->type); 436fd385855SPaul Moore if (ret_val != 0) 437fd385855SPaul Moore goto listdef_failure_lock; 438fd385855SPaul Moore switch (entry->type) { 439fd385855SPaul Moore case NETLBL_NLTYPE_CIPSOV4: 440fd385855SPaul Moore ret_val = nla_put_u32(ans_skb, 441fd385855SPaul Moore NLBL_MGMT_A_CV4DOI, 442fd385855SPaul Moore entry->type_def.cipsov4->doi); 443fd385855SPaul Moore if (ret_val != 0) 444fd385855SPaul Moore goto listdef_failure_lock; 445fd385855SPaul Moore break; 446fd385855SPaul Moore } 447fd385855SPaul Moore rcu_read_unlock(); 448fd385855SPaul Moore 449fd385855SPaul Moore genlmsg_end(ans_skb, data); 450fd385855SPaul Moore 45181878d27SThomas Graf ret_val = genlmsg_reply(ans_skb, info); 452d15c345fSPaul Moore if (ret_val != 0) 453d15c345fSPaul Moore goto listdef_failure; 454d15c345fSPaul Moore return 0; 455d15c345fSPaul Moore 456fd385855SPaul Moore listdef_failure_lock: 457fd385855SPaul Moore rcu_read_unlock(); 458d15c345fSPaul Moore listdef_failure: 459fd385855SPaul Moore kfree_skb(ans_skb); 460d15c345fSPaul Moore return ret_val; 461d15c345fSPaul Moore } 462d15c345fSPaul Moore 463d15c345fSPaul Moore /** 464fd385855SPaul Moore * netlbl_mgmt_protocols_cb - Write an individual PROTOCOL message response 465fd385855SPaul Moore * @skb: the skb to write to 466fd385855SPaul Moore * @seq: the NETLINK sequence number 467fd385855SPaul Moore * @cb: the NETLINK callback 468fd385855SPaul Moore * @protocol: the NetLabel protocol to use in the message 469d15c345fSPaul Moore * 470d15c345fSPaul Moore * Description: 471fd385855SPaul Moore * This function is to be used in conjunction with netlbl_mgmt_protocols() to 472fd385855SPaul Moore * answer a application's PROTOCOLS message. Returns the size of the message 473fd385855SPaul Moore * on success, negative values on failure. 474d15c345fSPaul Moore * 475d15c345fSPaul Moore */ 476fd385855SPaul Moore static int netlbl_mgmt_protocols_cb(struct sk_buff *skb, 477fd385855SPaul Moore struct netlink_callback *cb, 478fd385855SPaul Moore u32 protocol) 479d15c345fSPaul Moore { 480d15c345fSPaul Moore int ret_val = -ENOMEM; 481fd385855SPaul Moore void *data; 482d15c345fSPaul Moore 48317c157c8SThomas Graf data = genlmsg_put(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, 48417c157c8SThomas Graf &netlbl_mgmt_gnl_family, NLM_F_MULTI, 485fd385855SPaul Moore NLBL_MGMT_C_PROTOCOLS); 486fd385855SPaul Moore if (data == NULL) 487fd385855SPaul Moore goto protocols_cb_failure; 488d15c345fSPaul Moore 489fd385855SPaul Moore ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL, protocol); 490d15c345fSPaul Moore if (ret_val != 0) 491fd385855SPaul Moore goto protocols_cb_failure; 492d15c345fSPaul Moore 493fd385855SPaul Moore return genlmsg_end(skb, data); 494d15c345fSPaul Moore 495fd385855SPaul Moore protocols_cb_failure: 496fd385855SPaul Moore genlmsg_cancel(skb, data); 497d15c345fSPaul Moore return ret_val; 498d15c345fSPaul Moore } 499d15c345fSPaul Moore 500d15c345fSPaul Moore /** 501fd385855SPaul Moore * netlbl_mgmt_protocols - Handle a PROTOCOLS message 502fd385855SPaul Moore * @skb: the NETLINK buffer 503fd385855SPaul Moore * @cb: the NETLINK callback 504fd385855SPaul Moore * 505fd385855SPaul Moore * Description: 506fd385855SPaul Moore * Process a user generated PROTOCOLS message and respond accordingly. 507fd385855SPaul Moore * 508fd385855SPaul Moore */ 509fd385855SPaul Moore static int netlbl_mgmt_protocols(struct sk_buff *skb, 510fd385855SPaul Moore struct netlink_callback *cb) 511fd385855SPaul Moore { 512fd385855SPaul Moore u32 protos_sent = cb->args[0]; 513fd385855SPaul Moore 514fd385855SPaul Moore if (protos_sent == 0) { 515fd385855SPaul Moore if (netlbl_mgmt_protocols_cb(skb, 516fd385855SPaul Moore cb, 517fd385855SPaul Moore NETLBL_NLTYPE_UNLABELED) < 0) 518fd385855SPaul Moore goto protocols_return; 519fd385855SPaul Moore protos_sent++; 520fd385855SPaul Moore } 521fd385855SPaul Moore if (protos_sent == 1) { 522fd385855SPaul Moore if (netlbl_mgmt_protocols_cb(skb, 523fd385855SPaul Moore cb, 524fd385855SPaul Moore NETLBL_NLTYPE_CIPSOV4) < 0) 525fd385855SPaul Moore goto protocols_return; 526fd385855SPaul Moore protos_sent++; 527fd385855SPaul Moore } 528fd385855SPaul Moore 529fd385855SPaul Moore protocols_return: 530fd385855SPaul Moore cb->args[0] = protos_sent; 531fd385855SPaul Moore return skb->len; 532fd385855SPaul Moore } 533fd385855SPaul Moore 534fd385855SPaul Moore /** 535d15c345fSPaul Moore * netlbl_mgmt_version - Handle a VERSION message 536d15c345fSPaul Moore * @skb: the NETLINK buffer 537d15c345fSPaul Moore * @info: the Generic NETLINK info block 538d15c345fSPaul Moore * 539d15c345fSPaul Moore * Description: 540d15c345fSPaul Moore * Process a user generated VERSION message and respond accordingly. Returns 541d15c345fSPaul Moore * zero on success, negative values on failure. 542d15c345fSPaul Moore * 543d15c345fSPaul Moore */ 544d15c345fSPaul Moore static int netlbl_mgmt_version(struct sk_buff *skb, struct genl_info *info) 545d15c345fSPaul Moore { 546d15c345fSPaul Moore int ret_val = -ENOMEM; 547d15c345fSPaul Moore struct sk_buff *ans_skb = NULL; 548fd385855SPaul Moore void *data; 549d15c345fSPaul Moore 550339bf98fSThomas Graf ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 551d15c345fSPaul Moore if (ans_skb == NULL) 552fd385855SPaul Moore return -ENOMEM; 55317c157c8SThomas Graf data = genlmsg_put_reply(ans_skb, info, &netlbl_mgmt_gnl_family, 55417c157c8SThomas Graf 0, NLBL_MGMT_C_VERSION); 555fd385855SPaul Moore if (data == NULL) 556d15c345fSPaul Moore goto version_failure; 557d15c345fSPaul Moore 558fd385855SPaul Moore ret_val = nla_put_u32(ans_skb, 559fd385855SPaul Moore NLBL_MGMT_A_VERSION, 560fd385855SPaul Moore NETLBL_PROTO_VERSION); 561d15c345fSPaul Moore if (ret_val != 0) 562d15c345fSPaul Moore goto version_failure; 563d15c345fSPaul Moore 564fd385855SPaul Moore genlmsg_end(ans_skb, data); 565fd385855SPaul Moore 56681878d27SThomas Graf ret_val = genlmsg_reply(ans_skb, info); 567d15c345fSPaul Moore if (ret_val != 0) 568d15c345fSPaul Moore goto version_failure; 569d15c345fSPaul Moore return 0; 570d15c345fSPaul Moore 571d15c345fSPaul Moore version_failure: 572d15c345fSPaul Moore kfree_skb(ans_skb); 573d15c345fSPaul Moore return ret_val; 574d15c345fSPaul Moore } 575d15c345fSPaul Moore 576d15c345fSPaul Moore 577d15c345fSPaul Moore /* 578d15c345fSPaul Moore * NetLabel Generic NETLINK Command Definitions 579d15c345fSPaul Moore */ 580d15c345fSPaul Moore 581d15c345fSPaul Moore static struct genl_ops netlbl_mgmt_genl_c_add = { 582d15c345fSPaul Moore .cmd = NLBL_MGMT_C_ADD, 583fd385855SPaul Moore .flags = GENL_ADMIN_PERM, 584fd385855SPaul Moore .policy = netlbl_mgmt_genl_policy, 585d15c345fSPaul Moore .doit = netlbl_mgmt_add, 586d15c345fSPaul Moore .dumpit = NULL, 587d15c345fSPaul Moore }; 588d15c345fSPaul Moore 589d15c345fSPaul Moore static struct genl_ops netlbl_mgmt_genl_c_remove = { 590d15c345fSPaul Moore .cmd = NLBL_MGMT_C_REMOVE, 591fd385855SPaul Moore .flags = GENL_ADMIN_PERM, 592fd385855SPaul Moore .policy = netlbl_mgmt_genl_policy, 593d15c345fSPaul Moore .doit = netlbl_mgmt_remove, 594d15c345fSPaul Moore .dumpit = NULL, 595d15c345fSPaul Moore }; 596d15c345fSPaul Moore 597fd385855SPaul Moore static struct genl_ops netlbl_mgmt_genl_c_listall = { 598fd385855SPaul Moore .cmd = NLBL_MGMT_C_LISTALL, 599d15c345fSPaul Moore .flags = 0, 600fd385855SPaul Moore .policy = netlbl_mgmt_genl_policy, 601fd385855SPaul Moore .doit = NULL, 602fd385855SPaul Moore .dumpit = netlbl_mgmt_listall, 603d15c345fSPaul Moore }; 604d15c345fSPaul Moore 605d15c345fSPaul Moore static struct genl_ops netlbl_mgmt_genl_c_adddef = { 606d15c345fSPaul Moore .cmd = NLBL_MGMT_C_ADDDEF, 607fd385855SPaul Moore .flags = GENL_ADMIN_PERM, 608fd385855SPaul Moore .policy = netlbl_mgmt_genl_policy, 609d15c345fSPaul Moore .doit = netlbl_mgmt_adddef, 610d15c345fSPaul Moore .dumpit = NULL, 611d15c345fSPaul Moore }; 612d15c345fSPaul Moore 613d15c345fSPaul Moore static struct genl_ops netlbl_mgmt_genl_c_removedef = { 614d15c345fSPaul Moore .cmd = NLBL_MGMT_C_REMOVEDEF, 615fd385855SPaul Moore .flags = GENL_ADMIN_PERM, 616fd385855SPaul Moore .policy = netlbl_mgmt_genl_policy, 617d15c345fSPaul Moore .doit = netlbl_mgmt_removedef, 618d15c345fSPaul Moore .dumpit = NULL, 619d15c345fSPaul Moore }; 620d15c345fSPaul Moore 621d15c345fSPaul Moore static struct genl_ops netlbl_mgmt_genl_c_listdef = { 622d15c345fSPaul Moore .cmd = NLBL_MGMT_C_LISTDEF, 623d15c345fSPaul Moore .flags = 0, 624fd385855SPaul Moore .policy = netlbl_mgmt_genl_policy, 625d15c345fSPaul Moore .doit = netlbl_mgmt_listdef, 626d15c345fSPaul Moore .dumpit = NULL, 627d15c345fSPaul Moore }; 628d15c345fSPaul Moore 629fd385855SPaul Moore static struct genl_ops netlbl_mgmt_genl_c_protocols = { 630fd385855SPaul Moore .cmd = NLBL_MGMT_C_PROTOCOLS, 631d15c345fSPaul Moore .flags = 0, 632fd385855SPaul Moore .policy = netlbl_mgmt_genl_policy, 633fd385855SPaul Moore .doit = NULL, 634fd385855SPaul Moore .dumpit = netlbl_mgmt_protocols, 635d15c345fSPaul Moore }; 636d15c345fSPaul Moore 637d15c345fSPaul Moore static struct genl_ops netlbl_mgmt_genl_c_version = { 638d15c345fSPaul Moore .cmd = NLBL_MGMT_C_VERSION, 639d15c345fSPaul Moore .flags = 0, 640fd385855SPaul Moore .policy = netlbl_mgmt_genl_policy, 641d15c345fSPaul Moore .doit = netlbl_mgmt_version, 642d15c345fSPaul Moore .dumpit = NULL, 643d15c345fSPaul Moore }; 644d15c345fSPaul Moore 645d15c345fSPaul Moore /* 646d15c345fSPaul Moore * NetLabel Generic NETLINK Protocol Functions 647d15c345fSPaul Moore */ 648d15c345fSPaul Moore 649d15c345fSPaul Moore /** 650d15c345fSPaul Moore * netlbl_mgmt_genl_init - Register the NetLabel management component 651d15c345fSPaul Moore * 652d15c345fSPaul Moore * Description: 653d15c345fSPaul Moore * Register the NetLabel management component with the Generic NETLINK 654d15c345fSPaul Moore * mechanism. Returns zero on success, negative values on failure. 655d15c345fSPaul Moore * 656d15c345fSPaul Moore */ 657d15c345fSPaul Moore int netlbl_mgmt_genl_init(void) 658d15c345fSPaul Moore { 659d15c345fSPaul Moore int ret_val; 660d15c345fSPaul Moore 661d15c345fSPaul Moore ret_val = genl_register_family(&netlbl_mgmt_gnl_family); 662d15c345fSPaul Moore if (ret_val != 0) 663d15c345fSPaul Moore return ret_val; 664d15c345fSPaul Moore 665d15c345fSPaul Moore ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, 666d15c345fSPaul Moore &netlbl_mgmt_genl_c_add); 667d15c345fSPaul Moore if (ret_val != 0) 668d15c345fSPaul Moore return ret_val; 669d15c345fSPaul Moore ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, 670d15c345fSPaul Moore &netlbl_mgmt_genl_c_remove); 671d15c345fSPaul Moore if (ret_val != 0) 672d15c345fSPaul Moore return ret_val; 673d15c345fSPaul Moore ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, 674fd385855SPaul Moore &netlbl_mgmt_genl_c_listall); 675d15c345fSPaul Moore if (ret_val != 0) 676d15c345fSPaul Moore return ret_val; 677d15c345fSPaul Moore ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, 678d15c345fSPaul Moore &netlbl_mgmt_genl_c_adddef); 679d15c345fSPaul Moore if (ret_val != 0) 680d15c345fSPaul Moore return ret_val; 681d15c345fSPaul Moore ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, 682d15c345fSPaul Moore &netlbl_mgmt_genl_c_removedef); 683d15c345fSPaul Moore if (ret_val != 0) 684d15c345fSPaul Moore return ret_val; 685d15c345fSPaul Moore ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, 686d15c345fSPaul Moore &netlbl_mgmt_genl_c_listdef); 687d15c345fSPaul Moore if (ret_val != 0) 688d15c345fSPaul Moore return ret_val; 689d15c345fSPaul Moore ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, 690fd385855SPaul Moore &netlbl_mgmt_genl_c_protocols); 691d15c345fSPaul Moore if (ret_val != 0) 692d15c345fSPaul Moore return ret_val; 693d15c345fSPaul Moore ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, 694d15c345fSPaul Moore &netlbl_mgmt_genl_c_version); 695d15c345fSPaul Moore if (ret_val != 0) 696d15c345fSPaul Moore return ret_val; 697d15c345fSPaul Moore 698d15c345fSPaul Moore return 0; 699d15c345fSPaul Moore } 700