diff --git a/src/shared/ethtool-util.c b/src/shared/ethtool-util.c index 3119b2b92e3..e10948d6125 100644 --- a/src/shared/ethtool-util.c +++ b/src/shared/ethtool-util.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include "conf-parser.h" @@ -217,6 +218,46 @@ int ethtool_get_link_info(int *fd, const char *ifname, return 0; } +int ethtool_get_permanent_macaddr(int *fd, const char *ifname, struct ether_addr *ret) { + _cleanup_free_ struct ethtool_perm_addr *epaddr = NULL; + struct ifreq ifr; + int r; + + assert(fd); + assert(ifname); + assert(ret); + + if (*fd < 0) { + r = ethtool_connect_or_warn(fd, false); + if (r < 0) + return r; + } + + epaddr = malloc(offsetof(struct ethtool_perm_addr, data) + MAX_ADDR_LEN); + if (!epaddr) + return -ENOMEM; + + epaddr->cmd = ETHTOOL_GPERMADDR; + epaddr->size = MAX_ADDR_LEN; + + ifr = (struct ifreq) { + .ifr_data = (caddr_t) epaddr, + }; + strscpy(ifr.ifr_name, IFNAMSIZ, ifname); + + r = ioctl(*fd, SIOCETHTOOL, &ifr); + if (r < 0) + return -errno; + + if (epaddr->size != 6) + return -EOPNOTSUPP; + + for (size_t i = 0; i < epaddr->size; i++) + ret->ether_addr_octet[i] = epaddr->data[i]; + + return 0; +} + int ethtool_set_speed(int *fd, const char *ifname, unsigned speed, Duplex duplex) { struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET diff --git a/src/shared/ethtool-util.h b/src/shared/ethtool-util.h index d408bcd90a0..80bfffd6e94 100644 --- a/src/shared/ethtool-util.h +++ b/src/shared/ethtool-util.h @@ -2,6 +2,7 @@ #pragma once #include +#include #include #include "conf-parser.h" @@ -91,6 +92,7 @@ int ethtool_get_driver(int *fd, const char *ifname, char **ret); int ethtool_get_link_info(int *fd, const char *ifname, int *ret_autonegotiation, size_t *ret_speed, Duplex *ret_duplex, NetDevPort *ret_port); +int ethtool_get_permanent_macaddr(int *fd, const char *ifname, struct ether_addr *ret); int ethtool_set_speed(int *fd, const char *ifname, unsigned speed, Duplex duplex); int ethtool_set_wol(int *fd, const char *ifname, WakeOnLan wol); int ethtool_set_nic_buffer_size(int *fd, const char *ifname, netdev_ring_param *ring);