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