- update to new upstream release 5.7

OBS-URL: https://build.opensuse.org/package/show/network:utilities/ethtool?expand=0&rev=97
This commit is contained in:
Michal Kubeček 2020-06-07 20:15:53 +00:00 committed by Git OBS Bridge
parent c03953a30f
commit 7fbfad3245
12 changed files with 71 additions and 799 deletions

View File

@ -1,16 +0,0 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCAAdFiEEzkpNCA8NME8juevdly1b9NxhOAYFAl66uwEACgkQly1b9Nxh
OAawuxAAiwkGrEX++L/hoNYXYRpz1+h2DQsO0tBDQuqCrCkuL+tIH9M3D5aVzesL
a3TopQTutuWcvTQ49wye6k0jF4rncE8s24WcCQYxi2Y9HNtEWjqigXkwP/GoLSCF
oO73p7gM3IGKpK9Cz5RAh3xbgtPrvBq7fmP93+f0mTiXiaUiw9WEq90XV8buLbP4
JXcClnitFh5D8Cbv5s+vfvWEHWSjFUISaQBMdl5SKbZQT3nfzZR0AKiZPtt9QI4G
LqSIP18Ou/hBdstET2M0mdBEiM2oICnQ0cmjZIupBtYEAk3XwnebP3a5d4eNl0mL
Nlscw0gwDefAr7X9rrtQurFWaTjMHDDZ2LDEtFm6pYE9kxO6GGGGd5W2KziDHvLC
/2JfrQI+f6Z7ackPb3nfAYNvhaIQatBMK27371PwQYZ8e3ii0Sgi/t1jxvS+xejZ
TSXptwQoF2x2urfnwuowsHWWwzJEmqDYm1u662LfuJVYh4+3G587XRRte4bK+xaI
LClwO7zGh0al1RDxD4LaE7LZ6L5XqS2brFvWeoTKMhL2u6HhmZQgAlnIjPzImlz3
egdAd+9mj3Vx/4KYYa4VUVMSUqm5C/99a7AUbSSJKRs6u1uqpjXUTodx0fhzqA7G
8Ub1Lh8yTXOI3PbUPspnmJTzc9p21inktLAU6oKsobFN9iV+aPI=
=cWjJ
-----END PGP SIGNATURE-----

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ca0f1b526dad5153f0aa0f1eb3c17c31770c75a74f70af622b1a83ae38043995
size 281084

16
ethtool-5.7.tar.sign Normal file
View File

@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCAAdFiEEzkpNCA8NME8juevdly1b9NxhOAYFAl7ZOvwACgkQly1b9Nxh
OAaFyQ//cSW86pi2Ii06dK83dA+dsvHCApoUcxOS1UNuXfdUoOxQQzxgR7uU0i98
SbZJvSTSGxR3h1wsqNFrTxtYw9xbFLC3u+8otUJbbqatbVaT8DlB84v4UklcBsCE
if1CuYzCJEBUjCKneXL/WAET03uxV0RkKEgjcrXRma0JTYB0+5JW//7W2cKLFn2B
iCEWU65G9hR73nafUQJ1vypgTz5e1eMHl9FfXJNjqScHeAwJq9aGUePal8Mkfr80
ttb0yV48uw13j46Zj+w/QrurQPLNHAhUme2mHIwIly510rX6UZlylMBaTy0WDvGR
zg394CmyR9XvddIkTS+lQHBrAUdhA4xtEpUasTq4dWp6I/Q8xIg1S04TDLNeoznr
PTYLuGJAx+fuB6SaGSIAeClG++OEQzLeJQxrI9v3H3iLzqJpPZzchWWVC8QoTt8m
vQraqxXtUkqrosIinAL1kIjj508N706+7bTZA+ke8oRoQC5/KeRIjwhLk6+kthzo
vYOe/PKHU7o8RWoCERcj6LRWea6m6XaeNQEoMv2e7xEz6tKrRUdmlRSUbsIXWX7b
XhVgrBM4EHmW1oPkNhLLdG0i0eyXYF0cyBi13yfO0+suPdY7B9oXWdT/uZv48Lfj
YRUSpHqqb7aQxAZd4FysivXc+F7LEJKe4gPfV/4z8BaMgd6wZdI=
=yuDM
-----END PGP SIGNATURE-----

3
ethtool-5.7.tar.xz Normal file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:724eb8bd3c3a389fe285735959a1902fbd9310624656ad3220c5f23df1053c39
size 283048

View File

@ -1,3 +1,22 @@
-------------------------------------------------------------------
Sun Jun 7 19:55:27 UTC 2020 - Michal Kubecek <mkubecek@suse.cz>
- update to new upstream release 5.7
* support LLRS (Low Latency Reed Solomon) FEC mode
* accept long legacy flag names (-K)
* support for newer SFF-8024 compliance codes
* report transceiver when reported by kernel
* improve fallback from netlink to ioctl and error messages
- drop patches present in 5.7 release:
netlink-show-netlink-error-even-without-extack.patch
features-accept-long-legacy-flag-names-when-setting-.patch
refactor-interface-between-ioctl-and-netlink-code.patch
netlink-use-genetlink-ops-information-to-decide-abou.patch
- refresh
netlink-fix-build-warnings.patch
- fix cherry picked from upstream git:
netlink-fix-unwanted-switch-fall-through-in-family_i.patch
-------------------------------------------------------------------
Fri May 15 20:12:57 UTC 2020 - Michal Kubecek <mkubecek@suse.cz>

View File

@ -17,7 +17,7 @@
Name: ethtool
Version: 5.6
Version: 5.7
Release: 0
Summary: Utility for examining and tuning Ethernet-based network interfaces
License: GPL-2.0-only
@ -34,10 +34,7 @@ BuildRequires: xz
BuildRequires: pkgconfig(libmnl)
Patch1: netlink-fix-build-warnings.patch
Patch2: netlink-show-netlink-error-even-without-extack.patch
Patch3: features-accept-long-legacy-flag-names-when-setting-.patch
Patch4: refactor-interface-between-ioctl-and-netlink-code.patch
Patch5: netlink-use-genetlink-ops-information-to-decide-abou.patch
Patch2: netlink-fix-unwanted-switch-fall-through-in-family_i.patch
%description
Ethtool is a small utility for examining and tuning ethernet-based
@ -47,9 +44,6 @@ network interfaces. See the man page for more details.
%setup -q
%patch1 -p1
%patch2 -p1
%patch3 -p1
%patch4 -p1
%patch5 -p1
%build
export CFLAGS="%optflags -W -Wall -Wstrict-prototypes -Wformat-security -Wpointer-arith -Wno-missing-field-initializers"

View File

@ -1,63 +0,0 @@
From: Michal Kubecek <mkubecek@suse.cz>
Date: Mon, 13 Apr 2020 11:46:42 +0200
Subject: features: accept long legacy flag names when setting features
Patch-mainline: v5.7
Git-commit: 4b1fa2c2d250441f83b90f9410cd6ce7d879c2fe
The legacy feature flags have long names (e.g. "generic-receive-offload")
and short names (e.g. "gro"). While "ethtool -k" shows only long names,
"ethtool -K" accepts only short names. This is a bit confusing as users
have to resort to documentation to see what flag name to use; in
particular, if a legacy flag corresponds to only one actual kernel feature,
"ethtool -k" shows the output in the same form as if long flag name were
a kernel feature name but this name cannot be used to set the flag/feature.
Accept both short and long legacy flag names in "ethool -K".
Reported-by: Konstantin Kharlamov <hi-angel@yandex.ru>
Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
ethtool.c | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
--- a/ethtool.c
+++ b/ethtool.c
@@ -2297,26 +2297,33 @@ static int do_sfeatures(struct cmd_context *ctx)
/* Generate cmdline_info for legacy flags and kernel-named
* features, and parse our arguments.
*/
- cmdline_features = calloc(ARRAY_SIZE(off_flag_def) + defs->n_features,
+ cmdline_features = calloc(2 * ARRAY_SIZE(off_flag_def) +
+ defs->n_features,
sizeof(cmdline_features[0]));
if (!cmdline_features) {
perror("Cannot parse arguments");
rc = 1;
goto err;
}
- for (i = 0; i < ARRAY_SIZE(off_flag_def); i++)
+ j = 0;
+ for (i = 0; i < ARRAY_SIZE(off_flag_def); i++) {
flag_to_cmdline_info(off_flag_def[i].short_name,
off_flag_def[i].value,
&off_flags_wanted, &off_flags_mask,
- &cmdline_features[i]);
+ &cmdline_features[j++]);
+ flag_to_cmdline_info(off_flag_def[i].long_name,
+ off_flag_def[i].value,
+ &off_flags_wanted, &off_flags_mask,
+ &cmdline_features[j++]);
+ }
for (i = 0; i < defs->n_features; i++)
flag_to_cmdline_info(
defs->def[i].name, FEATURE_FIELD_FLAG(i),
&FEATURE_WORD(efeatures->features, i, requested),
&FEATURE_WORD(efeatures->features, i, valid),
- &cmdline_features[ARRAY_SIZE(off_flag_def) + i]);
+ &cmdline_features[j++]);
parse_generic_cmdline(ctx, &any_changed, cmdline_features,
- ARRAY_SIZE(off_flag_def) + defs->n_features);
+ 2 * ARRAY_SIZE(off_flag_def) + defs->n_features);
free(cmdline_features);
if (!any_changed) {

View File

@ -1,21 +1,21 @@
From: Michal Kubecek <mkubecek@suse.cz>
Date: Tue, 12 May 2020 22:10:19 +0200
Date: Fri, 29 May 2020 01:21:12 +0200
Subject: netlink: fix build warnings
Patch-mainline: Not yet, going to submit for 5.7 cycle
Patch-mainline: v5.8
Git-commit: a9b8685859075771887aad0328246e0afa089caf
Depending on compiler version and options, some of these warnings may
result in build failure.
- gcc 4.8 wants __KERNEL_DIV_ROUND_UP defined before including ethtool.h
- avoid pointer arithmetic on void *
- do not use printf(s) if string is not a string literal
Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
Tested-by: Heiko Thiery <heiko.thiery@gmail.com>
---
netlink/desc-ethtool.c | 2 +-
netlink/parser.c | 2 +-
netlink/settings.c | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
2 files changed, 2 insertions(+), 2 deletions(-)
--- a/netlink/desc-ethtool.c
+++ b/netlink/desc-ethtool.c
@ -41,14 +41,3 @@ Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
ret = parser->handler(nlctx, parser->type, parser->handler_data,
msgbuff, param_dest);
if (ret < 0)
--- a/netlink/settings.c
+++ b/netlink/settings.c
@@ -375,7 +375,7 @@ static int dump_link_modes(struct nl_context *nlctx,
after:
if (first && if_none)
printf("%s", if_none);
- printf(after);
+ fputs(after, stdout);
return 0;
err:

View File

@ -0,0 +1,26 @@
From: Michal Kubecek <mkubecek@suse.cz>
Date: Sun, 7 Jun 2020 21:32:50 +0200
Subject: netlink: fix unwanted switch fall through in family_info_cb()
Patch-mainline: v5.8
Git-commit: c07ea9e10498a09a08cc9b507704471d4d7f505b
Recently added switch branch for CTRL_ATTR_OPS in family_info_cb() is
missing final break statement so that it will fall through into
CTRL_ATTR_MCAST_GROUPS.
Fixes: 6c19c0d559c8 ("netlink: use genetlink ops information to decide about fallback")
Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
netlink/netlink.c | 1 +
1 file changed, 1 insertion(+)
--- a/netlink/netlink.c
+++ b/netlink/netlink.c
@@ -211,6 +211,7 @@ static int family_info_cb(const struct nlmsghdr *nlhdr, void *data)
ret = genl_read_ops(nlctx, attr);
if (ret < 0)
return MNL_CB_ERROR;
+ break;
case CTRL_ATTR_MCAST_GROUPS:
find_mc_group(nlctx, attr);
break;

View File

@ -1,87 +0,0 @@
From: Michal Kubecek <mkubecek@suse.cz>
Date: Tue, 10 Mar 2020 13:24:55 +0100
Subject: netlink: show netlink error even without extack
Patch-mainline: v5.7
Git-commit: 684f3e6c31bd096ef50725267957e0423b7932c6
Even if the NLMSG_ERROR message has no extack (NLM_F_ACK_TLVS not set, i.e.
no error/warning message and bad attribute offset), we still want to
display the error code (unless suppressed) and, if pretty printing is
enabled, the embedded client message (if present).
Fixes: 50efb3cdd2bb ("netlink: netlink socket wrapper and helpers")
Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
netlink/nlsock.c | 37 +++++++++++++++++--------------------
1 file changed, 17 insertions(+), 20 deletions(-)
--- a/netlink/nlsock.c
+++ b/netlink/nlsock.c
@@ -173,25 +173,25 @@ static int nlsock_process_ack(struct nlmsghdr *nlhdr, ssize_t len,
{
const struct nlattr *tb[NLMSGERR_ATTR_MAX + 1] = {};
DECLARE_ATTR_TB_INFO(tb);
+ unsigned int err_offset = 0;
unsigned int tlv_offset;
struct nlmsgerr *nlerr;
bool silent;
- if (len < NLMSG_HDRLEN + sizeof(*nlerr))
+ if ((len < NLMSG_HDRLEN + sizeof(*nlerr)) || (len < nlhdr->nlmsg_len))
return -EFAULT;
nlerr = mnl_nlmsg_get_payload(nlhdr);
- silent = (!(nlhdr->nlmsg_flags & NLM_F_ACK_TLVS) ||
- suppress_nlerr >= 2 ||
- (suppress_nlerr && nlerr->error == -EOPNOTSUPP));
- if (silent)
- goto out;
+ silent = suppress_nlerr >= 2 ||
+ (suppress_nlerr && nlerr->error == -EOPNOTSUPP);
+ if (silent || !(nlhdr->nlmsg_flags & NLM_F_ACK_TLVS))
+ goto tlv_done;
tlv_offset = sizeof(*nlerr);
if (!(nlhdr->nlmsg_flags & NLM_F_CAPPED))
tlv_offset += MNL_ALIGN(mnl_nlmsg_get_payload_len(&nlerr->msg));
-
if (mnl_attr_parse(nlhdr, tlv_offset, attr_cb, &tb_info) < 0)
- goto out;
+ goto tlv_done;
+
if (tb[NLMSGERR_ATTR_MSG]) {
const char *msg = mnl_attr_get_str(tb[NLMSGERR_ATTR_MSG]);
@@ -202,24 +202,21 @@ static int nlsock_process_ack(struct nlmsghdr *nlhdr, ssize_t len,
mnl_attr_get_u32(tb[NLMSGERR_ATTR_OFFS]));
fputc('\n', stderr);
}
+ if (tb[NLMSGERR_ATTR_OFFS])
+ err_offset = mnl_attr_get_u32(tb[NLMSGERR_ATTR_OFFS]);
- if (nlerr->error && pretty) {
- unsigned int err_offset = 0;
-
- if (tb[NLMSGERR_ATTR_OFFS])
- err_offset = mnl_attr_get_u32(tb[NLMSGERR_ATTR_OFFS]);
+tlv_done:
+ if (nlerr->error && !silent) {
+ errno = -nlerr->error;
+ perror("netlink error");
+ }
+ if (pretty && !(nlhdr->nlmsg_flags & NLM_F_CAPPED) &&
+ nlhdr->nlmsg_len >= NLMSG_HDRLEN + nlerr->msg.nlmsg_len) {
fprintf(stderr, "offending message%s:\n",
err_offset ? " and attribute" : "");
pretty_print_genlmsg(&nlerr->msg, ethnl_umsg_desc,
ethnl_umsg_n_desc, err_offset);
}
-
-out:
- if (nlerr->error) {
- errno = -nlerr->error;
- if (!silent)
- perror("netlink error");
- }
return nlerr->error;
}

View File

@ -1,335 +0,0 @@
From: Michal Kubecek <mkubecek@suse.cz>
Date: Mon, 13 Apr 2020 17:39:32 +0200
Subject: netlink: use genetlink ops information to decide about fallback
Patch-mainline: v5.7
Git-commit: 6c19c0d559c80824383c5f0e2dc229878d9b19f5
Currently ethtool falls back to ioctl when netlink socket initialization
fails or if netlink request fails with -EOPNOTSUPP (and we do not know that
request cannot possibly work via ioctl, e.g. because of wildcard device
name or device name longer than IFNAMSIZ). This logic has one problem: we
cannot distinguish if -EOPNOTSUPP error code means that subcommand as such
is not implemented in kernel or that it failed for some other reason (e.g.
specific combination of parameters is not supported by driver). If the
latter is the case, fallback to ioctl is pointless as the same request
would fail via ioctl as well. In some cases we can even get a duplicate
error message.
Fortunately, genetlink provides information about supported family commands
in the form of CTRL_ATTR_OPS nested attribute. Parse this information when
available and use it to only fall back to ioctl only if kernel support for
netlink request as such is missing so that there is a chance that ioctl
request will work. In such case, do not send netlink request at all.
Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
netlink/netlink.c | 138 ++++++++++++++++++++++++++++++++++++---------
netlink/netlink.h | 5 ++
netlink/parser.c | 7 +++
netlink/settings.c | 7 +++
4 files changed, 129 insertions(+), 28 deletions(-)
--- a/netlink/netlink.c
+++ b/netlink/netlink.c
@@ -92,16 +92,88 @@ int get_dev_info(const struct nlattr *nest, int *ifindex, char *ifname)
return 0;
}
+/**
+ * netlink_cmd_check() - check support for netlink command
+ * @ctx: ethtool command context
+ * @cmd: netlink command id
+ * @devname: device name from user
+ * @allow_wildcard: wildcard dumps supported
+ *
+ * Check if command @cmd is known to be unsupported based on ops information
+ * from genetlink family id request. Set nlctx->ioctl_fallback if ethtool
+ * should fall back to ioctl, i.e. when we do not know in advance that
+ * netlink request is supported. Set nlctx->wildcard_unsupported if "*" was
+ * used as device name but the request does not support wildcards (on either
+ * side).
+ *
+ * Return: true if we know the netlink request is not supported and should
+ * fail (and possibly fall back) without actually sending it to kernel.
+ */
+bool netlink_cmd_check(struct cmd_context *ctx, unsigned int cmd,
+ bool allow_wildcard)
+{
+ bool is_dump = !strcmp(ctx->devname, WILDCARD_DEVNAME);
+ uint32_t cap = is_dump ? GENL_CMD_CAP_DUMP : GENL_CMD_CAP_DO;
+ struct nl_context *nlctx = ctx->nlctx;
+
+ if (is_dump && !allow_wildcard) {
+ nlctx->wildcard_unsupported = true;
+ return true;
+ }
+ if (!nlctx->ops_flags) {
+ nlctx->ioctl_fallback = true;
+ return false;
+ }
+ if (cmd > ETHTOOL_MSG_USER_MAX || !nlctx->ops_flags[cmd]) {
+ nlctx->ioctl_fallback = true;
+ return true;
+ }
+
+ if (is_dump && !(nlctx->ops_flags[cmd] & GENL_CMD_CAP_DUMP))
+ nlctx->wildcard_unsupported = true;
+
+ return !(nlctx->ops_flags[cmd] & cap);
+}
+
/* initialization */
-struct fam_info {
- const char *fam_name;
- const char *grp_name;
- uint16_t fam_id;
- uint32_t grp_id;
-};
+static int genl_read_ops(struct nl_context *nlctx,
+ const struct nlattr *ops_attr)
+{
+ struct nlattr *op_attr;
+ uint32_t *ops_flags;
+ int ret;
+
+ ops_flags = calloc(__ETHTOOL_MSG_USER_CNT, sizeof(ops_flags[0]));
+ if (!ops_flags)
+ return -ENOMEM;
+
+ mnl_attr_for_each_nested(op_attr, ops_attr) {
+ const struct nlattr *tb[CTRL_ATTR_OP_MAX + 1] = {};
+ DECLARE_ATTR_TB_INFO(tb);
+ uint32_t op_id;
+
+ ret = mnl_attr_parse_nested(op_attr, attr_cb, &tb_info);
+ if (ret < 0)
+ goto err;
+
+ if (!tb[CTRL_ATTR_OP_ID] || !tb[CTRL_ATTR_OP_FLAGS])
+ continue;
+ op_id = mnl_attr_get_u32(tb[CTRL_ATTR_OP_ID]);
+ if (op_id >= __ETHTOOL_MSG_USER_CNT)
+ continue;
+
+ ops_flags[op_id] = mnl_attr_get_u32(tb[CTRL_ATTR_OP_FLAGS]);
+ }
+
+ nlctx->ops_flags = ops_flags;
+ return 0;
+err:
+ free(ops_flags);
+ return ret;
+}
-static void find_mc_group(struct nlattr *nest, struct fam_info *info)
+static void find_mc_group(struct nl_context *nlctx, struct nlattr *nest)
{
const struct nlattr *grp_tb[CTRL_ATTR_MCAST_GRP_MAX + 1] = {};
DECLARE_ATTR_TB_INFO(grp_tb);
@@ -116,9 +188,9 @@ static void find_mc_group(struct nlattr *nest, struct fam_info *info)
!grp_tb[CTRL_ATTR_MCAST_GRP_ID])
continue;
if (strcmp(mnl_attr_get_str(grp_tb[CTRL_ATTR_MCAST_GRP_NAME]),
- info->grp_name))
+ ETHTOOL_MCGRP_MONITOR_NAME))
continue;
- info->grp_id =
+ nlctx->ethnl_mongrp =
mnl_attr_get_u32(grp_tb[CTRL_ATTR_MCAST_GRP_ID]);
return;
}
@@ -126,16 +198,21 @@ static void find_mc_group(struct nlattr *nest, struct fam_info *info)
static int family_info_cb(const struct nlmsghdr *nlhdr, void *data)
{
- struct fam_info *info = data;
+ struct nl_context *nlctx = data;
struct nlattr *attr;
+ int ret;
mnl_attr_for_each(attr, nlhdr, GENL_HDRLEN) {
switch (mnl_attr_get_type(attr)) {
case CTRL_ATTR_FAMILY_ID:
- info->fam_id = mnl_attr_get_u16(attr);
+ nlctx->ethnl_fam = mnl_attr_get_u16(attr);
break;
+ case CTRL_ATTR_OPS:
+ ret = genl_read_ops(nlctx, attr);
+ if (ret < 0)
+ return MNL_CB_ERROR;
case CTRL_ATTR_MCAST_GROUPS:
- find_mc_group(attr, info);
+ find_mc_group(nlctx, attr);
break;
}
}
@@ -144,41 +221,37 @@ static int family_info_cb(const struct nlmsghdr *nlhdr, void *data)
}
#ifdef TEST_ETHTOOL
-static int get_genl_family(struct nl_socket *nlsk, struct fam_info *info)
+static int get_genl_family(struct nl_context *nlctx, struct nl_socket *nlsk)
{
return 0;
}
#else
-static int get_genl_family(struct nl_socket *nlsk, struct fam_info *info)
+static int get_genl_family(struct nl_context *nlctx, struct nl_socket *nlsk)
{
struct nl_msg_buff *msgbuff = &nlsk->msgbuff;
int ret;
- nlsk->nlctx->suppress_nlerr = 2;
+ nlctx->suppress_nlerr = 2;
ret = __msg_init(msgbuff, GENL_ID_CTRL, CTRL_CMD_GETFAMILY,
NLM_F_REQUEST | NLM_F_ACK, 1);
if (ret < 0)
goto out;
ret = -EMSGSIZE;
- if (ethnla_put_strz(msgbuff, CTRL_ATTR_FAMILY_NAME, info->fam_name))
+ if (ethnla_put_strz(msgbuff, CTRL_ATTR_FAMILY_NAME, ETHTOOL_GENL_NAME))
goto out;
nlsock_sendmsg(nlsk, NULL);
- nlsock_process_reply(nlsk, family_info_cb, info);
- ret = info->fam_id ? 0 : -EADDRNOTAVAIL;
+ nlsock_process_reply(nlsk, family_info_cb, nlctx);
+ ret = nlctx->ethnl_fam ? 0 : -EADDRNOTAVAIL;
out:
- nlsk->nlctx->suppress_nlerr = 0;
+ nlctx->suppress_nlerr = 0;
return ret;
}
#endif
int netlink_init(struct cmd_context *ctx)
{
- struct fam_info info = {
- .fam_name = ETHTOOL_GENL_NAME,
- .grp_name = ETHTOOL_MCGRP_MONITOR_NAME,
- };
struct nl_context *nlctx;
int ret;
@@ -189,11 +262,9 @@ int netlink_init(struct cmd_context *ctx)
ret = nlsock_init(nlctx, &nlctx->ethnl_socket, NETLINK_GENERIC);
if (ret < 0)
goto out_free;
- ret = get_genl_family(nlctx->ethnl_socket, &info);
+ ret = get_genl_family(nlctx, nlctx->ethnl_socket);
if (ret < 0)
goto out_nlsk;
- nlctx->ethnl_fam = info.fam_id;
- nlctx->ethnl_mongrp = info.grp_id;
ctx->nlctx = nlctx;
return 0;
@@ -201,6 +272,7 @@ int netlink_init(struct cmd_context *ctx)
out_nlsk:
nlsock_done(nlctx->ethnl_socket);
out_free:
+ free(nlctx->ops_flags);
free(nlctx);
return ret;
}
@@ -210,6 +282,7 @@ static void netlink_done(struct cmd_context *ctx)
if (!ctx->nlctx)
return;
+ free(ctx->nlctx->ops_flags);
free(ctx->nlctx);
ctx->nlctx = NULL;
cleanup_all_strings();
@@ -228,6 +301,7 @@ void netlink_run_handler(struct cmd_context *ctx, nl_func_t nlfunc,
bool no_fallback)
{
bool wildcard = ctx->devname && !strcmp(ctx->devname, WILDCARD_DEVNAME);
+ struct nl_context *nlctx;
const char *reason;
int ret;
@@ -245,12 +319,20 @@ void netlink_run_handler(struct cmd_context *ctx, nl_func_t nlfunc,
reason = "netlink interface initialization failed";
goto no_support;
}
+ nlctx = ctx->nlctx;
ret = nlfunc(ctx);
netlink_done(ctx);
- if (ret != -EOPNOTSUPP || no_fallback)
+ if (no_fallback || ret != -EOPNOTSUPP || !nlctx->ioctl_fallback) {
+ if (nlctx->wildcard_unsupported)
+ fprintf(stderr, "%s\n",
+ "subcommand does not support wildcard dump");
exit(ret >= 0 ? ret : 1);
- reason = "kernel netlink support for subcommand missing";
+ }
+ if (nlctx->wildcard_unsupported)
+ reason = "subcommand does not support wildcard dump";
+ else
+ reason = "kernel netlink support for subcommand missing";
no_support:
if (no_fallback) {
--- a/netlink/netlink.h
+++ b/netlink/netlink.h
@@ -25,6 +25,7 @@ struct nl_context {
unsigned int suppress_nlerr;
uint16_t ethnl_fam;
uint32_t ethnl_mongrp;
+ uint32_t *ops_flags;
struct nl_socket *ethnl_socket;
struct nl_socket *ethnl2_socket;
struct nl_socket *rtnl_socket;
@@ -36,6 +37,8 @@ struct nl_context {
const char *param;
char **argp;
int argc;
+ bool ioctl_fallback;
+ bool wildcard_unsupported;
};
struct attr_tb_info {
@@ -50,6 +53,8 @@ int nomsg_reply_cb(const struct nlmsghdr *nlhdr, void *data);
int attr_cb(const struct nlattr *attr, void *data);
int netlink_init(struct cmd_context *ctx);
+bool netlink_cmd_check(struct cmd_context *ctx, unsigned int cmd,
+ bool allow_wildcard);
const char *get_dev_name(const struct nlattr *nest);
int get_dev_info(const struct nlattr *nest, int *ifindex, char *ifname);
--- a/netlink/parser.c
+++ b/netlink/parser.c
@@ -1023,6 +1023,13 @@ int nl_parser(struct nl_context *nlctx, const struct param_parser *params,
goto out_free;
}
+ if (group_style == PARSER_GROUP_MSG) {
+ ret = -EOPNOTSUPP;
+ for (buff = buffs; buff; buff = buff->next)
+ if (msgbuff_len(&buff->msgbuff) > buff->orig_len &&
+ netlink_cmd_check(nlctx->ctx, buff->id, false))
+ goto out_free;
+ }
for (buff = buffs; buff; buff = buff->next) {
struct nl_msg_buff *msgbuff = &buff->msgbuff;
--- a/netlink/settings.c
+++ b/netlink/settings.c
@@ -726,6 +726,13 @@ int nl_gset(struct cmd_context *ctx)
struct nl_socket *nlsk = nlctx->ethnl_socket;
int ret;
+ if (netlink_cmd_check(ctx, ETHTOOL_MSG_LINKMODES_GET, true) ||
+ netlink_cmd_check(ctx, ETHTOOL_MSG_LINKINFO_GET, true) ||
+ netlink_cmd_check(ctx, ETHTOOL_MSG_WOL_GET, true) ||
+ netlink_cmd_check(ctx, ETHTOOL_MSG_DEBUG_GET, true) ||
+ netlink_cmd_check(ctx, ETHTOOL_MSG_LINKSTATE_GET, true))
+ return -EOPNOTSUPP;
+
nlctx->suppress_nlerr = 1;
ret = gset_request(nlsk, ETHTOOL_MSG_LINKMODES_GET,

View File

@ -1,271 +0,0 @@
From: Michal Kubecek <mkubecek@suse.cz>
Date: Mon, 13 Apr 2020 13:04:42 +0200
Subject: refactor interface between ioctl and netlink code
Patch-mainline: v5.7
Git-commit: ab88f37fa432eea925306b442ac283daf71d8791
Move netlink related code from main() to separate handlers in netlink code.
Improve the logic of fallback to ioctl and improve error messages when
fallback is not possible (e.g. wildcard device name or name longer than
IFNAMSIZ). Also handle the (theoretical for now) case when ioctl handler is
not available.
Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
ethtool.c | 51 +++++++++++-----------------------------
netlink/extapi.h | 14 +++++++----
netlink/monitor.c | 15 +++++++++---
netlink/netlink.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++-
netlink/netlink.h | 1 +
5 files changed, 93 insertions(+), 47 deletions(-)
--- a/ethtool.c
+++ b/ethtool.c
@@ -5164,7 +5164,7 @@ struct option {
const char *opts;
bool no_dev;
int (*func)(struct cmd_context *);
- int (*nlfunc)(struct cmd_context *);
+ nl_func_t nlfunc;
const char *help;
const char *xhelp;
};
@@ -5738,6 +5738,11 @@ static int ioctl_init(struct cmd_context *ctx, bool no_dev)
ctx->fd = -1;
return 0;
}
+ if (strlen(ctx->devname) >= IFNAMSIZ) {
+ fprintf(stderr, "Device name longer than %u characters\n",
+ IFNAMSIZ - 1);
+ exit_bad_args();
+ }
/* Setup our control structures. */
memset(&ctx->ifr, 0, sizeof(ctx->ifr));
@@ -5757,9 +5762,9 @@ static int ioctl_init(struct cmd_context *ctx, bool no_dev)
int main(int argc, char **argp)
{
- int (*nlfunc)(struct cmd_context *) = NULL;
int (*func)(struct cmd_context *);
struct cmd_context ctx = {};
+ nl_func_t nlfunc = NULL;
bool no_dev;
int ret;
int k;
@@ -5782,19 +5787,12 @@ int main(int argc, char **argp)
argp += 2;
argc -= 2;
}
-#ifdef ETHTOOL_ENABLE_NETLINK
if (*argp && !strcmp(*argp, "--monitor")) {
- if (netlink_init(&ctx)) {
- fprintf(stderr,
- "Option --monitor is only available with netlink.\n");
- return 1;
- } else {
- ctx.argp = ++argp;
- ctx.argc = --argc;
- return nl_monitor(&ctx);
- }
+ ctx.argp = ++argp;
+ ctx.argc = --argc;
+ ret = nl_monitor(&ctx);
+ return ret ? 1 : 0;
}
-#endif
/* First argument must be either a valid option or a device
* name to get settings for (which we don't expect to begin
@@ -5819,40 +5817,17 @@ int main(int argc, char **argp)
no_dev = false;
opt_found:
- if (nlfunc) {
- if (netlink_init(&ctx))
- nlfunc = NULL; /* fallback to ioctl() */
- }
-
if (!no_dev) {
ctx.devname = *argp++;
argc--;
- /* netlink supports altnames, we will have to recheck against
- * IFNAMSIZ later in case of fallback to ioctl
- */
- if (!ctx.devname || strlen(ctx.devname) >= ALTIFNAMSIZ) {
- netlink_done(&ctx);
+ if (!ctx.devname)
exit_bad_args();
- }
}
-
ctx.argc = argc;
ctx.argp = argp;
+ netlink_run_handler(&ctx, nlfunc, !func);
- if (nlfunc) {
- ret = nlfunc(&ctx);
- netlink_done(&ctx);
- if ((ret != -EOPNOTSUPP) || !func)
- return (ret >= 0) ? ret : 1;
- }
-
- if (ctx.devname && strlen(ctx.devname) >= IFNAMSIZ) {
- fprintf(stderr,
- "ethtool: device names longer than %u characters are only allowed with netlink\n",
- IFNAMSIZ - 1);
- exit_bad_args();
- }
ret = ioctl_init(&ctx, no_dev);
if (ret)
return ret;
--- a/netlink/extapi.h
+++ b/netlink/extapi.h
@@ -10,10 +10,12 @@
struct cmd_context;
struct nl_context;
+typedef int (*nl_func_t)(struct cmd_context *);
+
#ifdef ETHTOOL_ENABLE_NETLINK
-int netlink_init(struct cmd_context *ctx);
-void netlink_done(struct cmd_context *ctx);
+void netlink_run_handler(struct cmd_context *ctx, nl_func_t nlfunc,
+ bool no_fallback);
int nl_gset(struct cmd_context *ctx);
int nl_sset(struct cmd_context *ctx);
@@ -24,13 +26,15 @@ void nl_monitor_usage(void);
#else /* ETHTOOL_ENABLE_NETLINK */
-static inline int netlink_init(struct cmd_context *ctx maybe_unused)
+static inline void netlink_run_handler(struct cmd_context *ctx,
+ nl_func_t nlfunc, bool no_fallback)
{
- return -EOPNOTSUPP;
}
-static inline void netlink_done(struct cmd_context *ctx maybe_unused)
+static inline int nl_monitor(struct cmd_context *ctx)
{
+ fprintf(stderr, "Netlink not supported by ethtool, option --monitor unsupported.\n");
+ return -EOPNOTSUPP;
}
static inline void nl_monitor_usage(void)
--- a/netlink/monitor.c
+++ b/netlink/monitor.c
@@ -167,16 +167,25 @@ static int parse_monitor(struct cmd_context *ctx)
int nl_monitor(struct cmd_context *ctx)
{
- struct nl_context *nlctx = ctx->nlctx;
- struct nl_socket *nlsk = nlctx->ethnl_socket;
- uint32_t grpid = nlctx->ethnl_mongrp;
+ struct nl_context *nlctx;
+ struct nl_socket *nlsk;
+ uint32_t grpid;
bool is_dev;
int ret;
+ ret = netlink_init(ctx);
+ if (ret < 0) {
+ fprintf(stderr, "Netlink interface initialization failed, option --monitor not supported.\n");
+ return ret;
+ }
+ nlctx = ctx->nlctx;
+ nlsk = nlctx->ethnl_socket;
+ grpid = nlctx->ethnl_mongrp;
if (!grpid) {
fprintf(stderr, "multicast group 'monitor' not found\n");
return -EOPNOTSUPP;
}
+
if (parse_monitor(ctx) < 0)
return 1;
is_dev = ctx->devname && strcmp(ctx->devname, WILDCARD_DEVNAME);
--- a/netlink/netlink.c
+++ b/netlink/netlink.c
@@ -205,7 +205,7 @@ out_free:
return ret;
}
-void netlink_done(struct cmd_context *ctx)
+static void netlink_done(struct cmd_context *ctx)
{
if (!ctx->nlctx)
return;
@@ -214,3 +214,60 @@ void netlink_done(struct cmd_context *ctx)
ctx->nlctx = NULL;
cleanup_all_strings();
}
+
+/**
+ * netlink_run_handler() - run netlink handler for subcommand
+ * @ctx: command context
+ * @nlfunc: subcommand netlink handler to call
+ * @no_fallback: there is no ioctl fallback handler
+ *
+ * This function returns only if ioctl() handler should be run as fallback.
+ * Otherwise it exits with appropriate return code.
+ */
+void netlink_run_handler(struct cmd_context *ctx, nl_func_t nlfunc,
+ bool no_fallback)
+{
+ bool wildcard = ctx->devname && !strcmp(ctx->devname, WILDCARD_DEVNAME);
+ const char *reason;
+ int ret;
+
+ if (ctx->devname && strlen(ctx->devname) >= ALTIFNAMSIZ) {
+ fprintf(stderr, "device name '%s' longer than %u characters\n",
+ ctx->devname, ALTIFNAMSIZ - 1);
+ exit(1);
+ }
+
+ if (!nlfunc) {
+ reason = "ethtool netlink support for subcommand missing";
+ goto no_support;
+ }
+ if (netlink_init(ctx)) {
+ reason = "netlink interface initialization failed";
+ goto no_support;
+ }
+
+ ret = nlfunc(ctx);
+ netlink_done(ctx);
+ if (ret != -EOPNOTSUPP || no_fallback)
+ exit(ret >= 0 ? ret : 1);
+ reason = "kernel netlink support for subcommand missing";
+
+no_support:
+ if (no_fallback) {
+ fprintf(stderr, "%s, subcommand not supported by ioctl\n",
+ reason);
+ exit(1);
+ }
+ if (wildcard) {
+ fprintf(stderr, "%s, wildcard dump not supported\n", reason);
+ exit(1);
+ }
+ if (ctx->devname && strlen(ctx->devname) >= IFNAMSIZ) {
+ fprintf(stderr,
+ "%s, device name longer than %u not supported\n",
+ reason, IFNAMSIZ - 1);
+ exit(1);
+ }
+
+ /* fallback to ioctl() */
+}
--- a/netlink/netlink.h
+++ b/netlink/netlink.h
@@ -49,6 +49,7 @@ struct attr_tb_info {
int nomsg_reply_cb(const struct nlmsghdr *nlhdr, void *data);
int attr_cb(const struct nlattr *attr, void *data);
+int netlink_init(struct cmd_context *ctx);
const char *get_dev_name(const struct nlattr *nest);
int get_dev_info(const struct nlattr *nest, int *ifindex, char *ifname);