Line data Source code
1 : /*
2 : * Driver interaction with generic Linux Wireless Extensions
3 : * Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi>
4 : *
5 : * This software may be distributed under the terms of the BSD license.
6 : * See README for more details.
7 : *
8 : * This file implements a driver interface for the Linux Wireless Extensions.
9 : * When used with WE-18 or newer, this interface can be used as-is with number
10 : * of drivers. In addition to this, some of the common functions in this file
11 : * can be used by other driver interface implementations that use generic WE
12 : * ioctls, but require private ioctls for some of the functionality.
13 : */
14 :
15 : #include "includes.h"
16 : #include <sys/ioctl.h>
17 : #include <sys/types.h>
18 : #include <sys/stat.h>
19 : #include <fcntl.h>
20 : #include <net/if_arp.h>
21 : #include <dirent.h>
22 :
23 : #include "linux_wext.h"
24 : #include "common.h"
25 : #include "eloop.h"
26 : #include "common/ieee802_11_defs.h"
27 : #include "common/wpa_common.h"
28 : #include "priv_netlink.h"
29 : #include "netlink.h"
30 : #include "linux_ioctl.h"
31 : #include "rfkill.h"
32 : #include "driver.h"
33 : #include "driver_wext.h"
34 :
35 : static int wpa_driver_wext_flush_pmkid(void *priv);
36 : static int wpa_driver_wext_get_range(void *priv);
37 : static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv);
38 : static void wpa_driver_wext_disconnect(struct wpa_driver_wext_data *drv);
39 : static int wpa_driver_wext_set_auth_alg(void *priv, int auth_alg);
40 :
41 :
42 163 : int wpa_driver_wext_set_auth_param(struct wpa_driver_wext_data *drv,
43 : int idx, u32 value)
44 : {
45 : struct iwreq iwr;
46 163 : int ret = 0;
47 :
48 163 : os_memset(&iwr, 0, sizeof(iwr));
49 163 : os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
50 163 : iwr.u.param.flags = idx & IW_AUTH_INDEX;
51 163 : iwr.u.param.value = value;
52 :
53 163 : if (ioctl(drv->ioctl_sock, SIOCSIWAUTH, &iwr) < 0) {
54 19 : if (errno != EOPNOTSUPP) {
55 0 : wpa_printf(MSG_DEBUG, "WEXT: SIOCSIWAUTH(param %d "
56 : "value 0x%x) failed: %s)",
57 0 : idx, value, strerror(errno));
58 : }
59 19 : ret = errno == EOPNOTSUPP ? -2 : -1;
60 : }
61 :
62 163 : return ret;
63 : }
64 :
65 :
66 : /**
67 : * wpa_driver_wext_get_bssid - Get BSSID, SIOCGIWAP
68 : * @priv: Pointer to private wext data from wpa_driver_wext_init()
69 : * @bssid: Buffer for BSSID
70 : * Returns: 0 on success, -1 on failure
71 : */
72 26 : int wpa_driver_wext_get_bssid(void *priv, u8 *bssid)
73 : {
74 26 : struct wpa_driver_wext_data *drv = priv;
75 : struct iwreq iwr;
76 26 : int ret = 0;
77 :
78 26 : os_memset(&iwr, 0, sizeof(iwr));
79 26 : os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
80 :
81 26 : if (ioctl(drv->ioctl_sock, SIOCGIWAP, &iwr) < 0) {
82 0 : wpa_printf(MSG_ERROR, "ioctl[SIOCGIWAP]: %s", strerror(errno));
83 0 : ret = -1;
84 : }
85 26 : os_memcpy(bssid, iwr.u.ap_addr.sa_data, ETH_ALEN);
86 :
87 26 : return ret;
88 : }
89 :
90 :
91 : /**
92 : * wpa_driver_wext_set_bssid - Set BSSID, SIOCSIWAP
93 : * @priv: Pointer to private wext data from wpa_driver_wext_init()
94 : * @bssid: BSSID
95 : * Returns: 0 on success, -1 on failure
96 : */
97 41 : int wpa_driver_wext_set_bssid(void *priv, const u8 *bssid)
98 : {
99 41 : struct wpa_driver_wext_data *drv = priv;
100 : struct iwreq iwr;
101 41 : int ret = 0;
102 :
103 41 : os_memset(&iwr, 0, sizeof(iwr));
104 41 : os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
105 41 : iwr.u.ap_addr.sa_family = ARPHRD_ETHER;
106 41 : if (bssid)
107 41 : os_memcpy(iwr.u.ap_addr.sa_data, bssid, ETH_ALEN);
108 : else
109 0 : os_memset(iwr.u.ap_addr.sa_data, 0, ETH_ALEN);
110 :
111 41 : if (ioctl(drv->ioctl_sock, SIOCSIWAP, &iwr) < 0) {
112 0 : wpa_printf(MSG_ERROR, "ioctl[SIOCSIWAP]: %s", strerror(errno));
113 0 : ret = -1;
114 : }
115 :
116 41 : return ret;
117 : }
118 :
119 :
120 : /**
121 : * wpa_driver_wext_get_ssid - Get SSID, SIOCGIWESSID
122 : * @priv: Pointer to private wext data from wpa_driver_wext_init()
123 : * @ssid: Buffer for the SSID; must be at least 32 bytes long
124 : * Returns: SSID length on success, -1 on failure
125 : */
126 22 : int wpa_driver_wext_get_ssid(void *priv, u8 *ssid)
127 : {
128 22 : struct wpa_driver_wext_data *drv = priv;
129 : struct iwreq iwr;
130 22 : int ret = 0;
131 :
132 22 : os_memset(&iwr, 0, sizeof(iwr));
133 22 : os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
134 22 : iwr.u.essid.pointer = (caddr_t) ssid;
135 22 : iwr.u.essid.length = SSID_MAX_LEN;
136 :
137 22 : if (ioctl(drv->ioctl_sock, SIOCGIWESSID, &iwr) < 0) {
138 0 : wpa_printf(MSG_ERROR, "ioctl[SIOCGIWESSID]: %s",
139 0 : strerror(errno));
140 0 : ret = -1;
141 : } else {
142 22 : ret = iwr.u.essid.length;
143 22 : if (ret > SSID_MAX_LEN)
144 0 : ret = SSID_MAX_LEN;
145 : /* Some drivers include nul termination in the SSID, so let's
146 : * remove it here before further processing. WE-21 changes this
147 : * to explicitly require the length _not_ to include nul
148 : * termination. */
149 22 : if (ret > 0 && ssid[ret - 1] == '\0' &&
150 0 : drv->we_version_compiled < 21)
151 0 : ret--;
152 : }
153 :
154 22 : return ret;
155 : }
156 :
157 :
158 : /**
159 : * wpa_driver_wext_set_ssid - Set SSID, SIOCSIWESSID
160 : * @priv: Pointer to private wext data from wpa_driver_wext_init()
161 : * @ssid: SSID
162 : * @ssid_len: Length of SSID (0..32)
163 : * Returns: 0 on success, -1 on failure
164 : */
165 55 : int wpa_driver_wext_set_ssid(void *priv, const u8 *ssid, size_t ssid_len)
166 : {
167 55 : struct wpa_driver_wext_data *drv = priv;
168 : struct iwreq iwr;
169 55 : int ret = 0;
170 : char buf[33];
171 :
172 55 : if (ssid_len > SSID_MAX_LEN)
173 0 : return -1;
174 :
175 55 : os_memset(&iwr, 0, sizeof(iwr));
176 55 : os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
177 : /* flags: 1 = ESSID is active, 0 = not (promiscuous) */
178 55 : iwr.u.essid.flags = (ssid_len != 0);
179 55 : os_memset(buf, 0, sizeof(buf));
180 55 : os_memcpy(buf, ssid, ssid_len);
181 55 : iwr.u.essid.pointer = (caddr_t) buf;
182 55 : if (drv->we_version_compiled < 21) {
183 : /* For historic reasons, set SSID length to include one extra
184 : * character, C string nul termination, even though SSID is
185 : * really an octet string that should not be presented as a C
186 : * string. Some Linux drivers decrement the length by one and
187 : * can thus end up missing the last octet of the SSID if the
188 : * length is not incremented here. WE-21 changes this to
189 : * explicitly require the length _not_ to include nul
190 : * termination. */
191 0 : if (ssid_len)
192 0 : ssid_len++;
193 : }
194 55 : iwr.u.essid.length = ssid_len;
195 :
196 55 : if (ioctl(drv->ioctl_sock, SIOCSIWESSID, &iwr) < 0) {
197 0 : wpa_printf(MSG_ERROR, "ioctl[SIOCSIWESSID]: %s",
198 0 : strerror(errno));
199 0 : ret = -1;
200 : }
201 :
202 55 : return ret;
203 : }
204 :
205 :
206 : /**
207 : * wpa_driver_wext_set_freq - Set frequency/channel, SIOCSIWFREQ
208 : * @priv: Pointer to private wext data from wpa_driver_wext_init()
209 : * @freq: Frequency in MHz
210 : * Returns: 0 on success, -1 on failure
211 : */
212 14 : int wpa_driver_wext_set_freq(void *priv, int freq)
213 : {
214 14 : struct wpa_driver_wext_data *drv = priv;
215 : struct iwreq iwr;
216 14 : int ret = 0;
217 :
218 14 : os_memset(&iwr, 0, sizeof(iwr));
219 14 : os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
220 14 : iwr.u.freq.m = freq * 100000;
221 14 : iwr.u.freq.e = 1;
222 :
223 14 : if (ioctl(drv->ioctl_sock, SIOCSIWFREQ, &iwr) < 0) {
224 14 : wpa_printf(MSG_ERROR, "ioctl[SIOCSIWFREQ]: %s",
225 14 : strerror(errno));
226 14 : ret = -1;
227 : }
228 :
229 14 : return ret;
230 : }
231 :
232 :
233 : static void
234 2 : wpa_driver_wext_event_wireless_custom(void *ctx, char *custom)
235 : {
236 : union wpa_event_data data;
237 :
238 2 : wpa_printf(MSG_MSGDUMP, "WEXT: Custom wireless event: '%s'",
239 : custom);
240 :
241 2 : os_memset(&data, 0, sizeof(data));
242 : /* Host AP driver */
243 2 : if (os_strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) {
244 2 : data.michael_mic_failure.unicast =
245 2 : os_strstr(custom, " unicast ") != NULL;
246 : /* TODO: parse parameters(?) */
247 2 : wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
248 0 : } else if (os_strncmp(custom, "ASSOCINFO(ReqIEs=", 17) == 0) {
249 : char *spos;
250 : int bytes;
251 0 : u8 *req_ies = NULL, *resp_ies = NULL;
252 :
253 0 : spos = custom + 17;
254 :
255 0 : bytes = strspn(spos, "0123456789abcdefABCDEF");
256 0 : if (!bytes || (bytes & 1))
257 0 : return;
258 0 : bytes /= 2;
259 :
260 0 : req_ies = os_malloc(bytes);
261 0 : if (req_ies == NULL ||
262 0 : hexstr2bin(spos, req_ies, bytes) < 0)
263 : goto done;
264 0 : data.assoc_info.req_ies = req_ies;
265 0 : data.assoc_info.req_ies_len = bytes;
266 :
267 0 : spos += bytes * 2;
268 :
269 0 : data.assoc_info.resp_ies = NULL;
270 0 : data.assoc_info.resp_ies_len = 0;
271 :
272 0 : if (os_strncmp(spos, " RespIEs=", 9) == 0) {
273 0 : spos += 9;
274 :
275 0 : bytes = strspn(spos, "0123456789abcdefABCDEF");
276 0 : if (!bytes || (bytes & 1))
277 : goto done;
278 0 : bytes /= 2;
279 :
280 0 : resp_ies = os_malloc(bytes);
281 0 : if (resp_ies == NULL ||
282 0 : hexstr2bin(spos, resp_ies, bytes) < 0)
283 : goto done;
284 0 : data.assoc_info.resp_ies = resp_ies;
285 0 : data.assoc_info.resp_ies_len = bytes;
286 : }
287 :
288 0 : wpa_supplicant_event(ctx, EVENT_ASSOCINFO, &data);
289 :
290 : done:
291 0 : os_free(resp_ies);
292 0 : os_free(req_ies);
293 : #ifdef CONFIG_PEERKEY
294 0 : } else if (os_strncmp(custom, "STKSTART.request=", 17) == 0) {
295 0 : if (hwaddr_aton(custom + 17, data.stkstart.peer)) {
296 0 : wpa_printf(MSG_DEBUG, "WEXT: unrecognized "
297 : "STKSTART.request '%s'", custom + 17);
298 0 : return;
299 : }
300 0 : wpa_supplicant_event(ctx, EVENT_STKSTART, &data);
301 : #endif /* CONFIG_PEERKEY */
302 : }
303 : }
304 :
305 :
306 0 : static int wpa_driver_wext_event_wireless_michaelmicfailure(
307 : void *ctx, const char *ev, size_t len)
308 : {
309 : const struct iw_michaelmicfailure *mic;
310 : union wpa_event_data data;
311 :
312 0 : if (len < sizeof(*mic))
313 0 : return -1;
314 :
315 0 : mic = (const struct iw_michaelmicfailure *) ev;
316 :
317 0 : wpa_printf(MSG_DEBUG, "Michael MIC failure wireless event: "
318 : "flags=0x%x src_addr=" MACSTR, mic->flags,
319 0 : MAC2STR(mic->src_addr.sa_data));
320 :
321 0 : os_memset(&data, 0, sizeof(data));
322 0 : data.michael_mic_failure.unicast = !(mic->flags & IW_MICFAILURE_GROUP);
323 0 : wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
324 :
325 0 : return 0;
326 : }
327 :
328 :
329 0 : static int wpa_driver_wext_event_wireless_pmkidcand(
330 : struct wpa_driver_wext_data *drv, const char *ev, size_t len)
331 : {
332 : const struct iw_pmkid_cand *cand;
333 : union wpa_event_data data;
334 : const u8 *addr;
335 :
336 0 : if (len < sizeof(*cand))
337 0 : return -1;
338 :
339 0 : cand = (const struct iw_pmkid_cand *) ev;
340 0 : addr = (const u8 *) cand->bssid.sa_data;
341 :
342 0 : wpa_printf(MSG_DEBUG, "PMKID candidate wireless event: "
343 : "flags=0x%x index=%d bssid=" MACSTR, cand->flags,
344 0 : cand->index, MAC2STR(addr));
345 :
346 0 : os_memset(&data, 0, sizeof(data));
347 0 : os_memcpy(data.pmkid_candidate.bssid, addr, ETH_ALEN);
348 0 : data.pmkid_candidate.index = cand->index;
349 0 : data.pmkid_candidate.preauth = cand->flags & IW_PMKID_CAND_PREAUTH;
350 0 : wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE, &data);
351 :
352 0 : return 0;
353 : }
354 :
355 :
356 0 : static int wpa_driver_wext_event_wireless_assocreqie(
357 : struct wpa_driver_wext_data *drv, const char *ev, int len)
358 : {
359 0 : if (len < 0)
360 0 : return -1;
361 :
362 0 : wpa_hexdump(MSG_DEBUG, "AssocReq IE wireless event", (const u8 *) ev,
363 : len);
364 0 : os_free(drv->assoc_req_ies);
365 0 : drv->assoc_req_ies = os_malloc(len);
366 0 : if (drv->assoc_req_ies == NULL) {
367 0 : drv->assoc_req_ies_len = 0;
368 0 : return -1;
369 : }
370 0 : os_memcpy(drv->assoc_req_ies, ev, len);
371 0 : drv->assoc_req_ies_len = len;
372 :
373 0 : return 0;
374 : }
375 :
376 :
377 14 : static int wpa_driver_wext_event_wireless_assocrespie(
378 : struct wpa_driver_wext_data *drv, const char *ev, int len)
379 : {
380 14 : if (len < 0)
381 0 : return -1;
382 :
383 14 : wpa_hexdump(MSG_DEBUG, "AssocResp IE wireless event", (const u8 *) ev,
384 : len);
385 14 : os_free(drv->assoc_resp_ies);
386 14 : drv->assoc_resp_ies = os_malloc(len);
387 14 : if (drv->assoc_resp_ies == NULL) {
388 0 : drv->assoc_resp_ies_len = 0;
389 0 : return -1;
390 : }
391 14 : os_memcpy(drv->assoc_resp_ies, ev, len);
392 14 : drv->assoc_resp_ies_len = len;
393 :
394 14 : return 0;
395 : }
396 :
397 :
398 14 : static void wpa_driver_wext_event_assoc_ies(struct wpa_driver_wext_data *drv)
399 : {
400 : union wpa_event_data data;
401 :
402 14 : if (drv->assoc_req_ies == NULL && drv->assoc_resp_ies == NULL)
403 14 : return;
404 :
405 14 : os_memset(&data, 0, sizeof(data));
406 14 : if (drv->assoc_req_ies) {
407 0 : data.assoc_info.req_ies = drv->assoc_req_ies;
408 0 : data.assoc_info.req_ies_len = drv->assoc_req_ies_len;
409 : }
410 14 : if (drv->assoc_resp_ies) {
411 14 : data.assoc_info.resp_ies = drv->assoc_resp_ies;
412 14 : data.assoc_info.resp_ies_len = drv->assoc_resp_ies_len;
413 : }
414 :
415 14 : wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &data);
416 :
417 14 : os_free(drv->assoc_req_ies);
418 14 : drv->assoc_req_ies = NULL;
419 14 : os_free(drv->assoc_resp_ies);
420 14 : drv->assoc_resp_ies = NULL;
421 : }
422 :
423 :
424 118 : static void wpa_driver_wext_event_wireless(struct wpa_driver_wext_data *drv,
425 : char *data, int len)
426 : {
427 118 : struct iw_event iwe_buf, *iwe = &iwe_buf;
428 : char *pos, *end, *custom, *buf;
429 :
430 118 : pos = data;
431 118 : end = data + len;
432 :
433 354 : while (pos + IW_EV_LCP_LEN <= end) {
434 : /* Event data may be unaligned, so make a local, aligned copy
435 : * before processing. */
436 118 : os_memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
437 236 : wpa_printf(MSG_DEBUG, "Wireless event: cmd=0x%x len=%d",
438 236 : iwe->cmd, iwe->len);
439 118 : if (iwe->len <= IW_EV_LCP_LEN)
440 0 : return;
441 :
442 118 : custom = pos + IW_EV_POINT_LEN;
443 236 : if (drv->we_version_compiled > 18 &&
444 236 : (iwe->cmd == IWEVMICHAELMICFAILURE ||
445 234 : iwe->cmd == IWEVCUSTOM ||
446 232 : iwe->cmd == IWEVASSOCREQIE ||
447 218 : iwe->cmd == IWEVASSOCRESPIE ||
448 118 : iwe->cmd == IWEVPMKIDCAND)) {
449 : /* WE-19 removed the pointer from struct iw_point */
450 16 : char *dpos = (char *) &iwe_buf.u.data.length;
451 16 : int dlen = dpos - (char *) &iwe_buf;
452 16 : os_memcpy(dpos, pos + IW_EV_LCP_LEN,
453 : sizeof(struct iw_event) - dlen);
454 : } else {
455 102 : os_memcpy(&iwe_buf, pos, sizeof(struct iw_event));
456 102 : custom += IW_EV_POINT_OFF;
457 : }
458 :
459 118 : switch (iwe->cmd) {
460 : case SIOCGIWAP:
461 138 : wpa_printf(MSG_DEBUG, "Wireless event: new AP: "
462 : MACSTR,
463 138 : MAC2STR((u8 *) iwe->u.ap_addr.sa_data));
464 23 : if (is_zero_ether_addr(
465 37 : (const u8 *) iwe->u.ap_addr.sa_data) ||
466 14 : os_memcmp(iwe->u.ap_addr.sa_data,
467 : "\x44\x44\x44\x44\x44\x44", ETH_ALEN) ==
468 : 0) {
469 9 : os_free(drv->assoc_req_ies);
470 9 : drv->assoc_req_ies = NULL;
471 9 : os_free(drv->assoc_resp_ies);
472 9 : drv->assoc_resp_ies = NULL;
473 9 : wpa_supplicant_event(drv->ctx, EVENT_DISASSOC,
474 : NULL);
475 :
476 : } else {
477 14 : wpa_driver_wext_event_assoc_ies(drv);
478 14 : wpa_supplicant_event(drv->ctx, EVENT_ASSOC,
479 : NULL);
480 : }
481 23 : break;
482 : case IWEVMICHAELMICFAILURE:
483 0 : if (custom + iwe->u.data.length > end) {
484 0 : wpa_printf(MSG_DEBUG, "WEXT: Invalid "
485 : "IWEVMICHAELMICFAILURE length");
486 0 : return;
487 : }
488 0 : wpa_driver_wext_event_wireless_michaelmicfailure(
489 0 : drv->ctx, custom, iwe->u.data.length);
490 0 : break;
491 : case IWEVCUSTOM:
492 2 : if (custom + iwe->u.data.length > end) {
493 0 : wpa_printf(MSG_DEBUG, "WEXT: Invalid "
494 : "IWEVCUSTOM length");
495 0 : return;
496 : }
497 2 : buf = dup_binstr(custom, iwe->u.data.length);
498 2 : if (buf == NULL)
499 0 : return;
500 2 : wpa_driver_wext_event_wireless_custom(drv->ctx, buf);
501 2 : os_free(buf);
502 2 : break;
503 : case SIOCGIWSCAN:
504 15 : drv->scan_complete_events = 1;
505 15 : eloop_cancel_timeout(wpa_driver_wext_scan_timeout,
506 : drv, drv->ctx);
507 15 : wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS,
508 : NULL);
509 15 : break;
510 : case IWEVASSOCREQIE:
511 0 : if (custom + iwe->u.data.length > end) {
512 0 : wpa_printf(MSG_DEBUG, "WEXT: Invalid "
513 : "IWEVASSOCREQIE length");
514 0 : return;
515 : }
516 0 : wpa_driver_wext_event_wireless_assocreqie(
517 0 : drv, custom, iwe->u.data.length);
518 0 : break;
519 : case IWEVASSOCRESPIE:
520 14 : if (custom + iwe->u.data.length > end) {
521 0 : wpa_printf(MSG_DEBUG, "WEXT: Invalid "
522 : "IWEVASSOCRESPIE length");
523 0 : return;
524 : }
525 14 : wpa_driver_wext_event_wireless_assocrespie(
526 14 : drv, custom, iwe->u.data.length);
527 14 : break;
528 : case IWEVPMKIDCAND:
529 0 : if (custom + iwe->u.data.length > end) {
530 0 : wpa_printf(MSG_DEBUG, "WEXT: Invalid "
531 : "IWEVPMKIDCAND length");
532 0 : return;
533 : }
534 0 : wpa_driver_wext_event_wireless_pmkidcand(
535 0 : drv, custom, iwe->u.data.length);
536 0 : break;
537 : }
538 :
539 118 : pos += iwe->len;
540 : }
541 : }
542 :
543 :
544 179 : static void wpa_driver_wext_event_link(struct wpa_driver_wext_data *drv,
545 : char *buf, size_t len, int del)
546 : {
547 : union wpa_event_data event;
548 :
549 179 : os_memset(&event, 0, sizeof(event));
550 179 : if (len > sizeof(event.interface_status.ifname))
551 0 : len = sizeof(event.interface_status.ifname) - 1;
552 179 : os_memcpy(event.interface_status.ifname, buf, len);
553 179 : event.interface_status.ievent = del ? EVENT_INTERFACE_REMOVED :
554 : EVENT_INTERFACE_ADDED;
555 :
556 179 : wpa_printf(MSG_DEBUG, "RTM_%sLINK, IFLA_IFNAME: Interface '%s' %s",
557 : del ? "DEL" : "NEW",
558 : event.interface_status.ifname,
559 : del ? "removed" : "added");
560 :
561 179 : if (os_strcmp(drv->ifname, event.interface_status.ifname) == 0) {
562 179 : if (del) {
563 0 : if (drv->if_removed) {
564 0 : wpa_printf(MSG_DEBUG, "WEXT: if_removed "
565 : "already set - ignore event");
566 0 : return;
567 : }
568 0 : drv->if_removed = 1;
569 : } else {
570 179 : if (if_nametoindex(drv->ifname) == 0) {
571 0 : wpa_printf(MSG_DEBUG, "WEXT: Interface %s "
572 : "does not exist - ignore "
573 : "RTM_NEWLINK",
574 0 : drv->ifname);
575 0 : return;
576 : }
577 179 : if (!drv->if_removed) {
578 179 : wpa_printf(MSG_DEBUG, "WEXT: if_removed "
579 : "already cleared - ignore event");
580 179 : return;
581 : }
582 0 : drv->if_removed = 0;
583 : }
584 : }
585 :
586 0 : wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
587 : }
588 :
589 :
590 0 : static int wpa_driver_wext_own_ifname(struct wpa_driver_wext_data *drv,
591 : u8 *buf, size_t len)
592 : {
593 : int attrlen, rta_len;
594 : struct rtattr *attr;
595 :
596 0 : attrlen = len;
597 0 : attr = (struct rtattr *) buf;
598 :
599 0 : rta_len = RTA_ALIGN(sizeof(struct rtattr));
600 0 : while (RTA_OK(attr, attrlen)) {
601 0 : if (attr->rta_type == IFLA_IFNAME) {
602 0 : if (os_strcmp(((char *) attr) + rta_len, drv->ifname)
603 : == 0)
604 0 : return 1;
605 : else
606 0 : break;
607 : }
608 0 : attr = RTA_NEXT(attr, attrlen);
609 : }
610 :
611 0 : return 0;
612 : }
613 :
614 :
615 213 : static int wpa_driver_wext_own_ifindex(struct wpa_driver_wext_data *drv,
616 : int ifindex, u8 *buf, size_t len)
617 : {
618 213 : if (drv->ifindex == ifindex || drv->ifindex2 == ifindex)
619 179 : return 1;
620 :
621 34 : if (drv->if_removed && wpa_driver_wext_own_ifname(drv, buf, len)) {
622 0 : drv->ifindex = if_nametoindex(drv->ifname);
623 0 : wpa_printf(MSG_DEBUG, "WEXT: Update ifindex for a removed "
624 : "interface");
625 0 : wpa_driver_wext_finish_drv_init(drv);
626 0 : return 1;
627 : }
628 :
629 34 : return 0;
630 : }
631 :
632 :
633 213 : static void wpa_driver_wext_event_rtm_newlink(void *ctx, struct ifinfomsg *ifi,
634 : u8 *buf, size_t len)
635 : {
636 213 : struct wpa_driver_wext_data *drv = ctx;
637 : int attrlen, rta_len;
638 : struct rtattr *attr;
639 : char namebuf[IFNAMSIZ];
640 :
641 213 : if (!wpa_driver_wext_own_ifindex(drv, ifi->ifi_index, buf, len)) {
642 34 : wpa_printf(MSG_DEBUG, "Ignore event for foreign ifindex %d",
643 : ifi->ifi_index);
644 247 : return;
645 : }
646 :
647 716 : wpa_printf(MSG_DEBUG, "RTM_NEWLINK: operstate=%d ifi_flags=0x%x "
648 : "(%s%s%s%s)",
649 : drv->operstate, ifi->ifi_flags,
650 179 : (ifi->ifi_flags & IFF_UP) ? "[UP]" : "",
651 179 : (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
652 179 : (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
653 179 : (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
654 :
655 179 : if (!drv->if_disabled && !(ifi->ifi_flags & IFF_UP)) {
656 1 : wpa_printf(MSG_DEBUG, "WEXT: Interface down");
657 1 : drv->if_disabled = 1;
658 1 : wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_DISABLED, NULL);
659 : }
660 :
661 179 : if (drv->if_disabled && (ifi->ifi_flags & IFF_UP)) {
662 4 : if (if_indextoname(ifi->ifi_index, namebuf) &&
663 2 : linux_iface_up(drv->ioctl_sock, drv->ifname) == 0) {
664 1 : wpa_printf(MSG_DEBUG, "WEXT: Ignore interface up "
665 : "event since interface %s is down",
666 : namebuf);
667 1 : } else if (if_nametoindex(drv->ifname) == 0) {
668 0 : wpa_printf(MSG_DEBUG, "WEXT: Ignore interface up "
669 : "event since interface %s does not exist",
670 0 : drv->ifname);
671 1 : } else if (drv->if_removed) {
672 0 : wpa_printf(MSG_DEBUG, "WEXT: Ignore interface up "
673 : "event since interface %s is marked "
674 0 : "removed", drv->ifname);
675 : } else {
676 1 : wpa_printf(MSG_DEBUG, "WEXT: Interface up");
677 1 : drv->if_disabled = 0;
678 1 : wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED,
679 : NULL);
680 : }
681 : }
682 :
683 : /*
684 : * Some drivers send the association event before the operup event--in
685 : * this case, lifting operstate in wpa_driver_wext_set_operstate()
686 : * fails. This will hit us when wpa_supplicant does not need to do
687 : * IEEE 802.1X authentication
688 : */
689 200 : if (drv->operstate == 1 &&
690 39 : (ifi->ifi_flags & (IFF_LOWER_UP | IFF_DORMANT)) == IFF_LOWER_UP &&
691 18 : !(ifi->ifi_flags & IFF_RUNNING))
692 0 : netlink_send_oper_ifla(drv->netlink, drv->ifindex,
693 : -1, IF_OPER_UP);
694 :
695 179 : attrlen = len;
696 179 : attr = (struct rtattr *) buf;
697 :
698 179 : rta_len = RTA_ALIGN(sizeof(struct rtattr));
699 1753 : while (RTA_OK(attr, attrlen)) {
700 1395 : if (attr->rta_type == IFLA_WIRELESS) {
701 118 : wpa_driver_wext_event_wireless(
702 : drv, ((char *) attr) + rta_len,
703 118 : attr->rta_len - rta_len);
704 1277 : } else if (attr->rta_type == IFLA_IFNAME) {
705 179 : wpa_driver_wext_event_link(drv,
706 : ((char *) attr) + rta_len,
707 179 : attr->rta_len - rta_len, 0);
708 : }
709 1395 : attr = RTA_NEXT(attr, attrlen);
710 : }
711 : }
712 :
713 :
714 0 : static void wpa_driver_wext_event_rtm_dellink(void *ctx, struct ifinfomsg *ifi,
715 : u8 *buf, size_t len)
716 : {
717 0 : struct wpa_driver_wext_data *drv = ctx;
718 : int attrlen, rta_len;
719 : struct rtattr *attr;
720 :
721 0 : attrlen = len;
722 0 : attr = (struct rtattr *) buf;
723 :
724 0 : rta_len = RTA_ALIGN(sizeof(struct rtattr));
725 0 : while (RTA_OK(attr, attrlen)) {
726 0 : if (attr->rta_type == IFLA_IFNAME) {
727 0 : wpa_driver_wext_event_link(drv,
728 : ((char *) attr) + rta_len,
729 0 : attr->rta_len - rta_len, 1);
730 : }
731 0 : attr = RTA_NEXT(attr, attrlen);
732 : }
733 0 : }
734 :
735 :
736 1 : static void wpa_driver_wext_rfkill_blocked(void *ctx)
737 : {
738 1 : wpa_printf(MSG_DEBUG, "WEXT: RFKILL blocked");
739 : /*
740 : * This may be for any interface; use ifdown event to disable
741 : * interface.
742 : */
743 1 : }
744 :
745 :
746 1 : static void wpa_driver_wext_rfkill_unblocked(void *ctx)
747 : {
748 1 : struct wpa_driver_wext_data *drv = ctx;
749 1 : wpa_printf(MSG_DEBUG, "WEXT: RFKILL unblocked");
750 1 : if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1)) {
751 0 : wpa_printf(MSG_DEBUG, "WEXT: Could not set interface UP "
752 : "after rfkill unblock");
753 0 : return;
754 : }
755 : /* rtnetlink ifup handler will report interface as enabled */
756 : }
757 :
758 :
759 9 : static void wext_get_phy_name(struct wpa_driver_wext_data *drv)
760 : {
761 : /* Find phy (radio) to which this interface belongs */
762 : char buf[90], *pos;
763 : int f, rv;
764 :
765 9 : drv->phyname[0] = '\0';
766 9 : snprintf(buf, sizeof(buf) - 1, "/sys/class/net/%s/phy80211/name",
767 9 : drv->ifname);
768 9 : f = open(buf, O_RDONLY);
769 9 : if (f < 0) {
770 0 : wpa_printf(MSG_DEBUG, "Could not open file %s: %s",
771 0 : buf, strerror(errno));
772 0 : return;
773 : }
774 :
775 9 : rv = read(f, drv->phyname, sizeof(drv->phyname) - 1);
776 9 : close(f);
777 9 : if (rv < 0) {
778 0 : wpa_printf(MSG_DEBUG, "Could not read file %s: %s",
779 0 : buf, strerror(errno));
780 0 : return;
781 : }
782 :
783 9 : drv->phyname[rv] = '\0';
784 9 : pos = os_strchr(drv->phyname, '\n');
785 9 : if (pos)
786 9 : *pos = '\0';
787 9 : wpa_printf(MSG_DEBUG, "wext: interface %s phy: %s",
788 9 : drv->ifname, drv->phyname);
789 : }
790 :
791 :
792 : /**
793 : * wpa_driver_wext_init - Initialize WE driver interface
794 : * @ctx: context to be used when calling wpa_supplicant functions,
795 : * e.g., wpa_supplicant_event()
796 : * @ifname: interface name, e.g., wlan0
797 : * Returns: Pointer to private data, %NULL on failure
798 : */
799 9 : void * wpa_driver_wext_init(void *ctx, const char *ifname)
800 : {
801 : struct wpa_driver_wext_data *drv;
802 : struct netlink_config *cfg;
803 : struct rfkill_config *rcfg;
804 : char path[128];
805 : struct stat buf;
806 :
807 9 : drv = os_zalloc(sizeof(*drv));
808 9 : if (drv == NULL)
809 0 : return NULL;
810 9 : drv->ctx = ctx;
811 9 : os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
812 :
813 9 : os_snprintf(path, sizeof(path), "/sys/class/net/%s/phy80211", ifname);
814 9 : if (stat(path, &buf) == 0) {
815 9 : wpa_printf(MSG_DEBUG, "WEXT: cfg80211-based driver detected");
816 9 : drv->cfg80211 = 1;
817 9 : wext_get_phy_name(drv);
818 : }
819 :
820 9 : drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
821 9 : if (drv->ioctl_sock < 0) {
822 0 : wpa_printf(MSG_ERROR, "socket(PF_INET,SOCK_DGRAM): %s",
823 0 : strerror(errno));
824 0 : goto err1;
825 : }
826 :
827 9 : cfg = os_zalloc(sizeof(*cfg));
828 9 : if (cfg == NULL)
829 0 : goto err1;
830 9 : cfg->ctx = drv;
831 9 : cfg->newlink_cb = wpa_driver_wext_event_rtm_newlink;
832 9 : cfg->dellink_cb = wpa_driver_wext_event_rtm_dellink;
833 9 : drv->netlink = netlink_init(cfg);
834 9 : if (drv->netlink == NULL) {
835 0 : os_free(cfg);
836 0 : goto err2;
837 : }
838 :
839 9 : rcfg = os_zalloc(sizeof(*rcfg));
840 9 : if (rcfg == NULL)
841 0 : goto err3;
842 9 : rcfg->ctx = drv;
843 9 : os_strlcpy(rcfg->ifname, ifname, sizeof(rcfg->ifname));
844 9 : rcfg->blocked_cb = wpa_driver_wext_rfkill_blocked;
845 9 : rcfg->unblocked_cb = wpa_driver_wext_rfkill_unblocked;
846 9 : drv->rfkill = rfkill_init(rcfg);
847 9 : if (drv->rfkill == NULL) {
848 0 : wpa_printf(MSG_DEBUG, "WEXT: RFKILL status not available");
849 0 : os_free(rcfg);
850 : }
851 :
852 9 : drv->mlme_sock = -1;
853 :
854 9 : if (wpa_driver_wext_finish_drv_init(drv) < 0)
855 0 : goto err3;
856 :
857 9 : wpa_driver_wext_set_auth_param(drv, IW_AUTH_WPA_ENABLED, 1);
858 :
859 9 : return drv;
860 :
861 : err3:
862 0 : rfkill_deinit(drv->rfkill);
863 0 : netlink_deinit(drv->netlink);
864 : err2:
865 0 : close(drv->ioctl_sock);
866 : err1:
867 0 : os_free(drv);
868 0 : return NULL;
869 : }
870 :
871 :
872 0 : static void wpa_driver_wext_send_rfkill(void *eloop_ctx, void *timeout_ctx)
873 : {
874 0 : wpa_supplicant_event(timeout_ctx, EVENT_INTERFACE_DISABLED, NULL);
875 0 : }
876 :
877 :
878 0 : static int wext_hostap_ifname(struct wpa_driver_wext_data *drv,
879 : const char *ifname)
880 : {
881 : char buf[200], *res;
882 : int type;
883 : FILE *f;
884 :
885 0 : if (strcmp(ifname, ".") == 0 || strcmp(ifname, "..") == 0)
886 0 : return -1;
887 :
888 0 : snprintf(buf, sizeof(buf), "/sys/class/net/%s/device/net/%s/type",
889 0 : drv->ifname, ifname);
890 :
891 0 : f = fopen(buf, "r");
892 0 : if (!f)
893 0 : return -1;
894 0 : res = fgets(buf, sizeof(buf), f);
895 0 : fclose(f);
896 :
897 0 : type = res ? atoi(res) : -1;
898 0 : wpa_printf(MSG_DEBUG, "WEXT: hostap ifname %s type %d", ifname, type);
899 :
900 0 : if (type == ARPHRD_IEEE80211) {
901 0 : wpa_printf(MSG_DEBUG,
902 : "WEXT: Found hostap driver wifi# interface (%s)",
903 : ifname);
904 0 : wpa_driver_wext_alternative_ifindex(drv, ifname);
905 0 : return 0;
906 : }
907 0 : return -1;
908 : }
909 :
910 :
911 0 : static int wext_add_hostap(struct wpa_driver_wext_data *drv)
912 : {
913 : char buf[200];
914 : int n;
915 : struct dirent **names;
916 0 : int ret = -1;
917 :
918 0 : snprintf(buf, sizeof(buf), "/sys/class/net/%s/device/net", drv->ifname);
919 0 : n = scandir(buf, &names, NULL, alphasort);
920 0 : if (n < 0)
921 0 : return -1;
922 :
923 0 : while (n--) {
924 0 : if (ret < 0 && wext_hostap_ifname(drv, names[n]->d_name) == 0)
925 0 : ret = 0;
926 0 : free(names[n]);
927 : }
928 0 : free(names);
929 :
930 0 : return ret;
931 : }
932 :
933 :
934 9 : static void wext_check_hostap(struct wpa_driver_wext_data *drv)
935 : {
936 : char buf[200], *pos;
937 : ssize_t res;
938 :
939 : /*
940 : * Host AP driver may use both wlan# and wifi# interface in wireless
941 : * events. Since some of the versions included WE-18 support, let's add
942 : * the alternative ifindex also from driver_wext.c for the time being.
943 : * This may be removed at some point once it is believed that old
944 : * versions of the driver are not in use anymore. However, it looks like
945 : * the wifi# interface is still used in the current kernel tree, so it
946 : * may not really be possible to remove this before the Host AP driver
947 : * gets removed from the kernel.
948 : */
949 :
950 : /* First, try to see if driver information is available from sysfs */
951 9 : snprintf(buf, sizeof(buf), "/sys/class/net/%s/device/driver",
952 9 : drv->ifname);
953 9 : res = readlink(buf, buf, sizeof(buf) - 1);
954 9 : if (res > 0) {
955 9 : buf[res] = '\0';
956 9 : pos = strrchr(buf, '/');
957 9 : if (pos)
958 9 : pos++;
959 : else
960 0 : pos = buf;
961 9 : wpa_printf(MSG_DEBUG, "WEXT: Driver: %s", pos);
962 9 : if (os_strncmp(pos, "hostap", 6) == 0 &&
963 0 : wext_add_hostap(drv) == 0)
964 9 : return;
965 : }
966 :
967 : /* Second, use the old design with hardcoded ifname */
968 9 : if (os_strncmp(drv->ifname, "wlan", 4) == 0) {
969 : char ifname2[IFNAMSIZ + 1];
970 9 : os_strlcpy(ifname2, drv->ifname, sizeof(ifname2));
971 9 : os_memcpy(ifname2, "wifi", 4);
972 9 : wpa_driver_wext_alternative_ifindex(drv, ifname2);
973 : }
974 : }
975 :
976 :
977 9 : static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv)
978 : {
979 9 : int send_rfkill_event = 0;
980 :
981 9 : if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1) < 0) {
982 0 : if (rfkill_is_blocked(drv->rfkill)) {
983 0 : wpa_printf(MSG_DEBUG, "WEXT: Could not yet enable "
984 : "interface '%s' due to rfkill",
985 0 : drv->ifname);
986 0 : drv->if_disabled = 1;
987 0 : send_rfkill_event = 1;
988 : } else {
989 0 : wpa_printf(MSG_ERROR, "WEXT: Could not set "
990 0 : "interface '%s' UP", drv->ifname);
991 0 : return -1;
992 : }
993 : }
994 :
995 : /*
996 : * Make sure that the driver does not have any obsolete PMKID entries.
997 : */
998 9 : wpa_driver_wext_flush_pmkid(drv);
999 :
1000 9 : if (wpa_driver_wext_set_mode(drv, 0) < 0) {
1001 0 : wpa_printf(MSG_DEBUG, "Could not configure driver to use "
1002 : "managed mode");
1003 : /* Try to use it anyway */
1004 : }
1005 :
1006 9 : wpa_driver_wext_get_range(drv);
1007 :
1008 : /*
1009 : * Unlock the driver's BSSID and force to a random SSID to clear any
1010 : * previous association the driver might have when the supplicant
1011 : * starts up.
1012 : */
1013 9 : wpa_driver_wext_disconnect(drv);
1014 :
1015 9 : drv->ifindex = if_nametoindex(drv->ifname);
1016 :
1017 9 : wext_check_hostap(drv);
1018 :
1019 9 : netlink_send_oper_ifla(drv->netlink, drv->ifindex,
1020 : 1, IF_OPER_DORMANT);
1021 :
1022 9 : if (send_rfkill_event) {
1023 0 : eloop_register_timeout(0, 0, wpa_driver_wext_send_rfkill,
1024 : drv, drv->ctx);
1025 : }
1026 :
1027 9 : return 0;
1028 : }
1029 :
1030 :
1031 : /**
1032 : * wpa_driver_wext_deinit - Deinitialize WE driver interface
1033 : * @priv: Pointer to private wext data from wpa_driver_wext_init()
1034 : *
1035 : * Shut down driver interface and processing of driver events. Free
1036 : * private data buffer if one was allocated in wpa_driver_wext_init().
1037 : */
1038 9 : void wpa_driver_wext_deinit(void *priv)
1039 : {
1040 9 : struct wpa_driver_wext_data *drv = priv;
1041 :
1042 9 : wpa_driver_wext_set_auth_param(drv, IW_AUTH_WPA_ENABLED, 0);
1043 :
1044 9 : eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv, drv->ctx);
1045 :
1046 : /*
1047 : * Clear possibly configured driver parameters in order to make it
1048 : * easier to use the driver after wpa_supplicant has been terminated.
1049 : */
1050 9 : wpa_driver_wext_disconnect(drv);
1051 :
1052 9 : netlink_send_oper_ifla(drv->netlink, drv->ifindex, 0, IF_OPER_UP);
1053 9 : netlink_deinit(drv->netlink);
1054 9 : rfkill_deinit(drv->rfkill);
1055 :
1056 9 : if (drv->mlme_sock >= 0)
1057 0 : eloop_unregister_read_sock(drv->mlme_sock);
1058 :
1059 9 : (void) linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 0);
1060 :
1061 9 : close(drv->ioctl_sock);
1062 9 : if (drv->mlme_sock >= 0)
1063 0 : close(drv->mlme_sock);
1064 9 : os_free(drv->assoc_req_ies);
1065 9 : os_free(drv->assoc_resp_ies);
1066 9 : os_free(drv);
1067 9 : }
1068 :
1069 :
1070 : /**
1071 : * wpa_driver_wext_scan_timeout - Scan timeout to report scan completion
1072 : * @eloop_ctx: Unused
1073 : * @timeout_ctx: ctx argument given to wpa_driver_wext_init()
1074 : *
1075 : * This function can be used as registered timeout when starting a scan to
1076 : * generate a scan completed event if the driver does not report this.
1077 : */
1078 0 : void wpa_driver_wext_scan_timeout(void *eloop_ctx, void *timeout_ctx)
1079 : {
1080 0 : wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
1081 0 : wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
1082 0 : }
1083 :
1084 :
1085 : /**
1086 : * wpa_driver_wext_scan - Request the driver to initiate scan
1087 : * @priv: Pointer to private wext data from wpa_driver_wext_init()
1088 : * @param: Scan parameters (specific SSID to scan for (ProbeReq), etc.)
1089 : * Returns: 0 on success, -1 on failure
1090 : */
1091 15 : int wpa_driver_wext_scan(void *priv, struct wpa_driver_scan_params *params)
1092 : {
1093 15 : struct wpa_driver_wext_data *drv = priv;
1094 : struct iwreq iwr;
1095 15 : int ret = 0, timeout;
1096 : struct iw_scan_req req;
1097 15 : const u8 *ssid = params->ssids[0].ssid;
1098 15 : size_t ssid_len = params->ssids[0].ssid_len;
1099 :
1100 15 : if (ssid_len > IW_ESSID_MAX_SIZE) {
1101 0 : wpa_printf(MSG_DEBUG, "%s: too long SSID (%lu)",
1102 : __FUNCTION__, (unsigned long) ssid_len);
1103 0 : return -1;
1104 : }
1105 :
1106 15 : os_memset(&iwr, 0, sizeof(iwr));
1107 15 : os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1108 :
1109 15 : if (ssid && ssid_len) {
1110 2 : os_memset(&req, 0, sizeof(req));
1111 2 : req.essid_len = ssid_len;
1112 2 : req.bssid.sa_family = ARPHRD_ETHER;
1113 2 : os_memset(req.bssid.sa_data, 0xff, ETH_ALEN);
1114 2 : os_memcpy(req.essid, ssid, ssid_len);
1115 2 : iwr.u.data.pointer = (caddr_t) &req;
1116 2 : iwr.u.data.length = sizeof(req);
1117 2 : iwr.u.data.flags = IW_SCAN_THIS_ESSID;
1118 : }
1119 :
1120 15 : if (ioctl(drv->ioctl_sock, SIOCSIWSCAN, &iwr) < 0) {
1121 0 : wpa_printf(MSG_ERROR, "ioctl[SIOCSIWSCAN]: %s",
1122 0 : strerror(errno));
1123 0 : ret = -1;
1124 : }
1125 :
1126 : /* Not all drivers generate "scan completed" wireless event, so try to
1127 : * read results after a timeout. */
1128 15 : timeout = 10;
1129 15 : if (drv->scan_complete_events) {
1130 : /*
1131 : * The driver seems to deliver SIOCGIWSCAN events to notify
1132 : * when scan is complete, so use longer timeout to avoid race
1133 : * conditions with scanning and following association request.
1134 : */
1135 6 : timeout = 30;
1136 : }
1137 15 : wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d "
1138 : "seconds", ret, timeout);
1139 15 : eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv, drv->ctx);
1140 15 : eloop_register_timeout(timeout, 0, wpa_driver_wext_scan_timeout, drv,
1141 : drv->ctx);
1142 :
1143 15 : return ret;
1144 : }
1145 :
1146 :
1147 15 : static u8 * wpa_driver_wext_giwscan(struct wpa_driver_wext_data *drv,
1148 : size_t *len)
1149 : {
1150 : struct iwreq iwr;
1151 : u8 *res_buf;
1152 : size_t res_buf_len;
1153 :
1154 15 : res_buf_len = IW_SCAN_MAX_DATA;
1155 : for (;;) {
1156 15 : res_buf = os_malloc(res_buf_len);
1157 15 : if (res_buf == NULL)
1158 0 : return NULL;
1159 15 : os_memset(&iwr, 0, sizeof(iwr));
1160 15 : os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1161 15 : iwr.u.data.pointer = res_buf;
1162 15 : iwr.u.data.length = res_buf_len;
1163 :
1164 15 : if (ioctl(drv->ioctl_sock, SIOCGIWSCAN, &iwr) == 0)
1165 15 : break;
1166 :
1167 0 : if (errno == E2BIG && res_buf_len < 65535) {
1168 0 : os_free(res_buf);
1169 0 : res_buf = NULL;
1170 0 : res_buf_len *= 2;
1171 0 : if (res_buf_len > 65535)
1172 0 : res_buf_len = 65535; /* 16-bit length field */
1173 0 : wpa_printf(MSG_DEBUG, "Scan results did not fit - "
1174 : "trying larger buffer (%lu bytes)",
1175 : (unsigned long) res_buf_len);
1176 : } else {
1177 0 : wpa_printf(MSG_ERROR, "ioctl[SIOCGIWSCAN]: %s",
1178 0 : strerror(errno));
1179 0 : os_free(res_buf);
1180 0 : return NULL;
1181 : }
1182 0 : }
1183 :
1184 15 : if (iwr.u.data.length > res_buf_len) {
1185 0 : os_free(res_buf);
1186 0 : return NULL;
1187 : }
1188 15 : *len = iwr.u.data.length;
1189 :
1190 15 : return res_buf;
1191 : }
1192 :
1193 :
1194 : /*
1195 : * Data structure for collecting WEXT scan results. This is needed to allow
1196 : * the various methods of reporting IEs to be combined into a single IE buffer.
1197 : */
1198 : struct wext_scan_data {
1199 : struct wpa_scan_res res;
1200 : u8 *ie;
1201 : size_t ie_len;
1202 : u8 ssid[SSID_MAX_LEN];
1203 : size_t ssid_len;
1204 : int maxrate;
1205 : };
1206 :
1207 :
1208 28 : static void wext_get_scan_mode(struct iw_event *iwe,
1209 : struct wext_scan_data *res)
1210 : {
1211 28 : if (iwe->u.mode == IW_MODE_ADHOC)
1212 0 : res->res.caps |= IEEE80211_CAP_IBSS;
1213 28 : else if (iwe->u.mode == IW_MODE_MASTER || iwe->u.mode == IW_MODE_INFRA)
1214 28 : res->res.caps |= IEEE80211_CAP_ESS;
1215 28 : }
1216 :
1217 :
1218 29 : static void wext_get_scan_ssid(struct iw_event *iwe,
1219 : struct wext_scan_data *res, char *custom,
1220 : char *end)
1221 : {
1222 29 : int ssid_len = iwe->u.essid.length;
1223 29 : if (custom + ssid_len > end)
1224 29 : return;
1225 29 : if (iwe->u.essid.flags &&
1226 23 : ssid_len > 0 &&
1227 : ssid_len <= IW_ESSID_MAX_SIZE) {
1228 23 : os_memcpy(res->ssid, custom, ssid_len);
1229 23 : res->ssid_len = ssid_len;
1230 : }
1231 : }
1232 :
1233 :
1234 58 : static void wext_get_scan_freq(struct iw_event *iwe,
1235 : struct wext_scan_data *res)
1236 : {
1237 58 : int divi = 1000000, i;
1238 :
1239 58 : if (iwe->u.freq.e == 0) {
1240 : /*
1241 : * Some drivers do not report frequency, but a channel.
1242 : * Try to map this to frequency by assuming they are using
1243 : * IEEE 802.11b/g. But don't overwrite a previously parsed
1244 : * frequency if the driver sends both frequency and channel,
1245 : * since the driver may be sending an A-band channel that we
1246 : * don't handle here.
1247 : */
1248 :
1249 29 : if (res->res.freq)
1250 0 : return;
1251 :
1252 29 : if (iwe->u.freq.m >= 1 && iwe->u.freq.m <= 13) {
1253 29 : res->res.freq = 2407 + 5 * iwe->u.freq.m;
1254 29 : return;
1255 0 : } else if (iwe->u.freq.m == 14) {
1256 0 : res->res.freq = 2484;
1257 0 : return;
1258 : }
1259 : }
1260 :
1261 29 : if (iwe->u.freq.e > 6) {
1262 0 : wpa_printf(MSG_DEBUG, "Invalid freq in scan results (BSSID="
1263 : MACSTR " m=%d e=%d)",
1264 0 : MAC2STR(res->res.bssid), iwe->u.freq.m,
1265 0 : iwe->u.freq.e);
1266 0 : return;
1267 : }
1268 :
1269 203 : for (i = 0; i < iwe->u.freq.e; i++)
1270 174 : divi /= 10;
1271 29 : res->res.freq = iwe->u.freq.m / divi;
1272 : }
1273 :
1274 :
1275 29 : static void wext_get_scan_qual(struct wpa_driver_wext_data *drv,
1276 : struct iw_event *iwe,
1277 : struct wext_scan_data *res)
1278 : {
1279 29 : res->res.qual = iwe->u.qual.qual;
1280 29 : res->res.noise = iwe->u.qual.noise;
1281 29 : res->res.level = iwe->u.qual.level;
1282 29 : if (iwe->u.qual.updated & IW_QUAL_QUAL_INVALID)
1283 0 : res->res.flags |= WPA_SCAN_QUAL_INVALID;
1284 29 : if (iwe->u.qual.updated & IW_QUAL_LEVEL_INVALID)
1285 0 : res->res.flags |= WPA_SCAN_LEVEL_INVALID;
1286 29 : if (iwe->u.qual.updated & IW_QUAL_NOISE_INVALID)
1287 29 : res->res.flags |= WPA_SCAN_NOISE_INVALID;
1288 29 : if (iwe->u.qual.updated & IW_QUAL_DBM)
1289 29 : res->res.flags |= WPA_SCAN_LEVEL_DBM;
1290 29 : if ((iwe->u.qual.updated & IW_QUAL_DBM) ||
1291 0 : ((iwe->u.qual.level != 0) &&
1292 0 : (iwe->u.qual.level > drv->max_level))) {
1293 29 : if (iwe->u.qual.level >= 64)
1294 29 : res->res.level -= 0x100;
1295 29 : if (iwe->u.qual.noise >= 64)
1296 0 : res->res.noise -= 0x100;
1297 : }
1298 29 : }
1299 :
1300 :
1301 29 : static void wext_get_scan_encode(struct iw_event *iwe,
1302 : struct wext_scan_data *res)
1303 : {
1304 29 : if (!(iwe->u.data.flags & IW_ENCODE_DISABLED))
1305 16 : res->res.caps |= IEEE80211_CAP_PRIVACY;
1306 29 : }
1307 :
1308 :
1309 57 : static void wext_get_scan_rate(struct iw_event *iwe,
1310 : struct wext_scan_data *res, char *pos,
1311 : char *end)
1312 : {
1313 : int maxrate;
1314 57 : char *custom = pos + IW_EV_LCP_LEN;
1315 : struct iw_param p;
1316 : size_t clen;
1317 :
1318 57 : clen = iwe->len;
1319 57 : if (custom + clen > end)
1320 57 : return;
1321 57 : maxrate = 0;
1322 515 : while (((ssize_t) clen) >= (ssize_t) sizeof(struct iw_param)) {
1323 : /* Note: may be misaligned, make a local, aligned copy */
1324 401 : os_memcpy(&p, custom, sizeof(struct iw_param));
1325 401 : if (p.value > maxrate)
1326 288 : maxrate = p.value;
1327 401 : clen -= sizeof(struct iw_param);
1328 401 : custom += sizeof(struct iw_param);
1329 : }
1330 :
1331 : /* Convert the maxrate from WE-style (b/s units) to
1332 : * 802.11 rates (500000 b/s units).
1333 : */
1334 57 : res->maxrate = maxrate / 500000;
1335 : }
1336 :
1337 :
1338 29 : static void wext_get_scan_iwevgenie(struct iw_event *iwe,
1339 : struct wext_scan_data *res, char *custom,
1340 : char *end)
1341 : {
1342 : char *genie, *gpos, *gend;
1343 : u8 *tmp;
1344 :
1345 29 : if (iwe->u.data.length == 0)
1346 0 : return;
1347 :
1348 29 : gpos = genie = custom;
1349 29 : gend = genie + iwe->u.data.length;
1350 29 : if (gend > end) {
1351 0 : wpa_printf(MSG_INFO, "IWEVGENIE overflow");
1352 0 : return;
1353 : }
1354 :
1355 29 : tmp = os_realloc(res->ie, res->ie_len + gend - gpos);
1356 29 : if (tmp == NULL)
1357 0 : return;
1358 29 : os_memcpy(tmp + res->ie_len, gpos, gend - gpos);
1359 29 : res->ie = tmp;
1360 29 : res->ie_len += gend - gpos;
1361 : }
1362 :
1363 :
1364 58 : static void wext_get_scan_custom(struct iw_event *iwe,
1365 : struct wext_scan_data *res, char *custom,
1366 : char *end)
1367 : {
1368 : size_t clen;
1369 : u8 *tmp;
1370 :
1371 58 : clen = iwe->u.data.length;
1372 58 : if (custom + clen > end)
1373 0 : return;
1374 :
1375 58 : if (clen > 7 && os_strncmp(custom, "wpa_ie=", 7) == 0) {
1376 : char *spos;
1377 : int bytes;
1378 0 : spos = custom + 7;
1379 0 : bytes = custom + clen - spos;
1380 0 : if (bytes & 1 || bytes == 0)
1381 0 : return;
1382 0 : bytes /= 2;
1383 0 : tmp = os_realloc(res->ie, res->ie_len + bytes);
1384 0 : if (tmp == NULL)
1385 0 : return;
1386 0 : res->ie = tmp;
1387 0 : if (hexstr2bin(spos, tmp + res->ie_len, bytes) < 0)
1388 0 : return;
1389 0 : res->ie_len += bytes;
1390 58 : } else if (clen > 7 && os_strncmp(custom, "rsn_ie=", 7) == 0) {
1391 : char *spos;
1392 : int bytes;
1393 0 : spos = custom + 7;
1394 0 : bytes = custom + clen - spos;
1395 0 : if (bytes & 1 || bytes == 0)
1396 0 : return;
1397 0 : bytes /= 2;
1398 0 : tmp = os_realloc(res->ie, res->ie_len + bytes);
1399 0 : if (tmp == NULL)
1400 0 : return;
1401 0 : res->ie = tmp;
1402 0 : if (hexstr2bin(spos, tmp + res->ie_len, bytes) < 0)
1403 0 : return;
1404 0 : res->ie_len += bytes;
1405 58 : } else if (clen > 4 && os_strncmp(custom, "tsf=", 4) == 0) {
1406 : char *spos;
1407 : int bytes;
1408 : u8 bin[8];
1409 29 : spos = custom + 4;
1410 29 : bytes = custom + clen - spos;
1411 29 : if (bytes != 16) {
1412 0 : wpa_printf(MSG_INFO, "Invalid TSF length (%d)", bytes);
1413 0 : return;
1414 : }
1415 29 : bytes /= 2;
1416 29 : if (hexstr2bin(spos, bin, bytes) < 0) {
1417 0 : wpa_printf(MSG_DEBUG, "WEXT: Invalid TSF value");
1418 0 : return;
1419 : }
1420 29 : res->res.tsf += WPA_GET_BE64(bin);
1421 : }
1422 : }
1423 :
1424 :
1425 346 : static int wext_19_iw_point(struct wpa_driver_wext_data *drv, u16 cmd)
1426 : {
1427 491 : return drv->we_version_compiled > 18 &&
1428 317 : (cmd == SIOCGIWESSID || cmd == SIOCGIWENCODE ||
1429 259 : cmd == IWEVGENIE || cmd == IWEVCUSTOM);
1430 : }
1431 :
1432 :
1433 29 : static void wpa_driver_wext_add_scan_entry(struct wpa_scan_results *res,
1434 : struct wext_scan_data *data)
1435 : {
1436 : struct wpa_scan_res **tmp;
1437 : struct wpa_scan_res *r;
1438 : size_t extra_len;
1439 29 : u8 *pos, *end, *ssid_ie = NULL, *rate_ie = NULL;
1440 :
1441 : /* Figure out whether we need to fake any IEs */
1442 29 : pos = data->ie;
1443 29 : end = pos + data->ie_len;
1444 324 : while (pos && pos + 1 < end) {
1445 266 : if (pos + 2 + pos[1] > end)
1446 0 : break;
1447 266 : if (pos[0] == WLAN_EID_SSID)
1448 29 : ssid_ie = pos;
1449 237 : else if (pos[0] == WLAN_EID_SUPP_RATES)
1450 29 : rate_ie = pos;
1451 208 : else if (pos[0] == WLAN_EID_EXT_SUPP_RATES)
1452 28 : rate_ie = pos;
1453 266 : pos += 2 + pos[1];
1454 : }
1455 :
1456 29 : extra_len = 0;
1457 29 : if (ssid_ie == NULL)
1458 0 : extra_len += 2 + data->ssid_len;
1459 29 : if (rate_ie == NULL && data->maxrate)
1460 0 : extra_len += 3;
1461 :
1462 29 : r = os_zalloc(sizeof(*r) + extra_len + data->ie_len);
1463 29 : if (r == NULL)
1464 0 : return;
1465 29 : os_memcpy(r, &data->res, sizeof(*r));
1466 29 : r->ie_len = extra_len + data->ie_len;
1467 29 : pos = (u8 *) (r + 1);
1468 29 : if (ssid_ie == NULL) {
1469 : /*
1470 : * Generate a fake SSID IE since the driver did not report
1471 : * a full IE list.
1472 : */
1473 0 : *pos++ = WLAN_EID_SSID;
1474 0 : *pos++ = data->ssid_len;
1475 0 : os_memcpy(pos, data->ssid, data->ssid_len);
1476 0 : pos += data->ssid_len;
1477 : }
1478 29 : if (rate_ie == NULL && data->maxrate) {
1479 : /*
1480 : * Generate a fake Supported Rates IE since the driver did not
1481 : * report a full IE list.
1482 : */
1483 0 : *pos++ = WLAN_EID_SUPP_RATES;
1484 0 : *pos++ = 1;
1485 0 : *pos++ = data->maxrate;
1486 : }
1487 29 : if (data->ie)
1488 29 : os_memcpy(pos, data->ie, data->ie_len);
1489 :
1490 29 : tmp = os_realloc_array(res->res, res->num + 1,
1491 : sizeof(struct wpa_scan_res *));
1492 29 : if (tmp == NULL) {
1493 0 : os_free(r);
1494 0 : return;
1495 : }
1496 29 : tmp[res->num++] = r;
1497 29 : res->res = tmp;
1498 : }
1499 :
1500 :
1501 : /**
1502 : * wpa_driver_wext_get_scan_results - Fetch the latest scan results
1503 : * @priv: Pointer to private wext data from wpa_driver_wext_init()
1504 : * Returns: Scan results on success, -1 on failure
1505 : */
1506 15 : struct wpa_scan_results * wpa_driver_wext_get_scan_results(void *priv)
1507 : {
1508 15 : struct wpa_driver_wext_data *drv = priv;
1509 : size_t len;
1510 : int first;
1511 : u8 *res_buf;
1512 15 : struct iw_event iwe_buf, *iwe = &iwe_buf;
1513 : char *pos, *end, *custom;
1514 : struct wpa_scan_results *res;
1515 : struct wext_scan_data data;
1516 :
1517 15 : res_buf = wpa_driver_wext_giwscan(drv, &len);
1518 15 : if (res_buf == NULL)
1519 0 : return NULL;
1520 :
1521 15 : first = 1;
1522 :
1523 15 : res = os_zalloc(sizeof(*res));
1524 15 : if (res == NULL) {
1525 0 : os_free(res_buf);
1526 0 : return NULL;
1527 : }
1528 :
1529 15 : pos = (char *) res_buf;
1530 15 : end = (char *) res_buf + len;
1531 15 : os_memset(&data, 0, sizeof(data));
1532 :
1533 376 : while (pos + IW_EV_LCP_LEN <= end) {
1534 : /* Event data may be unaligned, so make a local, aligned copy
1535 : * before processing. */
1536 346 : os_memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
1537 346 : if (iwe->len <= IW_EV_LCP_LEN)
1538 0 : break;
1539 :
1540 346 : custom = pos + IW_EV_POINT_LEN;
1541 346 : if (wext_19_iw_point(drv, iwe->cmd)) {
1542 : /* WE-19 removed the pointer from struct iw_point */
1543 145 : char *dpos = (char *) &iwe_buf.u.data.length;
1544 145 : int dlen = dpos - (char *) &iwe_buf;
1545 145 : os_memcpy(dpos, pos + IW_EV_LCP_LEN,
1546 : sizeof(struct iw_event) - dlen);
1547 : } else {
1548 201 : os_memcpy(&iwe_buf, pos, sizeof(struct iw_event));
1549 201 : custom += IW_EV_POINT_OFF;
1550 : }
1551 :
1552 346 : switch (iwe->cmd) {
1553 : case SIOCGIWAP:
1554 29 : if (!first)
1555 14 : wpa_driver_wext_add_scan_entry(res, &data);
1556 29 : first = 0;
1557 29 : os_free(data.ie);
1558 29 : os_memset(&data, 0, sizeof(data));
1559 29 : os_memcpy(data.res.bssid,
1560 : iwe->u.ap_addr.sa_data, ETH_ALEN);
1561 29 : break;
1562 : case SIOCGIWMODE:
1563 28 : wext_get_scan_mode(iwe, &data);
1564 28 : break;
1565 : case SIOCGIWESSID:
1566 29 : wext_get_scan_ssid(iwe, &data, custom, end);
1567 29 : break;
1568 : case SIOCGIWFREQ:
1569 58 : wext_get_scan_freq(iwe, &data);
1570 58 : break;
1571 : case IWEVQUAL:
1572 29 : wext_get_scan_qual(drv, iwe, &data);
1573 29 : break;
1574 : case SIOCGIWENCODE:
1575 29 : wext_get_scan_encode(iwe, &data);
1576 29 : break;
1577 : case SIOCGIWRATE:
1578 57 : wext_get_scan_rate(iwe, &data, pos, end);
1579 57 : break;
1580 : case IWEVGENIE:
1581 29 : wext_get_scan_iwevgenie(iwe, &data, custom, end);
1582 29 : break;
1583 : case IWEVCUSTOM:
1584 58 : wext_get_scan_custom(iwe, &data, custom, end);
1585 58 : break;
1586 : }
1587 :
1588 346 : pos += iwe->len;
1589 : }
1590 15 : os_free(res_buf);
1591 15 : res_buf = NULL;
1592 15 : if (!first)
1593 15 : wpa_driver_wext_add_scan_entry(res, &data);
1594 15 : os_free(data.ie);
1595 :
1596 15 : wpa_printf(MSG_DEBUG, "Received %lu bytes of scan results (%lu BSSes)",
1597 : (unsigned long) len, (unsigned long) res->num);
1598 :
1599 15 : return res;
1600 : }
1601 :
1602 :
1603 9 : static int wpa_driver_wext_get_range(void *priv)
1604 : {
1605 9 : struct wpa_driver_wext_data *drv = priv;
1606 : struct iw_range *range;
1607 : struct iwreq iwr;
1608 : int minlen;
1609 : size_t buflen;
1610 :
1611 : /*
1612 : * Use larger buffer than struct iw_range in order to allow the
1613 : * structure to grow in the future.
1614 : */
1615 9 : buflen = sizeof(struct iw_range) + 500;
1616 9 : range = os_zalloc(buflen);
1617 9 : if (range == NULL)
1618 0 : return -1;
1619 :
1620 9 : os_memset(&iwr, 0, sizeof(iwr));
1621 9 : os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1622 9 : iwr.u.data.pointer = (caddr_t) range;
1623 9 : iwr.u.data.length = buflen;
1624 :
1625 9 : minlen = ((char *) &range->enc_capa) - (char *) range +
1626 : sizeof(range->enc_capa);
1627 :
1628 9 : if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) {
1629 0 : wpa_printf(MSG_ERROR, "ioctl[SIOCGIWRANGE]: %s",
1630 0 : strerror(errno));
1631 0 : os_free(range);
1632 0 : return -1;
1633 18 : } else if (iwr.u.data.length >= minlen &&
1634 9 : range->we_version_compiled >= 18) {
1635 27 : wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: WE(compiled)=%d "
1636 : "WE(source)=%d enc_capa=0x%x",
1637 9 : range->we_version_compiled,
1638 9 : range->we_version_source,
1639 : range->enc_capa);
1640 9 : drv->has_capability = 1;
1641 9 : drv->we_version_compiled = range->we_version_compiled;
1642 9 : if (range->enc_capa & IW_ENC_CAPA_WPA) {
1643 9 : drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1644 : WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK;
1645 : }
1646 9 : if (range->enc_capa & IW_ENC_CAPA_WPA2) {
1647 9 : drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
1648 : WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;
1649 : }
1650 9 : drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 |
1651 : WPA_DRIVER_CAPA_ENC_WEP104;
1652 9 : drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP128;
1653 9 : if (range->enc_capa & IW_ENC_CAPA_CIPHER_TKIP)
1654 9 : drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP;
1655 9 : if (range->enc_capa & IW_ENC_CAPA_CIPHER_CCMP)
1656 9 : drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP;
1657 9 : if (range->enc_capa & IW_ENC_CAPA_4WAY_HANDSHAKE)
1658 0 : drv->capa.flags |= WPA_DRIVER_FLAGS_4WAY_HANDSHAKE;
1659 9 : drv->capa.auth = WPA_DRIVER_AUTH_OPEN |
1660 : WPA_DRIVER_AUTH_SHARED |
1661 : WPA_DRIVER_AUTH_LEAP;
1662 9 : drv->capa.max_scan_ssids = 1;
1663 :
1664 9 : wpa_printf(MSG_DEBUG, " capabilities: key_mgmt 0x%x enc 0x%x "
1665 : "flags 0x%llx",
1666 : drv->capa.key_mgmt, drv->capa.enc,
1667 9 : (unsigned long long) drv->capa.flags);
1668 : } else {
1669 0 : wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: too old (short) data - "
1670 : "assuming WPA is not supported");
1671 : }
1672 :
1673 9 : drv->max_level = range->max_qual.level;
1674 :
1675 9 : os_free(range);
1676 9 : return 0;
1677 : }
1678 :
1679 :
1680 14 : static int wpa_driver_wext_set_psk(struct wpa_driver_wext_data *drv,
1681 : const u8 *psk)
1682 : {
1683 : struct iw_encode_ext *ext;
1684 : struct iwreq iwr;
1685 : int ret;
1686 :
1687 14 : wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
1688 :
1689 14 : if (!(drv->capa.flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
1690 14 : return 0;
1691 :
1692 0 : if (!psk)
1693 0 : return 0;
1694 :
1695 0 : os_memset(&iwr, 0, sizeof(iwr));
1696 0 : os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1697 :
1698 0 : ext = os_zalloc(sizeof(*ext) + PMK_LEN);
1699 0 : if (ext == NULL)
1700 0 : return -1;
1701 :
1702 0 : iwr.u.encoding.pointer = (caddr_t) ext;
1703 0 : iwr.u.encoding.length = sizeof(*ext) + PMK_LEN;
1704 0 : ext->key_len = PMK_LEN;
1705 0 : os_memcpy(&ext->key, psk, ext->key_len);
1706 0 : ext->alg = IW_ENCODE_ALG_PMK;
1707 :
1708 0 : ret = ioctl(drv->ioctl_sock, SIOCSIWENCODEEXT, &iwr);
1709 0 : if (ret < 0)
1710 0 : wpa_printf(MSG_ERROR, "ioctl[SIOCSIWENCODEEXT] PMK: %s",
1711 0 : strerror(errno));
1712 0 : os_free(ext);
1713 :
1714 0 : return ret;
1715 : }
1716 :
1717 :
1718 99 : static int wpa_driver_wext_set_key_ext(void *priv, enum wpa_alg alg,
1719 : const u8 *addr, int key_idx,
1720 : int set_tx, const u8 *seq,
1721 : size_t seq_len,
1722 : const u8 *key, size_t key_len)
1723 : {
1724 99 : struct wpa_driver_wext_data *drv = priv;
1725 : struct iwreq iwr;
1726 99 : int ret = 0;
1727 : struct iw_encode_ext *ext;
1728 :
1729 99 : if (seq_len > IW_ENCODE_SEQ_MAX_SIZE) {
1730 0 : wpa_printf(MSG_DEBUG, "%s: Invalid seq_len %lu",
1731 : __FUNCTION__, (unsigned long) seq_len);
1732 0 : return -1;
1733 : }
1734 :
1735 99 : ext = os_zalloc(sizeof(*ext) + key_len);
1736 99 : if (ext == NULL)
1737 0 : return -1;
1738 99 : os_memset(&iwr, 0, sizeof(iwr));
1739 99 : os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1740 99 : iwr.u.encoding.flags = key_idx + 1;
1741 99 : iwr.u.encoding.flags |= IW_ENCODE_TEMP;
1742 99 : if (alg == WPA_ALG_NONE)
1743 79 : iwr.u.encoding.flags |= IW_ENCODE_DISABLED;
1744 99 : iwr.u.encoding.pointer = (caddr_t) ext;
1745 99 : iwr.u.encoding.length = sizeof(*ext) + key_len;
1746 :
1747 99 : if (addr == NULL || is_broadcast_ether_addr(addr))
1748 84 : ext->ext_flags |= IW_ENCODE_EXT_GROUP_KEY;
1749 99 : if (set_tx)
1750 11 : ext->ext_flags |= IW_ENCODE_EXT_SET_TX_KEY;
1751 :
1752 99 : ext->addr.sa_family = ARPHRD_ETHER;
1753 99 : if (addr)
1754 24 : os_memcpy(ext->addr.sa_data, addr, ETH_ALEN);
1755 : else
1756 75 : os_memset(ext->addr.sa_data, 0xff, ETH_ALEN);
1757 99 : if (key && key_len) {
1758 20 : os_memcpy(ext + 1, key, key_len);
1759 20 : ext->key_len = key_len;
1760 : }
1761 99 : switch (alg) {
1762 : case WPA_ALG_NONE:
1763 79 : ext->alg = IW_ENCODE_ALG_NONE;
1764 79 : break;
1765 : case WPA_ALG_WEP:
1766 3 : ext->alg = IW_ENCODE_ALG_WEP;
1767 3 : break;
1768 : case WPA_ALG_TKIP:
1769 4 : ext->alg = IW_ENCODE_ALG_TKIP;
1770 4 : break;
1771 : case WPA_ALG_CCMP:
1772 12 : ext->alg = IW_ENCODE_ALG_CCMP;
1773 12 : break;
1774 : case WPA_ALG_PMK:
1775 0 : ext->alg = IW_ENCODE_ALG_PMK;
1776 0 : break;
1777 : #ifdef CONFIG_IEEE80211W
1778 : case WPA_ALG_IGTK:
1779 1 : ext->alg = IW_ENCODE_ALG_AES_CMAC;
1780 1 : break;
1781 : #endif /* CONFIG_IEEE80211W */
1782 : default:
1783 0 : wpa_printf(MSG_DEBUG, "%s: Unknown algorithm %d",
1784 : __FUNCTION__, alg);
1785 0 : os_free(ext);
1786 0 : return -1;
1787 : }
1788 :
1789 99 : if (seq && seq_len) {
1790 17 : ext->ext_flags |= IW_ENCODE_EXT_RX_SEQ_VALID;
1791 17 : os_memcpy(ext->rx_seq, seq, seq_len);
1792 : }
1793 :
1794 99 : if (ioctl(drv->ioctl_sock, SIOCSIWENCODEEXT, &iwr) < 0) {
1795 19 : ret = errno == EOPNOTSUPP ? -2 : -1;
1796 19 : if (errno == ENODEV) {
1797 : /*
1798 : * ndiswrapper seems to be returning incorrect error
1799 : * code.. */
1800 0 : ret = -2;
1801 : }
1802 :
1803 19 : wpa_printf(MSG_ERROR, "ioctl[SIOCSIWENCODEEXT]: %s",
1804 19 : strerror(errno));
1805 : }
1806 :
1807 99 : os_free(ext);
1808 99 : return ret;
1809 : }
1810 :
1811 :
1812 : /**
1813 : * wpa_driver_wext_set_key - Configure encryption key
1814 : * @priv: Pointer to private wext data from wpa_driver_wext_init()
1815 : * @priv: Private driver interface data
1816 : * @alg: Encryption algorithm (%WPA_ALG_NONE, %WPA_ALG_WEP,
1817 : * %WPA_ALG_TKIP, %WPA_ALG_CCMP); %WPA_ALG_NONE clears the key.
1818 : * @addr: Address of the peer STA or ff:ff:ff:ff:ff:ff for
1819 : * broadcast/default keys
1820 : * @key_idx: key index (0..3), usually 0 for unicast keys
1821 : * @set_tx: Configure this key as the default Tx key (only used when
1822 : * driver does not support separate unicast/individual key
1823 : * @seq: Sequence number/packet number, seq_len octets, the next
1824 : * packet number to be used for in replay protection; configured
1825 : * for Rx keys (in most cases, this is only used with broadcast
1826 : * keys and set to zero for unicast keys)
1827 : * @seq_len: Length of the seq, depends on the algorithm:
1828 : * TKIP: 6 octets, CCMP: 6 octets
1829 : * @key: Key buffer; TKIP: 16-byte temporal key, 8-byte Tx Mic key,
1830 : * 8-byte Rx Mic Key
1831 : * @key_len: Length of the key buffer in octets (WEP: 5 or 13,
1832 : * TKIP: 32, CCMP: 16)
1833 : * Returns: 0 on success, -1 on failure
1834 : *
1835 : * This function uses SIOCSIWENCODEEXT by default, but tries to use
1836 : * SIOCSIWENCODE if the extended ioctl fails when configuring a WEP key.
1837 : */
1838 99 : int wpa_driver_wext_set_key(const char *ifname, void *priv, enum wpa_alg alg,
1839 : const u8 *addr, int key_idx,
1840 : int set_tx, const u8 *seq, size_t seq_len,
1841 : const u8 *key, size_t key_len)
1842 : {
1843 99 : struct wpa_driver_wext_data *drv = priv;
1844 : struct iwreq iwr;
1845 99 : int ret = 0;
1846 :
1847 99 : wpa_printf(MSG_DEBUG, "%s: alg=%d key_idx=%d set_tx=%d seq_len=%lu "
1848 : "key_len=%lu",
1849 : __FUNCTION__, alg, key_idx, set_tx,
1850 : (unsigned long) seq_len, (unsigned long) key_len);
1851 :
1852 99 : ret = wpa_driver_wext_set_key_ext(drv, alg, addr, key_idx, set_tx,
1853 : seq, seq_len, key, key_len);
1854 99 : if (ret == 0)
1855 80 : return 0;
1856 :
1857 19 : if (ret == -2 &&
1858 0 : (alg == WPA_ALG_NONE || alg == WPA_ALG_WEP)) {
1859 0 : wpa_printf(MSG_DEBUG, "Driver did not support "
1860 : "SIOCSIWENCODEEXT, trying SIOCSIWENCODE");
1861 0 : ret = 0;
1862 : } else {
1863 19 : wpa_printf(MSG_DEBUG, "Driver did not support "
1864 : "SIOCSIWENCODEEXT");
1865 19 : return ret;
1866 : }
1867 :
1868 0 : os_memset(&iwr, 0, sizeof(iwr));
1869 0 : os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1870 0 : iwr.u.encoding.flags = key_idx + 1;
1871 0 : iwr.u.encoding.flags |= IW_ENCODE_TEMP;
1872 0 : if (alg == WPA_ALG_NONE)
1873 0 : iwr.u.encoding.flags |= IW_ENCODE_DISABLED;
1874 0 : iwr.u.encoding.pointer = (caddr_t) key;
1875 0 : iwr.u.encoding.length = key_len;
1876 :
1877 0 : if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) {
1878 0 : wpa_printf(MSG_ERROR, "ioctl[SIOCSIWENCODE]: %s",
1879 0 : strerror(errno));
1880 0 : ret = -1;
1881 : }
1882 :
1883 0 : if (set_tx && alg != WPA_ALG_NONE) {
1884 0 : os_memset(&iwr, 0, sizeof(iwr));
1885 0 : os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1886 0 : iwr.u.encoding.flags = key_idx + 1;
1887 0 : iwr.u.encoding.flags |= IW_ENCODE_TEMP;
1888 0 : iwr.u.encoding.pointer = (caddr_t) NULL;
1889 0 : iwr.u.encoding.length = 0;
1890 0 : if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) {
1891 0 : wpa_printf(MSG_ERROR,
1892 : "ioctl[SIOCSIWENCODE] (set_tx): %s",
1893 0 : strerror(errno));
1894 0 : ret = -1;
1895 : }
1896 : }
1897 :
1898 0 : return ret;
1899 : }
1900 :
1901 :
1902 19 : static int wpa_driver_wext_set_countermeasures(void *priv,
1903 : int enabled)
1904 : {
1905 19 : struct wpa_driver_wext_data *drv = priv;
1906 19 : wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
1907 19 : return wpa_driver_wext_set_auth_param(drv,
1908 : IW_AUTH_TKIP_COUNTERMEASURES,
1909 : enabled);
1910 : }
1911 :
1912 :
1913 14 : static int wpa_driver_wext_set_drop_unencrypted(void *priv,
1914 : int enabled)
1915 : {
1916 14 : struct wpa_driver_wext_data *drv = priv;
1917 14 : wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
1918 14 : drv->use_crypt = enabled;
1919 14 : return wpa_driver_wext_set_auth_param(drv, IW_AUTH_DROP_UNENCRYPTED,
1920 : enabled);
1921 : }
1922 :
1923 :
1924 9 : static int wpa_driver_wext_mlme(struct wpa_driver_wext_data *drv,
1925 : const u8 *addr, int cmd, int reason_code)
1926 : {
1927 : struct iwreq iwr;
1928 : struct iw_mlme mlme;
1929 9 : int ret = 0;
1930 :
1931 9 : os_memset(&iwr, 0, sizeof(iwr));
1932 9 : os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1933 9 : os_memset(&mlme, 0, sizeof(mlme));
1934 9 : mlme.cmd = cmd;
1935 9 : mlme.reason_code = reason_code;
1936 9 : mlme.addr.sa_family = ARPHRD_ETHER;
1937 9 : os_memcpy(mlme.addr.sa_data, addr, ETH_ALEN);
1938 9 : iwr.u.data.pointer = (caddr_t) &mlme;
1939 9 : iwr.u.data.length = sizeof(mlme);
1940 :
1941 9 : if (ioctl(drv->ioctl_sock, SIOCSIWMLME, &iwr) < 0) {
1942 0 : wpa_printf(MSG_ERROR, "ioctl[SIOCSIWMLME]: %s",
1943 0 : strerror(errno));
1944 0 : ret = -1;
1945 : }
1946 :
1947 9 : return ret;
1948 : }
1949 :
1950 :
1951 27 : static void wpa_driver_wext_disconnect(struct wpa_driver_wext_data *drv)
1952 : {
1953 : struct iwreq iwr;
1954 27 : const u8 null_bssid[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
1955 : u8 ssid[SSID_MAX_LEN];
1956 : int i;
1957 :
1958 : /*
1959 : * Only force-disconnect when the card is in infrastructure mode,
1960 : * otherwise the driver might interpret the cleared BSSID and random
1961 : * SSID as an attempt to create a new ad-hoc network.
1962 : */
1963 27 : os_memset(&iwr, 0, sizeof(iwr));
1964 27 : os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1965 27 : if (ioctl(drv->ioctl_sock, SIOCGIWMODE, &iwr) < 0) {
1966 0 : wpa_printf(MSG_ERROR, "ioctl[SIOCGIWMODE]: %s",
1967 0 : strerror(errno));
1968 0 : iwr.u.mode = IW_MODE_INFRA;
1969 : }
1970 :
1971 27 : if (iwr.u.mode == IW_MODE_INFRA) {
1972 : /* Clear the BSSID selection */
1973 27 : if (wpa_driver_wext_set_bssid(drv, null_bssid) < 0) {
1974 0 : wpa_printf(MSG_DEBUG, "WEXT: Failed to clear BSSID "
1975 : "selection on disconnect");
1976 : }
1977 :
1978 27 : if (drv->cfg80211) {
1979 : /*
1980 : * cfg80211 supports SIOCSIWMLME commands, so there is
1981 : * no need for the random SSID hack, but clear the
1982 : * SSID.
1983 : */
1984 27 : if (wpa_driver_wext_set_ssid(drv, (u8 *) "", 0) < 0) {
1985 0 : wpa_printf(MSG_DEBUG, "WEXT: Failed to clear "
1986 : "SSID on disconnect");
1987 : }
1988 54 : return;
1989 : }
1990 :
1991 : /*
1992 : * Set a random SSID to make sure the driver will not be trying
1993 : * to associate with something even if it does not understand
1994 : * SIOCSIWMLME commands (or tries to associate automatically
1995 : * after deauth/disassoc).
1996 : */
1997 0 : for (i = 0; i < SSID_MAX_LEN; i++)
1998 0 : ssid[i] = rand() & 0xFF;
1999 0 : if (wpa_driver_wext_set_ssid(drv, ssid, SSID_MAX_LEN) < 0) {
2000 0 : wpa_printf(MSG_DEBUG, "WEXT: Failed to set bogus "
2001 : "SSID to disconnect");
2002 : }
2003 : }
2004 : }
2005 :
2006 :
2007 9 : static int wpa_driver_wext_deauthenticate(void *priv, const u8 *addr,
2008 : int reason_code)
2009 : {
2010 9 : struct wpa_driver_wext_data *drv = priv;
2011 : int ret;
2012 9 : wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
2013 9 : ret = wpa_driver_wext_mlme(drv, addr, IW_MLME_DEAUTH, reason_code);
2014 9 : wpa_driver_wext_disconnect(drv);
2015 9 : return ret;
2016 : }
2017 :
2018 :
2019 14 : static int wpa_driver_wext_set_gen_ie(void *priv, const u8 *ie,
2020 : size_t ie_len)
2021 : {
2022 14 : struct wpa_driver_wext_data *drv = priv;
2023 : struct iwreq iwr;
2024 14 : int ret = 0;
2025 :
2026 14 : os_memset(&iwr, 0, sizeof(iwr));
2027 14 : os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
2028 14 : iwr.u.data.pointer = (caddr_t) ie;
2029 14 : iwr.u.data.length = ie_len;
2030 :
2031 14 : if (ioctl(drv->ioctl_sock, SIOCSIWGENIE, &iwr) < 0) {
2032 0 : wpa_printf(MSG_ERROR, "ioctl[SIOCSIWGENIE]: %s",
2033 0 : strerror(errno));
2034 0 : ret = -1;
2035 : }
2036 :
2037 14 : return ret;
2038 : }
2039 :
2040 :
2041 28 : int wpa_driver_wext_cipher2wext(int cipher)
2042 : {
2043 28 : switch (cipher) {
2044 : case WPA_CIPHER_NONE:
2045 8 : return IW_AUTH_CIPHER_NONE;
2046 : case WPA_CIPHER_WEP40:
2047 2 : return IW_AUTH_CIPHER_WEP40;
2048 : case WPA_CIPHER_TKIP:
2049 2 : return IW_AUTH_CIPHER_TKIP;
2050 : case WPA_CIPHER_CCMP:
2051 12 : return IW_AUTH_CIPHER_CCMP;
2052 : case WPA_CIPHER_WEP104:
2053 4 : return IW_AUTH_CIPHER_WEP104;
2054 : default:
2055 0 : return 0;
2056 : }
2057 : }
2058 :
2059 :
2060 14 : int wpa_driver_wext_keymgmt2wext(int keymgmt)
2061 : {
2062 14 : switch (keymgmt) {
2063 : case WPA_KEY_MGMT_IEEE8021X:
2064 : case WPA_KEY_MGMT_IEEE8021X_NO_WPA:
2065 4 : return IW_AUTH_KEY_MGMT_802_1X;
2066 : case WPA_KEY_MGMT_PSK:
2067 2 : return IW_AUTH_KEY_MGMT_PSK;
2068 : default:
2069 8 : return 0;
2070 : }
2071 : }
2072 :
2073 :
2074 : static int
2075 0 : wpa_driver_wext_auth_alg_fallback(struct wpa_driver_wext_data *drv,
2076 : struct wpa_driver_associate_params *params)
2077 : {
2078 : struct iwreq iwr;
2079 0 : int ret = 0;
2080 :
2081 0 : wpa_printf(MSG_DEBUG, "WEXT: Driver did not support "
2082 : "SIOCSIWAUTH for AUTH_ALG, trying SIOCSIWENCODE");
2083 :
2084 0 : os_memset(&iwr, 0, sizeof(iwr));
2085 0 : os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
2086 : /* Just changing mode, not actual keys */
2087 0 : iwr.u.encoding.flags = 0;
2088 0 : iwr.u.encoding.pointer = (caddr_t) NULL;
2089 0 : iwr.u.encoding.length = 0;
2090 :
2091 : /*
2092 : * Note: IW_ENCODE_{OPEN,RESTRICTED} can be interpreted to mean two
2093 : * different things. Here they are used to indicate Open System vs.
2094 : * Shared Key authentication algorithm. However, some drivers may use
2095 : * them to select between open/restricted WEP encrypted (open = allow
2096 : * both unencrypted and encrypted frames; restricted = only allow
2097 : * encrypted frames).
2098 : */
2099 :
2100 0 : if (!drv->use_crypt) {
2101 0 : iwr.u.encoding.flags |= IW_ENCODE_DISABLED;
2102 : } else {
2103 0 : if (params->auth_alg & WPA_AUTH_ALG_OPEN)
2104 0 : iwr.u.encoding.flags |= IW_ENCODE_OPEN;
2105 0 : if (params->auth_alg & WPA_AUTH_ALG_SHARED)
2106 0 : iwr.u.encoding.flags |= IW_ENCODE_RESTRICTED;
2107 : }
2108 :
2109 0 : if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) {
2110 0 : wpa_printf(MSG_ERROR, "ioctl[SIOCSIWENCODE]: %s",
2111 0 : strerror(errno));
2112 0 : ret = -1;
2113 : }
2114 :
2115 0 : return ret;
2116 : }
2117 :
2118 :
2119 14 : int wpa_driver_wext_associate(void *priv,
2120 : struct wpa_driver_associate_params *params)
2121 : {
2122 14 : struct wpa_driver_wext_data *drv = priv;
2123 14 : int ret = 0;
2124 : int allow_unencrypted_eapol;
2125 : int value;
2126 :
2127 14 : wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
2128 :
2129 14 : if (drv->cfg80211) {
2130 : /*
2131 : * Stop cfg80211 from trying to associate before we are done
2132 : * with all parameters.
2133 : */
2134 14 : if (wpa_driver_wext_set_ssid(drv, (u8 *) "", 0) < 0) {
2135 0 : wpa_printf(MSG_DEBUG,
2136 : "WEXT: Failed to clear SSID to stop pending cfg80211 association attempts (if any)");
2137 : /* continue anyway */
2138 : }
2139 : }
2140 :
2141 14 : if (wpa_driver_wext_set_drop_unencrypted(drv, params->drop_unencrypted)
2142 : < 0)
2143 0 : ret = -1;
2144 14 : if (wpa_driver_wext_set_auth_alg(drv, params->auth_alg) < 0)
2145 0 : ret = -1;
2146 14 : if (wpa_driver_wext_set_mode(drv, params->mode) < 0)
2147 0 : ret = -1;
2148 :
2149 : /*
2150 : * If the driver did not support SIOCSIWAUTH, fallback to
2151 : * SIOCSIWENCODE here.
2152 : */
2153 14 : if (drv->auth_alg_fallback &&
2154 0 : wpa_driver_wext_auth_alg_fallback(drv, params) < 0)
2155 0 : ret = -1;
2156 :
2157 14 : if (!params->bssid &&
2158 0 : wpa_driver_wext_set_bssid(drv, NULL) < 0)
2159 0 : ret = -1;
2160 :
2161 : /* TODO: should consider getting wpa version and cipher/key_mgmt suites
2162 : * from configuration, not from here, where only the selected suite is
2163 : * available */
2164 14 : if (wpa_driver_wext_set_gen_ie(drv, params->wpa_ie, params->wpa_ie_len)
2165 : < 0)
2166 0 : ret = -1;
2167 14 : if (params->wpa_proto & WPA_PROTO_RSN)
2168 6 : value = IW_AUTH_WPA_VERSION_WPA2;
2169 8 : else if (params->wpa_proto & WPA_PROTO_WPA)
2170 1 : value = IW_AUTH_WPA_VERSION_WPA;
2171 : else
2172 7 : value = IW_AUTH_WPA_VERSION_DISABLED;
2173 14 : if (wpa_driver_wext_set_auth_param(drv,
2174 : IW_AUTH_WPA_VERSION, value) < 0)
2175 0 : ret = -1;
2176 14 : value = wpa_driver_wext_cipher2wext(params->pairwise_suite);
2177 14 : if (wpa_driver_wext_set_auth_param(drv,
2178 : IW_AUTH_CIPHER_PAIRWISE, value) < 0)
2179 0 : ret = -1;
2180 14 : value = wpa_driver_wext_cipher2wext(params->group_suite);
2181 14 : if (wpa_driver_wext_set_auth_param(drv,
2182 : IW_AUTH_CIPHER_GROUP, value) < 0)
2183 0 : ret = -1;
2184 14 : value = wpa_driver_wext_keymgmt2wext(params->key_mgmt_suite);
2185 14 : if (wpa_driver_wext_set_auth_param(drv,
2186 : IW_AUTH_KEY_MGMT, value) < 0)
2187 0 : ret = -1;
2188 35 : value = params->key_mgmt_suite != WPA_KEY_MGMT_NONE ||
2189 11 : params->pairwise_suite != WPA_CIPHER_NONE ||
2190 22 : params->group_suite != WPA_CIPHER_NONE ||
2191 4 : (params->wpa_proto & (WPA_PROTO_RSN | WPA_PROTO_WPA));
2192 14 : if (wpa_driver_wext_set_auth_param(drv,
2193 : IW_AUTH_PRIVACY_INVOKED, value) < 0)
2194 0 : ret = -1;
2195 :
2196 : /* Allow unencrypted EAPOL messages even if pairwise keys are set when
2197 : * not using WPA. IEEE 802.1X specifies that these frames are not
2198 : * encrypted, but WPA encrypts them when pairwise keys are in use. */
2199 24 : if (params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
2200 10 : params->key_mgmt_suite == WPA_KEY_MGMT_PSK)
2201 6 : allow_unencrypted_eapol = 0;
2202 : else
2203 8 : allow_unencrypted_eapol = 1;
2204 :
2205 14 : if (wpa_driver_wext_set_psk(drv, params->psk) < 0)
2206 0 : ret = -1;
2207 14 : if (wpa_driver_wext_set_auth_param(drv,
2208 : IW_AUTH_RX_UNENCRYPTED_EAPOL,
2209 : allow_unencrypted_eapol) < 0)
2210 0 : ret = -1;
2211 : #ifdef CONFIG_IEEE80211W
2212 14 : switch (params->mgmt_frame_protection) {
2213 : case NO_MGMT_FRAME_PROTECTION:
2214 13 : value = IW_AUTH_MFP_DISABLED;
2215 13 : break;
2216 : case MGMT_FRAME_PROTECTION_OPTIONAL:
2217 0 : value = IW_AUTH_MFP_OPTIONAL;
2218 0 : break;
2219 : case MGMT_FRAME_PROTECTION_REQUIRED:
2220 1 : value = IW_AUTH_MFP_REQUIRED;
2221 1 : break;
2222 : };
2223 14 : if (wpa_driver_wext_set_auth_param(drv, IW_AUTH_MFP, value) < 0)
2224 0 : ret = -1;
2225 : #endif /* CONFIG_IEEE80211W */
2226 28 : if (params->freq.freq &&
2227 14 : wpa_driver_wext_set_freq(drv, params->freq.freq) < 0)
2228 14 : ret = -1;
2229 14 : if (!drv->cfg80211 &&
2230 0 : wpa_driver_wext_set_ssid(drv, params->ssid, params->ssid_len) < 0)
2231 0 : ret = -1;
2232 28 : if (params->bssid &&
2233 14 : wpa_driver_wext_set_bssid(drv, params->bssid) < 0)
2234 0 : ret = -1;
2235 28 : if (drv->cfg80211 &&
2236 14 : wpa_driver_wext_set_ssid(drv, params->ssid, params->ssid_len) < 0)
2237 0 : ret = -1;
2238 :
2239 14 : return ret;
2240 : }
2241 :
2242 :
2243 14 : static int wpa_driver_wext_set_auth_alg(void *priv, int auth_alg)
2244 : {
2245 14 : struct wpa_driver_wext_data *drv = priv;
2246 14 : int algs = 0, res;
2247 :
2248 14 : if (auth_alg & WPA_AUTH_ALG_OPEN)
2249 13 : algs |= IW_AUTH_ALG_OPEN_SYSTEM;
2250 14 : if (auth_alg & WPA_AUTH_ALG_SHARED)
2251 2 : algs |= IW_AUTH_ALG_SHARED_KEY;
2252 14 : if (auth_alg & WPA_AUTH_ALG_LEAP)
2253 0 : algs |= IW_AUTH_ALG_LEAP;
2254 14 : if (algs == 0) {
2255 : /* at least one algorithm should be set */
2256 0 : algs = IW_AUTH_ALG_OPEN_SYSTEM;
2257 : }
2258 :
2259 14 : res = wpa_driver_wext_set_auth_param(drv, IW_AUTH_80211_AUTH_ALG,
2260 : algs);
2261 14 : drv->auth_alg_fallback = res == -2;
2262 14 : return res;
2263 : }
2264 :
2265 :
2266 : /**
2267 : * wpa_driver_wext_set_mode - Set wireless mode (infra/adhoc), SIOCSIWMODE
2268 : * @priv: Pointer to private wext data from wpa_driver_wext_init()
2269 : * @mode: 0 = infra/BSS (associate with an AP), 1 = adhoc/IBSS
2270 : * Returns: 0 on success, -1 on failure
2271 : */
2272 23 : int wpa_driver_wext_set_mode(void *priv, int mode)
2273 : {
2274 23 : struct wpa_driver_wext_data *drv = priv;
2275 : struct iwreq iwr;
2276 23 : int ret = -1;
2277 23 : unsigned int new_mode = mode ? IW_MODE_ADHOC : IW_MODE_INFRA;
2278 :
2279 23 : os_memset(&iwr, 0, sizeof(iwr));
2280 23 : os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
2281 23 : iwr.u.mode = new_mode;
2282 23 : if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) == 0) {
2283 23 : ret = 0;
2284 23 : goto done;
2285 : }
2286 :
2287 0 : if (errno != EBUSY) {
2288 0 : wpa_printf(MSG_ERROR, "ioctl[SIOCSIWMODE]: %s",
2289 0 : strerror(errno));
2290 0 : goto done;
2291 : }
2292 :
2293 : /* mac80211 doesn't allow mode changes while the device is up, so if
2294 : * the device isn't in the mode we're about to change to, take device
2295 : * down, try to set the mode again, and bring it back up.
2296 : */
2297 0 : if (ioctl(drv->ioctl_sock, SIOCGIWMODE, &iwr) < 0) {
2298 0 : wpa_printf(MSG_ERROR, "ioctl[SIOCGIWMODE]: %s",
2299 0 : strerror(errno));
2300 0 : goto done;
2301 : }
2302 :
2303 0 : if (iwr.u.mode == new_mode) {
2304 0 : ret = 0;
2305 0 : goto done;
2306 : }
2307 :
2308 0 : if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 0) == 0) {
2309 : /* Try to set the mode again while the interface is down */
2310 0 : iwr.u.mode = new_mode;
2311 0 : if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0)
2312 0 : wpa_printf(MSG_ERROR, "ioctl[SIOCSIWMODE]: %s",
2313 0 : strerror(errno));
2314 : else
2315 0 : ret = 0;
2316 :
2317 0 : (void) linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1);
2318 : }
2319 :
2320 : done:
2321 23 : return ret;
2322 : }
2323 :
2324 :
2325 24 : static int wpa_driver_wext_pmksa(struct wpa_driver_wext_data *drv,
2326 : u32 cmd, const u8 *bssid, const u8 *pmkid)
2327 : {
2328 : struct iwreq iwr;
2329 : struct iw_pmksa pmksa;
2330 24 : int ret = 0;
2331 :
2332 24 : os_memset(&iwr, 0, sizeof(iwr));
2333 24 : os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
2334 24 : os_memset(&pmksa, 0, sizeof(pmksa));
2335 24 : pmksa.cmd = cmd;
2336 24 : pmksa.bssid.sa_family = ARPHRD_ETHER;
2337 24 : if (bssid)
2338 6 : os_memcpy(pmksa.bssid.sa_data, bssid, ETH_ALEN);
2339 24 : if (pmkid)
2340 6 : os_memcpy(pmksa.pmkid, pmkid, IW_PMKID_LEN);
2341 24 : iwr.u.data.pointer = (caddr_t) &pmksa;
2342 24 : iwr.u.data.length = sizeof(pmksa);
2343 :
2344 24 : if (ioctl(drv->ioctl_sock, SIOCSIWPMKSA, &iwr) < 0) {
2345 24 : if (errno != EOPNOTSUPP)
2346 0 : wpa_printf(MSG_ERROR, "ioctl[SIOCSIWPMKSA]: %s",
2347 0 : strerror(errno));
2348 24 : ret = -1;
2349 : }
2350 :
2351 24 : return ret;
2352 : }
2353 :
2354 :
2355 3 : static int wpa_driver_wext_add_pmkid(void *priv, const u8 *bssid,
2356 : const u8 *pmkid)
2357 : {
2358 3 : struct wpa_driver_wext_data *drv = priv;
2359 3 : return wpa_driver_wext_pmksa(drv, IW_PMKSA_ADD, bssid, pmkid);
2360 : }
2361 :
2362 :
2363 3 : static int wpa_driver_wext_remove_pmkid(void *priv, const u8 *bssid,
2364 : const u8 *pmkid)
2365 : {
2366 3 : struct wpa_driver_wext_data *drv = priv;
2367 3 : return wpa_driver_wext_pmksa(drv, IW_PMKSA_REMOVE, bssid, pmkid);
2368 : }
2369 :
2370 :
2371 18 : static int wpa_driver_wext_flush_pmkid(void *priv)
2372 : {
2373 18 : struct wpa_driver_wext_data *drv = priv;
2374 18 : return wpa_driver_wext_pmksa(drv, IW_PMKSA_FLUSH, NULL, NULL);
2375 : }
2376 :
2377 :
2378 9 : int wpa_driver_wext_get_capa(void *priv, struct wpa_driver_capa *capa)
2379 : {
2380 9 : struct wpa_driver_wext_data *drv = priv;
2381 9 : if (!drv->has_capability)
2382 0 : return -1;
2383 9 : os_memcpy(capa, &drv->capa, sizeof(*capa));
2384 9 : return 0;
2385 : }
2386 :
2387 :
2388 9 : int wpa_driver_wext_alternative_ifindex(struct wpa_driver_wext_data *drv,
2389 : const char *ifname)
2390 : {
2391 9 : if (ifname == NULL) {
2392 0 : drv->ifindex2 = -1;
2393 0 : return 0;
2394 : }
2395 :
2396 9 : drv->ifindex2 = if_nametoindex(ifname);
2397 9 : if (drv->ifindex2 <= 0)
2398 9 : return -1;
2399 :
2400 0 : wpa_printf(MSG_DEBUG, "Added alternative ifindex %d (%s) for "
2401 : "wireless events", drv->ifindex2, ifname);
2402 :
2403 0 : return 0;
2404 : }
2405 :
2406 :
2407 83 : int wpa_driver_wext_set_operstate(void *priv, int state)
2408 : {
2409 83 : struct wpa_driver_wext_data *drv = priv;
2410 :
2411 83 : wpa_printf(MSG_DEBUG, "%s: operstate %d->%d (%s)",
2412 : __func__, drv->operstate, state, state ? "UP" : "DORMANT");
2413 83 : drv->operstate = state;
2414 83 : return netlink_send_oper_ifla(drv->netlink, drv->ifindex, -1,
2415 : state ? IF_OPER_UP : IF_OPER_DORMANT);
2416 : }
2417 :
2418 :
2419 0 : int wpa_driver_wext_get_version(struct wpa_driver_wext_data *drv)
2420 : {
2421 0 : return drv->we_version_compiled;
2422 : }
2423 :
2424 :
2425 9 : static const char * wext_get_radio_name(void *priv)
2426 : {
2427 9 : struct wpa_driver_wext_data *drv = priv;
2428 9 : return drv->phyname;
2429 : }
2430 :
2431 :
2432 1 : static int wpa_driver_wext_signal_poll(void *priv, struct wpa_signal_info *si)
2433 : {
2434 1 : struct wpa_driver_wext_data *drv = priv;
2435 : struct iw_statistics stats;
2436 : struct iwreq iwr;
2437 :
2438 1 : os_memset(si, 0, sizeof(*si));
2439 1 : si->current_signal = -9999;
2440 1 : si->current_noise = 9999;
2441 1 : si->chanwidth = CHAN_WIDTH_UNKNOWN;
2442 :
2443 1 : os_memset(&iwr, 0, sizeof(iwr));
2444 1 : os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
2445 1 : iwr.u.data.pointer = (caddr_t) &stats;
2446 1 : iwr.u.data.length = sizeof(stats);
2447 1 : iwr.u.data.flags = 1;
2448 :
2449 1 : if (ioctl(drv->ioctl_sock, SIOCGIWSTATS, &iwr) < 0) {
2450 0 : wpa_printf(MSG_ERROR, "WEXT: SIOCGIWSTATS: %s",
2451 0 : strerror(errno));
2452 0 : return -1;
2453 : }
2454 :
2455 2 : si->current_signal = stats.qual.level -
2456 1 : ((stats.qual.updated & IW_QUAL_DBM) ? 0x100 : 0);
2457 2 : si->current_noise = stats.qual.noise -
2458 1 : ((stats.qual.updated & IW_QUAL_DBM) ? 0x100 : 0);
2459 1 : return 0;
2460 : }
2461 :
2462 :
2463 7 : static int wpa_driver_wext_status(void *priv, char *buf, size_t buflen)
2464 : {
2465 7 : struct wpa_driver_wext_data *drv = priv;
2466 : int res;
2467 : char *pos, *end;
2468 : unsigned char addr[ETH_ALEN];
2469 :
2470 7 : pos = buf;
2471 7 : end = buf + buflen;
2472 :
2473 7 : if (linux_get_ifhwaddr(drv->ioctl_sock, drv->ifname, addr))
2474 0 : return -1;
2475 :
2476 49 : res = os_snprintf(pos, end - pos,
2477 : "ifindex=%d\n"
2478 : "ifname=%s\n"
2479 : "addr=" MACSTR "\n",
2480 : drv->ifindex,
2481 7 : drv->ifname,
2482 42 : MAC2STR(addr));
2483 7 : if (os_snprintf_error(end - pos, res))
2484 0 : return pos - buf;
2485 7 : pos += res;
2486 :
2487 7 : return pos - buf;
2488 : }
2489 :
2490 : const struct wpa_driver_ops wpa_driver_wext_ops = {
2491 : .name = "wext",
2492 : .desc = "Linux wireless extensions (generic)",
2493 : .get_bssid = wpa_driver_wext_get_bssid,
2494 : .get_ssid = wpa_driver_wext_get_ssid,
2495 : .set_key = wpa_driver_wext_set_key,
2496 : .set_countermeasures = wpa_driver_wext_set_countermeasures,
2497 : .scan2 = wpa_driver_wext_scan,
2498 : .get_scan_results2 = wpa_driver_wext_get_scan_results,
2499 : .deauthenticate = wpa_driver_wext_deauthenticate,
2500 : .associate = wpa_driver_wext_associate,
2501 : .init = wpa_driver_wext_init,
2502 : .deinit = wpa_driver_wext_deinit,
2503 : .add_pmkid = wpa_driver_wext_add_pmkid,
2504 : .remove_pmkid = wpa_driver_wext_remove_pmkid,
2505 : .flush_pmkid = wpa_driver_wext_flush_pmkid,
2506 : .get_capa = wpa_driver_wext_get_capa,
2507 : .set_operstate = wpa_driver_wext_set_operstate,
2508 : .get_radio_name = wext_get_radio_name,
2509 : .signal_poll = wpa_driver_wext_signal_poll,
2510 : .status = wpa_driver_wext_status,
2511 : };
|