Skip to content

Commit d8af104

Browse files
yuwataDaanDeMeyer
authored andcommitted
ethtool-util: fix setting advertising link modes
Fixes a regression caused by d307410. 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.
1 parent b106194 commit d8af104

File tree

1 file changed

+17
-2
lines changed

1 file changed

+17
-2
lines changed

src/shared/ethtool-util.c

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -687,10 +687,19 @@ static int get_glinksettings(int fd, struct ifreq *ifr, union ethtool_link_usett
687687
if (ecmd.base.link_mode_masks_nwords <= 0 || ecmd.base.cmd != ETHTOOL_GLINKSETTINGS)
688688
return -EOPNOTSUPP;
689689

690-
union ethtool_link_usettings *u = newdup(union ethtool_link_usettings, &ecmd, 1);
690+
union ethtool_link_usettings *u = new0(union ethtool_link_usettings, 1);
691691
if (!u)
692692
return -ENOMEM;
693693

694+
u->base = ecmd.base;
695+
696+
uint32_t *p = ecmd.base.link_mode_masks;
697+
memcpy(u->link_modes.supported, p, sizeof(uint32_t) * ecmd.base.link_mode_masks_nwords);
698+
p += ecmd.base.link_mode_masks_nwords;
699+
memcpy(u->link_modes.advertising, p, sizeof(uint32_t) * ecmd.base.link_mode_masks_nwords);
700+
p += ecmd.base.link_mode_masks_nwords;
701+
memcpy(u->link_modes.lp_advertising, p, sizeof(uint32_t) * ecmd.base.link_mode_masks_nwords);
702+
694703
*ret = u;
695704
return 0;
696705
}
@@ -742,8 +751,14 @@ static int set_slinksettings(int fd, struct ifreq *ifr, const union ethtool_link
742751
if (u->base.cmd != ETHTOOL_GLINKSETTINGS || u->base.link_mode_masks_nwords <= 0)
743752
return -EINVAL;
744753

745-
union ethtool_link_usettings ecmd = *u;
754+
union ethtool_link_usettings ecmd = { .base = u->base };
746755
ecmd.base.cmd = ETHTOOL_SLINKSETTINGS;
756+
757+
uint32_t *p = ecmd.base.link_mode_masks;
758+
p = mempcpy(p, u->link_modes.supported, sizeof(uint32_t) * ecmd.base.link_mode_masks_nwords);
759+
p = mempcpy(p, u->link_modes.advertising, sizeof(uint32_t) * ecmd.base.link_mode_masks_nwords);
760+
memcpy(p, u->link_modes.lp_advertising, sizeof(uint32_t) * ecmd.base.link_mode_masks_nwords);
761+
747762
ifr->ifr_data = (void *) &ecmd;
748763

749764
return RET_NERRNO(ioctl(fd, SIOCETHTOOL, ifr));

0 commit comments

Comments
 (0)