]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/udev/net/ethtool-util.c
net: initialize structs when declaring them/do not clobber caller variables
[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[] = {
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[] = {
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 ifreq ifr;
93 struct ethtool_cmd ecmd;
94 bool need_update = false;
95 int r;
96
97 if (speed == 0 && duplex == _DUP_INVALID)
98 return 0;
99
100 zero(ecmd);
101 ecmd.cmd = ETHTOOL_GSET;
102
103 zero(ifr);
104 strscpy(ifr.ifr_name, IFNAMSIZ, ifname);
105 ifr.ifr_data = (void *)&ecmd;
106
107 r = ioctl(fd, SIOCETHTOOL, &ifr);
108 if (r < 0)
109 return -errno;
110
111 if (ethtool_cmd_speed(&ecmd) != speed) {
112 ethtool_cmd_speed_set(&ecmd, speed);
113 need_update = true;
114 }
115
116 switch (duplex) {
117 case DUP_HALF:
118 if (ecmd.duplex != DUPLEX_HALF) {
119 ecmd.duplex = DUPLEX_HALF;
120 need_update = true;
121 }
122 break;
123 case DUP_FULL:
124 if (ecmd.duplex != DUPLEX_FULL) {
125 ecmd.duplex = DUPLEX_FULL;
126 need_update = true;
127 }
128 break;
129 default:
130 break;
131 }
132
133 if (need_update) {
134 ecmd.cmd = ETHTOOL_SSET;
135
136 r = ioctl(fd, SIOCETHTOOL, &ifr);
137 if (r < 0)
138 return -errno;
139 }
140
141 return 0;
142 }
143
144 int ethtool_set_wol(int fd, const char *ifname, WakeOnLan wol) {
145 struct ifreq ifr;
146 struct ethtool_wolinfo ecmd;
147 bool need_update = false;
148 int r;
149
150 if (wol == _WOL_INVALID)
151 return 0;
152
153 zero(ecmd);
154 ecmd.cmd = ETHTOOL_GWOL;
155
156 zero(ifr);
157 strscpy(ifr.ifr_name, IFNAMSIZ, ifname);
158 ifr.ifr_data = (void *)&ecmd;
159
160 r = ioctl(fd, SIOCETHTOOL, &ifr);
161 if (r < 0)
162 return -errno;
163
164 switch (wol) {
165 case WOL_PHY:
166 if (ecmd.wolopts != WAKE_PHY) {
167 ecmd.wolopts = WAKE_PHY;
168 need_update = true;
169 }
170 break;
171 case WOL_MAGIC:
172 if (ecmd.wolopts != WAKE_MAGIC) {
173 ecmd.wolopts = WAKE_MAGIC;
174 need_update = true;
175 }
176 break;
177 case WOL_OFF:
178 if (ecmd.wolopts != 0) {
179 ecmd.wolopts = 0;
180 need_update = true;
181 }
182 break;
183 default:
184 break;
185 }
186
187 if (need_update) {
188 ecmd.cmd = ETHTOOL_SWOL;
189
190 r = ioctl(fd, SIOCETHTOOL, &ifr);
191 if (r < 0)
192 return -errno;
193 }
194
195 return 0;
196 }