ethtool-util.c revision 61f3af4fed2f0d2686bd7ae4cd22bc3e973ddeca
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering/***
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering This file is part of systemd.
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering systemd is free software; you can redistribute it and/or modify it
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering under the terms of the GNU Lesser General Public License as published by
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering (at your option) any later version.
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering systemd is distributed in the hope that it will be useful, but
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering Lesser General Public License for more details.
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering You should have received a copy of the GNU Lesser General Public License
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering***/
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering
dc3a1b76a6a6f9dfe9b451f534587251b50a0685Lennart Poettering#include <sys/ioctl.h>
dc3a1b76a6a6f9dfe9b451f534587251b50a0685Lennart Poettering#include <net/if.h>
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering#include <linux/ethtool.h>
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering#include <linux/sockios.h>
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering#include "ethtool-util.h"
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering#include "strxcpyx.h"
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering#include "util.h"
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering#include "log.h"
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering#include "conf-parser.h"
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poetteringstatic const char* const duplex_table[] = {
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering [DUP_FULL] = "full",
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering [DUP_HALF] = "half"
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering};
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart PoetteringDEFINE_STRING_TABLE_LOOKUP(duplex, Duplex);
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart PoetteringDEFINE_CONFIG_PARSE_ENUM(config_parse_duplex, duplex, Duplex, "Failed to parse duplex setting");
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poetteringstatic const char* const wol_table[] = {
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering [WOL_PHY] = "phy",
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering [WOL_MAGIC] = "magic",
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering [WOL_OFF] = "off"
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering};
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart PoetteringDEFINE_STRING_TABLE_LOOKUP(wol, WakeOnLan);
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart PoetteringDEFINE_CONFIG_PARSE_ENUM(config_parse_wol, wol, WakeOnLan, "Failed to parse WakeOnLan setting");
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poetteringint ethtool_connect(int *ret) {
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering int fd;
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering assert_return(ret, -EINVAL);
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering fd = socket(PF_INET, SOCK_DGRAM, 0);
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering if (fd < 0) {
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering return -errno;
af9792ac7f39354f80e9006c42c2400c5e41c447Lennart Poettering }
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering *ret = fd;
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering
af9792ac7f39354f80e9006c42c2400c5e41c447Lennart Poettering return 0;
af9792ac7f39354f80e9006c42c2400c5e41c447Lennart Poettering}
af9792ac7f39354f80e9006c42c2400c5e41c447Lennart Poettering
af9792ac7f39354f80e9006c42c2400c5e41c447Lennart Poetteringint ethtool_get_driver(int fd, const char *ifname, char **ret) {
af9792ac7f39354f80e9006c42c2400c5e41c447Lennart Poettering struct ethtool_drvinfo ecmd = {
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering .cmd = ETHTOOL_GDRVINFO
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering };
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering struct ifreq ifr = {
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering .ifr_data = (void*) &ecmd
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering };
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering char *d;
dc3a1b76a6a6f9dfe9b451f534587251b50a0685Lennart Poettering int r;
dc3a1b76a6a6f9dfe9b451f534587251b50a0685Lennart Poettering
dc3a1b76a6a6f9dfe9b451f534587251b50a0685Lennart Poettering strscpy(ifr.ifr_name, IFNAMSIZ, ifname);
dc3a1b76a6a6f9dfe9b451f534587251b50a0685Lennart Poettering
dc3a1b76a6a6f9dfe9b451f534587251b50a0685Lennart Poettering r = ioctl(fd, SIOCETHTOOL, &ifr);
dc3a1b76a6a6f9dfe9b451f534587251b50a0685Lennart Poettering if (r < 0)
dc3a1b76a6a6f9dfe9b451f534587251b50a0685Lennart Poettering return -errno;
dc3a1b76a6a6f9dfe9b451f534587251b50a0685Lennart Poettering
af9792ac7f39354f80e9006c42c2400c5e41c447Lennart Poettering d = strdup(ecmd.driver);
af9792ac7f39354f80e9006c42c2400c5e41c447Lennart Poettering if (!d)
dc3a1b76a6a6f9dfe9b451f534587251b50a0685Lennart Poettering return -ENOMEM;
dc3a1b76a6a6f9dfe9b451f534587251b50a0685Lennart Poettering
dc3a1b76a6a6f9dfe9b451f534587251b50a0685Lennart Poettering *ret = d;
dc3a1b76a6a6f9dfe9b451f534587251b50a0685Lennart Poettering return 0;
dc3a1b76a6a6f9dfe9b451f534587251b50a0685Lennart Poettering}
dc3a1b76a6a6f9dfe9b451f534587251b50a0685Lennart Poettering
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poetteringint ethtool_set_speed(int fd, const char *ifname, unsigned int speed, Duplex duplex)
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering{
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering struct ifreq ifr;
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering struct ethtool_cmd ecmd;
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering bool need_update = false;
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering int r;
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering if (speed == 0 && duplex == _DUP_INVALID)
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering return 0;
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering zero(ecmd);
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering ecmd.cmd = ETHTOOL_GSET;
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering zero(ifr);
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering strscpy(ifr.ifr_name, IFNAMSIZ, ifname);
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering ifr.ifr_data = (void *)&ecmd;
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering r = ioctl(fd, SIOCETHTOOL, &ifr);
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering if (r < 0)
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering return -errno;
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering if (ethtool_cmd_speed(&ecmd) != speed) {
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering ethtool_cmd_speed_set(&ecmd, speed);
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering need_update = true;
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering }
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering switch (duplex) {
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering case DUP_HALF:
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering if (ecmd.duplex != DUPLEX_HALF) {
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering ecmd.duplex = DUPLEX_HALF;
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering need_update = true;
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering }
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering break;
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering case DUP_FULL:
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering if (ecmd.duplex != DUPLEX_FULL) {
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering ecmd.duplex = DUPLEX_FULL;
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering need_update = true;
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering }
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering break;
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering default:
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering break;
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering }
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering if (need_update) {
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering ecmd.cmd = ETHTOOL_SSET;
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering r = ioctl(fd, SIOCETHTOOL, &ifr);
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering if (r < 0)
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering return -errno;
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering }
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering return 0;
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering}
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poetteringint ethtool_set_wol(int fd, const char *ifname, WakeOnLan wol) {
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering struct ifreq ifr;
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering struct ethtool_wolinfo ecmd;
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering bool need_update = false;
23406ce58aa7142e8df3c5c9e5ac34a01e90e3e0Lennart Poettering int r;
if (wol == _WOL_INVALID)
return 0;
zero(ecmd);
ecmd.cmd = ETHTOOL_GWOL;
zero(ifr);
strscpy(ifr.ifr_name, IFNAMSIZ, ifname);
ifr.ifr_data = (void *)&ecmd;
r = ioctl(fd, SIOCETHTOOL, &ifr);
if (r < 0)
return -errno;
switch (wol) {
case WOL_PHY:
if (ecmd.wolopts != WAKE_PHY) {
ecmd.wolopts = WAKE_PHY;
need_update = true;
}
break;
case WOL_MAGIC:
if (ecmd.wolopts != WAKE_MAGIC) {
ecmd.wolopts = WAKE_MAGIC;
need_update = true;
}
break;
case WOL_OFF:
if (ecmd.wolopts != 0) {
ecmd.wolopts = 0;
need_update = true;
}
break;
default:
break;
}
if (need_update) {
ecmd.cmd = ETHTOOL_SWOL;
r = ioctl(fd, SIOCETHTOOL, &ifr);
if (r < 0)
return -errno;
}
return 0;
}