dest = _v; \
} while(false)
-int ethtool_set_wol(int *ethtool_fd, const char *ifname, uint32_t wolopts) {
+int ethtool_set_wol(
+ int *ethtool_fd,
+ const char *ifname,
+ uint32_t wolopts,
+ const uint8_t password[SOPASS_MAX]) {
+
struct ethtool_wolinfo ecmd = {
.cmd = ETHTOOL_GWOL,
};
assert(ethtool_fd);
assert(ifname);
- if (wolopts == UINT32_MAX)
+ if (wolopts == UINT32_MAX && !password)
+ /* Nothing requested. Return earlier. */
return 0;
r = ethtool_connect(ethtool_fd);
if (ioctl(*ethtool_fd, SIOCETHTOOL, &ifr) < 0)
return -errno;
+ if (wolopts == UINT32_MAX) {
+ /* When password is specified without valid WoL options specified, then enable
+ * WAKE_MAGICSECURE flag if supported. */
+ wolopts = ecmd.wolopts;
+ if (password && FLAGS_SET(ecmd.supported, WAKE_MAGICSECURE))
+ wolopts |= WAKE_MAGICSECURE;
+ }
+
if ((wolopts & ~ecmd.supported) != 0) {
_cleanup_free_ char *str = NULL;
wolopts &= ecmd.supported;
}
+ if (!FLAGS_SET(wolopts, WAKE_MAGICSECURE))
+ /* When WAKE_MAGICSECURE flag is not set, then ignore password. */
+ password = NULL;
+
UPDATE(ecmd.wolopts, wolopts, need_update);
+ if (password &&
+ memcmp(ecmd.sopass, password, sizeof(ecmd.sopass)) != 0) {
+ memcpy(ecmd.sopass, password, sizeof(ecmd.sopass));
+ need_update = true;
+ }
- if (!need_update)
+ if (!need_update) {
+ explicit_bzero_safe(&ecmd, sizeof(ecmd));
return 0;
+ }
+ r = 0;
ecmd.cmd = ETHTOOL_SWOL;
if (ioctl(*ethtool_fd, SIOCETHTOOL, &ifr) < 0)
- return -errno;
+ r = -errno;
- return 0;
+ explicit_bzero_safe(&ecmd, sizeof(ecmd));
+ return r;
}
int ethtool_set_nic_buffer_size(int *ethtool_fd, const char *ifname, const netdev_ring_param *ring) {
int *ret_autonegotiation, uint64_t *ret_speed,
Duplex *ret_duplex, NetDevPort *ret_port);
int ethtool_get_permanent_macaddr(int *ethtool_fd, const char *ifname, struct ether_addr *ret);
-int ethtool_set_wol(int *ethtool_fd, const char *ifname, uint32_t wolopts);
+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_features(int *ethtool_fd, const char *ifname, const int features[static _NET_DEV_FEAT_MAX]);
int ethtool_set_glinksettings(int *ethtool_fd, const char *ifname,