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 2489 : int linux_set_iface_flags(int sock, const char *ifname, int dev_up)
19 : {
20 : struct ifreq ifr;
21 : int ret;
22 :
23 2489 : if (sock < 0)
24 0 : return -1;
25 :
26 2489 : os_memset(&ifr, 0, sizeof(ifr));
27 2489 : os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
28 :
29 2489 : if (ioctl(sock, SIOCGIFFLAGS, &ifr) != 0) {
30 31 : ret = errno ? -errno : -999;
31 31 : wpa_printf(MSG_ERROR, "Could not read interface %s flags: %s",
32 31 : ifname, strerror(errno));
33 31 : return ret;
34 : }
35 :
36 2458 : if (dev_up) {
37 1246 : if (ifr.ifr_flags & IFF_UP)
38 22 : return 0;
39 1224 : ifr.ifr_flags |= IFF_UP;
40 : } else {
41 1212 : if (!(ifr.ifr_flags & IFF_UP))
42 58 : return 0;
43 1154 : ifr.ifr_flags &= ~IFF_UP;
44 : }
45 :
46 2378 : 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 2378 : return 0;
55 : }
56 :
57 :
58 1443 : int linux_iface_up(int sock, const char *ifname)
59 : {
60 : struct ifreq ifr;
61 : int ret;
62 :
63 1443 : if (sock < 0)
64 0 : return -1;
65 :
66 1443 : os_memset(&ifr, 0, sizeof(ifr));
67 1443 : os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
68 :
69 1443 : if (ioctl(sock, SIOCGIFFLAGS, &ifr) != 0) {
70 8 : ret = errno ? -errno : -999;
71 8 : wpa_printf(MSG_ERROR, "Could not read interface %s flags: %s",
72 8 : ifname, strerror(errno));
73 8 : return ret;
74 : }
75 :
76 1435 : return !!(ifr.ifr_flags & IFF_UP);
77 : }
78 :
79 :
80 2205 : int linux_get_ifhwaddr(int sock, const char *ifname, u8 *addr)
81 : {
82 : struct ifreq ifr;
83 :
84 2205 : os_memset(&ifr, 0, sizeof(ifr));
85 2205 : os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
86 2205 : 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 2205 : 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 2205 : os_memcpy(addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
98 :
99 2205 : return 0;
100 : }
101 :
102 :
103 122 : int linux_set_ifhwaddr(int sock, const char *ifname, const u8 *addr)
104 : {
105 : struct ifreq ifr;
106 :
107 122 : os_memset(&ifr, 0, sizeof(ifr));
108 122 : os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
109 122 : os_memcpy(ifr.ifr_hwaddr.sa_data, addr, ETH_ALEN);
110 122 : ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
111 :
112 122 : 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 122 : 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 10 : int linux_br_add(int sock, const char *brname)
137 : {
138 10 : 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 10 : return 0;
145 : }
146 :
147 :
148 10 : int linux_br_del(int sock, const char *brname)
149 : {
150 10 : if (ioctl(sock, SIOCBRDELBR, brname) < 0) {
151 9 : wpa_printf(MSG_DEBUG, "Could not remove bridge %s: %s",
152 9 : brname, strerror(errno));
153 9 : return -1;
154 : }
155 :
156 1 : return 0;
157 : }
158 :
159 :
160 16 : int linux_br_add_if(int sock, const char *brname, const char *ifname)
161 : {
162 : struct ifreq ifr;
163 : int ifindex;
164 :
165 16 : ifindex = if_nametoindex(ifname);
166 16 : if (ifindex == 0)
167 0 : return -1;
168 :
169 16 : os_memset(&ifr, 0, sizeof(ifr));
170 16 : os_strlcpy(ifr.ifr_name, brname, IFNAMSIZ);
171 16 : ifr.ifr_ifindex = ifindex;
172 16 : 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 16 : return 0;
179 : }
180 :
181 :
182 17 : int linux_br_del_if(int sock, const char *brname, const char *ifname)
183 : {
184 : struct ifreq ifr;
185 : int ifindex;
186 :
187 17 : ifindex = if_nametoindex(ifname);
188 17 : if (ifindex == 0)
189 0 : return -1;
190 :
191 17 : os_memset(&ifr, 0, sizeof(ifr));
192 17 : os_strlcpy(ifr.ifr_name, brname, IFNAMSIZ);
193 17 : ifr.ifr_ifindex = ifindex;
194 17 : if (ioctl(sock, SIOCBRDELIF, &ifr) < 0) {
195 15 : wpa_printf(MSG_DEBUG, "Could not remove interface %s from "
196 15 : "bridge %s: %s", ifname, brname, strerror(errno));
197 15 : return -1;
198 : }
199 :
200 2 : return 0;
201 : }
202 :
203 :
204 965 : int linux_br_get(char *brname, const char *ifname)
205 : {
206 : char path[128], brlink[128], *pos;
207 : ssize_t res;
208 :
209 965 : os_snprintf(path, sizeof(path), "/sys/class/net/%s/brport/bridge",
210 : ifname);
211 965 : res = readlink(path, brlink, sizeof(brlink));
212 965 : if (res < 0 || (size_t) res >= sizeof(brlink))
213 962 : return -1;
214 3 : brlink[res] = '\0';
215 3 : pos = os_strrchr(brlink, '/');
216 3 : if (pos == NULL)
217 0 : return -1;
218 3 : pos++;
219 3 : os_strlcpy(brname, pos, IFNAMSIZ);
220 3 : return 0;
221 : }
|