]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/udev/net/ethtool-util.c
Make tables for DEFINE_STRING_TABLE_LOOKUP consistent
[thirdparty/systemd.git] / src / udev / net / ethtool-util.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
7
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.
12
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.
17
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/>.
20 ***/
21
22 #include <sys/ioctl.h>
23 #include <net/if.h>
24 #include <linux/ethtool.h>
25 #include <linux/sockios.h>
26
27 #include "ethtool-util.h"
28
29 #include "strxcpyx.h"
30 #include "util.h"
31 #include "log.h"
32 #include "conf-parser.h"
33
34 static const char* const duplex_table[_DUP_MAX] = {
35 [DUP_FULL] = "full",
36 [DUP_HALF] = "half"
37 };
38
39 DEFINE_STRING_TABLE_LOOKUP(duplex, Duplex);
40 DEFINE_CONFIG_PARSE_ENUM(config_parse_duplex, duplex, Duplex, "Failed to parse duplex setting");
41
42 static const char* const wol_table[_WOL_MAX] = {
43 [WOL_PHY] = "phy",
44 [WOL_MAGIC] = "magic",
45 [WOL_OFF] = "off"
46 };
47
48 DEFINE_STRING_TABLE_LOOKUP(wol, WakeOnLan);
49 DEFINE_CONFIG_PARSE_ENUM(config_parse_wol, wol, WakeOnLan, "Failed to parse WakeOnLan setting");
50
51 int ethtool_connect(int *ret) {
52 int fd;
53
54 assert_return(ret, -EINVAL);
55
56 fd = socket(PF_INET, SOCK_DGRAM, 0);
57 if (fd < 0) {
58 return -errno;
59 }
60
61 *ret = fd;
62
63 return 0;
64 }
65
66 int ethtool_get_driver(int fd, const char *ifname, char **ret) {
67 struct ethtool_drvinfo ecmd = {
68 .cmd = ETHTOOL_GDRVINFO
69 };
70 struct ifreq ifr = {
71 .ifr_data = (void*) &ecmd
72 };
73 char *d;
74 int r;
75
76 strscpy(ifr.ifr_name, IFNAMSIZ, ifname);
77
78 r = ioctl(fd, SIOCETHTOOL, &ifr);
79 if (r < 0)
80 return -errno;
81
82 d = strdup(ecmd.driver);
83 if (!d)
84 return -ENOMEM;
85
86 *ret = d;
87 return 0;
88 }
89
90 int ethtool_set_speed(int fd, const char *ifname, unsigned int speed, Duplex duplex)
91 {
92 struct ethtool_cmd ecmd = {
93 .cmd = ETHTOOL_GSET
94 };
95 struct ifreq ifr = {
96 .ifr_data = (void*) &ecmd
97 };
98 bool need_update = false;
99 int r;
100
101 if (speed == 0 && duplex == _DUP_INVALID)
102 return 0;
103
104 strscpy(ifr.ifr_name, IFNAMSIZ, ifname);
105
106 r = ioctl(fd, SIOCETHTOOL, &ifr);
107 if (r < 0)
108 return -errno;
109
110 if (ethtool_cmd_speed(&ecmd) != speed) {
111 ethtool_cmd_speed_set(&ecmd, speed);
112 need_update = true;
113 }
114
115 switch (duplex) {
116 case DUP_HALF:
117 if (ecmd.duplex != DUPLEX_HALF) {
118 ecmd.duplex = DUPLEX_HALF;
119 need_update = true;
120 }
121 break;
122 case DUP_FULL:
123 if (ecmd.duplex != DUPLEX_FULL) {
124 ecmd.duplex = DUPLEX_FULL;
125 need_update = true;
126 }
127 break;
128 default:
129 break;
130 }
131
132 if (need_update) {
133 ecmd.cmd = ETHTOOL_SSET;
134
135 r = ioctl(fd, SIOCETHTOOL, &ifr);
136 if (r < 0)
137 return -errno;
138 }
139
140 return 0;
141 }
142
143 int ethtool_set_wol(int fd, const char *ifname, WakeOnLan wol) {
144 struct ethtool_wolinfo ecmd = {
145 .cmd = ETHTOOL_GWOL
146 };
147 struct ifreq ifr = {
148 .ifr_data = (void*) &ecmd
149 };
150 bool need_update = false;
151 int r;
152
153 if (wol == _WOL_INVALID)
154 return 0;
155
156 strscpy(ifr.ifr_name, IFNAMSIZ, ifname);
157
158 r = ioctl(fd, SIOCETHTOOL, &ifr);
159 if (r < 0)
160 return -errno;
161
162 switch (wol) {
163 case WOL_PHY:
164 if (ecmd.wolopts != WAKE_PHY) {
165 ecmd.wolopts = WAKE_PHY;
166 need_update = true;
167 }
168 break;
169 case WOL_MAGIC:
170 if (ecmd.wolopts != WAKE_MAGIC) {
171 ecmd.wolopts = WAKE_MAGIC;
172 need_update = true;
173 }
174 break;
175 case WOL_OFF:
176 if (ecmd.wolopts != 0) {
177 ecmd.wolopts = 0;
178 need_update = true;
179 }
180 break;
181 default:
182 break;
183 }
184
185 if (need_update) {
186 ecmd.cmd = ETHTOOL_SWOL;
187
188 r = ioctl(fd, SIOCETHTOOL, &ifr);
189 if (r < 0)
190 return -errno;
191 }
192
193 return 0;
194 }