mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 00:14:32 +09:00
ethtool-util: fix setting advertising link modes
Fixes a regression caused by d307410327.
The link_mode_masks flex array in struct ethtool_link_settings contains
three packed arrays, and the length of each array is given by
link_mode_masks_nwords field:
```
__u32 link_mode_masks[];
/* layout of link_mode_masks fields:
* __u32 map_supported[link_mode_masks_nwords];
* __u32 map_advertising[link_mode_masks_nwords];
* __u32 map_lp_advertising[link_mode_masks_nwords];
*/
```
Hence, we cannot use the received data as is through the union, but need
to shift the array to make each map accessible through the union.
This commit is contained in:
committed by
Daan De Meyer
parent
b10619484d
commit
d8af104fb0
@@ -687,10 +687,19 @@ static int get_glinksettings(int fd, struct ifreq *ifr, union ethtool_link_usett
|
||||
if (ecmd.base.link_mode_masks_nwords <= 0 || ecmd.base.cmd != ETHTOOL_GLINKSETTINGS)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
union ethtool_link_usettings *u = newdup(union ethtool_link_usettings, &ecmd, 1);
|
||||
union ethtool_link_usettings *u = new0(union ethtool_link_usettings, 1);
|
||||
if (!u)
|
||||
return -ENOMEM;
|
||||
|
||||
u->base = ecmd.base;
|
||||
|
||||
uint32_t *p = ecmd.base.link_mode_masks;
|
||||
memcpy(u->link_modes.supported, p, sizeof(uint32_t) * ecmd.base.link_mode_masks_nwords);
|
||||
p += ecmd.base.link_mode_masks_nwords;
|
||||
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;
|
||||
return 0;
|
||||
}
|
||||
@@ -742,8 +751,14 @@ static int set_slinksettings(int fd, struct ifreq *ifr, const union ethtool_link
|
||||
if (u->base.cmd != ETHTOOL_GLINKSETTINGS || u->base.link_mode_masks_nwords <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
union ethtool_link_usettings ecmd = *u;
|
||||
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));
|
||||
|
||||
Reference in New Issue
Block a user