Merge pull request #17555 from yuwata/ethtool-get-driver

ethtool: make ethtool_get_driver() return -ENODATA if driver is an empty string.
This commit is contained in:
Lennart Poettering 2020-11-10 13:15:10 +01:00 committed by GitHub
commit 4165a0590d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -173,14 +173,18 @@ static int ethtool_connect_or_warn(int *ret, bool warn) {
int ethtool_get_driver(int *ethtool_fd, const char *ifname, char **ret) { int ethtool_get_driver(int *ethtool_fd, const char *ifname, char **ret) {
struct ethtool_drvinfo ecmd = { struct ethtool_drvinfo ecmd = {
.cmd = ETHTOOL_GDRVINFO .cmd = ETHTOOL_GDRVINFO,
}; };
struct ifreq ifr = { struct ifreq ifr = {
.ifr_data = (void*) &ecmd .ifr_data = (void*) &ecmd,
}; };
char *d; char *d;
int r; int r;
assert(ethtool_fd);
assert(ifname);
assert(ret);
if (*ethtool_fd < 0) { if (*ethtool_fd < 0) {
r = ethtool_connect_or_warn(ethtool_fd, true); r = ethtool_connect_or_warn(ethtool_fd, true);
if (r < 0) if (r < 0)
@ -193,6 +197,9 @@ int ethtool_get_driver(int *ethtool_fd, const char *ifname, char **ret) {
if (r < 0) if (r < 0)
return -errno; return -errno;
if (isempty(ecmd.driver))
return -ENODATA;
d = strdup(ecmd.driver); d = strdup(ecmd.driver);
if (!d) if (!d)
return -ENOMEM; return -ENOMEM;
@ -201,9 +208,14 @@ int ethtool_get_driver(int *ethtool_fd, const char *ifname, char **ret) {
return 0; return 0;
} }
int ethtool_get_link_info(int *ethtool_fd, const char *ifname, int ethtool_get_link_info(
int *ret_autonegotiation, uint64_t *ret_speed, int *ethtool_fd,
Duplex *ret_duplex, NetDevPort *ret_port) { const char *ifname,
int *ret_autonegotiation,
uint64_t *ret_speed,
Duplex *ret_duplex,
NetDevPort *ret_port) {
struct ethtool_cmd ecmd = { struct ethtool_cmd ecmd = {
.cmd = ETHTOOL_GSET, .cmd = ETHTOOL_GSET,
}; };
@ -212,6 +224,9 @@ int ethtool_get_link_info(int *ethtool_fd, const char *ifname,
}; };
int r; int r;
assert(ethtool_fd);
assert(ifname);
if (*ethtool_fd < 0) { if (*ethtool_fd < 0) {
r = ethtool_connect_or_warn(ethtool_fd, false); r = ethtool_connect_or_warn(ethtool_fd, false);
if (r < 0) if (r < 0)
@ -292,14 +307,17 @@ int ethtool_get_permanent_macaddr(int *ethtool_fd, const char *ifname, struct et
int ethtool_set_speed(int *ethtool_fd, const char *ifname, unsigned speed, Duplex duplex) { int ethtool_set_speed(int *ethtool_fd, const char *ifname, unsigned speed, Duplex duplex) {
struct ethtool_cmd ecmd = { struct ethtool_cmd ecmd = {
.cmd = ETHTOOL_GSET .cmd = ETHTOOL_GSET,
}; };
struct ifreq ifr = { struct ifreq ifr = {
.ifr_data = (void*) &ecmd .ifr_data = (void*) &ecmd,
}; };
bool need_update = false; bool need_update = false;
int r; int r;
assert(ethtool_fd);
assert(ifname);
if (speed == 0 && duplex == _DUP_INVALID) if (speed == 0 && duplex == _DUP_INVALID)
return 0; return 0;
@ -350,14 +368,17 @@ int ethtool_set_speed(int *ethtool_fd, const char *ifname, unsigned speed, Duple
int ethtool_set_wol(int *ethtool_fd, const char *ifname, WakeOnLan wol) { int ethtool_set_wol(int *ethtool_fd, const char *ifname, WakeOnLan wol) {
struct ethtool_wolinfo ecmd = { struct ethtool_wolinfo ecmd = {
.cmd = ETHTOOL_GWOL .cmd = ETHTOOL_GWOL,
}; };
struct ifreq ifr = { struct ifreq ifr = {
.ifr_data = (void*) &ecmd .ifr_data = (void*) &ecmd,
}; };
bool need_update = false; bool need_update = false;
int r; int r;
assert(ethtool_fd);
assert(ifname);
if (wol == _WOL_INVALID) if (wol == _WOL_INVALID)
return 0; return 0;
@ -439,14 +460,18 @@ int ethtool_set_wol(int *ethtool_fd, const char *ifname, WakeOnLan wol) {
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) {
struct ethtool_ringparam ecmd = { struct ethtool_ringparam ecmd = {
.cmd = ETHTOOL_GRINGPARAM .cmd = ETHTOOL_GRINGPARAM,
}; };
struct ifreq ifr = { struct ifreq ifr = {
.ifr_data = (void*) &ecmd .ifr_data = (void*) &ecmd,
}; };
bool need_update = false; bool need_update = false;
int r; int r;
assert(ethtool_fd);
assert(ifname);
assert(ring);
if (*ethtool_fd < 0) { if (*ethtool_fd < 0) {
r = ethtool_connect_or_warn(ethtool_fd, true); r = ethtool_connect_or_warn(ethtool_fd, true);
if (r < 0) if (r < 0)
@ -490,7 +515,7 @@ int ethtool_set_nic_buffer_size(int *ethtool_fd, const char *ifname, const netde
return 0; return 0;
} }
static int get_stringset(int ethtool_fd, struct ifreq *ifr, int stringset_id, struct ethtool_gstrings **gstrings) { static int get_stringset(int ethtool_fd, struct ifreq *ifr, int stringset_id, struct ethtool_gstrings **ret) {
_cleanup_free_ struct ethtool_gstrings *strings = NULL; _cleanup_free_ struct ethtool_gstrings *strings = NULL;
struct { struct {
struct ethtool_sset_info info; struct ethtool_sset_info info;
@ -504,6 +529,10 @@ static int get_stringset(int ethtool_fd, struct ifreq *ifr, int stringset_id, st
unsigned len; unsigned len;
int r; int r;
assert(ethtool_fd >= 0);
assert(ifr);
assert(ret);
ifr->ifr_data = (void *) &buffer.info; ifr->ifr_data = (void *) &buffer.info;
r = ioctl(ethtool_fd, SIOCETHTOOL, ifr); r = ioctl(ethtool_fd, SIOCETHTOOL, ifr);
@ -534,7 +563,7 @@ static int get_stringset(int ethtool_fd, struct ifreq *ifr, int stringset_id, st
if (r < 0) if (r < 0)
return -errno; return -errno;
*gstrings = TAKE_PTR(strings); *ret = TAKE_PTR(strings);
return 0; return 0;
} }
@ -572,6 +601,10 @@ int ethtool_set_features(int *ethtool_fd, const char *ifname, const int *feature
struct ifreq ifr = {}; struct ifreq ifr = {};
int i, r; int i, r;
assert(ethtool_fd);
assert(ifname);
assert(features);
if (*ethtool_fd < 0) { if (*ethtool_fd < 0) {
r = ethtool_connect_or_warn(ethtool_fd, true); r = ethtool_connect_or_warn(ethtool_fd, true);
if (r < 0) if (r < 0)
@ -606,7 +639,7 @@ int ethtool_set_features(int *ethtool_fd, const char *ifname, const int *feature
return 0; return 0;
} }
static int get_glinksettings(int fd, struct ifreq *ifr, struct ethtool_link_usettings **g) { static int get_glinksettings(int fd, struct ifreq *ifr, struct ethtool_link_usettings **ret) {
struct ecmd { struct ecmd {
struct ethtool_link_settings req; struct ethtool_link_settings req;
__u32 link_mode_data[3 * ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32]; __u32 link_mode_data[3 * ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32];
@ -617,6 +650,10 @@ static int get_glinksettings(int fd, struct ifreq *ifr, struct ethtool_link_uset
unsigned offset; unsigned offset;
int r; int r;
assert(fd >= 0);
assert(ifr);
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 to agree on the length of the link mode bitmaps. If kernel doesn't handshake first to agree on the length of the link mode bitmaps. If kernel doesn't
agree with user, it returns the bitmap length it is expecting from user as a negative agree with user, it returns the bitmap length it is expecting from user as a negative
@ -662,18 +699,22 @@ static int get_glinksettings(int fd, struct ifreq *ifr, struct ethtool_link_uset
offset += ecmd.req.link_mode_masks_nwords; offset += ecmd.req.link_mode_masks_nwords;
memcpy(u->link_modes.lp_advertising, &ecmd.link_mode_data[offset], 4 * ecmd.req.link_mode_masks_nwords); memcpy(u->link_modes.lp_advertising, &ecmd.link_mode_data[offset], 4 * ecmd.req.link_mode_masks_nwords);
*g = u; *ret = u;
return 0; return 0;
} }
static int get_gset(int fd, struct ifreq *ifr, struct ethtool_link_usettings **u) { static int get_gset(int fd, struct ifreq *ifr, struct ethtool_link_usettings **ret) {
struct ethtool_link_usettings *e; struct ethtool_link_usettings *e;
struct ethtool_cmd ecmd = { struct ethtool_cmd ecmd = {
.cmd = ETHTOOL_GSET, .cmd = ETHTOOL_GSET,
}; };
int r; int r;
assert(fd >= 0);
assert(ifr);
assert(ret);
ifr->ifr_data = (void *) &ecmd; ifr->ifr_data = (void *) &ecmd;
r = ioctl(fd, SIOCETHTOOL, ifr); r = ioctl(fd, SIOCETHTOOL, ifr);
@ -699,7 +740,7 @@ static int get_gset(int fd, struct ifreq *ifr, struct ethtool_link_usettings **u
.link_modes.lp_advertising[0] = ecmd.lp_advertising, .link_modes.lp_advertising[0] = ecmd.lp_advertising,
}; };
*u = e; *ret = e;
return 0; return 0;
} }
@ -712,6 +753,10 @@ static int set_slinksettings(int fd, struct ifreq *ifr, const struct ethtool_lin
unsigned offset; unsigned offset;
int r; int r;
assert(fd >= 0);
assert(ifr);
assert(u);
if (u->base.cmd != ETHTOOL_GLINKSETTINGS || u->base.link_mode_masks_nwords <= 0) if (u->base.cmd != ETHTOOL_GLINKSETTINGS || u->base.link_mode_masks_nwords <= 0)
return -EINVAL; return -EINVAL;
@ -741,6 +786,10 @@ static int set_sset(int fd, struct ifreq *ifr, const struct ethtool_link_usettin
}; };
int r; int r;
assert(fd >= 0);
assert(ifr);
assert(u);
if (u->base.cmd != ETHTOOL_GSET || u->base.link_mode_masks_nwords <= 0) if (u->base.cmd != ETHTOOL_GSET || u->base.link_mode_masks_nwords <= 0)
return -EINVAL; return -EINVAL;
@ -781,10 +830,13 @@ int ethtool_set_glinksettings(
uint64_t speed, uint64_t speed,
Duplex duplex, Duplex duplex,
NetDevPort port) { NetDevPort port) {
_cleanup_free_ struct ethtool_link_usettings *u = NULL; _cleanup_free_ struct ethtool_link_usettings *u = NULL;
struct ifreq ifr = {}; struct ifreq ifr = {};
int r; int r;
assert(fd);
assert(ifname);
assert(advertise); assert(advertise);
if (autonegotiation != AUTONEG_DISABLE && memeqzero(advertise, sizeof(uint32_t) * N_ADVERTISE)) { if (autonegotiation != AUTONEG_DISABLE && memeqzero(advertise, sizeof(uint32_t) * N_ADVERTISE)) {
@ -838,15 +890,18 @@ int ethtool_set_glinksettings(
int ethtool_set_channels(int *fd, const char *ifname, const netdev_channels *channels) { int ethtool_set_channels(int *fd, const char *ifname, const netdev_channels *channels) {
struct ethtool_channels ecmd = { struct ethtool_channels ecmd = {
.cmd = ETHTOOL_GCHANNELS .cmd = ETHTOOL_GCHANNELS,
}; };
struct ifreq ifr = { struct ifreq ifr = {
.ifr_data = (void*) &ecmd .ifr_data = (void*) &ecmd,
}; };
bool need_update = false; bool need_update = false;
int r; int r;
assert(fd);
assert(ifname);
assert(channels);
if (*fd < 0) { if (*fd < 0) {
r = ethtool_connect_or_warn(fd, true); r = ethtool_connect_or_warn(fd, true);
if (r < 0) if (r < 0)
@ -892,15 +947,17 @@ int ethtool_set_channels(int *fd, const char *ifname, const netdev_channels *cha
int ethtool_set_flow_control(int *fd, const char *ifname, int rx, int tx, int autoneg) { int ethtool_set_flow_control(int *fd, const char *ifname, int rx, int tx, int autoneg) {
struct ethtool_pauseparam ecmd = { struct ethtool_pauseparam ecmd = {
.cmd = ETHTOOL_GPAUSEPARAM .cmd = ETHTOOL_GPAUSEPARAM,
}; };
struct ifreq ifr = { struct ifreq ifr = {
.ifr_data = (void*) &ecmd .ifr_data = (void*) &ecmd,
}; };
bool need_update = false; bool need_update = false;
int r; int r;
assert(fd);
assert(ifname);
if (*fd < 0) { if (*fd < 0) {
r = ethtool_connect_or_warn(fd, true); r = ethtool_connect_or_warn(fd, true);
if (r < 0) if (r < 0)