chiark / gitweb /
bus: use new property retrieval calls everywhere
[elogind.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_set_speed(int fd, const char *ifname, unsigned int speed, Duplex duplex)
67 {
68         struct ifreq ifr;
69         struct ethtool_cmd ecmd;
70         bool need_update;
71         int r;
72
73         if (speed == 0 && duplex == _DUP_INVALID)
74                 return 0;
75
76         zero(ecmd);
77         ecmd.cmd = ETHTOOL_GSET;
78
79         zero(ifr);
80         strscpy(ifr.ifr_name, IFNAMSIZ, ifname);
81         ifr.ifr_data = (void *)&ecmd;
82
83         r = ioctl(fd, SIOCETHTOOL, &ifr);
84         if (r < 0)
85                 return -errno;
86
87         if (ethtool_cmd_speed(&ecmd) != speed) {
88                 ethtool_cmd_speed_set(&ecmd, speed);
89                 need_update = true;
90         }
91
92         switch (duplex) {
93                 case DUP_HALF:
94                         if (ecmd.duplex != DUPLEX_HALF) {
95                                 ecmd.duplex = DUPLEX_HALF;
96                                 need_update = true;
97                         }
98                         break;
99                 case DUP_FULL:
100                         if (ecmd.duplex != DUPLEX_FULL) {
101                                 ecmd.duplex = DUPLEX_FULL;
102                                 need_update = true;
103                         }
104                         break;
105                 default:
106                         break;
107         }
108
109         if (need_update) {
110                 ecmd.cmd = ETHTOOL_SSET;
111
112                 r = ioctl(fd, SIOCETHTOOL, &ifr);
113                 if (r < 0)
114                         return -errno;
115         }
116
117         return 0;
118 }
119
120 int ethtool_set_wol(int fd, const char *ifname, WakeOnLan wol) {
121         struct ifreq ifr;
122         struct ethtool_wolinfo ecmd;
123         bool need_update;
124         int r;
125
126         if (wol == _WOL_INVALID)
127                 return 0;
128
129         zero(ecmd);
130         ecmd.cmd = ETHTOOL_GWOL;
131
132         zero(ifr);
133         strscpy(ifr.ifr_name, IFNAMSIZ, ifname);
134         ifr.ifr_data = (void *)&ecmd;
135
136         r = ioctl(fd, SIOCETHTOOL, &ifr);
137         if (r < 0)
138                 return -errno;
139
140         switch (wol) {
141                 case WOL_PHY:
142                         if (ecmd.wolopts != WAKE_PHY) {
143                                 ecmd.wolopts = WAKE_PHY;
144                                 need_update = true;
145                         }
146                         break;
147                 case WOL_MAGIC:
148                         if (ecmd.wolopts != WAKE_MAGIC) {
149                                 ecmd.wolopts = WAKE_MAGIC;
150                                 need_update = true;
151                         }
152                         break;
153                 case WOL_OFF:
154                         if (ecmd.wolopts != 0) {
155                                 ecmd.wolopts = 0;
156                                 need_update = true;
157                         }
158                         break;
159                 default:
160                         break;
161         }
162
163         if (need_update) {
164                 ecmd.cmd = ETHTOOL_SWOL;
165
166                 r = ioctl(fd, SIOCETHTOOL, &ifr);
167                 if (r < 0)
168                         return -errno;
169         }
170
171         return 0;
172 }