- Update to new upstream release 5.6
OBS-URL: https://build.opensuse.org/package/show/network:utilities/ethtool?expand=0&rev=94
This commit is contained in:
parent
f00d1a6ec6
commit
c048623ce3
@ -1,16 +0,0 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQIzBAABCAAdFiEEzkpNCA8NME8juevdly1b9NxhOAYFAl4YxP0ACgkQly1b9Nxh
|
||||
OAaTIA//VZ21DyEwAqIb5yJssiCtb+LlTew1UFfuovyZzJsYNIZYBCDFWnN+uQ17
|
||||
6MbTcpOdRcVqkYY2yKG7urTprsSVzp+3bQFyvyPizI5iqHxgHODVbUIdikZnuvX3
|
||||
apadzLEw+B9cSFPahxb0i+8PRSg4oFT8QLm330dUBEzO9Ia/8Qoo3iVue3qQpbdL
|
||||
Sw8t4R3QgX4xULrFLiKURr/l0IZl8Wt3RqemxgDhgwdJR7+nbNgp4pFQ6mGEvo0Q
|
||||
+ZcOshyYSJOMHZNI0w6JxzqC2eH9mcAgq6KV9YHxoc1tQ0ZFAJn9Hs5r48tQkga4
|
||||
HspPG1ZPaKm6Ocpgg2sppqR/7yek3uzB9tdcsnlznDjXwAkf+8El9h5wNIMunYA4
|
||||
aKCI3vpK0HGDMODLdpCmS7/bBNALzrZvj/qV8soUv6c8HxXv5zfWd2D6G8FNCv0Q
|
||||
o/sYyTPL+6QIWGbN/t6t2yBye7G54DnCJTkm6dibFg9avHI1qPRj99TAVNg+td0I
|
||||
YPJcVfiQMzV35nYCDFSuHey1J/BuFHSW5433zrpR2vatHOi8cKc2Sym6NkgNn4iG
|
||||
zF+OlVVJyCzyLtaRqNC3fOHyeN90IQWBGPYeQibB8bzJDXPU7tQuOPv5sC8TLAXu
|
||||
P7pR5+P7u5Xj9OXkEKqeUGLKVb4RLZAkQ5DFMkxg0dYGJDix43k=
|
||||
=+qUX
|
||||
-----END PGP SIGNATURE-----
|
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:22f81e4927d6eb6a13a259d705248a96005fce2005e15257f639f5a1c8c52b6b
|
||||
size 239288
|
16
ethtool-5.6.tar.sign
Normal file
16
ethtool-5.6.tar.sign
Normal file
@ -0,0 +1,16 @@
|
||||
-----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-----
|
3
ethtool-5.6.tar.xz
Normal file
3
ethtool-5.6.tar.xz
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ca0f1b526dad5153f0aa0f1eb3c17c31770c75a74f70af622b1a83ae38043995
|
||||
size 281084
|
@ -1,3 +1,28 @@
|
||||
-------------------------------------------------------------------
|
||||
Tue May 12 21:27:12 UTC 2020 - Michal Kubeček <mkubecek@suse.cz>
|
||||
|
||||
- add fixes and improvements originally intended for 5.6:
|
||||
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
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Tue May 12 21:08:55 UTC 2020 - Michal Kubecek <mkubecek@suse.cz>
|
||||
|
||||
- Update to new upstream release 5.6
|
||||
* basic infrastructure for netlink kernel interface
|
||||
* netlink: support "ethtool <dev>"
|
||||
* netlink: support "ethtool -s <dev> ..."
|
||||
* netlink: support "ethtool -P <dev>"
|
||||
* netlink: monitor support
|
||||
* add --debug option
|
||||
* netlink: pretty printing of netlink messages
|
||||
- add libmnl build time dependency
|
||||
- fix SLE12 build:
|
||||
netlink-fix-build-warnings.patch
|
||||
- minor specfile cleanup
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Mon Jan 13 11:46:41 UTC 2020 - Michal Kubecek <mkubecek@suse.cz>
|
||||
|
||||
|
23
ethtool.spec
23
ethtool.spec
@ -1,7 +1,7 @@
|
||||
#
|
||||
# spec file for package ethtool
|
||||
#
|
||||
# Copyright (c) 2020 SUSE LINUX GmbH, Nuernberg, Germany.
|
||||
# Copyright (c) 2020 SUSE LLC
|
||||
#
|
||||
# All modifications and additions to the file contributed by third parties
|
||||
# remain the property of their copyright owners, unless otherwise agreed
|
||||
@ -17,19 +17,27 @@
|
||||
|
||||
|
||||
Name: ethtool
|
||||
Version: 5.4
|
||||
Version: 5.6
|
||||
Release: 0
|
||||
Summary: Utility for examining and tuning Ethernet-based network interfaces
|
||||
License: GPL-2.0-only
|
||||
Group: Productivity/Networking/Diagnostic
|
||||
Url: http://kernel.org/pub/software/network/ethtool/
|
||||
URL: https://www.kernel.org/pub/software/network/ethtool/
|
||||
|
||||
#Git-Clone: git://git.kernel.org/pub/scm/network/ethtool/ethtool
|
||||
Source: http://kernel.org/pub/software/network/ethtool/%{name}-%{version}.tar.xz
|
||||
Source2: http://kernel.org/pub/software/network/ethtool/%{name}-%{version}.tar.sign
|
||||
Source: https://www.kernel.org/pub/software/network/ethtool/%{name}-%{version}.tar.xz
|
||||
Source2: https://www.kernel.org/pub/software/network/ethtool/%{name}-%{version}.tar.sign
|
||||
Source3: %{name}.keyring
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||
BuildRequires: pkgconfig
|
||||
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
|
||||
|
||||
%description
|
||||
Ethtool is a small utility for examining and tuning ethernet-based
|
||||
@ -37,6 +45,11 @@ network interfaces. See the man page for more details.
|
||||
|
||||
%prep
|
||||
%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"
|
||||
|
62
features-accept-long-legacy-flag-names-when-setting-.patch
Normal file
62
features-accept-long-legacy-flag-names-when-setting-.patch
Normal file
@ -0,0 +1,62 @@
|
||||
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: Submitted - 2020-04-13 - http://lkml.kernel.org/r/20200413212120.7D775E0FAD@unicorn.suse.cz
|
||||
|
||||
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) {
|
54
netlink-fix-build-warnings.patch
Normal file
54
netlink-fix-build-warnings.patch
Normal file
@ -0,0 +1,54 @@
|
||||
From: Michal Kubecek <mkubecek@suse.cz>
|
||||
Date: Tue, 12 May 2020 22:10:19 +0200
|
||||
Subject: netlink: fix build warnings
|
||||
Patch-mainline: Not yet, going to submit for 5.7 cycle
|
||||
|
||||
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>
|
||||
---
|
||||
netlink/desc-ethtool.c | 2 +-
|
||||
netlink/parser.c | 2 +-
|
||||
netlink/settings.c | 2 +-
|
||||
3 files changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/netlink/desc-ethtool.c
|
||||
+++ b/netlink/desc-ethtool.c
|
||||
@@ -4,9 +4,9 @@
|
||||
* Descriptions of ethtool netlink messages and attributes for pretty print.
|
||||
*/
|
||||
|
||||
+#include "../internal.h"
|
||||
#include <linux/ethtool_netlink.h>
|
||||
|
||||
-#include "../internal.h"
|
||||
#include "prettymsg.h"
|
||||
|
||||
static const struct pretty_nla_desc __header_desc[] = {
|
||||
--- a/netlink/parser.c
|
||||
+++ b/netlink/parser.c
|
||||
@@ -1016,7 +1016,7 @@ int nl_parser(struct nl_context *nlctx, const struct param_parser *params,
|
||||
buff = tmp_buff_find(buffs, parser->group);
|
||||
msgbuff = buff ? &buff->msgbuff : &nlsk->msgbuff;
|
||||
|
||||
- param_dest = dest ? (dest + parser->dest_offset) : NULL;
|
||||
+ param_dest = dest ? ((char *)dest + parser->dest_offset) : NULL;
|
||||
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:
|
86
netlink-show-netlink-error-even-without-extack.patch
Normal file
86
netlink-show-netlink-error-even-without-extack.patch
Normal file
@ -0,0 +1,86 @@
|
||||
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: Submitted - 2020-03-30 - http://lkml.kernel.org/r/20200330073305.CC634E0FC6@unicorn.suse.cz
|
||||
|
||||
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;
|
||||
}
|
||||
|
334
netlink-use-genetlink-ops-information-to-decide-abou.patch
Normal file
334
netlink-use-genetlink-ops-information-to-decide-abou.patch
Normal file
@ -0,0 +1,334 @@
|
||||
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: Submitted - 2020-04-29 - http://lkml.kernel.org/r/8a495e43783170906ce3bf0213bc1dd7eca0e5c8.1588112572.git.mkubecek@suse.cz
|
||||
|
||||
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,
|
270
refactor-interface-between-ioctl-and-netlink-code.patch
Normal file
270
refactor-interface-between-ioctl-and-netlink-code.patch
Normal file
@ -0,0 +1,270 @@
|
||||
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: Submitted - 2020-04-29 - http://lkml.kernel.org/r/cb6ec48745c0626a6ca14fdc0c22f11a6578d648.1588112572.git.mkubecek@suse.cz
|
||||
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user