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[] = {
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[] = {
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) {
68 struct ethtool_drvinfo ecmd;
72 ecmd.cmd = ETHTOOL_GDRVINFO;
75 strscpy(ifr.ifr_name, IFNAMSIZ, ifname);
76 ifr.ifr_data = (void *)&ecmd;
78 r = ioctl(fd, SIOCETHTOOL, &ifr);
82 *ret = strdup(ecmd.driver);
89 int ethtool_set_speed(int fd, const char *ifname, unsigned int speed, Duplex duplex)
92 struct ethtool_cmd ecmd;
93 bool need_update = false;
96 if (speed == 0 && duplex == _DUP_INVALID)
100 ecmd.cmd = ETHTOOL_GSET;
103 strscpy(ifr.ifr_name, IFNAMSIZ, ifname);
104 ifr.ifr_data = (void *)&ecmd;
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) {
145 struct ethtool_wolinfo ecmd;
146 bool need_update = false;
149 if (wol == _WOL_INVALID)
153 ecmd.cmd = ETHTOOL_GWOL;
156 strscpy(ifr.ifr_name, IFNAMSIZ, ifname);
157 ifr.ifr_data = (void *)&ecmd;
159 r = ioctl(fd, SIOCETHTOOL, &ifr);
165 if (ecmd.wolopts != WAKE_PHY) {
166 ecmd.wolopts = WAKE_PHY;
171 if (ecmd.wolopts != WAKE_MAGIC) {
172 ecmd.wolopts = WAKE_MAGIC;
177 if (ecmd.wolopts != 0) {
187 ecmd.cmd = ETHTOOL_SWOL;
189 r = ioctl(fd, SIOCETHTOOL, &ifr);