1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/ioctl.h>
24 #include <linux/ethtool.h>
25 #include <linux/sockios.h>
27 #include "ethtool-util.h"
32 #include "conf-parser.h"
34 static const char* const duplex_table[_DUP_MAX] = {
39 DEFINE_STRING_TABLE_LOOKUP(duplex, Duplex);
40 DEFINE_CONFIG_PARSE_ENUM(config_parse_duplex, duplex, Duplex, "Failed to parse duplex setting");
42 static const char* const wol_table[_WOL_MAX] = {
44 [WOL_MAGIC] = "magic",
48 DEFINE_STRING_TABLE_LOOKUP(wol, WakeOnLan);
49 DEFINE_CONFIG_PARSE_ENUM(config_parse_wol, wol, WakeOnLan, "Failed to parse WakeOnLan setting");
51 int ethtool_connect(int *ret) {
54 assert_return(ret, -EINVAL);
56 fd = socket(PF_INET, SOCK_DGRAM, 0);
66 int ethtool_get_driver(int fd, const char *ifname, char **ret) {
67 struct ethtool_drvinfo ecmd = {
68 .cmd = ETHTOOL_GDRVINFO
71 .ifr_data = (void*) &ecmd
76 strscpy(ifr.ifr_name, IFNAMSIZ, ifname);
78 r = ioctl(fd, SIOCETHTOOL, &ifr);
82 d = strdup(ecmd.driver);
90 int ethtool_set_speed(int fd, const char *ifname, unsigned int speed, Duplex duplex)
92 struct ethtool_cmd ecmd = {
96 .ifr_data = (void*) &ecmd
98 bool need_update = false;
101 if (speed == 0 && duplex == _DUP_INVALID)
104 strscpy(ifr.ifr_name, IFNAMSIZ, ifname);
106 r = ioctl(fd, SIOCETHTOOL, &ifr);
110 if (ethtool_cmd_speed(&ecmd) != speed) {
111 ethtool_cmd_speed_set(&ecmd, speed);
117 if (ecmd.duplex != DUPLEX_HALF) {
118 ecmd.duplex = DUPLEX_HALF;
123 if (ecmd.duplex != DUPLEX_FULL) {
124 ecmd.duplex = DUPLEX_FULL;
133 ecmd.cmd = ETHTOOL_SSET;
135 r = ioctl(fd, SIOCETHTOOL, &ifr);
143 int ethtool_set_wol(int fd, const char *ifname, WakeOnLan wol) {
144 struct ethtool_wolinfo ecmd = {
148 .ifr_data = (void*) &ecmd
150 bool need_update = false;
153 if (wol == _WOL_INVALID)
156 strscpy(ifr.ifr_name, IFNAMSIZ, ifname);
158 r = ioctl(fd, SIOCETHTOOL, &ifr);
164 if (ecmd.wolopts != WAKE_PHY) {
165 ecmd.wolopts = WAKE_PHY;
170 if (ecmd.wolopts != WAKE_MAGIC) {
171 ecmd.wolopts = WAKE_MAGIC;
176 if (ecmd.wolopts != 0) {
186 ecmd.cmd = ETHTOOL_SWOL;
188 r = ioctl(fd, SIOCETHTOOL, &ifr);