| @@ -1,1642 +1,1750 @@ | | | @@ -1,1642 +1,1750 @@ |
1 | /* | | 1 | /* |
2 | * WPA Supplicant - driver interaction with BSD net80211 layer | | 2 | * WPA Supplicant - driver interaction with BSD net80211 layer |
3 | * Copyright (c) 2004, Sam Leffler <sam@errno.com> | | 3 | * Copyright (c) 2004, Sam Leffler <sam@errno.com> |
4 | * Copyright (c) 2004, 2Wire, Inc | | 4 | * Copyright (c) 2004, 2Wire, Inc |
5 | * | | 5 | * |
6 | * This software may be distributed under the terms of the BSD license. | | 6 | * This software may be distributed under the terms of the BSD license. |
7 | * See README for more details. | | 7 | * See README for more details. |
8 | */ | | 8 | */ |
9 | | | 9 | |
10 | #include "includes.h" | | 10 | #include "includes.h" |
11 | #include <sys/ioctl.h> | | 11 | #include <sys/ioctl.h> |
12 | | | 12 | |
13 | #include "common.h" | | 13 | #include "common.h" |
14 | #include "driver.h" | | 14 | #include "driver.h" |
15 | #include "eloop.h" | | 15 | #include "eloop.h" |
16 | #include "common/ieee802_11_defs.h" | | 16 | #include "common/ieee802_11_defs.h" |
17 | #include "common/wpa_common.h" | | 17 | #include "common/wpa_common.h" |
18 | | | 18 | |
| | | 19 | #include <ifaddrs.h> |
19 | #include <net/if.h> | | 20 | #include <net/if.h> |
| | | 21 | #include <net/if_dl.h> |
20 | #include <net/if_media.h> | | 22 | #include <net/if_media.h> |
21 | | | 23 | |
22 | #ifdef __NetBSD__ | | 24 | #ifdef __NetBSD__ |
23 | #include <net/if_ether.h> | | 25 | #include <net/if_ether.h> |
24 | #else | | 26 | #else |
25 | #include <net/ethernet.h> | | 27 | #include <net/ethernet.h> |
26 | #endif | | 28 | #endif |
27 | #include <net/route.h> | | 29 | #include <net/route.h> |
28 | | | 30 | |
29 | #ifdef __DragonFly__ | | 31 | #ifdef __DragonFly__ |
30 | #include <netproto/802_11/ieee80211_ioctl.h> | | 32 | #include <netproto/802_11/ieee80211_ioctl.h> |
31 | #include <netproto/802_11/ieee80211_dragonfly.h> | | 33 | #include <netproto/802_11/ieee80211_dragonfly.h> |
32 | #else /* __DragonFly__ */ | | 34 | #else /* __DragonFly__ */ |
33 | #ifdef __GLIBC__ | | 35 | #ifdef __GLIBC__ |
34 | #include <netinet/ether.h> | | 36 | #include <netinet/ether.h> |
35 | #endif /* __GLIBC__ */ | | 37 | #endif /* __GLIBC__ */ |
36 | #include <net80211/ieee80211.h> | | 38 | #include <net80211/ieee80211.h> |
37 | #include <net80211/ieee80211_ioctl.h> | | 39 | #include <net80211/ieee80211_ioctl.h> |
38 | #include <net80211/ieee80211_crypto.h> | | 40 | #include <net80211/ieee80211_crypto.h> |
39 | #endif /* __DragonFly__ || __GLIBC__ */ | | 41 | #endif /* __DragonFly__ || __GLIBC__ */ |
40 | #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) | | 42 | #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) |
41 | #include <net80211/ieee80211_freebsd.h> | | 43 | #include <net80211/ieee80211_freebsd.h> |
42 | #endif | | 44 | #endif |
43 | #if __NetBSD__ | | 45 | #if __NetBSD__ |
44 | #include <net80211/ieee80211_netbsd.h> | | 46 | #include <net80211/ieee80211_netbsd.h> |
45 | #endif | | 47 | #endif |
46 | | | 48 | |
47 | #include "l2_packet/l2_packet.h" | | 49 | #include "l2_packet/l2_packet.h" |
48 | | | 50 | |
49 | struct bsd_driver_global { | | 51 | struct bsd_driver_global { |
50 | void *ctx; | | 52 | void *ctx; |
51 | int sock; /* socket for 802.11 ioctls */ | | 53 | int sock; /* socket for 802.11 ioctls */ |
52 | int route; /* routing socket for events */ | | 54 | int route; /* routing socket for events */ |
53 | struct dl_list ifaces; /* list of interfaces */ | | 55 | struct dl_list ifaces; /* list of interfaces */ |
54 | }; | | 56 | }; |
55 | | | 57 | |
56 | struct bsd_driver_data { | | 58 | struct bsd_driver_data { |
57 | struct dl_list list; | | 59 | struct dl_list list; |
58 | struct bsd_driver_global *global; | | 60 | struct bsd_driver_global *global; |
59 | void *ctx; | | 61 | void *ctx; |
60 | | | 62 | |
61 | struct l2_packet_data *sock_xmit;/* raw packet xmit socket */ | | 63 | struct l2_packet_data *sock_xmit;/* raw packet xmit socket */ |
62 | char ifname[IFNAMSIZ+1]; /* interface name */ | | 64 | char ifname[IFNAMSIZ+1]; /* interface name */ |
63 | int flags; | | 65 | int flags; |
64 | unsigned int ifindex; /* interface index */ | | 66 | unsigned int ifindex; /* interface index */ |
65 | int if_removed; /* has the interface been removed? */ | | 67 | int if_removed; /* has the interface been removed? */ |
66 | struct wpa_driver_capa capa; /* driver capability */ | | 68 | struct wpa_driver_capa capa; /* driver capability */ |
67 | int is_ap; /* Access point mode */ | | 69 | int is_ap; /* Access point mode */ |
68 | int prev_roaming; /* roaming state to restore on deinit */ | | 70 | int prev_roaming; /* roaming state to restore on deinit */ |
69 | int prev_privacy; /* privacy state to restore on deinit */ | | 71 | int prev_privacy; /* privacy state to restore on deinit */ |
70 | int prev_wpa; /* wpa state to restore on deinit */ | | 72 | int prev_wpa; /* wpa state to restore on deinit */ |
71 | enum ieee80211_opmode opmode; /* operation mode */ | | 73 | enum ieee80211_opmode opmode; /* operation mode */ |
72 | }; | | 74 | }; |
73 | | | 75 | |
74 | /* Generic functions for hostapd and wpa_supplicant */ | | 76 | /* Generic functions for hostapd and wpa_supplicant */ |
75 | | | 77 | |
76 | static struct bsd_driver_data * | | 78 | static struct bsd_driver_data * |
77 | bsd_get_drvindex(void *priv, unsigned int ifindex) | | 79 | bsd_get_drvindex(void *priv, unsigned int ifindex) |
78 | { | | 80 | { |
79 | struct bsd_driver_global *global = priv; | | 81 | struct bsd_driver_global *global = priv; |
80 | struct bsd_driver_data *drv; | | 82 | struct bsd_driver_data *drv; |
81 | | | 83 | |
82 | dl_list_for_each(drv, &global->ifaces, struct bsd_driver_data, list) { | | 84 | dl_list_for_each(drv, &global->ifaces, struct bsd_driver_data, list) { |
83 | if (drv->ifindex == ifindex) | | 85 | if (drv->ifindex == ifindex) |
84 | return drv; | | 86 | return drv; |
85 | } | | 87 | } |
86 | return NULL; | | 88 | return NULL; |
87 | } | | 89 | } |
88 | | | 90 | |
89 | static struct bsd_driver_data * | | 91 | static struct bsd_driver_data * |
90 | bsd_get_drvname(void *priv, const char *ifname) | | 92 | bsd_get_drvname(void *priv, const char *ifname) |
91 | { | | 93 | { |
92 | struct bsd_driver_global *global = priv; | | 94 | struct bsd_driver_global *global = priv; |
93 | struct bsd_driver_data *drv; | | 95 | struct bsd_driver_data *drv; |
94 | | | 96 | |
95 | dl_list_for_each(drv, &global->ifaces, struct bsd_driver_data, list) { | | 97 | dl_list_for_each(drv, &global->ifaces, struct bsd_driver_data, list) { |
96 | if (os_strcmp(drv->ifname, ifname) == 0) | | 98 | if (os_strcmp(drv->ifname, ifname) == 0) |
97 | return drv; | | 99 | return drv; |
98 | } | | 100 | } |
99 | return NULL; | | 101 | return NULL; |
100 | } | | 102 | } |
101 | | | 103 | |
102 | static int | | 104 | static int |
103 | bsd_set80211(void *priv, int op, int val, const void *arg, int arg_len) | | 105 | bsd_set80211(void *priv, int op, int val, const void *arg, int arg_len) |
104 | { | | 106 | { |
105 | struct bsd_driver_data *drv = priv; | | 107 | struct bsd_driver_data *drv = priv; |
106 | struct ieee80211req ireq; | | 108 | struct ieee80211req ireq; |
107 | | | 109 | |
108 | if (drv->ifindex == 0 || drv->if_removed) | | 110 | if (drv->ifindex == 0 || drv->if_removed) |
109 | return -1; | | 111 | return -1; |
110 | | | 112 | |
111 | os_memset(&ireq, 0, sizeof(ireq)); | | 113 | os_memset(&ireq, 0, sizeof(ireq)); |
112 | os_strlcpy(ireq.i_name, drv->ifname, sizeof(ireq.i_name)); | | 114 | os_strlcpy(ireq.i_name, drv->ifname, sizeof(ireq.i_name)); |
113 | ireq.i_type = op; | | 115 | ireq.i_type = op; |
114 | ireq.i_val = val; | | 116 | ireq.i_val = val; |
115 | ireq.i_data = (void *) arg; | | 117 | ireq.i_data = (void *) arg; |
116 | ireq.i_len = arg_len; | | 118 | ireq.i_len = arg_len; |
117 | | | 119 | |
118 | if (ioctl(drv->global->sock, SIOCS80211, &ireq) < 0) { | | 120 | if (ioctl(drv->global->sock, SIOCS80211, &ireq) < 0) { |
119 | wpa_printf(MSG_ERROR, "ioctl[SIOCS80211, op=%u, val=%u, " | | 121 | wpa_printf(MSG_ERROR, "ioctl[SIOCS80211, op=%u, val=%u, " |
120 | "arg_len=%u]: %s", op, val, arg_len, | | 122 | "arg_len=%u]: %s", op, val, arg_len, |
121 | strerror(errno)); | | 123 | strerror(errno)); |
122 | return -1; | | 124 | return -1; |
123 | } | | 125 | } |
124 | return 0; | | 126 | return 0; |
125 | } | | 127 | } |
126 | | | 128 | |
127 | static int | | 129 | static int |
128 | bsd_get80211(void *priv, struct ieee80211req *ireq, int op, void *arg, | | 130 | bsd_get80211(void *priv, struct ieee80211req *ireq, int op, void *arg, |
129 | int arg_len) | | 131 | int arg_len) |
130 | { | | 132 | { |
131 | struct bsd_driver_data *drv = priv; | | 133 | struct bsd_driver_data *drv = priv; |
132 | | | 134 | |
133 | os_memset(ireq, 0, sizeof(*ireq)); | | 135 | os_memset(ireq, 0, sizeof(*ireq)); |
134 | os_strlcpy(ireq->i_name, drv->ifname, sizeof(ireq->i_name)); | | 136 | os_strlcpy(ireq->i_name, drv->ifname, sizeof(ireq->i_name)); |
135 | ireq->i_type = op; | | 137 | ireq->i_type = op; |
136 | ireq->i_len = arg_len; | | 138 | ireq->i_len = arg_len; |
137 | ireq->i_data = arg; | | 139 | ireq->i_data = arg; |
138 | | | 140 | |
139 | if (ioctl(drv->global->sock, SIOCG80211, ireq) < 0) { | | 141 | if (ioctl(drv->global->sock, SIOCG80211, ireq) < 0) { |
140 | int level = drv->if_removed ? MSG_DEBUG : MSG_ERROR; | | 142 | int level = drv->if_removed ? MSG_DEBUG : MSG_ERROR; |
141 | | | 143 | |
142 | wpa_printf(level, "ioctl[SIOCG80211, op=%u, " | | 144 | wpa_printf(level, "ioctl[SIOCG80211, op=%u, " |
143 | "arg_len=%u]: %s", op, arg_len, strerror(errno)); | | 145 | "arg_len=%u]: %s", op, arg_len, strerror(errno)); |
144 | return -1; | | 146 | return -1; |
145 | } | | 147 | } |
146 | return 0; | | 148 | return 0; |
147 | } | | 149 | } |
148 | | | 150 | |
149 | static int | | 151 | static int |
150 | get80211var(struct bsd_driver_data *drv, int op, void *arg, int arg_len) | | 152 | get80211var(struct bsd_driver_data *drv, int op, void *arg, int arg_len) |
151 | { | | 153 | { |
152 | struct ieee80211req ireq; | | 154 | struct ieee80211req ireq; |
153 | | | 155 | |
154 | if (bsd_get80211(drv, &ireq, op, arg, arg_len) < 0) | | 156 | if (bsd_get80211(drv, &ireq, op, arg, arg_len) < 0) |
155 | return -1; | | 157 | return -1; |
156 | return ireq.i_len; | | 158 | return ireq.i_len; |
157 | } | | 159 | } |
158 | | | 160 | |
159 | static int | | 161 | static int |
160 | set80211var(struct bsd_driver_data *drv, int op, const void *arg, int arg_len) | | 162 | set80211var(struct bsd_driver_data *drv, int op, const void *arg, int arg_len) |
161 | { | | 163 | { |
162 | return bsd_set80211(drv, op, 0, arg, arg_len); | | 164 | return bsd_set80211(drv, op, 0, arg, arg_len); |
163 | } | | 165 | } |
164 | | | 166 | |
165 | static int | | 167 | static int |
166 | set80211param(struct bsd_driver_data *drv, int op, int arg) | | 168 | set80211param(struct bsd_driver_data *drv, int op, int arg) |
167 | { | | 169 | { |
168 | return bsd_set80211(drv, op, arg, NULL, 0); | | 170 | return bsd_set80211(drv, op, arg, NULL, 0); |
169 | } | | 171 | } |
170 | | | 172 | |
171 | static int | | 173 | static int |
172 | bsd_get_ssid(void *priv, u8 *ssid, int len) | | 174 | bsd_get_ssid(void *priv, u8 *ssid, int len) |
173 | { | | 175 | { |
174 | struct bsd_driver_data *drv = priv; | | 176 | struct bsd_driver_data *drv = priv; |
175 | #ifdef SIOCG80211NWID | | 177 | #ifdef SIOCG80211NWID |
176 | struct ieee80211_nwid nwid; | | 178 | struct ieee80211_nwid nwid; |
177 | struct ifreq ifr; | | 179 | struct ifreq ifr; |
178 | | | 180 | |
179 | os_memset(&ifr, 0, sizeof(ifr)); | | 181 | os_memset(&ifr, 0, sizeof(ifr)); |
180 | os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); | | 182 | os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); |
181 | ifr.ifr_data = (void *)&nwid; | | 183 | ifr.ifr_data = (void *)&nwid; |
182 | if (ioctl(drv->global->sock, SIOCG80211NWID, &ifr) < 0 || | | 184 | if (ioctl(drv->global->sock, SIOCG80211NWID, &ifr) < 0 || |
183 | nwid.i_len > IEEE80211_NWID_LEN) | | 185 | nwid.i_len > IEEE80211_NWID_LEN) |
184 | return -1; | | 186 | return -1; |
185 | os_memcpy(ssid, nwid.i_nwid, nwid.i_len); | | 187 | os_memcpy(ssid, nwid.i_nwid, nwid.i_len); |
186 | return nwid.i_len; | | 188 | return nwid.i_len; |
187 | #else | | 189 | #else |
188 | return get80211var(drv, IEEE80211_IOC_SSID, ssid, IEEE80211_NWID_LEN); | | 190 | return get80211var(drv, IEEE80211_IOC_SSID, ssid, IEEE80211_NWID_LEN); |
189 | #endif | | 191 | #endif |
190 | } | | 192 | } |
191 | | | 193 | |
192 | static int | | 194 | static int |
193 | bsd_set_ssid(void *priv, const u8 *ssid, int ssid_len) | | 195 | bsd_set_ssid(void *priv, const u8 *ssid, int ssid_len) |
194 | { | | 196 | { |
195 | struct bsd_driver_data *drv = priv; | | 197 | struct bsd_driver_data *drv = priv; |
196 | #ifdef SIOCS80211NWID | | 198 | #ifdef SIOCS80211NWID |
197 | struct ieee80211_nwid nwid; | | 199 | struct ieee80211_nwid nwid; |
198 | struct ifreq ifr; | | 200 | struct ifreq ifr; |
199 | | | 201 | |
200 | os_memcpy(nwid.i_nwid, ssid, ssid_len); | | 202 | os_memcpy(nwid.i_nwid, ssid, ssid_len); |
201 | nwid.i_len = ssid_len; | | 203 | nwid.i_len = ssid_len; |
202 | os_memset(&ifr, 0, sizeof(ifr)); | | 204 | os_memset(&ifr, 0, sizeof(ifr)); |
203 | os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); | | 205 | os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); |
204 | ifr.ifr_data = (void *)&nwid; | | 206 | ifr.ifr_data = (void *)&nwid; |
205 | return ioctl(drv->global->sock, SIOCS80211NWID, &ifr); | | 207 | return ioctl(drv->global->sock, SIOCS80211NWID, &ifr); |
206 | #else | | 208 | #else |
207 | return set80211var(drv, IEEE80211_IOC_SSID, ssid, ssid_len); | | 209 | return set80211var(drv, IEEE80211_IOC_SSID, ssid, ssid_len); |
208 | #endif | | 210 | #endif |
209 | } | | 211 | } |
210 | | | 212 | |
211 | static int | | 213 | static int |
212 | bsd_get_if_media(void *priv) | | 214 | bsd_get_if_media(void *priv) |
213 | { | | 215 | { |
214 | struct bsd_driver_data *drv = priv; | | 216 | struct bsd_driver_data *drv = priv; |
215 | struct ifmediareq ifmr; | | 217 | struct ifmediareq ifmr; |
216 | | | 218 | |
217 | os_memset(&ifmr, 0, sizeof(ifmr)); | | 219 | os_memset(&ifmr, 0, sizeof(ifmr)); |
218 | os_strlcpy(ifmr.ifm_name, drv->ifname, sizeof(ifmr.ifm_name)); | | 220 | os_strlcpy(ifmr.ifm_name, drv->ifname, sizeof(ifmr.ifm_name)); |
219 | | | 221 | |
220 | if (ioctl(drv->global->sock, SIOCGIFMEDIA, &ifmr) < 0) { | | 222 | if (ioctl(drv->global->sock, SIOCGIFMEDIA, &ifmr) < 0) { |
221 | wpa_printf(MSG_ERROR, "%s: SIOCGIFMEDIA %s", __func__, | | 223 | wpa_printf(MSG_ERROR, "%s: SIOCGIFMEDIA %s", __func__, |
222 | strerror(errno)); | | 224 | strerror(errno)); |
223 | return -1; | | 225 | return -1; |
224 | } | | 226 | } |
225 | | | 227 | |
226 | return ifmr.ifm_current; | | 228 | return ifmr.ifm_current; |
227 | } | | 229 | } |
228 | | | 230 | |
229 | static int | | 231 | static int |
230 | bsd_set_if_media(void *priv, int media) | | 232 | bsd_set_if_media(void *priv, int media) |
231 | { | | 233 | { |
232 | struct bsd_driver_data *drv = priv; | | 234 | struct bsd_driver_data *drv = priv; |
233 | struct ifreq ifr; | | 235 | struct ifreq ifr; |
234 | | | 236 | |
235 | os_memset(&ifr, 0, sizeof(ifr)); | | 237 | os_memset(&ifr, 0, sizeof(ifr)); |
236 | os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); | | 238 | os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); |
237 | ifr.ifr_media = media; | | 239 | ifr.ifr_media = media; |
238 | | | 240 | |
239 | if (ioctl(drv->global->sock, SIOCSIFMEDIA, &ifr) < 0) { | | 241 | if (ioctl(drv->global->sock, SIOCSIFMEDIA, &ifr) < 0) { |
240 | wpa_printf(MSG_ERROR, "%s: SIOCSIFMEDIA %s", __func__, | | 242 | wpa_printf(MSG_ERROR, "%s: SIOCSIFMEDIA %s", __func__, |
241 | strerror(errno)); | | 243 | strerror(errno)); |
242 | return -1; | | 244 | return -1; |
243 | } | | 245 | } |
244 | | | 246 | |
245 | return 0; | | 247 | return 0; |
246 | } | | 248 | } |
247 | | | 249 | |
248 | static int | | 250 | static int |
249 | bsd_set_mediaopt(void *priv, uint32_t mask, uint32_t mode) | | 251 | bsd_set_mediaopt(void *priv, uint32_t mask, uint32_t mode) |
250 | { | | 252 | { |
251 | int media = bsd_get_if_media(priv); | | 253 | int media = bsd_get_if_media(priv); |
252 | | | 254 | |
253 | if (media < 0) | | 255 | if (media < 0) |
254 | return -1; | | 256 | return -1; |
255 | media &= ~mask; | | 257 | media &= ~mask; |
256 | media |= mode; | | 258 | media |= mode; |
257 | if (bsd_set_if_media(priv, media) < 0) | | 259 | if (bsd_set_if_media(priv, media) < 0) |
258 | return -1; | | 260 | return -1; |
259 | return 0; | | 261 | return 0; |
260 | } | | 262 | } |
261 | | | 263 | |
262 | static int | | 264 | static int |
263 | bsd_del_key(void *priv, const u8 *addr, int key_idx) | | 265 | bsd_del_key(void *priv, const u8 *addr, int key_idx) |
264 | { | | 266 | { |
265 | struct ieee80211req_del_key wk; | | 267 | struct ieee80211req_del_key wk; |
266 | | | 268 | |
267 | os_memset(&wk, 0, sizeof(wk)); | | 269 | os_memset(&wk, 0, sizeof(wk)); |
268 | if (addr == NULL) { | | 270 | if (addr == NULL) { |
269 | wpa_printf(MSG_DEBUG, "%s: key_idx=%d", __func__, key_idx); | | 271 | wpa_printf(MSG_DEBUG, "%s: key_idx=%d", __func__, key_idx); |
270 | wk.idk_keyix = key_idx; | | 272 | wk.idk_keyix = key_idx; |
271 | } else { | | 273 | } else { |
272 | wpa_printf(MSG_DEBUG, "%s: addr=" MACSTR, __func__, | | 274 | wpa_printf(MSG_DEBUG, "%s: addr=" MACSTR, __func__, |
273 | MAC2STR(addr)); | | 275 | MAC2STR(addr)); |
274 | os_memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN); | | 276 | os_memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN); |
275 | wk.idk_keyix = (u_int8_t) IEEE80211_KEYIX_NONE; /* XXX */ | | 277 | wk.idk_keyix = (u_int8_t) IEEE80211_KEYIX_NONE; /* XXX */ |
276 | } | | 278 | } |
277 | | | 279 | |
278 | return set80211var(priv, IEEE80211_IOC_DELKEY, &wk, sizeof(wk)); | | 280 | return set80211var(priv, IEEE80211_IOC_DELKEY, &wk, sizeof(wk)); |
279 | } | | 281 | } |
280 | | | 282 | |
281 | static int | | 283 | static int |
282 | bsd_send_mlme_param(void *priv, const u8 op, const u16 reason, const u8 *addr) | | 284 | bsd_send_mlme_param(void *priv, const u8 op, const u16 reason, const u8 *addr) |
283 | { | | 285 | { |
284 | struct ieee80211req_mlme mlme; | | 286 | struct ieee80211req_mlme mlme; |
285 | | | 287 | |
286 | os_memset(&mlme, 0, sizeof(mlme)); | | 288 | os_memset(&mlme, 0, sizeof(mlme)); |
287 | mlme.im_op = op; | | 289 | mlme.im_op = op; |
288 | mlme.im_reason = reason; | | 290 | mlme.im_reason = reason; |
289 | os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); | | 291 | os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); |
290 | wpa_printf(MSG_DEBUG, "%s: op=%d reason=%d addr=" MACSTR, __func__, | | 292 | wpa_printf(MSG_DEBUG, "%s: op=%d reason=%d addr=" MACSTR, __func__, |
291 | op, reason, MAC2STR(addr)); | | 293 | op, reason, MAC2STR(addr)); |
292 | return set80211var(priv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)); | | 294 | return set80211var(priv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)); |
293 | } | | 295 | } |
294 | | | 296 | |
295 | static int | | 297 | static int |
296 | bsd_get_iface_flags(struct bsd_driver_data *drv) | | 298 | bsd_get_iface_flags(struct bsd_driver_data *drv) |
297 | { | | 299 | { |
298 | struct ifreq ifr; | | 300 | struct ifreq ifr; |
299 | | | 301 | |
300 | os_memset(&ifr, 0, sizeof(ifr)); | | 302 | os_memset(&ifr, 0, sizeof(ifr)); |
301 | os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); | | 303 | os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); |
302 | | | 304 | |
303 | if (ioctl(drv->global->sock, SIOCGIFFLAGS, &ifr) < 0) { | | 305 | if (ioctl(drv->global->sock, SIOCGIFFLAGS, &ifr) < 0) { |
304 | wpa_printf(MSG_ERROR, "ioctl[SIOCGIFFLAGS]: %s", | | 306 | wpa_printf(MSG_ERROR, "ioctl[SIOCGIFFLAGS]: %s", |
305 | strerror(errno)); | | 307 | strerror(errno)); |
306 | return -1; | | 308 | return -1; |
307 | } | | 309 | } |
308 | drv->flags = ifr.ifr_flags; | | 310 | drv->flags = ifr.ifr_flags; |
309 | return 0; | | 311 | return 0; |
310 | } | | 312 | } |
311 | | | 313 | |
312 | static int | | 314 | static int |
313 | bsd_set_key(const char *ifname, void *priv, enum wpa_alg alg, | | 315 | bsd_set_key(const char *ifname, void *priv, enum wpa_alg alg, |
314 | const unsigned char *addr, int key_idx, int set_tx, const u8 *seq, | | 316 | const unsigned char *addr, int key_idx, int set_tx, const u8 *seq, |
315 | size_t seq_len, const u8 *key, size_t key_len) | | 317 | size_t seq_len, const u8 *key, size_t key_len) |
316 | { | | 318 | { |
317 | struct ieee80211req_key wk; | | 319 | struct ieee80211req_key wk; |
318 | #ifdef IEEE80211_KEY_NOREPLAY | | 320 | #ifdef IEEE80211_KEY_NOREPLAY |
319 | struct bsd_driver_data *drv = priv; | | 321 | struct bsd_driver_data *drv = priv; |
320 | #endif /* IEEE80211_KEY_NOREPLAY */ | | 322 | #endif /* IEEE80211_KEY_NOREPLAY */ |
321 | | | 323 | |
322 | wpa_printf(MSG_DEBUG, "%s: alg=%d addr=%p key_idx=%d set_tx=%d " | | 324 | wpa_printf(MSG_DEBUG, "%s: alg=%d addr=%p key_idx=%d set_tx=%d " |
323 | "seq_len=%zu key_len=%zu", __func__, alg, addr, key_idx, | | 325 | "seq_len=%zu key_len=%zu", __func__, alg, addr, key_idx, |
324 | set_tx, seq_len, key_len); | | 326 | set_tx, seq_len, key_len); |
325 | | | 327 | |
326 | if (alg == WPA_ALG_NONE) { | | 328 | if (alg == WPA_ALG_NONE) { |
327 | #ifndef HOSTAPD | | 329 | #ifndef HOSTAPD |
328 | if (addr == NULL || is_broadcast_ether_addr(addr)) | | 330 | if (addr == NULL || is_broadcast_ether_addr(addr)) |
329 | return bsd_del_key(priv, NULL, key_idx); | | 331 | return bsd_del_key(priv, NULL, key_idx); |
330 | else | | 332 | else |
331 | #endif /* HOSTAPD */ | | 333 | #endif /* HOSTAPD */ |
332 | return bsd_del_key(priv, addr, key_idx); | | 334 | return bsd_del_key(priv, addr, key_idx); |
333 | } | | 335 | } |
334 | | | 336 | |
335 | os_memset(&wk, 0, sizeof(wk)); | | 337 | os_memset(&wk, 0, sizeof(wk)); |
336 | switch (alg) { | | 338 | switch (alg) { |
337 | case WPA_ALG_WEP: | | 339 | case WPA_ALG_WEP: |
338 | wk.ik_type = IEEE80211_CIPHER_WEP; | | 340 | wk.ik_type = IEEE80211_CIPHER_WEP; |
339 | break; | | 341 | break; |
340 | case WPA_ALG_TKIP: | | 342 | case WPA_ALG_TKIP: |
341 | wk.ik_type = IEEE80211_CIPHER_TKIP; | | 343 | wk.ik_type = IEEE80211_CIPHER_TKIP; |
342 | break; | | 344 | break; |
343 | case WPA_ALG_CCMP: | | 345 | case WPA_ALG_CCMP: |
344 | wk.ik_type = IEEE80211_CIPHER_AES_CCM; | | 346 | wk.ik_type = IEEE80211_CIPHER_AES_CCM; |
345 | break; | | 347 | break; |
346 | default: | | 348 | default: |
347 | wpa_printf(MSG_ERROR, "%s: unknown alg=%d", __func__, alg); | | 349 | wpa_printf(MSG_ERROR, "%s: unknown alg=%d", __func__, alg); |
348 | return -1; | | 350 | return -1; |
349 | } | | 351 | } |
350 | | | 352 | |
351 | wk.ik_flags = IEEE80211_KEY_RECV; | | 353 | wk.ik_flags = IEEE80211_KEY_RECV; |
352 | if (set_tx) | | 354 | if (set_tx) |
353 | wk.ik_flags |= IEEE80211_KEY_XMIT; | | 355 | wk.ik_flags |= IEEE80211_KEY_XMIT; |
354 | | | 356 | |
355 | if (addr == NULL) { | | 357 | if (addr == NULL) { |
356 | os_memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); | | 358 | os_memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); |
357 | wk.ik_keyix = key_idx; | | 359 | wk.ik_keyix = key_idx; |
358 | } else { | | 360 | } else { |
359 | os_memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); | | 361 | os_memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); |
360 | /* | | 362 | /* |
361 | * Deduce whether group/global or unicast key by checking | | 363 | * Deduce whether group/global or unicast key by checking |
362 | * the address (yech). Note also that we can only mark global | | 364 | * the address (yech). Note also that we can only mark global |
363 | * keys default; doing this for a unicast key is an error. | | 365 | * keys default; doing this for a unicast key is an error. |
364 | */ | | 366 | */ |
365 | if (is_broadcast_ether_addr(addr)) { | | 367 | if (is_broadcast_ether_addr(addr)) { |
366 | wk.ik_flags |= IEEE80211_KEY_GROUP; | | 368 | wk.ik_flags |= IEEE80211_KEY_GROUP; |
367 | wk.ik_keyix = key_idx; | | 369 | wk.ik_keyix = key_idx; |
368 | } else { | | 370 | } else { |
369 | wk.ik_keyix = key_idx == 0 ? IEEE80211_KEYIX_NONE : | | 371 | wk.ik_keyix = key_idx == 0 ? IEEE80211_KEYIX_NONE : |
370 | key_idx; | | 372 | key_idx; |
371 | } | | 373 | } |
372 | } | | 374 | } |
373 | if (wk.ik_keyix != IEEE80211_KEYIX_NONE && set_tx) | | 375 | if (wk.ik_keyix != IEEE80211_KEYIX_NONE && set_tx) |
374 | wk.ik_flags |= IEEE80211_KEY_DEFAULT; | | 376 | wk.ik_flags |= IEEE80211_KEY_DEFAULT; |
375 | #ifndef HOSTAPD | | 377 | #ifndef HOSTAPD |
376 | #ifdef IEEE80211_KEY_NOREPLAY | | 378 | #ifdef IEEE80211_KEY_NOREPLAY |
377 | /* | | 379 | /* |
378 | * Ignore replay failures in IBSS and AHDEMO mode. | | 380 | * Ignore replay failures in IBSS and AHDEMO mode. |
379 | */ | | 381 | */ |
380 | if (drv->opmode == IEEE80211_M_IBSS || | | 382 | if (drv->opmode == IEEE80211_M_IBSS || |
381 | drv->opmode == IEEE80211_M_AHDEMO) | | 383 | drv->opmode == IEEE80211_M_AHDEMO) |
382 | wk.ik_flags |= IEEE80211_KEY_NOREPLAY; | | 384 | wk.ik_flags |= IEEE80211_KEY_NOREPLAY; |
383 | #endif /* IEEE80211_KEY_NOREPLAY */ | | 385 | #endif /* IEEE80211_KEY_NOREPLAY */ |
384 | #endif /* HOSTAPD */ | | 386 | #endif /* HOSTAPD */ |
385 | wk.ik_keylen = key_len; | | 387 | wk.ik_keylen = key_len; |
386 | if (seq) { | | 388 | if (seq) { |
387 | #ifdef WORDS_BIGENDIAN | | 389 | #ifdef WORDS_BIGENDIAN |
388 | /* | | 390 | /* |
389 | * wk.ik_keyrsc is in host byte order (big endian), need to | | 391 | * wk.ik_keyrsc is in host byte order (big endian), need to |
390 | * swap it to match with the byte order used in WPA. | | 392 | * swap it to match with the byte order used in WPA. |
391 | */ | | 393 | */ |
392 | int i; | | 394 | int i; |
393 | u8 *keyrsc = (u8 *) &wk.ik_keyrsc; | | 395 | u8 *keyrsc = (u8 *) &wk.ik_keyrsc; |
394 | for (i = 0; i < seq_len; i++) | | 396 | for (i = 0; i < seq_len; i++) |
395 | keyrsc[WPA_KEY_RSC_LEN - i - 1] = seq[i]; | | 397 | keyrsc[WPA_KEY_RSC_LEN - i - 1] = seq[i]; |
396 | #else /* WORDS_BIGENDIAN */ | | 398 | #else /* WORDS_BIGENDIAN */ |
397 | os_memcpy(&wk.ik_keyrsc, seq, seq_len); | | 399 | os_memcpy(&wk.ik_keyrsc, seq, seq_len); |
398 | #endif /* WORDS_BIGENDIAN */ | | 400 | #endif /* WORDS_BIGENDIAN */ |
399 | } | | 401 | } |
400 | os_memcpy(wk.ik_keydata, key, key_len); | | 402 | os_memcpy(wk.ik_keydata, key, key_len); |
401 | | | 403 | |
402 | return set80211var(priv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk)); | | 404 | return set80211var(priv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk)); |
403 | } | | 405 | } |
404 | | | 406 | |
405 | static int | | 407 | static int |
406 | bsd_configure_wpa(void *priv, struct wpa_bss_params *params) | | 408 | bsd_configure_wpa(void *priv, struct wpa_bss_params *params) |
407 | { | | 409 | { |
408 | #ifndef IEEE80211_IOC_APPIE | | 410 | #ifndef IEEE80211_IOC_APPIE |
409 | static const char *ciphernames[] = | | 411 | static const char *ciphernames[] = |
410 | { "WEP", "TKIP", "AES-OCB", "AES-CCM", "CKIP", "NONE" }; | | 412 | { "WEP", "TKIP", "AES-OCB", "AES-CCM", "CKIP", "NONE" }; |
411 | int v; | | 413 | int v; |
412 | | | 414 | |
413 | switch (params->wpa_group) { | | 415 | switch (params->wpa_group) { |
414 | case WPA_CIPHER_CCMP: | | 416 | case WPA_CIPHER_CCMP: |
415 | v = IEEE80211_CIPHER_AES_CCM; | | 417 | v = IEEE80211_CIPHER_AES_CCM; |
416 | break; | | 418 | break; |
417 | case WPA_CIPHER_TKIP: | | 419 | case WPA_CIPHER_TKIP: |
418 | v = IEEE80211_CIPHER_TKIP; | | 420 | v = IEEE80211_CIPHER_TKIP; |
419 | break; | | 421 | break; |
420 | case WPA_CIPHER_WEP104: | | 422 | case WPA_CIPHER_WEP104: |
421 | v = IEEE80211_CIPHER_WEP; | | 423 | v = IEEE80211_CIPHER_WEP; |
422 | break; | | 424 | break; |
423 | case WPA_CIPHER_WEP40: | | 425 | case WPA_CIPHER_WEP40: |
424 | v = IEEE80211_CIPHER_WEP; | | 426 | v = IEEE80211_CIPHER_WEP; |
425 | break; | | 427 | break; |
426 | case WPA_CIPHER_NONE: | | 428 | case WPA_CIPHER_NONE: |
427 | v = IEEE80211_CIPHER_NONE; | | 429 | v = IEEE80211_CIPHER_NONE; |
428 | break; | | 430 | break; |
429 | default: | | 431 | default: |
430 | wpa_printf(MSG_INFO, "Unknown group key cipher %u", | | 432 | wpa_printf(MSG_INFO, "Unknown group key cipher %u", |
431 | params->wpa_group); | | 433 | params->wpa_group); |
432 | return -1; | | 434 | return -1; |
433 | } | | 435 | } |
434 | wpa_printf(MSG_DEBUG, "%s: group key cipher=%s (%u)", | | 436 | wpa_printf(MSG_DEBUG, "%s: group key cipher=%s (%u)", |
435 | __func__, ciphernames[v], v); | | 437 | __func__, ciphernames[v], v); |
436 | if (set80211param(priv, IEEE80211_IOC_MCASTCIPHER, v)) { | | 438 | if (set80211param(priv, IEEE80211_IOC_MCASTCIPHER, v)) { |
437 | wpa_printf(MSG_INFO, | | 439 | wpa_printf(MSG_INFO, |
438 | "Unable to set group key cipher to %u (%s)", | | 440 | "Unable to set group key cipher to %u (%s)", |
439 | v, ciphernames[v]); | | 441 | v, ciphernames[v]); |
440 | return -1; | | 442 | return -1; |
441 | } | | 443 | } |
442 | if (v == IEEE80211_CIPHER_WEP) { | | 444 | if (v == IEEE80211_CIPHER_WEP) { |
443 | /* key length is done only for specific ciphers */ | | 445 | /* key length is done only for specific ciphers */ |
444 | v = (params->wpa_group == WPA_CIPHER_WEP104 ? 13 : 5); | | 446 | v = (params->wpa_group == WPA_CIPHER_WEP104 ? 13 : 5); |
445 | if (set80211param(priv, IEEE80211_IOC_MCASTKEYLEN, v)) { | | 447 | if (set80211param(priv, IEEE80211_IOC_MCASTKEYLEN, v)) { |
446 | wpa_printf(MSG_INFO, | | 448 | wpa_printf(MSG_INFO, |
447 | "Unable to set group key length to %u", v); | | 449 | "Unable to set group key length to %u", v); |
448 | return -1; | | 450 | return -1; |
449 | } | | 451 | } |
450 | } | | 452 | } |
451 | | | 453 | |
452 | v = 0; | | 454 | v = 0; |
453 | if (params->wpa_pairwise & WPA_CIPHER_CCMP) | | 455 | if (params->wpa_pairwise & WPA_CIPHER_CCMP) |
454 | v |= 1<<IEEE80211_CIPHER_AES_CCM; | | 456 | v |= 1<<IEEE80211_CIPHER_AES_CCM; |
455 | if (params->wpa_pairwise & WPA_CIPHER_TKIP) | | 457 | if (params->wpa_pairwise & WPA_CIPHER_TKIP) |
456 | v |= 1<<IEEE80211_CIPHER_TKIP; | | 458 | v |= 1<<IEEE80211_CIPHER_TKIP; |
457 | if (params->wpa_pairwise & WPA_CIPHER_NONE) | | 459 | if (params->wpa_pairwise & WPA_CIPHER_NONE) |
458 | v |= 1<<IEEE80211_CIPHER_NONE; | | 460 | v |= 1<<IEEE80211_CIPHER_NONE; |
459 | wpa_printf(MSG_DEBUG, "%s: pairwise key ciphers=0x%x", __func__, v); | | 461 | wpa_printf(MSG_DEBUG, "%s: pairwise key ciphers=0x%x", __func__, v); |
460 | if (set80211param(priv, IEEE80211_IOC_UCASTCIPHERS, v)) { | | 462 | if (set80211param(priv, IEEE80211_IOC_UCASTCIPHERS, v)) { |
461 | wpa_printf(MSG_INFO, | | 463 | wpa_printf(MSG_INFO, |
462 | "Unable to set pairwise key ciphers to 0x%x", v); | | 464 | "Unable to set pairwise key ciphers to 0x%x", v); |
463 | return -1; | | 465 | return -1; |
464 | } | | 466 | } |
465 | | | 467 | |
466 | wpa_printf(MSG_DEBUG, "%s: key management algorithms=0x%x", | | 468 | wpa_printf(MSG_DEBUG, "%s: key management algorithms=0x%x", |
467 | __func__, params->wpa_key_mgmt); | | 469 | __func__, params->wpa_key_mgmt); |
468 | if (set80211param(priv, IEEE80211_IOC_KEYMGTALGS, | | 470 | if (set80211param(priv, IEEE80211_IOC_KEYMGTALGS, |
469 | params->wpa_key_mgmt)) { | | 471 | params->wpa_key_mgmt)) { |
470 | wpa_printf(MSG_INFO, | | 472 | wpa_printf(MSG_INFO, |
471 | "Unable to set key management algorithms to 0x%x", | | 473 | "Unable to set key management algorithms to 0x%x", |
472 | params->wpa_key_mgmt); | | 474 | params->wpa_key_mgmt); |
473 | return -1; | | 475 | return -1; |
474 | } | | 476 | } |
475 | | | 477 | |
476 | v = 0; | | 478 | v = 0; |
477 | if (params->rsn_preauth) | | 479 | if (params->rsn_preauth) |
478 | v |= BIT(0); | | 480 | v |= BIT(0); |
479 | wpa_printf(MSG_DEBUG, "%s: rsn capabilities=0x%x", | | 481 | wpa_printf(MSG_DEBUG, "%s: rsn capabilities=0x%x", |
480 | __func__, params->rsn_preauth); | | 482 | __func__, params->rsn_preauth); |
481 | if (set80211param(priv, IEEE80211_IOC_RSNCAPS, v)) { | | 483 | if (set80211param(priv, IEEE80211_IOC_RSNCAPS, v)) { |
482 | wpa_printf(MSG_INFO, "Unable to set RSN capabilities to 0x%x", | | 484 | wpa_printf(MSG_INFO, "Unable to set RSN capabilities to 0x%x", |
483 | v); | | 485 | v); |
484 | return -1; | | 486 | return -1; |
485 | } | | 487 | } |
486 | #endif /* IEEE80211_IOC_APPIE */ | | 488 | #endif /* IEEE80211_IOC_APPIE */ |
487 | | | 489 | |
488 | wpa_printf(MSG_DEBUG, "%s: enable WPA= 0x%x", __func__, params->wpa); | | 490 | wpa_printf(MSG_DEBUG, "%s: enable WPA= 0x%x", __func__, params->wpa); |
489 | if (set80211param(priv, IEEE80211_IOC_WPA, params->wpa)) { | | 491 | if (set80211param(priv, IEEE80211_IOC_WPA, params->wpa)) { |
490 | wpa_printf(MSG_INFO, "Unable to set WPA to %u", params->wpa); | | 492 | wpa_printf(MSG_INFO, "Unable to set WPA to %u", params->wpa); |
491 | return -1; | | 493 | return -1; |
492 | } | | 494 | } |
493 | return 0; | | 495 | return 0; |
494 | } | | 496 | } |
495 | | | 497 | |
496 | static int | | 498 | static int |
497 | bsd_set_ieee8021x(void *priv, struct wpa_bss_params *params) | | 499 | bsd_set_ieee8021x(void *priv, struct wpa_bss_params *params) |
498 | { | | 500 | { |
499 | wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, params->enabled); | | 501 | wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, params->enabled); |
500 | | | 502 | |
501 | if (!params->enabled) { | | 503 | if (!params->enabled) { |
502 | /* XXX restore state */ | | 504 | /* XXX restore state */ |
503 | return set80211param(priv, IEEE80211_IOC_AUTHMODE, | | 505 | return set80211param(priv, IEEE80211_IOC_AUTHMODE, |
504 | IEEE80211_AUTH_AUTO); | | 506 | IEEE80211_AUTH_AUTO); |
505 | } | | 507 | } |
506 | if (!params->wpa && !params->ieee802_1x) { | | 508 | if (!params->wpa && !params->ieee802_1x) { |
507 | wpa_printf(MSG_ERROR, "%s: No 802.1X or WPA enabled", | | 509 | wpa_printf(MSG_ERROR, "%s: No 802.1X or WPA enabled", |
508 | __func__); | | 510 | __func__); |
509 | return -1; | | 511 | return -1; |
510 | } | | 512 | } |
511 | if (params->wpa && bsd_configure_wpa(priv, params) != 0) { | | 513 | if (params->wpa && bsd_configure_wpa(priv, params) != 0) { |
512 | wpa_printf(MSG_ERROR, "%s: Failed to configure WPA state", | | 514 | wpa_printf(MSG_ERROR, "%s: Failed to configure WPA state", |
513 | __func__); | | 515 | __func__); |
514 | return -1; | | 516 | return -1; |
515 | } | | 517 | } |
516 | if (set80211param(priv, IEEE80211_IOC_AUTHMODE, | | 518 | if (set80211param(priv, IEEE80211_IOC_AUTHMODE, |
517 | (params->wpa ? IEEE80211_AUTH_WPA : IEEE80211_AUTH_8021X))) { | | 519 | (params->wpa ? IEEE80211_AUTH_WPA : IEEE80211_AUTH_8021X))) { |
518 | wpa_printf(MSG_ERROR, "%s: Failed to enable WPA/802.1X", | | 520 | wpa_printf(MSG_ERROR, "%s: Failed to enable WPA/802.1X", |
519 | __func__); | | 521 | __func__); |
520 | return -1; | | 522 | return -1; |
521 | } | | 523 | } |
522 | return 0; | | 524 | return 0; |
523 | } | | 525 | } |
524 | | | 526 | |
525 | static void | | 527 | static void |
526 | bsd_new_sta(void *priv, void *ctx, u8 addr[IEEE80211_ADDR_LEN]) | | 528 | bsd_new_sta(void *priv, void *ctx, u8 addr[IEEE80211_ADDR_LEN]) |
527 | { | | 529 | { |
528 | struct ieee80211req_wpaie ie; | | 530 | struct ieee80211req_wpaie ie; |
529 | int ielen = 0; | | 531 | int ielen = 0; |
530 | u8 *iebuf = NULL; | | 532 | u8 *iebuf = NULL; |
531 | | | 533 | |
532 | /* | | 534 | /* |
533 | * Fetch and validate any negotiated WPA/RSN parameters. | | 535 | * Fetch and validate any negotiated WPA/RSN parameters. |
534 | */ | | 536 | */ |
535 | memset(&ie, 0, sizeof(ie)); | | 537 | memset(&ie, 0, sizeof(ie)); |
536 | memcpy(ie.wpa_macaddr, addr, IEEE80211_ADDR_LEN); | | 538 | memcpy(ie.wpa_macaddr, addr, IEEE80211_ADDR_LEN); |
537 | if (get80211var(priv, IEEE80211_IOC_WPAIE, &ie, sizeof(ie)) < 0) { | | 539 | if (get80211var(priv, IEEE80211_IOC_WPAIE, &ie, sizeof(ie)) < 0) { |
538 | wpa_printf(MSG_INFO, | | 540 | wpa_printf(MSG_INFO, |
539 | "Failed to get WPA/RSN information element"); | | 541 | "Failed to get WPA/RSN information element"); |
540 | goto no_ie; | | 542 | goto no_ie; |
541 | } | | 543 | } |
542 | iebuf = ie.wpa_ie; | | 544 | iebuf = ie.wpa_ie; |
543 | ielen = ie.wpa_ie[1]; | | 545 | ielen = ie.wpa_ie[1]; |
544 | if (ielen == 0) | | 546 | if (ielen == 0) |
545 | iebuf = NULL; | | 547 | iebuf = NULL; |
546 | else | | 548 | else |
547 | ielen += 2; | | 549 | ielen += 2; |
548 | | | 550 | |
549 | no_ie: | | 551 | no_ie: |
550 | drv_event_assoc(ctx, addr, iebuf, ielen, 0); | | 552 | drv_event_assoc(ctx, addr, iebuf, ielen, 0); |
551 | } | | 553 | } |
552 | | | 554 | |
553 | static int | | 555 | static int |
554 | bsd_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len, | | 556 | bsd_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len, |
555 | int encrypt, const u8 *own_addr, u32 flags) | | 557 | int encrypt, const u8 *own_addr, u32 flags) |
556 | { | | 558 | { |
557 | struct bsd_driver_data *drv = priv; | | 559 | struct bsd_driver_data *drv = priv; |
558 | | | 560 | |
559 | wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", data, data_len); | | 561 | wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", data, data_len); |
560 | | | 562 | |
561 | return l2_packet_send(drv->sock_xmit, addr, ETH_P_EAPOL, data, | | 563 | return l2_packet_send(drv->sock_xmit, addr, ETH_P_EAPOL, data, |
562 | data_len); | | 564 | data_len); |
563 | } | | 565 | } |
564 | | | 566 | |
565 | static int | | 567 | static int |
566 | bsd_set_freq(void *priv, struct hostapd_freq_params *freq) | | 568 | bsd_set_freq(void *priv, struct hostapd_freq_params *freq) |
567 | { | | 569 | { |
568 | struct bsd_driver_data *drv = priv; | | 570 | struct bsd_driver_data *drv = priv; |
569 | #ifdef SIOCS80211CHANNEL | | 571 | #ifdef SIOCS80211CHANNEL |
570 | struct ieee80211chanreq creq; | | 572 | struct ieee80211chanreq creq; |
571 | #endif /* SIOCS80211CHANNEL */ | | 573 | #endif /* SIOCS80211CHANNEL */ |
572 | u32 mode; | | 574 | u32 mode; |
573 | int channel = freq->channel; | | 575 | int channel = freq->channel; |
574 | | | 576 | |
575 | if (channel < 14) { | | 577 | if (channel < 14) { |
576 | mode = | | 578 | mode = |
577 | #ifdef CONFIG_IEEE80211N | | 579 | #ifdef CONFIG_IEEE80211N |
578 | freq->ht_enabled ? IFM_IEEE80211_11NG : | | 580 | freq->ht_enabled ? IFM_IEEE80211_11NG : |
579 | #endif /* CONFIG_IEEE80211N */ | | 581 | #endif /* CONFIG_IEEE80211N */ |
580 | IFM_IEEE80211_11G; | | 582 | IFM_IEEE80211_11G; |
581 | } else if (channel == 14) { | | 583 | } else if (channel == 14) { |
582 | mode = IFM_IEEE80211_11B; | | 584 | mode = IFM_IEEE80211_11B; |
583 | } else { | | 585 | } else { |
584 | mode = | | 586 | mode = |
585 | #ifdef CONFIG_IEEE80211N | | 587 | #ifdef CONFIG_IEEE80211N |
586 | freq->ht_enabled ? IFM_IEEE80211_11NA : | | 588 | freq->ht_enabled ? IFM_IEEE80211_11NA : |
587 | #endif /* CONFIG_IEEE80211N */ | | 589 | #endif /* CONFIG_IEEE80211N */ |
588 | IFM_IEEE80211_11A; | | 590 | IFM_IEEE80211_11A; |
589 | } | | 591 | } |
590 | if (bsd_set_mediaopt(drv, IFM_MMASK, mode) < 0) { | | 592 | if (bsd_set_mediaopt(drv, IFM_MMASK, mode) < 0) { |
591 | wpa_printf(MSG_ERROR, "%s: failed to set modulation mode", | | 593 | wpa_printf(MSG_ERROR, "%s: failed to set modulation mode", |
592 | __func__); | | 594 | __func__); |
593 | return -1; | | 595 | return -1; |
594 | } | | 596 | } |
595 | | | 597 | |
596 | #ifdef SIOCS80211CHANNEL | | 598 | #ifdef SIOCS80211CHANNEL |
597 | os_memset(&creq, 0, sizeof(creq)); | | 599 | os_memset(&creq, 0, sizeof(creq)); |
598 | os_strlcpy(creq.i_name, drv->ifname, sizeof(creq.i_name)); | | 600 | os_strlcpy(creq.i_name, drv->ifname, sizeof(creq.i_name)); |
599 | creq.i_channel = (u_int16_t)channel; | | 601 | creq.i_channel = (u_int16_t)channel; |
600 | return ioctl(drv->global->sock, SIOCS80211CHANNEL, &creq); | | 602 | return ioctl(drv->global->sock, SIOCS80211CHANNEL, &creq); |
601 | #else /* SIOCS80211CHANNEL */ | | 603 | #else /* SIOCS80211CHANNEL */ |
602 | return set80211param(priv, IEEE80211_IOC_CHANNEL, channel); | | 604 | return set80211param(priv, IEEE80211_IOC_CHANNEL, channel); |
603 | #endif /* SIOCS80211CHANNEL */ | | 605 | #endif /* SIOCS80211CHANNEL */ |
604 | } | | 606 | } |
605 | | | 607 | |
606 | static int | | 608 | static int |
607 | bsd_set_opt_ie(void *priv, const u8 *ie, size_t ie_len) | | 609 | bsd_set_opt_ie(void *priv, const u8 *ie, size_t ie_len) |
608 | { | | 610 | { |
609 | #ifdef IEEE80211_IOC_APPIE | | 611 | #ifdef IEEE80211_IOC_APPIE |
610 | wpa_printf(MSG_DEBUG, "%s: set WPA+RSN ie (len %lu)", __func__, | | 612 | wpa_printf(MSG_DEBUG, "%s: set WPA+RSN ie (len %lu)", __func__, |
611 | (unsigned long)ie_len); | | 613 | (unsigned long)ie_len); |
612 | return bsd_set80211(priv, IEEE80211_IOC_APPIE, IEEE80211_APPIE_WPA, | | 614 | return bsd_set80211(priv, IEEE80211_IOC_APPIE, IEEE80211_APPIE_WPA, |
613 | ie, ie_len); | | 615 | ie, ie_len); |
614 | #endif /* IEEE80211_IOC_APPIE */ | | 616 | #endif /* IEEE80211_IOC_APPIE */ |
615 | return 0; | | 617 | return 0; |
616 | } | | 618 | } |
617 | | | 619 | |
| | | 620 | #ifdef SO_RERROR |
| | | 621 | static void |
| | | 622 | bsd_route_overflow(int sock, void *ctx, struct bsd_driver_global *global) |
| | | 623 | { |
| | | 624 | char event_buf[2048]; /* max size of a single route(4) msg */ |
| | | 625 | int n; |
| | | 626 | struct ifaddrs *ifaddrs, *ifa; |
| | | 627 | struct bsd_driver_data *drv; |
| | | 628 | struct sockaddr_dl *sdl; |
| | | 629 | union wpa_event_data event; |
| | | 630 | |
| | | 631 | /* We need to match the system state, so drain the route |
| | | 632 | * socket to avoid stale messages. */ |
| | | 633 | do { |
| | | 634 | n = read(sock, event_buf, sizeof(event_buf)); |
| | | 635 | } while (n != -1 || errno == ENOBUFS); |
| | | 636 | |
| | | 637 | if (getifaddrs(&ifaddrs) == -1) { |
| | | 638 | wpa_printf(MSG_ERROR, "%s getifaddrs() failed: %s", |
| | | 639 | __func__, strerror(errno)); |
| | | 640 | return; |
| | | 641 | } |
| | | 642 | |
| | | 643 | /* add or update existing interfaces */ |
| | | 644 | for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) { |
| | | 645 | if (ifa->ifa_addr == NULL || |
| | | 646 | ifa->ifa_addr->sa_family != AF_LINK) |
| | | 647 | continue; |
| | | 648 | sdl = (struct sockaddr_dl *)(void *)ifa->ifa_addr; |
| | | 649 | drv = bsd_get_drvname(global, ifa->ifa_name); |
| | | 650 | if (drv != NULL && |
| | | 651 | (drv->ifindex != sdl->sdl_index || drv->if_removed)) { |
| | | 652 | wpa_printf(MSG_DEBUG, |
| | | 653 | "RTM_IFANNOUNCE: Interface '%s' added", |
| | | 654 | drv->ifname); |
| | | 655 | drv->ifindex = sdl->sdl_index; |
| | | 656 | drv->if_removed = 0; |
| | | 657 | event.interface_status.ievent = EVENT_INTERFACE_ADDED; |
| | | 658 | os_strlcpy(event.interface_status.ifname, ifa->ifa_name, |
| | | 659 | sizeof(event.interface_status.ifname)); |
| | | 660 | wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, |
| | | 661 | &event); |
| | | 662 | } |
| | | 663 | if (drv == NULL && |
| | | 664 | (drv = bsd_get_drvindex(global, sdl->sdl_index)) != NULL) { |
| | | 665 | /* Driver name is invalid */ |
| | | 666 | wpa_printf(MSG_DEBUG, |
| | | 667 | "RTM_IFANNOUNCE: Interface '%s' removed", |
| | | 668 | drv->ifname); |
| | | 669 | drv->if_removed = 1; |
| | | 670 | event.interface_status.ievent = EVENT_INTERFACE_REMOVED; |
| | | 671 | os_strlcpy(event.interface_status.ifname, drv->ifname, |
| | | 672 | sizeof(event.interface_status.ifname)); |
| | | 673 | wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, |
| | | 674 | &event); |
| | | 675 | } |
| | | 676 | } |
| | | 677 | |
| | | 678 | /* punt missing interfaces and update flags */ |
| | | 679 | dl_list_for_each(drv, &global->ifaces, struct bsd_driver_data, list) { |
| | | 680 | for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) { |
| | | 681 | if (ifa->ifa_addr == NULL || |
| | | 682 | ifa->ifa_addr->sa_family != AF_LINK) |
| | | 683 | continue; |
| | | 684 | sdl = (struct sockaddr_dl *)(void *)ifa->ifa_addr; |
| | | 685 | if (os_strcmp(drv->ifname, ifa->ifa_name) == 0) |
| | | 686 | break; |
| | | 687 | } |
| | | 688 | if (ifa == NULL && !drv->if_removed) { |
| | | 689 | wpa_printf(MSG_DEBUG, |
| | | 690 | "RTM_IFANNOUNCE: Interface '%s' removed", |
| | | 691 | drv->ifname); |
| | | 692 | drv->if_removed = 1; |
| | | 693 | event.interface_status.ievent = EVENT_INTERFACE_REMOVED; |
| | | 694 | os_strlcpy(event.interface_status.ifname, drv->ifname, |
| | | 695 | sizeof(event.interface_status.ifname)); |
| | | 696 | wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, |
| | | 697 | &event); |
| | | 698 | } |
| | | 699 | if (ifa == NULL) |
| | | 700 | continue; |
| | | 701 | |
| | | 702 | if ((ifa->ifa_flags & IFF_UP) == 0 && |
| | | 703 | (drv->flags & IFF_UP) != 0) { |
| | | 704 | wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' DOWN", |
| | | 705 | drv->ifname); |
| | | 706 | wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_DISABLED, |
| | | 707 | NULL); |
| | | 708 | } else if ((ifa->ifa_flags & IFF_UP) != 0 && |
| | | 709 | (drv->flags & IFF_UP) == 0) { |
| | | 710 | wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' UP", |
| | | 711 | drv->ifname); |
| | | 712 | wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED, |
| | | 713 | NULL); |
| | | 714 | } |
| | | 715 | drv->flags = ifa->ifa_flags; |
| | | 716 | } |
| | | 717 | |
| | | 718 | freeifaddrs(ifaddrs); |
| | | 719 | } |
| | | 720 | #endif |
| | | 721 | |
618 | static void | | 722 | static void |
619 | bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx) | | 723 | bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx) |
620 | { | | 724 | { |
621 | char event_buf[2048]; /* max size of a single route(4) msg */ | | 725 | char event_buf[2048]; /* max size of a single route(4) msg */ |
622 | struct bsd_driver_global *global = sock_ctx; | | 726 | struct bsd_driver_global *global = sock_ctx; |
623 | struct bsd_driver_data *drv; | | 727 | struct bsd_driver_data *drv; |
624 | struct if_announcemsghdr *ifan; | | 728 | struct if_announcemsghdr *ifan; |
625 | struct if_msghdr *ifm; | | 729 | struct if_msghdr *ifm; |
626 | struct rt_msghdr *rtm; | | 730 | struct rt_msghdr *rtm; |
627 | union wpa_event_data event; | | 731 | union wpa_event_data event; |
628 | struct ieee80211_michael_event *mic; | | 732 | struct ieee80211_michael_event *mic; |
629 | struct ieee80211_leave_event *leave; | | 733 | struct ieee80211_leave_event *leave; |
630 | struct ieee80211_join_event *join; | | 734 | struct ieee80211_join_event *join; |
631 | int n; | | 735 | int n; |
632 | | | 736 | |
633 | n = read(sock, event_buf, sizeof(event_buf)); | | 737 | n = read(sock, event_buf, sizeof(event_buf)); |
634 | if (n < 0) { | | 738 | if (n < 0) { |
635 | if (errno != EINTR && errno != EAGAIN) | | 739 | if (errno != EINTR && errno != EAGAIN) |
636 | wpa_printf(MSG_ERROR, "%s read() failed: %s", | | 740 | wpa_printf(MSG_ERROR, "%s read() failed: %s", |
637 | __func__, strerror(errno)); | | 741 | __func__, strerror(errno)); |
| | | 742 | #ifdef SO_RERROR |
| | | 743 | if (errno == ENOBUFS) |
| | | 744 | bsd_route_overflow(sock, ctx, sock_ctx); |
| | | 745 | #endif |
638 | return; | | 746 | return; |
639 | } | | 747 | } |
640 | | | 748 | |
641 | rtm = (struct rt_msghdr *) event_buf; | | 749 | rtm = (struct rt_msghdr *) event_buf; |
642 | if (rtm->rtm_version != RTM_VERSION) { | | 750 | if (rtm->rtm_version != RTM_VERSION) { |
643 | wpa_printf(MSG_DEBUG, "Invalid routing message version=%d", | | 751 | wpa_printf(MSG_DEBUG, "Invalid routing message version=%d", |
644 | rtm->rtm_version); | | 752 | rtm->rtm_version); |
645 | return; | | 753 | return; |
646 | } | | 754 | } |
647 | os_memset(&event, 0, sizeof(event)); | | 755 | os_memset(&event, 0, sizeof(event)); |
648 | switch (rtm->rtm_type) { | | 756 | switch (rtm->rtm_type) { |
649 | case RTM_IEEE80211: | | 757 | case RTM_IEEE80211: |
650 | ifan = (struct if_announcemsghdr *) rtm; | | 758 | ifan = (struct if_announcemsghdr *) rtm; |
651 | drv = bsd_get_drvindex(global, ifan->ifan_index); | | 759 | drv = bsd_get_drvindex(global, ifan->ifan_index); |
652 | if (drv == NULL) | | 760 | if (drv == NULL) |
653 | return; | | 761 | return; |
654 | switch (ifan->ifan_what) { | | 762 | switch (ifan->ifan_what) { |
655 | case RTM_IEEE80211_ASSOC: | | 763 | case RTM_IEEE80211_ASSOC: |
656 | case RTM_IEEE80211_REASSOC: | | 764 | case RTM_IEEE80211_REASSOC: |
657 | if (drv->is_ap) | | 765 | if (drv->is_ap) |
658 | break; | | 766 | break; |
659 | wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL); | | 767 | wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL); |
660 | break; | | 768 | break; |
661 | case RTM_IEEE80211_DISASSOC: | | 769 | case RTM_IEEE80211_DISASSOC: |
662 | if (drv->is_ap) | | 770 | if (drv->is_ap) |
663 | break; | | 771 | break; |
664 | wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); | | 772 | wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); |
665 | break; | | 773 | break; |
666 | case RTM_IEEE80211_SCAN: | | 774 | case RTM_IEEE80211_SCAN: |
667 | if (drv->is_ap) | | 775 | if (drv->is_ap) |
668 | break; | | 776 | break; |
669 | wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, | | 777 | wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, |
670 | NULL); | | 778 | NULL); |
671 | break; | | 779 | break; |
672 | case RTM_IEEE80211_LEAVE: | | 780 | case RTM_IEEE80211_LEAVE: |
673 | leave = (struct ieee80211_leave_event *) &ifan[1]; | | 781 | leave = (struct ieee80211_leave_event *) &ifan[1]; |
674 | drv_event_disassoc(drv->ctx, leave->iev_addr); | | 782 | drv_event_disassoc(drv->ctx, leave->iev_addr); |
675 | break; | | 783 | break; |
676 | case RTM_IEEE80211_JOIN: | | 784 | case RTM_IEEE80211_JOIN: |
677 | #ifdef RTM_IEEE80211_REJOIN | | 785 | #ifdef RTM_IEEE80211_REJOIN |
678 | case RTM_IEEE80211_REJOIN: | | 786 | case RTM_IEEE80211_REJOIN: |
679 | #endif | | 787 | #endif |
680 | join = (struct ieee80211_join_event *) &ifan[1]; | | 788 | join = (struct ieee80211_join_event *) &ifan[1]; |
681 | bsd_new_sta(drv, drv->ctx, join->iev_addr); | | 789 | bsd_new_sta(drv, drv->ctx, join->iev_addr); |
682 | break; | | 790 | break; |
683 | case RTM_IEEE80211_REPLAY: | | 791 | case RTM_IEEE80211_REPLAY: |
684 | /* ignore */ | | 792 | /* ignore */ |
685 | break; | | 793 | break; |
686 | case RTM_IEEE80211_MICHAEL: | | 794 | case RTM_IEEE80211_MICHAEL: |
687 | mic = (struct ieee80211_michael_event *) &ifan[1]; | | 795 | mic = (struct ieee80211_michael_event *) &ifan[1]; |
688 | wpa_printf(MSG_DEBUG, | | 796 | wpa_printf(MSG_DEBUG, |
689 | "Michael MIC failure wireless event: " | | 797 | "Michael MIC failure wireless event: " |
690 | "keyix=%u src_addr=" MACSTR, mic->iev_keyix, | | 798 | "keyix=%u src_addr=" MACSTR, mic->iev_keyix, |
691 | MAC2STR(mic->iev_src)); | | 799 | MAC2STR(mic->iev_src)); |
692 | os_memset(&event, 0, sizeof(event)); | | 800 | os_memset(&event, 0, sizeof(event)); |
693 | event.michael_mic_failure.unicast = | | 801 | event.michael_mic_failure.unicast = |
694 | !IEEE80211_IS_MULTICAST(mic->iev_dst); | | 802 | !IEEE80211_IS_MULTICAST(mic->iev_dst); |
695 | event.michael_mic_failure.src = mic->iev_src; | | 803 | event.michael_mic_failure.src = mic->iev_src; |
696 | wpa_supplicant_event(drv->ctx, | | 804 | wpa_supplicant_event(drv->ctx, |
697 | EVENT_MICHAEL_MIC_FAILURE, &event); | | 805 | EVENT_MICHAEL_MIC_FAILURE, &event); |
698 | break; | | 806 | break; |
699 | } | | 807 | } |
700 | break; | | 808 | break; |
701 | case RTM_IFANNOUNCE: | | 809 | case RTM_IFANNOUNCE: |
702 | ifan = (struct if_announcemsghdr *) rtm; | | 810 | ifan = (struct if_announcemsghdr *) rtm; |
703 | switch (ifan->ifan_what) { | | 811 | switch (ifan->ifan_what) { |
704 | case IFAN_DEPARTURE: | | 812 | case IFAN_DEPARTURE: |
705 | drv = bsd_get_drvindex(global, ifan->ifan_index); | | 813 | drv = bsd_get_drvindex(global, ifan->ifan_index); |
706 | if (drv) | | 814 | if (drv) |
707 | drv->if_removed = 1; | | 815 | drv->if_removed = 1; |
708 | event.interface_status.ievent = EVENT_INTERFACE_REMOVED; | | 816 | event.interface_status.ievent = EVENT_INTERFACE_REMOVED; |
709 | break; | | 817 | break; |
710 | case IFAN_ARRIVAL: | | 818 | case IFAN_ARRIVAL: |
711 | drv = bsd_get_drvname(global, ifan->ifan_name); | | 819 | drv = bsd_get_drvname(global, ifan->ifan_name); |
712 | if (drv) { | | 820 | if (drv) { |
713 | drv->ifindex = ifan->ifan_index; | | 821 | drv->ifindex = ifan->ifan_index; |
714 | drv->if_removed = 0; | | 822 | drv->if_removed = 0; |
715 | } | | 823 | } |
716 | event.interface_status.ievent = EVENT_INTERFACE_ADDED; | | 824 | event.interface_status.ievent = EVENT_INTERFACE_ADDED; |
717 | break; | | 825 | break; |
718 | default: | | 826 | default: |
719 | wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: unknown action"); | | 827 | wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: unknown action"); |
720 | return; | | 828 | return; |
721 | } | | 829 | } |
722 | wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: Interface '%s' %s", | | 830 | wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: Interface '%s' %s", |
723 | ifan->ifan_name, | | 831 | ifan->ifan_name, |
724 | ifan->ifan_what == IFAN_DEPARTURE ? | | 832 | ifan->ifan_what == IFAN_DEPARTURE ? |
725 | "removed" : "added"); | | 833 | "removed" : "added"); |
726 | os_strlcpy(event.interface_status.ifname, ifan->ifan_name, | | 834 | os_strlcpy(event.interface_status.ifname, ifan->ifan_name, |
727 | sizeof(event.interface_status.ifname)); | | 835 | sizeof(event.interface_status.ifname)); |
728 | if (drv) { | | 836 | if (drv) { |
729 | wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, | | 837 | wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, |
730 | &event); | | 838 | &event); |
731 | /* | | 839 | /* |
732 | * Set ifindex to zero after sending the event as the | | 840 | * Set ifindex to zero after sending the event as the |
733 | * event might query the driver to ensure a match. | | 841 | * event might query the driver to ensure a match. |
734 | */ | | 842 | */ |
735 | if (ifan->ifan_what == IFAN_DEPARTURE) | | 843 | if (ifan->ifan_what == IFAN_DEPARTURE) |
736 | drv->ifindex = 0; | | 844 | drv->ifindex = 0; |
737 | } else { | | 845 | } else { |
738 | wpa_supplicant_event_global(global->ctx, | | 846 | wpa_supplicant_event_global(global->ctx, |
739 | EVENT_INTERFACE_STATUS, | | 847 | EVENT_INTERFACE_STATUS, |
740 | &event); | | 848 | &event); |
741 | } | | 849 | } |
742 | break; | | 850 | break; |
743 | case RTM_IFINFO: | | 851 | case RTM_IFINFO: |
744 | ifm = (struct if_msghdr *) rtm; | | 852 | ifm = (struct if_msghdr *) rtm; |
745 | drv = bsd_get_drvindex(global, ifm->ifm_index); | | 853 | drv = bsd_get_drvindex(global, ifm->ifm_index); |
746 | if (drv == NULL) | | 854 | if (drv == NULL) |
747 | return; | | 855 | return; |
748 | if ((ifm->ifm_flags & IFF_UP) == 0 && | | 856 | if ((ifm->ifm_flags & IFF_UP) == 0 && |
749 | (drv->flags & IFF_UP) != 0) { | | 857 | (drv->flags & IFF_UP) != 0) { |
750 | wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' DOWN", | | 858 | wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' DOWN", |
751 | drv->ifname); | | 859 | drv->ifname); |
752 | wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_DISABLED, | | 860 | wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_DISABLED, |
753 | NULL); | | 861 | NULL); |
754 | } else if ((ifm->ifm_flags & IFF_UP) != 0 && | | 862 | } else if ((ifm->ifm_flags & IFF_UP) != 0 && |
755 | (drv->flags & IFF_UP) == 0) { | | 863 | (drv->flags & IFF_UP) == 0) { |
756 | wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' UP", | | 864 | wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' UP", |
757 | drv->ifname); | | 865 | drv->ifname); |
758 | wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED, | | 866 | wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED, |
759 | NULL); | | 867 | NULL); |
760 | } | | 868 | } |
761 | drv->flags = ifm->ifm_flags; | | 869 | drv->flags = ifm->ifm_flags; |
762 | break; | | 870 | break; |
763 | } | | 871 | } |
764 | } | | 872 | } |
765 | | | 873 | |
766 | #ifdef HOSTAPD | | 874 | #ifdef HOSTAPD |
767 | | | 875 | |
768 | /* | | 876 | /* |
769 | * Avoid conflicts with hostapd definitions by undefining couple of defines | | 877 | * Avoid conflicts with hostapd definitions by undefining couple of defines |
770 | * from net80211 header files. | | 878 | * from net80211 header files. |
771 | */ | | 879 | */ |
772 | #undef RSN_VERSION | | 880 | #undef RSN_VERSION |
773 | #undef WPA_VERSION | | 881 | #undef WPA_VERSION |
774 | #undef WPA_OUI_TYPE | | 882 | #undef WPA_OUI_TYPE |
775 | | | 883 | |
776 | static int bsd_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, | | 884 | static int bsd_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, |
777 | int reason_code); | | 885 | int reason_code); |
778 | | | 886 | |
779 | static const char * | | 887 | static const char * |
780 | ether_sprintf(const u8 *addr) | | 888 | ether_sprintf(const u8 *addr) |
781 | { | | 889 | { |
782 | static char buf[sizeof(MACSTR)]; | | 890 | static char buf[sizeof(MACSTR)]; |
783 | | | 891 | |
784 | if (addr != NULL) | | 892 | if (addr != NULL) |
785 | snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr)); | | 893 | snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr)); |
786 | else | | 894 | else |
787 | snprintf(buf, sizeof(buf), MACSTR, 0,0,0,0,0,0); | | 895 | snprintf(buf, sizeof(buf), MACSTR, 0,0,0,0,0,0); |
788 | return buf; | | 896 | return buf; |
789 | } | | 897 | } |
790 | | | 898 | |
791 | static int | | 899 | static int |
792 | bsd_set_privacy(void *priv, int enabled) | | 900 | bsd_set_privacy(void *priv, int enabled) |
793 | { | | 901 | { |
794 | wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); | | 902 | wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); |
795 | | | 903 | |
796 | return set80211param(priv, IEEE80211_IOC_PRIVACY, enabled); | | 904 | return set80211param(priv, IEEE80211_IOC_PRIVACY, enabled); |
797 | } | | 905 | } |
798 | | | 906 | |
799 | static int | | 907 | static int |
800 | bsd_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx, | | 908 | bsd_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx, |
801 | u8 *seq) | | 909 | u8 *seq) |
802 | { | | 910 | { |
803 | struct ieee80211req_key wk; | | 911 | struct ieee80211req_key wk; |
804 | | | 912 | |
805 | wpa_printf(MSG_DEBUG, "%s: addr=%s idx=%d", | | 913 | wpa_printf(MSG_DEBUG, "%s: addr=%s idx=%d", |
806 | __func__, ether_sprintf(addr), idx); | | 914 | __func__, ether_sprintf(addr), idx); |
807 | | | 915 | |
808 | memset(&wk, 0, sizeof(wk)); | | 916 | memset(&wk, 0, sizeof(wk)); |
809 | if (addr == NULL) | | 917 | if (addr == NULL) |
810 | memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); | | 918 | memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); |
811 | else | | 919 | else |
812 | memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); | | 920 | memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); |
813 | wk.ik_keyix = idx; | | 921 | wk.ik_keyix = idx; |
814 | | | 922 | |
815 | if (get80211var(priv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk)) < 0) { | | 923 | if (get80211var(priv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk)) < 0) { |
816 | wpa_printf(MSG_INFO, "Failed to get encryption"); | | 924 | wpa_printf(MSG_INFO, "Failed to get encryption"); |
817 | return -1; | | 925 | return -1; |
818 | } | | 926 | } |
819 | | | 927 | |
820 | #ifdef WORDS_BIGENDIAN | | 928 | #ifdef WORDS_BIGENDIAN |
821 | { | | 929 | { |
822 | /* | | 930 | /* |
823 | * wk.ik_keytsc is in host byte order (big endian), need to | | 931 | * wk.ik_keytsc is in host byte order (big endian), need to |
824 | * swap it to match with the byte order used in WPA. | | 932 | * swap it to match with the byte order used in WPA. |
825 | */ | | 933 | */ |
826 | int i; | | 934 | int i; |
827 | u8 tmp[WPA_KEY_RSC_LEN]; | | 935 | u8 tmp[WPA_KEY_RSC_LEN]; |
828 | memcpy(tmp, &wk.ik_keytsc, sizeof(wk.ik_keytsc)); | | 936 | memcpy(tmp, &wk.ik_keytsc, sizeof(wk.ik_keytsc)); |
829 | for (i = 0; i < WPA_KEY_RSC_LEN; i++) { | | 937 | for (i = 0; i < WPA_KEY_RSC_LEN; i++) { |
830 | seq[i] = tmp[WPA_KEY_RSC_LEN - i - 1]; | | 938 | seq[i] = tmp[WPA_KEY_RSC_LEN - i - 1]; |
831 | } | | 939 | } |
832 | } | | 940 | } |
833 | #else /* WORDS_BIGENDIAN */ | | 941 | #else /* WORDS_BIGENDIAN */ |
834 | memcpy(seq, &wk.ik_keytsc, sizeof(wk.ik_keytsc)); | | 942 | memcpy(seq, &wk.ik_keytsc, sizeof(wk.ik_keytsc)); |
835 | #endif /* WORDS_BIGENDIAN */ | | 943 | #endif /* WORDS_BIGENDIAN */ |
836 | return 0; | | 944 | return 0; |
837 | } | | 945 | } |
838 | | | 946 | |
839 | | | 947 | |
840 | static int | | 948 | static int |
841 | bsd_flush(void *priv) | | 949 | bsd_flush(void *priv) |
842 | { | | 950 | { |
843 | u8 allsta[IEEE80211_ADDR_LEN]; | | 951 | u8 allsta[IEEE80211_ADDR_LEN]; |
844 | | | 952 | |
845 | memset(allsta, 0xff, IEEE80211_ADDR_LEN); | | 953 | memset(allsta, 0xff, IEEE80211_ADDR_LEN); |
846 | return bsd_sta_deauth(priv, NULL, allsta, IEEE80211_REASON_AUTH_LEAVE); | | 954 | return bsd_sta_deauth(priv, NULL, allsta, IEEE80211_REASON_AUTH_LEAVE); |
847 | } | | 955 | } |
848 | | | 956 | |
849 | | | 957 | |
850 | static int | | 958 | static int |
851 | bsd_read_sta_driver_data(void *priv, struct hostap_sta_driver_data *data, | | 959 | bsd_read_sta_driver_data(void *priv, struct hostap_sta_driver_data *data, |
852 | const u8 *addr) | | 960 | const u8 *addr) |
853 | { | | 961 | { |
854 | struct ieee80211req_sta_stats stats; | | 962 | struct ieee80211req_sta_stats stats; |
855 | | | 963 | |
856 | memcpy(stats.is_u.macaddr, addr, IEEE80211_ADDR_LEN); | | 964 | memcpy(stats.is_u.macaddr, addr, IEEE80211_ADDR_LEN); |
857 | if (get80211var(priv, IEEE80211_IOC_STA_STATS, &stats, sizeof(stats)) | | 965 | if (get80211var(priv, IEEE80211_IOC_STA_STATS, &stats, sizeof(stats)) |
858 | > 0) { | | 966 | > 0) { |
859 | /* XXX? do packets counts include non-data frames? */ | | 967 | /* XXX? do packets counts include non-data frames? */ |
860 | data->rx_packets = stats.is_stats.ns_rx_data; | | 968 | data->rx_packets = stats.is_stats.ns_rx_data; |
861 | data->rx_bytes = stats.is_stats.ns_rx_bytes; | | 969 | data->rx_bytes = stats.is_stats.ns_rx_bytes; |
862 | data->tx_packets = stats.is_stats.ns_tx_data; | | 970 | data->tx_packets = stats.is_stats.ns_tx_data; |
863 | data->tx_bytes = stats.is_stats.ns_tx_bytes; | | 971 | data->tx_bytes = stats.is_stats.ns_tx_bytes; |
864 | } | | 972 | } |
865 | return 0; | | 973 | return 0; |
866 | } | | 974 | } |
867 | | | 975 | |
868 | static int | | 976 | static int |
869 | bsd_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, int reason_code) | | 977 | bsd_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, int reason_code) |
870 | { | | 978 | { |
871 | return bsd_send_mlme_param(priv, IEEE80211_MLME_DEAUTH, reason_code, | | 979 | return bsd_send_mlme_param(priv, IEEE80211_MLME_DEAUTH, reason_code, |
872 | addr); | | 980 | addr); |
873 | } | | 981 | } |
874 | | | 982 | |
875 | static int | | 983 | static int |
876 | bsd_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr, | | 984 | bsd_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr, |
877 | int reason_code) | | 985 | int reason_code) |
878 | { | | 986 | { |
879 | return bsd_send_mlme_param(priv, IEEE80211_MLME_DISASSOC, reason_code, | | 987 | return bsd_send_mlme_param(priv, IEEE80211_MLME_DISASSOC, reason_code, |
880 | addr); | | 988 | addr); |
881 | } | | 989 | } |
882 | | | 990 | |
883 | static void | | 991 | static void |
884 | handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len) | | 992 | handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len) |
885 | { | | 993 | { |
886 | struct bsd_driver_data *drv = ctx; | | 994 | struct bsd_driver_data *drv = ctx; |
887 | drv_event_eapol_rx(drv->ctx, src_addr, buf, len); | | 995 | drv_event_eapol_rx(drv->ctx, src_addr, buf, len); |
888 | } | | 996 | } |
889 | | | 997 | |
890 | static void * | | 998 | static void * |
891 | bsd_init(struct hostapd_data *hapd, struct wpa_init_params *params) | | 999 | bsd_init(struct hostapd_data *hapd, struct wpa_init_params *params) |
892 | { | | 1000 | { |
893 | struct bsd_driver_data *drv; | | 1001 | struct bsd_driver_data *drv; |
894 | | | 1002 | |
895 | drv = os_zalloc(sizeof(struct bsd_driver_data)); | | 1003 | drv = os_zalloc(sizeof(struct bsd_driver_data)); |
896 | if (drv == NULL) { | | 1004 | if (drv == NULL) { |
897 | wpa_printf(MSG_ERROR, "Could not allocate memory for bsd driver data"); | | 1005 | wpa_printf(MSG_ERROR, "Could not allocate memory for bsd driver data"); |
898 | return NULL; | | 1006 | return NULL; |
899 | } | | 1007 | } |
900 | | | 1008 | |
901 | drv->ifindex = if_nametoindex(params->ifname); | | 1009 | drv->ifindex = if_nametoindex(params->ifname); |
902 | if (drv->ifindex == 0) { | | 1010 | if (drv->ifindex == 0) { |
903 | wpa_printf(MSG_DEBUG, "%s: interface %s does not exist", | | 1011 | wpa_printf(MSG_DEBUG, "%s: interface %s does not exist", |
904 | __func__, params->ifname); | | 1012 | __func__, params->ifname); |
905 | goto bad; | | 1013 | goto bad; |
906 | } | | 1014 | } |
907 | | | 1015 | |
908 | drv->ctx = hapd; | | 1016 | drv->ctx = hapd; |
909 | drv->is_ap = 1; | | 1017 | drv->is_ap = 1; |
910 | drv->global = params->global_priv; | | 1018 | drv->global = params->global_priv; |
911 | os_strlcpy(drv->ifname, params->ifname, sizeof(drv->ifname)); | | 1019 | os_strlcpy(drv->ifname, params->ifname, sizeof(drv->ifname)); |
912 | | | 1020 | |
913 | drv->sock_xmit = l2_packet_init(drv->ifname, NULL, ETH_P_EAPOL, | | 1021 | drv->sock_xmit = l2_packet_init(drv->ifname, NULL, ETH_P_EAPOL, |
914 | handle_read, drv, 0); | | 1022 | handle_read, drv, 0); |
915 | if (drv->sock_xmit == NULL) | | 1023 | if (drv->sock_xmit == NULL) |
916 | goto bad; | | 1024 | goto bad; |
917 | if (l2_packet_get_own_addr(drv->sock_xmit, params->own_addr)) | | 1025 | if (l2_packet_get_own_addr(drv->sock_xmit, params->own_addr)) |
918 | goto bad; | | 1026 | goto bad; |
919 | | | 1027 | |
920 | if (bsd_get_iface_flags(drv) < 0) | | 1028 | if (bsd_get_iface_flags(drv) < 0) |
921 | goto bad; | | 1029 | goto bad; |
922 | | | 1030 | |
923 | if (bsd_set_mediaopt(drv, IFM_OMASK, IFM_IEEE80211_HOSTAP) < 0) { | | 1031 | if (bsd_set_mediaopt(drv, IFM_OMASK, IFM_IEEE80211_HOSTAP) < 0) { |
924 | wpa_printf(MSG_ERROR, "%s: failed to set operation mode", | | 1032 | wpa_printf(MSG_ERROR, "%s: failed to set operation mode", |
925 | __func__); | | 1033 | __func__); |
926 | goto bad; | | 1034 | goto bad; |
927 | } | | 1035 | } |
928 | | | 1036 | |
929 | dl_list_add(&drv->global->ifaces, &drv->list); | | 1037 | dl_list_add(&drv->global->ifaces, &drv->list); |
930 | | | 1038 | |
931 | return drv; | | 1039 | return drv; |
932 | bad: | | 1040 | bad: |
933 | if (drv->sock_xmit != NULL) | | 1041 | if (drv->sock_xmit != NULL) |
934 | l2_packet_deinit(drv->sock_xmit); | | 1042 | l2_packet_deinit(drv->sock_xmit); |
935 | os_free(drv); | | 1043 | os_free(drv); |
936 | return NULL; | | 1044 | return NULL; |
937 | } | | 1045 | } |
938 | | | 1046 | |
939 | | | 1047 | |
940 | static void | | 1048 | static void |
941 | bsd_deinit(void *priv) | | 1049 | bsd_deinit(void *priv) |
942 | { | | 1050 | { |
943 | struct bsd_driver_data *drv = priv; | | 1051 | struct bsd_driver_data *drv = priv; |
944 | | | 1052 | |
945 | if (drv->sock_xmit != NULL) | | 1053 | if (drv->sock_xmit != NULL) |
946 | l2_packet_deinit(drv->sock_xmit); | | 1054 | l2_packet_deinit(drv->sock_xmit); |
947 | os_free(drv); | | 1055 | os_free(drv); |
948 | } | | 1056 | } |
949 | | | 1057 | |
950 | | | 1058 | |
951 | static int | | 1059 | static int |
952 | bsd_set_sta_authorized(void *priv, const u8 *addr, | | 1060 | bsd_set_sta_authorized(void *priv, const u8 *addr, |
953 | unsigned int total_flags, unsigned int flags_or, | | 1061 | unsigned int total_flags, unsigned int flags_or, |
954 | unsigned int flags_and) | | 1062 | unsigned int flags_and) |
955 | { | | 1063 | { |
956 | int authorized = -1; | | 1064 | int authorized = -1; |
957 | | | 1065 | |
958 | /* For now, only support setting Authorized flag */ | | 1066 | /* For now, only support setting Authorized flag */ |
959 | if (flags_or & WPA_STA_AUTHORIZED) | | 1067 | if (flags_or & WPA_STA_AUTHORIZED) |
960 | authorized = 1; | | 1068 | authorized = 1; |
961 | if (!(flags_and & WPA_STA_AUTHORIZED)) | | 1069 | if (!(flags_and & WPA_STA_AUTHORIZED)) |
962 | authorized = 0; | | 1070 | authorized = 0; |
963 | | | 1071 | |
964 | if (authorized < 0) | | 1072 | if (authorized < 0) |
965 | return 0; | | 1073 | return 0; |
966 | | | 1074 | |
967 | return bsd_send_mlme_param(priv, authorized ? | | 1075 | return bsd_send_mlme_param(priv, authorized ? |
968 | IEEE80211_MLME_AUTHORIZE : | | 1076 | IEEE80211_MLME_AUTHORIZE : |
969 | IEEE80211_MLME_UNAUTHORIZE, 0, addr); | | 1077 | IEEE80211_MLME_UNAUTHORIZE, 0, addr); |
970 | } | | 1078 | } |
971 | #else /* HOSTAPD */ | | 1079 | #else /* HOSTAPD */ |
972 | | | 1080 | |
973 | static int | | 1081 | static int |
974 | get80211param(struct bsd_driver_data *drv, int op) | | 1082 | get80211param(struct bsd_driver_data *drv, int op) |
975 | { | | 1083 | { |
976 | struct ieee80211req ireq; | | 1084 | struct ieee80211req ireq; |
977 | | | 1085 | |
978 | if (bsd_get80211(drv, &ireq, op, NULL, 0) < 0) | | 1086 | if (bsd_get80211(drv, &ireq, op, NULL, 0) < 0) |
979 | return -1; | | 1087 | return -1; |
980 | return ireq.i_val; | | 1088 | return ireq.i_val; |
981 | } | | 1089 | } |
982 | | | 1090 | |
983 | static int | | 1091 | static int |
984 | wpa_driver_bsd_get_bssid(void *priv, u8 *bssid) | | 1092 | wpa_driver_bsd_get_bssid(void *priv, u8 *bssid) |
985 | { | | 1093 | { |
986 | struct bsd_driver_data *drv = priv; | | 1094 | struct bsd_driver_data *drv = priv; |
987 | #ifdef SIOCG80211BSSID | | 1095 | #ifdef SIOCG80211BSSID |
988 | struct ieee80211_bssid bs; | | 1096 | struct ieee80211_bssid bs; |
989 | | | 1097 | |
990 | os_strlcpy(bs.i_name, drv->ifname, sizeof(bs.i_name)); | | 1098 | os_strlcpy(bs.i_name, drv->ifname, sizeof(bs.i_name)); |
991 | if (ioctl(drv->global->sock, SIOCG80211BSSID, &bs) < 0) | | 1099 | if (ioctl(drv->global->sock, SIOCG80211BSSID, &bs) < 0) |
992 | return -1; | | 1100 | return -1; |
993 | os_memcpy(bssid, bs.i_bssid, sizeof(bs.i_bssid)); | | 1101 | os_memcpy(bssid, bs.i_bssid, sizeof(bs.i_bssid)); |
994 | return 0; | | 1102 | return 0; |
995 | #else | | 1103 | #else |
996 | return get80211var(drv, IEEE80211_IOC_BSSID, | | 1104 | return get80211var(drv, IEEE80211_IOC_BSSID, |
997 | bssid, IEEE80211_ADDR_LEN) < 0 ? -1 : 0; | | 1105 | bssid, IEEE80211_ADDR_LEN) < 0 ? -1 : 0; |
998 | #endif | | 1106 | #endif |
999 | } | | 1107 | } |
1000 | | | 1108 | |
1001 | static int | | 1109 | static int |
1002 | wpa_driver_bsd_get_ssid(void *priv, u8 *ssid) | | 1110 | wpa_driver_bsd_get_ssid(void *priv, u8 *ssid) |
1003 | { | | 1111 | { |
1004 | struct bsd_driver_data *drv = priv; | | 1112 | struct bsd_driver_data *drv = priv; |
1005 | return bsd_get_ssid(drv, ssid, 0); | | 1113 | return bsd_get_ssid(drv, ssid, 0); |
1006 | } | | 1114 | } |
1007 | | | 1115 | |
1008 | static int | | 1116 | static int |
1009 | wpa_driver_bsd_set_wpa_ie(struct bsd_driver_data *drv, const u8 *wpa_ie, | | 1117 | wpa_driver_bsd_set_wpa_ie(struct bsd_driver_data *drv, const u8 *wpa_ie, |
1010 | size_t wpa_ie_len) | | 1118 | size_t wpa_ie_len) |
1011 | { | | 1119 | { |
1012 | #ifdef IEEE80211_IOC_APPIE | | 1120 | #ifdef IEEE80211_IOC_APPIE |
1013 | return bsd_set_opt_ie(drv, wpa_ie, wpa_ie_len); | | 1121 | return bsd_set_opt_ie(drv, wpa_ie, wpa_ie_len); |
1014 | #else /* IEEE80211_IOC_APPIE */ | | 1122 | #else /* IEEE80211_IOC_APPIE */ |
1015 | return set80211var(drv, IEEE80211_IOC_OPTIE, wpa_ie, wpa_ie_len); | | 1123 | return set80211var(drv, IEEE80211_IOC_OPTIE, wpa_ie, wpa_ie_len); |
1016 | #endif /* IEEE80211_IOC_APPIE */ | | 1124 | #endif /* IEEE80211_IOC_APPIE */ |
1017 | } | | 1125 | } |
1018 | | | 1126 | |
1019 | static int | | 1127 | static int |
1020 | wpa_driver_bsd_set_wpa_internal(void *priv, int wpa, int privacy) | | 1128 | wpa_driver_bsd_set_wpa_internal(void *priv, int wpa, int privacy) |
1021 | { | | 1129 | { |
1022 | int ret = 0; | | 1130 | int ret = 0; |
1023 | | | 1131 | |
1024 | wpa_printf(MSG_DEBUG, "%s: wpa=%d privacy=%d", | | 1132 | wpa_printf(MSG_DEBUG, "%s: wpa=%d privacy=%d", |
1025 | __func__, wpa, privacy); | | 1133 | __func__, wpa, privacy); |
1026 | | | 1134 | |
1027 | if (!wpa && wpa_driver_bsd_set_wpa_ie(priv, NULL, 0) < 0) | | 1135 | if (!wpa && wpa_driver_bsd_set_wpa_ie(priv, NULL, 0) < 0) |
1028 | ret = -1; | | 1136 | ret = -1; |
1029 | if (set80211param(priv, IEEE80211_IOC_PRIVACY, privacy) < 0) | | 1137 | if (set80211param(priv, IEEE80211_IOC_PRIVACY, privacy) < 0) |
1030 | ret = -1; | | 1138 | ret = -1; |
1031 | if (set80211param(priv, IEEE80211_IOC_WPA, wpa) < 0) | | 1139 | if (set80211param(priv, IEEE80211_IOC_WPA, wpa) < 0) |
1032 | ret = -1; | | 1140 | ret = -1; |
1033 | | | 1141 | |
1034 | return ret; | | 1142 | return ret; |
1035 | } | | 1143 | } |
1036 | | | 1144 | |
1037 | static int | | 1145 | static int |
1038 | wpa_driver_bsd_set_wpa(void *priv, int enabled) | | 1146 | wpa_driver_bsd_set_wpa(void *priv, int enabled) |
1039 | { | | 1147 | { |
1040 | wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); | | 1148 | wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); |
1041 | | | 1149 | |
1042 | return wpa_driver_bsd_set_wpa_internal(priv, enabled ? 3 : 0, enabled); | | 1150 | return wpa_driver_bsd_set_wpa_internal(priv, enabled ? 3 : 0, enabled); |
1043 | } | | 1151 | } |
1044 | | | 1152 | |
1045 | static int | | 1153 | static int |
1046 | wpa_driver_bsd_set_countermeasures(void *priv, int enabled) | | 1154 | wpa_driver_bsd_set_countermeasures(void *priv, int enabled) |
1047 | { | | 1155 | { |
1048 | wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); | | 1156 | wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); |
1049 | return set80211param(priv, IEEE80211_IOC_COUNTERMEASURES, enabled); | | 1157 | return set80211param(priv, IEEE80211_IOC_COUNTERMEASURES, enabled); |
1050 | } | | 1158 | } |
1051 | | | 1159 | |
1052 | | | 1160 | |
1053 | static int | | 1161 | static int |
1054 | wpa_driver_bsd_set_drop_unencrypted(void *priv, int enabled) | | 1162 | wpa_driver_bsd_set_drop_unencrypted(void *priv, int enabled) |
1055 | { | | 1163 | { |
1056 | wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); | | 1164 | wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); |
1057 | return set80211param(priv, IEEE80211_IOC_DROPUNENCRYPTED, enabled); | | 1165 | return set80211param(priv, IEEE80211_IOC_DROPUNENCRYPTED, enabled); |
1058 | } | | 1166 | } |
1059 | | | 1167 | |
1060 | static int | | 1168 | static int |
1061 | wpa_driver_bsd_deauthenticate(void *priv, const u8 *addr, int reason_code) | | 1169 | wpa_driver_bsd_deauthenticate(void *priv, const u8 *addr, int reason_code) |
1062 | { | | 1170 | { |
1063 | return bsd_send_mlme_param(priv, IEEE80211_MLME_DEAUTH, reason_code, | | 1171 | return bsd_send_mlme_param(priv, IEEE80211_MLME_DEAUTH, reason_code, |
1064 | addr); | | 1172 | addr); |
1065 | } | | 1173 | } |
1066 | | | 1174 | |
1067 | static int | | 1175 | static int |
1068 | wpa_driver_bsd_set_auth_alg(void *priv, int auth_alg) | | 1176 | wpa_driver_bsd_set_auth_alg(void *priv, int auth_alg) |
1069 | { | | 1177 | { |
1070 | int authmode; | | 1178 | int authmode; |
1071 | | | 1179 | |
1072 | if ((auth_alg & WPA_AUTH_ALG_OPEN) && | | 1180 | if ((auth_alg & WPA_AUTH_ALG_OPEN) && |
1073 | (auth_alg & WPA_AUTH_ALG_SHARED)) | | 1181 | (auth_alg & WPA_AUTH_ALG_SHARED)) |
1074 | authmode = IEEE80211_AUTH_AUTO; | | 1182 | authmode = IEEE80211_AUTH_AUTO; |
1075 | else if (auth_alg & WPA_AUTH_ALG_SHARED) | | 1183 | else if (auth_alg & WPA_AUTH_ALG_SHARED) |
1076 | authmode = IEEE80211_AUTH_SHARED; | | 1184 | authmode = IEEE80211_AUTH_SHARED; |
1077 | else | | 1185 | else |
1078 | authmode = IEEE80211_AUTH_OPEN; | | 1186 | authmode = IEEE80211_AUTH_OPEN; |
1079 | | | 1187 | |
1080 | return set80211param(priv, IEEE80211_IOC_AUTHMODE, authmode); | | 1188 | return set80211param(priv, IEEE80211_IOC_AUTHMODE, authmode); |
1081 | } | | 1189 | } |
1082 | | | 1190 | |
1083 | static void | | 1191 | static void |
1084 | handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len) | | 1192 | handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len) |
1085 | { | | 1193 | { |
1086 | struct bsd_driver_data *drv = ctx; | | 1194 | struct bsd_driver_data *drv = ctx; |
1087 | | | 1195 | |
1088 | drv_event_eapol_rx(drv->ctx, src_addr, buf, len); | | 1196 | drv_event_eapol_rx(drv->ctx, src_addr, buf, len); |
1089 | } | | 1197 | } |
1090 | | | 1198 | |
1091 | static int | | 1199 | static int |
1092 | wpa_driver_bsd_associate(void *priv, struct wpa_driver_associate_params *params) | | 1200 | wpa_driver_bsd_associate(void *priv, struct wpa_driver_associate_params *params) |
1093 | { | | 1201 | { |
1094 | struct bsd_driver_data *drv = priv; | | 1202 | struct bsd_driver_data *drv = priv; |
1095 | struct ieee80211req_mlme mlme; | | 1203 | struct ieee80211req_mlme mlme; |
1096 | u32 mode; | | 1204 | u32 mode; |
1097 | int privacy; | | 1205 | int privacy; |
1098 | int ret = 0; | | 1206 | int ret = 0; |
1099 | | | 1207 | |
1100 | wpa_printf(MSG_DEBUG, | | 1208 | wpa_printf(MSG_DEBUG, |
1101 | "%s: ssid '%.*s' wpa ie len %u pairwise %u group %u key mgmt %u" | | 1209 | "%s: ssid '%.*s' wpa ie len %u pairwise %u group %u key mgmt %u" |
1102 | , __func__ | | 1210 | , __func__ |
1103 | , (unsigned int) params->ssid_len, params->ssid | | 1211 | , (unsigned int) params->ssid_len, params->ssid |
1104 | , (unsigned int) params->wpa_ie_len | | 1212 | , (unsigned int) params->wpa_ie_len |
1105 | , params->pairwise_suite | | 1213 | , params->pairwise_suite |
1106 | , params->group_suite | | 1214 | , params->group_suite |
1107 | , params->key_mgmt_suite | | 1215 | , params->key_mgmt_suite |
1108 | ); | | 1216 | ); |
1109 | | | 1217 | |
1110 | switch (params->mode) { | | 1218 | switch (params->mode) { |
1111 | case IEEE80211_MODE_INFRA: | | 1219 | case IEEE80211_MODE_INFRA: |
1112 | mode = 0 /* STA */; | | 1220 | mode = 0 /* STA */; |
1113 | break; | | 1221 | break; |
1114 | case IEEE80211_MODE_IBSS: | | 1222 | case IEEE80211_MODE_IBSS: |
1115 | mode = IFM_IEEE80211_IBSS; | | 1223 | mode = IFM_IEEE80211_IBSS; |
1116 | break; | | 1224 | break; |
1117 | case IEEE80211_MODE_AP: | | 1225 | case IEEE80211_MODE_AP: |
1118 | mode = IFM_IEEE80211_HOSTAP; | | 1226 | mode = IFM_IEEE80211_HOSTAP; |
1119 | break; | | 1227 | break; |
1120 | default: | | 1228 | default: |
1121 | wpa_printf(MSG_ERROR, "%s: unknown operation mode", __func__); | | 1229 | wpa_printf(MSG_ERROR, "%s: unknown operation mode", __func__); |
1122 | return -1; | | 1230 | return -1; |
1123 | } | | 1231 | } |
1124 | if (bsd_set_mediaopt(drv, IFM_OMASK, mode) < 0) { | | 1232 | if (bsd_set_mediaopt(drv, IFM_OMASK, mode) < 0) { |
1125 | wpa_printf(MSG_ERROR, "%s: failed to set operation mode", | | 1233 | wpa_printf(MSG_ERROR, "%s: failed to set operation mode", |
1126 | __func__); | | 1234 | __func__); |
1127 | return -1; | | 1235 | return -1; |
1128 | } | | 1236 | } |
1129 | | | 1237 | |
1130 | if (params->mode == IEEE80211_MODE_AP) { | | 1238 | if (params->mode == IEEE80211_MODE_AP) { |
1131 | drv->sock_xmit = l2_packet_init(drv->ifname, NULL, ETH_P_EAPOL, | | 1239 | drv->sock_xmit = l2_packet_init(drv->ifname, NULL, ETH_P_EAPOL, |
1132 | handle_read, drv, 0); | | 1240 | handle_read, drv, 0); |
1133 | if (drv->sock_xmit == NULL) | | 1241 | if (drv->sock_xmit == NULL) |
1134 | return -1; | | 1242 | return -1; |
1135 | drv->is_ap = 1; | | 1243 | drv->is_ap = 1; |
1136 | return 0; | | 1244 | return 0; |
1137 | } | | 1245 | } |
1138 | | | 1246 | |
1139 | if (wpa_driver_bsd_set_drop_unencrypted(drv, params->drop_unencrypted) | | 1247 | if (wpa_driver_bsd_set_drop_unencrypted(drv, params->drop_unencrypted) |
1140 | < 0) | | 1248 | < 0) |
1141 | ret = -1; | | 1249 | ret = -1; |
1142 | if (wpa_driver_bsd_set_auth_alg(drv, params->auth_alg) < 0) | | 1250 | if (wpa_driver_bsd_set_auth_alg(drv, params->auth_alg) < 0) |
1143 | ret = -1; | | 1251 | ret = -1; |
1144 | /* XXX error handling is wrong but unclear what to do... */ | | 1252 | /* XXX error handling is wrong but unclear what to do... */ |
1145 | if (wpa_driver_bsd_set_wpa_ie(drv, params->wpa_ie, params->wpa_ie_len) < 0) | | 1253 | if (wpa_driver_bsd_set_wpa_ie(drv, params->wpa_ie, params->wpa_ie_len) < 0) |
1146 | return -1; | | 1254 | return -1; |
1147 | | | 1255 | |
1148 | privacy = !(params->pairwise_suite == WPA_CIPHER_NONE && | | 1256 | privacy = !(params->pairwise_suite == WPA_CIPHER_NONE && |
1149 | params->group_suite == WPA_CIPHER_NONE && | | 1257 | params->group_suite == WPA_CIPHER_NONE && |
1150 | params->key_mgmt_suite == WPA_KEY_MGMT_NONE && | | 1258 | params->key_mgmt_suite == WPA_KEY_MGMT_NONE && |
1151 | params->wpa_ie_len == 0); | | 1259 | params->wpa_ie_len == 0); |
1152 | wpa_printf(MSG_DEBUG, "%s: set PRIVACY %u", __func__, privacy); | | 1260 | wpa_printf(MSG_DEBUG, "%s: set PRIVACY %u", __func__, privacy); |
1153 | | | 1261 | |
1154 | if (set80211param(drv, IEEE80211_IOC_PRIVACY, privacy) < 0) | | 1262 | if (set80211param(drv, IEEE80211_IOC_PRIVACY, privacy) < 0) |
1155 | return -1; | | 1263 | return -1; |
1156 | | | 1264 | |
1157 | if (params->wpa_ie_len && | | 1265 | if (params->wpa_ie_len && |
1158 | set80211param(drv, IEEE80211_IOC_WPA, | | 1266 | set80211param(drv, IEEE80211_IOC_WPA, |
1159 | params->wpa_ie[0] == WLAN_EID_RSN ? 2 : 1) < 0) | | 1267 | params->wpa_ie[0] == WLAN_EID_RSN ? 2 : 1) < 0) |
1160 | return -1; | | 1268 | return -1; |
1161 | | | 1269 | |
1162 | os_memset(&mlme, 0, sizeof(mlme)); | | 1270 | os_memset(&mlme, 0, sizeof(mlme)); |
1163 | mlme.im_op = IEEE80211_MLME_ASSOC; | | 1271 | mlme.im_op = IEEE80211_MLME_ASSOC; |
1164 | if (params->ssid != NULL) | | 1272 | if (params->ssid != NULL) |
1165 | os_memcpy(mlme.im_ssid, params->ssid, params->ssid_len); | | 1273 | os_memcpy(mlme.im_ssid, params->ssid, params->ssid_len); |
1166 | mlme.im_ssid_len = params->ssid_len; | | 1274 | mlme.im_ssid_len = params->ssid_len; |
1167 | if (params->bssid != NULL) | | 1275 | if (params->bssid != NULL) |
1168 | os_memcpy(mlme.im_macaddr, params->bssid, IEEE80211_ADDR_LEN); | | 1276 | os_memcpy(mlme.im_macaddr, params->bssid, IEEE80211_ADDR_LEN); |
1169 | if (set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)) < 0) | | 1277 | if (set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)) < 0) |
1170 | return -1; | | 1278 | return -1; |
1171 | return ret; | | 1279 | return ret; |
1172 | } | | 1280 | } |
1173 | | | 1281 | |
1174 | static int | | 1282 | static int |
1175 | wpa_driver_bsd_scan(void *priv, struct wpa_driver_scan_params *params) | | 1283 | wpa_driver_bsd_scan(void *priv, struct wpa_driver_scan_params *params) |
1176 | { | | 1284 | { |
1177 | struct bsd_driver_data *drv = priv; | | 1285 | struct bsd_driver_data *drv = priv; |
1178 | #ifdef IEEE80211_IOC_SCAN_MAX_SSID | | 1286 | #ifdef IEEE80211_IOC_SCAN_MAX_SSID |
1179 | struct ieee80211_scan_req sr; | | 1287 | struct ieee80211_scan_req sr; |
1180 | int i; | | 1288 | int i; |
1181 | #endif /* IEEE80211_IOC_SCAN_MAX_SSID */ | | 1289 | #endif /* IEEE80211_IOC_SCAN_MAX_SSID */ |
1182 | | | 1290 | |
1183 | if (bsd_set_mediaopt(drv, IFM_OMASK, 0 /* STA */) < 0) { | | 1291 | if (bsd_set_mediaopt(drv, IFM_OMASK, 0 /* STA */) < 0) { |
1184 | wpa_printf(MSG_ERROR, "%s: failed to set operation mode", | | 1292 | wpa_printf(MSG_ERROR, "%s: failed to set operation mode", |
1185 | __func__); | | 1293 | __func__); |
1186 | return -1; | | 1294 | return -1; |
1187 | } | | 1295 | } |
1188 | | | 1296 | |
1189 | if (set80211param(drv, IEEE80211_IOC_ROAMING, | | 1297 | if (set80211param(drv, IEEE80211_IOC_ROAMING, |
1190 | IEEE80211_ROAMING_MANUAL) < 0) { | | 1298 | IEEE80211_ROAMING_MANUAL) < 0) { |
1191 | wpa_printf(MSG_ERROR, "%s: failed to set " | | 1299 | wpa_printf(MSG_ERROR, "%s: failed to set " |
1192 | "wpa_supplicant-based roaming: %s", __func__, | | 1300 | "wpa_supplicant-based roaming: %s", __func__, |
1193 | strerror(errno)); | | 1301 | strerror(errno)); |
1194 | return -1; | | 1302 | return -1; |
1195 | } | | 1303 | } |
1196 | | | 1304 | |
1197 | if (wpa_driver_bsd_set_wpa(drv, 1) < 0) { | | 1305 | if (wpa_driver_bsd_set_wpa(drv, 1) < 0) { |
1198 | wpa_printf(MSG_ERROR, "%s: failed to set wpa: %s", __func__, | | 1306 | wpa_printf(MSG_ERROR, "%s: failed to set wpa: %s", __func__, |
1199 | strerror(errno)); | | 1307 | strerror(errno)); |
1200 | return -1; | | 1308 | return -1; |
1201 | } | | 1309 | } |
1202 | | | 1310 | |
1203 | /* NB: interface must be marked UP to do a scan */ | | 1311 | /* NB: interface must be marked UP to do a scan */ |
1204 | if (!(drv->flags & IFF_UP)) { | | 1312 | if (!(drv->flags & IFF_UP)) { |
1205 | wpa_printf(MSG_DEBUG, "%s: interface is not up, cannot scan", | | 1313 | wpa_printf(MSG_DEBUG, "%s: interface is not up, cannot scan", |
1206 | __func__); | | 1314 | __func__); |
1207 | return -1; | | 1315 | return -1; |
1208 | } | | 1316 | } |
1209 | | | 1317 | |
1210 | #ifdef IEEE80211_IOC_SCAN_MAX_SSID | | 1318 | #ifdef IEEE80211_IOC_SCAN_MAX_SSID |
1211 | os_memset(&sr, 0, sizeof(sr)); | | 1319 | os_memset(&sr, 0, sizeof(sr)); |
1212 | sr.sr_flags = IEEE80211_IOC_SCAN_ACTIVE | IEEE80211_IOC_SCAN_ONCE | | | 1320 | sr.sr_flags = IEEE80211_IOC_SCAN_ACTIVE | IEEE80211_IOC_SCAN_ONCE | |
1213 | IEEE80211_IOC_SCAN_NOJOIN; | | 1321 | IEEE80211_IOC_SCAN_NOJOIN; |
1214 | sr.sr_duration = IEEE80211_IOC_SCAN_FOREVER; | | 1322 | sr.sr_duration = IEEE80211_IOC_SCAN_FOREVER; |
1215 | if (params->num_ssids > 0) { | | 1323 | if (params->num_ssids > 0) { |
1216 | sr.sr_nssid = params->num_ssids; | | 1324 | sr.sr_nssid = params->num_ssids; |
1217 | #if 0 | | 1325 | #if 0 |
1218 | /* Boundary check is done by upper layer */ | | 1326 | /* Boundary check is done by upper layer */ |
1219 | if (sr.sr_nssid > IEEE80211_IOC_SCAN_MAX_SSID) | | 1327 | if (sr.sr_nssid > IEEE80211_IOC_SCAN_MAX_SSID) |
1220 | sr.sr_nssid = IEEE80211_IOC_SCAN_MAX_SSID; | | 1328 | sr.sr_nssid = IEEE80211_IOC_SCAN_MAX_SSID; |
1221 | #endif | | 1329 | #endif |
1222 | | | 1330 | |
1223 | /* NB: check scan cache first */ | | 1331 | /* NB: check scan cache first */ |
1224 | sr.sr_flags |= IEEE80211_IOC_SCAN_CHECK; | | 1332 | sr.sr_flags |= IEEE80211_IOC_SCAN_CHECK; |
1225 | } | | 1333 | } |
1226 | for (i = 0; i < sr.sr_nssid; i++) { | | 1334 | for (i = 0; i < sr.sr_nssid; i++) { |
1227 | sr.sr_ssid[i].len = params->ssids[i].ssid_len; | | 1335 | sr.sr_ssid[i].len = params->ssids[i].ssid_len; |
1228 | os_memcpy(sr.sr_ssid[i].ssid, params->ssids[i].ssid, | | 1336 | os_memcpy(sr.sr_ssid[i].ssid, params->ssids[i].ssid, |
1229 | sr.sr_ssid[i].len); | | 1337 | sr.sr_ssid[i].len); |
1230 | } | | 1338 | } |
1231 | | | 1339 | |
1232 | /* NB: net80211 delivers a scan complete event so no need to poll */ | | 1340 | /* NB: net80211 delivers a scan complete event so no need to poll */ |
1233 | return set80211var(drv, IEEE80211_IOC_SCAN_REQ, &sr, sizeof(sr)); | | 1341 | return set80211var(drv, IEEE80211_IOC_SCAN_REQ, &sr, sizeof(sr)); |
1234 | #else /* IEEE80211_IOC_SCAN_MAX_SSID */ | | 1342 | #else /* IEEE80211_IOC_SCAN_MAX_SSID */ |
1235 | /* set desired ssid before scan */ | | 1343 | /* set desired ssid before scan */ |
1236 | if (bsd_set_ssid(drv, params->ssids[0].ssid, | | 1344 | if (bsd_set_ssid(drv, params->ssids[0].ssid, |
1237 | params->ssids[0].ssid_len) < 0) | | 1345 | params->ssids[0].ssid_len) < 0) |
1238 | return -1; | | 1346 | return -1; |
1239 | | | 1347 | |
1240 | /* NB: net80211 delivers a scan complete event so no need to poll */ | | 1348 | /* NB: net80211 delivers a scan complete event so no need to poll */ |
1241 | return set80211param(drv, IEEE80211_IOC_SCAN_REQ, 0); | | 1349 | return set80211param(drv, IEEE80211_IOC_SCAN_REQ, 0); |
1242 | #endif /* IEEE80211_IOC_SCAN_MAX_SSID */ | | 1350 | #endif /* IEEE80211_IOC_SCAN_MAX_SSID */ |
1243 | } | | 1351 | } |
1244 | | | 1352 | |
1245 | static void | | 1353 | static void |
1246 | wpa_driver_bsd_add_scan_entry(struct wpa_scan_results *res, | | 1354 | wpa_driver_bsd_add_scan_entry(struct wpa_scan_results *res, |
1247 | struct ieee80211req_scan_result *sr) | | 1355 | struct ieee80211req_scan_result *sr) |
1248 | { | | 1356 | { |
1249 | struct wpa_scan_res *result, **tmp; | | 1357 | struct wpa_scan_res *result, **tmp; |
1250 | size_t extra_len; | | 1358 | size_t extra_len; |
1251 | u8 *pos; | | 1359 | u8 *pos; |
1252 | | | 1360 | |
1253 | extra_len = 2 + sr->isr_ssid_len; | | 1361 | extra_len = 2 + sr->isr_ssid_len; |
1254 | extra_len += 2 + sr->isr_nrates; | | 1362 | extra_len += 2 + sr->isr_nrates; |
1255 | extra_len += 3; /* ERP IE */ | | 1363 | extra_len += 3; /* ERP IE */ |
1256 | extra_len += sr->isr_ie_len; | | 1364 | extra_len += sr->isr_ie_len; |
1257 | | | 1365 | |
1258 | result = os_zalloc(sizeof(*result) + extra_len); | | 1366 | result = os_zalloc(sizeof(*result) + extra_len); |
1259 | if (result == NULL) | | 1367 | if (result == NULL) |
1260 | return; | | 1368 | return; |
1261 | os_memcpy(result->bssid, sr->isr_bssid, ETH_ALEN); | | 1369 | os_memcpy(result->bssid, sr->isr_bssid, ETH_ALEN); |
1262 | result->freq = sr->isr_freq; | | 1370 | result->freq = sr->isr_freq; |
1263 | result->beacon_int = sr->isr_intval; | | 1371 | result->beacon_int = sr->isr_intval; |
1264 | result->caps = sr->isr_capinfo; | | 1372 | result->caps = sr->isr_capinfo; |
1265 | result->qual = sr->isr_rssi; | | 1373 | result->qual = sr->isr_rssi; |
1266 | result->noise = sr->isr_noise; | | 1374 | result->noise = sr->isr_noise; |
1267 | | | 1375 | |
1268 | #ifdef __FreeBSD__ | | 1376 | #ifdef __FreeBSD__ |
1269 | /* | | 1377 | /* |
1270 | * the rssi value reported by the kernel is in 0.5dB steps relative to | | 1378 | * the rssi value reported by the kernel is in 0.5dB steps relative to |
1271 | * the reported noise floor. see ieee80211_node.h for details. | | 1379 | * the reported noise floor. see ieee80211_node.h for details. |
1272 | */ | | 1380 | */ |
1273 | result->level = sr->isr_rssi / 2 + sr->isr_noise; | | 1381 | result->level = sr->isr_rssi / 2 + sr->isr_noise; |
1274 | #else | | 1382 | #else |
1275 | result->level = sr->isr_rssi; | | 1383 | result->level = sr->isr_rssi; |
1276 | #endif | | 1384 | #endif |
1277 | | | 1385 | |
1278 | pos = (u8 *)(result + 1); | | 1386 | pos = (u8 *)(result + 1); |
1279 | | | 1387 | |
1280 | *pos++ = WLAN_EID_SSID; | | 1388 | *pos++ = WLAN_EID_SSID; |
1281 | *pos++ = sr->isr_ssid_len; | | 1389 | *pos++ = sr->isr_ssid_len; |
1282 | os_memcpy(pos, sr + 1, sr->isr_ssid_len); | | 1390 | os_memcpy(pos, sr + 1, sr->isr_ssid_len); |
1283 | pos += sr->isr_ssid_len; | | 1391 | pos += sr->isr_ssid_len; |
1284 | | | 1392 | |
1285 | /* | | 1393 | /* |
1286 | * Deal all rates as supported rate. | | 1394 | * Deal all rates as supported rate. |
1287 | * Because net80211 doesn't report extended supported rate or not. | | 1395 | * Because net80211 doesn't report extended supported rate or not. |
1288 | */ | | 1396 | */ |
1289 | *pos++ = WLAN_EID_SUPP_RATES; | | 1397 | *pos++ = WLAN_EID_SUPP_RATES; |
1290 | *pos++ = sr->isr_nrates; | | 1398 | *pos++ = sr->isr_nrates; |
1291 | os_memcpy(pos, sr->isr_rates, sr->isr_nrates); | | 1399 | os_memcpy(pos, sr->isr_rates, sr->isr_nrates); |
1292 | pos += sr->isr_nrates; | | 1400 | pos += sr->isr_nrates; |
1293 | | | 1401 | |
1294 | *pos++ = WLAN_EID_ERP_INFO; | | 1402 | *pos++ = WLAN_EID_ERP_INFO; |
1295 | *pos++ = 1; | | 1403 | *pos++ = 1; |
1296 | *pos++ = sr->isr_erp; | | 1404 | *pos++ = sr->isr_erp; |
1297 | | | 1405 | |
1298 | #if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) | | 1406 | #if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) |
1299 | os_memcpy(pos, (u8 *)(sr + 1) + sr->isr_ssid_len + sr->isr_meshid_len, | | 1407 | os_memcpy(pos, (u8 *)(sr + 1) + sr->isr_ssid_len + sr->isr_meshid_len, |
1300 | sr->isr_ie_len); | | 1408 | sr->isr_ie_len); |
1301 | #else | | 1409 | #else |
1302 | os_memcpy(pos, (u8 *)(sr + 1) + sr->isr_ssid_len, sr->isr_ie_len); | | 1410 | os_memcpy(pos, (u8 *)(sr + 1) + sr->isr_ssid_len, sr->isr_ie_len); |
1303 | #endif | | 1411 | #endif |
1304 | pos += sr->isr_ie_len; | | 1412 | pos += sr->isr_ie_len; |
1305 | | | 1413 | |
1306 | result->ie_len = pos - (u8 *)(result + 1); | | 1414 | result->ie_len = pos - (u8 *)(result + 1); |
1307 | | | 1415 | |
1308 | tmp = os_realloc_array(res->res, res->num + 1, | | 1416 | tmp = os_realloc_array(res->res, res->num + 1, |
1309 | sizeof(struct wpa_scan_res *)); | | 1417 | sizeof(struct wpa_scan_res *)); |
1310 | if (tmp == NULL) { | | 1418 | if (tmp == NULL) { |
1311 | os_free(result); | | 1419 | os_free(result); |
1312 | return; | | 1420 | return; |
1313 | } | | 1421 | } |
1314 | tmp[res->num++] = result; | | 1422 | tmp[res->num++] = result; |
1315 | res->res = tmp; | | 1423 | res->res = tmp; |
1316 | } | | 1424 | } |
1317 | | | 1425 | |
1318 | struct wpa_scan_results * | | 1426 | struct wpa_scan_results * |
1319 | wpa_driver_bsd_get_scan_results2(void *priv) | | 1427 | wpa_driver_bsd_get_scan_results2(void *priv) |
1320 | { | | 1428 | { |
1321 | struct ieee80211req_scan_result *sr; | | 1429 | struct ieee80211req_scan_result *sr; |
1322 | struct wpa_scan_results *res; | | 1430 | struct wpa_scan_results *res; |
1323 | int len, rest; | | 1431 | int len, rest; |
1324 | uint8_t buf[24*1024], *pos; | | 1432 | uint8_t buf[24*1024], *pos; |
1325 | | | 1433 | |
1326 | len = get80211var(priv, IEEE80211_IOC_SCAN_RESULTS, buf, 24*1024); | | 1434 | len = get80211var(priv, IEEE80211_IOC_SCAN_RESULTS, buf, 24*1024); |
1327 | if (len < 0) | | 1435 | if (len < 0) |
1328 | return NULL; | | 1436 | return NULL; |
1329 | | | 1437 | |
1330 | res = os_zalloc(sizeof(*res)); | | 1438 | res = os_zalloc(sizeof(*res)); |
1331 | if (res == NULL) | | 1439 | if (res == NULL) |
1332 | return NULL; | | 1440 | return NULL; |
1333 | | | 1441 | |
1334 | pos = buf; | | 1442 | pos = buf; |
1335 | rest = len; | | 1443 | rest = len; |
1336 | while (rest >= sizeof(struct ieee80211req_scan_result)) { | | 1444 | while (rest >= sizeof(struct ieee80211req_scan_result)) { |
1337 | sr = (struct ieee80211req_scan_result *)pos; | | 1445 | sr = (struct ieee80211req_scan_result *)pos; |
1338 | wpa_driver_bsd_add_scan_entry(res, sr); | | 1446 | wpa_driver_bsd_add_scan_entry(res, sr); |
1339 | pos += sr->isr_len; | | 1447 | pos += sr->isr_len; |
1340 | rest -= sr->isr_len; | | 1448 | rest -= sr->isr_len; |
1341 | } | | 1449 | } |
1342 | | | 1450 | |
1343 | wpa_printf(MSG_DEBUG, "Received %d bytes of scan results (%lu BSSes)", | | 1451 | wpa_printf(MSG_DEBUG, "Received %d bytes of scan results (%lu BSSes)", |
1344 | len, (unsigned long)res->num); | | 1452 | len, (unsigned long)res->num); |
1345 | | | 1453 | |
1346 | return res; | | 1454 | return res; |
1347 | } | | 1455 | } |
1348 | | | 1456 | |
1349 | static int wpa_driver_bsd_capa(struct bsd_driver_data *drv) | | 1457 | static int wpa_driver_bsd_capa(struct bsd_driver_data *drv) |
1350 | { | | 1458 | { |
1351 | #ifdef IEEE80211_IOC_DEVCAPS | | 1459 | #ifdef IEEE80211_IOC_DEVCAPS |
1352 | /* kernel definitions copied from net80211/ieee80211_var.h */ | | 1460 | /* kernel definitions copied from net80211/ieee80211_var.h */ |
1353 | #define IEEE80211_CIPHER_WEP 0 | | 1461 | #define IEEE80211_CIPHER_WEP 0 |
1354 | #define IEEE80211_CIPHER_TKIP 1 | | 1462 | #define IEEE80211_CIPHER_TKIP 1 |
1355 | #define IEEE80211_CIPHER_AES_CCM 3 | | 1463 | #define IEEE80211_CIPHER_AES_CCM 3 |
1356 | #define IEEE80211_CRYPTO_WEP (1<<IEEE80211_CIPHER_WEP) | | 1464 | #define IEEE80211_CRYPTO_WEP (1<<IEEE80211_CIPHER_WEP) |
1357 | #define IEEE80211_CRYPTO_TKIP (1<<IEEE80211_CIPHER_TKIP) | | 1465 | #define IEEE80211_CRYPTO_TKIP (1<<IEEE80211_CIPHER_TKIP) |
1358 | #define IEEE80211_CRYPTO_AES_CCM (1<<IEEE80211_CIPHER_AES_CCM) | | 1466 | #define IEEE80211_CRYPTO_AES_CCM (1<<IEEE80211_CIPHER_AES_CCM) |
1359 | #define IEEE80211_C_HOSTAP 0x00000400 /* CAPABILITY: HOSTAP avail */ | | 1467 | #define IEEE80211_C_HOSTAP 0x00000400 /* CAPABILITY: HOSTAP avail */ |
1360 | #define IEEE80211_C_WPA1 0x00800000 /* CAPABILITY: WPA1 avail */ | | 1468 | #define IEEE80211_C_WPA1 0x00800000 /* CAPABILITY: WPA1 avail */ |
1361 | #define IEEE80211_C_WPA2 0x01000000 /* CAPABILITY: WPA2 avail */ | | 1469 | #define IEEE80211_C_WPA2 0x01000000 /* CAPABILITY: WPA2 avail */ |
1362 | struct ieee80211_devcaps_req devcaps; | | 1470 | struct ieee80211_devcaps_req devcaps; |
1363 | | | 1471 | |
1364 | if (get80211var(drv, IEEE80211_IOC_DEVCAPS, &devcaps, | | 1472 | if (get80211var(drv, IEEE80211_IOC_DEVCAPS, &devcaps, |
1365 | sizeof(devcaps)) < 0) { | | 1473 | sizeof(devcaps)) < 0) { |
1366 | wpa_printf(MSG_ERROR, "failed to IEEE80211_IOC_DEVCAPS: %s", | | 1474 | wpa_printf(MSG_ERROR, "failed to IEEE80211_IOC_DEVCAPS: %s", |
1367 | strerror(errno)); | | 1475 | strerror(errno)); |
1368 | return -1; | | 1476 | return -1; |
1369 | } | | 1477 | } |
1370 | | | 1478 | |
1371 | wpa_printf(MSG_DEBUG, "%s: drivercaps=0x%08x,cryptocaps=0x%08x", | | 1479 | wpa_printf(MSG_DEBUG, "%s: drivercaps=0x%08x,cryptocaps=0x%08x", |
1372 | __func__, devcaps.dc_drivercaps, devcaps.dc_cryptocaps); | | 1480 | __func__, devcaps.dc_drivercaps, devcaps.dc_cryptocaps); |
1373 | | | 1481 | |
1374 | if (devcaps.dc_drivercaps & IEEE80211_C_WPA1) | | 1482 | if (devcaps.dc_drivercaps & IEEE80211_C_WPA1) |
1375 | drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA | | | 1483 | drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA | |
1376 | WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK; | | 1484 | WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK; |
1377 | if (devcaps.dc_drivercaps & IEEE80211_C_WPA2) | | 1485 | if (devcaps.dc_drivercaps & IEEE80211_C_WPA2) |
1378 | drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | | | 1486 | drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | |
1379 | WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK; | | 1487 | WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK; |
1380 | | | 1488 | |
1381 | if (devcaps.dc_cryptocaps & IEEE80211_CRYPTO_WEP) | | 1489 | if (devcaps.dc_cryptocaps & IEEE80211_CRYPTO_WEP) |
1382 | drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 | | | 1490 | drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 | |
1383 | WPA_DRIVER_CAPA_ENC_WEP104; | | 1491 | WPA_DRIVER_CAPA_ENC_WEP104; |
1384 | if (devcaps.dc_cryptocaps & IEEE80211_CRYPTO_TKIP) | | 1492 | if (devcaps.dc_cryptocaps & IEEE80211_CRYPTO_TKIP) |
1385 | drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP; | | 1493 | drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP; |
1386 | if (devcaps.dc_cryptocaps & IEEE80211_CRYPTO_AES_CCM) | | 1494 | if (devcaps.dc_cryptocaps & IEEE80211_CRYPTO_AES_CCM) |
1387 | drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP; | | 1495 | drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP; |
1388 | | | 1496 | |
1389 | if (devcaps.dc_drivercaps & IEEE80211_C_HOSTAP) | | 1497 | if (devcaps.dc_drivercaps & IEEE80211_C_HOSTAP) |
1390 | drv->capa.flags |= WPA_DRIVER_FLAGS_AP; | | 1498 | drv->capa.flags |= WPA_DRIVER_FLAGS_AP; |
1391 | #undef IEEE80211_CIPHER_WEP | | 1499 | #undef IEEE80211_CIPHER_WEP |
1392 | #undef IEEE80211_CIPHER_TKIP | | 1500 | #undef IEEE80211_CIPHER_TKIP |
1393 | #undef IEEE80211_CIPHER_AES_CCM | | 1501 | #undef IEEE80211_CIPHER_AES_CCM |
1394 | #undef IEEE80211_CRYPTO_WEP | | 1502 | #undef IEEE80211_CRYPTO_WEP |
1395 | #undef IEEE80211_CRYPTO_TKIP | | 1503 | #undef IEEE80211_CRYPTO_TKIP |
1396 | #undef IEEE80211_CRYPTO_AES_CCM | | 1504 | #undef IEEE80211_CRYPTO_AES_CCM |
1397 | #undef IEEE80211_C_HOSTAP | | 1505 | #undef IEEE80211_C_HOSTAP |
1398 | #undef IEEE80211_C_WPA1 | | 1506 | #undef IEEE80211_C_WPA1 |
1399 | #undef IEEE80211_C_WPA2 | | 1507 | #undef IEEE80211_C_WPA2 |
1400 | #else /* IEEE80211_IOC_DEVCAPS */ | | 1508 | #else /* IEEE80211_IOC_DEVCAPS */ |
1401 | /* For now, assume TKIP, CCMP, WPA, WPA2 are supported */ | | 1509 | /* For now, assume TKIP, CCMP, WPA, WPA2 are supported */ |
1402 | drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA | | | 1510 | drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA | |
1403 | WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | | | 1511 | WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | |
1404 | WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | | | 1512 | WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | |
1405 | WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK; | | 1513 | WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK; |
1406 | drv->capa.enc = WPA_DRIVER_CAPA_ENC_WEP40 | | | 1514 | drv->capa.enc = WPA_DRIVER_CAPA_ENC_WEP40 | |
1407 | WPA_DRIVER_CAPA_ENC_WEP104 | | | 1515 | WPA_DRIVER_CAPA_ENC_WEP104 | |
1408 | WPA_DRIVER_CAPA_ENC_TKIP | | | 1516 | WPA_DRIVER_CAPA_ENC_TKIP | |
1409 | WPA_DRIVER_CAPA_ENC_CCMP; | | 1517 | WPA_DRIVER_CAPA_ENC_CCMP; |
1410 | drv->capa.flags |= WPA_DRIVER_FLAGS_AP; | | 1518 | drv->capa.flags |= WPA_DRIVER_FLAGS_AP; |
1411 | #endif /* IEEE80211_IOC_DEVCAPS */ | | 1519 | #endif /* IEEE80211_IOC_DEVCAPS */ |
1412 | #ifdef IEEE80211_IOC_SCAN_MAX_SSID | | 1520 | #ifdef IEEE80211_IOC_SCAN_MAX_SSID |
1413 | drv->capa.max_scan_ssids = IEEE80211_IOC_SCAN_MAX_SSID; | | 1521 | drv->capa.max_scan_ssids = IEEE80211_IOC_SCAN_MAX_SSID; |
1414 | #else /* IEEE80211_IOC_SCAN_MAX_SSID */ | | 1522 | #else /* IEEE80211_IOC_SCAN_MAX_SSID */ |
1415 | drv->capa.max_scan_ssids = 1; | | 1523 | drv->capa.max_scan_ssids = 1; |
1416 | #endif /* IEEE80211_IOC_SCAN_MAX_SSID */ | | 1524 | #endif /* IEEE80211_IOC_SCAN_MAX_SSID */ |
1417 | drv->capa.auth = WPA_DRIVER_AUTH_OPEN | | | 1525 | drv->capa.auth = WPA_DRIVER_AUTH_OPEN | |
1418 | WPA_DRIVER_AUTH_SHARED | | | 1526 | WPA_DRIVER_AUTH_SHARED | |
1419 | WPA_DRIVER_AUTH_LEAP; | | 1527 | WPA_DRIVER_AUTH_LEAP; |
1420 | return 0; | | 1528 | return 0; |
1421 | } | | 1529 | } |
1422 | | | 1530 | |
1423 | static enum ieee80211_opmode | | 1531 | static enum ieee80211_opmode |
1424 | get80211opmode(struct bsd_driver_data *drv) | | 1532 | get80211opmode(struct bsd_driver_data *drv) |
1425 | { | | 1533 | { |
1426 | struct ifmediareq ifmr; | | 1534 | struct ifmediareq ifmr; |
1427 | | | 1535 | |
1428 | (void) memset(&ifmr, 0, sizeof(ifmr)); | | 1536 | (void) memset(&ifmr, 0, sizeof(ifmr)); |
1429 | (void) os_strlcpy(ifmr.ifm_name, drv->ifname, sizeof(ifmr.ifm_name)); | | 1537 | (void) os_strlcpy(ifmr.ifm_name, drv->ifname, sizeof(ifmr.ifm_name)); |
1430 | | | 1538 | |
1431 | if (ioctl(drv->global->sock, SIOCGIFMEDIA, (caddr_t)&ifmr) >= 0) { | | 1539 | if (ioctl(drv->global->sock, SIOCGIFMEDIA, (caddr_t)&ifmr) >= 0) { |
1432 | if (ifmr.ifm_current & IFM_IEEE80211_ADHOC) { | | 1540 | if (ifmr.ifm_current & IFM_IEEE80211_ADHOC) { |
1433 | if (ifmr.ifm_current & IFM_FLAG0) | | 1541 | if (ifmr.ifm_current & IFM_FLAG0) |
1434 | return IEEE80211_M_AHDEMO; | | 1542 | return IEEE80211_M_AHDEMO; |
1435 | else | | 1543 | else |
1436 | return IEEE80211_M_IBSS; | | 1544 | return IEEE80211_M_IBSS; |
1437 | } | | 1545 | } |
1438 | if (ifmr.ifm_current & IFM_IEEE80211_HOSTAP) | | 1546 | if (ifmr.ifm_current & IFM_IEEE80211_HOSTAP) |
1439 | return IEEE80211_M_HOSTAP; | | 1547 | return IEEE80211_M_HOSTAP; |
1440 | if (ifmr.ifm_current & IFM_IEEE80211_MONITOR) | | 1548 | if (ifmr.ifm_current & IFM_IEEE80211_MONITOR) |
1441 | return IEEE80211_M_MONITOR; | | 1549 | return IEEE80211_M_MONITOR; |
1442 | #ifdef IEEE80211_M_MBSS | | 1550 | #ifdef IEEE80211_M_MBSS |
1443 | if (ifmr.ifm_current & IFM_IEEE80211_MBSS) | | 1551 | if (ifmr.ifm_current & IFM_IEEE80211_MBSS) |
1444 | return IEEE80211_M_MBSS; | | 1552 | return IEEE80211_M_MBSS; |
1445 | #endif /* IEEE80211_M_MBSS */ | | 1553 | #endif /* IEEE80211_M_MBSS */ |
1446 | } | | 1554 | } |
1447 | return IEEE80211_M_STA; | | 1555 | return IEEE80211_M_STA; |
1448 | } | | 1556 | } |
1449 | | | 1557 | |
1450 | static void * | | 1558 | static void * |
1451 | wpa_driver_bsd_init(void *ctx, const char *ifname, void *priv) | | 1559 | wpa_driver_bsd_init(void *ctx, const char *ifname, void *priv) |
1452 | { | | 1560 | { |
1453 | #define GETPARAM(drv, param, v) \ | | 1561 | #define GETPARAM(drv, param, v) \ |
1454 | (((v) = get80211param(drv, param)) != -1) | | 1562 | (((v) = get80211param(drv, param)) != -1) |
1455 | struct bsd_driver_data *drv; | | 1563 | struct bsd_driver_data *drv; |
1456 | | | 1564 | |
1457 | drv = os_zalloc(sizeof(*drv)); | | 1565 | drv = os_zalloc(sizeof(*drv)); |
1458 | if (drv == NULL) | | 1566 | if (drv == NULL) |
1459 | return NULL; | | 1567 | return NULL; |
1460 | | | 1568 | |
1461 | drv->ifindex = if_nametoindex(ifname); | | 1569 | drv->ifindex = if_nametoindex(ifname); |
1462 | if (drv->ifindex == 0) { | | 1570 | if (drv->ifindex == 0) { |
1463 | wpa_printf(MSG_DEBUG, "%s: interface %s does not exist", | | 1571 | wpa_printf(MSG_DEBUG, "%s: interface %s does not exist", |
1464 | __func__, ifname); | | 1572 | __func__, ifname); |
1465 | goto fail; | | 1573 | goto fail; |
1466 | } | | 1574 | } |
1467 | | | 1575 | |
1468 | drv->ctx = ctx; | | 1576 | drv->ctx = ctx; |
1469 | drv->global = priv; | | 1577 | drv->global = priv; |
1470 | os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); | | 1578 | os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); |
1471 | | | 1579 | |
1472 | /* Set the interface as removed until proven to work. */ | | 1580 | /* Set the interface as removed until proven to work. */ |
1473 | drv->if_removed = 1; | | 1581 | drv->if_removed = 1; |
1474 | | | 1582 | |
1475 | if (!GETPARAM(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming)) { | | 1583 | if (!GETPARAM(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming)) { |
1476 | wpa_printf(MSG_DEBUG, "%s: failed to get roaming state: %s", | | 1584 | wpa_printf(MSG_DEBUG, "%s: failed to get roaming state: %s", |
1477 | __func__, strerror(errno)); | | 1585 | __func__, strerror(errno)); |
1478 | goto fail; | | 1586 | goto fail; |
1479 | } | | 1587 | } |
1480 | if (!GETPARAM(drv, IEEE80211_IOC_PRIVACY, drv->prev_privacy)) { | | 1588 | if (!GETPARAM(drv, IEEE80211_IOC_PRIVACY, drv->prev_privacy)) { |
1481 | wpa_printf(MSG_DEBUG, "%s: failed to get privacy state: %s", | | 1589 | wpa_printf(MSG_DEBUG, "%s: failed to get privacy state: %s", |
1482 | __func__, strerror(errno)); | | 1590 | __func__, strerror(errno)); |
1483 | goto fail; | | 1591 | goto fail; |
1484 | } | | 1592 | } |
1485 | if (!GETPARAM(drv, IEEE80211_IOC_WPA, drv->prev_wpa)) { | | 1593 | if (!GETPARAM(drv, IEEE80211_IOC_WPA, drv->prev_wpa)) { |
1486 | wpa_printf(MSG_DEBUG, "%s: failed to get wpa state: %s", | | 1594 | wpa_printf(MSG_DEBUG, "%s: failed to get wpa state: %s", |
1487 | __func__, strerror(errno)); | | 1595 | __func__, strerror(errno)); |
1488 | goto fail; | | 1596 | goto fail; |
1489 | } | | 1597 | } |
1490 | | | 1598 | |
1491 | if (wpa_driver_bsd_capa(drv)) | | 1599 | if (wpa_driver_bsd_capa(drv)) |
1492 | goto fail; | | 1600 | goto fail; |
1493 | | | 1601 | |
1494 | /* Down interface during setup. */ | | 1602 | /* Down interface during setup. */ |
1495 | if (bsd_get_iface_flags(drv) < 0) | | 1603 | if (bsd_get_iface_flags(drv) < 0) |
1496 | goto fail; | | 1604 | goto fail; |
1497 | | | 1605 | |
1498 | /* Proven to work, lets go! */ | | 1606 | /* Proven to work, lets go! */ |
1499 | drv->if_removed = 0; | | 1607 | drv->if_removed = 0; |
1500 | | | 1608 | |
1501 | drv->opmode = get80211opmode(drv); | | 1609 | drv->opmode = get80211opmode(drv); |
1502 | dl_list_add(&drv->global->ifaces, &drv->list); | | 1610 | dl_list_add(&drv->global->ifaces, &drv->list); |
1503 | | | 1611 | |
1504 | return drv; | | 1612 | return drv; |
1505 | fail: | | 1613 | fail: |
1506 | os_free(drv); | | 1614 | os_free(drv); |
1507 | return NULL; | | 1615 | return NULL; |
1508 | #undef GETPARAM | | 1616 | #undef GETPARAM |
1509 | } | | 1617 | } |
1510 | | | 1618 | |
1511 | static void | | 1619 | static void |
1512 | wpa_driver_bsd_deinit(void *priv) | | 1620 | wpa_driver_bsd_deinit(void *priv) |
1513 | { | | 1621 | { |
1514 | struct bsd_driver_data *drv = priv; | | 1622 | struct bsd_driver_data *drv = priv; |
1515 | | | 1623 | |
1516 | if (drv->ifindex != 0 && !drv->if_removed) { | | 1624 | if (drv->ifindex != 0 && !drv->if_removed) { |
1517 | wpa_driver_bsd_set_wpa(drv, 0); | | 1625 | wpa_driver_bsd_set_wpa(drv, 0); |
1518 | | | 1626 | |
1519 | wpa_driver_bsd_set_wpa_internal(drv, drv->prev_wpa, | | 1627 | wpa_driver_bsd_set_wpa_internal(drv, drv->prev_wpa, |
1520 | drv->prev_privacy); | | 1628 | drv->prev_privacy); |
1521 | | | 1629 | |
1522 | if (set80211param(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming) | | 1630 | if (set80211param(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming) |
1523 | < 0) | | 1631 | < 0) |
1524 | wpa_printf(MSG_DEBUG, | | 1632 | wpa_printf(MSG_DEBUG, |
1525 | "%s: failed to restore roaming state", | | 1633 | "%s: failed to restore roaming state", |
1526 | __func__); | | 1634 | __func__); |
1527 | } | | 1635 | } |
1528 | | | 1636 | |
1529 | if (drv->sock_xmit != NULL) | | 1637 | if (drv->sock_xmit != NULL) |
1530 | l2_packet_deinit(drv->sock_xmit); | | 1638 | l2_packet_deinit(drv->sock_xmit); |
1531 | dl_list_del(&drv->list); | | 1639 | dl_list_del(&drv->list); |
1532 | os_free(drv); | | 1640 | os_free(drv); |
1533 | } | | 1641 | } |
1534 | | | 1642 | |
1535 | static int | | 1643 | static int |
1536 | wpa_driver_bsd_get_capa(void *priv, struct wpa_driver_capa *capa) | | 1644 | wpa_driver_bsd_get_capa(void *priv, struct wpa_driver_capa *capa) |
1537 | { | | 1645 | { |
1538 | struct bsd_driver_data *drv = priv; | | 1646 | struct bsd_driver_data *drv = priv; |
1539 | | | 1647 | |
1540 | os_memcpy(capa, &drv->capa, sizeof(*capa)); | | 1648 | os_memcpy(capa, &drv->capa, sizeof(*capa)); |
1541 | return 0; | | 1649 | return 0; |
1542 | } | | 1650 | } |
1543 | #endif /* HOSTAPD */ | | 1651 | #endif /* HOSTAPD */ |
1544 | | | 1652 | |
1545 | static void * | | 1653 | static void * |
1546 | bsd_global_init(void *ctx) | | 1654 | bsd_global_init(void *ctx) |
1547 | { | | 1655 | { |
1548 | struct bsd_driver_global *global; | | 1656 | struct bsd_driver_global *global; |
1549 | #ifdef RO_MSGFILTER | | 1657 | #ifdef RO_MSGFILTER |
1550 | unsigned char msgfilter[] = { | | 1658 | unsigned char msgfilter[] = { |
1551 | RTM_IEEE80211, | | 1659 | RTM_IEEE80211, |
1552 | RTM_IFINFO, RTM_IFANNOUNCE, | | 1660 | RTM_IFINFO, RTM_IFANNOUNCE, |
1553 | }; | | 1661 | }; |
1554 | #endif | | 1662 | #endif |
1555 | | | 1663 | |
1556 | global = os_zalloc(sizeof(*global)); | | 1664 | global = os_zalloc(sizeof(*global)); |
1557 | if (global == NULL) | | 1665 | if (global == NULL) |
1558 | return NULL; | | 1666 | return NULL; |
1559 | | | 1667 | |
1560 | global->ctx = ctx; | | 1668 | global->ctx = ctx; |
1561 | dl_list_init(&global->ifaces); | | 1669 | dl_list_init(&global->ifaces); |
1562 | | | 1670 | |
1563 | global->sock = socket(PF_INET, SOCK_DGRAM, 0); | | 1671 | global->sock = socket(PF_INET, SOCK_DGRAM|SOCK_CLOEXEC, 0); |
1564 | if (global->sock < 0) { | | 1672 | if (global->sock < 0) { |
1565 | wpa_printf(MSG_ERROR, "socket[PF_INET,SOCK_DGRAM]: %s", | | 1673 | wpa_printf(MSG_ERROR, "socket[PF_INET,SOCK_DGRAM]: %s", |
1566 | strerror(errno)); | | 1674 | strerror(errno)); |
1567 | goto fail1; | | 1675 | goto fail1; |
1568 | } | | 1676 | } |
1569 | | | 1677 | |
1570 | global->route = socket(PF_ROUTE, SOCK_RAW, 0); | | 1678 | global->route = socket(PF_ROUTE, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); |
1571 | if (global->route < 0) { | | 1679 | if (global->route < 0) { |
1572 | wpa_printf(MSG_ERROR, "socket[PF_ROUTE,SOCK_RAW]: %s", | | 1680 | wpa_printf(MSG_ERROR, "socket[PF_ROUTE,SOCK_RAW]: %s", |
1573 | strerror(errno)); | | 1681 | strerror(errno)); |
1574 | goto fail; | | 1682 | goto fail; |
1575 | } | | 1683 | } |
1576 | | | 1684 | |
1577 | #ifdef RO_MSGFILTER | | 1685 | #ifdef RO_MSGFILTER |
1578 | if (setsockopt(global->route, PF_ROUTE, RO_MSGFILTER, | | 1686 | if (setsockopt(global->route, PF_ROUTE, RO_MSGFILTER, |
1579 | &msgfilter, sizeof(msgfilter)) < 0) | | 1687 | &msgfilter, sizeof(msgfilter)) < 0) |
1580 | wpa_printf(MSG_ERROR, "socket[PF_ROUTE,RO_MSGFILTER]: %s", | | 1688 | wpa_printf(MSG_ERROR, "socket[PF_ROUTE,RO_MSGFILTER]: %s", |
1581 | strerror(errno)); | | 1689 | strerror(errno)); |
1582 | #endif | | 1690 | #endif |
1583 | | | 1691 | |
1584 | eloop_register_read_sock(global->route, bsd_wireless_event_receive, | | 1692 | eloop_register_read_sock(global->route, bsd_wireless_event_receive, |
1585 | NULL, global); | | 1693 | NULL, global); |
1586 | | | 1694 | |
1587 | return global; | | 1695 | return global; |
1588 | | | 1696 | |
1589 | fail: | | 1697 | fail: |
1590 | close(global->sock); | | 1698 | close(global->sock); |
1591 | fail1: | | 1699 | fail1: |
1592 | os_free(global); | | 1700 | os_free(global); |
1593 | return NULL; | | 1701 | return NULL; |
1594 | } | | 1702 | } |
1595 | | | 1703 | |
1596 | static void | | 1704 | static void |
1597 | bsd_global_deinit(void *priv) | | 1705 | bsd_global_deinit(void *priv) |
1598 | { | | 1706 | { |
1599 | struct bsd_driver_global *global = priv; | | 1707 | struct bsd_driver_global *global = priv; |
1600 | | | 1708 | |
1601 | eloop_unregister_read_sock(global->route); | | 1709 | eloop_unregister_read_sock(global->route); |
1602 | (void) close(global->route); | | 1710 | (void) close(global->route); |
1603 | (void) close(global->sock); | | 1711 | (void) close(global->sock); |
1604 | os_free(global); | | 1712 | os_free(global); |
1605 | } | | 1713 | } |
1606 | | | 1714 | |
1607 | | | 1715 | |
1608 | const struct wpa_driver_ops wpa_driver_bsd_ops = { | | 1716 | const struct wpa_driver_ops wpa_driver_bsd_ops = { |
1609 | .name = "bsd", | | 1717 | .name = "bsd", |
1610 | .desc = "BSD 802.11 support", | | 1718 | .desc = "BSD 802.11 support", |
1611 | .global_init = bsd_global_init, | | 1719 | .global_init = bsd_global_init, |
1612 | .global_deinit = bsd_global_deinit, | | 1720 | .global_deinit = bsd_global_deinit, |
1613 | #ifdef HOSTAPD | | 1721 | #ifdef HOSTAPD |
1614 | .hapd_init = bsd_init, | | 1722 | .hapd_init = bsd_init, |
1615 | .hapd_deinit = bsd_deinit, | | 1723 | .hapd_deinit = bsd_deinit, |
1616 | .set_privacy = bsd_set_privacy, | | 1724 | .set_privacy = bsd_set_privacy, |
1617 | .get_seqnum = bsd_get_seqnum, | | 1725 | .get_seqnum = bsd_get_seqnum, |
1618 | .flush = bsd_flush, | | 1726 | .flush = bsd_flush, |
1619 | .read_sta_data = bsd_read_sta_driver_data, | | 1727 | .read_sta_data = bsd_read_sta_driver_data, |
1620 | .sta_disassoc = bsd_sta_disassoc, | | 1728 | .sta_disassoc = bsd_sta_disassoc, |
1621 | .sta_deauth = bsd_sta_deauth, | | 1729 | .sta_deauth = bsd_sta_deauth, |
1622 | .sta_set_flags = bsd_set_sta_authorized, | | 1730 | .sta_set_flags = bsd_set_sta_authorized, |
1623 | #else /* HOSTAPD */ | | 1731 | #else /* HOSTAPD */ |
1624 | .init2 = wpa_driver_bsd_init, | | 1732 | .init2 = wpa_driver_bsd_init, |
1625 | .deinit = wpa_driver_bsd_deinit, | | 1733 | .deinit = wpa_driver_bsd_deinit, |
1626 | .get_bssid = wpa_driver_bsd_get_bssid, | | 1734 | .get_bssid = wpa_driver_bsd_get_bssid, |
1627 | .get_ssid = wpa_driver_bsd_get_ssid, | | 1735 | .get_ssid = wpa_driver_bsd_get_ssid, |
1628 | .set_countermeasures = wpa_driver_bsd_set_countermeasures, | | 1736 | .set_countermeasures = wpa_driver_bsd_set_countermeasures, |
1629 | .scan2 = wpa_driver_bsd_scan, | | 1737 | .scan2 = wpa_driver_bsd_scan, |
1630 | .get_scan_results2 = wpa_driver_bsd_get_scan_results2, | | 1738 | .get_scan_results2 = wpa_driver_bsd_get_scan_results2, |
1631 | .deauthenticate = wpa_driver_bsd_deauthenticate, | | 1739 | .deauthenticate = wpa_driver_bsd_deauthenticate, |
1632 | .associate = wpa_driver_bsd_associate, | | 1740 | .associate = wpa_driver_bsd_associate, |
1633 | .get_capa = wpa_driver_bsd_get_capa, | | 1741 | .get_capa = wpa_driver_bsd_get_capa, |
1634 | #endif /* HOSTAPD */ | | 1742 | #endif /* HOSTAPD */ |
1635 | .set_freq = bsd_set_freq, | | 1743 | .set_freq = bsd_set_freq, |
1636 | .set_key = bsd_set_key, | | 1744 | .set_key = bsd_set_key, |
1637 | .set_ieee8021x = bsd_set_ieee8021x, | | 1745 | .set_ieee8021x = bsd_set_ieee8021x, |
1638 | .hapd_set_ssid = bsd_set_ssid, | | 1746 | .hapd_set_ssid = bsd_set_ssid, |
1639 | .hapd_get_ssid = bsd_get_ssid, | | 1747 | .hapd_get_ssid = bsd_get_ssid, |
1640 | .hapd_send_eapol = bsd_send_eapol, | | 1748 | .hapd_send_eapol = bsd_send_eapol, |
1641 | .set_generic_elem = bsd_set_opt_ie, | | 1749 | .set_generic_elem = bsd_set_opt_ie, |
1642 | }; | | 1750 | }; |