Branch data Line data Source code
1 : : /*
2 : : * Linux ioctl helper functions for driver wrappers
3 : : * Copyright (c) 2002-2010, Jouni Malinen <j@w1.fi>
4 : : *
5 : : * This software may be distributed under the terms of the BSD license.
6 : : * See README for more details.
7 : : */
8 : :
9 : : #include "utils/includes.h"
10 : : #include <sys/ioctl.h>
11 : : #include <net/if.h>
12 : : #include <net/if_arp.h>
13 : :
14 : : #include "utils/common.h"
15 : : #include "linux_ioctl.h"
16 : :
17 : :
18 : 321 : int linux_set_iface_flags(int sock, const char *ifname, int dev_up)
19 : : {
20 : : struct ifreq ifr;
21 : : int ret;
22 : :
23 [ - + ]: 321 : if (sock < 0)
24 : 0 : return -1;
25 : :
26 : 321 : os_memset(&ifr, 0, sizeof(ifr));
27 : 321 : os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
28 : :
29 [ - + ]: 321 : if (ioctl(sock, SIOCGIFFLAGS, &ifr) != 0) {
30 [ # # ]: 0 : ret = errno ? -errno : -999;
31 : 0 : wpa_printf(MSG_ERROR, "Could not read interface %s flags: %s",
32 : 0 : ifname, strerror(errno));
33 : 0 : return ret;
34 : : }
35 : :
36 [ + + ]: 321 : if (dev_up) {
37 [ - + ]: 166 : if (ifr.ifr_flags & IFF_UP)
38 : 0 : return 0;
39 : 166 : ifr.ifr_flags |= IFF_UP;
40 : : } else {
41 [ + + ]: 155 : if (!(ifr.ifr_flags & IFF_UP))
42 : 6 : return 0;
43 : 149 : ifr.ifr_flags &= ~IFF_UP;
44 : : }
45 : :
46 [ - + ]: 315 : if (ioctl(sock, SIOCSIFFLAGS, &ifr) != 0) {
47 [ # # ]: 0 : ret = errno ? -errno : -999;
48 [ # # ]: 0 : wpa_printf(MSG_ERROR, "Could not set interface %s flags (%s): "
49 : : "%s",
50 : 0 : ifname, dev_up ? "UP" : "DOWN", strerror(errno));
51 : 0 : return ret;
52 : : }
53 : :
54 : 321 : return 0;
55 : : }
56 : :
57 : :
58 : 189 : int linux_iface_up(int sock, const char *ifname)
59 : : {
60 : : struct ifreq ifr;
61 : : int ret;
62 : :
63 [ - + ]: 189 : if (sock < 0)
64 : 0 : return -1;
65 : :
66 : 189 : os_memset(&ifr, 0, sizeof(ifr));
67 : 189 : os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
68 : :
69 [ - + ]: 189 : if (ioctl(sock, SIOCGIFFLAGS, &ifr) != 0) {
70 [ # # ]: 0 : ret = errno ? -errno : -999;
71 : 0 : wpa_printf(MSG_ERROR, "Could not read interface %s flags: %s",
72 : 0 : ifname, strerror(errno));
73 : 0 : return ret;
74 : : }
75 : :
76 : 189 : return !!(ifr.ifr_flags & IFF_UP);
77 : : }
78 : :
79 : :
80 : 298 : int linux_get_ifhwaddr(int sock, const char *ifname, u8 *addr)
81 : : {
82 : : struct ifreq ifr;
83 : :
84 : 298 : os_memset(&ifr, 0, sizeof(ifr));
85 : 298 : os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
86 [ - + ]: 298 : if (ioctl(sock, SIOCGIFHWADDR, &ifr)) {
87 : 0 : wpa_printf(MSG_ERROR, "Could not get interface %s hwaddr: %s",
88 : 0 : ifname, strerror(errno));
89 : 0 : return -1;
90 : : }
91 : :
92 [ - + ]: 298 : if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
93 : 0 : wpa_printf(MSG_ERROR, "%s: Invalid HW-addr family 0x%04x",
94 : 0 : ifname, ifr.ifr_hwaddr.sa_family);
95 : 0 : return -1;
96 : : }
97 : 298 : os_memcpy(addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
98 : :
99 : 298 : return 0;
100 : : }
101 : :
102 : :
103 : 23 : int linux_set_ifhwaddr(int sock, const char *ifname, const u8 *addr)
104 : : {
105 : : struct ifreq ifr;
106 : :
107 : 23 : os_memset(&ifr, 0, sizeof(ifr));
108 : 23 : os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
109 : 23 : os_memcpy(ifr.ifr_hwaddr.sa_data, addr, ETH_ALEN);
110 : 23 : ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
111 : :
112 [ - + ]: 23 : if (ioctl(sock, SIOCSIFHWADDR, &ifr)) {
113 : 0 : wpa_printf(MSG_DEBUG, "Could not set interface %s hwaddr: %s",
114 : 0 : ifname, strerror(errno));
115 : 0 : return -1;
116 : : }
117 : :
118 : 23 : return 0;
119 : : }
120 : :
121 : :
122 : : #ifndef SIOCBRADDBR
123 : : #define SIOCBRADDBR 0x89a0
124 : : #endif
125 : : #ifndef SIOCBRDELBR
126 : : #define SIOCBRDELBR 0x89a1
127 : : #endif
128 : : #ifndef SIOCBRADDIF
129 : : #define SIOCBRADDIF 0x89a2
130 : : #endif
131 : : #ifndef SIOCBRDELIF
132 : : #define SIOCBRDELIF 0x89a3
133 : : #endif
134 : :
135 : :
136 : 0 : int linux_br_add(int sock, const char *brname)
137 : : {
138 [ # # ]: 0 : if (ioctl(sock, SIOCBRADDBR, brname) < 0) {
139 : 0 : wpa_printf(MSG_DEBUG, "Could not add bridge %s: %s",
140 : 0 : brname, strerror(errno));
141 : 0 : return -1;
142 : : }
143 : :
144 : 0 : return 0;
145 : : }
146 : :
147 : :
148 : 0 : int linux_br_del(int sock, const char *brname)
149 : : {
150 [ # # ]: 0 : if (ioctl(sock, SIOCBRDELBR, brname) < 0) {
151 : 0 : wpa_printf(MSG_DEBUG, "Could not remove bridge %s: %s",
152 : 0 : brname, strerror(errno));
153 : 0 : return -1;
154 : : }
155 : :
156 : 0 : return 0;
157 : : }
158 : :
159 : :
160 : 0 : int linux_br_add_if(int sock, const char *brname, const char *ifname)
161 : : {
162 : : struct ifreq ifr;
163 : : int ifindex;
164 : :
165 : 0 : ifindex = if_nametoindex(ifname);
166 [ # # ]: 0 : if (ifindex == 0)
167 : 0 : return -1;
168 : :
169 : 0 : os_memset(&ifr, 0, sizeof(ifr));
170 : 0 : os_strlcpy(ifr.ifr_name, brname, IFNAMSIZ);
171 : 0 : ifr.ifr_ifindex = ifindex;
172 [ # # ]: 0 : if (ioctl(sock, SIOCBRADDIF, &ifr) < 0) {
173 : 0 : wpa_printf(MSG_DEBUG, "Could not add interface %s into bridge "
174 : 0 : "%s: %s", ifname, brname, strerror(errno));
175 : 0 : return -1;
176 : : }
177 : :
178 : 0 : return 0;
179 : : }
180 : :
181 : :
182 : 0 : int linux_br_del_if(int sock, const char *brname, const char *ifname)
183 : : {
184 : : struct ifreq ifr;
185 : : int ifindex;
186 : :
187 : 0 : ifindex = if_nametoindex(ifname);
188 [ # # ]: 0 : if (ifindex == 0)
189 : 0 : return -1;
190 : :
191 : 0 : os_memset(&ifr, 0, sizeof(ifr));
192 : 0 : os_strlcpy(ifr.ifr_name, brname, IFNAMSIZ);
193 : 0 : ifr.ifr_ifindex = ifindex;
194 [ # # ]: 0 : if (ioctl(sock, SIOCBRDELIF, &ifr) < 0) {
195 : 0 : wpa_printf(MSG_DEBUG, "Could not remove interface %s from "
196 : 0 : "bridge %s: %s", ifname, brname, strerror(errno));
197 : 0 : return -1;
198 : : }
199 : :
200 : 0 : return 0;
201 : : }
202 : :
203 : :
204 : 149 : int linux_br_get(char *brname, const char *ifname)
205 : : {
206 : : char path[128], brlink[128], *pos;
207 : : ssize_t res;
208 : :
209 : 149 : os_snprintf(path, sizeof(path), "/sys/class/net/%s/brport/bridge",
210 : : ifname);
211 : 149 : res = readlink(path, brlink, sizeof(brlink));
212 [ - + ][ # # ]: 149 : if (res < 0 || (size_t) res >= sizeof(brlink))
213 : 149 : return -1;
214 : 0 : brlink[res] = '\0';
215 : 0 : pos = os_strrchr(brlink, '/');
216 [ # # ]: 0 : if (pos == NULL)
217 : 0 : return -1;
218 : 0 : pos++;
219 : 0 : os_strlcpy(brname, pos, IFNAMSIZ);
220 : 149 : return 0;
221 : : }
|