History

Merge branch 'ethtool-allow-dumping-policies-to-user-space'

Jakub Kicinski says: ==================== ethtool: allow dumping policies to user space This series wires up ethtool policies to ops, so they can be dumped to user space for feature discovery. First patch wires up GET commands, and second patch wires up SETs. The policy tables are trimmed to save space and LoC. Next - take care of linking up nested policies for the header (which is the policy what we actually care about). And once header policy is linked make sure that attribute range validation for flags is done by policy, not a conditions in the code. New type of policy is needed to validate masks (patch 6). Netlink as always staying a step ahead of all the other kernel API interfaces :) v2: - merge patches 1 & 2 -> 1 - add patch 3 & 5 - remove .max_attr from struct ethnl_request_ops ====================

David S. Miller committed 6 years ago

Commit 9faebeb2 parents 02da0b6 a0de1cd23 files · +317 −414Browse files

Unified · Split

23 files
  1. include/net/netlink.h +19 −8
  2. include/uapi/linux/netlink.h +2 −0
  3. lib/nlattr.c +36 −0
  4. net/ethtool/bitset.c +12 −14
  5. net/ethtool/cabletest.c +14 −27
  6. net/ethtool/channels.c +7 −28
  7. net/ethtool/coalesce.c +7 −38
  8. net/ethtool/debug.c +7 −17
  9. net/ethtool/eee.c +8 −24
  10. net/ethtool/features.c +7 −23
  11. net/ethtool/linkinfo.c +7 −23
  12. net/ethtool/linkmodes.c +7 −25
  13. net/ethtool/linkstate.c +3 −11
  14. net/ethtool/netlink.c +88 −36
  15. net/ethtool/netlink.h +31 −4
  16. net/ethtool/pause.c +7 −20
  17. net/ethtool/privflags.c +7 −17
  18. net/ethtool/rings.c +7 −28
  19. net/ethtool/strset.c +9 −16
  20. net/ethtool/tsinfo.c +3 −10
  21. net/ethtool/tunnels.c +14 −28
  22. net/ethtool/wol.c +7 −17
  23. net/netlink/policy.c +8 −0
include/net/netlink.h+19−8
@@ -200,6 +200,7 @@ enum nla_policy_validation { · 199 unmodified lines
200 NLA_VALIDATE_RANGE_WARN_TOO_LONG,200 NLA_VALIDATE_RANGE_WARN_TOO_LONG,
201 NLA_VALIDATE_MIN,201 NLA_VALIDATE_MIN,
202 NLA_VALIDATE_MAX,202 NLA_VALIDATE_MAX,
203 NLA_VALIDATE_MASK,
203 NLA_VALIDATE_RANGE_PTR,204 NLA_VALIDATE_RANGE_PTR,
204 NLA_VALIDATE_FUNCTION,205 NLA_VALIDATE_FUNCTION,
205};206};
@@ -317,6 +318,7 @@ struct nla_policy { · 111 unmodified lines
317 u16 len;318 u16 len;
318 union {319 union {
319 const u32 bitfield32_valid;320 const u32 bitfield32_valid;
321 const u32 mask;
320 const char *reject_message;322 const char *reject_message;
321 const struct nla_policy *nested_policy;323 const struct nla_policy *nested_policy;
322 struct netlink_range_validation *range;324 struct netlink_range_validation *range;
@@ -362,20 +364,23 @@ struct nla_policy { · 39 unmodified lines
362#define NLA_POLICY_BITFIELD32(valid) \364#define NLA_POLICY_BITFIELD32(valid) \
363 { .type = NLA_BITFIELD32, .bitfield32_valid = valid }365 { .type = NLA_BITFIELD32, .bitfield32_valid = valid }
364 366
367#define __NLA_IS_UINT_TYPE(tp) \
368 (tp == NLA_U8 || tp == NLA_U16 || tp == NLA_U32 || tp == NLA_U64)
369#define __NLA_IS_SINT_TYPE(tp) \
370 (tp == NLA_S8 || tp == NLA_S16 || tp == NLA_S32 || tp == NLA_S64)
371
365#define __NLA_ENSURE(condition) BUILD_BUG_ON_ZERO(!(condition))372#define __NLA_ENSURE(condition) BUILD_BUG_ON_ZERO(!(condition))
373#define NLA_ENSURE_UINT_TYPE(tp) \
374 (__NLA_ENSURE(__NLA_IS_UINT_TYPE(tp)) + tp)
366#define NLA_ENSURE_UINT_OR_BINARY_TYPE(tp) \375#define NLA_ENSURE_UINT_OR_BINARY_TYPE(tp) \
367 (__NLA_ENSURE(tp == NLA_U8 || tp == NLA_U16 || \376 (__NLA_ENSURE(__NLA_IS_UINT_TYPE(tp) || \
368 tp == NLA_U32 || tp == NLA_U64 || \
369 tp == NLA_MSECS || \377 tp == NLA_MSECS || \
370 tp == NLA_BINARY) + tp)378 tp == NLA_BINARY) + tp)
371#define NLA_ENSURE_SINT_TYPE(tp) \379#define NLA_ENSURE_SINT_TYPE(tp) \
372 (__NLA_ENSURE(tp == NLA_S8 || tp == NLA_S16 || \380 (__NLA_ENSURE(__NLA_IS_SINT_TYPE(tp)) + tp)
373 tp == NLA_S32 || tp == NLA_S64) + tp)
374#define NLA_ENSURE_INT_OR_BINARY_TYPE(tp) \381#define NLA_ENSURE_INT_OR_BINARY_TYPE(tp) \
375 (__NLA_ENSURE(tp == NLA_S8 || tp == NLA_U8 || \382 (__NLA_ENSURE(__NLA_IS_UINT_TYPE(tp) || \
376 tp == NLA_S16 || tp == NLA_U16 || \383 __NLA_IS_SINT_TYPE(tp) || \
377 tp == NLA_S32 || tp == NLA_U32 || \
378 tp == NLA_S64 || tp == NLA_U64 || \
379 tp == NLA_MSECS || \384 tp == NLA_MSECS || \
380 tp == NLA_BINARY) + tp)385 tp == NLA_BINARY) + tp)
381#define NLA_ENSURE_NO_VALIDATION_PTR(tp) \386#define NLA_ENSURE_NO_VALIDATION_PTR(tp) \
@@ -415,6 +420,12 @@ struct nla_policy { · 33 unmodified lines
415 .max = _max, \420 .max = _max, \
416}421}
417 422
423#define NLA_POLICY_MASK(tp, _mask) { \
424 .type = NLA_ENSURE_UINT_TYPE(tp), \
425 .validation_type = NLA_VALIDATE_MASK, \
426 .mask = _mask, \
427}
428
418#define NLA_POLICY_VALIDATE_FN(tp, fn, ...) { \429#define NLA_POLICY_VALIDATE_FN(tp, fn, ...) { \
419 .type = NLA_ENSURE_NO_VALIDATION_PTR(tp), \430 .type = NLA_ENSURE_NO_VALIDATION_PTR(tp), \
420 .validation_type = NLA_VALIDATE_FUNCTION, \431 .validation_type = NLA_VALIDATE_FUNCTION, \
include/uapi/linux/netlink.h+2−0
@@ -331,6 +331,7 @@ enum netlink_attribute_type { · 330 unmodified lines
331 * the index, if limited inside the nesting (U32)331 * the index, if limited inside the nesting (U32)
332 * @NL_POLICY_TYPE_ATTR_BITFIELD32_MASK: valid mask for the332 * @NL_POLICY_TYPE_ATTR_BITFIELD32_MASK: valid mask for the
333 * bitfield32 type (U32)333 * bitfield32 type (U32)
334 * @NL_POLICY_TYPE_ATTR_MASK: mask of valid bits for unsigned integers (U64)
334 * @NL_POLICY_TYPE_ATTR_PAD: pad attribute for 64-bit alignment335 * @NL_POLICY_TYPE_ATTR_PAD: pad attribute for 64-bit alignment
335 */336 */
336enum netlink_policy_type_attr {337enum netlink_policy_type_attr {
@@ -346,6 +347,7 @@ enum netlink_policy_type_attr { · 9 unmodified lines
346 NL_POLICY_TYPE_ATTR_POLICY_MAXTYPE,347 NL_POLICY_TYPE_ATTR_POLICY_MAXTYPE,
347 NL_POLICY_TYPE_ATTR_BITFIELD32_MASK,348 NL_POLICY_TYPE_ATTR_BITFIELD32_MASK,
348 NL_POLICY_TYPE_ATTR_PAD,349 NL_POLICY_TYPE_ATTR_PAD,
350 NL_POLICY_TYPE_ATTR_MASK,
349 351
350 /* keep last */352 /* keep last */
351 __NL_POLICY_TYPE_ATTR_MAX,353 __NL_POLICY_TYPE_ATTR_MAX,
lib/nlattr.c+36−0
@@ -323,6 +323,37 @@ static int nla_validate_int_range(const struct nla_policy *pt, · 322 unmodified lines
323 }323 }
324}324}
325 325
326static int nla_validate_mask(const struct nla_policy *pt,
327 const struct nlattr *nla,
328 struct netlink_ext_ack *extack)
329{
330 u64 value;
331
332 switch (pt->type) {
333 case NLA_U8:
334 value = nla_get_u8(nla);
335 break;
336 case NLA_U16:
337 value = nla_get_u16(nla);
338 break;
339 case NLA_U32:
340 value = nla_get_u32(nla);
341 break;
342 case NLA_U64:
343 value = nla_get_u64(nla);
344 break;
345 default:
346 return -EINVAL;
347 }
348
349 if (value & ~(u64)pt->mask) {
350 NL_SET_ERR_MSG_ATTR(extack, nla, "reserved bit set");
351 return -EINVAL;
352 }
353
354 return 0;
355}
356
326static int validate_nla(const struct nlattr *nla, int maxtype,357static int validate_nla(const struct nlattr *nla, int maxtype,
327 const struct nla_policy *policy, unsigned int validate,358 const struct nla_policy *policy, unsigned int validate,
328 struct netlink_ext_ack *extack, unsigned int depth)359 struct netlink_ext_ack *extack, unsigned int depth)
@@ -503,6 +534,11 @@ static int validate_nla(const struct nlattr *nla, int maxtype, · 174 unmodified lines
503 if (err)534 if (err)
504 return err;535 return err;
505 break;536 break;
537 case NLA_VALIDATE_MASK:
538 err = nla_validate_mask(pt, nla, extack);
539 if (err)
540 return err;
541 break;
506 case NLA_VALIDATE_FUNCTION:542 case NLA_VALIDATE_FUNCTION:
507 if (pt->validate) {543 if (pt->validate) {
508 err = pt->validate(nla, extack);544 err = pt->validate(nla, extack);
net/ethtool/bitset.c+12−14
@@ -302,8 +302,7 @@ nla_put_failure: · 301 unmodified lines
302 return -EMSGSIZE;302 return -EMSGSIZE;
303}303}
304 304
305static const struct nla_policy bitset_policy[ETHTOOL_A_BITSET_MAX + 1] = {305static const struct nla_policy bitset_policy[] = {
306 [ETHTOOL_A_BITSET_UNSPEC] = { .type = NLA_REJECT },
307 [ETHTOOL_A_BITSET_NOMASK] = { .type = NLA_FLAG },306 [ETHTOOL_A_BITSET_NOMASK] = { .type = NLA_FLAG },
308 [ETHTOOL_A_BITSET_SIZE] = NLA_POLICY_MAX(NLA_U32,307 [ETHTOOL_A_BITSET_SIZE] = NLA_POLICY_MAX(NLA_U32,
309 ETHNL_MAX_BITSET_SIZE),308 ETHNL_MAX_BITSET_SIZE),
@@ -312,8 +311,7 @@ static const struct nla_policy bitset_policy[ETHTOOL_A_BITSET_MAX + 1] = { · 2 unmodified lines
312 [ETHTOOL_A_BITSET_MASK] = { .type = NLA_BINARY },311 [ETHTOOL_A_BITSET_MASK] = { .type = NLA_BINARY },
313};312};
314 313
315static const struct nla_policy bit_policy[ETHTOOL_A_BITSET_BIT_MAX + 1] = {314static const struct nla_policy bit_policy[] = {
316 [ETHTOOL_A_BITSET_BIT_UNSPEC] = { .type = NLA_REJECT },
317 [ETHTOOL_A_BITSET_BIT_INDEX] = { .type = NLA_U32 },315 [ETHTOOL_A_BITSET_BIT_INDEX] = { .type = NLA_U32 },
318 [ETHTOOL_A_BITSET_BIT_NAME] = { .type = NLA_NUL_STRING },316 [ETHTOOL_A_BITSET_BIT_NAME] = { .type = NLA_NUL_STRING },
319 [ETHTOOL_A_BITSET_BIT_VALUE] = { .type = NLA_FLAG },317 [ETHTOOL_A_BITSET_BIT_VALUE] = { .type = NLA_FLAG },
@@ -329,10 +327,10 @@ static const struct nla_policy bit_policy[ETHTOOL_A_BITSET_BIT_MAX + 1] = { · 9 unmodified lines
329 */327 */
330int ethnl_bitset_is_compact(const struct nlattr *bitset, bool *compact)328int ethnl_bitset_is_compact(const struct nlattr *bitset, bool *compact)
331{329{
332 struct nlattr *tb[ETHTOOL_A_BITSET_MAX + 1];330 struct nlattr *tb[ARRAY_SIZE(bitset_policy)];
333 int ret;331 int ret;
334 332
335 ret = nla_parse_nested(tb, ETHTOOL_A_BITSET_MAX, bitset,333 ret = nla_parse_nested(tb, ARRAY_SIZE(bitset_policy) - 1, bitset,
336 bitset_policy, NULL);334 bitset_policy, NULL);
337 if (ret < 0)335 if (ret < 0)
338 return ret;336 return ret;
@@ -381,10 +379,10 @@ static int ethnl_parse_bit(unsigned int *index, bool *val, unsigned int nbits, · 42 unmodified lines
381 ethnl_string_array_t names,379 ethnl_string_array_t names,
382 struct netlink_ext_ack *extack)380 struct netlink_ext_ack *extack)
383{381{
384 struct nlattr *tb[ETHTOOL_A_BITSET_BIT_MAX + 1];382 struct nlattr *tb[ARRAY_SIZE(bit_policy)];
385 int ret, idx;383 int ret, idx;
386 384
387 ret = nla_parse_nested(tb, ETHTOOL_A_BITSET_BIT_MAX, bit_attr,385 ret = nla_parse_nested(tb, ARRAY_SIZE(bit_policy) - 1, bit_attr,
388 bit_policy, extack);386 bit_policy, extack);
389 if (ret < 0)387 if (ret < 0)
390 return ret;388 return ret;
@@ -555,15 +553,15 @@ int ethnl_update_bitset32(u32 *bitmap, unsigned int nbits, · 164 unmodified lines
555 const struct nlattr *attr, ethnl_string_array_t names,553 const struct nlattr *attr, ethnl_string_array_t names,
556 struct netlink_ext_ack *extack, bool *mod)554 struct netlink_ext_ack *extack, bool *mod)
557{555{
558 struct nlattr *tb[ETHTOOL_A_BITSET_MAX + 1];556 struct nlattr *tb[ARRAY_SIZE(bitset_policy)];
559 unsigned int change_bits;557 unsigned int change_bits;
560 bool no_mask;558 bool no_mask;
561 int ret;559 int ret;
562 560
563 if (!attr)561 if (!attr)
564 return 0;562 return 0;
565 ret = nla_parse_nested(tb, ETHTOOL_A_BITSET_MAX, attr, bitset_policy,563 ret = nla_parse_nested(tb, ARRAY_SIZE(bitset_policy) - 1, attr,
566 extack);564 bitset_policy, extack);
567 if (ret < 0)565 if (ret < 0)
568 return ret;566 return ret;
569 567
@@ -608,7 +606,7 @@ int ethnl_parse_bitset(unsigned long *val, unsigned long *mask, · 38 unmodified lines
608 ethnl_string_array_t names,606 ethnl_string_array_t names,
609 struct netlink_ext_ack *extack)607 struct netlink_ext_ack *extack)
610{608{
611 struct nlattr *tb[ETHTOOL_A_BITSET_MAX + 1];609 struct nlattr *tb[ARRAY_SIZE(bitset_policy)];
612 const struct nlattr *bit_attr;610 const struct nlattr *bit_attr;
613 bool no_mask;611 bool no_mask;
614 int rem;612 int rem;
@@ -616,8 +614,8 @@ int ethnl_parse_bitset(unsigned long *val, unsigned long *mask, · 1 unmodified line
616 614
617 if (!attr)615 if (!attr)
618 return 0;616 return 0;
619 ret = nla_parse_nested(tb, ETHTOOL_A_BITSET_MAX, attr, bitset_policy,617 ret = nla_parse_nested(tb, ARRAY_SIZE(bitset_policy) - 1, attr,
620 extack);618 bitset_policy, extack);
621 if (ret < 0)619 if (ret < 0)
622 return ret;620 return ret;
623 no_mask = tb[ETHTOOL_A_BITSET_NOMASK];621 no_mask = tb[ETHTOOL_A_BITSET_NOMASK];
net/ethtool/cabletest.c+14−27
@@ -11,10 +11,9 @@ · 10 unmodified lines
11 */11 */
12#define MAX_CABLE_LENGTH_CM (150 * 100)12#define MAX_CABLE_LENGTH_CM (150 * 100)
13 13
14static const struct nla_policy14const struct nla_policy ethnl_cable_test_act_policy[] = {
15cable_test_act_policy[ETHTOOL_A_CABLE_TEST_MAX + 1] = {15 [ETHTOOL_A_CABLE_TEST_HEADER] =
16 [ETHTOOL_A_CABLE_TEST_UNSPEC] = { .type = NLA_REJECT },16 NLA_POLICY_NESTED(ethnl_header_policy),
17 [ETHTOOL_A_CABLE_TEST_HEADER] = { .type = NLA_NESTED },
18};17};
19 18
20static int ethnl_cable_test_started(struct phy_device *phydev, u8 cmd)19static int ethnl_cable_test_started(struct phy_device *phydev, u8 cmd)
@@ -56,18 +55,12 @@ out: · 35 unmodified lines
56 55
57int ethnl_act_cable_test(struct sk_buff *skb, struct genl_info *info)56int ethnl_act_cable_test(struct sk_buff *skb, struct genl_info *info)
58{57{
59 struct nlattr *tb[ETHTOOL_A_CABLE_TEST_MAX + 1];
60 struct ethnl_req_info req_info = {};58 struct ethnl_req_info req_info = {};
61 const struct ethtool_phy_ops *ops;59 const struct ethtool_phy_ops *ops;
60 struct nlattr **tb = info->attrs;
62 struct net_device *dev;61 struct net_device *dev;
63 int ret;62 int ret;
64 63
65 ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb,
66 ETHTOOL_A_CABLE_TEST_MAX,
67 cable_test_act_policy, info->extack);
68 if (ret < 0)
69 return ret;
70
71 ret = ethnl_parse_header_dev_get(&req_info,64 ret = ethnl_parse_header_dev_get(&req_info,
72 tb[ETHTOOL_A_CABLE_TEST_HEADER],65 tb[ETHTOOL_A_CABLE_TEST_HEADER],
73 genl_info_net(info), info->extack,66 genl_info_net(info), info->extack,
@@ -218,18 +211,16 @@ struct cable_test_tdr_req_info { · 144 unmodified lines
218 struct ethnl_req_info base;211 struct ethnl_req_info base;
219};212};
220 213
221static const struct nla_policy214static const struct nla_policy cable_test_tdr_act_cfg_policy[] = {
222cable_test_tdr_act_cfg_policy[ETHTOOL_A_CABLE_TEST_TDR_CFG_MAX + 1] = {
223 [ETHTOOL_A_CABLE_TEST_TDR_CFG_FIRST] = { .type = NLA_U32 },215 [ETHTOOL_A_CABLE_TEST_TDR_CFG_FIRST] = { .type = NLA_U32 },
224 [ETHTOOL_A_CABLE_TEST_TDR_CFG_LAST] = { .type = NLA_U32 },216 [ETHTOOL_A_CABLE_TEST_TDR_CFG_LAST] = { .type = NLA_U32 },
225 [ETHTOOL_A_CABLE_TEST_TDR_CFG_STEP] = { .type = NLA_U32 },217 [ETHTOOL_A_CABLE_TEST_TDR_CFG_STEP] = { .type = NLA_U32 },
226 [ETHTOOL_A_CABLE_TEST_TDR_CFG_PAIR] = { .type = NLA_U8 },218 [ETHTOOL_A_CABLE_TEST_TDR_CFG_PAIR] = { .type = NLA_U8 },
227};219};
228 220
229static const struct nla_policy221const struct nla_policy ethnl_cable_test_tdr_act_policy[] = {
230cable_test_tdr_act_policy[ETHTOOL_A_CABLE_TEST_TDR_MAX + 1] = {222 [ETHTOOL_A_CABLE_TEST_TDR_HEADER] =
231 [ETHTOOL_A_CABLE_TEST_TDR_UNSPEC] = { .type = NLA_REJECT },223 NLA_POLICY_NESTED(ethnl_header_policy),
232 [ETHTOOL_A_CABLE_TEST_TDR_HEADER] = { .type = NLA_NESTED },
233 [ETHTOOL_A_CABLE_TEST_TDR_CFG] = { .type = NLA_NESTED },224 [ETHTOOL_A_CABLE_TEST_TDR_CFG] = { .type = NLA_NESTED },
234};225};
235 226
@@ -238,7 +229,7 @@ static int ethnl_act_cable_test_tdr_cfg(const struct nlattr *nest, · 2 unmodified lines
238 struct genl_info *info,229 struct genl_info *info,
239 struct phy_tdr_config *cfg)230 struct phy_tdr_config *cfg)
240{231{
241 struct nlattr *tb[ETHTOOL_A_CABLE_TEST_TDR_CFG_MAX + 1];232 struct nlattr *tb[ARRAY_SIZE(cable_test_tdr_act_cfg_policy)];
242 int ret;233 int ret;
243 234
244 cfg->first = 100;235 cfg->first = 100;
@@ -249,8 +240,10 @@ static int ethnl_act_cable_test_tdr_cfg(const struct nlattr *nest, · 4 unmodified lines
249 if (!nest)240 if (!nest)
250 return 0;241 return 0;
251 242
252 ret = nla_parse_nested(tb, ETHTOOL_A_CABLE_TEST_TDR_CFG_MAX, nest,243 ret = nla_parse_nested(tb,
253 cable_test_tdr_act_cfg_policy, info->extack);244 ARRAY_SIZE(cable_test_tdr_act_cfg_policy) - 1,
245 nest, cable_test_tdr_act_cfg_policy,
246 info->extack);
254 if (ret < 0)247 if (ret < 0)
255 return ret;248 return ret;
256 249
@@ -313,19 +306,13 @@ static int ethnl_act_cable_test_tdr_cfg(const struct nlattr *nest, · 56 unmodified lines
313 306
314int ethnl_act_cable_test_tdr(struct sk_buff *skb, struct genl_info *info)307int ethnl_act_cable_test_tdr(struct sk_buff *skb, struct genl_info *info)
315{308{
316 struct nlattr *tb[ETHTOOL_A_CABLE_TEST_TDR_MAX + 1];
317 struct ethnl_req_info req_info = {};309 struct ethnl_req_info req_info = {};
318 const struct ethtool_phy_ops *ops;310 const struct ethtool_phy_ops *ops;
311 struct nlattr **tb = info->attrs;
319 struct phy_tdr_config cfg;312 struct phy_tdr_config cfg;
320 struct net_device *dev;313 struct net_device *dev;
321 int ret;314 int ret;
322 315
323 ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb,
324 ETHTOOL_A_CABLE_TEST_TDR_MAX,
325 cable_test_tdr_act_policy, info->extack);
326 if (ret < 0)
327 return ret;
328
329 ret = ethnl_parse_header_dev_get(&req_info,316 ret = ethnl_parse_header_dev_get(&req_info,
330 tb[ETHTOOL_A_CABLE_TEST_TDR_HEADER],317 tb[ETHTOOL_A_CABLE_TEST_TDR_HEADER],
331 genl_info_net(info), info->extack,318 genl_info_net(info), info->extack,
net/ethtool/channels.c+7−28
@@ -17,18 +17,9 @@ struct channels_reply_data { · 16 unmodified lines
17#define CHANNELS_REPDATA(__reply_base) \17#define CHANNELS_REPDATA(__reply_base) \
18 container_of(__reply_base, struct channels_reply_data, base)18 container_of(__reply_base, struct channels_reply_data, base)
19 19
20static const struct nla_policy20const struct nla_policy ethnl_channels_get_policy[] = {
21channels_get_policy[ETHTOOL_A_CHANNELS_MAX + 1] = {21 [ETHTOOL_A_CHANNELS_HEADER] =
22 [ETHTOOL_A_CHANNELS_UNSPEC] = { .type = NLA_REJECT },22 NLA_POLICY_NESTED(ethnl_header_policy),
23 [ETHTOOL_A_CHANNELS_HEADER] = { .type = NLA_NESTED },
24 [ETHTOOL_A_CHANNELS_RX_MAX] = { .type = NLA_REJECT },
25 [ETHTOOL_A_CHANNELS_TX_MAX] = { .type = NLA_REJECT },
26 [ETHTOOL_A_CHANNELS_OTHER_MAX] = { .type = NLA_REJECT },
27 [ETHTOOL_A_CHANNELS_COMBINED_MAX] = { .type = NLA_REJECT },
28 [ETHTOOL_A_CHANNELS_RX_COUNT] = { .type = NLA_REJECT },
29 [ETHTOOL_A_CHANNELS_TX_COUNT] = { .type = NLA_REJECT },
30 [ETHTOOL_A_CHANNELS_OTHER_COUNT] = { .type = NLA_REJECT },
31 [ETHTOOL_A_CHANNELS_COMBINED_COUNT] = { .type = NLA_REJECT },
32};23};
33 24
34static int channels_prepare_data(const struct ethnl_req_info *req_base,25static int channels_prepare_data(const struct ethnl_req_info *req_base,
@@ -99,10 +90,8 @@ const struct ethnl_request_ops ethnl_channels_request_ops = { · 64 unmodified lines
99 .request_cmd = ETHTOOL_MSG_CHANNELS_GET,90 .request_cmd = ETHTOOL_MSG_CHANNELS_GET,
100 .reply_cmd = ETHTOOL_MSG_CHANNELS_GET_REPLY,91 .reply_cmd = ETHTOOL_MSG_CHANNELS_GET_REPLY,
101 .hdr_attr = ETHTOOL_A_CHANNELS_HEADER,92 .hdr_attr = ETHTOOL_A_CHANNELS_HEADER,
102 .max_attr = ETHTOOL_A_CHANNELS_MAX,
103 .req_info_size = sizeof(struct channels_req_info),93 .req_info_size = sizeof(struct channels_req_info),
104 .reply_data_size = sizeof(struct channels_reply_data),94 .reply_data_size = sizeof(struct channels_reply_data),
105 .request_policy = channels_get_policy,
106 95
107 .prepare_data = channels_prepare_data,96 .prepare_data = channels_prepare_data,
108 .reply_size = channels_reply_size,97 .reply_size = channels_reply_size,
@@ -111,14 +100,9 @@ const struct ethnl_request_ops ethnl_channels_request_ops = { · 2 unmodified lines
111 100
112/* CHANNELS_SET */101/* CHANNELS_SET */
113 102
114static const struct nla_policy103const struct nla_policy ethnl_channels_set_policy[] = {
115channels_set_policy[ETHTOOL_A_CHANNELS_MAX + 1] = {104 [ETHTOOL_A_CHANNELS_HEADER] =
116 [ETHTOOL_A_CHANNELS_UNSPEC] = { .type = NLA_REJECT },105 NLA_POLICY_NESTED(ethnl_header_policy),
117 [ETHTOOL_A_CHANNELS_HEADER] = { .type = NLA_NESTED },
118 [ETHTOOL_A_CHANNELS_RX_MAX] = { .type = NLA_REJECT },
119 [ETHTOOL_A_CHANNELS_TX_MAX] = { .type = NLA_REJECT },
120 [ETHTOOL_A_CHANNELS_OTHER_MAX] = { .type = NLA_REJECT },
121 [ETHTOOL_A_CHANNELS_COMBINED_MAX] = { .type = NLA_REJECT },
122 [ETHTOOL_A_CHANNELS_RX_COUNT] = { .type = NLA_U32 },106 [ETHTOOL_A_CHANNELS_RX_COUNT] = { .type = NLA_U32 },
123 [ETHTOOL_A_CHANNELS_TX_COUNT] = { .type = NLA_U32 },107 [ETHTOOL_A_CHANNELS_TX_COUNT] = { .type = NLA_U32 },
124 [ETHTOOL_A_CHANNELS_OTHER_COUNT] = { .type = NLA_U32 },108 [ETHTOOL_A_CHANNELS_OTHER_COUNT] = { .type = NLA_U32 },
@@ -127,22 +111,17 @@ channels_set_policy[ETHTOOL_A_CHANNELS_MAX + 1] = { · 2 unmodified lines
127 111
128int ethnl_set_channels(struct sk_buff *skb, struct genl_info *info)112int ethnl_set_channels(struct sk_buff *skb, struct genl_info *info)
129{113{
130 struct nlattr *tb[ETHTOOL_A_CHANNELS_MAX + 1];
131 unsigned int from_channel, old_total, i;114 unsigned int from_channel, old_total, i;
132 bool mod = false, mod_combined = false;115 bool mod = false, mod_combined = false;
133 struct ethtool_channels channels = {};116 struct ethtool_channels channels = {};
134 struct ethnl_req_info req_info = {};117 struct ethnl_req_info req_info = {};
118 struct nlattr **tb = info->attrs;
135 const struct nlattr *err_attr;119 const struct nlattr *err_attr;
136 const struct ethtool_ops *ops;120 const struct ethtool_ops *ops;
137 struct net_device *dev;121 struct net_device *dev;
138 u32 max_rx_in_use = 0;122 u32 max_rx_in_use = 0;
139 int ret;123 int ret;
140 124
141 ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb,
142 ETHTOOL_A_CHANNELS_MAX, channels_set_policy,
143 info->extack);
144 if (ret < 0)
145 return ret;
146 ret = ethnl_parse_header_dev_get(&req_info,125 ret = ethnl_parse_header_dev_get(&req_info,
147 tb[ETHTOOL_A_CHANNELS_HEADER],126 tb[ETHTOOL_A_CHANNELS_HEADER],
148 genl_info_net(info), info->extack,127 genl_info_net(info), info->extack,
net/ethtool/coalesce.c+7−38
@@ -51,32 +51,9 @@ __CHECK_SUPPORTED_OFFSET(COALESCE_TX_USECS_HIGH); · 50 unmodified lines
51__CHECK_SUPPORTED_OFFSET(COALESCE_TX_MAX_FRAMES_HIGH);51__CHECK_SUPPORTED_OFFSET(COALESCE_TX_MAX_FRAMES_HIGH);
52__CHECK_SUPPORTED_OFFSET(COALESCE_RATE_SAMPLE_INTERVAL);52__CHECK_SUPPORTED_OFFSET(COALESCE_RATE_SAMPLE_INTERVAL);
53 53
54static const struct nla_policy54const struct nla_policy ethnl_coalesce_get_policy[] = {
55coalesce_get_policy[ETHTOOL_A_COALESCE_MAX + 1] = {55 [ETHTOOL_A_COALESCE_HEADER] =
56 [ETHTOOL_A_COALESCE_UNSPEC] = { .type = NLA_REJECT },56 NLA_POLICY_NESTED(ethnl_header_policy),
57 [ETHTOOL_A_COALESCE_HEADER] = { .type = NLA_NESTED },
58 [ETHTOOL_A_COALESCE_RX_USECS] = { .type = NLA_REJECT },
59 [ETHTOOL_A_COALESCE_RX_MAX_FRAMES] = { .type = NLA_REJECT },
60 [ETHTOOL_A_COALESCE_RX_USECS_IRQ] = { .type = NLA_REJECT },
61 [ETHTOOL_A_COALESCE_RX_MAX_FRAMES_IRQ] = { .type = NLA_REJECT },
62 [ETHTOOL_A_COALESCE_TX_USECS] = { .type = NLA_REJECT },
63 [ETHTOOL_A_COALESCE_TX_MAX_FRAMES] = { .type = NLA_REJECT },
64 [ETHTOOL_A_COALESCE_TX_USECS_IRQ] = { .type = NLA_REJECT },
65 [ETHTOOL_A_COALESCE_TX_MAX_FRAMES_IRQ] = { .type = NLA_REJECT },
66 [ETHTOOL_A_COALESCE_STATS_BLOCK_USECS] = { .type = NLA_REJECT },
67 [ETHTOOL_A_COALESCE_USE_ADAPTIVE_RX] = { .type = NLA_REJECT },
68 [ETHTOOL_A_COALESCE_USE_ADAPTIVE_TX] = { .type = NLA_REJECT },
69 [ETHTOOL_A_COALESCE_PKT_RATE_LOW] = { .type = NLA_REJECT },
70 [ETHTOOL_A_COALESCE_RX_USECS_LOW] = { .type = NLA_REJECT },
71 [ETHTOOL_A_COALESCE_RX_MAX_FRAMES_LOW] = { .type = NLA_REJECT },
72 [ETHTOOL_A_COALESCE_TX_USECS_LOW] = { .type = NLA_REJECT },
73 [ETHTOOL_A_COALESCE_TX_MAX_FRAMES_LOW] = { .type = NLA_REJECT },
74 [ETHTOOL_A_COALESCE_PKT_RATE_HIGH] = { .type = NLA_REJECT },
75 [ETHTOOL_A_COALESCE_RX_USECS_HIGH] = { .type = NLA_REJECT },
76 [ETHTOOL_A_COALESCE_RX_MAX_FRAMES_HIGH] = { .type = NLA_REJECT },
77 [ETHTOOL_A_COALESCE_TX_USECS_HIGH] = { .type = NLA_REJECT },
78 [ETHTOOL_A_COALESCE_TX_MAX_FRAMES_HIGH] = { .type = NLA_REJECT },
79 [ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL] = { .type = NLA_REJECT },
80};57};
81 58
82static int coalesce_prepare_data(const struct ethnl_req_info *req_base,59static int coalesce_prepare_data(const struct ethnl_req_info *req_base,
@@ -203,10 +180,8 @@ const struct ethnl_request_ops ethnl_coalesce_request_ops = { · 120 unmodified lines
203 .request_cmd = ETHTOOL_MSG_COALESCE_GET,180 .request_cmd = ETHTOOL_MSG_COALESCE_GET,
204 .reply_cmd = ETHTOOL_MSG_COALESCE_GET_REPLY,181 .reply_cmd = ETHTOOL_MSG_COALESCE_GET_REPLY,
205 .hdr_attr = ETHTOOL_A_COALESCE_HEADER,182 .hdr_attr = ETHTOOL_A_COALESCE_HEADER,
206 .max_attr = ETHTOOL_A_COALESCE_MAX,
207 .req_info_size = sizeof(struct coalesce_req_info),183 .req_info_size = sizeof(struct coalesce_req_info),
208 .reply_data_size = sizeof(struct coalesce_reply_data),184 .reply_data_size = sizeof(struct coalesce_reply_data),
209 .request_policy = coalesce_get_policy,
210 185
211 .prepare_data = coalesce_prepare_data,186 .prepare_data = coalesce_prepare_data,
212 .reply_size = coalesce_reply_size,187 .reply_size = coalesce_reply_size,
@@ -215,10 +190,9 @@ const struct ethnl_request_ops ethnl_coalesce_request_ops = { · 2 unmodified lines
215 190
216/* COALESCE_SET */191/* COALESCE_SET */
217 192
218static const struct nla_policy193const struct nla_policy ethnl_coalesce_set_policy[] = {
219coalesce_set_policy[ETHTOOL_A_COALESCE_MAX + 1] = {194 [ETHTOOL_A_COALESCE_HEADER] =
220 [ETHTOOL_A_COALESCE_UNSPEC] = { .type = NLA_REJECT },195 NLA_POLICY_NESTED(ethnl_header_policy),
221 [ETHTOOL_A_COALESCE_HEADER] = { .type = NLA_NESTED },
222 [ETHTOOL_A_COALESCE_RX_USECS] = { .type = NLA_U32 },196 [ETHTOOL_A_COALESCE_RX_USECS] = { .type = NLA_U32 },
223 [ETHTOOL_A_COALESCE_RX_MAX_FRAMES] = { .type = NLA_U32 },197 [ETHTOOL_A_COALESCE_RX_MAX_FRAMES] = { .type = NLA_U32 },
224 [ETHTOOL_A_COALESCE_RX_USECS_IRQ] = { .type = NLA_U32 },198 [ETHTOOL_A_COALESCE_RX_USECS_IRQ] = { .type = NLA_U32 },
@@ -245,9 +219,9 @@ coalesce_set_policy[ETHTOOL_A_COALESCE_MAX + 1] = { · 20 unmodified lines
245 219
246int ethnl_set_coalesce(struct sk_buff *skb, struct genl_info *info)220int ethnl_set_coalesce(struct sk_buff *skb, struct genl_info *info)
247{221{
248 struct nlattr *tb[ETHTOOL_A_COALESCE_MAX + 1];
249 struct ethtool_coalesce coalesce = {};222 struct ethtool_coalesce coalesce = {};
250 struct ethnl_req_info req_info = {};223 struct ethnl_req_info req_info = {};
224 struct nlattr **tb = info->attrs;
251 const struct ethtool_ops *ops;225 const struct ethtool_ops *ops;
252 struct net_device *dev;226 struct net_device *dev;
253 u32 supported_params;227 u32 supported_params;
@@ -255,11 +229,6 @@ int ethnl_set_coalesce(struct sk_buff *skb, struct genl_info *info) · 1 unmodified line
255 int ret;229 int ret;
256 u16 a;230 u16 a;
257 231
258 ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb,
259 ETHTOOL_A_COALESCE_MAX, coalesce_set_policy,
260 info->extack);
261 if (ret < 0)
262 return ret;
263 ret = ethnl_parse_header_dev_get(&req_info,232 ret = ethnl_parse_header_dev_get(&req_info,
264 tb[ETHTOOL_A_COALESCE_HEADER],233 tb[ETHTOOL_A_COALESCE_HEADER],
265 genl_info_net(info), info->extack,234 genl_info_net(info), info->extack,
net/ethtool/debug.c+7−17
@@ -16,11 +16,9 @@ struct debug_reply_data { · 15 unmodified lines
16#define DEBUG_REPDATA(__reply_base) \16#define DEBUG_REPDATA(__reply_base) \
17 container_of(__reply_base, struct debug_reply_data, base)17 container_of(__reply_base, struct debug_reply_data, base)
18 18
19static const struct nla_policy19const struct nla_policy ethnl_debug_get_policy[] = {
20debug_get_policy[ETHTOOL_A_DEBUG_MAX + 1] = {20 [ETHTOOL_A_DEBUG_HEADER] =
21 [ETHTOOL_A_DEBUG_UNSPEC] = { .type = NLA_REJECT },21 NLA_POLICY_NESTED(ethnl_header_policy),
22 [ETHTOOL_A_DEBUG_HEADER] = { .type = NLA_NESTED },
23 [ETHTOOL_A_DEBUG_MSGMASK] = { .type = NLA_REJECT },
24};22};
25 23
26static int debug_prepare_data(const struct ethnl_req_info *req_base,24static int debug_prepare_data(const struct ethnl_req_info *req_base,
@@ -69,10 +67,8 @@ const struct ethnl_request_ops ethnl_debug_request_ops = { · 42 unmodified lines
69 .request_cmd = ETHTOOL_MSG_DEBUG_GET,67 .request_cmd = ETHTOOL_MSG_DEBUG_GET,
70 .reply_cmd = ETHTOOL_MSG_DEBUG_GET_REPLY,68 .reply_cmd = ETHTOOL_MSG_DEBUG_GET_REPLY,
71 .hdr_attr = ETHTOOL_A_DEBUG_HEADER,69 .hdr_attr = ETHTOOL_A_DEBUG_HEADER,
72 .max_attr = ETHTOOL_A_DEBUG_MAX,
73 .req_info_size = sizeof(struct debug_req_info),70 .req_info_size = sizeof(struct debug_req_info),
74 .reply_data_size = sizeof(struct debug_reply_data),71 .reply_data_size = sizeof(struct debug_reply_data),
75 .request_policy = debug_get_policy,
76 72
77 .prepare_data = debug_prepare_data,73 .prepare_data = debug_prepare_data,
78 .reply_size = debug_reply_size,74 .reply_size = debug_reply_size,
@@ -81,27 +77,21 @@ const struct ethnl_request_ops ethnl_debug_request_ops = { · 2 unmodified lines
81 77
82/* DEBUG_SET */78/* DEBUG_SET */
83 79
84static const struct nla_policy80const struct nla_policy ethnl_debug_set_policy[] = {
85debug_set_policy[ETHTOOL_A_DEBUG_MAX + 1] = {81 [ETHTOOL_A_DEBUG_HEADER] =
86 [ETHTOOL_A_DEBUG_UNSPEC] = { .type = NLA_REJECT },82 NLA_POLICY_NESTED(ethnl_header_policy),
87 [ETHTOOL_A_DEBUG_HEADER] = { .type = NLA_NESTED },
88 [ETHTOOL_A_DEBUG_MSGMASK] = { .type = NLA_NESTED },83 [ETHTOOL_A_DEBUG_MSGMASK] = { .type = NLA_NESTED },
89};84};
90 85
91int ethnl_set_debug(struct sk_buff *skb, struct genl_info *info)86int ethnl_set_debug(struct sk_buff *skb, struct genl_info *info)
92{87{
93 struct nlattr *tb[ETHTOOL_A_DEBUG_MAX + 1];
94 struct ethnl_req_info req_info = {};88 struct ethnl_req_info req_info = {};
89 struct nlattr **tb = info->attrs;
95 struct net_device *dev;90 struct net_device *dev;
96 bool mod = false;91 bool mod = false;
97 u32 msg_mask;92 u32 msg_mask;
98 int ret;93 int ret;
99 94
100 ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb,
101 ETHTOOL_A_DEBUG_MAX, debug_set_policy,
102 info->extack);
103 if (ret < 0)
104 return ret;
105 ret = ethnl_parse_header_dev_get(&req_info,95 ret = ethnl_parse_header_dev_get(&req_info,
106 tb[ETHTOOL_A_DEBUG_HEADER],96 tb[ETHTOOL_A_DEBUG_HEADER],
107 genl_info_net(info), info->extack,97 genl_info_net(info), info->extack,
net/ethtool/eee.c+8−24
@@ -19,16 +19,9 @@ struct eee_reply_data { · 18 unmodified lines
19#define EEE_REPDATA(__reply_base) \19#define EEE_REPDATA(__reply_base) \
20 container_of(__reply_base, struct eee_reply_data, base)20 container_of(__reply_base, struct eee_reply_data, base)
21 21
22static const struct nla_policy22const struct nla_policy ethnl_eee_get_policy[] = {
23eee_get_policy[ETHTOOL_A_EEE_MAX + 1] = {23 [ETHTOOL_A_EEE_HEADER] =
24 [ETHTOOL_A_EEE_UNSPEC] = { .type = NLA_REJECT },24 NLA_POLICY_NESTED(ethnl_header_policy),
25 [ETHTOOL_A_EEE_HEADER] = { .type = NLA_NESTED },
26 [ETHTOOL_A_EEE_MODES_OURS] = { .type = NLA_REJECT },
27 [ETHTOOL_A_EEE_MODES_PEER] = { .type = NLA_REJECT },
28 [ETHTOOL_A_EEE_ACTIVE] = { .type = NLA_REJECT },
29 [ETHTOOL_A_EEE_ENABLED] = { .type = NLA_REJECT },
30 [ETHTOOL_A_EEE_TX_LPI_ENABLED] = { .type = NLA_REJECT },
31 [ETHTOOL_A_EEE_TX_LPI_TIMER] = { .type = NLA_REJECT },
32};25};
33 26
34static int eee_prepare_data(const struct ethnl_req_info *req_base,27static int eee_prepare_data(const struct ethnl_req_info *req_base,
@@ -119,10 +112,8 @@ const struct ethnl_request_ops ethnl_eee_request_ops = { · 84 unmodified lines
119 .request_cmd = ETHTOOL_MSG_EEE_GET,112 .request_cmd = ETHTOOL_MSG_EEE_GET,
120 .reply_cmd = ETHTOOL_MSG_EEE_GET_REPLY,113 .reply_cmd = ETHTOOL_MSG_EEE_GET_REPLY,
121 .hdr_attr = ETHTOOL_A_EEE_HEADER,114 .hdr_attr = ETHTOOL_A_EEE_HEADER,
122 .max_attr = ETHTOOL_A_EEE_MAX,
123 .req_info_size = sizeof(struct eee_req_info),115 .req_info_size = sizeof(struct eee_req_info),
124 .reply_data_size = sizeof(struct eee_reply_data),116 .reply_data_size = sizeof(struct eee_reply_data),
125 .request_policy = eee_get_policy,
126 117
127 .prepare_data = eee_prepare_data,118 .prepare_data = eee_prepare_data,
128 .reply_size = eee_reply_size,119 .reply_size = eee_reply_size,
@@ -131,13 +122,10 @@ const struct ethnl_request_ops ethnl_eee_request_ops = { · 2 unmodified lines
131 122
132/* EEE_SET */123/* EEE_SET */
133 124
134static const struct nla_policy125const struct nla_policy ethnl_eee_set_policy[] = {
135eee_set_policy[ETHTOOL_A_EEE_MAX + 1] = {126 [ETHTOOL_A_EEE_HEADER] =
136 [ETHTOOL_A_EEE_UNSPEC] = { .type = NLA_REJECT },127 NLA_POLICY_NESTED(ethnl_header_policy),
137 [ETHTOOL_A_EEE_HEADER] = { .type = NLA_NESTED },
138 [ETHTOOL_A_EEE_MODES_OURS] = { .type = NLA_NESTED },128 [ETHTOOL_A_EEE_MODES_OURS] = { .type = NLA_NESTED },
139 [ETHTOOL_A_EEE_MODES_PEER] = { .type = NLA_REJECT },
140 [ETHTOOL_A_EEE_ACTIVE] = { .type = NLA_REJECT },
141 [ETHTOOL_A_EEE_ENABLED] = { .type = NLA_U8 },129 [ETHTOOL_A_EEE_ENABLED] = { .type = NLA_U8 },
142 [ETHTOOL_A_EEE_TX_LPI_ENABLED] = { .type = NLA_U8 },130 [ETHTOOL_A_EEE_TX_LPI_ENABLED] = { .type = NLA_U8 },
143 [ETHTOOL_A_EEE_TX_LPI_TIMER] = { .type = NLA_U32 },131 [ETHTOOL_A_EEE_TX_LPI_TIMER] = { .type = NLA_U32 },
@@ -145,18 +133,14 @@ eee_set_policy[ETHTOOL_A_EEE_MAX + 1] = { · 1 unmodified line
145 133
146int ethnl_set_eee(struct sk_buff *skb, struct genl_info *info)134int ethnl_set_eee(struct sk_buff *skb, struct genl_info *info)
147{135{
148 struct nlattr *tb[ETHTOOL_A_EEE_MAX + 1];
149 struct ethtool_eee eee = {};
150 struct ethnl_req_info req_info = {};136 struct ethnl_req_info req_info = {};
137 struct nlattr **tb = info->attrs;
151 const struct ethtool_ops *ops;138 const struct ethtool_ops *ops;
139 struct ethtool_eee eee = {};
152 struct net_device *dev;140 struct net_device *dev;
153 bool mod = false;141 bool mod = false;
154 int ret;142 int ret;
155 143
156 ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb, ETHTOOL_A_EEE_MAX,
157 eee_set_policy, info->extack);
158 if (ret < 0)
159 return ret;
160 ret = ethnl_parse_header_dev_get(&req_info,144 ret = ethnl_parse_header_dev_get(&req_info,
161 tb[ETHTOOL_A_EEE_HEADER],145 tb[ETHTOOL_A_EEE_HEADER],
162 genl_info_net(info), info->extack,146 genl_info_net(info), info->extack,
net/ethtool/features.c+7−23
@@ -20,14 +20,9 @@ struct features_reply_data { · 19 unmodified lines
20#define FEATURES_REPDATA(__reply_base) \20#define FEATURES_REPDATA(__reply_base) \
21 container_of(__reply_base, struct features_reply_data, base)21 container_of(__reply_base, struct features_reply_data, base)
22 22
23static const struct nla_policy23const struct nla_policy ethnl_features_get_policy[] = {
24features_get_policy[ETHTOOL_A_FEATURES_MAX + 1] = {24 [ETHTOOL_A_FEATURES_HEADER] =
25 [ETHTOOL_A_FEATURES_UNSPEC] = { .type = NLA_REJECT },25 NLA_POLICY_NESTED(ethnl_header_policy),
26 [ETHTOOL_A_FEATURES_HEADER] = { .type = NLA_NESTED },
27 [ETHTOOL_A_FEATURES_HW] = { .type = NLA_REJECT },
28 [ETHTOOL_A_FEATURES_WANTED] = { .type = NLA_REJECT },
29 [ETHTOOL_A_FEATURES_ACTIVE] = { .type = NLA_REJECT },
30 [ETHTOOL_A_FEATURES_NOCHANGE] = { .type = NLA_REJECT },
31};26};
32 27
33static void ethnl_features_to_bitmap32(u32 *dest, netdev_features_t src)28static void ethnl_features_to_bitmap32(u32 *dest, netdev_features_t src)
@@ -120,10 +115,8 @@ const struct ethnl_request_ops ethnl_features_request_ops = { · 86 unmodified lines
120 .request_cmd = ETHTOOL_MSG_FEATURES_GET,115 .request_cmd = ETHTOOL_MSG_FEATURES_GET,
121 .reply_cmd = ETHTOOL_MSG_FEATURES_GET_REPLY,116 .reply_cmd = ETHTOOL_MSG_FEATURES_GET_REPLY,
122 .hdr_attr = ETHTOOL_A_FEATURES_HEADER,117 .hdr_attr = ETHTOOL_A_FEATURES_HEADER,
123 .max_attr = ETHTOOL_A_FEATURES_MAX,
124 .req_info_size = sizeof(struct features_req_info),118 .req_info_size = sizeof(struct features_req_info),
125 .reply_data_size = sizeof(struct features_reply_data),119 .reply_data_size = sizeof(struct features_reply_data),
126 .request_policy = features_get_policy,
127 120
128 .prepare_data = features_prepare_data,121 .prepare_data = features_prepare_data,
129 .reply_size = features_reply_size,122 .reply_size = features_reply_size,
@@ -132,14 +125,10 @@ const struct ethnl_request_ops ethnl_features_request_ops = { · 2 unmodified lines
132 125
133/* FEATURES_SET */126/* FEATURES_SET */
134 127
135static const struct nla_policy128const struct nla_policy ethnl_features_set_policy[] = {
136features_set_policy[ETHTOOL_A_FEATURES_MAX + 1] = {129 [ETHTOOL_A_FEATURES_HEADER] =
137 [ETHTOOL_A_FEATURES_UNSPEC] = { .type = NLA_REJECT },130 NLA_POLICY_NESTED(ethnl_header_policy),
138 [ETHTOOL_A_FEATURES_HEADER] = { .type = NLA_NESTED },
139 [ETHTOOL_A_FEATURES_HW] = { .type = NLA_REJECT },
140 [ETHTOOL_A_FEATURES_WANTED] = { .type = NLA_NESTED },131 [ETHTOOL_A_FEATURES_WANTED] = { .type = NLA_NESTED },
141 [ETHTOOL_A_FEATURES_ACTIVE] = { .type = NLA_REJECT },
142 [ETHTOOL_A_FEATURES_NOCHANGE] = { .type = NLA_REJECT },
143};132};
144 133
145static void ethnl_features_to_bitmap(unsigned long *dest, netdev_features_t val)134static void ethnl_features_to_bitmap(unsigned long *dest, netdev_features_t val)
@@ -229,17 +218,12 @@ int ethnl_set_features(struct sk_buff *skb, struct genl_info *info) · 83 unmodified lines
229 DECLARE_BITMAP(new_wanted, NETDEV_FEATURE_COUNT);218 DECLARE_BITMAP(new_wanted, NETDEV_FEATURE_COUNT);
230 DECLARE_BITMAP(req_wanted, NETDEV_FEATURE_COUNT);219 DECLARE_BITMAP(req_wanted, NETDEV_FEATURE_COUNT);
231 DECLARE_BITMAP(req_mask, NETDEV_FEATURE_COUNT);220 DECLARE_BITMAP(req_mask, NETDEV_FEATURE_COUNT);
232 struct nlattr *tb[ETHTOOL_A_FEATURES_MAX + 1];
233 struct ethnl_req_info req_info = {};221 struct ethnl_req_info req_info = {};
222 struct nlattr **tb = info->attrs;
234 struct net_device *dev;223 struct net_device *dev;
235 bool mod;224 bool mod;
236 int ret;225 int ret;
237 226
238 ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb,
239 ETHTOOL_A_FEATURES_MAX, features_set_policy,
240 info->extack);
241 if (ret < 0)
242 return ret;
243 if (!tb[ETHTOOL_A_FEATURES_WANTED])227 if (!tb[ETHTOOL_A_FEATURES_WANTED])
244 return -EINVAL;228 return -EINVAL;
245 ret = ethnl_parse_header_dev_get(&req_info,229 ret = ethnl_parse_header_dev_get(&req_info,
net/ethtool/linkinfo.c+7−23
@@ -16,15 +16,9 @@ struct linkinfo_reply_data { · 15 unmodified lines
16#define LINKINFO_REPDATA(__reply_base) \16#define LINKINFO_REPDATA(__reply_base) \
17 container_of(__reply_base, struct linkinfo_reply_data, base)17 container_of(__reply_base, struct linkinfo_reply_data, base)
18 18
19static const struct nla_policy19const struct nla_policy ethnl_linkinfo_get_policy[] = {
20linkinfo_get_policy[ETHTOOL_A_LINKINFO_MAX + 1] = {20 [ETHTOOL_A_LINKINFO_HEADER] =
21 [ETHTOOL_A_LINKINFO_UNSPEC] = { .type = NLA_REJECT },21 NLA_POLICY_NESTED(ethnl_header_policy),
22 [ETHTOOL_A_LINKINFO_HEADER] = { .type = NLA_NESTED },
23 [ETHTOOL_A_LINKINFO_PORT] = { .type = NLA_REJECT },
24 [ETHTOOL_A_LINKINFO_PHYADDR] = { .type = NLA_REJECT },
25 [ETHTOOL_A_LINKINFO_TP_MDIX] = { .type = NLA_REJECT },
26 [ETHTOOL_A_LINKINFO_TP_MDIX_CTRL] = { .type = NLA_REJECT },
27 [ETHTOOL_A_LINKINFO_TRANSCEIVER] = { .type = NLA_REJECT },
28};22};
29 23
30static int linkinfo_prepare_data(const struct ethnl_req_info *req_base,24static int linkinfo_prepare_data(const struct ethnl_req_info *req_base,
@@ -83,10 +77,8 @@ const struct ethnl_request_ops ethnl_linkinfo_request_ops = { · 52 unmodified lines
83 .request_cmd = ETHTOOL_MSG_LINKINFO_GET,77 .request_cmd = ETHTOOL_MSG_LINKINFO_GET,
84 .reply_cmd = ETHTOOL_MSG_LINKINFO_GET_REPLY,78 .reply_cmd = ETHTOOL_MSG_LINKINFO_GET_REPLY,
85 .hdr_attr = ETHTOOL_A_LINKINFO_HEADER,79 .hdr_attr = ETHTOOL_A_LINKINFO_HEADER,
86 .max_attr = ETHTOOL_A_LINKINFO_MAX,
87 .req_info_size = sizeof(struct linkinfo_req_info),80 .req_info_size = sizeof(struct linkinfo_req_info),
88 .reply_data_size = sizeof(struct linkinfo_reply_data),81 .reply_data_size = sizeof(struct linkinfo_reply_data),
89 .request_policy = linkinfo_get_policy,
90 82
91 .prepare_data = linkinfo_prepare_data,83 .prepare_data = linkinfo_prepare_data,
92 .reply_size = linkinfo_reply_size,84 .reply_size = linkinfo_reply_size,
@@ -95,32 +87,24 @@ const struct ethnl_request_ops ethnl_linkinfo_request_ops = { · 2 unmodified lines
95 87
96/* LINKINFO_SET */88/* LINKINFO_SET */
97 89
98static const struct nla_policy90const struct nla_policy ethnl_linkinfo_set_policy[] = {
99linkinfo_set_policy[ETHTOOL_A_LINKINFO_MAX + 1] = {91 [ETHTOOL_A_LINKINFO_HEADER] =
100 [ETHTOOL_A_LINKINFO_UNSPEC] = { .type = NLA_REJECT },92 NLA_POLICY_NESTED(ethnl_header_policy),
101 [ETHTOOL_A_LINKINFO_HEADER] = { .type = NLA_NESTED },
102 [ETHTOOL_A_LINKINFO_PORT] = { .type = NLA_U8 },93 [ETHTOOL_A_LINKINFO_PORT] = { .type = NLA_U8 },
103 [ETHTOOL_A_LINKINFO_PHYADDR] = { .type = NLA_U8 },94 [ETHTOOL_A_LINKINFO_PHYADDR] = { .type = NLA_U8 },
104 [ETHTOOL_A_LINKINFO_TP_MDIX] = { .type = NLA_REJECT },
105 [ETHTOOL_A_LINKINFO_TP_MDIX_CTRL] = { .type = NLA_U8 },95 [ETHTOOL_A_LINKINFO_TP_MDIX_CTRL] = { .type = NLA_U8 },
106 [ETHTOOL_A_LINKINFO_TRANSCEIVER] = { .type = NLA_REJECT },
107};96};
108 97
109int ethnl_set_linkinfo(struct sk_buff *skb, struct genl_info *info)98int ethnl_set_linkinfo(struct sk_buff *skb, struct genl_info *info)
110{99{
111 struct nlattr *tb[ETHTOOL_A_LINKINFO_MAX + 1];
112 struct ethtool_link_ksettings ksettings = {};100 struct ethtool_link_ksettings ksettings = {};
113 struct ethtool_link_settings *lsettings;101 struct ethtool_link_settings *lsettings;
114 struct ethnl_req_info req_info = {};102 struct ethnl_req_info req_info = {};
103 struct nlattr **tb = info->attrs;
115 struct net_device *dev;104 struct net_device *dev;
116 bool mod = false;105 bool mod = false;
117 int ret;106 int ret;
118 107
119 ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb,
120 ETHTOOL_A_LINKINFO_MAX, linkinfo_set_policy,
121 info->extack);
122 if (ret < 0)
123 return ret;
124 ret = ethnl_parse_header_dev_get(&req_info,108 ret = ethnl_parse_header_dev_get(&req_info,
125 tb[ETHTOOL_A_LINKINFO_HEADER],109 tb[ETHTOOL_A_LINKINFO_HEADER],
126 genl_info_net(info), info->extack,110 genl_info_net(info), info->extack,
net/ethtool/linkmodes.c+7−25
@@ -18,17 +18,9 @@ struct linkmodes_reply_data { · 17 unmodified lines
18#define LINKMODES_REPDATA(__reply_base) \18#define LINKMODES_REPDATA(__reply_base) \
19 container_of(__reply_base, struct linkmodes_reply_data, base)19 container_of(__reply_base, struct linkmodes_reply_data, base)
20 20
21static const struct nla_policy21const struct nla_policy ethnl_linkmodes_get_policy[] = {
22linkmodes_get_policy[ETHTOOL_A_LINKMODES_MAX + 1] = {22 [ETHTOOL_A_LINKMODES_HEADER] =
23 [ETHTOOL_A_LINKMODES_UNSPEC] = { .type = NLA_REJECT },23 NLA_POLICY_NESTED(ethnl_header_policy),
24 [ETHTOOL_A_LINKMODES_HEADER] = { .type = NLA_NESTED },
25 [ETHTOOL_A_LINKMODES_AUTONEG] = { .type = NLA_REJECT },
26 [ETHTOOL_A_LINKMODES_OURS] = { .type = NLA_REJECT },
27 [ETHTOOL_A_LINKMODES_PEER] = { .type = NLA_REJECT },
28 [ETHTOOL_A_LINKMODES_SPEED] = { .type = NLA_REJECT },
29 [ETHTOOL_A_LINKMODES_DUPLEX] = { .type = NLA_REJECT },
30 [ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG] = { .type = NLA_REJECT },
31 [ETHTOOL_A_LINKMODES_MASTER_SLAVE_STATE] = { .type = NLA_REJECT },
32};24};
33 25
34static int linkmodes_prepare_data(const struct ethnl_req_info *req_base,26static int linkmodes_prepare_data(const struct ethnl_req_info *req_base,
@@ -148,10 +140,8 @@ const struct ethnl_request_ops ethnl_linkmodes_request_ops = { · 113 unmodified lines
148 .request_cmd = ETHTOOL_MSG_LINKMODES_GET,140 .request_cmd = ETHTOOL_MSG_LINKMODES_GET,
149 .reply_cmd = ETHTOOL_MSG_LINKMODES_GET_REPLY,141 .reply_cmd = ETHTOOL_MSG_LINKMODES_GET_REPLY,
150 .hdr_attr = ETHTOOL_A_LINKMODES_HEADER,142 .hdr_attr = ETHTOOL_A_LINKMODES_HEADER,
151 .max_attr = ETHTOOL_A_LINKMODES_MAX,
152 .req_info_size = sizeof(struct linkmodes_req_info),143 .req_info_size = sizeof(struct linkmodes_req_info),
153 .reply_data_size = sizeof(struct linkmodes_reply_data),144 .reply_data_size = sizeof(struct linkmodes_reply_data),
154 .request_policy = linkmodes_get_policy,
155 145
156 .prepare_data = linkmodes_prepare_data,146 .prepare_data = linkmodes_prepare_data,
157 .reply_size = linkmodes_reply_size,147 .reply_size = linkmodes_reply_size,
@@ -276,17 +266,14 @@ static const struct link_mode_info link_mode_params[] = { · 118 unmodified lines
276 __DEFINE_LINK_MODE_PARAMS(100, FX, Full),266 __DEFINE_LINK_MODE_PARAMS(100, FX, Full),
277};267};
278 268
279static const struct nla_policy269const struct nla_policy ethnl_linkmodes_set_policy[] = {
280linkmodes_set_policy[ETHTOOL_A_LINKMODES_MAX + 1] = {270 [ETHTOOL_A_LINKMODES_HEADER] =
281 [ETHTOOL_A_LINKMODES_UNSPEC] = { .type = NLA_REJECT },271 NLA_POLICY_NESTED(ethnl_header_policy),
282 [ETHTOOL_A_LINKMODES_HEADER] = { .type = NLA_NESTED },
283 [ETHTOOL_A_LINKMODES_AUTONEG] = { .type = NLA_U8 },272 [ETHTOOL_A_LINKMODES_AUTONEG] = { .type = NLA_U8 },
284 [ETHTOOL_A_LINKMODES_OURS] = { .type = NLA_NESTED },273 [ETHTOOL_A_LINKMODES_OURS] = { .type = NLA_NESTED },
285 [ETHTOOL_A_LINKMODES_PEER] = { .type = NLA_REJECT },
286 [ETHTOOL_A_LINKMODES_SPEED] = { .type = NLA_U32 },274 [ETHTOOL_A_LINKMODES_SPEED] = { .type = NLA_U32 },
287 [ETHTOOL_A_LINKMODES_DUPLEX] = { .type = NLA_U8 },275 [ETHTOOL_A_LINKMODES_DUPLEX] = { .type = NLA_U8 },
288 [ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG] = { .type = NLA_U8 },276 [ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG] = { .type = NLA_U8 },
289 [ETHTOOL_A_LINKMODES_MASTER_SLAVE_STATE] = { .type = NLA_REJECT },
290};277};
291 278
292/* Set advertised link modes to all supported modes matching requested speed279/* Set advertised link modes to all supported modes matching requested speed
@@ -392,18 +379,13 @@ static int ethnl_update_linkmodes(struct genl_info *info, struct nlattr **tb, · 99 unmodified lines
392 379
393int ethnl_set_linkmodes(struct sk_buff *skb, struct genl_info *info)380int ethnl_set_linkmodes(struct sk_buff *skb, struct genl_info *info)
394{381{
395 struct nlattr *tb[ETHTOOL_A_LINKMODES_MAX + 1];
396 struct ethtool_link_ksettings ksettings = {};382 struct ethtool_link_ksettings ksettings = {};
397 struct ethnl_req_info req_info = {};383 struct ethnl_req_info req_info = {};
384 struct nlattr **tb = info->attrs;
398 struct net_device *dev;385 struct net_device *dev;
399 bool mod = false;386 bool mod = false;
400 int ret;387 int ret;
401 388
402 ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb,
403 ETHTOOL_A_LINKMODES_MAX, linkmodes_set_policy,
404 info->extack);
405 if (ret < 0)
406 return ret;
407 ret = ethnl_parse_header_dev_get(&req_info,389 ret = ethnl_parse_header_dev_get(&req_info,
408 tb[ETHTOOL_A_LINKMODES_HEADER],390 tb[ETHTOOL_A_LINKMODES_HEADER],
409 genl_info_net(info), info->extack,391 genl_info_net(info), info->extack,
net/ethtool/linkstate.c+3−11
@@ -20,15 +20,9 @@ struct linkstate_reply_data { · 19 unmodified lines
20#define LINKSTATE_REPDATA(__reply_base) \20#define LINKSTATE_REPDATA(__reply_base) \
21 container_of(__reply_base, struct linkstate_reply_data, base)21 container_of(__reply_base, struct linkstate_reply_data, base)
22 22
23static const struct nla_policy23const struct nla_policy ethnl_linkstate_get_policy[] = {
24linkstate_get_policy[ETHTOOL_A_LINKSTATE_MAX + 1] = {24 [ETHTOOL_A_LINKSTATE_HEADER] =
25 [ETHTOOL_A_LINKSTATE_UNSPEC] = { .type = NLA_REJECT },25 NLA_POLICY_NESTED(ethnl_header_policy),
26 [ETHTOOL_A_LINKSTATE_HEADER] = { .type = NLA_NESTED },
27 [ETHTOOL_A_LINKSTATE_LINK] = { .type = NLA_REJECT },
28 [ETHTOOL_A_LINKSTATE_SQI] = { .type = NLA_REJECT },
29 [ETHTOOL_A_LINKSTATE_SQI_MAX] = { .type = NLA_REJECT },
30 [ETHTOOL_A_LINKSTATE_EXT_STATE] = { .type = NLA_REJECT },
31 [ETHTOOL_A_LINKSTATE_EXT_SUBSTATE] = { .type = NLA_REJECT },
32};26};
33 27
34static int linkstate_get_sqi(struct net_device *dev)28static int linkstate_get_sqi(struct net_device *dev)
@@ -179,10 +173,8 @@ const struct ethnl_request_ops ethnl_linkstate_request_ops = { · 144 unmodified lines
179 .request_cmd = ETHTOOL_MSG_LINKSTATE_GET,173 .request_cmd = ETHTOOL_MSG_LINKSTATE_GET,
180 .reply_cmd = ETHTOOL_MSG_LINKSTATE_GET_REPLY,174 .reply_cmd = ETHTOOL_MSG_LINKSTATE_GET_REPLY,
181 .hdr_attr = ETHTOOL_A_LINKSTATE_HEADER,175 .hdr_attr = ETHTOOL_A_LINKSTATE_HEADER,
182 .max_attr = ETHTOOL_A_LINKSTATE_MAX,
183 .req_info_size = sizeof(struct linkstate_req_info),176 .req_info_size = sizeof(struct linkstate_req_info),
184 .reply_data_size = sizeof(struct linkstate_reply_data),177 .reply_data_size = sizeof(struct linkstate_reply_data),
185 .request_policy = linkstate_get_policy,
186 178
187 .prepare_data = linkstate_prepare_data,179 .prepare_data = linkstate_prepare_data,
188 .reply_size = linkstate_reply_size,180 .reply_size = linkstate_reply_size,
net/ethtool/netlink.c+88−36
@@ -9,12 +9,24 @@ static struct genl_family ethtool_genl_family; · 8 unmodified lines
9static bool ethnl_ok __read_mostly;9static bool ethnl_ok __read_mostly;
10static u32 ethnl_bcast_seq;10static u32 ethnl_bcast_seq;
11 11
12static const struct nla_policy ethnl_header_policy[ETHTOOL_A_HEADER_MAX + 1] = {12#define ETHTOOL_FLAGS_BASIC (ETHTOOL_FLAG_COMPACT_BITSETS | \
13 [ETHTOOL_A_HEADER_UNSPEC] = { .type = NLA_REJECT },13 ETHTOOL_FLAG_OMIT_REPLY)
14#define ETHTOOL_FLAGS_STATS (ETHTOOL_FLAGS_BASIC | ETHTOOL_FLAG_STATS)
15
16const struct nla_policy ethnl_header_policy[] = {
14 [ETHTOOL_A_HEADER_DEV_INDEX] = { .type = NLA_U32 },17 [ETHTOOL_A_HEADER_DEV_INDEX] = { .type = NLA_U32 },
15 [ETHTOOL_A_HEADER_DEV_NAME] = { .type = NLA_NUL_STRING,18 [ETHTOOL_A_HEADER_DEV_NAME] = { .type = NLA_NUL_STRING,
16 .len = ALTIFNAMSIZ - 1 },19 .len = ALTIFNAMSIZ - 1 },
17 [ETHTOOL_A_HEADER_FLAGS] = { .type = NLA_U32 },20 [ETHTOOL_A_HEADER_FLAGS] = NLA_POLICY_MASK(NLA_U32,
21 ETHTOOL_FLAGS_BASIC),
22};
23
24const struct nla_policy ethnl_header_policy_stats[] = {
25 [ETHTOOL_A_HEADER_DEV_INDEX] = { .type = NLA_U32 },
26 [ETHTOOL_A_HEADER_DEV_NAME] = { .type = NLA_NUL_STRING,
27 .len = ALTIFNAMSIZ - 1 },
28 [ETHTOOL_A_HEADER_FLAGS] = NLA_POLICY_MASK(NLA_U32,
29 ETHTOOL_FLAGS_STATS),
18};30};
19 31
20/**32/**
@@ -37,7 +49,7 @@ int ethnl_parse_header_dev_get(struct ethnl_req_info *req_info, · 16 unmodified lines
37 const struct nlattr *header, struct net *net,49 const struct nlattr *header, struct net *net,
38 struct netlink_ext_ack *extack, bool require_dev)50 struct netlink_ext_ack *extack, bool require_dev)
39{51{
40 struct nlattr *tb[ETHTOOL_A_HEADER_MAX + 1];52 struct nlattr *tb[ARRAY_SIZE(ethnl_header_policy)];
41 const struct nlattr *devname_attr;53 const struct nlattr *devname_attr;
42 struct net_device *dev = NULL;54 struct net_device *dev = NULL;
43 u32 flags = 0;55 u32 flags = 0;
@@ -47,19 +59,15 @@ int ethnl_parse_header_dev_get(struct ethnl_req_info *req_info, · 3 unmodified lines
47 NL_SET_ERR_MSG(extack, "request header missing");59 NL_SET_ERR_MSG(extack, "request header missing");
48 return -EINVAL;60 return -EINVAL;
49 }61 }
50 ret = nla_parse_nested(tb, ETHTOOL_A_HEADER_MAX, header,62 /* No validation here, command policy should have a nested policy set
51 ethnl_header_policy, extack);63 * for the header, therefore validation should have already been done.
64 */
65 ret = nla_parse_nested(tb, ARRAY_SIZE(ethnl_header_policy) - 1, header,
66 NULL, extack);
52 if (ret < 0)67 if (ret < 0)
53 return ret;68 return ret;
54 if (tb[ETHTOOL_A_HEADER_FLAGS]) {69 if (tb[ETHTOOL_A_HEADER_FLAGS])
55 flags = nla_get_u32(tb[ETHTOOL_A_HEADER_FLAGS]);70 flags = nla_get_u32(tb[ETHTOOL_A_HEADER_FLAGS]);
56 if (flags & ~ETHTOOL_FLAG_ALL) {
57 NL_SET_ERR_MSG_ATTR(extack, tb[ETHTOOL_A_HEADER_FLAGS],
58 "unrecognized request flags");
59 nl_set_extack_cookie_u32(extack, ETHTOOL_FLAG_ALL);
60 return -EOPNOTSUPP;
61 }
62 }
63 71
64 devname_attr = tb[ETHTOOL_A_HEADER_DEV_NAME];72 devname_attr = tb[ETHTOOL_A_HEADER_DEV_NAME];
65 if (tb[ETHTOOL_A_HEADER_DEV_INDEX]) {73 if (tb[ETHTOOL_A_HEADER_DEV_INDEX]) {
@@ -247,7 +255,7 @@ static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb) · 181 unmodified lines
247/**255/**
248 * ethnl_default_parse() - Parse request message256 * ethnl_default_parse() - Parse request message
249 * @req_info: pointer to structure to put data into257 * @req_info: pointer to structure to put data into
250 * @nlhdr: pointer to request message header258 * @tb: parsed attributes
251 * @net: request netns259 * @net: request netns
252 * @request_ops: struct request_ops for request type260 * @request_ops: struct request_ops for request type
253 * @extack: netlink extack for error reporting261 * @extack: netlink extack for error reporting
@@ -259,37 +267,24 @@ static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb) · 5 unmodified lines
259 * Return: 0 on success or negative error code267 * Return: 0 on success or negative error code
260 */268 */
261static int ethnl_default_parse(struct ethnl_req_info *req_info,269static int ethnl_default_parse(struct ethnl_req_info *req_info,
262 const struct nlmsghdr *nlhdr, struct net *net,270 struct nlattr **tb, struct net *net,
263 const struct ethnl_request_ops *request_ops,271 const struct ethnl_request_ops *request_ops,
264 struct netlink_ext_ack *extack, bool require_dev)272 struct netlink_ext_ack *extack, bool require_dev)
265{273{
266 struct nlattr **tb;
267 int ret;274 int ret;
268 275
269 tb = kmalloc_array(request_ops->max_attr + 1, sizeof(tb[0]),
270 GFP_KERNEL);
271 if (!tb)
272 return -ENOMEM;
273
274 ret = nlmsg_parse(nlhdr, GENL_HDRLEN, tb, request_ops->max_attr,
275 request_ops->request_policy, extack);
276 if (ret < 0)
277 goto out;
278 ret = ethnl_parse_header_dev_get(req_info, tb[request_ops->hdr_attr],276 ret = ethnl_parse_header_dev_get(req_info, tb[request_ops->hdr_attr],
279 net, extack, require_dev);277 net, extack, require_dev);
280 if (ret < 0)278 if (ret < 0)
281 goto out;279 return ret;
282 280
283 if (request_ops->parse_request) {281 if (request_ops->parse_request) {
284 ret = request_ops->parse_request(req_info, tb, extack);282 ret = request_ops->parse_request(req_info, tb, extack);
285 if (ret < 0)283 if (ret < 0)
286 goto out;284 return ret;
287 }285 }
288 286
289 ret = 0;287 return 0;
290out:
291 kfree(tb);
292 return ret;
293}288}
294 289
295/**290/**
@@ -334,8 +329,8 @@ static int ethnl_default_doit(struct sk_buff *skb, struct genl_info *info) · 38 unmodified lines
334 return -ENOMEM;329 return -ENOMEM;
335 }330 }
336 331
337 ret = ethnl_default_parse(req_info, info->nlhdr, genl_info_net(info), ops,332 ret = ethnl_default_parse(req_info, info->attrs, genl_info_net(info),
338 info->extack, !ops->allow_nodev_do);333 ops, info->extack, !ops->allow_nodev_do);
339 if (ret < 0)334 if (ret < 0)
340 goto err_dev;335 goto err_dev;
341 ethnl_init_reply_data(reply_data, ops, req_info->dev);336 ethnl_init_reply_data(reply_data, ops, req_info->dev);
@@ -480,6 +475,7 @@ out: · 138 unmodified lines
480/* generic ->start() handler for GET requests */475/* generic ->start() handler for GET requests */
481static int ethnl_default_start(struct netlink_callback *cb)476static int ethnl_default_start(struct netlink_callback *cb)
482{477{
478 const struct genl_dumpit_info *info = genl_dumpit_info(cb);
483 struct ethnl_dump_ctx *ctx = ethnl_dump_context(cb);479 struct ethnl_dump_ctx *ctx = ethnl_dump_context(cb);
484 struct ethnl_reply_data *reply_data;480 struct ethnl_reply_data *reply_data;
485 const struct ethnl_request_ops *ops;481 const struct ethnl_request_ops *ops;
@@ -502,8 +498,8 @@ static int ethnl_default_start(struct netlink_callback *cb) · 16 unmodified lines
502 goto free_req_info;498 goto free_req_info;
503 }499 }
504 500
505 ret = ethnl_default_parse(req_info, cb->nlh, sock_net(cb->skb->sk), ops,501 ret = ethnl_default_parse(req_info, info->attrs, sock_net(cb->skb->sk),
506 cb->extack, false);502 ops, cb->extack, false);
507 if (req_info->dev) {503 if (req_info->dev) {
508 /* We ignore device specification in dump requests but as the504 /* We ignore device specification in dump requests but as the
509 * same parser as for non-dump (doit) requests is used, it505 * same parser as for non-dump (doit) requests is used, it
@@ -696,6 +692,8 @@ static const struct genl_ops ethtool_genl_ops[] = { · 186 unmodified lines
696 .start = ethnl_default_start,692 .start = ethnl_default_start,
697 .dumpit = ethnl_default_dumpit,693 .dumpit = ethnl_default_dumpit,
698 .done = ethnl_default_done,694 .done = ethnl_default_done,
695 .policy = ethnl_strset_get_policy,
696 .maxattr = ARRAY_SIZE(ethnl_strset_get_policy) - 1,
699 },697 },
700 {698 {
701 .cmd = ETHTOOL_MSG_LINKINFO_GET,699 .cmd = ETHTOOL_MSG_LINKINFO_GET,
@@ -703,11 +701,15 @@ static const struct genl_ops ethtool_genl_ops[] = { · 1 unmodified line
703 .start = ethnl_default_start,701 .start = ethnl_default_start,
704 .dumpit = ethnl_default_dumpit,702 .dumpit = ethnl_default_dumpit,
705 .done = ethnl_default_done,703 .done = ethnl_default_done,
704 .policy = ethnl_linkinfo_get_policy,
705 .maxattr = ARRAY_SIZE(ethnl_linkinfo_get_policy) - 1,
706 },706 },
707 {707 {
708 .cmd = ETHTOOL_MSG_LINKINFO_SET,708 .cmd = ETHTOOL_MSG_LINKINFO_SET,
709 .flags = GENL_UNS_ADMIN_PERM,709 .flags = GENL_UNS_ADMIN_PERM,
710 .doit = ethnl_set_linkinfo,710 .doit = ethnl_set_linkinfo,
711 .policy = ethnl_linkinfo_set_policy,
712 .maxattr = ARRAY_SIZE(ethnl_linkinfo_set_policy) - 1,
711 },713 },
712 {714 {
713 .cmd = ETHTOOL_MSG_LINKMODES_GET,715 .cmd = ETHTOOL_MSG_LINKMODES_GET,
@@ -715,11 +717,15 @@ static const struct genl_ops ethtool_genl_ops[] = { · 1 unmodified line
715 .start = ethnl_default_start,717 .start = ethnl_default_start,
716 .dumpit = ethnl_default_dumpit,718 .dumpit = ethnl_default_dumpit,
717 .done = ethnl_default_done,719 .done = ethnl_default_done,
720 .policy = ethnl_linkmodes_get_policy,
721 .maxattr = ARRAY_SIZE(ethnl_linkmodes_get_policy) - 1,
718 },722 },
719 {723 {
720 .cmd = ETHTOOL_MSG_LINKMODES_SET,724 .cmd = ETHTOOL_MSG_LINKMODES_SET,
721 .flags = GENL_UNS_ADMIN_PERM,725 .flags = GENL_UNS_ADMIN_PERM,
722 .doit = ethnl_set_linkmodes,726 .doit = ethnl_set_linkmodes,
727 .policy = ethnl_linkmodes_set_policy,
728 .maxattr = ARRAY_SIZE(ethnl_linkmodes_set_policy) - 1,
723 },729 },
724 {730 {
725 .cmd = ETHTOOL_MSG_LINKSTATE_GET,731 .cmd = ETHTOOL_MSG_LINKSTATE_GET,
@@ -727,6 +733,8 @@ static const struct genl_ops ethtool_genl_ops[] = { · 1 unmodified line
727 .start = ethnl_default_start,733 .start = ethnl_default_start,
728 .dumpit = ethnl_default_dumpit,734 .dumpit = ethnl_default_dumpit,
729 .done = ethnl_default_done,735 .done = ethnl_default_done,
736 .policy = ethnl_linkstate_get_policy,
737 .maxattr = ARRAY_SIZE(ethnl_linkstate_get_policy) - 1,
730 },738 },
731 {739 {
732 .cmd = ETHTOOL_MSG_DEBUG_GET,740 .cmd = ETHTOOL_MSG_DEBUG_GET,
@@ -734,11 +742,15 @@ static const struct genl_ops ethtool_genl_ops[] = { · 1 unmodified line
734 .start = ethnl_default_start,742 .start = ethnl_default_start,
735 .dumpit = ethnl_default_dumpit,743 .dumpit = ethnl_default_dumpit,
736 .done = ethnl_default_done,744 .done = ethnl_default_done,
745 .policy = ethnl_debug_get_policy,
746 .maxattr = ARRAY_SIZE(ethnl_debug_get_policy) - 1,
737 },747 },
738 {748 {
739 .cmd = ETHTOOL_MSG_DEBUG_SET,749 .cmd = ETHTOOL_MSG_DEBUG_SET,
740 .flags = GENL_UNS_ADMIN_PERM,750 .flags = GENL_UNS_ADMIN_PERM,
741 .doit = ethnl_set_debug,751 .doit = ethnl_set_debug,
752 .policy = ethnl_debug_set_policy,
753 .maxattr = ARRAY_SIZE(ethnl_debug_set_policy) - 1,
742 },754 },
743 {755 {
744 .cmd = ETHTOOL_MSG_WOL_GET,756 .cmd = ETHTOOL_MSG_WOL_GET,
@@ -747,11 +759,15 @@ static const struct genl_ops ethtool_genl_ops[] = { · 2 unmodified lines
747 .start = ethnl_default_start,759 .start = ethnl_default_start,
748 .dumpit = ethnl_default_dumpit,760 .dumpit = ethnl_default_dumpit,
749 .done = ethnl_default_done,761 .done = ethnl_default_done,
762 .policy = ethnl_wol_get_policy,
763 .maxattr = ARRAY_SIZE(ethnl_wol_get_policy) - 1,
750 },764 },
751 {765 {
752 .cmd = ETHTOOL_MSG_WOL_SET,766 .cmd = ETHTOOL_MSG_WOL_SET,
753 .flags = GENL_UNS_ADMIN_PERM,767 .flags = GENL_UNS_ADMIN_PERM,
754 .doit = ethnl_set_wol,768 .doit = ethnl_set_wol,
769 .policy = ethnl_wol_set_policy,
770 .maxattr = ARRAY_SIZE(ethnl_wol_set_policy) - 1,
755 },771 },
756 {772 {
757 .cmd = ETHTOOL_MSG_FEATURES_GET,773 .cmd = ETHTOOL_MSG_FEATURES_GET,
@@ -759,11 +775,15 @@ static const struct genl_ops ethtool_genl_ops[] = { · 1 unmodified line
759 .start = ethnl_default_start,775 .start = ethnl_default_start,
760 .dumpit = ethnl_default_dumpit,776 .dumpit = ethnl_default_dumpit,
761 .done = ethnl_default_done,777 .done = ethnl_default_done,
778 .policy = ethnl_features_get_policy,
779 .maxattr = ARRAY_SIZE(ethnl_features_get_policy) - 1,
762 },780 },
763 {781 {
764 .cmd = ETHTOOL_MSG_FEATURES_SET,782 .cmd = ETHTOOL_MSG_FEATURES_SET,
765 .flags = GENL_UNS_ADMIN_PERM,783 .flags = GENL_UNS_ADMIN_PERM,
766 .doit = ethnl_set_features,784 .doit = ethnl_set_features,
785 .policy = ethnl_features_set_policy,
786 .maxattr = ARRAY_SIZE(ethnl_features_set_policy) - 1,
767 },787 },
768 {788 {
769 .cmd = ETHTOOL_MSG_PRIVFLAGS_GET,789 .cmd = ETHTOOL_MSG_PRIVFLAGS_GET,
@@ -771,11 +791,15 @@ static const struct genl_ops ethtool_genl_ops[] = { · 1 unmodified line
771 .start = ethnl_default_start,791 .start = ethnl_default_start,
772 .dumpit = ethnl_default_dumpit,792 .dumpit = ethnl_default_dumpit,
773 .done = ethnl_default_done,793 .done = ethnl_default_done,
794 .policy = ethnl_privflags_get_policy,
795 .maxattr = ARRAY_SIZE(ethnl_privflags_get_policy) - 1,
774 },796 },
775 {797 {
776 .cmd = ETHTOOL_MSG_PRIVFLAGS_SET,798 .cmd = ETHTOOL_MSG_PRIVFLAGS_SET,
777 .flags = GENL_UNS_ADMIN_PERM,799 .flags = GENL_UNS_ADMIN_PERM,
778 .doit = ethnl_set_privflags,800 .doit = ethnl_set_privflags,
801 .policy = ethnl_privflags_set_policy,
802 .maxattr = ARRAY_SIZE(ethnl_privflags_set_policy) - 1,
779 },803 },
780 {804 {
781 .cmd = ETHTOOL_MSG_RINGS_GET,805 .cmd = ETHTOOL_MSG_RINGS_GET,
@@ -783,11 +807,15 @@ static const struct genl_ops ethtool_genl_ops[] = { · 1 unmodified line
783 .start = ethnl_default_start,807 .start = ethnl_default_start,
784 .dumpit = ethnl_default_dumpit,808 .dumpit = ethnl_default_dumpit,
785 .done = ethnl_default_done,809 .done = ethnl_default_done,
810 .policy = ethnl_rings_get_policy,
811 .maxattr = ARRAY_SIZE(ethnl_rings_get_policy) - 1,
786 },812 },
787 {813 {
788 .cmd = ETHTOOL_MSG_RINGS_SET,814 .cmd = ETHTOOL_MSG_RINGS_SET,
789 .flags = GENL_UNS_ADMIN_PERM,815 .flags = GENL_UNS_ADMIN_PERM,
790 .doit = ethnl_set_rings,816 .doit = ethnl_set_rings,
817 .policy = ethnl_rings_set_policy,
818 .maxattr = ARRAY_SIZE(ethnl_rings_set_policy) - 1,
791 },819 },
792 {820 {
793 .cmd = ETHTOOL_MSG_CHANNELS_GET,821 .cmd = ETHTOOL_MSG_CHANNELS_GET,
@@ -795,11 +823,15 @@ static const struct genl_ops ethtool_genl_ops[] = { · 1 unmodified line
795 .start = ethnl_default_start,823 .start = ethnl_default_start,
796 .dumpit = ethnl_default_dumpit,824 .dumpit = ethnl_default_dumpit,
797 .done = ethnl_default_done,825 .done = ethnl_default_done,
826 .policy = ethnl_channels_get_policy,
827 .maxattr = ARRAY_SIZE(ethnl_channels_get_policy) - 1,
798 },828 },
799 {829 {
800 .cmd = ETHTOOL_MSG_CHANNELS_SET,830 .cmd = ETHTOOL_MSG_CHANNELS_SET,
801 .flags = GENL_UNS_ADMIN_PERM,831 .flags = GENL_UNS_ADMIN_PERM,
802 .doit = ethnl_set_channels,832 .doit = ethnl_set_channels,
833 .policy = ethnl_channels_get_policy,
834 .maxattr = ARRAY_SIZE(ethnl_channels_get_policy) - 1,
803 },835 },
804 {836 {
805 .cmd = ETHTOOL_MSG_COALESCE_GET,837 .cmd = ETHTOOL_MSG_COALESCE_GET,
@@ -807,11 +839,15 @@ static const struct genl_ops ethtool_genl_ops[] = { · 1 unmodified line
807 .start = ethnl_default_start,839 .start = ethnl_default_start,
808 .dumpit = ethnl_default_dumpit,840 .dumpit = ethnl_default_dumpit,
809 .done = ethnl_default_done,841 .done = ethnl_default_done,
842 .policy = ethnl_coalesce_get_policy,
843 .maxattr = ARRAY_SIZE(ethnl_coalesce_get_policy) - 1,
810 },844 },
811 {845 {
812 .cmd = ETHTOOL_MSG_COALESCE_SET,846 .cmd = ETHTOOL_MSG_COALESCE_SET,
813 .flags = GENL_UNS_ADMIN_PERM,847 .flags = GENL_UNS_ADMIN_PERM,
814 .doit = ethnl_set_coalesce,848 .doit = ethnl_set_coalesce,
849 .policy = ethnl_coalesce_set_policy,
850 .maxattr = ARRAY_SIZE(ethnl_coalesce_set_policy) - 1,
815 },851 },
816 {852 {
817 .cmd = ETHTOOL_MSG_PAUSE_GET,853 .cmd = ETHTOOL_MSG_PAUSE_GET,
@@ -819,11 +855,15 @@ static const struct genl_ops ethtool_genl_ops[] = { · 1 unmodified line
819 .start = ethnl_default_start,855 .start = ethnl_default_start,
820 .dumpit = ethnl_default_dumpit,856 .dumpit = ethnl_default_dumpit,
821 .done = ethnl_default_done,857 .done = ethnl_default_done,
858 .policy = ethnl_pause_get_policy,
859 .maxattr = ARRAY_SIZE(ethnl_pause_get_policy) - 1,
822 },860 },
823 {861 {
824 .cmd = ETHTOOL_MSG_PAUSE_SET,862 .cmd = ETHTOOL_MSG_PAUSE_SET,
825 .flags = GENL_UNS_ADMIN_PERM,863 .flags = GENL_UNS_ADMIN_PERM,
826 .doit = ethnl_set_pause,864 .doit = ethnl_set_pause,
865 .policy = ethnl_pause_set_policy,
866 .maxattr = ARRAY_SIZE(ethnl_pause_set_policy) - 1,
827 },867 },
828 {868 {
829 .cmd = ETHTOOL_MSG_EEE_GET,869 .cmd = ETHTOOL_MSG_EEE_GET,
@@ -831,11 +871,15 @@ static const struct genl_ops ethtool_genl_ops[] = { · 1 unmodified line
831 .start = ethnl_default_start,871 .start = ethnl_default_start,
832 .dumpit = ethnl_default_dumpit,872 .dumpit = ethnl_default_dumpit,
833 .done = ethnl_default_done,873 .done = ethnl_default_done,
874 .policy = ethnl_eee_get_policy,
875 .maxattr = ARRAY_SIZE(ethnl_eee_get_policy) - 1,
834 },876 },
835 {877 {
836 .cmd = ETHTOOL_MSG_EEE_SET,878 .cmd = ETHTOOL_MSG_EEE_SET,
837 .flags = GENL_UNS_ADMIN_PERM,879 .flags = GENL_UNS_ADMIN_PERM,
838 .doit = ethnl_set_eee,880 .doit = ethnl_set_eee,
881 .policy = ethnl_eee_set_policy,
882 .maxattr = ARRAY_SIZE(ethnl_eee_set_policy) - 1,
839 },883 },
840 {884 {
841 .cmd = ETHTOOL_MSG_TSINFO_GET,885 .cmd = ETHTOOL_MSG_TSINFO_GET,
@@ -843,22 +887,30 @@ static const struct genl_ops ethtool_genl_ops[] = { · 1 unmodified line
843 .start = ethnl_default_start,887 .start = ethnl_default_start,
844 .dumpit = ethnl_default_dumpit,888 .dumpit = ethnl_default_dumpit,
845 .done = ethnl_default_done,889 .done = ethnl_default_done,
890 .policy = ethnl_tsinfo_get_policy,
891 .maxattr = ARRAY_SIZE(ethnl_tsinfo_get_policy) - 1,
846 },892 },
847 {893 {
848 .cmd = ETHTOOL_MSG_CABLE_TEST_ACT,894 .cmd = ETHTOOL_MSG_CABLE_TEST_ACT,
849 .flags = GENL_UNS_ADMIN_PERM,895 .flags = GENL_UNS_ADMIN_PERM,
850 .doit = ethnl_act_cable_test,896 .doit = ethnl_act_cable_test,
897 .policy = ethnl_cable_test_act_policy,
898 .maxattr = ARRAY_SIZE(ethnl_cable_test_act_policy) - 1,
851 },899 },
852 {900 {
853 .cmd = ETHTOOL_MSG_CABLE_TEST_TDR_ACT,901 .cmd = ETHTOOL_MSG_CABLE_TEST_TDR_ACT,
854 .flags = GENL_UNS_ADMIN_PERM,902 .flags = GENL_UNS_ADMIN_PERM,
855 .doit = ethnl_act_cable_test_tdr,903 .doit = ethnl_act_cable_test_tdr,
904 .policy = ethnl_cable_test_tdr_act_policy,
905 .maxattr = ARRAY_SIZE(ethnl_cable_test_tdr_act_policy) - 1,
856 },906 },
857 {907 {
858 .cmd = ETHTOOL_MSG_TUNNEL_INFO_GET,908 .cmd = ETHTOOL_MSG_TUNNEL_INFO_GET,
859 .doit = ethnl_tunnel_info_doit,909 .doit = ethnl_tunnel_info_doit,
860 .start = ethnl_tunnel_info_start,910 .start = ethnl_tunnel_info_start,
861 .dumpit = ethnl_tunnel_info_dumpit,911 .dumpit = ethnl_tunnel_info_dumpit,
912 .policy = ethnl_tunnel_info_get_policy,
913 .maxattr = ARRAY_SIZE(ethnl_tunnel_info_get_policy) - 1,
862 },914 },
863};915};
864 916
net/ethtool/netlink.h+31−4
@@ -266,10 +266,8 @@ static inline void ethnl_ops_complete(struct net_device *dev) · 265 unmodified lines
266 * @request_cmd: command id for request (GET)266 * @request_cmd: command id for request (GET)
267 * @reply_cmd: command id for reply (GET_REPLY)267 * @reply_cmd: command id for reply (GET_REPLY)
268 * @hdr_attr: attribute type for request header268 * @hdr_attr: attribute type for request header
269 * @max_attr: maximum (top level) attribute type
270 * @req_info_size: size of request info269 * @req_info_size: size of request info
271 * @reply_data_size: size of reply data270 * @reply_data_size: size of reply data
272 * @request_policy: netlink policy for message contents
273 * @allow_nodev_do: allow non-dump request with no device identification271 * @allow_nodev_do: allow non-dump request with no device identification
274 * @parse_request:272 * @parse_request:
275 * Parse request except common header (struct ethnl_req_info). Common273 * Parse request except common header (struct ethnl_req_info). Common
@@ -312,10 +310,8 @@ struct ethnl_request_ops { · 36 unmodified lines
312 u8 request_cmd;310 u8 request_cmd;
313 u8 reply_cmd;311 u8 reply_cmd;
314 u16 hdr_attr;312 u16 hdr_attr;
315 unsigned int max_attr;
316 unsigned int req_info_size;313 unsigned int req_info_size;
317 unsigned int reply_data_size;314 unsigned int reply_data_size;
318 const struct nla_policy *request_policy;
319 bool allow_nodev_do;315 bool allow_nodev_do;
320 316
321 int (*parse_request)(struct ethnl_req_info *req_info,317 int (*parse_request)(struct ethnl_req_info *req_info,
@@ -349,6 +345,37 @@ extern const struct ethnl_request_ops ethnl_pause_request_ops; · 27 unmodified lines
349extern const struct ethnl_request_ops ethnl_eee_request_ops;345extern const struct ethnl_request_ops ethnl_eee_request_ops;
350extern const struct ethnl_request_ops ethnl_tsinfo_request_ops;346extern const struct ethnl_request_ops ethnl_tsinfo_request_ops;
351 347
348extern const struct nla_policy ethnl_header_policy[ETHTOOL_A_HEADER_FLAGS + 1];
349extern const struct nla_policy ethnl_header_policy_stats[ETHTOOL_A_HEADER_FLAGS + 1];
350extern const struct nla_policy ethnl_strset_get_policy[ETHTOOL_A_STRSET_STRINGSETS + 1];
351extern const struct nla_policy ethnl_linkinfo_get_policy[ETHTOOL_A_LINKINFO_HEADER + 1];
352extern const struct nla_policy ethnl_linkinfo_set_policy[ETHTOOL_A_LINKINFO_TP_MDIX_CTRL + 1];
353extern const struct nla_policy ethnl_linkmodes_get_policy[ETHTOOL_A_LINKMODES_HEADER + 1];
354extern const struct nla_policy ethnl_linkmodes_set_policy[ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG + 1];
355extern const struct nla_policy ethnl_linkstate_get_policy[ETHTOOL_A_LINKSTATE_HEADER + 1];
356extern const struct nla_policy ethnl_debug_get_policy[ETHTOOL_A_DEBUG_HEADER + 1];
357extern const struct nla_policy ethnl_debug_set_policy[ETHTOOL_A_DEBUG_MSGMASK + 1];
358extern const struct nla_policy ethnl_wol_get_policy[ETHTOOL_A_WOL_HEADER + 1];
359extern const struct nla_policy ethnl_wol_set_policy[ETHTOOL_A_WOL_SOPASS + 1];
360extern const struct nla_policy ethnl_features_get_policy[ETHTOOL_A_FEATURES_HEADER + 1];
361extern const struct nla_policy ethnl_features_set_policy[ETHTOOL_A_FEATURES_WANTED + 1];
362extern const struct nla_policy ethnl_privflags_get_policy[ETHTOOL_A_PRIVFLAGS_HEADER + 1];
363extern const struct nla_policy ethnl_privflags_set_policy[ETHTOOL_A_PRIVFLAGS_FLAGS + 1];
364extern const struct nla_policy ethnl_rings_get_policy[ETHTOOL_A_RINGS_HEADER + 1];
365extern const struct nla_policy ethnl_rings_set_policy[ETHTOOL_A_RINGS_TX + 1];
366extern const struct nla_policy ethnl_channels_get_policy[ETHTOOL_A_CHANNELS_HEADER + 1];
367extern const struct nla_policy ethnl_channels_set_policy[ETHTOOL_A_CHANNELS_COMBINED_COUNT + 1];
368extern const struct nla_policy ethnl_coalesce_get_policy[ETHTOOL_A_COALESCE_HEADER + 1];
369extern const struct nla_policy ethnl_coalesce_set_policy[ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL + 1];
370extern const struct nla_policy ethnl_pause_get_policy[ETHTOOL_A_PAUSE_HEADER + 1];
371extern const struct nla_policy ethnl_pause_set_policy[ETHTOOL_A_PAUSE_TX + 1];
372extern const struct nla_policy ethnl_eee_get_policy[ETHTOOL_A_EEE_HEADER + 1];
373extern const struct nla_policy ethnl_eee_set_policy[ETHTOOL_A_EEE_TX_LPI_TIMER + 1];
374extern const struct nla_policy ethnl_tsinfo_get_policy[ETHTOOL_A_TSINFO_HEADER + 1];
375extern const struct nla_policy ethnl_cable_test_act_policy[ETHTOOL_A_CABLE_TEST_HEADER + 1];
376extern const struct nla_policy ethnl_cable_test_tdr_act_policy[ETHTOOL_A_CABLE_TEST_TDR_CFG + 1];
377extern const struct nla_policy ethnl_tunnel_info_get_policy[ETHTOOL_A_TUNNEL_INFO_HEADER + 1];
378
352int ethnl_set_linkinfo(struct sk_buff *skb, struct genl_info *info);379int ethnl_set_linkinfo(struct sk_buff *skb, struct genl_info *info);
353int ethnl_set_linkmodes(struct sk_buff *skb, struct genl_info *info);380int ethnl_set_linkmodes(struct sk_buff *skb, struct genl_info *info);
354int ethnl_set_debug(struct sk_buff *skb, struct genl_info *info);381int ethnl_set_debug(struct sk_buff *skb, struct genl_info *info);
net/ethtool/pause.c+7−20
@@ -16,14 +16,9 @@ struct pause_reply_data { · 15 unmodified lines
16#define PAUSE_REPDATA(__reply_base) \16#define PAUSE_REPDATA(__reply_base) \
17 container_of(__reply_base, struct pause_reply_data, base)17 container_of(__reply_base, struct pause_reply_data, base)
18 18
19static const struct nla_policy19const struct nla_policy ethnl_pause_get_policy[] = {
20pause_get_policy[ETHTOOL_A_PAUSE_MAX + 1] = {20 [ETHTOOL_A_PAUSE_HEADER] =
21 [ETHTOOL_A_PAUSE_UNSPEC] = { .type = NLA_REJECT },21 NLA_POLICY_NESTED(ethnl_header_policy_stats),
22 [ETHTOOL_A_PAUSE_HEADER] = { .type = NLA_NESTED },
23 [ETHTOOL_A_PAUSE_AUTONEG] = { .type = NLA_REJECT },
24 [ETHTOOL_A_PAUSE_RX] = { .type = NLA_REJECT },
25 [ETHTOOL_A_PAUSE_TX] = { .type = NLA_REJECT },
26 [ETHTOOL_A_PAUSE_STATS] = { .type = NLA_REJECT },
27};22};
28 23
29static void ethtool_stats_init(u64 *stats, unsigned int n)24static void ethtool_stats_init(u64 *stats, unsigned int n)
@@ -130,10 +125,8 @@ const struct ethnl_request_ops ethnl_pause_request_ops = { · 100 unmodified lines
130 .request_cmd = ETHTOOL_MSG_PAUSE_GET,125 .request_cmd = ETHTOOL_MSG_PAUSE_GET,
131 .reply_cmd = ETHTOOL_MSG_PAUSE_GET_REPLY,126 .reply_cmd = ETHTOOL_MSG_PAUSE_GET_REPLY,
132 .hdr_attr = ETHTOOL_A_PAUSE_HEADER,127 .hdr_attr = ETHTOOL_A_PAUSE_HEADER,
133 .max_attr = ETHTOOL_A_PAUSE_MAX,
134 .req_info_size = sizeof(struct pause_req_info),128 .req_info_size = sizeof(struct pause_req_info),
135 .reply_data_size = sizeof(struct pause_reply_data),129 .reply_data_size = sizeof(struct pause_reply_data),
136 .request_policy = pause_get_policy,
137 130
138 .prepare_data = pause_prepare_data,131 .prepare_data = pause_prepare_data,
139 .reply_size = pause_reply_size,132 .reply_size = pause_reply_size,
@@ -142,30 +135,24 @@ const struct ethnl_request_ops ethnl_pause_request_ops = { · 2 unmodified lines
142 135
143/* PAUSE_SET */136/* PAUSE_SET */
144 137
145static const struct nla_policy138const struct nla_policy ethnl_pause_set_policy[] = {
146pause_set_policy[ETHTOOL_A_PAUSE_MAX + 1] = {139 [ETHTOOL_A_PAUSE_HEADER] =
147 [ETHTOOL_A_PAUSE_UNSPEC] = { .type = NLA_REJECT },140 NLA_POLICY_NESTED(ethnl_header_policy),
148 [ETHTOOL_A_PAUSE_HEADER] = { .type = NLA_NESTED },
149 [ETHTOOL_A_PAUSE_AUTONEG] = { .type = NLA_U8 },141 [ETHTOOL_A_PAUSE_AUTONEG] = { .type = NLA_U8 },
150 [ETHTOOL_A_PAUSE_RX] = { .type = NLA_U8 },142 [ETHTOOL_A_PAUSE_RX] = { .type = NLA_U8 },
151 [ETHTOOL_A_PAUSE_TX] = { .type = NLA_U8 },143 [ETHTOOL_A_PAUSE_TX] = { .type = NLA_U8 },
152 [ETHTOOL_A_PAUSE_STATS] = { .type = NLA_REJECT },
153};144};
154 145
155int ethnl_set_pause(struct sk_buff *skb, struct genl_info *info)146int ethnl_set_pause(struct sk_buff *skb, struct genl_info *info)
156{147{
157 struct nlattr *tb[ETHTOOL_A_PAUSE_MAX + 1];
158 struct ethtool_pauseparam params = {};148 struct ethtool_pauseparam params = {};
159 struct ethnl_req_info req_info = {};149 struct ethnl_req_info req_info = {};
150 struct nlattr **tb = info->attrs;
160 const struct ethtool_ops *ops;151 const struct ethtool_ops *ops;
161 struct net_device *dev;152 struct net_device *dev;
162 bool mod = false;153 bool mod = false;
163 int ret;154 int ret;
164 155
165 ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb, ETHTOOL_A_PAUSE_MAX,
166 pause_set_policy, info->extack);
167 if (ret < 0)
168 return ret;
169 ret = ethnl_parse_header_dev_get(&req_info,156 ret = ethnl_parse_header_dev_get(&req_info,
170 tb[ETHTOOL_A_PAUSE_HEADER],157 tb[ETHTOOL_A_PAUSE_HEADER],
171 genl_info_net(info), info->extack,158 genl_info_net(info), info->extack,
net/ethtool/privflags.c+7−17
@@ -18,11 +18,9 @@ struct privflags_reply_data { · 17 unmodified lines
18#define PRIVFLAGS_REPDATA(__reply_base) \18#define PRIVFLAGS_REPDATA(__reply_base) \
19 container_of(__reply_base, struct privflags_reply_data, base)19 container_of(__reply_base, struct privflags_reply_data, base)
20 20
21static const struct nla_policy21const struct nla_policy ethnl_privflags_get_policy[] = {
22privflags_get_policy[ETHTOOL_A_PRIVFLAGS_MAX + 1] = {22 [ETHTOOL_A_PRIVFLAGS_HEADER] =
23 [ETHTOOL_A_PRIVFLAGS_UNSPEC] = { .type = NLA_REJECT },23 NLA_POLICY_NESTED(ethnl_header_policy),
24 [ETHTOOL_A_PRIVFLAGS_HEADER] = { .type = NLA_NESTED },
25 [ETHTOOL_A_PRIVFLAGS_FLAGS] = { .type = NLA_REJECT },
26};24};
27 25
28static int ethnl_get_priv_flags_info(struct net_device *dev,26static int ethnl_get_priv_flags_info(struct net_device *dev,
@@ -124,10 +122,8 @@ const struct ethnl_request_ops ethnl_privflags_request_ops = { · 95 unmodified lines
124 .request_cmd = ETHTOOL_MSG_PRIVFLAGS_GET,122 .request_cmd = ETHTOOL_MSG_PRIVFLAGS_GET,
125 .reply_cmd = ETHTOOL_MSG_PRIVFLAGS_GET_REPLY,123 .reply_cmd = ETHTOOL_MSG_PRIVFLAGS_GET_REPLY,
126 .hdr_attr = ETHTOOL_A_PRIVFLAGS_HEADER,124 .hdr_attr = ETHTOOL_A_PRIVFLAGS_HEADER,
127 .max_attr = ETHTOOL_A_PRIVFLAGS_MAX,
128 .req_info_size = sizeof(struct privflags_req_info),125 .req_info_size = sizeof(struct privflags_req_info),
129 .reply_data_size = sizeof(struct privflags_reply_data),126 .reply_data_size = sizeof(struct privflags_reply_data),
130 .request_policy = privflags_get_policy,
131 127
132 .prepare_data = privflags_prepare_data,128 .prepare_data = privflags_prepare_data,
133 .reply_size = privflags_reply_size,129 .reply_size = privflags_reply_size,
@@ -137,18 +133,17 @@ const struct ethnl_request_ops ethnl_privflags_request_ops = { · 3 unmodified lines
137 133
138/* PRIVFLAGS_SET */134/* PRIVFLAGS_SET */
139 135
140static const struct nla_policy136const struct nla_policy ethnl_privflags_set_policy[] = {
141privflags_set_policy[ETHTOOL_A_PRIVFLAGS_MAX + 1] = {137 [ETHTOOL_A_PRIVFLAGS_HEADER] =
142 [ETHTOOL_A_PRIVFLAGS_UNSPEC] = { .type = NLA_REJECT },138 NLA_POLICY_NESTED(ethnl_header_policy),
143 [ETHTOOL_A_PRIVFLAGS_HEADER] = { .type = NLA_NESTED },
144 [ETHTOOL_A_PRIVFLAGS_FLAGS] = { .type = NLA_NESTED },139 [ETHTOOL_A_PRIVFLAGS_FLAGS] = { .type = NLA_NESTED },
145};140};
146 141
147int ethnl_set_privflags(struct sk_buff *skb, struct genl_info *info)142int ethnl_set_privflags(struct sk_buff *skb, struct genl_info *info)
148{143{
149 struct nlattr *tb[ETHTOOL_A_PRIVFLAGS_MAX + 1];
150 const char (*names)[ETH_GSTRING_LEN] = NULL;144 const char (*names)[ETH_GSTRING_LEN] = NULL;
151 struct ethnl_req_info req_info = {};145 struct ethnl_req_info req_info = {};
146 struct nlattr **tb = info->attrs;
152 const struct ethtool_ops *ops;147 const struct ethtool_ops *ops;
153 struct net_device *dev;148 struct net_device *dev;
154 unsigned int nflags;149 unsigned int nflags;
@@ -157,11 +152,6 @@ int ethnl_set_privflags(struct sk_buff *skb, struct genl_info *info) · 2 unmodified lines
157 u32 flags;152 u32 flags;
158 int ret;153 int ret;
159 154
160 ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb,
161 ETHTOOL_A_PRIVFLAGS_MAX, privflags_set_policy,
162 info->extack);
163 if (ret < 0)
164 return ret;
165 if (!tb[ETHTOOL_A_PRIVFLAGS_FLAGS])155 if (!tb[ETHTOOL_A_PRIVFLAGS_FLAGS])
166 return -EINVAL;156 return -EINVAL;
167 ret = ethnl_bitset_is_compact(tb[ETHTOOL_A_PRIVFLAGS_FLAGS], &compact);157 ret = ethnl_bitset_is_compact(tb[ETHTOOL_A_PRIVFLAGS_FLAGS], &compact);
net/ethtool/rings.c+7−28
@@ -15,18 +15,9 @@ struct rings_reply_data { · 14 unmodified lines
15#define RINGS_REPDATA(__reply_base) \15#define RINGS_REPDATA(__reply_base) \
16 container_of(__reply_base, struct rings_reply_data, base)16 container_of(__reply_base, struct rings_reply_data, base)
17 17
18static const struct nla_policy18const struct nla_policy ethnl_rings_get_policy[] = {
19rings_get_policy[ETHTOOL_A_RINGS_MAX + 1] = {19 [ETHTOOL_A_RINGS_HEADER] =
20 [ETHTOOL_A_RINGS_UNSPEC] = { .type = NLA_REJECT },20 NLA_POLICY_NESTED(ethnl_header_policy),
21 [ETHTOOL_A_RINGS_HEADER] = { .type = NLA_NESTED },
22 [ETHTOOL_A_RINGS_RX_MAX] = { .type = NLA_REJECT },
23 [ETHTOOL_A_RINGS_RX_MINI_MAX] = { .type = NLA_REJECT },
24 [ETHTOOL_A_RINGS_RX_JUMBO_MAX] = { .type = NLA_REJECT },
25 [ETHTOOL_A_RINGS_TX_MAX] = { .type = NLA_REJECT },
26 [ETHTOOL_A_RINGS_RX] = { .type = NLA_REJECT },
27 [ETHTOOL_A_RINGS_RX_MINI] = { .type = NLA_REJECT },
28 [ETHTOOL_A_RINGS_RX_JUMBO] = { .type = NLA_REJECT },
29 [ETHTOOL_A_RINGS_TX] = { .type = NLA_REJECT },
30};21};
31 22
32static int rings_prepare_data(const struct ethnl_req_info *req_base,23static int rings_prepare_data(const struct ethnl_req_info *req_base,
@@ -97,10 +88,8 @@ const struct ethnl_request_ops ethnl_rings_request_ops = { · 64 unmodified lines
97 .request_cmd = ETHTOOL_MSG_RINGS_GET,88 .request_cmd = ETHTOOL_MSG_RINGS_GET,
98 .reply_cmd = ETHTOOL_MSG_RINGS_GET_REPLY,89 .reply_cmd = ETHTOOL_MSG_RINGS_GET_REPLY,
99 .hdr_attr = ETHTOOL_A_RINGS_HEADER,90 .hdr_attr = ETHTOOL_A_RINGS_HEADER,
100 .max_attr = ETHTOOL_A_RINGS_MAX,
101 .req_info_size = sizeof(struct rings_req_info),91 .req_info_size = sizeof(struct rings_req_info),
102 .reply_data_size = sizeof(struct rings_reply_data),92 .reply_data_size = sizeof(struct rings_reply_data),
103 .request_policy = rings_get_policy,
104 93
105 .prepare_data = rings_prepare_data,94 .prepare_data = rings_prepare_data,
106 .reply_size = rings_reply_size,95 .reply_size = rings_reply_size,
@@ -109,14 +98,9 @@ const struct ethnl_request_ops ethnl_rings_request_ops = { · 2 unmodified lines
109 98
110/* RINGS_SET */99/* RINGS_SET */
111 100
112static const struct nla_policy101const struct nla_policy ethnl_rings_set_policy[] = {
113rings_set_policy[ETHTOOL_A_RINGS_MAX + 1] = {102 [ETHTOOL_A_RINGS_HEADER] =
114 [ETHTOOL_A_RINGS_UNSPEC] = { .type = NLA_REJECT },103 NLA_POLICY_NESTED(ethnl_header_policy),
115 [ETHTOOL_A_RINGS_HEADER] = { .type = NLA_NESTED },
116 [ETHTOOL_A_RINGS_RX_MAX] = { .type = NLA_REJECT },
117 [ETHTOOL_A_RINGS_RX_MINI_MAX] = { .type = NLA_REJECT },
118 [ETHTOOL_A_RINGS_RX_JUMBO_MAX] = { .type = NLA_REJECT },
119 [ETHTOOL_A_RINGS_TX_MAX] = { .type = NLA_REJECT },
120 [ETHTOOL_A_RINGS_RX] = { .type = NLA_U32 },104 [ETHTOOL_A_RINGS_RX] = { .type = NLA_U32 },
121 [ETHTOOL_A_RINGS_RX_MINI] = { .type = NLA_U32 },105 [ETHTOOL_A_RINGS_RX_MINI] = { .type = NLA_U32 },
122 [ETHTOOL_A_RINGS_RX_JUMBO] = { .type = NLA_U32 },106 [ETHTOOL_A_RINGS_RX_JUMBO] = { .type = NLA_U32 },
@@ -125,20 +109,15 @@ rings_set_policy[ETHTOOL_A_RINGS_MAX + 1] = { · 2 unmodified lines
125 109
126int ethnl_set_rings(struct sk_buff *skb, struct genl_info *info)110int ethnl_set_rings(struct sk_buff *skb, struct genl_info *info)
127{111{
128 struct nlattr *tb[ETHTOOL_A_RINGS_MAX + 1];
129 struct ethtool_ringparam ringparam = {};112 struct ethtool_ringparam ringparam = {};
130 struct ethnl_req_info req_info = {};113 struct ethnl_req_info req_info = {};
114 struct nlattr **tb = info->attrs;
131 const struct nlattr *err_attr;115 const struct nlattr *err_attr;
132 const struct ethtool_ops *ops;116 const struct ethtool_ops *ops;
133 struct net_device *dev;117 struct net_device *dev;
134 bool mod = false;118 bool mod = false;
135 int ret;119 int ret;
136 120
137 ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb,
138 ETHTOOL_A_RINGS_MAX, rings_set_policy,
139 info->extack);
140 if (ret < 0)
141 return ret;
142 ret = ethnl_parse_header_dev_get(&req_info,121 ret = ethnl_parse_header_dev_get(&req_info,
143 tb[ETHTOOL_A_RINGS_HEADER],122 tb[ETHTOOL_A_RINGS_HEADER],
144 genl_info_net(info), info->extack,123 genl_info_net(info), info->extack,
net/ethtool/strset.c+9−16
@@ -99,18 +99,14 @@ struct strset_reply_data { · 98 unmodified lines
99#define STRSET_REPDATA(__reply_base) \99#define STRSET_REPDATA(__reply_base) \
100 container_of(__reply_base, struct strset_reply_data, base)100 container_of(__reply_base, struct strset_reply_data, base)
101 101
102static const struct nla_policy strset_get_policy[ETHTOOL_A_STRSET_MAX + 1] = {102const struct nla_policy ethnl_strset_get_policy[] = {
103 [ETHTOOL_A_STRSET_UNSPEC] = { .type = NLA_REJECT },103 [ETHTOOL_A_STRSET_HEADER] =
104 [ETHTOOL_A_STRSET_HEADER] = { .type = NLA_NESTED },104 NLA_POLICY_NESTED(ethnl_header_policy),
105 [ETHTOOL_A_STRSET_STRINGSETS] = { .type = NLA_NESTED },105 [ETHTOOL_A_STRSET_STRINGSETS] = { .type = NLA_NESTED },
106};106};
107 107
108static const struct nla_policy108static const struct nla_policy get_stringset_policy[] = {
109get_stringset_policy[ETHTOOL_A_STRINGSET_MAX + 1] = {
110 [ETHTOOL_A_STRINGSET_UNSPEC] = { .type = NLA_REJECT },
111 [ETHTOOL_A_STRINGSET_ID] = { .type = NLA_U32 },109 [ETHTOOL_A_STRINGSET_ID] = { .type = NLA_U32 },
112 [ETHTOOL_A_STRINGSET_COUNT] = { .type = NLA_REJECT },
113 [ETHTOOL_A_STRINGSET_STRINGS] = { .type = NLA_REJECT },
114};110};
115 111
116/**112/**
@@ -138,10 +134,10 @@ static bool strset_include(const struct strset_req_info *info, · 21 unmodified lines
138static int strset_get_id(const struct nlattr *nest, u32 *val,134static int strset_get_id(const struct nlattr *nest, u32 *val,
139 struct netlink_ext_ack *extack)135 struct netlink_ext_ack *extack)
140{136{
141 struct nlattr *tb[ETHTOOL_A_STRINGSET_MAX + 1];137 struct nlattr *tb[ARRAY_SIZE(get_stringset_policy)];
142 int ret;138 int ret;
143 139
144 ret = nla_parse_nested(tb, ETHTOOL_A_STRINGSET_MAX, nest,140 ret = nla_parse_nested(tb, ARRAY_SIZE(get_stringset_policy) - 1, nest,
145 get_stringset_policy, extack);141 get_stringset_policy, extack);
146 if (ret < 0)142 if (ret < 0)
147 return ret;143 return ret;
@@ -152,9 +148,7 @@ static int strset_get_id(const struct nlattr *nest, u32 *val, · 4 unmodified lines
152 return 0;148 return 0;
153}149}
154 150
155static const struct nla_policy151static const struct nla_policy strset_stringsets_policy[] = {
156strset_stringsets_policy[ETHTOOL_A_STRINGSETS_MAX + 1] = {
157 [ETHTOOL_A_STRINGSETS_UNSPEC] = { .type = NLA_REJECT },
158 [ETHTOOL_A_STRINGSETS_STRINGSET] = { .type = NLA_NESTED },152 [ETHTOOL_A_STRINGSETS_STRINGSET] = { .type = NLA_NESTED },
159};153};
160 154
@@ -169,7 +163,8 @@ static int strset_parse_request(struct ethnl_req_info *req_base, · 8 unmodified lines
169 163
170 if (!nest)164 if (!nest)
171 return 0;165 return 0;
172 ret = nla_validate_nested(nest, ETHTOOL_A_STRINGSETS_MAX,166 ret = nla_validate_nested(nest,
167 ARRAY_SIZE(strset_stringsets_policy) - 1,
173 strset_stringsets_policy, extack);168 strset_stringsets_policy, extack);
174 if (ret < 0)169 if (ret < 0)
175 return ret;170 return ret;
@@ -445,10 +440,8 @@ const struct ethnl_request_ops ethnl_strset_request_ops = { · 269 unmodified lines
445 .request_cmd = ETHTOOL_MSG_STRSET_GET,440 .request_cmd = ETHTOOL_MSG_STRSET_GET,
446 .reply_cmd = ETHTOOL_MSG_STRSET_GET_REPLY,441 .reply_cmd = ETHTOOL_MSG_STRSET_GET_REPLY,
447 .hdr_attr = ETHTOOL_A_STRSET_HEADER,442 .hdr_attr = ETHTOOL_A_STRSET_HEADER,
448 .max_attr = ETHTOOL_A_STRSET_MAX,
449 .req_info_size = sizeof(struct strset_req_info),443 .req_info_size = sizeof(struct strset_req_info),
450 .reply_data_size = sizeof(struct strset_reply_data),444 .reply_data_size = sizeof(struct strset_reply_data),
451 .request_policy = strset_get_policy,
452 .allow_nodev_do = true,445 .allow_nodev_do = true,
453 446
454 .parse_request = strset_parse_request,447 .parse_request = strset_parse_request,
net/ethtool/tsinfo.c+3−10
@@ -18,14 +18,9 @@ struct tsinfo_reply_data { · 17 unmodified lines
18#define TSINFO_REPDATA(__reply_base) \18#define TSINFO_REPDATA(__reply_base) \
19 container_of(__reply_base, struct tsinfo_reply_data, base)19 container_of(__reply_base, struct tsinfo_reply_data, base)
20 20
21static const struct nla_policy21const struct nla_policy ethnl_tsinfo_get_policy[] = {
22tsinfo_get_policy[ETHTOOL_A_TSINFO_MAX + 1] = {22 [ETHTOOL_A_TSINFO_HEADER] =
23 [ETHTOOL_A_TSINFO_UNSPEC] = { .type = NLA_REJECT },23 NLA_POLICY_NESTED(ethnl_header_policy),
24 [ETHTOOL_A_TSINFO_HEADER] = { .type = NLA_NESTED },
25 [ETHTOOL_A_TSINFO_TIMESTAMPING] = { .type = NLA_REJECT },
26 [ETHTOOL_A_TSINFO_TX_TYPES] = { .type = NLA_REJECT },
27 [ETHTOOL_A_TSINFO_RX_FILTERS] = { .type = NLA_REJECT },
28 [ETHTOOL_A_TSINFO_PHC_INDEX] = { .type = NLA_REJECT },
29};24};
30 25
31static int tsinfo_prepare_data(const struct ethnl_req_info *req_base,26static int tsinfo_prepare_data(const struct ethnl_req_info *req_base,
@@ -132,10 +127,8 @@ const struct ethnl_request_ops ethnl_tsinfo_request_ops = { · 100 unmodified lines
132 .request_cmd = ETHTOOL_MSG_TSINFO_GET,127 .request_cmd = ETHTOOL_MSG_TSINFO_GET,
133 .reply_cmd = ETHTOOL_MSG_TSINFO_GET_REPLY,128 .reply_cmd = ETHTOOL_MSG_TSINFO_GET_REPLY,
134 .hdr_attr = ETHTOOL_A_TSINFO_HEADER,129 .hdr_attr = ETHTOOL_A_TSINFO_HEADER,
135 .max_attr = ETHTOOL_A_TSINFO_MAX,
136 .req_info_size = sizeof(struct tsinfo_req_info),130 .req_info_size = sizeof(struct tsinfo_req_info),
137 .reply_data_size = sizeof(struct tsinfo_reply_data),131 .reply_data_size = sizeof(struct tsinfo_reply_data),
138 .request_policy = tsinfo_get_policy,
139 132
140 .prepare_data = tsinfo_prepare_data,133 .prepare_data = tsinfo_prepare_data,
141 .reply_size = tsinfo_reply_size,134 .reply_size = tsinfo_reply_size,
net/ethtool/tunnels.c+14−28
@@ -8,10 +8,9 @@ · 7 unmodified lines
8#include "common.h"8#include "common.h"
9#include "netlink.h"9#include "netlink.h"
10 10
11static const struct nla_policy11const struct nla_policy ethnl_tunnel_info_get_policy[] = {
12ethtool_tunnel_info_policy[ETHTOOL_A_TUNNEL_INFO_MAX + 1] = {12 [ETHTOOL_A_TUNNEL_INFO_HEADER] =
13 [ETHTOOL_A_TUNNEL_INFO_UNSPEC] = { .type = NLA_REJECT },13 NLA_POLICY_NESTED(ethnl_header_policy),
14 [ETHTOOL_A_TUNNEL_INFO_HEADER] = { .type = NLA_NESTED },
15};14};
16 15
17static_assert(ETHTOOL_UDP_TUNNEL_TYPE_VXLAN == ilog2(UDP_TUNNEL_TYPE_VXLAN));16static_assert(ETHTOOL_UDP_TUNNEL_TYPE_VXLAN == ilog2(UDP_TUNNEL_TYPE_VXLAN));
@@ -161,35 +160,19 @@ err_cancel_ports: · 143 unmodified lines
161 return -EMSGSIZE;160 return -EMSGSIZE;
162}161}
163 162
164static int
165ethnl_tunnel_info_req_parse(struct ethnl_req_info *req_info,
166 const struct nlmsghdr *nlhdr, struct net *net,
167 struct netlink_ext_ack *extack, bool require_dev)
168{
169 struct nlattr *tb[ETHTOOL_A_TUNNEL_INFO_MAX + 1];
170 int ret;
171
172 ret = nlmsg_parse(nlhdr, GENL_HDRLEN, tb, ETHTOOL_A_TUNNEL_INFO_MAX,
173 ethtool_tunnel_info_policy, extack);
174 if (ret < 0)
175 return ret;
176
177 return ethnl_parse_header_dev_get(req_info,
178 tb[ETHTOOL_A_TUNNEL_INFO_HEADER],
179 net, extack, require_dev);
180}
181
182int ethnl_tunnel_info_doit(struct sk_buff *skb, struct genl_info *info)163int ethnl_tunnel_info_doit(struct sk_buff *skb, struct genl_info *info)
183{164{
184 struct ethnl_req_info req_info = {};165 struct ethnl_req_info req_info = {};
166 struct nlattr **tb = info->attrs;
185 struct sk_buff *rskb;167 struct sk_buff *rskb;
186 void *reply_payload;168 void *reply_payload;
187 int reply_len;169 int reply_len;
188 int ret;170 int ret;
189 171
190 ret = ethnl_tunnel_info_req_parse(&req_info, info->nlhdr,172 ret = ethnl_parse_header_dev_get(&req_info,
191 genl_info_net(info), info->extack,173 tb[ETHTOOL_A_TUNNEL_INFO_HEADER],
192 true);174 genl_info_net(info), info->extack,
175 true);
193 if (ret < 0)176 if (ret < 0)
194 return ret;177 return ret;
195 178
@@ -233,16 +216,19 @@ struct ethnl_tunnel_info_dump_ctx { · 37 unmodified lines
233 216
234int ethnl_tunnel_info_start(struct netlink_callback *cb)217int ethnl_tunnel_info_start(struct netlink_callback *cb)
235{218{
219 const struct genl_dumpit_info *info = genl_dumpit_info(cb);
236 struct ethnl_tunnel_info_dump_ctx *ctx = (void *)cb->ctx;220 struct ethnl_tunnel_info_dump_ctx *ctx = (void *)cb->ctx;
221 struct nlattr **tb = info->attrs;
237 int ret;222 int ret;
238 223
239 BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx));224 BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx));
240 225
241 memset(ctx, 0, sizeof(*ctx));226 memset(ctx, 0, sizeof(*ctx));
242 227
243 ret = ethnl_tunnel_info_req_parse(&ctx->req_info, cb->nlh,228 ret = ethnl_parse_header_dev_get(&ctx->req_info,
244 sock_net(cb->skb->sk), cb->extack,229 tb[ETHTOOL_A_TUNNEL_INFO_HEADER],
245 false);230 sock_net(cb->skb->sk), cb->extack,
231 false);
246 if (ctx->req_info.dev) {232 if (ctx->req_info.dev) {
247 dev_put(ctx->req_info.dev);233 dev_put(ctx->req_info.dev);
248 ctx->req_info.dev = NULL;234 ctx->req_info.dev = NULL;
net/ethtool/wol.c+7−17
@@ -17,12 +17,9 @@ struct wol_reply_data { · 16 unmodified lines
17#define WOL_REPDATA(__reply_base) \17#define WOL_REPDATA(__reply_base) \
18 container_of(__reply_base, struct wol_reply_data, base)18 container_of(__reply_base, struct wol_reply_data, base)
19 19
20static const struct nla_policy20const struct nla_policy ethnl_wol_get_policy[] = {
21wol_get_policy[ETHTOOL_A_WOL_MAX + 1] = {21 [ETHTOOL_A_WOL_HEADER] =
22 [ETHTOOL_A_WOL_UNSPEC] = { .type = NLA_REJECT },22 NLA_POLICY_NESTED(ethnl_header_policy),
23 [ETHTOOL_A_WOL_HEADER] = { .type = NLA_NESTED },
24 [ETHTOOL_A_WOL_MODES] = { .type = NLA_REJECT },
25 [ETHTOOL_A_WOL_SOPASS] = { .type = NLA_REJECT },
26};23};
27 24
28static int wol_prepare_data(const struct ethnl_req_info *req_base,25static int wol_prepare_data(const struct ethnl_req_info *req_base,
@@ -89,10 +86,8 @@ const struct ethnl_request_ops ethnl_wol_request_ops = { · 60 unmodified lines
89 .request_cmd = ETHTOOL_MSG_WOL_GET,86 .request_cmd = ETHTOOL_MSG_WOL_GET,
90 .reply_cmd = ETHTOOL_MSG_WOL_GET_REPLY,87 .reply_cmd = ETHTOOL_MSG_WOL_GET_REPLY,
91 .hdr_attr = ETHTOOL_A_WOL_HEADER,88 .hdr_attr = ETHTOOL_A_WOL_HEADER,
92 .max_attr = ETHTOOL_A_WOL_MAX,
93 .req_info_size = sizeof(struct wol_req_info),89 .req_info_size = sizeof(struct wol_req_info),
94 .reply_data_size = sizeof(struct wol_reply_data),90 .reply_data_size = sizeof(struct wol_reply_data),
95 .request_policy = wol_get_policy,
96 91
97 .prepare_data = wol_prepare_data,92 .prepare_data = wol_prepare_data,
98 .reply_size = wol_reply_size,93 .reply_size = wol_reply_size,
@@ -101,10 +96,9 @@ const struct ethnl_request_ops ethnl_wol_request_ops = { · 2 unmodified lines
101 96
102/* WOL_SET */97/* WOL_SET */
103 98
104static const struct nla_policy99const struct nla_policy ethnl_wol_set_policy[] = {
105wol_set_policy[ETHTOOL_A_WOL_MAX + 1] = {100 [ETHTOOL_A_WOL_HEADER] =
106 [ETHTOOL_A_WOL_UNSPEC] = { .type = NLA_REJECT },101 NLA_POLICY_NESTED(ethnl_header_policy),
107 [ETHTOOL_A_WOL_HEADER] = { .type = NLA_NESTED },
108 [ETHTOOL_A_WOL_MODES] = { .type = NLA_NESTED },102 [ETHTOOL_A_WOL_MODES] = { .type = NLA_NESTED },
109 [ETHTOOL_A_WOL_SOPASS] = { .type = NLA_BINARY,103 [ETHTOOL_A_WOL_SOPASS] = { .type = NLA_BINARY,
110 .len = SOPASS_MAX },104 .len = SOPASS_MAX },
@@ -113,16 +107,12 @@ wol_set_policy[ETHTOOL_A_WOL_MAX + 1] = { · 2 unmodified lines
113int ethnl_set_wol(struct sk_buff *skb, struct genl_info *info)107int ethnl_set_wol(struct sk_buff *skb, struct genl_info *info)
114{108{
115 struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL };109 struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL };
116 struct nlattr *tb[ETHTOOL_A_WOL_MAX + 1];
117 struct ethnl_req_info req_info = {};110 struct ethnl_req_info req_info = {};
111 struct nlattr **tb = info->attrs;
118 struct net_device *dev;112 struct net_device *dev;
119 bool mod = false;113 bool mod = false;
120 int ret;114 int ret;
121 115
122 ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb, ETHTOOL_A_WOL_MAX,
123 wol_set_policy, info->extack);
124 if (ret < 0)
125 return ret;
126 ret = ethnl_parse_header_dev_get(&req_info, tb[ETHTOOL_A_WOL_HEADER],116 ret = ethnl_parse_header_dev_get(&req_info, tb[ETHTOOL_A_WOL_HEADER],
127 genl_info_net(info), info->extack,117 genl_info_net(info), info->extack,
128 true);118 true);
net/netlink/policy.c+8−0
@@ -263,6 +263,14 @@ send_attribute: · 262 unmodified lines
263 else263 else
264 type = NL_ATTR_TYPE_U64;264 type = NL_ATTR_TYPE_U64;
265 265
266 if (pt->validation_type == NLA_VALIDATE_MASK) {
267 if (nla_put_u64_64bit(skb, NL_POLICY_TYPE_ATTR_MASK,
268 pt->mask,
269 NL_POLICY_TYPE_ATTR_PAD))
270 goto nla_put_failure;
271 break;
272 }
273
266 nla_get_range_unsigned(pt, &range);274 nla_get_range_unsigned(pt, &range);
267 275
268 if (nla_put_u64_64bit(skb, NL_POLICY_TYPE_ATTR_MIN_VALUE_U,276 if (nla_put_u64_64bit(skb, NL_POLICY_TYPE_ATTR_MIN_VALUE_U,