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
200200 NLA_VALIDATE_RANGE_WARN_TOO_LONG,
201201 NLA_VALIDATE_MIN,
202202 NLA_VALIDATE_MAX,
203+ NLA_VALIDATE_MASK,
203204 NLA_VALIDATE_RANGE_PTR,
204205 NLA_VALIDATE_FUNCTION,
205206 };
@@ -317,6 +318,7 @@ struct nla_policy { · 111 unmodified lines
317318 u16 len;
318319 union {
319320 const u32 bitfield32_valid;
321+ const u32 mask;
320322 const char *reject_message;
321323 const struct nla_policy *nested_policy;
322324 struct netlink_range_validation *range;
@@ -362,20 +364,23 @@ struct nla_policy { · 39 unmodified lines
362364 #define NLA_POLICY_BITFIELD32(valid) \
363365 { .type = NLA_BITFIELD32, .bitfield32_valid = valid }
364366
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+
365372 #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)
366375 #define NLA_ENSURE_UINT_OR_BINARY_TYPE(tp) \
367− (__NLA_ENSURE(tp == NLA_U8 || tp == NLA_U16 || \
368− tp == NLA_U32 || tp == NLA_U64 || \
376+ (__NLA_ENSURE(__NLA_IS_UINT_TYPE(tp) || \
369377 tp == NLA_MSECS || \
370378 tp == NLA_BINARY) + tp)
371379 #define NLA_ENSURE_SINT_TYPE(tp) \
372− (__NLA_ENSURE(tp == NLA_S8 || tp == NLA_S16 || \
373− tp == NLA_S32 || tp == NLA_S64) + tp)
380+ (__NLA_ENSURE(__NLA_IS_SINT_TYPE(tp)) + tp)
374381 #define NLA_ENSURE_INT_OR_BINARY_TYPE(tp) \
375− (__NLA_ENSURE(tp == NLA_S8 || tp == NLA_U8 || \
376− tp == NLA_S16 || tp == NLA_U16 || \
377− tp == NLA_S32 || tp == NLA_U32 || \
378− tp == NLA_S64 || tp == NLA_U64 || \
382+ (__NLA_ENSURE(__NLA_IS_UINT_TYPE(tp) || \
383+ __NLA_IS_SINT_TYPE(tp) || \
379384 tp == NLA_MSECS || \
380385 tp == NLA_BINARY) + tp)
381386 #define NLA_ENSURE_NO_VALIDATION_PTR(tp) \
@@ -415,6 +420,12 @@ struct nla_policy { · 33 unmodified lines
415420 .max = _max, \
416421 }
417422
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+
418429 #define NLA_POLICY_VALIDATE_FN(tp, fn, ...) { \
419430 .type = NLA_ENSURE_NO_VALIDATION_PTR(tp), \
420431 .validation_type = NLA_VALIDATE_FUNCTION, \
include/uapi/linux/netlink.h+2−0
@@ -331,6 +331,7 @@ enum netlink_attribute_type { · 330 unmodified lines
331331 * the index, if limited inside the nesting (U32)
332332 * @NL_POLICY_TYPE_ATTR_BITFIELD32_MASK: valid mask for the
333333 * bitfield32 type (U32)
334+ * @NL_POLICY_TYPE_ATTR_MASK: mask of valid bits for unsigned integers (U64)
334335 * @NL_POLICY_TYPE_ATTR_PAD: pad attribute for 64-bit alignment
335336 */
336337 enum netlink_policy_type_attr {
@@ -346,6 +347,7 @@ enum netlink_policy_type_attr { · 9 unmodified lines
346347 NL_POLICY_TYPE_ATTR_POLICY_MAXTYPE,
347348 NL_POLICY_TYPE_ATTR_BITFIELD32_MASK,
348349 NL_POLICY_TYPE_ATTR_PAD,
350+ NL_POLICY_TYPE_ATTR_MASK,
349351
350352 /* keep last */
351353 __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
323323 }
324324 }
325325
326+static 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+
326357 static int validate_nla(const struct nlattr *nla, int maxtype,
327358 const struct nla_policy *policy, unsigned int validate,
328359 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
503534 if (err)
504535 return err;
505536 break;
537+ case NLA_VALIDATE_MASK:
538+ err = nla_validate_mask(pt, nla, extack);
539+ if (err)
540+ return err;
541+ break;
506542 case NLA_VALIDATE_FUNCTION:
507543 if (pt->validate) {
508544 err = pt->validate(nla, extack);
net/ethtool/bitset.c+12−14
@@ -302,8 +302,7 @@ nla_put_failure: · 301 unmodified lines
302302 return -EMSGSIZE;
303303 }
304304
305−static const struct nla_policy bitset_policy[ETHTOOL_A_BITSET_MAX + 1] = {
306− [ETHTOOL_A_BITSET_UNSPEC] = { .type = NLA_REJECT },
305+static const struct nla_policy bitset_policy[] = {
307306 [ETHTOOL_A_BITSET_NOMASK] = { .type = NLA_FLAG },
308307 [ETHTOOL_A_BITSET_SIZE] = NLA_POLICY_MAX(NLA_U32,
309308 ETHNL_MAX_BITSET_SIZE),
@@ -312,8 +311,7 @@ static const struct nla_policy bitset_policy[ETHTOOL_A_BITSET_MAX + 1] = { · 2 unmodified lines
312311 [ETHTOOL_A_BITSET_MASK] = { .type = NLA_BINARY },
313312 };
314313
315−static const struct nla_policy bit_policy[ETHTOOL_A_BITSET_BIT_MAX + 1] = {
316− [ETHTOOL_A_BITSET_BIT_UNSPEC] = { .type = NLA_REJECT },
314+static const struct nla_policy bit_policy[] = {
317315 [ETHTOOL_A_BITSET_BIT_INDEX] = { .type = NLA_U32 },
318316 [ETHTOOL_A_BITSET_BIT_NAME] = { .type = NLA_NUL_STRING },
319317 [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
329327 */
330328 int ethnl_bitset_is_compact(const struct nlattr *bitset, bool *compact)
331329 {
332− struct nlattr *tb[ETHTOOL_A_BITSET_MAX + 1];
330+ struct nlattr *tb[ARRAY_SIZE(bitset_policy)];
333331 int ret;
334332
335− ret = nla_parse_nested(tb, ETHTOOL_A_BITSET_MAX, bitset,
333+ ret = nla_parse_nested(tb, ARRAY_SIZE(bitset_policy) - 1, bitset,
336334 bitset_policy, NULL);
337335 if (ret < 0)
338336 return ret;
@@ -381,10 +379,10 @@ static int ethnl_parse_bit(unsigned int *index, bool *val, unsigned int nbits, · 42 unmodified lines
381379 ethnl_string_array_t names,
382380 struct netlink_ext_ack *extack)
383381 {
384− struct nlattr *tb[ETHTOOL_A_BITSET_BIT_MAX + 1];
382+ struct nlattr *tb[ARRAY_SIZE(bit_policy)];
385383 int ret, idx;
386384
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,
388386 bit_policy, extack);
389387 if (ret < 0)
390388 return ret;
@@ -555,15 +553,15 @@ int ethnl_update_bitset32(u32 *bitmap, unsigned int nbits, · 164 unmodified lines
555553 const struct nlattr *attr, ethnl_string_array_t names,
556554 struct netlink_ext_ack *extack, bool *mod)
557555 {
558− struct nlattr *tb[ETHTOOL_A_BITSET_MAX + 1];
556+ struct nlattr *tb[ARRAY_SIZE(bitset_policy)];
559557 unsigned int change_bits;
560558 bool no_mask;
561559 int ret;
562560
563561 if (!attr)
564562 return 0;
565− ret = nla_parse_nested(tb, ETHTOOL_A_BITSET_MAX, attr, bitset_policy,
566− extack);
563+ ret = nla_parse_nested(tb, ARRAY_SIZE(bitset_policy) - 1, attr,
564+ bitset_policy, extack);
567565 if (ret < 0)
568566 return ret;
569567
@@ -608,7 +606,7 @@ int ethnl_parse_bitset(unsigned long *val, unsigned long *mask, · 38 unmodified lines
608606 ethnl_string_array_t names,
609607 struct netlink_ext_ack *extack)
610608 {
611− struct nlattr *tb[ETHTOOL_A_BITSET_MAX + 1];
609+ struct nlattr *tb[ARRAY_SIZE(bitset_policy)];
612610 const struct nlattr *bit_attr;
613611 bool no_mask;
614612 int rem;
@@ -616,8 +614,8 @@ int ethnl_parse_bitset(unsigned long *val, unsigned long *mask, · 1 unmodified line
616614
617615 if (!attr)
618616 return 0;
619− ret = nla_parse_nested(tb, ETHTOOL_A_BITSET_MAX, attr, bitset_policy,
620− extack);
617+ ret = nla_parse_nested(tb, ARRAY_SIZE(bitset_policy) - 1, attr,
618+ bitset_policy, extack);
621619 if (ret < 0)
622620 return ret;
623621 no_mask = tb[ETHTOOL_A_BITSET_NOMASK];
net/ethtool/cabletest.c+14−27
@@ -11,10 +11,9 @@ · 10 unmodified lines
1111 */
1212 #define MAX_CABLE_LENGTH_CM (150 * 100)
1313
14−static const struct nla_policy
15−cable_test_act_policy[ETHTOOL_A_CABLE_TEST_MAX + 1] = {
16− [ETHTOOL_A_CABLE_TEST_UNSPEC] = { .type = NLA_REJECT },
17− [ETHTOOL_A_CABLE_TEST_HEADER] = { .type = NLA_NESTED },
14+const struct nla_policy ethnl_cable_test_act_policy[] = {
15+ [ETHTOOL_A_CABLE_TEST_HEADER] =
16+ NLA_POLICY_NESTED(ethnl_header_policy),
1817 };
1918
2019 static int ethnl_cable_test_started(struct phy_device *phydev, u8 cmd)
@@ -56,18 +55,12 @@ out: · 35 unmodified lines
5655
5756 int ethnl_act_cable_test(struct sk_buff *skb, struct genl_info *info)
5857 {
59− struct nlattr *tb[ETHTOOL_A_CABLE_TEST_MAX + 1];
6058 struct ethnl_req_info req_info = {};
6159 const struct ethtool_phy_ops *ops;
60+ struct nlattr **tb = info->attrs;
6261 struct net_device *dev;
6362 int ret;
6463
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−
7164 ret = ethnl_parse_header_dev_get(&req_info,
7265 tb[ETHTOOL_A_CABLE_TEST_HEADER],
7366 genl_info_net(info), info->extack,
@@ -218,18 +211,16 @@ struct cable_test_tdr_req_info { · 144 unmodified lines
218211 struct ethnl_req_info base;
219212 };
220213
221−static const struct nla_policy
222−cable_test_tdr_act_cfg_policy[ETHTOOL_A_CABLE_TEST_TDR_CFG_MAX + 1] = {
214+static const struct nla_policy cable_test_tdr_act_cfg_policy[] = {
223215 [ETHTOOL_A_CABLE_TEST_TDR_CFG_FIRST] = { .type = NLA_U32 },
224216 [ETHTOOL_A_CABLE_TEST_TDR_CFG_LAST] = { .type = NLA_U32 },
225217 [ETHTOOL_A_CABLE_TEST_TDR_CFG_STEP] = { .type = NLA_U32 },
226218 [ETHTOOL_A_CABLE_TEST_TDR_CFG_PAIR] = { .type = NLA_U8 },
227219 };
228220
229−static const struct nla_policy
230−cable_test_tdr_act_policy[ETHTOOL_A_CABLE_TEST_TDR_MAX + 1] = {
231− [ETHTOOL_A_CABLE_TEST_TDR_UNSPEC] = { .type = NLA_REJECT },
232− [ETHTOOL_A_CABLE_TEST_TDR_HEADER] = { .type = NLA_NESTED },
221+const struct nla_policy ethnl_cable_test_tdr_act_policy[] = {
222+ [ETHTOOL_A_CABLE_TEST_TDR_HEADER] =
223+ NLA_POLICY_NESTED(ethnl_header_policy),
233224 [ETHTOOL_A_CABLE_TEST_TDR_CFG] = { .type = NLA_NESTED },
234225 };
235226
@@ -238,7 +229,7 @@ static int ethnl_act_cable_test_tdr_cfg(const struct nlattr *nest, · 2 unmodified lines
238229 struct genl_info *info,
239230 struct phy_tdr_config *cfg)
240231 {
241− struct nlattr *tb[ETHTOOL_A_CABLE_TEST_TDR_CFG_MAX + 1];
232+ struct nlattr *tb[ARRAY_SIZE(cable_test_tdr_act_cfg_policy)];
242233 int ret;
243234
244235 cfg->first = 100;
@@ -249,8 +240,10 @@ static int ethnl_act_cable_test_tdr_cfg(const struct nlattr *nest, · 4 unmodified lines
249240 if (!nest)
250241 return 0;
251242
252− ret = nla_parse_nested(tb, ETHTOOL_A_CABLE_TEST_TDR_CFG_MAX, nest,
253− cable_test_tdr_act_cfg_policy, info->extack);
243+ ret = nla_parse_nested(tb,
244+ ARRAY_SIZE(cable_test_tdr_act_cfg_policy) - 1,
245+ nest, cable_test_tdr_act_cfg_policy,
246+ info->extack);
254247 if (ret < 0)
255248 return ret;
256249
@@ -313,19 +306,13 @@ static int ethnl_act_cable_test_tdr_cfg(const struct nlattr *nest, · 56 unmodified lines
313306
314307 int ethnl_act_cable_test_tdr(struct sk_buff *skb, struct genl_info *info)
315308 {
316− struct nlattr *tb[ETHTOOL_A_CABLE_TEST_TDR_MAX + 1];
317309 struct ethnl_req_info req_info = {};
318310 const struct ethtool_phy_ops *ops;
311+ struct nlattr **tb = info->attrs;
319312 struct phy_tdr_config cfg;
320313 struct net_device *dev;
321314 int ret;
322315
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−
329316 ret = ethnl_parse_header_dev_get(&req_info,
330317 tb[ETHTOOL_A_CABLE_TEST_TDR_HEADER],
331318 genl_info_net(info), info->extack,
net/ethtool/channels.c+7−28
@@ -17,18 +17,9 @@ struct channels_reply_data { · 16 unmodified lines
1717 #define CHANNELS_REPDATA(__reply_base) \
1818 container_of(__reply_base, struct channels_reply_data, base)
1919
20−static const struct nla_policy
21−channels_get_policy[ETHTOOL_A_CHANNELS_MAX + 1] = {
22− [ETHTOOL_A_CHANNELS_UNSPEC] = { .type = NLA_REJECT },
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 },
20+const struct nla_policy ethnl_channels_get_policy[] = {
21+ [ETHTOOL_A_CHANNELS_HEADER] =
22+ NLA_POLICY_NESTED(ethnl_header_policy),
3223 };
3324
3425 static 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
9990 .request_cmd = ETHTOOL_MSG_CHANNELS_GET,
10091 .reply_cmd = ETHTOOL_MSG_CHANNELS_GET_REPLY,
10192 .hdr_attr = ETHTOOL_A_CHANNELS_HEADER,
102− .max_attr = ETHTOOL_A_CHANNELS_MAX,
10393 .req_info_size = sizeof(struct channels_req_info),
10494 .reply_data_size = sizeof(struct channels_reply_data),
105− .request_policy = channels_get_policy,
10695
10796 .prepare_data = channels_prepare_data,
10897 .reply_size = channels_reply_size,
@@ -111,14 +100,9 @@ const struct ethnl_request_ops ethnl_channels_request_ops = { · 2 unmodified lines
111100
112101 /* CHANNELS_SET */
113102
114−static const struct nla_policy
115−channels_set_policy[ETHTOOL_A_CHANNELS_MAX + 1] = {
116− [ETHTOOL_A_CHANNELS_UNSPEC] = { .type = NLA_REJECT },
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 },
103+const struct nla_policy ethnl_channels_set_policy[] = {
104+ [ETHTOOL_A_CHANNELS_HEADER] =
105+ NLA_POLICY_NESTED(ethnl_header_policy),
122106 [ETHTOOL_A_CHANNELS_RX_COUNT] = { .type = NLA_U32 },
123107 [ETHTOOL_A_CHANNELS_TX_COUNT] = { .type = NLA_U32 },
124108 [ETHTOOL_A_CHANNELS_OTHER_COUNT] = { .type = NLA_U32 },
@@ -127,22 +111,17 @@ channels_set_policy[ETHTOOL_A_CHANNELS_MAX + 1] = { · 2 unmodified lines
127111
128112 int ethnl_set_channels(struct sk_buff *skb, struct genl_info *info)
129113 {
130− struct nlattr *tb[ETHTOOL_A_CHANNELS_MAX + 1];
131114 unsigned int from_channel, old_total, i;
132115 bool mod = false, mod_combined = false;
133116 struct ethtool_channels channels = {};
134117 struct ethnl_req_info req_info = {};
118+ struct nlattr **tb = info->attrs;
135119 const struct nlattr *err_attr;
136120 const struct ethtool_ops *ops;
137121 struct net_device *dev;
138122 u32 max_rx_in_use = 0;
139123 int ret;
140124
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;
146125 ret = ethnl_parse_header_dev_get(&req_info,
147126 tb[ETHTOOL_A_CHANNELS_HEADER],
148127 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
5151 __CHECK_SUPPORTED_OFFSET(COALESCE_TX_MAX_FRAMES_HIGH);
5252 __CHECK_SUPPORTED_OFFSET(COALESCE_RATE_SAMPLE_INTERVAL);
5353
54−static const struct nla_policy
55−coalesce_get_policy[ETHTOOL_A_COALESCE_MAX + 1] = {
56− [ETHTOOL_A_COALESCE_UNSPEC] = { .type = NLA_REJECT },
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 },
54+const struct nla_policy ethnl_coalesce_get_policy[] = {
55+ [ETHTOOL_A_COALESCE_HEADER] =
56+ NLA_POLICY_NESTED(ethnl_header_policy),
8057 };
8158
8259 static 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
203180 .request_cmd = ETHTOOL_MSG_COALESCE_GET,
204181 .reply_cmd = ETHTOOL_MSG_COALESCE_GET_REPLY,
205182 .hdr_attr = ETHTOOL_A_COALESCE_HEADER,
206− .max_attr = ETHTOOL_A_COALESCE_MAX,
207183 .req_info_size = sizeof(struct coalesce_req_info),
208184 .reply_data_size = sizeof(struct coalesce_reply_data),
209− .request_policy = coalesce_get_policy,
210185
211186 .prepare_data = coalesce_prepare_data,
212187 .reply_size = coalesce_reply_size,
@@ -215,10 +190,9 @@ const struct ethnl_request_ops ethnl_coalesce_request_ops = { · 2 unmodified lines
215190
216191 /* COALESCE_SET */
217192
218−static const struct nla_policy
219−coalesce_set_policy[ETHTOOL_A_COALESCE_MAX + 1] = {
220− [ETHTOOL_A_COALESCE_UNSPEC] = { .type = NLA_REJECT },
221− [ETHTOOL_A_COALESCE_HEADER] = { .type = NLA_NESTED },
193+const struct nla_policy ethnl_coalesce_set_policy[] = {
194+ [ETHTOOL_A_COALESCE_HEADER] =
195+ NLA_POLICY_NESTED(ethnl_header_policy),
222196 [ETHTOOL_A_COALESCE_RX_USECS] = { .type = NLA_U32 },
223197 [ETHTOOL_A_COALESCE_RX_MAX_FRAMES] = { .type = NLA_U32 },
224198 [ETHTOOL_A_COALESCE_RX_USECS_IRQ] = { .type = NLA_U32 },
@@ -245,9 +219,9 @@ coalesce_set_policy[ETHTOOL_A_COALESCE_MAX + 1] = { · 20 unmodified lines
245219
246220 int ethnl_set_coalesce(struct sk_buff *skb, struct genl_info *info)
247221 {
248− struct nlattr *tb[ETHTOOL_A_COALESCE_MAX + 1];
249222 struct ethtool_coalesce coalesce = {};
250223 struct ethnl_req_info req_info = {};
224+ struct nlattr **tb = info->attrs;
251225 const struct ethtool_ops *ops;
252226 struct net_device *dev;
253227 u32 supported_params;
@@ -255,11 +229,6 @@ int ethnl_set_coalesce(struct sk_buff *skb, struct genl_info *info) · 1 unmodified line
255229 int ret;
256230 u16 a;
257231
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;
263232 ret = ethnl_parse_header_dev_get(&req_info,
264233 tb[ETHTOOL_A_COALESCE_HEADER],
265234 genl_info_net(info), info->extack,
net/ethtool/debug.c+7−17
@@ -16,11 +16,9 @@ struct debug_reply_data { · 15 unmodified lines
1616 #define DEBUG_REPDATA(__reply_base) \
1717 container_of(__reply_base, struct debug_reply_data, base)
1818
19−static const struct nla_policy
20−debug_get_policy[ETHTOOL_A_DEBUG_MAX + 1] = {
21− [ETHTOOL_A_DEBUG_UNSPEC] = { .type = NLA_REJECT },
22− [ETHTOOL_A_DEBUG_HEADER] = { .type = NLA_NESTED },
23− [ETHTOOL_A_DEBUG_MSGMASK] = { .type = NLA_REJECT },
19+const struct nla_policy ethnl_debug_get_policy[] = {
20+ [ETHTOOL_A_DEBUG_HEADER] =
21+ NLA_POLICY_NESTED(ethnl_header_policy),
2422 };
2523
2624 static 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
6967 .request_cmd = ETHTOOL_MSG_DEBUG_GET,
7068 .reply_cmd = ETHTOOL_MSG_DEBUG_GET_REPLY,
7169 .hdr_attr = ETHTOOL_A_DEBUG_HEADER,
72− .max_attr = ETHTOOL_A_DEBUG_MAX,
7370 .req_info_size = sizeof(struct debug_req_info),
7471 .reply_data_size = sizeof(struct debug_reply_data),
75− .request_policy = debug_get_policy,
7672
7773 .prepare_data = debug_prepare_data,
7874 .reply_size = debug_reply_size,
@@ -81,27 +77,21 @@ const struct ethnl_request_ops ethnl_debug_request_ops = { · 2 unmodified lines
8177
8278 /* DEBUG_SET */
8379
84−static const struct nla_policy
85−debug_set_policy[ETHTOOL_A_DEBUG_MAX + 1] = {
86− [ETHTOOL_A_DEBUG_UNSPEC] = { .type = NLA_REJECT },
87− [ETHTOOL_A_DEBUG_HEADER] = { .type = NLA_NESTED },
80+const struct nla_policy ethnl_debug_set_policy[] = {
81+ [ETHTOOL_A_DEBUG_HEADER] =
82+ NLA_POLICY_NESTED(ethnl_header_policy),
8883 [ETHTOOL_A_DEBUG_MSGMASK] = { .type = NLA_NESTED },
8984 };
9085
9186 int ethnl_set_debug(struct sk_buff *skb, struct genl_info *info)
9287 {
93− struct nlattr *tb[ETHTOOL_A_DEBUG_MAX + 1];
9488 struct ethnl_req_info req_info = {};
89+ struct nlattr **tb = info->attrs;
9590 struct net_device *dev;
9691 bool mod = false;
9792 u32 msg_mask;
9893 int ret;
9994
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;
10595 ret = ethnl_parse_header_dev_get(&req_info,
10696 tb[ETHTOOL_A_DEBUG_HEADER],
10797 genl_info_net(info), info->extack,
net/ethtool/eee.c+8−24
@@ -19,16 +19,9 @@ struct eee_reply_data { · 18 unmodified lines
1919 #define EEE_REPDATA(__reply_base) \
2020 container_of(__reply_base, struct eee_reply_data, base)
2121
22−static const struct nla_policy
23−eee_get_policy[ETHTOOL_A_EEE_MAX + 1] = {
24− [ETHTOOL_A_EEE_UNSPEC] = { .type = NLA_REJECT },
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 },
22+const struct nla_policy ethnl_eee_get_policy[] = {
23+ [ETHTOOL_A_EEE_HEADER] =
24+ NLA_POLICY_NESTED(ethnl_header_policy),
3225 };
3326
3427 static 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
119112 .request_cmd = ETHTOOL_MSG_EEE_GET,
120113 .reply_cmd = ETHTOOL_MSG_EEE_GET_REPLY,
121114 .hdr_attr = ETHTOOL_A_EEE_HEADER,
122− .max_attr = ETHTOOL_A_EEE_MAX,
123115 .req_info_size = sizeof(struct eee_req_info),
124116 .reply_data_size = sizeof(struct eee_reply_data),
125− .request_policy = eee_get_policy,
126117
127118 .prepare_data = eee_prepare_data,
128119 .reply_size = eee_reply_size,
@@ -131,13 +122,10 @@ const struct ethnl_request_ops ethnl_eee_request_ops = { · 2 unmodified lines
131122
132123 /* EEE_SET */
133124
134−static const struct nla_policy
135−eee_set_policy[ETHTOOL_A_EEE_MAX + 1] = {
136− [ETHTOOL_A_EEE_UNSPEC] = { .type = NLA_REJECT },
137− [ETHTOOL_A_EEE_HEADER] = { .type = NLA_NESTED },
125+const struct nla_policy ethnl_eee_set_policy[] = {
126+ [ETHTOOL_A_EEE_HEADER] =
127+ NLA_POLICY_NESTED(ethnl_header_policy),
138128 [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 },
141129 [ETHTOOL_A_EEE_ENABLED] = { .type = NLA_U8 },
142130 [ETHTOOL_A_EEE_TX_LPI_ENABLED] = { .type = NLA_U8 },
143131 [ETHTOOL_A_EEE_TX_LPI_TIMER] = { .type = NLA_U32 },
@@ -145,18 +133,14 @@ eee_set_policy[ETHTOOL_A_EEE_MAX + 1] = { · 1 unmodified line
145133
146134 int ethnl_set_eee(struct sk_buff *skb, struct genl_info *info)
147135 {
148− struct nlattr *tb[ETHTOOL_A_EEE_MAX + 1];
149− struct ethtool_eee eee = {};
150136 struct ethnl_req_info req_info = {};
137+ struct nlattr **tb = info->attrs;
151138 const struct ethtool_ops *ops;
139+ struct ethtool_eee eee = {};
152140 struct net_device *dev;
153141 bool mod = false;
154142 int ret;
155143
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;
160144 ret = ethnl_parse_header_dev_get(&req_info,
161145 tb[ETHTOOL_A_EEE_HEADER],
162146 genl_info_net(info), info->extack,
net/ethtool/features.c+7−23
@@ -20,14 +20,9 @@ struct features_reply_data { · 19 unmodified lines
2020 #define FEATURES_REPDATA(__reply_base) \
2121 container_of(__reply_base, struct features_reply_data, base)
2222
23−static const struct nla_policy
24−features_get_policy[ETHTOOL_A_FEATURES_MAX + 1] = {
25− [ETHTOOL_A_FEATURES_UNSPEC] = { .type = NLA_REJECT },
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 },
23+const struct nla_policy ethnl_features_get_policy[] = {
24+ [ETHTOOL_A_FEATURES_HEADER] =
25+ NLA_POLICY_NESTED(ethnl_header_policy),
3126 };
3227
3328 static 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
120115 .request_cmd = ETHTOOL_MSG_FEATURES_GET,
121116 .reply_cmd = ETHTOOL_MSG_FEATURES_GET_REPLY,
122117 .hdr_attr = ETHTOOL_A_FEATURES_HEADER,
123− .max_attr = ETHTOOL_A_FEATURES_MAX,
124118 .req_info_size = sizeof(struct features_req_info),
125119 .reply_data_size = sizeof(struct features_reply_data),
126− .request_policy = features_get_policy,
127120
128121 .prepare_data = features_prepare_data,
129122 .reply_size = features_reply_size,
@@ -132,14 +125,10 @@ const struct ethnl_request_ops ethnl_features_request_ops = { · 2 unmodified lines
132125
133126 /* FEATURES_SET */
134127
135−static const struct nla_policy
136−features_set_policy[ETHTOOL_A_FEATURES_MAX + 1] = {
137− [ETHTOOL_A_FEATURES_UNSPEC] = { .type = NLA_REJECT },
138− [ETHTOOL_A_FEATURES_HEADER] = { .type = NLA_NESTED },
139− [ETHTOOL_A_FEATURES_HW] = { .type = NLA_REJECT },
128+const struct nla_policy ethnl_features_set_policy[] = {
129+ [ETHTOOL_A_FEATURES_HEADER] =
130+ NLA_POLICY_NESTED(ethnl_header_policy),
140131 [ETHTOOL_A_FEATURES_WANTED] = { .type = NLA_NESTED },
141− [ETHTOOL_A_FEATURES_ACTIVE] = { .type = NLA_REJECT },
142− [ETHTOOL_A_FEATURES_NOCHANGE] = { .type = NLA_REJECT },
143132 };
144133
145134 static 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
229218 DECLARE_BITMAP(new_wanted, NETDEV_FEATURE_COUNT);
230219 DECLARE_BITMAP(req_wanted, NETDEV_FEATURE_COUNT);
231220 DECLARE_BITMAP(req_mask, NETDEV_FEATURE_COUNT);
232− struct nlattr *tb[ETHTOOL_A_FEATURES_MAX + 1];
233221 struct ethnl_req_info req_info = {};
222+ struct nlattr **tb = info->attrs;
234223 struct net_device *dev;
235224 bool mod;
236225 int ret;
237226
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;
243227 if (!tb[ETHTOOL_A_FEATURES_WANTED])
244228 return -EINVAL;
245229 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
1616 #define LINKINFO_REPDATA(__reply_base) \
1717 container_of(__reply_base, struct linkinfo_reply_data, base)
1818
19−static const struct nla_policy
20−linkinfo_get_policy[ETHTOOL_A_LINKINFO_MAX + 1] = {
21− [ETHTOOL_A_LINKINFO_UNSPEC] = { .type = NLA_REJECT },
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 },
19+const struct nla_policy ethnl_linkinfo_get_policy[] = {
20+ [ETHTOOL_A_LINKINFO_HEADER] =
21+ NLA_POLICY_NESTED(ethnl_header_policy),
2822 };
2923
3024 static 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
8377 .request_cmd = ETHTOOL_MSG_LINKINFO_GET,
8478 .reply_cmd = ETHTOOL_MSG_LINKINFO_GET_REPLY,
8579 .hdr_attr = ETHTOOL_A_LINKINFO_HEADER,
86− .max_attr = ETHTOOL_A_LINKINFO_MAX,
8780 .req_info_size = sizeof(struct linkinfo_req_info),
8881 .reply_data_size = sizeof(struct linkinfo_reply_data),
89− .request_policy = linkinfo_get_policy,
9082
9183 .prepare_data = linkinfo_prepare_data,
9284 .reply_size = linkinfo_reply_size,
@@ -95,32 +87,24 @@ const struct ethnl_request_ops ethnl_linkinfo_request_ops = { · 2 unmodified lines
9587
9688 /* LINKINFO_SET */
9789
98−static const struct nla_policy
99−linkinfo_set_policy[ETHTOOL_A_LINKINFO_MAX + 1] = {
100− [ETHTOOL_A_LINKINFO_UNSPEC] = { .type = NLA_REJECT },
101− [ETHTOOL_A_LINKINFO_HEADER] = { .type = NLA_NESTED },
90+const struct nla_policy ethnl_linkinfo_set_policy[] = {
91+ [ETHTOOL_A_LINKINFO_HEADER] =
92+ NLA_POLICY_NESTED(ethnl_header_policy),
10293 [ETHTOOL_A_LINKINFO_PORT] = { .type = NLA_U8 },
10394 [ETHTOOL_A_LINKINFO_PHYADDR] = { .type = NLA_U8 },
104− [ETHTOOL_A_LINKINFO_TP_MDIX] = { .type = NLA_REJECT },
10595 [ETHTOOL_A_LINKINFO_TP_MDIX_CTRL] = { .type = NLA_U8 },
106− [ETHTOOL_A_LINKINFO_TRANSCEIVER] = { .type = NLA_REJECT },
10796 };
10897
10998 int ethnl_set_linkinfo(struct sk_buff *skb, struct genl_info *info)
11099 {
111− struct nlattr *tb[ETHTOOL_A_LINKINFO_MAX + 1];
112100 struct ethtool_link_ksettings ksettings = {};
113101 struct ethtool_link_settings *lsettings;
114102 struct ethnl_req_info req_info = {};
103+ struct nlattr **tb = info->attrs;
115104 struct net_device *dev;
116105 bool mod = false;
117106 int ret;
118107
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;
124108 ret = ethnl_parse_header_dev_get(&req_info,
125109 tb[ETHTOOL_A_LINKINFO_HEADER],
126110 genl_info_net(info), info->extack,
net/ethtool/linkmodes.c+7−25
@@ -18,17 +18,9 @@ struct linkmodes_reply_data { · 17 unmodified lines
1818 #define LINKMODES_REPDATA(__reply_base) \
1919 container_of(__reply_base, struct linkmodes_reply_data, base)
2020
21−static const struct nla_policy
22−linkmodes_get_policy[ETHTOOL_A_LINKMODES_MAX + 1] = {
23− [ETHTOOL_A_LINKMODES_UNSPEC] = { .type = NLA_REJECT },
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 },
21+const struct nla_policy ethnl_linkmodes_get_policy[] = {
22+ [ETHTOOL_A_LINKMODES_HEADER] =
23+ NLA_POLICY_NESTED(ethnl_header_policy),
3224 };
3325
3426 static 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
148140 .request_cmd = ETHTOOL_MSG_LINKMODES_GET,
149141 .reply_cmd = ETHTOOL_MSG_LINKMODES_GET_REPLY,
150142 .hdr_attr = ETHTOOL_A_LINKMODES_HEADER,
151− .max_attr = ETHTOOL_A_LINKMODES_MAX,
152143 .req_info_size = sizeof(struct linkmodes_req_info),
153144 .reply_data_size = sizeof(struct linkmodes_reply_data),
154− .request_policy = linkmodes_get_policy,
155145
156146 .prepare_data = linkmodes_prepare_data,
157147 .reply_size = linkmodes_reply_size,
@@ -276,17 +266,14 @@ static const struct link_mode_info link_mode_params[] = { · 118 unmodified lines
276266 __DEFINE_LINK_MODE_PARAMS(100, FX, Full),
277267 };
278268
279−static const struct nla_policy
280−linkmodes_set_policy[ETHTOOL_A_LINKMODES_MAX + 1] = {
281− [ETHTOOL_A_LINKMODES_UNSPEC] = { .type = NLA_REJECT },
282− [ETHTOOL_A_LINKMODES_HEADER] = { .type = NLA_NESTED },
269+const struct nla_policy ethnl_linkmodes_set_policy[] = {
270+ [ETHTOOL_A_LINKMODES_HEADER] =
271+ NLA_POLICY_NESTED(ethnl_header_policy),
283272 [ETHTOOL_A_LINKMODES_AUTONEG] = { .type = NLA_U8 },
284273 [ETHTOOL_A_LINKMODES_OURS] = { .type = NLA_NESTED },
285− [ETHTOOL_A_LINKMODES_PEER] = { .type = NLA_REJECT },
286274 [ETHTOOL_A_LINKMODES_SPEED] = { .type = NLA_U32 },
287275 [ETHTOOL_A_LINKMODES_DUPLEX] = { .type = NLA_U8 },
288276 [ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG] = { .type = NLA_U8 },
289− [ETHTOOL_A_LINKMODES_MASTER_SLAVE_STATE] = { .type = NLA_REJECT },
290277 };
291278
292279 /* 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
392379
393380 int ethnl_set_linkmodes(struct sk_buff *skb, struct genl_info *info)
394381 {
395− struct nlattr *tb[ETHTOOL_A_LINKMODES_MAX + 1];
396382 struct ethtool_link_ksettings ksettings = {};
397383 struct ethnl_req_info req_info = {};
384+ struct nlattr **tb = info->attrs;
398385 struct net_device *dev;
399386 bool mod = false;
400387 int ret;
401388
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;
407389 ret = ethnl_parse_header_dev_get(&req_info,
408390 tb[ETHTOOL_A_LINKMODES_HEADER],
409391 genl_info_net(info), info->extack,
net/ethtool/linkstate.c+3−11
@@ -20,15 +20,9 @@ struct linkstate_reply_data { · 19 unmodified lines
2020 #define LINKSTATE_REPDATA(__reply_base) \
2121 container_of(__reply_base, struct linkstate_reply_data, base)
2222
23−static const struct nla_policy
24−linkstate_get_policy[ETHTOOL_A_LINKSTATE_MAX + 1] = {
25− [ETHTOOL_A_LINKSTATE_UNSPEC] = { .type = NLA_REJECT },
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 },
23+const struct nla_policy ethnl_linkstate_get_policy[] = {
24+ [ETHTOOL_A_LINKSTATE_HEADER] =
25+ NLA_POLICY_NESTED(ethnl_header_policy),
3226 };
3327
3428 static int linkstate_get_sqi(struct net_device *dev)
@@ -179,10 +173,8 @@ const struct ethnl_request_ops ethnl_linkstate_request_ops = { · 144 unmodified lines
179173 .request_cmd = ETHTOOL_MSG_LINKSTATE_GET,
180174 .reply_cmd = ETHTOOL_MSG_LINKSTATE_GET_REPLY,
181175 .hdr_attr = ETHTOOL_A_LINKSTATE_HEADER,
182− .max_attr = ETHTOOL_A_LINKSTATE_MAX,
183176 .req_info_size = sizeof(struct linkstate_req_info),
184177 .reply_data_size = sizeof(struct linkstate_reply_data),
185− .request_policy = linkstate_get_policy,
186178
187179 .prepare_data = linkstate_prepare_data,
188180 .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
99 static bool ethnl_ok __read_mostly;
1010 static u32 ethnl_bcast_seq;
1111
12−static const struct nla_policy ethnl_header_policy[ETHTOOL_A_HEADER_MAX + 1] = {
13− [ETHTOOL_A_HEADER_UNSPEC] = { .type = NLA_REJECT },
12+#define ETHTOOL_FLAGS_BASIC (ETHTOOL_FLAG_COMPACT_BITSETS | \
13+ ETHTOOL_FLAG_OMIT_REPLY)
14+#define ETHTOOL_FLAGS_STATS (ETHTOOL_FLAGS_BASIC | ETHTOOL_FLAG_STATS)
15+
16+const struct nla_policy ethnl_header_policy[] = {
1417 [ETHTOOL_A_HEADER_DEV_INDEX] = { .type = NLA_U32 },
1518 [ETHTOOL_A_HEADER_DEV_NAME] = { .type = NLA_NUL_STRING,
1619 .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+
24+const 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),
1830 };
1931
2032 /**
@@ -37,7 +49,7 @@ int ethnl_parse_header_dev_get(struct ethnl_req_info *req_info, · 16 unmodified lines
3749 const struct nlattr *header, struct net *net,
3850 struct netlink_ext_ack *extack, bool require_dev)
3951 {
40− struct nlattr *tb[ETHTOOL_A_HEADER_MAX + 1];
52+ struct nlattr *tb[ARRAY_SIZE(ethnl_header_policy)];
4153 const struct nlattr *devname_attr;
4254 struct net_device *dev = NULL;
4355 u32 flags = 0;
@@ -47,19 +59,15 @@ int ethnl_parse_header_dev_get(struct ethnl_req_info *req_info, · 3 unmodified lines
4759 NL_SET_ERR_MSG(extack, "request header missing");
4860 return -EINVAL;
4961 }
50− ret = nla_parse_nested(tb, ETHTOOL_A_HEADER_MAX, header,
51− ethnl_header_policy, extack);
62+ /* No validation here, command policy should have a nested policy set
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);
5267 if (ret < 0)
5368 return ret;
54− if (tb[ETHTOOL_A_HEADER_FLAGS]) {
69+ if (tb[ETHTOOL_A_HEADER_FLAGS])
5570 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− }
6371
6472 devname_attr = tb[ETHTOOL_A_HEADER_DEV_NAME];
6573 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
247255 /**
248256 * ethnl_default_parse() - Parse request message
249257 * @req_info: pointer to structure to put data into
250− * @nlhdr: pointer to request message header
258+ * @tb: parsed attributes
251259 * @net: request netns
252260 * @request_ops: struct request_ops for request type
253261 * @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
259267 * Return: 0 on success or negative error code
260268 */
261269 static 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,
263271 const struct ethnl_request_ops *request_ops,
264272 struct netlink_ext_ack *extack, bool require_dev)
265273 {
266− struct nlattr **tb;
267274 int ret;
268275
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;
278276 ret = ethnl_parse_header_dev_get(req_info, tb[request_ops->hdr_attr],
279277 net, extack, require_dev);
280278 if (ret < 0)
281− goto out;
279+ return ret;
282280
283281 if (request_ops->parse_request) {
284282 ret = request_ops->parse_request(req_info, tb, extack);
285283 if (ret < 0)
286− goto out;
284+ return ret;
287285 }
288286
289− ret = 0;
290−out:
291− kfree(tb);
292− return ret;
287+ return 0;
293288 }
294289
295290 /**
@@ -334,8 +329,8 @@ static int ethnl_default_doit(struct sk_buff *skb, struct genl_info *info) · 38 unmodified lines
334329 return -ENOMEM;
335330 }
336331
337− ret = ethnl_default_parse(req_info, info->nlhdr, genl_info_net(info), ops,
338− info->extack, !ops->allow_nodev_do);
332+ ret = ethnl_default_parse(req_info, info->attrs, genl_info_net(info),
333+ ops, info->extack, !ops->allow_nodev_do);
339334 if (ret < 0)
340335 goto err_dev;
341336 ethnl_init_reply_data(reply_data, ops, req_info->dev);
@@ -480,6 +475,7 @@ out: · 138 unmodified lines
480475 /* generic ->start() handler for GET requests */
481476 static int ethnl_default_start(struct netlink_callback *cb)
482477 {
478+ const struct genl_dumpit_info *info = genl_dumpit_info(cb);
483479 struct ethnl_dump_ctx *ctx = ethnl_dump_context(cb);
484480 struct ethnl_reply_data *reply_data;
485481 const struct ethnl_request_ops *ops;
@@ -502,8 +498,8 @@ static int ethnl_default_start(struct netlink_callback *cb) · 16 unmodified lines
502498 goto free_req_info;
503499 }
504500
505− ret = ethnl_default_parse(req_info, cb->nlh, sock_net(cb->skb->sk), ops,
506− cb->extack, false);
501+ ret = ethnl_default_parse(req_info, info->attrs, sock_net(cb->skb->sk),
502+ ops, cb->extack, false);
507503 if (req_info->dev) {
508504 /* We ignore device specification in dump requests but as the
509505 * 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
696692 .start = ethnl_default_start,
697693 .dumpit = ethnl_default_dumpit,
698694 .done = ethnl_default_done,
695+ .policy = ethnl_strset_get_policy,
696+ .maxattr = ARRAY_SIZE(ethnl_strset_get_policy) - 1,
699697 },
700698 {
701699 .cmd = ETHTOOL_MSG_LINKINFO_GET,
@@ -703,11 +701,15 @@ static const struct genl_ops ethtool_genl_ops[] = { · 1 unmodified line
703701 .start = ethnl_default_start,
704702 .dumpit = ethnl_default_dumpit,
705703 .done = ethnl_default_done,
704+ .policy = ethnl_linkinfo_get_policy,
705+ .maxattr = ARRAY_SIZE(ethnl_linkinfo_get_policy) - 1,
706706 },
707707 {
708708 .cmd = ETHTOOL_MSG_LINKINFO_SET,
709709 .flags = GENL_UNS_ADMIN_PERM,
710710 .doit = ethnl_set_linkinfo,
711+ .policy = ethnl_linkinfo_set_policy,
712+ .maxattr = ARRAY_SIZE(ethnl_linkinfo_set_policy) - 1,
711713 },
712714 {
713715 .cmd = ETHTOOL_MSG_LINKMODES_GET,
@@ -715,11 +717,15 @@ static const struct genl_ops ethtool_genl_ops[] = { · 1 unmodified line
715717 .start = ethnl_default_start,
716718 .dumpit = ethnl_default_dumpit,
717719 .done = ethnl_default_done,
720+ .policy = ethnl_linkmodes_get_policy,
721+ .maxattr = ARRAY_SIZE(ethnl_linkmodes_get_policy) - 1,
718722 },
719723 {
720724 .cmd = ETHTOOL_MSG_LINKMODES_SET,
721725 .flags = GENL_UNS_ADMIN_PERM,
722726 .doit = ethnl_set_linkmodes,
727+ .policy = ethnl_linkmodes_set_policy,
728+ .maxattr = ARRAY_SIZE(ethnl_linkmodes_set_policy) - 1,
723729 },
724730 {
725731 .cmd = ETHTOOL_MSG_LINKSTATE_GET,
@@ -727,6 +733,8 @@ static const struct genl_ops ethtool_genl_ops[] = { · 1 unmodified line
727733 .start = ethnl_default_start,
728734 .dumpit = ethnl_default_dumpit,
729735 .done = ethnl_default_done,
736+ .policy = ethnl_linkstate_get_policy,
737+ .maxattr = ARRAY_SIZE(ethnl_linkstate_get_policy) - 1,
730738 },
731739 {
732740 .cmd = ETHTOOL_MSG_DEBUG_GET,
@@ -734,11 +742,15 @@ static const struct genl_ops ethtool_genl_ops[] = { · 1 unmodified line
734742 .start = ethnl_default_start,
735743 .dumpit = ethnl_default_dumpit,
736744 .done = ethnl_default_done,
745+ .policy = ethnl_debug_get_policy,
746+ .maxattr = ARRAY_SIZE(ethnl_debug_get_policy) - 1,
737747 },
738748 {
739749 .cmd = ETHTOOL_MSG_DEBUG_SET,
740750 .flags = GENL_UNS_ADMIN_PERM,
741751 .doit = ethnl_set_debug,
752+ .policy = ethnl_debug_set_policy,
753+ .maxattr = ARRAY_SIZE(ethnl_debug_set_policy) - 1,
742754 },
743755 {
744756 .cmd = ETHTOOL_MSG_WOL_GET,
@@ -747,11 +759,15 @@ static const struct genl_ops ethtool_genl_ops[] = { · 2 unmodified lines
747759 .start = ethnl_default_start,
748760 .dumpit = ethnl_default_dumpit,
749761 .done = ethnl_default_done,
762+ .policy = ethnl_wol_get_policy,
763+ .maxattr = ARRAY_SIZE(ethnl_wol_get_policy) - 1,
750764 },
751765 {
752766 .cmd = ETHTOOL_MSG_WOL_SET,
753767 .flags = GENL_UNS_ADMIN_PERM,
754768 .doit = ethnl_set_wol,
769+ .policy = ethnl_wol_set_policy,
770+ .maxattr = ARRAY_SIZE(ethnl_wol_set_policy) - 1,
755771 },
756772 {
757773 .cmd = ETHTOOL_MSG_FEATURES_GET,
@@ -759,11 +775,15 @@ static const struct genl_ops ethtool_genl_ops[] = { · 1 unmodified line
759775 .start = ethnl_default_start,
760776 .dumpit = ethnl_default_dumpit,
761777 .done = ethnl_default_done,
778+ .policy = ethnl_features_get_policy,
779+ .maxattr = ARRAY_SIZE(ethnl_features_get_policy) - 1,
762780 },
763781 {
764782 .cmd = ETHTOOL_MSG_FEATURES_SET,
765783 .flags = GENL_UNS_ADMIN_PERM,
766784 .doit = ethnl_set_features,
785+ .policy = ethnl_features_set_policy,
786+ .maxattr = ARRAY_SIZE(ethnl_features_set_policy) - 1,
767787 },
768788 {
769789 .cmd = ETHTOOL_MSG_PRIVFLAGS_GET,
@@ -771,11 +791,15 @@ static const struct genl_ops ethtool_genl_ops[] = { · 1 unmodified line
771791 .start = ethnl_default_start,
772792 .dumpit = ethnl_default_dumpit,
773793 .done = ethnl_default_done,
794+ .policy = ethnl_privflags_get_policy,
795+ .maxattr = ARRAY_SIZE(ethnl_privflags_get_policy) - 1,
774796 },
775797 {
776798 .cmd = ETHTOOL_MSG_PRIVFLAGS_SET,
777799 .flags = GENL_UNS_ADMIN_PERM,
778800 .doit = ethnl_set_privflags,
801+ .policy = ethnl_privflags_set_policy,
802+ .maxattr = ARRAY_SIZE(ethnl_privflags_set_policy) - 1,
779803 },
780804 {
781805 .cmd = ETHTOOL_MSG_RINGS_GET,
@@ -783,11 +807,15 @@ static const struct genl_ops ethtool_genl_ops[] = { · 1 unmodified line
783807 .start = ethnl_default_start,
784808 .dumpit = ethnl_default_dumpit,
785809 .done = ethnl_default_done,
810+ .policy = ethnl_rings_get_policy,
811+ .maxattr = ARRAY_SIZE(ethnl_rings_get_policy) - 1,
786812 },
787813 {
788814 .cmd = ETHTOOL_MSG_RINGS_SET,
789815 .flags = GENL_UNS_ADMIN_PERM,
790816 .doit = ethnl_set_rings,
817+ .policy = ethnl_rings_set_policy,
818+ .maxattr = ARRAY_SIZE(ethnl_rings_set_policy) - 1,
791819 },
792820 {
793821 .cmd = ETHTOOL_MSG_CHANNELS_GET,
@@ -795,11 +823,15 @@ static const struct genl_ops ethtool_genl_ops[] = { · 1 unmodified line
795823 .start = ethnl_default_start,
796824 .dumpit = ethnl_default_dumpit,
797825 .done = ethnl_default_done,
826+ .policy = ethnl_channels_get_policy,
827+ .maxattr = ARRAY_SIZE(ethnl_channels_get_policy) - 1,
798828 },
799829 {
800830 .cmd = ETHTOOL_MSG_CHANNELS_SET,
801831 .flags = GENL_UNS_ADMIN_PERM,
802832 .doit = ethnl_set_channels,
833+ .policy = ethnl_channels_get_policy,
834+ .maxattr = ARRAY_SIZE(ethnl_channels_get_policy) - 1,
803835 },
804836 {
805837 .cmd = ETHTOOL_MSG_COALESCE_GET,
@@ -807,11 +839,15 @@ static const struct genl_ops ethtool_genl_ops[] = { · 1 unmodified line
807839 .start = ethnl_default_start,
808840 .dumpit = ethnl_default_dumpit,
809841 .done = ethnl_default_done,
842+ .policy = ethnl_coalesce_get_policy,
843+ .maxattr = ARRAY_SIZE(ethnl_coalesce_get_policy) - 1,
810844 },
811845 {
812846 .cmd = ETHTOOL_MSG_COALESCE_SET,
813847 .flags = GENL_UNS_ADMIN_PERM,
814848 .doit = ethnl_set_coalesce,
849+ .policy = ethnl_coalesce_set_policy,
850+ .maxattr = ARRAY_SIZE(ethnl_coalesce_set_policy) - 1,
815851 },
816852 {
817853 .cmd = ETHTOOL_MSG_PAUSE_GET,
@@ -819,11 +855,15 @@ static const struct genl_ops ethtool_genl_ops[] = { · 1 unmodified line
819855 .start = ethnl_default_start,
820856 .dumpit = ethnl_default_dumpit,
821857 .done = ethnl_default_done,
858+ .policy = ethnl_pause_get_policy,
859+ .maxattr = ARRAY_SIZE(ethnl_pause_get_policy) - 1,
822860 },
823861 {
824862 .cmd = ETHTOOL_MSG_PAUSE_SET,
825863 .flags = GENL_UNS_ADMIN_PERM,
826864 .doit = ethnl_set_pause,
865+ .policy = ethnl_pause_set_policy,
866+ .maxattr = ARRAY_SIZE(ethnl_pause_set_policy) - 1,
827867 },
828868 {
829869 .cmd = ETHTOOL_MSG_EEE_GET,
@@ -831,11 +871,15 @@ static const struct genl_ops ethtool_genl_ops[] = { · 1 unmodified line
831871 .start = ethnl_default_start,
832872 .dumpit = ethnl_default_dumpit,
833873 .done = ethnl_default_done,
874+ .policy = ethnl_eee_get_policy,
875+ .maxattr = ARRAY_SIZE(ethnl_eee_get_policy) - 1,
834876 },
835877 {
836878 .cmd = ETHTOOL_MSG_EEE_SET,
837879 .flags = GENL_UNS_ADMIN_PERM,
838880 .doit = ethnl_set_eee,
881+ .policy = ethnl_eee_set_policy,
882+ .maxattr = ARRAY_SIZE(ethnl_eee_set_policy) - 1,
839883 },
840884 {
841885 .cmd = ETHTOOL_MSG_TSINFO_GET,
@@ -843,22 +887,30 @@ static const struct genl_ops ethtool_genl_ops[] = { · 1 unmodified line
843887 .start = ethnl_default_start,
844888 .dumpit = ethnl_default_dumpit,
845889 .done = ethnl_default_done,
890+ .policy = ethnl_tsinfo_get_policy,
891+ .maxattr = ARRAY_SIZE(ethnl_tsinfo_get_policy) - 1,
846892 },
847893 {
848894 .cmd = ETHTOOL_MSG_CABLE_TEST_ACT,
849895 .flags = GENL_UNS_ADMIN_PERM,
850896 .doit = ethnl_act_cable_test,
897+ .policy = ethnl_cable_test_act_policy,
898+ .maxattr = ARRAY_SIZE(ethnl_cable_test_act_policy) - 1,
851899 },
852900 {
853901 .cmd = ETHTOOL_MSG_CABLE_TEST_TDR_ACT,
854902 .flags = GENL_UNS_ADMIN_PERM,
855903 .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,
856906 },
857907 {
858908 .cmd = ETHTOOL_MSG_TUNNEL_INFO_GET,
859909 .doit = ethnl_tunnel_info_doit,
860910 .start = ethnl_tunnel_info_start,
861911 .dumpit = ethnl_tunnel_info_dumpit,
912+ .policy = ethnl_tunnel_info_get_policy,
913+ .maxattr = ARRAY_SIZE(ethnl_tunnel_info_get_policy) - 1,
862914 },
863915 };
864916
net/ethtool/netlink.h+31−4
@@ -266,10 +266,8 @@ static inline void ethnl_ops_complete(struct net_device *dev) · 265 unmodified lines
266266 * @request_cmd: command id for request (GET)
267267 * @reply_cmd: command id for reply (GET_REPLY)
268268 * @hdr_attr: attribute type for request header
269− * @max_attr: maximum (top level) attribute type
270269 * @req_info_size: size of request info
271270 * @reply_data_size: size of reply data
272− * @request_policy: netlink policy for message contents
273271 * @allow_nodev_do: allow non-dump request with no device identification
274272 * @parse_request:
275273 * Parse request except common header (struct ethnl_req_info). Common
@@ -312,10 +310,8 @@ struct ethnl_request_ops { · 36 unmodified lines
312310 u8 request_cmd;
313311 u8 reply_cmd;
314312 u16 hdr_attr;
315− unsigned int max_attr;
316313 unsigned int req_info_size;
317314 unsigned int reply_data_size;
318− const struct nla_policy *request_policy;
319315 bool allow_nodev_do;
320316
321317 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
349345 extern const struct ethnl_request_ops ethnl_eee_request_ops;
350346 extern const struct ethnl_request_ops ethnl_tsinfo_request_ops;
351347
348+extern const struct nla_policy ethnl_header_policy[ETHTOOL_A_HEADER_FLAGS + 1];
349+extern const struct nla_policy ethnl_header_policy_stats[ETHTOOL_A_HEADER_FLAGS + 1];
350+extern const struct nla_policy ethnl_strset_get_policy[ETHTOOL_A_STRSET_STRINGSETS + 1];
351+extern const struct nla_policy ethnl_linkinfo_get_policy[ETHTOOL_A_LINKINFO_HEADER + 1];
352+extern const struct nla_policy ethnl_linkinfo_set_policy[ETHTOOL_A_LINKINFO_TP_MDIX_CTRL + 1];
353+extern const struct nla_policy ethnl_linkmodes_get_policy[ETHTOOL_A_LINKMODES_HEADER + 1];
354+extern const struct nla_policy ethnl_linkmodes_set_policy[ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG + 1];
355+extern const struct nla_policy ethnl_linkstate_get_policy[ETHTOOL_A_LINKSTATE_HEADER + 1];
356+extern const struct nla_policy ethnl_debug_get_policy[ETHTOOL_A_DEBUG_HEADER + 1];
357+extern const struct nla_policy ethnl_debug_set_policy[ETHTOOL_A_DEBUG_MSGMASK + 1];
358+extern const struct nla_policy ethnl_wol_get_policy[ETHTOOL_A_WOL_HEADER + 1];
359+extern const struct nla_policy ethnl_wol_set_policy[ETHTOOL_A_WOL_SOPASS + 1];
360+extern const struct nla_policy ethnl_features_get_policy[ETHTOOL_A_FEATURES_HEADER + 1];
361+extern const struct nla_policy ethnl_features_set_policy[ETHTOOL_A_FEATURES_WANTED + 1];
362+extern const struct nla_policy ethnl_privflags_get_policy[ETHTOOL_A_PRIVFLAGS_HEADER + 1];
363+extern const struct nla_policy ethnl_privflags_set_policy[ETHTOOL_A_PRIVFLAGS_FLAGS + 1];
364+extern const struct nla_policy ethnl_rings_get_policy[ETHTOOL_A_RINGS_HEADER + 1];
365+extern const struct nla_policy ethnl_rings_set_policy[ETHTOOL_A_RINGS_TX + 1];
366+extern const struct nla_policy ethnl_channels_get_policy[ETHTOOL_A_CHANNELS_HEADER + 1];
367+extern const struct nla_policy ethnl_channels_set_policy[ETHTOOL_A_CHANNELS_COMBINED_COUNT + 1];
368+extern const struct nla_policy ethnl_coalesce_get_policy[ETHTOOL_A_COALESCE_HEADER + 1];
369+extern const struct nla_policy ethnl_coalesce_set_policy[ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL + 1];
370+extern const struct nla_policy ethnl_pause_get_policy[ETHTOOL_A_PAUSE_HEADER + 1];
371+extern const struct nla_policy ethnl_pause_set_policy[ETHTOOL_A_PAUSE_TX + 1];
372+extern const struct nla_policy ethnl_eee_get_policy[ETHTOOL_A_EEE_HEADER + 1];
373+extern const struct nla_policy ethnl_eee_set_policy[ETHTOOL_A_EEE_TX_LPI_TIMER + 1];
374+extern const struct nla_policy ethnl_tsinfo_get_policy[ETHTOOL_A_TSINFO_HEADER + 1];
375+extern const struct nla_policy ethnl_cable_test_act_policy[ETHTOOL_A_CABLE_TEST_HEADER + 1];
376+extern const struct nla_policy ethnl_cable_test_tdr_act_policy[ETHTOOL_A_CABLE_TEST_TDR_CFG + 1];
377+extern const struct nla_policy ethnl_tunnel_info_get_policy[ETHTOOL_A_TUNNEL_INFO_HEADER + 1];
378+
352379 int ethnl_set_linkinfo(struct sk_buff *skb, struct genl_info *info);
353380 int ethnl_set_linkmodes(struct sk_buff *skb, struct genl_info *info);
354381 int 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
1616 #define PAUSE_REPDATA(__reply_base) \
1717 container_of(__reply_base, struct pause_reply_data, base)
1818
19−static const struct nla_policy
20−pause_get_policy[ETHTOOL_A_PAUSE_MAX + 1] = {
21− [ETHTOOL_A_PAUSE_UNSPEC] = { .type = NLA_REJECT },
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 },
19+const struct nla_policy ethnl_pause_get_policy[] = {
20+ [ETHTOOL_A_PAUSE_HEADER] =
21+ NLA_POLICY_NESTED(ethnl_header_policy_stats),
2722 };
2823
2924 static 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
130125 .request_cmd = ETHTOOL_MSG_PAUSE_GET,
131126 .reply_cmd = ETHTOOL_MSG_PAUSE_GET_REPLY,
132127 .hdr_attr = ETHTOOL_A_PAUSE_HEADER,
133− .max_attr = ETHTOOL_A_PAUSE_MAX,
134128 .req_info_size = sizeof(struct pause_req_info),
135129 .reply_data_size = sizeof(struct pause_reply_data),
136− .request_policy = pause_get_policy,
137130
138131 .prepare_data = pause_prepare_data,
139132 .reply_size = pause_reply_size,
@@ -142,30 +135,24 @@ const struct ethnl_request_ops ethnl_pause_request_ops = { · 2 unmodified lines
142135
143136 /* PAUSE_SET */
144137
145−static const struct nla_policy
146−pause_set_policy[ETHTOOL_A_PAUSE_MAX + 1] = {
147− [ETHTOOL_A_PAUSE_UNSPEC] = { .type = NLA_REJECT },
148− [ETHTOOL_A_PAUSE_HEADER] = { .type = NLA_NESTED },
138+const struct nla_policy ethnl_pause_set_policy[] = {
139+ [ETHTOOL_A_PAUSE_HEADER] =
140+ NLA_POLICY_NESTED(ethnl_header_policy),
149141 [ETHTOOL_A_PAUSE_AUTONEG] = { .type = NLA_U8 },
150142 [ETHTOOL_A_PAUSE_RX] = { .type = NLA_U8 },
151143 [ETHTOOL_A_PAUSE_TX] = { .type = NLA_U8 },
152− [ETHTOOL_A_PAUSE_STATS] = { .type = NLA_REJECT },
153144 };
154145
155146 int ethnl_set_pause(struct sk_buff *skb, struct genl_info *info)
156147 {
157− struct nlattr *tb[ETHTOOL_A_PAUSE_MAX + 1];
158148 struct ethtool_pauseparam params = {};
159149 struct ethnl_req_info req_info = {};
150+ struct nlattr **tb = info->attrs;
160151 const struct ethtool_ops *ops;
161152 struct net_device *dev;
162153 bool mod = false;
163154 int ret;
164155
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;
169156 ret = ethnl_parse_header_dev_get(&req_info,
170157 tb[ETHTOOL_A_PAUSE_HEADER],
171158 genl_info_net(info), info->extack,
net/ethtool/privflags.c+7−17
@@ -18,11 +18,9 @@ struct privflags_reply_data { · 17 unmodified lines
1818 #define PRIVFLAGS_REPDATA(__reply_base) \
1919 container_of(__reply_base, struct privflags_reply_data, base)
2020
21−static const struct nla_policy
22−privflags_get_policy[ETHTOOL_A_PRIVFLAGS_MAX + 1] = {
23− [ETHTOOL_A_PRIVFLAGS_UNSPEC] = { .type = NLA_REJECT },
24− [ETHTOOL_A_PRIVFLAGS_HEADER] = { .type = NLA_NESTED },
25− [ETHTOOL_A_PRIVFLAGS_FLAGS] = { .type = NLA_REJECT },
21+const struct nla_policy ethnl_privflags_get_policy[] = {
22+ [ETHTOOL_A_PRIVFLAGS_HEADER] =
23+ NLA_POLICY_NESTED(ethnl_header_policy),
2624 };
2725
2826 static 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
124122 .request_cmd = ETHTOOL_MSG_PRIVFLAGS_GET,
125123 .reply_cmd = ETHTOOL_MSG_PRIVFLAGS_GET_REPLY,
126124 .hdr_attr = ETHTOOL_A_PRIVFLAGS_HEADER,
127− .max_attr = ETHTOOL_A_PRIVFLAGS_MAX,
128125 .req_info_size = sizeof(struct privflags_req_info),
129126 .reply_data_size = sizeof(struct privflags_reply_data),
130− .request_policy = privflags_get_policy,
131127
132128 .prepare_data = privflags_prepare_data,
133129 .reply_size = privflags_reply_size,
@@ -137,18 +133,17 @@ const struct ethnl_request_ops ethnl_privflags_request_ops = { · 3 unmodified lines
137133
138134 /* PRIVFLAGS_SET */
139135
140−static const struct nla_policy
141−privflags_set_policy[ETHTOOL_A_PRIVFLAGS_MAX + 1] = {
142− [ETHTOOL_A_PRIVFLAGS_UNSPEC] = { .type = NLA_REJECT },
143− [ETHTOOL_A_PRIVFLAGS_HEADER] = { .type = NLA_NESTED },
136+const struct nla_policy ethnl_privflags_set_policy[] = {
137+ [ETHTOOL_A_PRIVFLAGS_HEADER] =
138+ NLA_POLICY_NESTED(ethnl_header_policy),
144139 [ETHTOOL_A_PRIVFLAGS_FLAGS] = { .type = NLA_NESTED },
145140 };
146141
147142 int ethnl_set_privflags(struct sk_buff *skb, struct genl_info *info)
148143 {
149− struct nlattr *tb[ETHTOOL_A_PRIVFLAGS_MAX + 1];
150144 const char (*names)[ETH_GSTRING_LEN] = NULL;
151145 struct ethnl_req_info req_info = {};
146+ struct nlattr **tb = info->attrs;
152147 const struct ethtool_ops *ops;
153148 struct net_device *dev;
154149 unsigned int nflags;
@@ -157,11 +152,6 @@ int ethnl_set_privflags(struct sk_buff *skb, struct genl_info *info) · 2 unmodified lines
157152 u32 flags;
158153 int ret;
159154
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;
165155 if (!tb[ETHTOOL_A_PRIVFLAGS_FLAGS])
166156 return -EINVAL;
167157 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
1515 #define RINGS_REPDATA(__reply_base) \
1616 container_of(__reply_base, struct rings_reply_data, base)
1717
18−static const struct nla_policy
19−rings_get_policy[ETHTOOL_A_RINGS_MAX + 1] = {
20− [ETHTOOL_A_RINGS_UNSPEC] = { .type = NLA_REJECT },
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 },
18+const struct nla_policy ethnl_rings_get_policy[] = {
19+ [ETHTOOL_A_RINGS_HEADER] =
20+ NLA_POLICY_NESTED(ethnl_header_policy),
3021 };
3122
3223 static 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
9788 .request_cmd = ETHTOOL_MSG_RINGS_GET,
9889 .reply_cmd = ETHTOOL_MSG_RINGS_GET_REPLY,
9990 .hdr_attr = ETHTOOL_A_RINGS_HEADER,
100− .max_attr = ETHTOOL_A_RINGS_MAX,
10191 .req_info_size = sizeof(struct rings_req_info),
10292 .reply_data_size = sizeof(struct rings_reply_data),
103− .request_policy = rings_get_policy,
10493
10594 .prepare_data = rings_prepare_data,
10695 .reply_size = rings_reply_size,
@@ -109,14 +98,9 @@ const struct ethnl_request_ops ethnl_rings_request_ops = { · 2 unmodified lines
10998
11099 /* RINGS_SET */
111100
112−static const struct nla_policy
113−rings_set_policy[ETHTOOL_A_RINGS_MAX + 1] = {
114− [ETHTOOL_A_RINGS_UNSPEC] = { .type = NLA_REJECT },
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 },
101+const struct nla_policy ethnl_rings_set_policy[] = {
102+ [ETHTOOL_A_RINGS_HEADER] =
103+ NLA_POLICY_NESTED(ethnl_header_policy),
120104 [ETHTOOL_A_RINGS_RX] = { .type = NLA_U32 },
121105 [ETHTOOL_A_RINGS_RX_MINI] = { .type = NLA_U32 },
122106 [ETHTOOL_A_RINGS_RX_JUMBO] = { .type = NLA_U32 },
@@ -125,20 +109,15 @@ rings_set_policy[ETHTOOL_A_RINGS_MAX + 1] = { · 2 unmodified lines
125109
126110 int ethnl_set_rings(struct sk_buff *skb, struct genl_info *info)
127111 {
128− struct nlattr *tb[ETHTOOL_A_RINGS_MAX + 1];
129112 struct ethtool_ringparam ringparam = {};
130113 struct ethnl_req_info req_info = {};
114+ struct nlattr **tb = info->attrs;
131115 const struct nlattr *err_attr;
132116 const struct ethtool_ops *ops;
133117 struct net_device *dev;
134118 bool mod = false;
135119 int ret;
136120
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;
142121 ret = ethnl_parse_header_dev_get(&req_info,
143122 tb[ETHTOOL_A_RINGS_HEADER],
144123 genl_info_net(info), info->extack,
net/ethtool/strset.c+9−16
@@ -99,18 +99,14 @@ struct strset_reply_data { · 98 unmodified lines
9999 #define STRSET_REPDATA(__reply_base) \
100100 container_of(__reply_base, struct strset_reply_data, base)
101101
102−static const struct nla_policy strset_get_policy[ETHTOOL_A_STRSET_MAX + 1] = {
103− [ETHTOOL_A_STRSET_UNSPEC] = { .type = NLA_REJECT },
104− [ETHTOOL_A_STRSET_HEADER] = { .type = NLA_NESTED },
102+const struct nla_policy ethnl_strset_get_policy[] = {
103+ [ETHTOOL_A_STRSET_HEADER] =
104+ NLA_POLICY_NESTED(ethnl_header_policy),
105105 [ETHTOOL_A_STRSET_STRINGSETS] = { .type = NLA_NESTED },
106106 };
107107
108−static const struct nla_policy
109−get_stringset_policy[ETHTOOL_A_STRINGSET_MAX + 1] = {
110− [ETHTOOL_A_STRINGSET_UNSPEC] = { .type = NLA_REJECT },
108+static const struct nla_policy get_stringset_policy[] = {
111109 [ETHTOOL_A_STRINGSET_ID] = { .type = NLA_U32 },
112− [ETHTOOL_A_STRINGSET_COUNT] = { .type = NLA_REJECT },
113− [ETHTOOL_A_STRINGSET_STRINGS] = { .type = NLA_REJECT },
114110 };
115111
116112 /**
@@ -138,10 +134,10 @@ static bool strset_include(const struct strset_req_info *info, · 21 unmodified lines
138134 static int strset_get_id(const struct nlattr *nest, u32 *val,
139135 struct netlink_ext_ack *extack)
140136 {
141− struct nlattr *tb[ETHTOOL_A_STRINGSET_MAX + 1];
137+ struct nlattr *tb[ARRAY_SIZE(get_stringset_policy)];
142138 int ret;
143139
144− ret = nla_parse_nested(tb, ETHTOOL_A_STRINGSET_MAX, nest,
140+ ret = nla_parse_nested(tb, ARRAY_SIZE(get_stringset_policy) - 1, nest,
145141 get_stringset_policy, extack);
146142 if (ret < 0)
147143 return ret;
@@ -152,9 +148,7 @@ static int strset_get_id(const struct nlattr *nest, u32 *val, · 4 unmodified lines
152148 return 0;
153149 }
154150
155−static const struct nla_policy
156−strset_stringsets_policy[ETHTOOL_A_STRINGSETS_MAX + 1] = {
157− [ETHTOOL_A_STRINGSETS_UNSPEC] = { .type = NLA_REJECT },
151+static const struct nla_policy strset_stringsets_policy[] = {
158152 [ETHTOOL_A_STRINGSETS_STRINGSET] = { .type = NLA_NESTED },
159153 };
160154
@@ -169,7 +163,8 @@ static int strset_parse_request(struct ethnl_req_info *req_base, · 8 unmodified lines
169163
170164 if (!nest)
171165 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,
173168 strset_stringsets_policy, extack);
174169 if (ret < 0)
175170 return ret;
@@ -445,10 +440,8 @@ const struct ethnl_request_ops ethnl_strset_request_ops = { · 269 unmodified lines
445440 .request_cmd = ETHTOOL_MSG_STRSET_GET,
446441 .reply_cmd = ETHTOOL_MSG_STRSET_GET_REPLY,
447442 .hdr_attr = ETHTOOL_A_STRSET_HEADER,
448− .max_attr = ETHTOOL_A_STRSET_MAX,
449443 .req_info_size = sizeof(struct strset_req_info),
450444 .reply_data_size = sizeof(struct strset_reply_data),
451− .request_policy = strset_get_policy,
452445 .allow_nodev_do = true,
453446
454447 .parse_request = strset_parse_request,
net/ethtool/tsinfo.c+3−10
@@ -18,14 +18,9 @@ struct tsinfo_reply_data { · 17 unmodified lines
1818 #define TSINFO_REPDATA(__reply_base) \
1919 container_of(__reply_base, struct tsinfo_reply_data, base)
2020
21−static const struct nla_policy
22−tsinfo_get_policy[ETHTOOL_A_TSINFO_MAX + 1] = {
23− [ETHTOOL_A_TSINFO_UNSPEC] = { .type = NLA_REJECT },
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 },
21+const struct nla_policy ethnl_tsinfo_get_policy[] = {
22+ [ETHTOOL_A_TSINFO_HEADER] =
23+ NLA_POLICY_NESTED(ethnl_header_policy),
2924 };
3025
3126 static 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
132127 .request_cmd = ETHTOOL_MSG_TSINFO_GET,
133128 .reply_cmd = ETHTOOL_MSG_TSINFO_GET_REPLY,
134129 .hdr_attr = ETHTOOL_A_TSINFO_HEADER,
135− .max_attr = ETHTOOL_A_TSINFO_MAX,
136130 .req_info_size = sizeof(struct tsinfo_req_info),
137131 .reply_data_size = sizeof(struct tsinfo_reply_data),
138− .request_policy = tsinfo_get_policy,
139132
140133 .prepare_data = tsinfo_prepare_data,
141134 .reply_size = tsinfo_reply_size,
net/ethtool/tunnels.c+14−28
@@ -8,10 +8,9 @@ · 7 unmodified lines
88 #include "common.h"
99 #include "netlink.h"
1010
11−static const struct nla_policy
12−ethtool_tunnel_info_policy[ETHTOOL_A_TUNNEL_INFO_MAX + 1] = {
13− [ETHTOOL_A_TUNNEL_INFO_UNSPEC] = { .type = NLA_REJECT },
14− [ETHTOOL_A_TUNNEL_INFO_HEADER] = { .type = NLA_NESTED },
11+const struct nla_policy ethnl_tunnel_info_get_policy[] = {
12+ [ETHTOOL_A_TUNNEL_INFO_HEADER] =
13+ NLA_POLICY_NESTED(ethnl_header_policy),
1514 };
1615
1716 static_assert(ETHTOOL_UDP_TUNNEL_TYPE_VXLAN == ilog2(UDP_TUNNEL_TYPE_VXLAN));
@@ -161,35 +160,19 @@ err_cancel_ports: · 143 unmodified lines
161160 return -EMSGSIZE;
162161 }
163162
164−static int
165−ethnl_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−
182163 int ethnl_tunnel_info_doit(struct sk_buff *skb, struct genl_info *info)
183164 {
184165 struct ethnl_req_info req_info = {};
166+ struct nlattr **tb = info->attrs;
185167 struct sk_buff *rskb;
186168 void *reply_payload;
187169 int reply_len;
188170 int ret;
189171
190− ret = ethnl_tunnel_info_req_parse(&req_info, info->nlhdr,
191− genl_info_net(info), info->extack,
192− true);
172+ ret = ethnl_parse_header_dev_get(&req_info,
173+ tb[ETHTOOL_A_TUNNEL_INFO_HEADER],
174+ genl_info_net(info), info->extack,
175+ true);
193176 if (ret < 0)
194177 return ret;
195178
@@ -233,16 +216,19 @@ struct ethnl_tunnel_info_dump_ctx { · 37 unmodified lines
233216
234217 int ethnl_tunnel_info_start(struct netlink_callback *cb)
235218 {
219+ const struct genl_dumpit_info *info = genl_dumpit_info(cb);
236220 struct ethnl_tunnel_info_dump_ctx *ctx = (void *)cb->ctx;
221+ struct nlattr **tb = info->attrs;
237222 int ret;
238223
239224 BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx));
240225
241226 memset(ctx, 0, sizeof(*ctx));
242227
243− ret = ethnl_tunnel_info_req_parse(&ctx->req_info, cb->nlh,
244− sock_net(cb->skb->sk), cb->extack,
245− false);
228+ ret = ethnl_parse_header_dev_get(&ctx->req_info,
229+ tb[ETHTOOL_A_TUNNEL_INFO_HEADER],
230+ sock_net(cb->skb->sk), cb->extack,
231+ false);
246232 if (ctx->req_info.dev) {
247233 dev_put(ctx->req_info.dev);
248234 ctx->req_info.dev = NULL;
net/ethtool/wol.c+7−17
@@ -17,12 +17,9 @@ struct wol_reply_data { · 16 unmodified lines
1717 #define WOL_REPDATA(__reply_base) \
1818 container_of(__reply_base, struct wol_reply_data, base)
1919
20−static const struct nla_policy
21−wol_get_policy[ETHTOOL_A_WOL_MAX + 1] = {
22− [ETHTOOL_A_WOL_UNSPEC] = { .type = NLA_REJECT },
23− [ETHTOOL_A_WOL_HEADER] = { .type = NLA_NESTED },
24− [ETHTOOL_A_WOL_MODES] = { .type = NLA_REJECT },
25− [ETHTOOL_A_WOL_SOPASS] = { .type = NLA_REJECT },
20+const struct nla_policy ethnl_wol_get_policy[] = {
21+ [ETHTOOL_A_WOL_HEADER] =
22+ NLA_POLICY_NESTED(ethnl_header_policy),
2623 };
2724
2825 static 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
8986 .request_cmd = ETHTOOL_MSG_WOL_GET,
9087 .reply_cmd = ETHTOOL_MSG_WOL_GET_REPLY,
9188 .hdr_attr = ETHTOOL_A_WOL_HEADER,
92− .max_attr = ETHTOOL_A_WOL_MAX,
9389 .req_info_size = sizeof(struct wol_req_info),
9490 .reply_data_size = sizeof(struct wol_reply_data),
95− .request_policy = wol_get_policy,
9691
9792 .prepare_data = wol_prepare_data,
9893 .reply_size = wol_reply_size,
@@ -101,10 +96,9 @@ const struct ethnl_request_ops ethnl_wol_request_ops = { · 2 unmodified lines
10196
10297 /* WOL_SET */
10398
104−static const struct nla_policy
105−wol_set_policy[ETHTOOL_A_WOL_MAX + 1] = {
106− [ETHTOOL_A_WOL_UNSPEC] = { .type = NLA_REJECT },
107− [ETHTOOL_A_WOL_HEADER] = { .type = NLA_NESTED },
99+const struct nla_policy ethnl_wol_set_policy[] = {
100+ [ETHTOOL_A_WOL_HEADER] =
101+ NLA_POLICY_NESTED(ethnl_header_policy),
108102 [ETHTOOL_A_WOL_MODES] = { .type = NLA_NESTED },
109103 [ETHTOOL_A_WOL_SOPASS] = { .type = NLA_BINARY,
110104 .len = SOPASS_MAX },
@@ -113,16 +107,12 @@ wol_set_policy[ETHTOOL_A_WOL_MAX + 1] = { · 2 unmodified lines
113107 int ethnl_set_wol(struct sk_buff *skb, struct genl_info *info)
114108 {
115109 struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL };
116− struct nlattr *tb[ETHTOOL_A_WOL_MAX + 1];
117110 struct ethnl_req_info req_info = {};
111+ struct nlattr **tb = info->attrs;
118112 struct net_device *dev;
119113 bool mod = false;
120114 int ret;
121115
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;
126116 ret = ethnl_parse_header_dev_get(&req_info, tb[ETHTOOL_A_WOL_HEADER],
127117 genl_info_net(info), info->extack,
128118 true);
net/netlink/policy.c+8−0
@@ -263,6 +263,14 @@ send_attribute: · 262 unmodified lines
263263 else
264264 type = NL_ATTR_TYPE_U64;
265265
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+
266274 nla_get_range_unsigned(pt, &range);
267275
268276 if (nla_put_u64_64bit(skb, NL_POLICY_TYPE_ATTR_MIN_VALUE_U,