1d07dcf9aSJohannes Berg // SPDX-License-Identifier: GPL-2.0 2d07dcf9aSJohannes Berg /* 3d07dcf9aSJohannes Berg * NETLINK Policy advertisement to userspace 4d07dcf9aSJohannes Berg * 5d07dcf9aSJohannes Berg * Authors: Johannes Berg <johannes@sipsolutions.net> 6d07dcf9aSJohannes Berg * 7d07dcf9aSJohannes Berg * Copyright 2019 Intel Corporation 8d07dcf9aSJohannes Berg */ 9d07dcf9aSJohannes Berg 10d07dcf9aSJohannes Berg #include <linux/kernel.h> 11d07dcf9aSJohannes Berg #include <linux/errno.h> 12d07dcf9aSJohannes Berg #include <linux/types.h> 13d07dcf9aSJohannes Berg #include <net/netlink.h> 14d07dcf9aSJohannes Berg 15d07dcf9aSJohannes Berg #define INITIAL_POLICIES_ALLOC 10 16d07dcf9aSJohannes Berg 17adc84845SJakub Kicinski struct netlink_policy_dump_state { 18d07dcf9aSJohannes Berg unsigned int policy_idx; 19d07dcf9aSJohannes Berg unsigned int attr_idx; 20d07dcf9aSJohannes Berg unsigned int n_alloc; 21d07dcf9aSJohannes Berg struct { 22d07dcf9aSJohannes Berg const struct nla_policy *policy; 23d07dcf9aSJohannes Berg unsigned int maxtype; 24d07dcf9aSJohannes Berg } policies[]; 25d07dcf9aSJohannes Berg }; 26d07dcf9aSJohannes Berg 27adc84845SJakub Kicinski static int add_policy(struct netlink_policy_dump_state **statep, 28d07dcf9aSJohannes Berg const struct nla_policy *policy, 29d07dcf9aSJohannes Berg unsigned int maxtype) 30d07dcf9aSJohannes Berg { 31adc84845SJakub Kicinski struct netlink_policy_dump_state *state = *statep; 32d07dcf9aSJohannes Berg unsigned int n_alloc, i; 33d07dcf9aSJohannes Berg 34d07dcf9aSJohannes Berg if (!policy || !maxtype) 35d07dcf9aSJohannes Berg return 0; 36d07dcf9aSJohannes Berg 37d07dcf9aSJohannes Berg for (i = 0; i < state->n_alloc; i++) { 38899b07c5SJohannes Berg if (state->policies[i].policy == policy && 39899b07c5SJohannes Berg state->policies[i].maxtype == maxtype) 40d07dcf9aSJohannes Berg return 0; 41d07dcf9aSJohannes Berg 42d07dcf9aSJohannes Berg if (!state->policies[i].policy) { 43d07dcf9aSJohannes Berg state->policies[i].policy = policy; 44d07dcf9aSJohannes Berg state->policies[i].maxtype = maxtype; 45d07dcf9aSJohannes Berg return 0; 46d07dcf9aSJohannes Berg } 47d07dcf9aSJohannes Berg } 48d07dcf9aSJohannes Berg 49d07dcf9aSJohannes Berg n_alloc = state->n_alloc + INITIAL_POLICIES_ALLOC; 50d07dcf9aSJohannes Berg state = krealloc(state, struct_size(state, policies, n_alloc), 51d07dcf9aSJohannes Berg GFP_KERNEL); 52d07dcf9aSJohannes Berg if (!state) 53d07dcf9aSJohannes Berg return -ENOMEM; 54d07dcf9aSJohannes Berg 55d1fb5559SJohannes Berg memset(&state->policies[state->n_alloc], 0, 56d1fb5559SJohannes Berg flex_array_size(state, policies, n_alloc - state->n_alloc)); 57d1fb5559SJohannes Berg 58d07dcf9aSJohannes Berg state->policies[state->n_alloc].policy = policy; 59d07dcf9aSJohannes Berg state->policies[state->n_alloc].maxtype = maxtype; 60d07dcf9aSJohannes Berg state->n_alloc = n_alloc; 61d07dcf9aSJohannes Berg *statep = state; 62d07dcf9aSJohannes Berg 63d07dcf9aSJohannes Berg return 0; 64d07dcf9aSJohannes Berg } 65d07dcf9aSJohannes Berg 6604a351a6SJohannes Berg /** 6704a351a6SJohannes Berg * netlink_policy_dump_get_policy_idx - retrieve policy index 6804a351a6SJohannes Berg * @state: the policy dump state 6904a351a6SJohannes Berg * @policy: the policy to find 7004a351a6SJohannes Berg * @maxtype: the policy's maxattr 7104a351a6SJohannes Berg * 7204a351a6SJohannes Berg * Returns: the index of the given policy in the dump state 7304a351a6SJohannes Berg * 7404a351a6SJohannes Berg * Call this to find a policy index when you've added multiple and e.g. 7504a351a6SJohannes Berg * need to tell userspace which command has which policy (by index). 7604a351a6SJohannes Berg * 7704a351a6SJohannes Berg * Note: this will WARN and return 0 if the policy isn't found, which 7804a351a6SJohannes Berg * means it wasn't added in the first place, which would be an 7904a351a6SJohannes Berg * internal consistency bug. 8004a351a6SJohannes Berg */ 8104a351a6SJohannes Berg int netlink_policy_dump_get_policy_idx(struct netlink_policy_dump_state *state, 82899b07c5SJohannes Berg const struct nla_policy *policy, 83899b07c5SJohannes Berg unsigned int maxtype) 84d07dcf9aSJohannes Berg { 85d07dcf9aSJohannes Berg unsigned int i; 86d07dcf9aSJohannes Berg 8704a351a6SJohannes Berg if (WARN_ON(!policy || !maxtype)) 8804a351a6SJohannes Berg return 0; 8904a351a6SJohannes Berg 90d07dcf9aSJohannes Berg for (i = 0; i < state->n_alloc; i++) { 91899b07c5SJohannes Berg if (state->policies[i].policy == policy && 92899b07c5SJohannes Berg state->policies[i].maxtype == maxtype) 93d07dcf9aSJohannes Berg return i; 94d07dcf9aSJohannes Berg } 95d07dcf9aSJohannes Berg 9604a351a6SJohannes Berg WARN_ON(1); 9704a351a6SJohannes Berg return 0; 98d07dcf9aSJohannes Berg } 99d07dcf9aSJohannes Berg 10004a351a6SJohannes Berg static struct netlink_policy_dump_state *alloc_state(void) 101d07dcf9aSJohannes Berg { 102adc84845SJakub Kicinski struct netlink_policy_dump_state *state; 10304a351a6SJohannes Berg 10404a351a6SJohannes Berg state = kzalloc(struct_size(state, policies, INITIAL_POLICIES_ALLOC), 10504a351a6SJohannes Berg GFP_KERNEL); 10604a351a6SJohannes Berg if (!state) 10704a351a6SJohannes Berg return ERR_PTR(-ENOMEM); 10804a351a6SJohannes Berg state->n_alloc = INITIAL_POLICIES_ALLOC; 10904a351a6SJohannes Berg 11004a351a6SJohannes Berg return state; 11104a351a6SJohannes Berg } 11204a351a6SJohannes Berg 11304a351a6SJohannes Berg /** 11404a351a6SJohannes Berg * netlink_policy_dump_add_policy - add a policy to the dump 11504a351a6SJohannes Berg * @pstate: state to add to, may be reallocated, must be %NULL the first time 11604a351a6SJohannes Berg * @policy: the new policy to add to the dump 11704a351a6SJohannes Berg * @maxtype: the new policy's max attr type 11804a351a6SJohannes Berg * 11904a351a6SJohannes Berg * Returns: 0 on success, a negative error code otherwise. 12004a351a6SJohannes Berg * 12104a351a6SJohannes Berg * Call this to allocate a policy dump state, and to add policies to it. This 12204a351a6SJohannes Berg * should be called from the dump start() callback. 12304a351a6SJohannes Berg * 12404a351a6SJohannes Berg * Note: on failures, any previously allocated state is freed. 12504a351a6SJohannes Berg */ 12604a351a6SJohannes Berg int netlink_policy_dump_add_policy(struct netlink_policy_dump_state **pstate, 12704a351a6SJohannes Berg const struct nla_policy *policy, 12804a351a6SJohannes Berg unsigned int maxtype) 12904a351a6SJohannes Berg { 13004a351a6SJohannes Berg struct netlink_policy_dump_state *state = *pstate; 131d07dcf9aSJohannes Berg unsigned int policy_idx; 132d07dcf9aSJohannes Berg int err; 133d07dcf9aSJohannes Berg 13404a351a6SJohannes Berg if (!state) { 13504a351a6SJohannes Berg state = alloc_state(); 13604a351a6SJohannes Berg if (IS_ERR(state)) 13704a351a6SJohannes Berg return PTR_ERR(state); 13804a351a6SJohannes Berg } 139d07dcf9aSJohannes Berg 140d07dcf9aSJohannes Berg /* 141d07dcf9aSJohannes Berg * walk the policies and nested ones first, and build 142d07dcf9aSJohannes Berg * a linear list of them. 143d07dcf9aSJohannes Berg */ 144d07dcf9aSJohannes Berg 145d07dcf9aSJohannes Berg err = add_policy(&state, policy, maxtype); 146d07dcf9aSJohannes Berg if (err) 147d07dcf9aSJohannes Berg return err; 148d07dcf9aSJohannes Berg 149d07dcf9aSJohannes Berg for (policy_idx = 0; 150d07dcf9aSJohannes Berg policy_idx < state->n_alloc && state->policies[policy_idx].policy; 151d07dcf9aSJohannes Berg policy_idx++) { 152d07dcf9aSJohannes Berg const struct nla_policy *policy; 153d07dcf9aSJohannes Berg unsigned int type; 154d07dcf9aSJohannes Berg 155d07dcf9aSJohannes Berg policy = state->policies[policy_idx].policy; 156d07dcf9aSJohannes Berg 157d07dcf9aSJohannes Berg for (type = 0; 158d07dcf9aSJohannes Berg type <= state->policies[policy_idx].maxtype; 159d07dcf9aSJohannes Berg type++) { 160d07dcf9aSJohannes Berg switch (policy[type].type) { 161d07dcf9aSJohannes Berg case NLA_NESTED: 162d07dcf9aSJohannes Berg case NLA_NESTED_ARRAY: 163d07dcf9aSJohannes Berg err = add_policy(&state, 164d07dcf9aSJohannes Berg policy[type].nested_policy, 165d07dcf9aSJohannes Berg policy[type].len); 166d07dcf9aSJohannes Berg if (err) 167d07dcf9aSJohannes Berg return err; 168d07dcf9aSJohannes Berg break; 169d07dcf9aSJohannes Berg default: 170d07dcf9aSJohannes Berg break; 171d07dcf9aSJohannes Berg } 172d07dcf9aSJohannes Berg } 173d07dcf9aSJohannes Berg } 174d07dcf9aSJohannes Berg 17504a351a6SJohannes Berg *pstate = state; 176d07dcf9aSJohannes Berg return 0; 177d07dcf9aSJohannes Berg } 178d07dcf9aSJohannes Berg 179adc84845SJakub Kicinski static bool 180adc84845SJakub Kicinski netlink_policy_dump_finished(struct netlink_policy_dump_state *state) 181d07dcf9aSJohannes Berg { 182d07dcf9aSJohannes Berg return state->policy_idx >= state->n_alloc || 183d07dcf9aSJohannes Berg !state->policies[state->policy_idx].policy; 184d07dcf9aSJohannes Berg } 185d07dcf9aSJohannes Berg 18604a351a6SJohannes Berg /** 18704a351a6SJohannes Berg * netlink_policy_dump_loop - dumping loop indicator 18804a351a6SJohannes Berg * @state: the policy dump state 18904a351a6SJohannes Berg * 19004a351a6SJohannes Berg * Returns: %true if the dump continues, %false otherwise 19104a351a6SJohannes Berg * 19204a351a6SJohannes Berg * Note: this frees the dump state when finishing 19304a351a6SJohannes Berg */ 194adc84845SJakub Kicinski bool netlink_policy_dump_loop(struct netlink_policy_dump_state *state) 195d07dcf9aSJohannes Berg { 196949ca6b8SJohannes Berg return !netlink_policy_dump_finished(state); 197d07dcf9aSJohannes Berg } 198d07dcf9aSJohannes Berg 19944f3625bSJohannes Berg int netlink_policy_dump_attr_size_estimate(const struct nla_policy *pt) 20044f3625bSJohannes Berg { 20144f3625bSJohannes Berg /* nested + type */ 20244f3625bSJohannes Berg int common = 2 * nla_attr_size(sizeof(u32)); 20344f3625bSJohannes Berg 20444f3625bSJohannes Berg switch (pt->type) { 20544f3625bSJohannes Berg case NLA_UNSPEC: 20644f3625bSJohannes Berg case NLA_REJECT: 20744f3625bSJohannes Berg /* these actually don't need any space */ 20844f3625bSJohannes Berg return 0; 20944f3625bSJohannes Berg case NLA_NESTED: 21044f3625bSJohannes Berg case NLA_NESTED_ARRAY: 21144f3625bSJohannes Berg /* common, policy idx, policy maxattr */ 21244f3625bSJohannes Berg return common + 2 * nla_attr_size(sizeof(u32)); 21344f3625bSJohannes Berg case NLA_U8: 21444f3625bSJohannes Berg case NLA_U16: 21544f3625bSJohannes Berg case NLA_U32: 21644f3625bSJohannes Berg case NLA_U64: 21744f3625bSJohannes Berg case NLA_MSECS: 21844f3625bSJohannes Berg case NLA_S8: 21944f3625bSJohannes Berg case NLA_S16: 22044f3625bSJohannes Berg case NLA_S32: 22144f3625bSJohannes Berg case NLA_S64: 22244f3625bSJohannes Berg /* maximum is common, u64 min/max with padding */ 22344f3625bSJohannes Berg return common + 22444f3625bSJohannes Berg 2 * (nla_attr_size(0) + nla_attr_size(sizeof(u64))); 22544f3625bSJohannes Berg case NLA_BITFIELD32: 22644f3625bSJohannes Berg return common + nla_attr_size(sizeof(u32)); 22744f3625bSJohannes Berg case NLA_STRING: 22844f3625bSJohannes Berg case NLA_NUL_STRING: 22944f3625bSJohannes Berg case NLA_BINARY: 23044f3625bSJohannes Berg /* maximum is common, u32 min-length/max-length */ 23144f3625bSJohannes Berg return common + 2 * nla_attr_size(sizeof(u32)); 23244f3625bSJohannes Berg case NLA_FLAG: 23344f3625bSJohannes Berg return common; 23444f3625bSJohannes Berg } 23544f3625bSJohannes Berg 23644f3625bSJohannes Berg /* this should then cause a warning later */ 23744f3625bSJohannes Berg return 0; 23844f3625bSJohannes Berg } 23944f3625bSJohannes Berg 240d2681e93SJohannes Berg static int 241d2681e93SJohannes Berg __netlink_policy_dump_write_attr(struct netlink_policy_dump_state *state, 242d2681e93SJohannes Berg struct sk_buff *skb, 243d2681e93SJohannes Berg const struct nla_policy *pt, 244d2681e93SJohannes Berg int nestattr) 245d07dcf9aSJohannes Berg { 24644f3625bSJohannes Berg int estimate = netlink_policy_dump_attr_size_estimate(pt); 247d07dcf9aSJohannes Berg enum netlink_attribute_type type; 248d2681e93SJohannes Berg struct nlattr *attr; 249d07dcf9aSJohannes Berg 250d2681e93SJohannes Berg attr = nla_nest_start(skb, nestattr); 251d07dcf9aSJohannes Berg if (!attr) 252d2681e93SJohannes Berg return -ENOBUFS; 253d07dcf9aSJohannes Berg 254d07dcf9aSJohannes Berg switch (pt->type) { 255d07dcf9aSJohannes Berg default: 256d07dcf9aSJohannes Berg case NLA_UNSPEC: 257d07dcf9aSJohannes Berg case NLA_REJECT: 258d07dcf9aSJohannes Berg /* skip - use NLA_MIN_LEN to advertise such */ 259d2681e93SJohannes Berg nla_nest_cancel(skb, attr); 260d2681e93SJohannes Berg return -ENODATA; 261d07dcf9aSJohannes Berg case NLA_NESTED: 262d07dcf9aSJohannes Berg type = NL_ATTR_TYPE_NESTED; 263df561f66SGustavo A. R. Silva fallthrough; 264d07dcf9aSJohannes Berg case NLA_NESTED_ARRAY: 265d07dcf9aSJohannes Berg if (pt->type == NLA_NESTED_ARRAY) 266d07dcf9aSJohannes Berg type = NL_ATTR_TYPE_NESTED_ARRAY; 267d2681e93SJohannes Berg if (state && pt->nested_policy && pt->len && 268d07dcf9aSJohannes Berg (nla_put_u32(skb, NL_POLICY_TYPE_ATTR_POLICY_IDX, 26904a351a6SJohannes Berg netlink_policy_dump_get_policy_idx(state, 27004a351a6SJohannes Berg pt->nested_policy, 271899b07c5SJohannes Berg pt->len)) || 272d07dcf9aSJohannes Berg nla_put_u32(skb, NL_POLICY_TYPE_ATTR_POLICY_MAXTYPE, 273d07dcf9aSJohannes Berg pt->len))) 274d07dcf9aSJohannes Berg goto nla_put_failure; 275d07dcf9aSJohannes Berg break; 276d07dcf9aSJohannes Berg case NLA_U8: 277d07dcf9aSJohannes Berg case NLA_U16: 278d07dcf9aSJohannes Berg case NLA_U32: 279d07dcf9aSJohannes Berg case NLA_U64: 280d07dcf9aSJohannes Berg case NLA_MSECS: { 281d07dcf9aSJohannes Berg struct netlink_range_validation range; 282d07dcf9aSJohannes Berg 283d07dcf9aSJohannes Berg if (pt->type == NLA_U8) 284d07dcf9aSJohannes Berg type = NL_ATTR_TYPE_U8; 285d07dcf9aSJohannes Berg else if (pt->type == NLA_U16) 286d07dcf9aSJohannes Berg type = NL_ATTR_TYPE_U16; 287d07dcf9aSJohannes Berg else if (pt->type == NLA_U32) 288d07dcf9aSJohannes Berg type = NL_ATTR_TYPE_U32; 289d07dcf9aSJohannes Berg else 290d07dcf9aSJohannes Berg type = NL_ATTR_TYPE_U64; 291d07dcf9aSJohannes Berg 292bdbb4e29SJakub Kicinski if (pt->validation_type == NLA_VALIDATE_MASK) { 293bdbb4e29SJakub Kicinski if (nla_put_u64_64bit(skb, NL_POLICY_TYPE_ATTR_MASK, 294bdbb4e29SJakub Kicinski pt->mask, 295bdbb4e29SJakub Kicinski NL_POLICY_TYPE_ATTR_PAD)) 296bdbb4e29SJakub Kicinski goto nla_put_failure; 297bdbb4e29SJakub Kicinski break; 298bdbb4e29SJakub Kicinski } 299bdbb4e29SJakub Kicinski 300d07dcf9aSJohannes Berg nla_get_range_unsigned(pt, &range); 301d07dcf9aSJohannes Berg 302d07dcf9aSJohannes Berg if (nla_put_u64_64bit(skb, NL_POLICY_TYPE_ATTR_MIN_VALUE_U, 303d07dcf9aSJohannes Berg range.min, NL_POLICY_TYPE_ATTR_PAD) || 304d07dcf9aSJohannes Berg nla_put_u64_64bit(skb, NL_POLICY_TYPE_ATTR_MAX_VALUE_U, 305d07dcf9aSJohannes Berg range.max, NL_POLICY_TYPE_ATTR_PAD)) 306d07dcf9aSJohannes Berg goto nla_put_failure; 307d07dcf9aSJohannes Berg break; 308d07dcf9aSJohannes Berg } 309d07dcf9aSJohannes Berg case NLA_S8: 310d07dcf9aSJohannes Berg case NLA_S16: 311d07dcf9aSJohannes Berg case NLA_S32: 312d07dcf9aSJohannes Berg case NLA_S64: { 313d07dcf9aSJohannes Berg struct netlink_range_validation_signed range; 314d07dcf9aSJohannes Berg 315d07dcf9aSJohannes Berg if (pt->type == NLA_S8) 316d07dcf9aSJohannes Berg type = NL_ATTR_TYPE_S8; 317d07dcf9aSJohannes Berg else if (pt->type == NLA_S16) 318d07dcf9aSJohannes Berg type = NL_ATTR_TYPE_S16; 319d07dcf9aSJohannes Berg else if (pt->type == NLA_S32) 320d07dcf9aSJohannes Berg type = NL_ATTR_TYPE_S32; 321d07dcf9aSJohannes Berg else 322d07dcf9aSJohannes Berg type = NL_ATTR_TYPE_S64; 323d07dcf9aSJohannes Berg 324d07dcf9aSJohannes Berg nla_get_range_signed(pt, &range); 325d07dcf9aSJohannes Berg 326d07dcf9aSJohannes Berg if (nla_put_s64(skb, NL_POLICY_TYPE_ATTR_MIN_VALUE_S, 327d07dcf9aSJohannes Berg range.min, NL_POLICY_TYPE_ATTR_PAD) || 328d07dcf9aSJohannes Berg nla_put_s64(skb, NL_POLICY_TYPE_ATTR_MAX_VALUE_S, 329d07dcf9aSJohannes Berg range.max, NL_POLICY_TYPE_ATTR_PAD)) 330d07dcf9aSJohannes Berg goto nla_put_failure; 331d07dcf9aSJohannes Berg break; 332d07dcf9aSJohannes Berg } 333d07dcf9aSJohannes Berg case NLA_BITFIELD32: 334d07dcf9aSJohannes Berg type = NL_ATTR_TYPE_BITFIELD32; 335d07dcf9aSJohannes Berg if (nla_put_u32(skb, NL_POLICY_TYPE_ATTR_BITFIELD32_MASK, 336d07dcf9aSJohannes Berg pt->bitfield32_valid)) 337d07dcf9aSJohannes Berg goto nla_put_failure; 338d07dcf9aSJohannes Berg break; 339d07dcf9aSJohannes Berg case NLA_STRING: 340d07dcf9aSJohannes Berg case NLA_NUL_STRING: 341d07dcf9aSJohannes Berg case NLA_BINARY: 342d07dcf9aSJohannes Berg if (pt->type == NLA_STRING) 343d07dcf9aSJohannes Berg type = NL_ATTR_TYPE_STRING; 344d07dcf9aSJohannes Berg else if (pt->type == NLA_NUL_STRING) 345d07dcf9aSJohannes Berg type = NL_ATTR_TYPE_NUL_STRING; 346d07dcf9aSJohannes Berg else 347d07dcf9aSJohannes Berg type = NL_ATTR_TYPE_BINARY; 3488aa26c57SJohannes Berg 349c30a3c95SJohannes Berg if (pt->validation_type == NLA_VALIDATE_RANGE || 350c30a3c95SJohannes Berg pt->validation_type == NLA_VALIDATE_RANGE_WARN_TOO_LONG) { 3518aa26c57SJohannes Berg struct netlink_range_validation range; 3528aa26c57SJohannes Berg 3538aa26c57SJohannes Berg nla_get_range_unsigned(pt, &range); 3548aa26c57SJohannes Berg 3558aa26c57SJohannes Berg if (range.min && 3568aa26c57SJohannes Berg nla_put_u32(skb, NL_POLICY_TYPE_ATTR_MIN_LENGTH, 3578aa26c57SJohannes Berg range.min)) 358d07dcf9aSJohannes Berg goto nla_put_failure; 3598aa26c57SJohannes Berg 3608aa26c57SJohannes Berg if (range.max < U16_MAX && 3618aa26c57SJohannes Berg nla_put_u32(skb, NL_POLICY_TYPE_ATTR_MAX_LENGTH, 3628aa26c57SJohannes Berg range.max)) 363d07dcf9aSJohannes Berg goto nla_put_failure; 3648aa26c57SJohannes Berg } else if (pt->len && 3658aa26c57SJohannes Berg nla_put_u32(skb, NL_POLICY_TYPE_ATTR_MAX_LENGTH, 3668aa26c57SJohannes Berg pt->len)) { 3678aa26c57SJohannes Berg goto nla_put_failure; 3688aa26c57SJohannes Berg } 369d07dcf9aSJohannes Berg break; 370d07dcf9aSJohannes Berg case NLA_FLAG: 371d07dcf9aSJohannes Berg type = NL_ATTR_TYPE_FLAG; 372d07dcf9aSJohannes Berg break; 373d07dcf9aSJohannes Berg } 374d07dcf9aSJohannes Berg 375d07dcf9aSJohannes Berg if (nla_put_u32(skb, NL_POLICY_TYPE_ATTR_TYPE, type)) 376d07dcf9aSJohannes Berg goto nla_put_failure; 377d07dcf9aSJohannes Berg 378d07dcf9aSJohannes Berg nla_nest_end(skb, attr); 37944f3625bSJohannes Berg WARN_ON(attr->nla_len > estimate); 38044f3625bSJohannes Berg 381d2681e93SJohannes Berg return 0; 382d2681e93SJohannes Berg nla_put_failure: 383d2681e93SJohannes Berg nla_nest_cancel(skb, attr); 384d2681e93SJohannes Berg return -ENOBUFS; 385d2681e93SJohannes Berg } 386d2681e93SJohannes Berg 387d2681e93SJohannes Berg /** 38844f3625bSJohannes Berg * netlink_policy_dump_write_attr - write a given attribute policy 38944f3625bSJohannes Berg * @skb: the message skb to write to 39044f3625bSJohannes Berg * @pt: the attribute's policy 39144f3625bSJohannes Berg * @nestattr: the nested attribute ID to use 39244f3625bSJohannes Berg * 39344f3625bSJohannes Berg * Returns: 0 on success, an error code otherwise; -%ENODATA is 39444f3625bSJohannes Berg * special, indicating that there's no policy data and 39544f3625bSJohannes Berg * the attribute is generally rejected. 39644f3625bSJohannes Berg */ 39744f3625bSJohannes Berg int netlink_policy_dump_write_attr(struct sk_buff *skb, 39844f3625bSJohannes Berg const struct nla_policy *pt, 39944f3625bSJohannes Berg int nestattr) 40044f3625bSJohannes Berg { 40144f3625bSJohannes Berg return __netlink_policy_dump_write_attr(NULL, skb, pt, nestattr); 40244f3625bSJohannes Berg } 40344f3625bSJohannes Berg 40444f3625bSJohannes Berg /** 405d2681e93SJohannes Berg * netlink_policy_dump_write - write current policy dump attributes 406d2681e93SJohannes Berg * @skb: the message skb to write to 407d2681e93SJohannes Berg * @state: the policy dump state 408d2681e93SJohannes Berg * 409d2681e93SJohannes Berg * Returns: 0 on success, an error code otherwise 410d2681e93SJohannes Berg */ 411d2681e93SJohannes Berg int netlink_policy_dump_write(struct sk_buff *skb, 412d2681e93SJohannes Berg struct netlink_policy_dump_state *state) 413d2681e93SJohannes Berg { 414d2681e93SJohannes Berg const struct nla_policy *pt; 415d2681e93SJohannes Berg struct nlattr *policy; 416d2681e93SJohannes Berg bool again; 417d2681e93SJohannes Berg int err; 418d2681e93SJohannes Berg 419d2681e93SJohannes Berg send_attribute: 420d2681e93SJohannes Berg again = false; 421d2681e93SJohannes Berg 422d2681e93SJohannes Berg pt = &state->policies[state->policy_idx].policy[state->attr_idx]; 423d2681e93SJohannes Berg 424d2681e93SJohannes Berg policy = nla_nest_start(skb, state->policy_idx); 425d2681e93SJohannes Berg if (!policy) 426d2681e93SJohannes Berg return -ENOBUFS; 427d2681e93SJohannes Berg 428d2681e93SJohannes Berg err = __netlink_policy_dump_write_attr(state, skb, pt, state->attr_idx); 429d2681e93SJohannes Berg if (err == -ENODATA) { 430d2681e93SJohannes Berg nla_nest_cancel(skb, policy); 431d2681e93SJohannes Berg again = true; 432d2681e93SJohannes Berg goto next; 433d2681e93SJohannes Berg } else if (err) { 434d2681e93SJohannes Berg goto nla_put_failure; 435d2681e93SJohannes Berg } 436d2681e93SJohannes Berg 437d2681e93SJohannes Berg /* finish and move state to next attribute */ 438d07dcf9aSJohannes Berg nla_nest_end(skb, policy); 439d07dcf9aSJohannes Berg 440d07dcf9aSJohannes Berg next: 441d07dcf9aSJohannes Berg state->attr_idx += 1; 442d07dcf9aSJohannes Berg if (state->attr_idx > state->policies[state->policy_idx].maxtype) { 443d07dcf9aSJohannes Berg state->attr_idx = 0; 444d07dcf9aSJohannes Berg state->policy_idx++; 445d07dcf9aSJohannes Berg } 446d07dcf9aSJohannes Berg 447d07dcf9aSJohannes Berg if (again) { 448d07dcf9aSJohannes Berg if (netlink_policy_dump_finished(state)) 449d07dcf9aSJohannes Berg return -ENODATA; 450d07dcf9aSJohannes Berg goto send_attribute; 451d07dcf9aSJohannes Berg } 452d07dcf9aSJohannes Berg 453d07dcf9aSJohannes Berg return 0; 454d07dcf9aSJohannes Berg 455d07dcf9aSJohannes Berg nla_put_failure: 456d07dcf9aSJohannes Berg nla_nest_cancel(skb, policy); 457d07dcf9aSJohannes Berg return -ENOBUFS; 458d07dcf9aSJohannes Berg } 459949ca6b8SJohannes Berg 46004a351a6SJohannes Berg /** 46104a351a6SJohannes Berg * netlink_policy_dump_free - free policy dump state 46204a351a6SJohannes Berg * @state: the policy dump state to free 46304a351a6SJohannes Berg * 46404a351a6SJohannes Berg * Call this from the done() method to ensure dump state is freed. 46504a351a6SJohannes Berg */ 466adc84845SJakub Kicinski void netlink_policy_dump_free(struct netlink_policy_dump_state *state) 467949ca6b8SJohannes Berg { 468949ca6b8SJohannes Berg kfree(state); 469949ca6b8SJohannes Berg } 470