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