From 9bd3ecdd8d6664dc716ae04b4e0ef3b2627eecf0 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 6 Oct 2021 21:49:39 +0900 Subject: [PATCH] ethtool-util: make ethtool_set_wol() take password --- src/shared/ethtool-util.c | 37 ++++++++++++++++++++++++++++++++----- src/shared/ethtool-util.h | 2 +- src/udev/net/link-config.c | 2 +- 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/src/shared/ethtool-util.c b/src/shared/ethtool-util.c index 618ec8d2c35..ee7be4635fa 100644 --- a/src/shared/ethtool-util.c +++ b/src/shared/ethtool-util.c @@ -400,7 +400,12 @@ int ethtool_get_permanent_macaddr(int *ethtool_fd, const char *ifname, struct et 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, }; @@ -413,7 +418,8 @@ int ethtool_set_wol(int *ethtool_fd, const char *ifname, uint32_t wolopts) { 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); @@ -425,6 +431,14 @@ int ethtool_set_wol(int *ethtool_fd, const char *ifname, uint32_t wolopts) { 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; @@ -435,16 +449,29 @@ int ethtool_set_wol(int *ethtool_fd, const char *ifname, uint32_t wolopts) { 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) { diff --git a/src/shared/ethtool-util.h b/src/shared/ethtool-util.h index cc065589317..c57ff1a2b5a 100644 --- a/src/shared/ethtool-util.h +++ b/src/shared/ethtool-util.h @@ -164,7 +164,7 @@ int ethtool_get_link_info(int *ethtool_fd, const char *ifname, 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, diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c index ca0522c3042..4802a0bf3ee 100644 --- a/src/udev/net/link-config.c +++ b/src/udev/net/link-config.c @@ -329,7 +329,7 @@ static int link_config_apply_ethtool_settings(int *ethtool_fd, const LinkConfig port_to_string(config->port)); } - r = ethtool_set_wol(ethtool_fd, name, config->wol); + r = ethtool_set_wol(ethtool_fd, name, config->wol, NULL); if (r < 0) { _cleanup_free_ char *str = NULL;