1
0
mirror of https://github.com/systemd/systemd synced 2025-11-22 02:04:45 +01:00

Compare commits

..

6 Commits

Author SHA1 Message Date
Luca Boccassi
463f0a027a Revert "Bump required minimum version of libfido2 to 1.5.0" and add missing def instead
It helps nobody to break compatibility for a missing definition
for printing an error.
Just add the missing definition if not present, as it is already
done for thousands of others from the kernel, glibc, etc.

This partially reverts commit d8b60944f5f752a06ad1553ca77b04b7fea903e9.
2025-09-27 15:46:13 +02:00
Daan De Meyer
d15343d561
ethtool-util: several cleanups for applying link settings (#38879) 2025-09-27 14:31:11 +02:00
Yu Watanabe
f6e9e1e304 ethtool-util: drop use of union ethtool_link_usettings
Previously, we shift arrays on read and then shift back on write.
It is inefficient and not necessary.
Let's directly use the buffer that kernel provides as is.
2025-09-26 19:45:58 +09:00
Yu Watanabe
f8606bc54e ethtool-util: fix comment
The very initial implementation sets cmd with zero when the bitmap
length does not match. But, it is fixed by
793cf87de9

Fortunately, our code does not follow the outdated comment, but checks
cmd field correctly.
2025-09-26 19:45:58 +09:00
Yu Watanabe
8a4929c4e4 ethtool-util: rename functions and update log messages 2025-09-26 19:45:58 +09:00
Yu Watanabe
5505c528b9 ethtool-util: drop use of deprecated ETHTOOL_GSET and ETHTOOL_SSET
The methods are deprecated since kernel v4.20,
9b30049535
and they are trivial wrapper of ETHTOOL_GLINKSETTINGS and ETHTOOL_SLINKSETTINGS,
respectively. Hence, the fallback logic is nowadays completely
meaningless. Let's drop them.
2025-09-26 19:45:58 +09:00
6 changed files with 56 additions and 169 deletions

2
README
View File

@ -245,7 +245,7 @@ REQUIREMENTS:
gnutls >= 3.1.4 (optional) gnutls >= 3.1.4 (optional)
openssl >= 1.1.0 (optional, required to support DNS-over-TLS) openssl >= 1.1.0 (optional, required to support DNS-over-TLS)
p11-kit >= 0.23.3 (optional) p11-kit >= 0.23.3 (optional)
libfido2 >= 1.5.0 (optional) libfido2 (optional)
tpm2-tss (optional) tpm2-tss (optional)
elfutils >= 158 (optional) elfutils >= 158 (optional)
polkit (optional) polkit (optional)

View File

@ -1354,7 +1354,6 @@ feature = get_option('libfido2').require(
conf.get('HAVE_OPENSSL') == 1, conf.get('HAVE_OPENSSL') == 1,
error_message : 'openssl required') error_message : 'openssl required')
libfido2 = dependency('libfido2', libfido2 = dependency('libfido2',
version : '>=1.5.0',
required : feature) required : feature)
conf.set10('HAVE_LIBFIDO2', libfido2.found()) conf.set10('HAVE_LIBFIDO2', libfido2.found())

View File

@ -652,150 +652,51 @@ int ethtool_set_features(int *ethtool_fd, const char *ifname, const int features
return 0; return 0;
} }
static int get_glinksettings(int fd, struct ifreq *ifr, union ethtool_link_usettings **ret) { static int get_link_settings(int fd, struct ifreq *ifr, struct ethtool_link_settings **ret) {
union ethtool_link_usettings ecmd = { struct ethtool_link_settings ecmd = {
.base.cmd = ETHTOOL_GLINKSETTINGS, .cmd = ETHTOOL_GLINKSETTINGS,
}; };
assert(fd >= 0); assert(fd >= 0);
assert(ifr); assert(ifr);
assert(ret); assert(ret);
/* The interaction user/kernel via the new API requires a small ETHTOOL_GLINKSETTINGS /* The interaction user/kernel via the new API requires a small ETHTOOL_GLINKSETTINGS handshake first
handshake first to agree on the length of the link mode bitmaps. If kernel doesn't * to agree on the length of the link mode bitmaps. If kernel doesn't agree with user, it returns the
agree with user, it returns the bitmap length it is expecting from user as a negative * bitmap length it is expecting from user as a negative length. When kernel and user agree, kernel
length (and cmd field is 0). When kernel and user agree, kernel returns valid info in * returns valid info in all fields (with bitmap length > 0).
all fields (ie. link mode length > 0 and cmd is ETHTOOL_GLINKSETTINGS). Based on * https://github.com/torvalds/linux/commit/3f1ac7a700d039c61d8d8b99f28d605d489a60cf
https://github.com/torvalds/linux/commit/3f1ac7a700d039c61d8d8b99f28d605d489a60cf * https://github.com/torvalds/linux/commit/793cf87de9d1a62dc9079c3ec5fcc01cfc62fafb */
*/
ifr->ifr_data = (void*) &ecmd; ifr->ifr_data = &ecmd;
if (ioctl(fd, SIOCETHTOOL, ifr) < 0) if (ioctl(fd, SIOCETHTOOL, ifr) < 0)
return -errno; return -errno;
if (ecmd.base.link_mode_masks_nwords >= 0 || ecmd.base.cmd != ETHTOOL_GLINKSETTINGS) if (ecmd.link_mode_masks_nwords >= 0 || ecmd.cmd != ETHTOOL_GLINKSETTINGS)
return -EOPNOTSUPP; return -EOPNOTSUPP;
ecmd.base.link_mode_masks_nwords = -ecmd.base.link_mode_masks_nwords; int8_t n = -ecmd.link_mode_masks_nwords;
size_t sz = offsetof(struct ethtool_link_settings, link_mode_masks) + sizeof(uint32_t) * n * 3;
ifr->ifr_data = (void *) &ecmd; _cleanup_free_ struct ethtool_link_settings *settings = calloc(sz, 1);
if (!settings)
if (ioctl(fd, SIOCETHTOOL, ifr) < 0)
return -errno;
if (ecmd.base.link_mode_masks_nwords <= 0 || ecmd.base.cmd != ETHTOOL_GLINKSETTINGS)
return -EOPNOTSUPP;
union ethtool_link_usettings *u = new0(union ethtool_link_usettings, 1);
if (!u)
return -ENOMEM; return -ENOMEM;
u->base = ecmd.base; settings->cmd = ETHTOOL_GLINKSETTINGS;
settings->link_mode_masks_nwords = n;
uint32_t *p = ecmd.base.link_mode_masks; ifr->ifr_data = settings;
memcpy(u->link_modes.supported, p, sizeof(uint32_t) * ecmd.base.link_mode_masks_nwords); if (ioctl(fd, SIOCETHTOOL, ifr) < 0)
p += ecmd.base.link_mode_masks_nwords; return -errno;
memcpy(u->link_modes.advertising, p, sizeof(uint32_t) * ecmd.base.link_mode_masks_nwords);
p += ecmd.base.link_mode_masks_nwords;
memcpy(u->link_modes.lp_advertising, p, sizeof(uint32_t) * ecmd.base.link_mode_masks_nwords);
*ret = u; if (settings->link_mode_masks_nwords != n || settings->cmd != ETHTOOL_GLINKSETTINGS)
return -EOPNOTSUPP;
*ret = TAKE_PTR(settings);
return 0; return 0;
} }
static int get_gset(int fd, struct ifreq *ifr, union ethtool_link_usettings **ret) { int ethtool_set_link_settings(
struct ethtool_cmd ecmd = {
.cmd = ETHTOOL_GSET,
};
assert(fd >= 0);
assert(ifr);
assert(ret);
ifr->ifr_data = (void *) &ecmd;
if (ioctl(fd, SIOCETHTOOL, ifr) < 0)
return -errno;
union ethtool_link_usettings *u = new(union ethtool_link_usettings, 1);
if (!u)
return -ENOMEM;
*u = (union ethtool_link_usettings) {
.base.cmd = ETHTOOL_GSET,
.base.link_mode_masks_nwords = 1,
.base.speed = ethtool_cmd_speed(&ecmd),
.base.duplex = ecmd.duplex,
.base.port = ecmd.port,
.base.phy_address = ecmd.phy_address,
.base.autoneg = ecmd.autoneg,
.base.mdio_support = ecmd.mdio_support,
.base.eth_tp_mdix = ecmd.eth_tp_mdix,
.base.eth_tp_mdix_ctrl = ecmd.eth_tp_mdix_ctrl,
};
u->link_modes.supported[0] = ecmd.supported;
u->link_modes.advertising[0] = ecmd.advertising;
u->link_modes.lp_advertising[0] = ecmd.lp_advertising;
*ret = u;
return 0;
}
static int set_slinksettings(int fd, struct ifreq *ifr, const union ethtool_link_usettings *u) {
assert(fd >= 0);
assert(ifr);
assert(u);
if (u->base.cmd != ETHTOOL_GLINKSETTINGS || u->base.link_mode_masks_nwords <= 0)
return -EINVAL;
union ethtool_link_usettings ecmd = { .base = u->base };
ecmd.base.cmd = ETHTOOL_SLINKSETTINGS;
uint32_t *p = ecmd.base.link_mode_masks;
p = mempcpy(p, u->link_modes.supported, sizeof(uint32_t) * ecmd.base.link_mode_masks_nwords);
p = mempcpy(p, u->link_modes.advertising, sizeof(uint32_t) * ecmd.base.link_mode_masks_nwords);
memcpy(p, u->link_modes.lp_advertising, sizeof(uint32_t) * ecmd.base.link_mode_masks_nwords);
ifr->ifr_data = (void *) &ecmd;
return RET_NERRNO(ioctl(fd, SIOCETHTOOL, ifr));
}
static int set_sset(int fd, struct ifreq *ifr, const union ethtool_link_usettings *u) {
struct ethtool_cmd ecmd = {
.cmd = ETHTOOL_SSET,
};
assert(fd >= 0);
assert(ifr);
assert(u);
if (u->base.cmd != ETHTOOL_GSET || u->base.link_mode_masks_nwords <= 0)
return -EINVAL;
ecmd.supported = u->link_modes.supported[0];
ecmd.advertising = u->link_modes.advertising[0];
ecmd.lp_advertising = u->link_modes.lp_advertising[0];
ethtool_cmd_speed_set(&ecmd, u->base.speed);
ecmd.duplex = u->base.duplex;
ecmd.port = u->base.port;
ecmd.phy_address = u->base.phy_address;
ecmd.autoneg = u->base.autoneg;
ecmd.mdio_support = u->base.mdio_support;
ecmd.eth_tp_mdix = u->base.eth_tp_mdix;
ecmd.eth_tp_mdix_ctrl = u->base.eth_tp_mdix_ctrl;
ifr->ifr_data = (void *) &ecmd;
return RET_NERRNO(ioctl(fd, SIOCETHTOOL, ifr));
}
int ethtool_set_glinksettings(
int *fd, int *fd,
const char *ifname, const char *ifname,
int autonegotiation, int autonegotiation,
@ -805,7 +706,7 @@ int ethtool_set_glinksettings(
NetDevPort port, NetDevPort port,
uint8_t mdi) { uint8_t mdi) {
_cleanup_free_ union ethtool_link_usettings *u = NULL; _cleanup_free_ struct ethtool_link_settings *settings = NULL;
struct ifreq ifr = {}; struct ifreq ifr = {};
bool changed = false; bool changed = false;
int r; int r;
@ -842,53 +743,50 @@ int ethtool_set_glinksettings(
strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname); strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname);
r = get_glinksettings(*fd, &ifr, &u); r = get_link_settings(*fd, &ifr, &settings);
if (r < 0) {
r = get_gset(*fd, &ifr, &u);
if (r < 0) if (r < 0)
return log_debug_errno(r, "ethtool: Cannot get device settings for %s: %m", ifname); return log_debug_errno(r, "ethtool: Cannot get link settings for %s: %m", ifname);
}
if (speed > 0) if (speed > 0)
UPDATE(u->base.speed, DIV_ROUND_UP(speed, 1000000), changed); UPDATE(settings->speed, DIV_ROUND_UP(speed, 1000000), changed);
if (duplex >= 0) if (duplex >= 0)
UPDATE(u->base.duplex, duplex, changed); UPDATE(settings->duplex, duplex, changed);
if (port >= 0) if (port >= 0)
UPDATE(u->base.port, port, changed); UPDATE(settings->port, port, changed);
if (autonegotiation >= 0) if (autonegotiation >= 0)
UPDATE(u->base.autoneg, autonegotiation, changed); UPDATE(settings->autoneg, autonegotiation, changed);
if (!memeqzero(advertise, sizeof(uint32_t) * N_ADVERTISE)) { if (!memeqzero(advertise, sizeof(uint32_t) * N_ADVERTISE)) {
UPDATE(u->base.autoneg, AUTONEG_ENABLE, changed); UPDATE(settings->autoneg, AUTONEG_ENABLE, changed);
uint32_t *a = settings->link_mode_masks + settings->link_mode_masks_nwords;
size_t n = MIN(settings->link_mode_masks_nwords, N_ADVERTISE);
changed = changed || changed = changed ||
memcmp(&u->link_modes.advertising, advertise, sizeof(uint32_t) * N_ADVERTISE) != 0 || memcmp(a, advertise, sizeof(uint32_t) * n) != 0 ||
!memeqzero((uint8_t*) &u->link_modes.advertising + sizeof(uint32_t) * N_ADVERTISE, !memeqzero(a + n, sizeof(uint32_t) * (settings->link_mode_masks_nwords - n));
ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NBYTES - sizeof(uint32_t) * N_ADVERTISE);
memcpy(&u->link_modes.advertising, advertise, sizeof(uint32_t) * N_ADVERTISE); memcpy(a, advertise, sizeof(uint32_t) * n);
memzero((uint8_t*) &u->link_modes.advertising + sizeof(uint32_t) * N_ADVERTISE, memzero(a + n, sizeof(uint32_t) * (settings->link_mode_masks_nwords - n));
ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NBYTES - sizeof(uint32_t) * N_ADVERTISE);
} }
if (mdi != ETH_TP_MDI_INVALID) { if (mdi != ETH_TP_MDI_INVALID) {
if (u->base.eth_tp_mdix_ctrl == ETH_TP_MDI_INVALID) if (settings->eth_tp_mdix_ctrl == ETH_TP_MDI_INVALID)
log_debug("ethtool: setting MDI not supported for %s, ignoring.", ifname); log_debug("ethtool: setting MDI not supported for %s, ignoring.", ifname);
else else
UPDATE(u->base.eth_tp_mdix_ctrl, mdi, changed); UPDATE(settings->eth_tp_mdix_ctrl, mdi, changed);
} }
if (!changed) if (!changed)
return 0; return 0;
if (u->base.cmd == ETHTOOL_GLINKSETTINGS) settings->cmd = ETHTOOL_SLINKSETTINGS;
r = set_slinksettings(*fd, &ifr, u); ifr.ifr_data = settings;
else if (ioctl(*fd, SIOCETHTOOL, &ifr) < 0)
r = set_sset(*fd, &ifr, u); return log_debug_errno(errno, "ethtool: Cannot set link settings for %s: %m", ifname);
if (r < 0)
return log_debug_errno(r, "ethtool: Cannot set device settings for %s: %m", ifname);
return r; return r;
} }

View File

@ -100,21 +100,6 @@ typedef enum NetDevPort {
_NET_DEV_PORT_INVALID = -EINVAL, _NET_DEV_PORT_INVALID = -EINVAL,
} NetDevPort; } NetDevPort;
#define ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32 (SCHAR_MAX)
#define ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NBYTES (4 * ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32)
/* layout of the struct passed from/to userland */
union ethtool_link_usettings {
struct ethtool_link_settings base;
struct {
uint8_t header[offsetof(struct ethtool_link_settings, link_mode_masks)];
uint32_t supported[ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32];
uint32_t advertising[ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32];
uint32_t lp_advertising[ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32];
} link_modes;
};
typedef struct u32_opt { typedef struct u32_opt {
uint32_t value; /* a value of 0 indicates the hardware advertised maximum should be used. */ uint32_t value; /* a value of 0 indicates the hardware advertised maximum should be used. */
bool set; bool set;
@ -167,7 +152,7 @@ int ethtool_get_permanent_hw_addr(int *ethtool_fd, const char *ifname, struct hw
int ethtool_set_wol(int *ethtool_fd, const char *ifname, uint32_t wolopts, const uint8_t password[SOPASS_MAX]); int ethtool_set_wol(int *ethtool_fd, const char *ifname, uint32_t wolopts, const uint8_t password[SOPASS_MAX]);
int ethtool_set_nic_buffer_size(int *ethtool_fd, const char *ifname, const netdev_ring_param *ring); int ethtool_set_nic_buffer_size(int *ethtool_fd, const char *ifname, const netdev_ring_param *ring);
int ethtool_set_features(int *ethtool_fd, const char *ifname, const int features[static _NET_DEV_FEAT_MAX]); int ethtool_set_features(int *ethtool_fd, const char *ifname, const int features[static _NET_DEV_FEAT_MAX]);
int ethtool_set_glinksettings( int ethtool_set_link_settings(
int *fd, int *fd,
const char *ifname, const char *ifname,
int autonegotiation, int autonegotiation,

View File

@ -16,6 +16,11 @@
#include "strv.h" #include "strv.h"
#include "unistd.h" #include "unistd.h"
/* Added in version 1.5.0 */
#ifndef FIDO_ERR_UV_BLOCKED
#define FIDO_ERR_UV_BLOCKED 0x3c
#endif
static void *libfido2_dl = NULL; static void *libfido2_dl = NULL;
DLSYM_PROTOTYPE(fido_assert_allow_cred) = NULL; DLSYM_PROTOTYPE(fido_assert_allow_cred) = NULL;

View File

@ -491,7 +491,7 @@ static int link_apply_ethtool_settings(Link *link, int *ethtool_fd) {
return 0; return 0;
} }
r = ethtool_set_glinksettings(ethtool_fd, name, r = ethtool_set_link_settings(ethtool_fd, name,
config->autonegotiation, config->advertise, config->autonegotiation, config->advertise,
config->speed, config->duplex, config->port, config->mdi); config->speed, config->duplex, config->port, config->mdi);
if (r < 0) { if (r < 0) {