11ccea77eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2d15c345fSPaul Moore /* 3d15c345fSPaul Moore * NetLabel Management Support 4d15c345fSPaul Moore * 5d15c345fSPaul Moore * This file defines the management functions for the NetLabel system. The 6d15c345fSPaul Moore * NetLabel system manages static and dynamic label mappings for network 7d15c345fSPaul Moore * protocols such as CIPSO and RIPSO. 8d15c345fSPaul Moore * 982c21bfaSPaul Moore * Author: Paul Moore <paul@paul-moore.com> 10d15c345fSPaul Moore */ 11d15c345fSPaul Moore 12d15c345fSPaul Moore /* 1363c41688SPaul Moore * (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008 14d15c345fSPaul Moore */ 15d15c345fSPaul Moore 16d15c345fSPaul Moore #include <linux/types.h> 17d15c345fSPaul Moore #include <linux/socket.h> 18d15c345fSPaul Moore #include <linux/string.h> 19d15c345fSPaul Moore #include <linux/skbuff.h> 2063c41688SPaul Moore #include <linux/in.h> 2163c41688SPaul Moore #include <linux/in6.h> 225a0e3ad6STejun Heo #include <linux/slab.h> 23d15c345fSPaul Moore #include <net/sock.h> 24d15c345fSPaul Moore #include <net/netlink.h> 25d15c345fSPaul Moore #include <net/genetlink.h> 2663c41688SPaul Moore #include <net/ip.h> 2763c41688SPaul Moore #include <net/ipv6.h> 28d15c345fSPaul Moore #include <net/netlabel.h> 29d15c345fSPaul Moore #include <net/cipso_ipv4.h> 30dc7de73fSHuw Davies #include <net/calipso.h> 3160063497SArun Sharma #include <linux/atomic.h> 32d15c345fSPaul Moore 33dc7de73fSHuw Davies #include "netlabel_calipso.h" 34d15c345fSPaul Moore #include "netlabel_domainhash.h" 35d15c345fSPaul Moore #include "netlabel_user.h" 36d15c345fSPaul Moore #include "netlabel_mgmt.h" 37d15c345fSPaul Moore 38c783f1ceSPaul Moore /* NetLabel configured protocol counter */ 39c783f1ceSPaul Moore atomic_t netlabel_mgmt_protocount = ATOMIC_INIT(0); 4023bcdc1aSPaul Moore 41fd385855SPaul Moore /* Argument struct for netlbl_domhsh_walk() */ 42fd385855SPaul Moore struct netlbl_domhsh_walk_arg { 43fd385855SPaul Moore struct netlink_callback *nl_cb; 44fd385855SPaul Moore struct sk_buff *skb; 45fd385855SPaul Moore u32 seq; 46fd385855SPaul Moore }; 47fd385855SPaul Moore 48d15c345fSPaul Moore /* NetLabel Generic NETLINK CIPSOv4 family */ 49489111e5SJohannes Berg static struct genl_family netlbl_mgmt_gnl_family; 50d15c345fSPaul Moore 51fd385855SPaul Moore /* NetLabel Netlink attribute policy */ 52ef7c79edSPatrick McHardy static const struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = { 53fd385855SPaul Moore [NLBL_MGMT_A_DOMAIN] = { .type = NLA_NUL_STRING }, 54fd385855SPaul Moore [NLBL_MGMT_A_PROTOCOL] = { .type = NLA_U32 }, 55fd385855SPaul Moore [NLBL_MGMT_A_VERSION] = { .type = NLA_U32 }, 56fd385855SPaul Moore [NLBL_MGMT_A_CV4DOI] = { .type = NLA_U32 }, 578f18e675SHuw Davies [NLBL_MGMT_A_FAMILY] = { .type = NLA_U16 }, 58dc7de73fSHuw Davies [NLBL_MGMT_A_CLPDOI] = { .type = NLA_U32 }, 59fd385855SPaul Moore }; 60d15c345fSPaul Moore 61d15c345fSPaul Moore /* 6263c41688SPaul Moore * Helper Functions 6363c41688SPaul Moore */ 6463c41688SPaul Moore 6563c41688SPaul Moore /** 66*3ba937fbSXiongfeng Wang * netlbl_mgmt_add_common - Handle an ADD message 6763c41688SPaul Moore * @info: the Generic NETLINK info block 6863c41688SPaul Moore * @audit_info: NetLabel audit information 6963c41688SPaul Moore * 7063c41688SPaul Moore * Description: 7163c41688SPaul Moore * Helper function for the ADD and ADDDEF messages to add the domain mappings 7263c41688SPaul Moore * from the message to the hash table. See netlabel.h for a description of the 7363c41688SPaul Moore * message format. Returns zero on success, negative values on failure. 7463c41688SPaul Moore * 7563c41688SPaul Moore */ 7663c41688SPaul Moore static int netlbl_mgmt_add_common(struct genl_info *info, 7763c41688SPaul Moore struct netlbl_audit *audit_info) 7863c41688SPaul Moore { 7963c41688SPaul Moore int ret_val = -EINVAL; 8063c41688SPaul Moore struct netlbl_domaddr_map *addrmap = NULL; 8163c41688SPaul Moore struct cipso_v4_doi *cipsov4 = NULL; 82dc7de73fSHuw Davies #if IS_ENABLED(CONFIG_IPV6) 83dc7de73fSHuw Davies struct calipso_doi *calipso = NULL; 84dc7de73fSHuw Davies #endif 8563c41688SPaul Moore u32 tmp_val; 864de46d5eSMarkus Elfring struct netlbl_dom_map *entry = kzalloc(sizeof(*entry), GFP_KERNEL); 8763c41688SPaul Moore 884de46d5eSMarkus Elfring if (!entry) 894de46d5eSMarkus Elfring return -ENOMEM; 906a8b7f0cSPaul Moore entry->def.type = nla_get_u32(info->attrs[NLBL_MGMT_A_PROTOCOL]); 9163c41688SPaul Moore if (info->attrs[NLBL_MGMT_A_DOMAIN]) { 9263c41688SPaul Moore size_t tmp_size = nla_len(info->attrs[NLBL_MGMT_A_DOMAIN]); 9363c41688SPaul Moore entry->domain = kmalloc(tmp_size, GFP_KERNEL); 9463c41688SPaul Moore if (entry->domain == NULL) { 9563c41688SPaul Moore ret_val = -ENOMEM; 964de46d5eSMarkus Elfring goto add_free_entry; 9763c41688SPaul Moore } 98872f6903SFrancis Laniel nla_strscpy(entry->domain, 9963c41688SPaul Moore info->attrs[NLBL_MGMT_A_DOMAIN], tmp_size); 10063c41688SPaul Moore } 10163c41688SPaul Moore 1026a8b7f0cSPaul Moore /* NOTE: internally we allow/use a entry->def.type value of 10363c41688SPaul Moore * NETLBL_NLTYPE_ADDRSELECT but we don't currently allow users 10463c41688SPaul Moore * to pass that as a protocol value because we need to know the 10563c41688SPaul Moore * "real" protocol */ 10663c41688SPaul Moore 1076a8b7f0cSPaul Moore switch (entry->def.type) { 10863c41688SPaul Moore case NETLBL_NLTYPE_UNLABELED: 1098f18e675SHuw Davies if (info->attrs[NLBL_MGMT_A_FAMILY]) 1108f18e675SHuw Davies entry->family = 1118f18e675SHuw Davies nla_get_u16(info->attrs[NLBL_MGMT_A_FAMILY]); 1128f18e675SHuw Davies else 1138f18e675SHuw Davies entry->family = AF_UNSPEC; 11463c41688SPaul Moore break; 11563c41688SPaul Moore case NETLBL_NLTYPE_CIPSOV4: 11663c41688SPaul Moore if (!info->attrs[NLBL_MGMT_A_CV4DOI]) 1174de46d5eSMarkus Elfring goto add_free_domain; 11863c41688SPaul Moore 11963c41688SPaul Moore tmp_val = nla_get_u32(info->attrs[NLBL_MGMT_A_CV4DOI]); 12063c41688SPaul Moore cipsov4 = cipso_v4_doi_getdef(tmp_val); 12163c41688SPaul Moore if (cipsov4 == NULL) 1224de46d5eSMarkus Elfring goto add_free_domain; 1238f18e675SHuw Davies entry->family = AF_INET; 1246a8b7f0cSPaul Moore entry->def.cipso = cipsov4; 12563c41688SPaul Moore break; 126dc7de73fSHuw Davies #if IS_ENABLED(CONFIG_IPV6) 127dc7de73fSHuw Davies case NETLBL_NLTYPE_CALIPSO: 128dc7de73fSHuw Davies if (!info->attrs[NLBL_MGMT_A_CLPDOI]) 129dc7de73fSHuw Davies goto add_free_domain; 130dc7de73fSHuw Davies 131dc7de73fSHuw Davies tmp_val = nla_get_u32(info->attrs[NLBL_MGMT_A_CLPDOI]); 132dc7de73fSHuw Davies calipso = calipso_doi_getdef(tmp_val); 133dc7de73fSHuw Davies if (calipso == NULL) 134dc7de73fSHuw Davies goto add_free_domain; 135dc7de73fSHuw Davies entry->family = AF_INET6; 136dc7de73fSHuw Davies entry->def.calipso = calipso; 137dc7de73fSHuw Davies break; 138dc7de73fSHuw Davies #endif /* IPv6 */ 13963c41688SPaul Moore default: 1404de46d5eSMarkus Elfring goto add_free_domain; 14163c41688SPaul Moore } 14263c41688SPaul Moore 1438f18e675SHuw Davies if ((entry->family == AF_INET && info->attrs[NLBL_MGMT_A_IPV6ADDR]) || 1448f18e675SHuw Davies (entry->family == AF_INET6 && info->attrs[NLBL_MGMT_A_IPV4ADDR])) 1458f18e675SHuw Davies goto add_doi_put_def; 1468f18e675SHuw Davies 14763c41688SPaul Moore if (info->attrs[NLBL_MGMT_A_IPV4ADDR]) { 14863c41688SPaul Moore struct in_addr *addr; 14963c41688SPaul Moore struct in_addr *mask; 15063c41688SPaul Moore struct netlbl_domaddr4_map *map; 15163c41688SPaul Moore 15263c41688SPaul Moore addrmap = kzalloc(sizeof(*addrmap), GFP_KERNEL); 15363c41688SPaul Moore if (addrmap == NULL) { 15463c41688SPaul Moore ret_val = -ENOMEM; 1554de46d5eSMarkus Elfring goto add_doi_put_def; 15663c41688SPaul Moore } 15763c41688SPaul Moore INIT_LIST_HEAD(&addrmap->list4); 15863c41688SPaul Moore INIT_LIST_HEAD(&addrmap->list6); 15963c41688SPaul Moore 16063c41688SPaul Moore if (nla_len(info->attrs[NLBL_MGMT_A_IPV4ADDR]) != 16163c41688SPaul Moore sizeof(struct in_addr)) { 16263c41688SPaul Moore ret_val = -EINVAL; 1634de46d5eSMarkus Elfring goto add_free_addrmap; 16463c41688SPaul Moore } 16563c41688SPaul Moore if (nla_len(info->attrs[NLBL_MGMT_A_IPV4MASK]) != 16663c41688SPaul Moore sizeof(struct in_addr)) { 16763c41688SPaul Moore ret_val = -EINVAL; 1684de46d5eSMarkus Elfring goto add_free_addrmap; 16963c41688SPaul Moore } 17063c41688SPaul Moore addr = nla_data(info->attrs[NLBL_MGMT_A_IPV4ADDR]); 17163c41688SPaul Moore mask = nla_data(info->attrs[NLBL_MGMT_A_IPV4MASK]); 17263c41688SPaul Moore 17363c41688SPaul Moore map = kzalloc(sizeof(*map), GFP_KERNEL); 17463c41688SPaul Moore if (map == NULL) { 17563c41688SPaul Moore ret_val = -ENOMEM; 1764de46d5eSMarkus Elfring goto add_free_addrmap; 17763c41688SPaul Moore } 17863c41688SPaul Moore map->list.addr = addr->s_addr & mask->s_addr; 17963c41688SPaul Moore map->list.mask = mask->s_addr; 18063c41688SPaul Moore map->list.valid = 1; 1816a8b7f0cSPaul Moore map->def.type = entry->def.type; 18263c41688SPaul Moore if (cipsov4) 1836a8b7f0cSPaul Moore map->def.cipso = cipsov4; 18463c41688SPaul Moore 18563c41688SPaul Moore ret_val = netlbl_af4list_add(&map->list, &addrmap->list4); 18663c41688SPaul Moore if (ret_val != 0) { 18763c41688SPaul Moore kfree(map); 1884de46d5eSMarkus Elfring goto add_free_addrmap; 18963c41688SPaul Moore } 19063c41688SPaul Moore 1918f18e675SHuw Davies entry->family = AF_INET; 1926a8b7f0cSPaul Moore entry->def.type = NETLBL_NLTYPE_ADDRSELECT; 1936a8b7f0cSPaul Moore entry->def.addrsel = addrmap; 194dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6) 19563c41688SPaul Moore } else if (info->attrs[NLBL_MGMT_A_IPV6ADDR]) { 19663c41688SPaul Moore struct in6_addr *addr; 19763c41688SPaul Moore struct in6_addr *mask; 19863c41688SPaul Moore struct netlbl_domaddr6_map *map; 19963c41688SPaul Moore 20063c41688SPaul Moore addrmap = kzalloc(sizeof(*addrmap), GFP_KERNEL); 20163c41688SPaul Moore if (addrmap == NULL) { 20263c41688SPaul Moore ret_val = -ENOMEM; 2034de46d5eSMarkus Elfring goto add_doi_put_def; 20463c41688SPaul Moore } 20563c41688SPaul Moore INIT_LIST_HEAD(&addrmap->list4); 20663c41688SPaul Moore INIT_LIST_HEAD(&addrmap->list6); 20763c41688SPaul Moore 20863c41688SPaul Moore if (nla_len(info->attrs[NLBL_MGMT_A_IPV6ADDR]) != 20963c41688SPaul Moore sizeof(struct in6_addr)) { 21063c41688SPaul Moore ret_val = -EINVAL; 2114de46d5eSMarkus Elfring goto add_free_addrmap; 21263c41688SPaul Moore } 21363c41688SPaul Moore if (nla_len(info->attrs[NLBL_MGMT_A_IPV6MASK]) != 21463c41688SPaul Moore sizeof(struct in6_addr)) { 21563c41688SPaul Moore ret_val = -EINVAL; 2164de46d5eSMarkus Elfring goto add_free_addrmap; 21763c41688SPaul Moore } 21863c41688SPaul Moore addr = nla_data(info->attrs[NLBL_MGMT_A_IPV6ADDR]); 21963c41688SPaul Moore mask = nla_data(info->attrs[NLBL_MGMT_A_IPV6MASK]); 22063c41688SPaul Moore 22163c41688SPaul Moore map = kzalloc(sizeof(*map), GFP_KERNEL); 22263c41688SPaul Moore if (map == NULL) { 22363c41688SPaul Moore ret_val = -ENOMEM; 2244de46d5eSMarkus Elfring goto add_free_addrmap; 22563c41688SPaul Moore } 2264e3fd7a0SAlexey Dobriyan map->list.addr = *addr; 22763c41688SPaul Moore map->list.addr.s6_addr32[0] &= mask->s6_addr32[0]; 22863c41688SPaul Moore map->list.addr.s6_addr32[1] &= mask->s6_addr32[1]; 22963c41688SPaul Moore map->list.addr.s6_addr32[2] &= mask->s6_addr32[2]; 23063c41688SPaul Moore map->list.addr.s6_addr32[3] &= mask->s6_addr32[3]; 2314e3fd7a0SAlexey Dobriyan map->list.mask = *mask; 23263c41688SPaul Moore map->list.valid = 1; 2336a8b7f0cSPaul Moore map->def.type = entry->def.type; 234dc7de73fSHuw Davies if (calipso) 235dc7de73fSHuw Davies map->def.calipso = calipso; 23663c41688SPaul Moore 23763c41688SPaul Moore ret_val = netlbl_af6list_add(&map->list, &addrmap->list6); 23863c41688SPaul Moore if (ret_val != 0) { 23963c41688SPaul Moore kfree(map); 2404de46d5eSMarkus Elfring goto add_free_addrmap; 24163c41688SPaul Moore } 24263c41688SPaul Moore 2438f18e675SHuw Davies entry->family = AF_INET6; 2446a8b7f0cSPaul Moore entry->def.type = NETLBL_NLTYPE_ADDRSELECT; 2456a8b7f0cSPaul Moore entry->def.addrsel = addrmap; 24663c41688SPaul Moore #endif /* IPv6 */ 24763c41688SPaul Moore } 24863c41688SPaul Moore 24963c41688SPaul Moore ret_val = netlbl_domhsh_add(entry, audit_info); 25063c41688SPaul Moore if (ret_val != 0) 2514de46d5eSMarkus Elfring goto add_free_addrmap; 25263c41688SPaul Moore 25363c41688SPaul Moore return 0; 25463c41688SPaul Moore 2554de46d5eSMarkus Elfring add_free_addrmap: 25663c41688SPaul Moore kfree(addrmap); 2574de46d5eSMarkus Elfring add_doi_put_def: 2584de46d5eSMarkus Elfring cipso_v4_doi_putdef(cipsov4); 259dc7de73fSHuw Davies #if IS_ENABLED(CONFIG_IPV6) 260dc7de73fSHuw Davies calipso_doi_putdef(calipso); 261dc7de73fSHuw Davies #endif 2624de46d5eSMarkus Elfring add_free_domain: 2634de46d5eSMarkus Elfring kfree(entry->domain); 2644de46d5eSMarkus Elfring add_free_entry: 26563c41688SPaul Moore kfree(entry); 26663c41688SPaul Moore return ret_val; 26763c41688SPaul Moore } 26863c41688SPaul Moore 26963c41688SPaul Moore /** 27063c41688SPaul Moore * netlbl_mgmt_listentry - List a NetLabel/LSM domain map entry 27163c41688SPaul Moore * @skb: the NETLINK buffer 27263c41688SPaul Moore * @entry: the map entry 27363c41688SPaul Moore * 27463c41688SPaul Moore * Description: 27563c41688SPaul Moore * This function is a helper function used by the LISTALL and LISTDEF command 27625985edcSLucas De Marchi * handlers. The caller is responsible for ensuring that the RCU read lock 27763c41688SPaul Moore * is held. Returns zero on success, negative values on failure. 27863c41688SPaul Moore * 27963c41688SPaul Moore */ 28063c41688SPaul Moore static int netlbl_mgmt_listentry(struct sk_buff *skb, 28163c41688SPaul Moore struct netlbl_dom_map *entry) 28263c41688SPaul Moore { 283f8a02479SPaul Moore int ret_val = 0; 28463c41688SPaul Moore struct nlattr *nla_a; 28563c41688SPaul Moore struct nlattr *nla_b; 28663c41688SPaul Moore struct netlbl_af4list *iter4; 287dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6) 28863c41688SPaul Moore struct netlbl_af6list *iter6; 28963c41688SPaul Moore #endif 29063c41688SPaul Moore 29163c41688SPaul Moore if (entry->domain != NULL) { 29263c41688SPaul Moore ret_val = nla_put_string(skb, 29363c41688SPaul Moore NLBL_MGMT_A_DOMAIN, entry->domain); 29463c41688SPaul Moore if (ret_val != 0) 29563c41688SPaul Moore return ret_val; 29663c41688SPaul Moore } 29763c41688SPaul Moore 2988f18e675SHuw Davies ret_val = nla_put_u16(skb, NLBL_MGMT_A_FAMILY, entry->family); 2998f18e675SHuw Davies if (ret_val != 0) 3008f18e675SHuw Davies return ret_val; 3018f18e675SHuw Davies 3026a8b7f0cSPaul Moore switch (entry->def.type) { 30363c41688SPaul Moore case NETLBL_NLTYPE_ADDRSELECT: 304ae0be8deSMichal Kubecek nla_a = nla_nest_start_noflag(skb, NLBL_MGMT_A_SELECTORLIST); 30563c41688SPaul Moore if (nla_a == NULL) 30663c41688SPaul Moore return -ENOMEM; 30763c41688SPaul Moore 3086a8b7f0cSPaul Moore netlbl_af4list_foreach_rcu(iter4, &entry->def.addrsel->list4) { 30963c41688SPaul Moore struct netlbl_domaddr4_map *map4; 31063c41688SPaul Moore struct in_addr addr_struct; 31163c41688SPaul Moore 312ae0be8deSMichal Kubecek nla_b = nla_nest_start_noflag(skb, 313ae0be8deSMichal Kubecek NLBL_MGMT_A_ADDRSELECTOR); 31463c41688SPaul Moore if (nla_b == NULL) 31563c41688SPaul Moore return -ENOMEM; 31663c41688SPaul Moore 31763c41688SPaul Moore addr_struct.s_addr = iter4->addr; 318930345eaSJiri Benc ret_val = nla_put_in_addr(skb, NLBL_MGMT_A_IPV4ADDR, 319930345eaSJiri Benc addr_struct.s_addr); 32063c41688SPaul Moore if (ret_val != 0) 32163c41688SPaul Moore return ret_val; 32263c41688SPaul Moore addr_struct.s_addr = iter4->mask; 323930345eaSJiri Benc ret_val = nla_put_in_addr(skb, NLBL_MGMT_A_IPV4MASK, 324930345eaSJiri Benc addr_struct.s_addr); 32563c41688SPaul Moore if (ret_val != 0) 32663c41688SPaul Moore return ret_val; 32763c41688SPaul Moore map4 = netlbl_domhsh_addr4_entry(iter4); 32863c41688SPaul Moore ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL, 3296a8b7f0cSPaul Moore map4->def.type); 33063c41688SPaul Moore if (ret_val != 0) 33163c41688SPaul Moore return ret_val; 3326a8b7f0cSPaul Moore switch (map4->def.type) { 33363c41688SPaul Moore case NETLBL_NLTYPE_CIPSOV4: 33463c41688SPaul Moore ret_val = nla_put_u32(skb, NLBL_MGMT_A_CV4DOI, 3356a8b7f0cSPaul Moore map4->def.cipso->doi); 33663c41688SPaul Moore if (ret_val != 0) 33763c41688SPaul Moore return ret_val; 33863c41688SPaul Moore break; 33963c41688SPaul Moore } 34063c41688SPaul Moore 34163c41688SPaul Moore nla_nest_end(skb, nla_b); 34263c41688SPaul Moore } 343dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6) 3446a8b7f0cSPaul Moore netlbl_af6list_foreach_rcu(iter6, &entry->def.addrsel->list6) { 34563c41688SPaul Moore struct netlbl_domaddr6_map *map6; 34663c41688SPaul Moore 347ae0be8deSMichal Kubecek nla_b = nla_nest_start_noflag(skb, 348ae0be8deSMichal Kubecek NLBL_MGMT_A_ADDRSELECTOR); 34963c41688SPaul Moore if (nla_b == NULL) 35063c41688SPaul Moore return -ENOMEM; 35163c41688SPaul Moore 352930345eaSJiri Benc ret_val = nla_put_in6_addr(skb, NLBL_MGMT_A_IPV6ADDR, 35363c41688SPaul Moore &iter6->addr); 35463c41688SPaul Moore if (ret_val != 0) 35563c41688SPaul Moore return ret_val; 356930345eaSJiri Benc ret_val = nla_put_in6_addr(skb, NLBL_MGMT_A_IPV6MASK, 35763c41688SPaul Moore &iter6->mask); 35863c41688SPaul Moore if (ret_val != 0) 35963c41688SPaul Moore return ret_val; 36063c41688SPaul Moore map6 = netlbl_domhsh_addr6_entry(iter6); 36163c41688SPaul Moore ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL, 3626a8b7f0cSPaul Moore map6->def.type); 36363c41688SPaul Moore if (ret_val != 0) 36463c41688SPaul Moore return ret_val; 36563c41688SPaul Moore 366dc7de73fSHuw Davies switch (map6->def.type) { 367dc7de73fSHuw Davies case NETLBL_NLTYPE_CALIPSO: 368dc7de73fSHuw Davies ret_val = nla_put_u32(skb, NLBL_MGMT_A_CLPDOI, 369dc7de73fSHuw Davies map6->def.calipso->doi); 370dc7de73fSHuw Davies if (ret_val != 0) 371dc7de73fSHuw Davies return ret_val; 372dc7de73fSHuw Davies break; 373dc7de73fSHuw Davies } 374dc7de73fSHuw Davies 37563c41688SPaul Moore nla_nest_end(skb, nla_b); 37663c41688SPaul Moore } 37763c41688SPaul Moore #endif /* IPv6 */ 37863c41688SPaul Moore 37963c41688SPaul Moore nla_nest_end(skb, nla_a); 38063c41688SPaul Moore break; 38163c41688SPaul Moore case NETLBL_NLTYPE_UNLABELED: 382dc7de73fSHuw Davies ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL, 383dc7de73fSHuw Davies entry->def.type); 38463c41688SPaul Moore break; 38563c41688SPaul Moore case NETLBL_NLTYPE_CIPSOV4: 386dc7de73fSHuw Davies ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL, 387dc7de73fSHuw Davies entry->def.type); 38863c41688SPaul Moore if (ret_val != 0) 38963c41688SPaul Moore return ret_val; 39063c41688SPaul Moore ret_val = nla_put_u32(skb, NLBL_MGMT_A_CV4DOI, 3916a8b7f0cSPaul Moore entry->def.cipso->doi); 39263c41688SPaul Moore break; 393dc7de73fSHuw Davies case NETLBL_NLTYPE_CALIPSO: 394dc7de73fSHuw Davies ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL, 395dc7de73fSHuw Davies entry->def.type); 396dc7de73fSHuw Davies if (ret_val != 0) 397dc7de73fSHuw Davies return ret_val; 398dc7de73fSHuw Davies ret_val = nla_put_u32(skb, NLBL_MGMT_A_CLPDOI, 399dc7de73fSHuw Davies entry->def.calipso->doi); 400dc7de73fSHuw Davies break; 40163c41688SPaul Moore } 40263c41688SPaul Moore 40363c41688SPaul Moore return ret_val; 40463c41688SPaul Moore } 40563c41688SPaul Moore 40663c41688SPaul Moore /* 407d15c345fSPaul Moore * NetLabel Command Handlers 408d15c345fSPaul Moore */ 409d15c345fSPaul Moore 410d15c345fSPaul Moore /** 411d15c345fSPaul Moore * netlbl_mgmt_add - Handle an ADD message 412d15c345fSPaul Moore * @skb: the NETLINK buffer 413d15c345fSPaul Moore * @info: the Generic NETLINK info block 414d15c345fSPaul Moore * 415d15c345fSPaul Moore * Description: 416d15c345fSPaul Moore * Process a user generated ADD message and add the domains from the message 417d15c345fSPaul Moore * to the hash table. See netlabel.h for a description of the message format. 418d15c345fSPaul Moore * Returns zero on success, negative values on failure. 419d15c345fSPaul Moore * 420d15c345fSPaul Moore */ 421d15c345fSPaul Moore static int netlbl_mgmt_add(struct sk_buff *skb, struct genl_info *info) 422d15c345fSPaul Moore { 42395d4e6beSPaul Moore struct netlbl_audit audit_info; 424d15c345fSPaul Moore 42563c41688SPaul Moore if ((!info->attrs[NLBL_MGMT_A_DOMAIN]) || 42663c41688SPaul Moore (!info->attrs[NLBL_MGMT_A_PROTOCOL]) || 42763c41688SPaul Moore (info->attrs[NLBL_MGMT_A_IPV4ADDR] && 42863c41688SPaul Moore info->attrs[NLBL_MGMT_A_IPV6ADDR]) || 42963c41688SPaul Moore (info->attrs[NLBL_MGMT_A_IPV4MASK] && 43063c41688SPaul Moore info->attrs[NLBL_MGMT_A_IPV6MASK]) || 43163c41688SPaul Moore ((info->attrs[NLBL_MGMT_A_IPV4ADDR] != NULL) ^ 43263c41688SPaul Moore (info->attrs[NLBL_MGMT_A_IPV4MASK] != NULL)) || 43363c41688SPaul Moore ((info->attrs[NLBL_MGMT_A_IPV6ADDR] != NULL) ^ 43463c41688SPaul Moore (info->attrs[NLBL_MGMT_A_IPV6MASK] != NULL))) 43563c41688SPaul Moore return -EINVAL; 436d15c345fSPaul Moore 43795d4e6beSPaul Moore netlbl_netlink_auditinfo(skb, &audit_info); 43895d4e6beSPaul Moore 43963c41688SPaul Moore return netlbl_mgmt_add_common(info, &audit_info); 440d15c345fSPaul Moore } 441d15c345fSPaul Moore 442d15c345fSPaul Moore /** 443d15c345fSPaul Moore * netlbl_mgmt_remove - Handle a REMOVE message 444d15c345fSPaul Moore * @skb: the NETLINK buffer 445d15c345fSPaul Moore * @info: the Generic NETLINK info block 446d15c345fSPaul Moore * 447d15c345fSPaul Moore * Description: 448d15c345fSPaul Moore * Process a user generated REMOVE message and remove the specified domain 449d15c345fSPaul Moore * mappings. Returns zero on success, negative values on failure. 450d15c345fSPaul Moore * 451d15c345fSPaul Moore */ 452d15c345fSPaul Moore static int netlbl_mgmt_remove(struct sk_buff *skb, struct genl_info *info) 453d15c345fSPaul Moore { 454fd385855SPaul Moore char *domain; 45595d4e6beSPaul Moore struct netlbl_audit audit_info; 456d15c345fSPaul Moore 457fd385855SPaul Moore if (!info->attrs[NLBL_MGMT_A_DOMAIN]) 458fd385855SPaul Moore return -EINVAL; 459d15c345fSPaul Moore 46095d4e6beSPaul Moore netlbl_netlink_auditinfo(skb, &audit_info); 46195d4e6beSPaul Moore 462fd385855SPaul Moore domain = nla_data(info->attrs[NLBL_MGMT_A_DOMAIN]); 4638f18e675SHuw Davies return netlbl_domhsh_remove(domain, AF_UNSPEC, &audit_info); 464d15c345fSPaul Moore } 465d15c345fSPaul Moore 466fd385855SPaul Moore /** 467fd385855SPaul Moore * netlbl_mgmt_listall_cb - netlbl_domhsh_walk() callback for LISTALL 468fd385855SPaul Moore * @entry: the domain mapping hash table entry 469fd385855SPaul Moore * @arg: the netlbl_domhsh_walk_arg structure 470fd385855SPaul Moore * 471fd385855SPaul Moore * Description: 472fd385855SPaul Moore * This function is designed to be used as a callback to the 473fd385855SPaul Moore * netlbl_domhsh_walk() function for use in generating a response for a LISTALL 474fd385855SPaul Moore * message. Returns the size of the message on success, negative values on 475fd385855SPaul Moore * failure. 476fd385855SPaul Moore * 477fd385855SPaul Moore */ 478fd385855SPaul Moore static int netlbl_mgmt_listall_cb(struct netlbl_dom_map *entry, void *arg) 479fd385855SPaul Moore { 480fd385855SPaul Moore int ret_val = -ENOMEM; 481fd385855SPaul Moore struct netlbl_domhsh_walk_arg *cb_arg = arg; 482fd385855SPaul Moore void *data; 483d15c345fSPaul Moore 48415e47304SEric W. Biederman data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).portid, 48517c157c8SThomas Graf cb_arg->seq, &netlbl_mgmt_gnl_family, 48617c157c8SThomas Graf NLM_F_MULTI, NLBL_MGMT_C_LISTALL); 487fd385855SPaul Moore if (data == NULL) 488fd385855SPaul Moore goto listall_cb_failure; 489fd385855SPaul Moore 49063c41688SPaul Moore ret_val = netlbl_mgmt_listentry(cb_arg->skb, entry); 491fd385855SPaul Moore if (ret_val != 0) 492fd385855SPaul Moore goto listall_cb_failure; 493fd385855SPaul Moore 494fd385855SPaul Moore cb_arg->seq++; 495053c095aSJohannes Berg genlmsg_end(cb_arg->skb, data); 496053c095aSJohannes Berg return 0; 497fd385855SPaul Moore 498fd385855SPaul Moore listall_cb_failure: 499fd385855SPaul Moore genlmsg_cancel(cb_arg->skb, data); 500d15c345fSPaul Moore return ret_val; 501d15c345fSPaul Moore } 502d15c345fSPaul Moore 503d15c345fSPaul Moore /** 504fd385855SPaul Moore * netlbl_mgmt_listall - Handle a LISTALL message 505d15c345fSPaul Moore * @skb: the NETLINK buffer 506fd385855SPaul Moore * @cb: the NETLINK callback 507d15c345fSPaul Moore * 508d15c345fSPaul Moore * Description: 509fd385855SPaul Moore * Process a user generated LISTALL message and dumps the domain hash table in 510fd385855SPaul Moore * a form suitable for use in a kernel generated LISTALL message. Returns zero 511fd385855SPaul Moore * on success, negative values on failure. 512d15c345fSPaul Moore * 513d15c345fSPaul Moore */ 514fd385855SPaul Moore static int netlbl_mgmt_listall(struct sk_buff *skb, 515fd385855SPaul Moore struct netlink_callback *cb) 516d15c345fSPaul Moore { 517fd385855SPaul Moore struct netlbl_domhsh_walk_arg cb_arg; 518fd385855SPaul Moore u32 skip_bkt = cb->args[0]; 519fd385855SPaul Moore u32 skip_chain = cb->args[1]; 520d15c345fSPaul Moore 521fd385855SPaul Moore cb_arg.nl_cb = cb; 522fd385855SPaul Moore cb_arg.skb = skb; 523fd385855SPaul Moore cb_arg.seq = cb->nlh->nlmsg_seq; 524d15c345fSPaul Moore 525fd385855SPaul Moore netlbl_domhsh_walk(&skip_bkt, 526fd385855SPaul Moore &skip_chain, 527fd385855SPaul Moore netlbl_mgmt_listall_cb, 528fd385855SPaul Moore &cb_arg); 529d15c345fSPaul Moore 530fd385855SPaul Moore cb->args[0] = skip_bkt; 531fd385855SPaul Moore cb->args[1] = skip_chain; 532fd385855SPaul Moore return skb->len; 533d15c345fSPaul Moore } 534d15c345fSPaul Moore 535d15c345fSPaul Moore /** 536d15c345fSPaul Moore * netlbl_mgmt_adddef - Handle an ADDDEF message 537d15c345fSPaul Moore * @skb: the NETLINK buffer 538d15c345fSPaul Moore * @info: the Generic NETLINK info block 539d15c345fSPaul Moore * 540d15c345fSPaul Moore * Description: 541d15c345fSPaul Moore * Process a user generated ADDDEF message and respond accordingly. Returns 542d15c345fSPaul Moore * zero on success, negative values on failure. 543d15c345fSPaul Moore * 544d15c345fSPaul Moore */ 545d15c345fSPaul Moore static int netlbl_mgmt_adddef(struct sk_buff *skb, struct genl_info *info) 546d15c345fSPaul Moore { 54795d4e6beSPaul Moore struct netlbl_audit audit_info; 548d15c345fSPaul Moore 54963c41688SPaul Moore if ((!info->attrs[NLBL_MGMT_A_PROTOCOL]) || 55063c41688SPaul Moore (info->attrs[NLBL_MGMT_A_IPV4ADDR] && 55163c41688SPaul Moore info->attrs[NLBL_MGMT_A_IPV6ADDR]) || 55263c41688SPaul Moore (info->attrs[NLBL_MGMT_A_IPV4MASK] && 55363c41688SPaul Moore info->attrs[NLBL_MGMT_A_IPV6MASK]) || 55463c41688SPaul Moore ((info->attrs[NLBL_MGMT_A_IPV4ADDR] != NULL) ^ 55563c41688SPaul Moore (info->attrs[NLBL_MGMT_A_IPV4MASK] != NULL)) || 55663c41688SPaul Moore ((info->attrs[NLBL_MGMT_A_IPV6ADDR] != NULL) ^ 55763c41688SPaul Moore (info->attrs[NLBL_MGMT_A_IPV6MASK] != NULL))) 55863c41688SPaul Moore return -EINVAL; 559d15c345fSPaul Moore 56095d4e6beSPaul Moore netlbl_netlink_auditinfo(skb, &audit_info); 56195d4e6beSPaul Moore 56263c41688SPaul Moore return netlbl_mgmt_add_common(info, &audit_info); 563d15c345fSPaul Moore } 564d15c345fSPaul Moore 565d15c345fSPaul Moore /** 566d15c345fSPaul Moore * netlbl_mgmt_removedef - Handle a REMOVEDEF message 567d15c345fSPaul Moore * @skb: the NETLINK buffer 568d15c345fSPaul Moore * @info: the Generic NETLINK info block 569d15c345fSPaul Moore * 570d15c345fSPaul Moore * Description: 571d15c345fSPaul Moore * Process a user generated REMOVEDEF message and remove the default domain 572d15c345fSPaul Moore * mapping. Returns zero on success, negative values on failure. 573d15c345fSPaul Moore * 574d15c345fSPaul Moore */ 575d15c345fSPaul Moore static int netlbl_mgmt_removedef(struct sk_buff *skb, struct genl_info *info) 576d15c345fSPaul Moore { 57795d4e6beSPaul Moore struct netlbl_audit audit_info; 57895d4e6beSPaul Moore 57995d4e6beSPaul Moore netlbl_netlink_auditinfo(skb, &audit_info); 58095d4e6beSPaul Moore 5818f18e675SHuw Davies return netlbl_domhsh_remove_default(AF_UNSPEC, &audit_info); 582d15c345fSPaul Moore } 583d15c345fSPaul Moore 584d15c345fSPaul Moore /** 585d15c345fSPaul Moore * netlbl_mgmt_listdef - Handle a LISTDEF message 586d15c345fSPaul Moore * @skb: the NETLINK buffer 587d15c345fSPaul Moore * @info: the Generic NETLINK info block 588d15c345fSPaul Moore * 589d15c345fSPaul Moore * Description: 590d15c345fSPaul Moore * Process a user generated LISTDEF message and dumps the default domain 591d15c345fSPaul Moore * mapping in a form suitable for use in a kernel generated LISTDEF message. 592d15c345fSPaul Moore * Returns zero on success, negative values on failure. 593d15c345fSPaul Moore * 594d15c345fSPaul Moore */ 595d15c345fSPaul Moore static int netlbl_mgmt_listdef(struct sk_buff *skb, struct genl_info *info) 596d15c345fSPaul Moore { 597d15c345fSPaul Moore int ret_val = -ENOMEM; 598fd385855SPaul Moore struct sk_buff *ans_skb = NULL; 599fd385855SPaul Moore void *data; 600fd385855SPaul Moore struct netlbl_dom_map *entry; 6018f18e675SHuw Davies u16 family; 6028f18e675SHuw Davies 6038f18e675SHuw Davies if (info->attrs[NLBL_MGMT_A_FAMILY]) 6048f18e675SHuw Davies family = nla_get_u16(info->attrs[NLBL_MGMT_A_FAMILY]); 6058f18e675SHuw Davies else 6068f18e675SHuw Davies family = AF_INET; 607d15c345fSPaul Moore 608339bf98fSThomas Graf ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 609d15c345fSPaul Moore if (ans_skb == NULL) 610fd385855SPaul Moore return -ENOMEM; 61117c157c8SThomas Graf data = genlmsg_put_reply(ans_skb, info, &netlbl_mgmt_gnl_family, 61217c157c8SThomas Graf 0, NLBL_MGMT_C_LISTDEF); 613fd385855SPaul Moore if (data == NULL) 614fd385855SPaul Moore goto listdef_failure; 615d15c345fSPaul Moore 616fd385855SPaul Moore rcu_read_lock(); 6178f18e675SHuw Davies entry = netlbl_domhsh_getentry(NULL, family); 618fd385855SPaul Moore if (entry == NULL) { 619fd385855SPaul Moore ret_val = -ENOENT; 620fd385855SPaul Moore goto listdef_failure_lock; 621fd385855SPaul Moore } 62263c41688SPaul Moore ret_val = netlbl_mgmt_listentry(ans_skb, entry); 623fd385855SPaul Moore rcu_read_unlock(); 62463c41688SPaul Moore if (ret_val != 0) 62563c41688SPaul Moore goto listdef_failure; 626fd385855SPaul Moore 627fd385855SPaul Moore genlmsg_end(ans_skb, data); 628fe785beeSDenis V. Lunev return genlmsg_reply(ans_skb, info); 629d15c345fSPaul Moore 630fd385855SPaul Moore listdef_failure_lock: 631fd385855SPaul Moore rcu_read_unlock(); 632d15c345fSPaul Moore listdef_failure: 633fd385855SPaul Moore kfree_skb(ans_skb); 634d15c345fSPaul Moore return ret_val; 635d15c345fSPaul Moore } 636d15c345fSPaul Moore 637d15c345fSPaul Moore /** 638fd385855SPaul Moore * netlbl_mgmt_protocols_cb - Write an individual PROTOCOL message response 639fd385855SPaul Moore * @skb: the skb to write to 640fd385855SPaul Moore * @cb: the NETLINK callback 641fd385855SPaul Moore * @protocol: the NetLabel protocol to use in the message 642d15c345fSPaul Moore * 643d15c345fSPaul Moore * Description: 644fd385855SPaul Moore * This function is to be used in conjunction with netlbl_mgmt_protocols() to 645fd385855SPaul Moore * answer a application's PROTOCOLS message. Returns the size of the message 646fd385855SPaul Moore * on success, negative values on failure. 647d15c345fSPaul Moore * 648d15c345fSPaul Moore */ 649fd385855SPaul Moore static int netlbl_mgmt_protocols_cb(struct sk_buff *skb, 650fd385855SPaul Moore struct netlink_callback *cb, 651fd385855SPaul Moore u32 protocol) 652d15c345fSPaul Moore { 653d15c345fSPaul Moore int ret_val = -ENOMEM; 654fd385855SPaul Moore void *data; 655d15c345fSPaul Moore 65615e47304SEric W. Biederman data = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, 65717c157c8SThomas Graf &netlbl_mgmt_gnl_family, NLM_F_MULTI, 658fd385855SPaul Moore NLBL_MGMT_C_PROTOCOLS); 659fd385855SPaul Moore if (data == NULL) 660fd385855SPaul Moore goto protocols_cb_failure; 661d15c345fSPaul Moore 662fd385855SPaul Moore ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL, protocol); 663d15c345fSPaul Moore if (ret_val != 0) 664fd385855SPaul Moore goto protocols_cb_failure; 665d15c345fSPaul Moore 666053c095aSJohannes Berg genlmsg_end(skb, data); 667053c095aSJohannes Berg return 0; 668d15c345fSPaul Moore 669fd385855SPaul Moore protocols_cb_failure: 670fd385855SPaul Moore genlmsg_cancel(skb, data); 671d15c345fSPaul Moore return ret_val; 672d15c345fSPaul Moore } 673d15c345fSPaul Moore 674d15c345fSPaul Moore /** 675fd385855SPaul Moore * netlbl_mgmt_protocols - Handle a PROTOCOLS message 676fd385855SPaul Moore * @skb: the NETLINK buffer 677fd385855SPaul Moore * @cb: the NETLINK callback 678fd385855SPaul Moore * 679fd385855SPaul Moore * Description: 680fd385855SPaul Moore * Process a user generated PROTOCOLS message and respond accordingly. 681fd385855SPaul Moore * 682fd385855SPaul Moore */ 683fd385855SPaul Moore static int netlbl_mgmt_protocols(struct sk_buff *skb, 684fd385855SPaul Moore struct netlink_callback *cb) 685fd385855SPaul Moore { 686fd385855SPaul Moore u32 protos_sent = cb->args[0]; 687fd385855SPaul Moore 688fd385855SPaul Moore if (protos_sent == 0) { 689fd385855SPaul Moore if (netlbl_mgmt_protocols_cb(skb, 690fd385855SPaul Moore cb, 691fd385855SPaul Moore NETLBL_NLTYPE_UNLABELED) < 0) 692fd385855SPaul Moore goto protocols_return; 693fd385855SPaul Moore protos_sent++; 694fd385855SPaul Moore } 695fd385855SPaul Moore if (protos_sent == 1) { 696fd385855SPaul Moore if (netlbl_mgmt_protocols_cb(skb, 697fd385855SPaul Moore cb, 698fd385855SPaul Moore NETLBL_NLTYPE_CIPSOV4) < 0) 699fd385855SPaul Moore goto protocols_return; 700fd385855SPaul Moore protos_sent++; 701fd385855SPaul Moore } 702cb72d382SHuw Davies #if IS_ENABLED(CONFIG_IPV6) 703cb72d382SHuw Davies if (protos_sent == 2) { 704cb72d382SHuw Davies if (netlbl_mgmt_protocols_cb(skb, 705cb72d382SHuw Davies cb, 706cb72d382SHuw Davies NETLBL_NLTYPE_CALIPSO) < 0) 707cb72d382SHuw Davies goto protocols_return; 708cb72d382SHuw Davies protos_sent++; 709cb72d382SHuw Davies } 710cb72d382SHuw Davies #endif 711fd385855SPaul Moore 712fd385855SPaul Moore protocols_return: 713fd385855SPaul Moore cb->args[0] = protos_sent; 714fd385855SPaul Moore return skb->len; 715fd385855SPaul Moore } 716fd385855SPaul Moore 717fd385855SPaul Moore /** 718d15c345fSPaul Moore * netlbl_mgmt_version - Handle a VERSION message 719d15c345fSPaul Moore * @skb: the NETLINK buffer 720d15c345fSPaul Moore * @info: the Generic NETLINK info block 721d15c345fSPaul Moore * 722d15c345fSPaul Moore * Description: 723d15c345fSPaul Moore * Process a user generated VERSION message and respond accordingly. Returns 724d15c345fSPaul Moore * zero on success, negative values on failure. 725d15c345fSPaul Moore * 726d15c345fSPaul Moore */ 727d15c345fSPaul Moore static int netlbl_mgmt_version(struct sk_buff *skb, struct genl_info *info) 728d15c345fSPaul Moore { 729d15c345fSPaul Moore int ret_val = -ENOMEM; 730d15c345fSPaul Moore struct sk_buff *ans_skb = NULL; 731fd385855SPaul Moore void *data; 732d15c345fSPaul Moore 733339bf98fSThomas Graf ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 734d15c345fSPaul Moore if (ans_skb == NULL) 735fd385855SPaul Moore return -ENOMEM; 73617c157c8SThomas Graf data = genlmsg_put_reply(ans_skb, info, &netlbl_mgmt_gnl_family, 73717c157c8SThomas Graf 0, NLBL_MGMT_C_VERSION); 738fd385855SPaul Moore if (data == NULL) 739d15c345fSPaul Moore goto version_failure; 740d15c345fSPaul Moore 741fd385855SPaul Moore ret_val = nla_put_u32(ans_skb, 742fd385855SPaul Moore NLBL_MGMT_A_VERSION, 743fd385855SPaul Moore NETLBL_PROTO_VERSION); 744d15c345fSPaul Moore if (ret_val != 0) 745d15c345fSPaul Moore goto version_failure; 746d15c345fSPaul Moore 747fd385855SPaul Moore genlmsg_end(ans_skb, data); 748fe785beeSDenis V. Lunev return genlmsg_reply(ans_skb, info); 749d15c345fSPaul Moore 750d15c345fSPaul Moore version_failure: 751d15c345fSPaul Moore kfree_skb(ans_skb); 752d15c345fSPaul Moore return ret_val; 753d15c345fSPaul Moore } 754d15c345fSPaul Moore 755d15c345fSPaul Moore 756d15c345fSPaul Moore /* 757d15c345fSPaul Moore * NetLabel Generic NETLINK Command Definitions 758d15c345fSPaul Moore */ 759d15c345fSPaul Moore 76066a9b928SJakub Kicinski static const struct genl_small_ops netlbl_mgmt_genl_ops[] = { 761227c43c3SPavel Emelyanov { 762d15c345fSPaul Moore .cmd = NLBL_MGMT_C_ADD, 763ef6243acSJohannes Berg .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 764fd385855SPaul Moore .flags = GENL_ADMIN_PERM, 765d15c345fSPaul Moore .doit = netlbl_mgmt_add, 766d15c345fSPaul Moore .dumpit = NULL, 767227c43c3SPavel Emelyanov }, 768227c43c3SPavel Emelyanov { 769d15c345fSPaul Moore .cmd = NLBL_MGMT_C_REMOVE, 770ef6243acSJohannes Berg .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 771fd385855SPaul Moore .flags = GENL_ADMIN_PERM, 772d15c345fSPaul Moore .doit = netlbl_mgmt_remove, 773d15c345fSPaul Moore .dumpit = NULL, 774227c43c3SPavel Emelyanov }, 775227c43c3SPavel Emelyanov { 776fd385855SPaul Moore .cmd = NLBL_MGMT_C_LISTALL, 777ef6243acSJohannes Berg .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 778d15c345fSPaul Moore .flags = 0, 779fd385855SPaul Moore .doit = NULL, 780fd385855SPaul Moore .dumpit = netlbl_mgmt_listall, 781227c43c3SPavel Emelyanov }, 782227c43c3SPavel Emelyanov { 783d15c345fSPaul Moore .cmd = NLBL_MGMT_C_ADDDEF, 784ef6243acSJohannes Berg .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 785fd385855SPaul Moore .flags = GENL_ADMIN_PERM, 786d15c345fSPaul Moore .doit = netlbl_mgmt_adddef, 787d15c345fSPaul Moore .dumpit = NULL, 788227c43c3SPavel Emelyanov }, 789227c43c3SPavel Emelyanov { 790d15c345fSPaul Moore .cmd = NLBL_MGMT_C_REMOVEDEF, 791ef6243acSJohannes Berg .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 792fd385855SPaul Moore .flags = GENL_ADMIN_PERM, 793d15c345fSPaul Moore .doit = netlbl_mgmt_removedef, 794d15c345fSPaul Moore .dumpit = NULL, 795227c43c3SPavel Emelyanov }, 796227c43c3SPavel Emelyanov { 797d15c345fSPaul Moore .cmd = NLBL_MGMT_C_LISTDEF, 798ef6243acSJohannes Berg .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 799d15c345fSPaul Moore .flags = 0, 800d15c345fSPaul Moore .doit = netlbl_mgmt_listdef, 801d15c345fSPaul Moore .dumpit = NULL, 802227c43c3SPavel Emelyanov }, 803227c43c3SPavel Emelyanov { 804fd385855SPaul Moore .cmd = NLBL_MGMT_C_PROTOCOLS, 805ef6243acSJohannes Berg .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 806d15c345fSPaul Moore .flags = 0, 807fd385855SPaul Moore .doit = NULL, 808fd385855SPaul Moore .dumpit = netlbl_mgmt_protocols, 809227c43c3SPavel Emelyanov }, 810227c43c3SPavel Emelyanov { 811d15c345fSPaul Moore .cmd = NLBL_MGMT_C_VERSION, 812ef6243acSJohannes Berg .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 813d15c345fSPaul Moore .flags = 0, 814d15c345fSPaul Moore .doit = netlbl_mgmt_version, 815d15c345fSPaul Moore .dumpit = NULL, 816227c43c3SPavel Emelyanov }, 817d15c345fSPaul Moore }; 818d15c345fSPaul Moore 81956989f6dSJohannes Berg static struct genl_family netlbl_mgmt_gnl_family __ro_after_init = { 820489111e5SJohannes Berg .hdrsize = 0, 821489111e5SJohannes Berg .name = NETLBL_NLTYPE_MGMT_NAME, 822489111e5SJohannes Berg .version = NETLBL_PROTO_VERSION, 823489111e5SJohannes Berg .maxattr = NLBL_MGMT_A_MAX, 8243b0f31f2SJohannes Berg .policy = netlbl_mgmt_genl_policy, 825489111e5SJohannes Berg .module = THIS_MODULE, 82666a9b928SJakub Kicinski .small_ops = netlbl_mgmt_genl_ops, 82766a9b928SJakub Kicinski .n_small_ops = ARRAY_SIZE(netlbl_mgmt_genl_ops), 828489111e5SJohannes Berg }; 829489111e5SJohannes Berg 830d15c345fSPaul Moore /* 831d15c345fSPaul Moore * NetLabel Generic NETLINK Protocol Functions 832d15c345fSPaul Moore */ 833d15c345fSPaul Moore 834d15c345fSPaul Moore /** 835d15c345fSPaul Moore * netlbl_mgmt_genl_init - Register the NetLabel management component 836d15c345fSPaul Moore * 837d15c345fSPaul Moore * Description: 838d15c345fSPaul Moore * Register the NetLabel management component with the Generic NETLINK 839d15c345fSPaul Moore * mechanism. Returns zero on success, negative values on failure. 840d15c345fSPaul Moore * 841d15c345fSPaul Moore */ 84205705e4eSPavel Emelyanov int __init netlbl_mgmt_genl_init(void) 843d15c345fSPaul Moore { 844489111e5SJohannes Berg return genl_register_family(&netlbl_mgmt_gnl_family); 845d15c345fSPaul Moore } 846