]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/udev/net/ethtool-util.c
units: set 'AllowUser=root own' and 'AllowWorld=talk' own for all .busname files
[thirdparty/systemd.git] / src / udev / net / ethtool-util.c
CommitLineData
a5010333
TG
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"
5fde13d7
TG
32#include "conf-parser.h"
33
34static const char* const duplex_table[] = {
35 [DUP_FULL] = "full",
36 [DUP_HALF] = "half"
37};
38
39DEFINE_STRING_TABLE_LOOKUP(duplex, Duplex);
40DEFINE_CONFIG_PARSE_ENUM(config_parse_duplex, duplex, Duplex, "Failed to parse duplex setting");
41
42static const char* const wol_table[] = {
43 [WOL_PHY] = "phy",
44 [WOL_MAGIC] = "magic",
45 [WOL_OFF] = "off"
46};
47
48DEFINE_STRING_TABLE_LOOKUP(wol, WakeOnLan);
49DEFINE_CONFIG_PARSE_ENUM(config_parse_wol, wol, WakeOnLan, "Failed to parse WakeOnLan setting");
a5010333
TG
50
51int 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
847a8a5f 66int ethtool_get_driver(int fd, const char *ifname, char **ret) {
61f3af4f
LP
67 struct ethtool_drvinfo ecmd = {
68 .cmd = ETHTOOL_GDRVINFO
69 };
70 struct ifreq ifr = {
71 .ifr_data = (void*) &ecmd
72 };
73 char *d;
847a8a5f
TG
74 int r;
75
847a8a5f 76 strscpy(ifr.ifr_name, IFNAMSIZ, ifname);
847a8a5f
TG
77
78 r = ioctl(fd, SIOCETHTOOL, &ifr);
79 if (r < 0)
80 return -errno;
81
61f3af4f
LP
82 d = strdup(ecmd.driver);
83 if (!d)
847a8a5f
TG
84 return -ENOMEM;
85
61f3af4f 86 *ret = d;
847a8a5f
TG
87 return 0;
88}
89
5fde13d7 90int ethtool_set_speed(int fd, const char *ifname, unsigned int speed, Duplex duplex)
a5010333 91{
6c0519c0
TG
92 struct ethtool_cmd ecmd = {
93 .cmd = ETHTOOL_GSET
94 };
95 struct ifreq ifr = {
96 .ifr_data = (void*) &ecmd
97 };
0a2c2294 98 bool need_update = false;
a5010333
TG
99 int r;
100
5fde13d7 101 if (speed == 0 && duplex == _DUP_INVALID)
a5010333
TG
102 return 0;
103
a5010333 104 strscpy(ifr.ifr_name, IFNAMSIZ, ifname);
a5010333
TG
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
5fde13d7
TG
115 switch (duplex) {
116 case DUP_HALF:
a5010333
TG
117 if (ecmd.duplex != DUPLEX_HALF) {
118 ecmd.duplex = DUPLEX_HALF;
119 need_update = true;
120 }
5fde13d7
TG
121 break;
122 case DUP_FULL:
a5010333
TG
123 if (ecmd.duplex != DUPLEX_FULL) {
124 ecmd.duplex = DUPLEX_FULL;
125 need_update = true;
126 }
5fde13d7
TG
127 break;
128 default:
129 break;
a5010333
TG
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
5fde13d7 143int ethtool_set_wol(int fd, const char *ifname, WakeOnLan wol) {
6c0519c0
TG
144 struct ethtool_wolinfo ecmd = {
145 .cmd = ETHTOOL_GWOL
146 };
147 struct ifreq ifr = {
148 .ifr_data = (void*) &ecmd
149 };
0a2c2294 150 bool need_update = false;
a5010333
TG
151 int r;
152
5fde13d7 153 if (wol == _WOL_INVALID)
a5010333
TG
154 return 0;
155
a5010333 156 strscpy(ifr.ifr_name, IFNAMSIZ, ifname);
a5010333
TG
157
158 r = ioctl(fd, SIOCETHTOOL, &ifr);
159 if (r < 0)
160 return -errno;
161
5fde13d7
TG
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 }
a5010333
TG
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}