xref: /netbsd-src/external/bsd/wpa/dist/src/drivers/driver_wext.c (revision 6a493d6bc668897c91594964a732d38505b70cbb)
1 /*
2  * Driver interaction with generic Linux Wireless Extensions
3  * Copyright (c) 2003-2010, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  *
14  * This file implements a driver interface for the Linux Wireless Extensions.
15  * When used with WE-18 or newer, this interface can be used as-is with number
16  * of drivers. In addition to this, some of the common functions in this file
17  * can be used by other driver interface implementations that use generic WE
18  * ioctls, but require private ioctls for some of the functionality.
19  */
20 
21 #include "includes.h"
22 #include <sys/ioctl.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <net/if_arp.h>
27 
28 #include "wireless_copy.h"
29 #include "common.h"
30 #include "eloop.h"
31 #include "common/ieee802_11_defs.h"
32 #include "common/wpa_common.h"
33 #include "priv_netlink.h"
34 #include "netlink.h"
35 #include "linux_ioctl.h"
36 #include "rfkill.h"
37 #include "driver.h"
38 #include "driver_wext.h"
39 
40 
41 static int wpa_driver_wext_flush_pmkid(void *priv);
42 static int wpa_driver_wext_get_range(void *priv);
43 static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv);
44 static void wpa_driver_wext_disconnect(struct wpa_driver_wext_data *drv);
45 static int wpa_driver_wext_set_auth_alg(void *priv, int auth_alg);
46 
47 
48 int wpa_driver_wext_set_auth_param(struct wpa_driver_wext_data *drv,
49 				   int idx, u32 value)
50 {
51 	struct iwreq iwr;
52 	int ret = 0;
53 
54 	os_memset(&iwr, 0, sizeof(iwr));
55 	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
56 	iwr.u.param.flags = idx & IW_AUTH_INDEX;
57 	iwr.u.param.value = value;
58 
59 	if (ioctl(drv->ioctl_sock, SIOCSIWAUTH, &iwr) < 0) {
60 		if (errno != EOPNOTSUPP) {
61 			wpa_printf(MSG_DEBUG, "WEXT: SIOCSIWAUTH(param %d "
62 				   "value 0x%x) failed: %s)",
63 				   idx, value, strerror(errno));
64 		}
65 		ret = errno == EOPNOTSUPP ? -2 : -1;
66 	}
67 
68 	return ret;
69 }
70 
71 
72 /**
73  * wpa_driver_wext_get_bssid - Get BSSID, SIOCGIWAP
74  * @priv: Pointer to private wext data from wpa_driver_wext_init()
75  * @bssid: Buffer for BSSID
76  * Returns: 0 on success, -1 on failure
77  */
78 int wpa_driver_wext_get_bssid(void *priv, u8 *bssid)
79 {
80 	struct wpa_driver_wext_data *drv = priv;
81 	struct iwreq iwr;
82 	int ret = 0;
83 
84 	os_memset(&iwr, 0, sizeof(iwr));
85 	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
86 
87 	if (ioctl(drv->ioctl_sock, SIOCGIWAP, &iwr) < 0) {
88 		perror("ioctl[SIOCGIWAP]");
89 		ret = -1;
90 	}
91 	os_memcpy(bssid, iwr.u.ap_addr.sa_data, ETH_ALEN);
92 
93 	return ret;
94 }
95 
96 
97 /**
98  * wpa_driver_wext_set_bssid - Set BSSID, SIOCSIWAP
99  * @priv: Pointer to private wext data from wpa_driver_wext_init()
100  * @bssid: BSSID
101  * Returns: 0 on success, -1 on failure
102  */
103 int wpa_driver_wext_set_bssid(void *priv, const u8 *bssid)
104 {
105 	struct wpa_driver_wext_data *drv = priv;
106 	struct iwreq iwr;
107 	int ret = 0;
108 
109 	os_memset(&iwr, 0, sizeof(iwr));
110 	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
111 	iwr.u.ap_addr.sa_family = ARPHRD_ETHER;
112 	if (bssid)
113 		os_memcpy(iwr.u.ap_addr.sa_data, bssid, ETH_ALEN);
114 	else
115 		os_memset(iwr.u.ap_addr.sa_data, 0, ETH_ALEN);
116 
117 	if (ioctl(drv->ioctl_sock, SIOCSIWAP, &iwr) < 0) {
118 		perror("ioctl[SIOCSIWAP]");
119 		ret = -1;
120 	}
121 
122 	return ret;
123 }
124 
125 
126 /**
127  * wpa_driver_wext_get_ssid - Get SSID, SIOCGIWESSID
128  * @priv: Pointer to private wext data from wpa_driver_wext_init()
129  * @ssid: Buffer for the SSID; must be at least 32 bytes long
130  * Returns: SSID length on success, -1 on failure
131  */
132 int wpa_driver_wext_get_ssid(void *priv, u8 *ssid)
133 {
134 	struct wpa_driver_wext_data *drv = priv;
135 	struct iwreq iwr;
136 	int ret = 0;
137 
138 	os_memset(&iwr, 0, sizeof(iwr));
139 	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
140 	iwr.u.essid.pointer = (caddr_t) ssid;
141 	iwr.u.essid.length = 32;
142 
143 	if (ioctl(drv->ioctl_sock, SIOCGIWESSID, &iwr) < 0) {
144 		perror("ioctl[SIOCGIWESSID]");
145 		ret = -1;
146 	} else {
147 		ret = iwr.u.essid.length;
148 		if (ret > 32)
149 			ret = 32;
150 		/* Some drivers include nul termination in the SSID, so let's
151 		 * remove it here before further processing. WE-21 changes this
152 		 * to explicitly require the length _not_ to include nul
153 		 * termination. */
154 		if (ret > 0 && ssid[ret - 1] == '\0' &&
155 		    drv->we_version_compiled < 21)
156 			ret--;
157 	}
158 
159 	return ret;
160 }
161 
162 
163 /**
164  * wpa_driver_wext_set_ssid - Set SSID, SIOCSIWESSID
165  * @priv: Pointer to private wext data from wpa_driver_wext_init()
166  * @ssid: SSID
167  * @ssid_len: Length of SSID (0..32)
168  * Returns: 0 on success, -1 on failure
169  */
170 int wpa_driver_wext_set_ssid(void *priv, const u8 *ssid, size_t ssid_len)
171 {
172 	struct wpa_driver_wext_data *drv = priv;
173 	struct iwreq iwr;
174 	int ret = 0;
175 	char buf[33];
176 
177 	if (ssid_len > 32)
178 		return -1;
179 
180 	os_memset(&iwr, 0, sizeof(iwr));
181 	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
182 	/* flags: 1 = ESSID is active, 0 = not (promiscuous) */
183 	iwr.u.essid.flags = (ssid_len != 0);
184 	os_memset(buf, 0, sizeof(buf));
185 	os_memcpy(buf, ssid, ssid_len);
186 	iwr.u.essid.pointer = (caddr_t) buf;
187 	if (drv->we_version_compiled < 21) {
188 		/* For historic reasons, set SSID length to include one extra
189 		 * character, C string nul termination, even though SSID is
190 		 * really an octet string that should not be presented as a C
191 		 * string. Some Linux drivers decrement the length by one and
192 		 * can thus end up missing the last octet of the SSID if the
193 		 * length is not incremented here. WE-21 changes this to
194 		 * explicitly require the length _not_ to include nul
195 		 * termination. */
196 		if (ssid_len)
197 			ssid_len++;
198 	}
199 	iwr.u.essid.length = ssid_len;
200 
201 	if (ioctl(drv->ioctl_sock, SIOCSIWESSID, &iwr) < 0) {
202 		perror("ioctl[SIOCSIWESSID]");
203 		ret = -1;
204 	}
205 
206 	return ret;
207 }
208 
209 
210 /**
211  * wpa_driver_wext_set_freq - Set frequency/channel, SIOCSIWFREQ
212  * @priv: Pointer to private wext data from wpa_driver_wext_init()
213  * @freq: Frequency in MHz
214  * Returns: 0 on success, -1 on failure
215  */
216 int wpa_driver_wext_set_freq(void *priv, int freq)
217 {
218 	struct wpa_driver_wext_data *drv = priv;
219 	struct iwreq iwr;
220 	int ret = 0;
221 
222 	os_memset(&iwr, 0, sizeof(iwr));
223 	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
224 	iwr.u.freq.m = freq * 100000;
225 	iwr.u.freq.e = 1;
226 
227 	if (ioctl(drv->ioctl_sock, SIOCSIWFREQ, &iwr) < 0) {
228 		perror("ioctl[SIOCSIWFREQ]");
229 		ret = -1;
230 	}
231 
232 	return ret;
233 }
234 
235 
236 static void
237 wpa_driver_wext_event_wireless_custom(void *ctx, char *custom)
238 {
239 	union wpa_event_data data;
240 
241 	wpa_printf(MSG_MSGDUMP, "WEXT: Custom wireless event: '%s'",
242 		   custom);
243 
244 	os_memset(&data, 0, sizeof(data));
245 	/* Host AP driver */
246 	if (os_strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) {
247 		data.michael_mic_failure.unicast =
248 			os_strstr(custom, " unicast ") != NULL;
249 		/* TODO: parse parameters(?) */
250 		wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
251 	} else if (os_strncmp(custom, "ASSOCINFO(ReqIEs=", 17) == 0) {
252 		char *spos;
253 		int bytes;
254 		u8 *req_ies = NULL, *resp_ies = NULL;
255 
256 		spos = custom + 17;
257 
258 		bytes = strspn(spos, "0123456789abcdefABCDEF");
259 		if (!bytes || (bytes & 1))
260 			return;
261 		bytes /= 2;
262 
263 		req_ies = os_malloc(bytes);
264 		if (req_ies == NULL ||
265 		    hexstr2bin(spos, req_ies, bytes) < 0)
266 			goto done;
267 		data.assoc_info.req_ies = req_ies;
268 		data.assoc_info.req_ies_len = bytes;
269 
270 		spos += bytes * 2;
271 
272 		data.assoc_info.resp_ies = NULL;
273 		data.assoc_info.resp_ies_len = 0;
274 
275 		if (os_strncmp(spos, " RespIEs=", 9) == 0) {
276 			spos += 9;
277 
278 			bytes = strspn(spos, "0123456789abcdefABCDEF");
279 			if (!bytes || (bytes & 1))
280 				goto done;
281 			bytes /= 2;
282 
283 			resp_ies = os_malloc(bytes);
284 			if (resp_ies == NULL ||
285 			    hexstr2bin(spos, resp_ies, bytes) < 0)
286 				goto done;
287 			data.assoc_info.resp_ies = resp_ies;
288 			data.assoc_info.resp_ies_len = bytes;
289 		}
290 
291 		wpa_supplicant_event(ctx, EVENT_ASSOCINFO, &data);
292 
293 	done:
294 		os_free(resp_ies);
295 		os_free(req_ies);
296 #ifdef CONFIG_PEERKEY
297 	} else if (os_strncmp(custom, "STKSTART.request=", 17) == 0) {
298 		if (hwaddr_aton(custom + 17, data.stkstart.peer)) {
299 			wpa_printf(MSG_DEBUG, "WEXT: unrecognized "
300 				   "STKSTART.request '%s'", custom + 17);
301 			return;
302 		}
303 		wpa_supplicant_event(ctx, EVENT_STKSTART, &data);
304 #endif /* CONFIG_PEERKEY */
305 	}
306 }
307 
308 
309 static int wpa_driver_wext_event_wireless_michaelmicfailure(
310 	void *ctx, const char *ev, size_t len)
311 {
312 	const struct iw_michaelmicfailure *mic;
313 	union wpa_event_data data;
314 
315 	if (len < sizeof(*mic))
316 		return -1;
317 
318 	mic = (const struct iw_michaelmicfailure *) ev;
319 
320 	wpa_printf(MSG_DEBUG, "Michael MIC failure wireless event: "
321 		   "flags=0x%x src_addr=" MACSTR, mic->flags,
322 		   MAC2STR(mic->src_addr.sa_data));
323 
324 	os_memset(&data, 0, sizeof(data));
325 	data.michael_mic_failure.unicast = !(mic->flags & IW_MICFAILURE_GROUP);
326 	wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
327 
328 	return 0;
329 }
330 
331 
332 static int wpa_driver_wext_event_wireless_pmkidcand(
333 	struct wpa_driver_wext_data *drv, const char *ev, size_t len)
334 {
335 	const struct iw_pmkid_cand *cand;
336 	union wpa_event_data data;
337 	const u8 *addr;
338 
339 	if (len < sizeof(*cand))
340 		return -1;
341 
342 	cand = (const struct iw_pmkid_cand *) ev;
343 	addr = (const u8 *) cand->bssid.sa_data;
344 
345 	wpa_printf(MSG_DEBUG, "PMKID candidate wireless event: "
346 		   "flags=0x%x index=%d bssid=" MACSTR, cand->flags,
347 		   cand->index, MAC2STR(addr));
348 
349 	os_memset(&data, 0, sizeof(data));
350 	os_memcpy(data.pmkid_candidate.bssid, addr, ETH_ALEN);
351 	data.pmkid_candidate.index = cand->index;
352 	data.pmkid_candidate.preauth = cand->flags & IW_PMKID_CAND_PREAUTH;
353 	wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE, &data);
354 
355 	return 0;
356 }
357 
358 
359 static int wpa_driver_wext_event_wireless_assocreqie(
360 	struct wpa_driver_wext_data *drv, const char *ev, int len)
361 {
362 	if (len < 0)
363 		return -1;
364 
365 	wpa_hexdump(MSG_DEBUG, "AssocReq IE wireless event", (const u8 *) ev,
366 		    len);
367 	os_free(drv->assoc_req_ies);
368 	drv->assoc_req_ies = os_malloc(len);
369 	if (drv->assoc_req_ies == NULL) {
370 		drv->assoc_req_ies_len = 0;
371 		return -1;
372 	}
373 	os_memcpy(drv->assoc_req_ies, ev, len);
374 	drv->assoc_req_ies_len = len;
375 
376 	return 0;
377 }
378 
379 
380 static int wpa_driver_wext_event_wireless_assocrespie(
381 	struct wpa_driver_wext_data *drv, const char *ev, int len)
382 {
383 	if (len < 0)
384 		return -1;
385 
386 	wpa_hexdump(MSG_DEBUG, "AssocResp IE wireless event", (const u8 *) ev,
387 		    len);
388 	os_free(drv->assoc_resp_ies);
389 	drv->assoc_resp_ies = os_malloc(len);
390 	if (drv->assoc_resp_ies == NULL) {
391 		drv->assoc_resp_ies_len = 0;
392 		return -1;
393 	}
394 	os_memcpy(drv->assoc_resp_ies, ev, len);
395 	drv->assoc_resp_ies_len = len;
396 
397 	return 0;
398 }
399 
400 
401 static void wpa_driver_wext_event_assoc_ies(struct wpa_driver_wext_data *drv)
402 {
403 	union wpa_event_data data;
404 
405 	if (drv->assoc_req_ies == NULL && drv->assoc_resp_ies == NULL)
406 		return;
407 
408 	os_memset(&data, 0, sizeof(data));
409 	if (drv->assoc_req_ies) {
410 		data.assoc_info.req_ies = drv->assoc_req_ies;
411 		data.assoc_info.req_ies_len = drv->assoc_req_ies_len;
412 	}
413 	if (drv->assoc_resp_ies) {
414 		data.assoc_info.resp_ies = drv->assoc_resp_ies;
415 		data.assoc_info.resp_ies_len = drv->assoc_resp_ies_len;
416 	}
417 
418 	wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &data);
419 
420 	os_free(drv->assoc_req_ies);
421 	drv->assoc_req_ies = NULL;
422 	os_free(drv->assoc_resp_ies);
423 	drv->assoc_resp_ies = NULL;
424 }
425 
426 
427 static void wpa_driver_wext_event_wireless(struct wpa_driver_wext_data *drv,
428 					   char *data, int len)
429 {
430 	struct iw_event iwe_buf, *iwe = &iwe_buf;
431 	char *pos, *end, *custom, *buf;
432 
433 	pos = data;
434 	end = data + len;
435 
436 	while (pos + IW_EV_LCP_LEN <= end) {
437 		/* Event data may be unaligned, so make a local, aligned copy
438 		 * before processing. */
439 		os_memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
440 		wpa_printf(MSG_DEBUG, "Wireless event: cmd=0x%x len=%d",
441 			   iwe->cmd, iwe->len);
442 		if (iwe->len <= IW_EV_LCP_LEN)
443 			return;
444 
445 		custom = pos + IW_EV_POINT_LEN;
446 		if (drv->we_version_compiled > 18 &&
447 		    (iwe->cmd == IWEVMICHAELMICFAILURE ||
448 		     iwe->cmd == IWEVCUSTOM ||
449 		     iwe->cmd == IWEVASSOCREQIE ||
450 		     iwe->cmd == IWEVASSOCRESPIE ||
451 		     iwe->cmd == IWEVPMKIDCAND)) {
452 			/* WE-19 removed the pointer from struct iw_point */
453 			char *dpos = (char *) &iwe_buf.u.data.length;
454 			int dlen = dpos - (char *) &iwe_buf;
455 			os_memcpy(dpos, pos + IW_EV_LCP_LEN,
456 				  sizeof(struct iw_event) - dlen);
457 		} else {
458 			os_memcpy(&iwe_buf, pos, sizeof(struct iw_event));
459 			custom += IW_EV_POINT_OFF;
460 		}
461 
462 		switch (iwe->cmd) {
463 		case SIOCGIWAP:
464 			wpa_printf(MSG_DEBUG, "Wireless event: new AP: "
465 				   MACSTR,
466 				   MAC2STR((u8 *) iwe->u.ap_addr.sa_data));
467 			if (is_zero_ether_addr(
468 				    (const u8 *) iwe->u.ap_addr.sa_data) ||
469 			    os_memcmp(iwe->u.ap_addr.sa_data,
470 				      "\x44\x44\x44\x44\x44\x44", ETH_ALEN) ==
471 			    0) {
472 				os_free(drv->assoc_req_ies);
473 				drv->assoc_req_ies = NULL;
474 				os_free(drv->assoc_resp_ies);
475 				drv->assoc_resp_ies = NULL;
476 				wpa_supplicant_event(drv->ctx, EVENT_DISASSOC,
477 						     NULL);
478 
479 			} else {
480 				wpa_driver_wext_event_assoc_ies(drv);
481 				wpa_supplicant_event(drv->ctx, EVENT_ASSOC,
482 						     NULL);
483 			}
484 			break;
485 		case IWEVMICHAELMICFAILURE:
486 			if (custom + iwe->u.data.length > end) {
487 				wpa_printf(MSG_DEBUG, "WEXT: Invalid "
488 					   "IWEVMICHAELMICFAILURE length");
489 				return;
490 			}
491 			wpa_driver_wext_event_wireless_michaelmicfailure(
492 				drv->ctx, custom, iwe->u.data.length);
493 			break;
494 		case IWEVCUSTOM:
495 			if (custom + iwe->u.data.length > end) {
496 				wpa_printf(MSG_DEBUG, "WEXT: Invalid "
497 					   "IWEVCUSTOM length");
498 				return;
499 			}
500 			buf = os_malloc(iwe->u.data.length + 1);
501 			if (buf == NULL)
502 				return;
503 			os_memcpy(buf, custom, iwe->u.data.length);
504 			buf[iwe->u.data.length] = '\0';
505 			wpa_driver_wext_event_wireless_custom(drv->ctx, buf);
506 			os_free(buf);
507 			break;
508 		case SIOCGIWSCAN:
509 			drv->scan_complete_events = 1;
510 			eloop_cancel_timeout(wpa_driver_wext_scan_timeout,
511 					     drv, drv->ctx);
512 			wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS,
513 					     NULL);
514 			break;
515 		case IWEVASSOCREQIE:
516 			if (custom + iwe->u.data.length > end) {
517 				wpa_printf(MSG_DEBUG, "WEXT: Invalid "
518 					   "IWEVASSOCREQIE length");
519 				return;
520 			}
521 			wpa_driver_wext_event_wireless_assocreqie(
522 				drv, custom, iwe->u.data.length);
523 			break;
524 		case IWEVASSOCRESPIE:
525 			if (custom + iwe->u.data.length > end) {
526 				wpa_printf(MSG_DEBUG, "WEXT: Invalid "
527 					   "IWEVASSOCRESPIE length");
528 				return;
529 			}
530 			wpa_driver_wext_event_wireless_assocrespie(
531 				drv, custom, iwe->u.data.length);
532 			break;
533 		case IWEVPMKIDCAND:
534 			if (custom + iwe->u.data.length > end) {
535 				wpa_printf(MSG_DEBUG, "WEXT: Invalid "
536 					   "IWEVPMKIDCAND length");
537 				return;
538 			}
539 			wpa_driver_wext_event_wireless_pmkidcand(
540 				drv, custom, iwe->u.data.length);
541 			break;
542 		}
543 
544 		pos += iwe->len;
545 	}
546 }
547 
548 
549 static void wpa_driver_wext_event_link(struct wpa_driver_wext_data *drv,
550 				       char *buf, size_t len, int del)
551 {
552 	union wpa_event_data event;
553 
554 	os_memset(&event, 0, sizeof(event));
555 	if (len > sizeof(event.interface_status.ifname))
556 		len = sizeof(event.interface_status.ifname) - 1;
557 	os_memcpy(event.interface_status.ifname, buf, len);
558 	event.interface_status.ievent = del ? EVENT_INTERFACE_REMOVED :
559 		EVENT_INTERFACE_ADDED;
560 
561 	wpa_printf(MSG_DEBUG, "RTM_%sLINK, IFLA_IFNAME: Interface '%s' %s",
562 		   del ? "DEL" : "NEW",
563 		   event.interface_status.ifname,
564 		   del ? "removed" : "added");
565 
566 	if (os_strcmp(drv->ifname, event.interface_status.ifname) == 0) {
567 		if (del) {
568 			if (drv->if_removed) {
569 				wpa_printf(MSG_DEBUG, "WEXT: if_removed "
570 					   "already set - ignore event");
571 				return;
572 			}
573 			drv->if_removed = 1;
574 		} else {
575 			if (if_nametoindex(drv->ifname) == 0) {
576 				wpa_printf(MSG_DEBUG, "WEXT: Interface %s "
577 					   "does not exist - ignore "
578 					   "RTM_NEWLINK",
579 					   drv->ifname);
580 				return;
581 			}
582 			if (!drv->if_removed) {
583 				wpa_printf(MSG_DEBUG, "WEXT: if_removed "
584 					   "already cleared - ignore event");
585 				return;
586 			}
587 			drv->if_removed = 0;
588 		}
589 	}
590 
591 	wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
592 }
593 
594 
595 static int wpa_driver_wext_own_ifname(struct wpa_driver_wext_data *drv,
596 				      u8 *buf, size_t len)
597 {
598 	int attrlen, rta_len;
599 	struct rtattr *attr;
600 
601 	attrlen = len;
602 	attr = (struct rtattr *) buf;
603 
604 	rta_len = RTA_ALIGN(sizeof(struct rtattr));
605 	while (RTA_OK(attr, attrlen)) {
606 		if (attr->rta_type == IFLA_IFNAME) {
607 			if (os_strcmp(((char *) attr) + rta_len, drv->ifname)
608 			    == 0)
609 				return 1;
610 			else
611 				break;
612 		}
613 		attr = RTA_NEXT(attr, attrlen);
614 	}
615 
616 	return 0;
617 }
618 
619 
620 static int wpa_driver_wext_own_ifindex(struct wpa_driver_wext_data *drv,
621 				       int ifindex, u8 *buf, size_t len)
622 {
623 	if (drv->ifindex == ifindex || drv->ifindex2 == ifindex)
624 		return 1;
625 
626 	if (drv->if_removed && wpa_driver_wext_own_ifname(drv, buf, len)) {
627 		drv->ifindex = if_nametoindex(drv->ifname);
628 		wpa_printf(MSG_DEBUG, "WEXT: Update ifindex for a removed "
629 			   "interface");
630 		wpa_driver_wext_finish_drv_init(drv);
631 		return 1;
632 	}
633 
634 	return 0;
635 }
636 
637 
638 static void wpa_driver_wext_event_rtm_newlink(void *ctx, struct ifinfomsg *ifi,
639 					      u8 *buf, size_t len)
640 {
641 	struct wpa_driver_wext_data *drv = ctx;
642 	int attrlen, rta_len;
643 	struct rtattr *attr;
644 	char namebuf[IFNAMSIZ];
645 
646 	if (!wpa_driver_wext_own_ifindex(drv, ifi->ifi_index, buf, len)) {
647 		wpa_printf(MSG_DEBUG, "Ignore event for foreign ifindex %d",
648 			   ifi->ifi_index);
649 		return;
650 	}
651 
652 	wpa_printf(MSG_DEBUG, "RTM_NEWLINK: operstate=%d ifi_flags=0x%x "
653 		   "(%s%s%s%s)",
654 		   drv->operstate, ifi->ifi_flags,
655 		   (ifi->ifi_flags & IFF_UP) ? "[UP]" : "",
656 		   (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
657 		   (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
658 		   (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
659 
660 	if (!drv->if_disabled && !(ifi->ifi_flags & IFF_UP)) {
661 		wpa_printf(MSG_DEBUG, "WEXT: Interface down");
662 		drv->if_disabled = 1;
663 		wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_DISABLED, NULL);
664 	}
665 
666 	if (drv->if_disabled && (ifi->ifi_flags & IFF_UP)) {
667 		if (if_indextoname(ifi->ifi_index, namebuf) &&
668 		    linux_iface_up(drv->ioctl_sock, drv->ifname) == 0) {
669 			wpa_printf(MSG_DEBUG, "WEXT: Ignore interface up "
670 				   "event since interface %s is down",
671 				   namebuf);
672 		} else if (if_nametoindex(drv->ifname) == 0) {
673 			wpa_printf(MSG_DEBUG, "WEXT: Ignore interface up "
674 				   "event since interface %s does not exist",
675 				   drv->ifname);
676 		} else if (drv->if_removed) {
677 			wpa_printf(MSG_DEBUG, "WEXT: Ignore interface up "
678 				   "event since interface %s is marked "
679 				   "removed", drv->ifname);
680 		} else {
681 			wpa_printf(MSG_DEBUG, "WEXT: Interface up");
682 			drv->if_disabled = 0;
683 			wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED,
684 					     NULL);
685 		}
686 	}
687 
688 	/*
689 	 * Some drivers send the association event before the operup event--in
690 	 * this case, lifting operstate in wpa_driver_wext_set_operstate()
691 	 * fails. This will hit us when wpa_supplicant does not need to do
692 	 * IEEE 802.1X authentication
693 	 */
694 	if (drv->operstate == 1 &&
695 	    (ifi->ifi_flags & (IFF_LOWER_UP | IFF_DORMANT)) == IFF_LOWER_UP &&
696 	    !(ifi->ifi_flags & IFF_RUNNING))
697 		netlink_send_oper_ifla(drv->netlink, drv->ifindex,
698 				       -1, IF_OPER_UP);
699 
700 	attrlen = len;
701 	attr = (struct rtattr *) buf;
702 
703 	rta_len = RTA_ALIGN(sizeof(struct rtattr));
704 	while (RTA_OK(attr, attrlen)) {
705 		if (attr->rta_type == IFLA_WIRELESS) {
706 			wpa_driver_wext_event_wireless(
707 				drv, ((char *) attr) + rta_len,
708 				attr->rta_len - rta_len);
709 		} else if (attr->rta_type == IFLA_IFNAME) {
710 			wpa_driver_wext_event_link(drv,
711 						   ((char *) attr) + rta_len,
712 						   attr->rta_len - rta_len, 0);
713 		}
714 		attr = RTA_NEXT(attr, attrlen);
715 	}
716 }
717 
718 
719 static void wpa_driver_wext_event_rtm_dellink(void *ctx, struct ifinfomsg *ifi,
720 					      u8 *buf, size_t len)
721 {
722 	struct wpa_driver_wext_data *drv = ctx;
723 	int attrlen, rta_len;
724 	struct rtattr *attr;
725 
726 	attrlen = len;
727 	attr = (struct rtattr *) buf;
728 
729 	rta_len = RTA_ALIGN(sizeof(struct rtattr));
730 	while (RTA_OK(attr, attrlen)) {
731 		if (attr->rta_type == IFLA_IFNAME) {
732 			wpa_driver_wext_event_link(drv,
733 						   ((char *) attr) + rta_len,
734 						   attr->rta_len - rta_len, 1);
735 		}
736 		attr = RTA_NEXT(attr, attrlen);
737 	}
738 }
739 
740 
741 static void wpa_driver_wext_rfkill_blocked(void *ctx)
742 {
743 	wpa_printf(MSG_DEBUG, "WEXT: RFKILL blocked");
744 	/*
745 	 * This may be for any interface; use ifdown event to disable
746 	 * interface.
747 	 */
748 }
749 
750 
751 static void wpa_driver_wext_rfkill_unblocked(void *ctx)
752 {
753 	struct wpa_driver_wext_data *drv = ctx;
754 	wpa_printf(MSG_DEBUG, "WEXT: RFKILL unblocked");
755 	if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1)) {
756 		wpa_printf(MSG_DEBUG, "WEXT: Could not set interface UP "
757 			   "after rfkill unblock");
758 		return;
759 	}
760 	/* rtnetlink ifup handler will report interface as enabled */
761 }
762 
763 
764 static void wext_get_phy_name(struct wpa_driver_wext_data *drv)
765 {
766 	/* Find phy (radio) to which this interface belongs */
767 	char buf[90], *pos;
768 	int f, rv;
769 
770 	drv->phyname[0] = '\0';
771 	snprintf(buf, sizeof(buf) - 1, "/sys/class/net/%s/phy80211/name",
772 		 drv->ifname);
773 	f = open(buf, O_RDONLY);
774 	if (f < 0) {
775 		wpa_printf(MSG_DEBUG, "Could not open file %s: %s",
776 			   buf, strerror(errno));
777 		return;
778 	}
779 
780 	rv = read(f, drv->phyname, sizeof(drv->phyname) - 1);
781 	close(f);
782 	if (rv < 0) {
783 		wpa_printf(MSG_DEBUG, "Could not read file %s: %s",
784 			   buf, strerror(errno));
785 		return;
786 	}
787 
788 	drv->phyname[rv] = '\0';
789 	pos = os_strchr(drv->phyname, '\n');
790 	if (pos)
791 		*pos = '\0';
792 	wpa_printf(MSG_DEBUG, "wext: interface %s phy: %s",
793 		   drv->ifname, drv->phyname);
794 }
795 
796 
797 /**
798  * wpa_driver_wext_init - Initialize WE driver interface
799  * @ctx: context to be used when calling wpa_supplicant functions,
800  * e.g., wpa_supplicant_event()
801  * @ifname: interface name, e.g., wlan0
802  * Returns: Pointer to private data, %NULL on failure
803  */
804 void * wpa_driver_wext_init(void *ctx, const char *ifname)
805 {
806 	struct wpa_driver_wext_data *drv;
807 	struct netlink_config *cfg;
808 	struct rfkill_config *rcfg;
809 	char path[128];
810 	struct stat buf;
811 
812 	drv = os_zalloc(sizeof(*drv));
813 	if (drv == NULL)
814 		return NULL;
815 	drv->ctx = ctx;
816 	os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
817 
818 	os_snprintf(path, sizeof(path), "/sys/class/net/%s/phy80211", ifname);
819 	if (stat(path, &buf) == 0) {
820 		wpa_printf(MSG_DEBUG, "WEXT: cfg80211-based driver detected");
821 		drv->cfg80211 = 1;
822 		wext_get_phy_name(drv);
823 	}
824 
825 	drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
826 	if (drv->ioctl_sock < 0) {
827 		perror("socket(PF_INET,SOCK_DGRAM)");
828 		goto err1;
829 	}
830 
831 	cfg = os_zalloc(sizeof(*cfg));
832 	if (cfg == NULL)
833 		goto err1;
834 	cfg->ctx = drv;
835 	cfg->newlink_cb = wpa_driver_wext_event_rtm_newlink;
836 	cfg->dellink_cb = wpa_driver_wext_event_rtm_dellink;
837 	drv->netlink = netlink_init(cfg);
838 	if (drv->netlink == NULL) {
839 		os_free(cfg);
840 		goto err2;
841 	}
842 
843 	rcfg = os_zalloc(sizeof(*rcfg));
844 	if (rcfg == NULL)
845 		goto err3;
846 	rcfg->ctx = drv;
847 	os_strlcpy(rcfg->ifname, ifname, sizeof(rcfg->ifname));
848 	rcfg->blocked_cb = wpa_driver_wext_rfkill_blocked;
849 	rcfg->unblocked_cb = wpa_driver_wext_rfkill_unblocked;
850 	drv->rfkill = rfkill_init(rcfg);
851 	if (drv->rfkill == NULL) {
852 		wpa_printf(MSG_DEBUG, "WEXT: RFKILL status not available");
853 		os_free(rcfg);
854 	}
855 
856 	drv->mlme_sock = -1;
857 
858 	if (wpa_driver_wext_finish_drv_init(drv) < 0)
859 		goto err3;
860 
861 	wpa_driver_wext_set_auth_param(drv, IW_AUTH_WPA_ENABLED, 1);
862 
863 	return drv;
864 
865 err3:
866 	rfkill_deinit(drv->rfkill);
867 	netlink_deinit(drv->netlink);
868 err2:
869 	close(drv->ioctl_sock);
870 err1:
871 	os_free(drv);
872 	return NULL;
873 }
874 
875 
876 static void wpa_driver_wext_send_rfkill(void *eloop_ctx, void *timeout_ctx)
877 {
878 	wpa_supplicant_event(timeout_ctx, EVENT_INTERFACE_DISABLED, NULL);
879 }
880 
881 
882 static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv)
883 {
884 	int send_rfkill_event = 0;
885 
886 	if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1) < 0) {
887 		if (rfkill_is_blocked(drv->rfkill)) {
888 			wpa_printf(MSG_DEBUG, "WEXT: Could not yet enable "
889 				   "interface '%s' due to rfkill",
890 				   drv->ifname);
891 			drv->if_disabled = 1;
892 			send_rfkill_event = 1;
893 		} else {
894 			wpa_printf(MSG_ERROR, "WEXT: Could not set "
895 				   "interface '%s' UP", drv->ifname);
896 			return -1;
897 		}
898 	}
899 
900 	/*
901 	 * Make sure that the driver does not have any obsolete PMKID entries.
902 	 */
903 	wpa_driver_wext_flush_pmkid(drv);
904 
905 	if (wpa_driver_wext_set_mode(drv, 0) < 0) {
906 		wpa_printf(MSG_DEBUG, "Could not configure driver to use "
907 			   "managed mode");
908 		/* Try to use it anyway */
909 	}
910 
911 	wpa_driver_wext_get_range(drv);
912 
913 	/*
914 	 * Unlock the driver's BSSID and force to a random SSID to clear any
915 	 * previous association the driver might have when the supplicant
916 	 * starts up.
917 	 */
918 	wpa_driver_wext_disconnect(drv);
919 
920 	drv->ifindex = if_nametoindex(drv->ifname);
921 
922 	if (os_strncmp(drv->ifname, "wlan", 4) == 0) {
923 		/*
924 		 * Host AP driver may use both wlan# and wifi# interface in
925 		 * wireless events. Since some of the versions included WE-18
926 		 * support, let's add the alternative ifindex also from
927 		 * driver_wext.c for the time being. This may be removed at
928 		 * some point once it is believed that old versions of the
929 		 * driver are not in use anymore.
930 		 */
931 		char ifname2[IFNAMSIZ + 1];
932 		os_strlcpy(ifname2, drv->ifname, sizeof(ifname2));
933 		os_memcpy(ifname2, "wifi", 4);
934 		wpa_driver_wext_alternative_ifindex(drv, ifname2);
935 	}
936 
937 	netlink_send_oper_ifla(drv->netlink, drv->ifindex,
938 			       1, IF_OPER_DORMANT);
939 
940 	if (send_rfkill_event) {
941 		eloop_register_timeout(0, 0, wpa_driver_wext_send_rfkill,
942 				       drv, drv->ctx);
943 	}
944 
945 	return 0;
946 }
947 
948 
949 /**
950  * wpa_driver_wext_deinit - Deinitialize WE driver interface
951  * @priv: Pointer to private wext data from wpa_driver_wext_init()
952  *
953  * Shut down driver interface and processing of driver events. Free
954  * private data buffer if one was allocated in wpa_driver_wext_init().
955  */
956 void wpa_driver_wext_deinit(void *priv)
957 {
958 	struct wpa_driver_wext_data *drv = priv;
959 
960 	wpa_driver_wext_set_auth_param(drv, IW_AUTH_WPA_ENABLED, 0);
961 
962 	eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv, drv->ctx);
963 
964 	/*
965 	 * Clear possibly configured driver parameters in order to make it
966 	 * easier to use the driver after wpa_supplicant has been terminated.
967 	 */
968 	wpa_driver_wext_disconnect(drv);
969 
970 	netlink_send_oper_ifla(drv->netlink, drv->ifindex, 0, IF_OPER_UP);
971 	netlink_deinit(drv->netlink);
972 	rfkill_deinit(drv->rfkill);
973 
974 	if (drv->mlme_sock >= 0)
975 		eloop_unregister_read_sock(drv->mlme_sock);
976 
977 	(void) linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 0);
978 
979 	close(drv->ioctl_sock);
980 	if (drv->mlme_sock >= 0)
981 		close(drv->mlme_sock);
982 	os_free(drv->assoc_req_ies);
983 	os_free(drv->assoc_resp_ies);
984 	os_free(drv);
985 }
986 
987 
988 /**
989  * wpa_driver_wext_scan_timeout - Scan timeout to report scan completion
990  * @eloop_ctx: Unused
991  * @timeout_ctx: ctx argument given to wpa_driver_wext_init()
992  *
993  * This function can be used as registered timeout when starting a scan to
994  * generate a scan completed event if the driver does not report this.
995  */
996 void wpa_driver_wext_scan_timeout(void *eloop_ctx, void *timeout_ctx)
997 {
998 	wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
999 	wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
1000 }
1001 
1002 
1003 /**
1004  * wpa_driver_wext_scan - Request the driver to initiate scan
1005  * @priv: Pointer to private wext data from wpa_driver_wext_init()
1006  * @param: Scan parameters (specific SSID to scan for (ProbeReq), etc.)
1007  * Returns: 0 on success, -1 on failure
1008  */
1009 int wpa_driver_wext_scan(void *priv, struct wpa_driver_scan_params *params)
1010 {
1011 	struct wpa_driver_wext_data *drv = priv;
1012 	struct iwreq iwr;
1013 	int ret = 0, timeout;
1014 	struct iw_scan_req req;
1015 	const u8 *ssid = params->ssids[0].ssid;
1016 	size_t ssid_len = params->ssids[0].ssid_len;
1017 
1018 	if (ssid_len > IW_ESSID_MAX_SIZE) {
1019 		wpa_printf(MSG_DEBUG, "%s: too long SSID (%lu)",
1020 			   __FUNCTION__, (unsigned long) ssid_len);
1021 		return -1;
1022 	}
1023 
1024 	os_memset(&iwr, 0, sizeof(iwr));
1025 	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1026 
1027 	if (ssid && ssid_len) {
1028 		os_memset(&req, 0, sizeof(req));
1029 		req.essid_len = ssid_len;
1030 		req.bssid.sa_family = ARPHRD_ETHER;
1031 		os_memset(req.bssid.sa_data, 0xff, ETH_ALEN);
1032 		os_memcpy(req.essid, ssid, ssid_len);
1033 		iwr.u.data.pointer = (caddr_t) &req;
1034 		iwr.u.data.length = sizeof(req);
1035 		iwr.u.data.flags = IW_SCAN_THIS_ESSID;
1036 	}
1037 
1038 	if (ioctl(drv->ioctl_sock, SIOCSIWSCAN, &iwr) < 0) {
1039 		perror("ioctl[SIOCSIWSCAN]");
1040 		ret = -1;
1041 	}
1042 
1043 	/* Not all drivers generate "scan completed" wireless event, so try to
1044 	 * read results after a timeout. */
1045 	timeout = 10;
1046 	if (drv->scan_complete_events) {
1047 		/*
1048 		 * The driver seems to deliver SIOCGIWSCAN events to notify
1049 		 * when scan is complete, so use longer timeout to avoid race
1050 		 * conditions with scanning and following association request.
1051 		 */
1052 		timeout = 30;
1053 	}
1054 	wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d "
1055 		   "seconds", ret, timeout);
1056 	eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv, drv->ctx);
1057 	eloop_register_timeout(timeout, 0, wpa_driver_wext_scan_timeout, drv,
1058 			       drv->ctx);
1059 
1060 	return ret;
1061 }
1062 
1063 
1064 static u8 * wpa_driver_wext_giwscan(struct wpa_driver_wext_data *drv,
1065 				    size_t *len)
1066 {
1067 	struct iwreq iwr;
1068 	u8 *res_buf;
1069 	size_t res_buf_len;
1070 
1071 	res_buf_len = IW_SCAN_MAX_DATA;
1072 	for (;;) {
1073 		res_buf = os_malloc(res_buf_len);
1074 		if (res_buf == NULL)
1075 			return NULL;
1076 		os_memset(&iwr, 0, sizeof(iwr));
1077 		os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1078 		iwr.u.data.pointer = res_buf;
1079 		iwr.u.data.length = res_buf_len;
1080 
1081 		if (ioctl(drv->ioctl_sock, SIOCGIWSCAN, &iwr) == 0)
1082 			break;
1083 
1084 		if (errno == E2BIG && res_buf_len < 65535) {
1085 			os_free(res_buf);
1086 			res_buf = NULL;
1087 			res_buf_len *= 2;
1088 			if (res_buf_len > 65535)
1089 				res_buf_len = 65535; /* 16-bit length field */
1090 			wpa_printf(MSG_DEBUG, "Scan results did not fit - "
1091 				   "trying larger buffer (%lu bytes)",
1092 				   (unsigned long) res_buf_len);
1093 		} else {
1094 			perror("ioctl[SIOCGIWSCAN]");
1095 			os_free(res_buf);
1096 			return NULL;
1097 		}
1098 	}
1099 
1100 	if (iwr.u.data.length > res_buf_len) {
1101 		os_free(res_buf);
1102 		return NULL;
1103 	}
1104 	*len = iwr.u.data.length;
1105 
1106 	return res_buf;
1107 }
1108 
1109 
1110 /*
1111  * Data structure for collecting WEXT scan results. This is needed to allow
1112  * the various methods of reporting IEs to be combined into a single IE buffer.
1113  */
1114 struct wext_scan_data {
1115 	struct wpa_scan_res res;
1116 	u8 *ie;
1117 	size_t ie_len;
1118 	u8 ssid[32];
1119 	size_t ssid_len;
1120 	int maxrate;
1121 };
1122 
1123 
1124 static void wext_get_scan_mode(struct iw_event *iwe,
1125 			       struct wext_scan_data *res)
1126 {
1127 	if (iwe->u.mode == IW_MODE_ADHOC)
1128 		res->res.caps |= IEEE80211_CAP_IBSS;
1129 	else if (iwe->u.mode == IW_MODE_MASTER || iwe->u.mode == IW_MODE_INFRA)
1130 		res->res.caps |= IEEE80211_CAP_ESS;
1131 }
1132 
1133 
1134 static void wext_get_scan_ssid(struct iw_event *iwe,
1135 			       struct wext_scan_data *res, char *custom,
1136 			       char *end)
1137 {
1138 	int ssid_len = iwe->u.essid.length;
1139 	if (custom + ssid_len > end)
1140 		return;
1141 	if (iwe->u.essid.flags &&
1142 	    ssid_len > 0 &&
1143 	    ssid_len <= IW_ESSID_MAX_SIZE) {
1144 		os_memcpy(res->ssid, custom, ssid_len);
1145 		res->ssid_len = ssid_len;
1146 	}
1147 }
1148 
1149 
1150 static void wext_get_scan_freq(struct iw_event *iwe,
1151 			       struct wext_scan_data *res)
1152 {
1153 	int divi = 1000000, i;
1154 
1155 	if (iwe->u.freq.e == 0) {
1156 		/*
1157 		 * Some drivers do not report frequency, but a channel.
1158 		 * Try to map this to frequency by assuming they are using
1159 		 * IEEE 802.11b/g.  But don't overwrite a previously parsed
1160 		 * frequency if the driver sends both frequency and channel,
1161 		 * since the driver may be sending an A-band channel that we
1162 		 * don't handle here.
1163 		 */
1164 
1165 		if (res->res.freq)
1166 			return;
1167 
1168 		if (iwe->u.freq.m >= 1 && iwe->u.freq.m <= 13) {
1169 			res->res.freq = 2407 + 5 * iwe->u.freq.m;
1170 			return;
1171 		} else if (iwe->u.freq.m == 14) {
1172 			res->res.freq = 2484;
1173 			return;
1174 		}
1175 	}
1176 
1177 	if (iwe->u.freq.e > 6) {
1178 		wpa_printf(MSG_DEBUG, "Invalid freq in scan results (BSSID="
1179 			   MACSTR " m=%d e=%d)",
1180 			   MAC2STR(res->res.bssid), iwe->u.freq.m,
1181 			   iwe->u.freq.e);
1182 		return;
1183 	}
1184 
1185 	for (i = 0; i < iwe->u.freq.e; i++)
1186 		divi /= 10;
1187 	res->res.freq = iwe->u.freq.m / divi;
1188 }
1189 
1190 
1191 static void wext_get_scan_qual(struct wpa_driver_wext_data *drv,
1192 			       struct iw_event *iwe,
1193 			       struct wext_scan_data *res)
1194 {
1195 	res->res.qual = iwe->u.qual.qual;
1196 	res->res.noise = iwe->u.qual.noise;
1197 	res->res.level = iwe->u.qual.level;
1198 	if (iwe->u.qual.updated & IW_QUAL_QUAL_INVALID)
1199 		res->res.flags |= WPA_SCAN_QUAL_INVALID;
1200 	if (iwe->u.qual.updated & IW_QUAL_LEVEL_INVALID)
1201 		res->res.flags |= WPA_SCAN_LEVEL_INVALID;
1202 	if (iwe->u.qual.updated & IW_QUAL_NOISE_INVALID)
1203 		res->res.flags |= WPA_SCAN_NOISE_INVALID;
1204 	if (iwe->u.qual.updated & IW_QUAL_DBM)
1205 		res->res.flags |= WPA_SCAN_LEVEL_DBM;
1206 	if ((iwe->u.qual.updated & IW_QUAL_DBM) ||
1207 	    ((iwe->u.qual.level != 0) &&
1208 	     (iwe->u.qual.level > drv->max_level))) {
1209 		if (iwe->u.qual.level >= 64)
1210 			res->res.level -= 0x100;
1211 		if (iwe->u.qual.noise >= 64)
1212 			res->res.noise -= 0x100;
1213 	}
1214 }
1215 
1216 
1217 static void wext_get_scan_encode(struct iw_event *iwe,
1218 				 struct wext_scan_data *res)
1219 {
1220 	if (!(iwe->u.data.flags & IW_ENCODE_DISABLED))
1221 		res->res.caps |= IEEE80211_CAP_PRIVACY;
1222 }
1223 
1224 
1225 static void wext_get_scan_rate(struct iw_event *iwe,
1226 			       struct wext_scan_data *res, char *pos,
1227 			       char *end)
1228 {
1229 	int maxrate;
1230 	char *custom = pos + IW_EV_LCP_LEN;
1231 	struct iw_param p;
1232 	size_t clen;
1233 
1234 	clen = iwe->len;
1235 	if (custom + clen > end)
1236 		return;
1237 	maxrate = 0;
1238 	while (((ssize_t) clen) >= (ssize_t) sizeof(struct iw_param)) {
1239 		/* Note: may be misaligned, make a local, aligned copy */
1240 		os_memcpy(&p, custom, sizeof(struct iw_param));
1241 		if (p.value > maxrate)
1242 			maxrate = p.value;
1243 		clen -= sizeof(struct iw_param);
1244 		custom += sizeof(struct iw_param);
1245 	}
1246 
1247 	/* Convert the maxrate from WE-style (b/s units) to
1248 	 * 802.11 rates (500000 b/s units).
1249 	 */
1250 	res->maxrate = maxrate / 500000;
1251 }
1252 
1253 
1254 static void wext_get_scan_iwevgenie(struct iw_event *iwe,
1255 				    struct wext_scan_data *res, char *custom,
1256 				    char *end)
1257 {
1258 	char *genie, *gpos, *gend;
1259 	u8 *tmp;
1260 
1261 	if (iwe->u.data.length == 0)
1262 		return;
1263 
1264 	gpos = genie = custom;
1265 	gend = genie + iwe->u.data.length;
1266 	if (gend > end) {
1267 		wpa_printf(MSG_INFO, "IWEVGENIE overflow");
1268 		return;
1269 	}
1270 
1271 	tmp = os_realloc(res->ie, res->ie_len + gend - gpos);
1272 	if (tmp == NULL)
1273 		return;
1274 	os_memcpy(tmp + res->ie_len, gpos, gend - gpos);
1275 	res->ie = tmp;
1276 	res->ie_len += gend - gpos;
1277 }
1278 
1279 
1280 static void wext_get_scan_custom(struct iw_event *iwe,
1281 				 struct wext_scan_data *res, char *custom,
1282 				 char *end)
1283 {
1284 	size_t clen;
1285 	u8 *tmp;
1286 
1287 	clen = iwe->u.data.length;
1288 	if (custom + clen > end)
1289 		return;
1290 
1291 	if (clen > 7 && os_strncmp(custom, "wpa_ie=", 7) == 0) {
1292 		char *spos;
1293 		int bytes;
1294 		spos = custom + 7;
1295 		bytes = custom + clen - spos;
1296 		if (bytes & 1 || bytes == 0)
1297 			return;
1298 		bytes /= 2;
1299 		tmp = os_realloc(res->ie, res->ie_len + bytes);
1300 		if (tmp == NULL)
1301 			return;
1302 		res->ie = tmp;
1303 		if (hexstr2bin(spos, tmp + res->ie_len, bytes) < 0)
1304 			return;
1305 		res->ie_len += bytes;
1306 	} else if (clen > 7 && os_strncmp(custom, "rsn_ie=", 7) == 0) {
1307 		char *spos;
1308 		int bytes;
1309 		spos = custom + 7;
1310 		bytes = custom + clen - spos;
1311 		if (bytes & 1 || bytes == 0)
1312 			return;
1313 		bytes /= 2;
1314 		tmp = os_realloc(res->ie, res->ie_len + bytes);
1315 		if (tmp == NULL)
1316 			return;
1317 		res->ie = tmp;
1318 		if (hexstr2bin(spos, tmp + res->ie_len, bytes) < 0)
1319 			return;
1320 		res->ie_len += bytes;
1321 	} else if (clen > 4 && os_strncmp(custom, "tsf=", 4) == 0) {
1322 		char *spos;
1323 		int bytes;
1324 		u8 bin[8];
1325 		spos = custom + 4;
1326 		bytes = custom + clen - spos;
1327 		if (bytes != 16) {
1328 			wpa_printf(MSG_INFO, "Invalid TSF length (%d)", bytes);
1329 			return;
1330 		}
1331 		bytes /= 2;
1332 		if (hexstr2bin(spos, bin, bytes) < 0) {
1333 			wpa_printf(MSG_DEBUG, "WEXT: Invalid TSF value");
1334 			return;
1335 		}
1336 		res->res.tsf += WPA_GET_BE64(bin);
1337 	}
1338 }
1339 
1340 
1341 static int wext_19_iw_point(struct wpa_driver_wext_data *drv, u16 cmd)
1342 {
1343 	return drv->we_version_compiled > 18 &&
1344 		(cmd == SIOCGIWESSID || cmd == SIOCGIWENCODE ||
1345 		 cmd == IWEVGENIE || cmd == IWEVCUSTOM);
1346 }
1347 
1348 
1349 static void wpa_driver_wext_add_scan_entry(struct wpa_scan_results *res,
1350 					   struct wext_scan_data *data)
1351 {
1352 	struct wpa_scan_res **tmp;
1353 	struct wpa_scan_res *r;
1354 	size_t extra_len;
1355 	u8 *pos, *end, *ssid_ie = NULL, *rate_ie = NULL;
1356 
1357 	/* Figure out whether we need to fake any IEs */
1358 	pos = data->ie;
1359 	end = pos + data->ie_len;
1360 	while (pos && pos + 1 < end) {
1361 		if (pos + 2 + pos[1] > end)
1362 			break;
1363 		if (pos[0] == WLAN_EID_SSID)
1364 			ssid_ie = pos;
1365 		else if (pos[0] == WLAN_EID_SUPP_RATES)
1366 			rate_ie = pos;
1367 		else if (pos[0] == WLAN_EID_EXT_SUPP_RATES)
1368 			rate_ie = pos;
1369 		pos += 2 + pos[1];
1370 	}
1371 
1372 	extra_len = 0;
1373 	if (ssid_ie == NULL)
1374 		extra_len += 2 + data->ssid_len;
1375 	if (rate_ie == NULL && data->maxrate)
1376 		extra_len += 3;
1377 
1378 	r = os_zalloc(sizeof(*r) + extra_len + data->ie_len);
1379 	if (r == NULL)
1380 		return;
1381 	os_memcpy(r, &data->res, sizeof(*r));
1382 	r->ie_len = extra_len + data->ie_len;
1383 	pos = (u8 *) (r + 1);
1384 	if (ssid_ie == NULL) {
1385 		/*
1386 		 * Generate a fake SSID IE since the driver did not report
1387 		 * a full IE list.
1388 		 */
1389 		*pos++ = WLAN_EID_SSID;
1390 		*pos++ = data->ssid_len;
1391 		os_memcpy(pos, data->ssid, data->ssid_len);
1392 		pos += data->ssid_len;
1393 	}
1394 	if (rate_ie == NULL && data->maxrate) {
1395 		/*
1396 		 * Generate a fake Supported Rates IE since the driver did not
1397 		 * report a full IE list.
1398 		 */
1399 		*pos++ = WLAN_EID_SUPP_RATES;
1400 		*pos++ = 1;
1401 		*pos++ = data->maxrate;
1402 	}
1403 	if (data->ie)
1404 		os_memcpy(pos, data->ie, data->ie_len);
1405 
1406 	tmp = os_realloc(res->res,
1407 			 (res->num + 1) * sizeof(struct wpa_scan_res *));
1408 	if (tmp == NULL) {
1409 		os_free(r);
1410 		return;
1411 	}
1412 	tmp[res->num++] = r;
1413 	res->res = tmp;
1414 }
1415 
1416 
1417 /**
1418  * wpa_driver_wext_get_scan_results - Fetch the latest scan results
1419  * @priv: Pointer to private wext data from wpa_driver_wext_init()
1420  * Returns: Scan results on success, -1 on failure
1421  */
1422 struct wpa_scan_results * wpa_driver_wext_get_scan_results(void *priv)
1423 {
1424 	struct wpa_driver_wext_data *drv = priv;
1425 	size_t len;
1426 	int first;
1427 	u8 *res_buf;
1428 	struct iw_event iwe_buf, *iwe = &iwe_buf;
1429 	char *pos, *end, *custom;
1430 	struct wpa_scan_results *res;
1431 	struct wext_scan_data data;
1432 
1433 	res_buf = wpa_driver_wext_giwscan(drv, &len);
1434 	if (res_buf == NULL)
1435 		return NULL;
1436 
1437 	first = 1;
1438 
1439 	res = os_zalloc(sizeof(*res));
1440 	if (res == NULL) {
1441 		os_free(res_buf);
1442 		return NULL;
1443 	}
1444 
1445 	pos = (char *) res_buf;
1446 	end = (char *) res_buf + len;
1447 	os_memset(&data, 0, sizeof(data));
1448 
1449 	while (pos + IW_EV_LCP_LEN <= end) {
1450 		/* Event data may be unaligned, so make a local, aligned copy
1451 		 * before processing. */
1452 		os_memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
1453 		if (iwe->len <= IW_EV_LCP_LEN)
1454 			break;
1455 
1456 		custom = pos + IW_EV_POINT_LEN;
1457 		if (wext_19_iw_point(drv, iwe->cmd)) {
1458 			/* WE-19 removed the pointer from struct iw_point */
1459 			char *dpos = (char *) &iwe_buf.u.data.length;
1460 			int dlen = dpos - (char *) &iwe_buf;
1461 			os_memcpy(dpos, pos + IW_EV_LCP_LEN,
1462 				  sizeof(struct iw_event) - dlen);
1463 		} else {
1464 			os_memcpy(&iwe_buf, pos, sizeof(struct iw_event));
1465 			custom += IW_EV_POINT_OFF;
1466 		}
1467 
1468 		switch (iwe->cmd) {
1469 		case SIOCGIWAP:
1470 			if (!first)
1471 				wpa_driver_wext_add_scan_entry(res, &data);
1472 			first = 0;
1473 			os_free(data.ie);
1474 			os_memset(&data, 0, sizeof(data));
1475 			os_memcpy(data.res.bssid,
1476 				  iwe->u.ap_addr.sa_data, ETH_ALEN);
1477 			break;
1478 		case SIOCGIWMODE:
1479 			wext_get_scan_mode(iwe, &data);
1480 			break;
1481 		case SIOCGIWESSID:
1482 			wext_get_scan_ssid(iwe, &data, custom, end);
1483 			break;
1484 		case SIOCGIWFREQ:
1485 			wext_get_scan_freq(iwe, &data);
1486 			break;
1487 		case IWEVQUAL:
1488 			wext_get_scan_qual(drv, iwe, &data);
1489 			break;
1490 		case SIOCGIWENCODE:
1491 			wext_get_scan_encode(iwe, &data);
1492 			break;
1493 		case SIOCGIWRATE:
1494 			wext_get_scan_rate(iwe, &data, pos, end);
1495 			break;
1496 		case IWEVGENIE:
1497 			wext_get_scan_iwevgenie(iwe, &data, custom, end);
1498 			break;
1499 		case IWEVCUSTOM:
1500 			wext_get_scan_custom(iwe, &data, custom, end);
1501 			break;
1502 		}
1503 
1504 		pos += iwe->len;
1505 	}
1506 	os_free(res_buf);
1507 	res_buf = NULL;
1508 	if (!first)
1509 		wpa_driver_wext_add_scan_entry(res, &data);
1510 	os_free(data.ie);
1511 
1512 	wpa_printf(MSG_DEBUG, "Received %lu bytes of scan results (%lu BSSes)",
1513 		   (unsigned long) len, (unsigned long) res->num);
1514 
1515 	return res;
1516 }
1517 
1518 
1519 static int wpa_driver_wext_get_range(void *priv)
1520 {
1521 	struct wpa_driver_wext_data *drv = priv;
1522 	struct iw_range *range;
1523 	struct iwreq iwr;
1524 	int minlen;
1525 	size_t buflen;
1526 
1527 	/*
1528 	 * Use larger buffer than struct iw_range in order to allow the
1529 	 * structure to grow in the future.
1530 	 */
1531 	buflen = sizeof(struct iw_range) + 500;
1532 	range = os_zalloc(buflen);
1533 	if (range == NULL)
1534 		return -1;
1535 
1536 	os_memset(&iwr, 0, sizeof(iwr));
1537 	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1538 	iwr.u.data.pointer = (caddr_t) range;
1539 	iwr.u.data.length = buflen;
1540 
1541 	minlen = ((char *) &range->enc_capa) - (char *) range +
1542 		sizeof(range->enc_capa);
1543 
1544 	if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) {
1545 		perror("ioctl[SIOCGIWRANGE]");
1546 		os_free(range);
1547 		return -1;
1548 	} else if (iwr.u.data.length >= minlen &&
1549 		   range->we_version_compiled >= 18) {
1550 		wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: WE(compiled)=%d "
1551 			   "WE(source)=%d enc_capa=0x%x",
1552 			   range->we_version_compiled,
1553 			   range->we_version_source,
1554 			   range->enc_capa);
1555 		drv->has_capability = 1;
1556 		drv->we_version_compiled = range->we_version_compiled;
1557 		if (range->enc_capa & IW_ENC_CAPA_WPA) {
1558 			drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1559 				WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK;
1560 		}
1561 		if (range->enc_capa & IW_ENC_CAPA_WPA2) {
1562 			drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
1563 				WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;
1564 		}
1565 		drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 |
1566 			WPA_DRIVER_CAPA_ENC_WEP104;
1567 		if (range->enc_capa & IW_ENC_CAPA_CIPHER_TKIP)
1568 			drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP;
1569 		if (range->enc_capa & IW_ENC_CAPA_CIPHER_CCMP)
1570 			drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP;
1571 		if (range->enc_capa & IW_ENC_CAPA_4WAY_HANDSHAKE)
1572 			drv->capa.flags |= WPA_DRIVER_FLAGS_4WAY_HANDSHAKE;
1573 		drv->capa.auth = WPA_DRIVER_AUTH_OPEN |
1574 			WPA_DRIVER_AUTH_SHARED |
1575 			WPA_DRIVER_AUTH_LEAP;
1576 		drv->capa.max_scan_ssids = 1;
1577 
1578 		wpa_printf(MSG_DEBUG, "  capabilities: key_mgmt 0x%x enc 0x%x "
1579 			   "flags 0x%x",
1580 			   drv->capa.key_mgmt, drv->capa.enc, drv->capa.flags);
1581 	} else {
1582 		wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: too old (short) data - "
1583 			   "assuming WPA is not supported");
1584 	}
1585 
1586 	drv->max_level = range->max_qual.level;
1587 
1588 	os_free(range);
1589 	return 0;
1590 }
1591 
1592 
1593 static int wpa_driver_wext_set_psk(struct wpa_driver_wext_data *drv,
1594 				   const u8 *psk)
1595 {
1596 	struct iw_encode_ext *ext;
1597 	struct iwreq iwr;
1598 	int ret;
1599 
1600 	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
1601 
1602 	if (!(drv->capa.flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
1603 		return 0;
1604 
1605 	if (!psk)
1606 		return 0;
1607 
1608 	os_memset(&iwr, 0, sizeof(iwr));
1609 	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1610 
1611 	ext = os_zalloc(sizeof(*ext) + PMK_LEN);
1612 	if (ext == NULL)
1613 		return -1;
1614 
1615 	iwr.u.encoding.pointer = (caddr_t) ext;
1616 	iwr.u.encoding.length = sizeof(*ext) + PMK_LEN;
1617 	ext->key_len = PMK_LEN;
1618 	os_memcpy(&ext->key, psk, ext->key_len);
1619 	ext->alg = IW_ENCODE_ALG_PMK;
1620 
1621 	ret = ioctl(drv->ioctl_sock, SIOCSIWENCODEEXT, &iwr);
1622 	if (ret < 0)
1623 		perror("ioctl[SIOCSIWENCODEEXT] PMK");
1624 	os_free(ext);
1625 
1626 	return ret;
1627 }
1628 
1629 
1630 static int wpa_driver_wext_set_key_ext(void *priv, enum wpa_alg alg,
1631 				       const u8 *addr, int key_idx,
1632 				       int set_tx, const u8 *seq,
1633 				       size_t seq_len,
1634 				       const u8 *key, size_t key_len)
1635 {
1636 	struct wpa_driver_wext_data *drv = priv;
1637 	struct iwreq iwr;
1638 	int ret = 0;
1639 	struct iw_encode_ext *ext;
1640 
1641 	if (seq_len > IW_ENCODE_SEQ_MAX_SIZE) {
1642 		wpa_printf(MSG_DEBUG, "%s: Invalid seq_len %lu",
1643 			   __FUNCTION__, (unsigned long) seq_len);
1644 		return -1;
1645 	}
1646 
1647 	ext = os_zalloc(sizeof(*ext) + key_len);
1648 	if (ext == NULL)
1649 		return -1;
1650 	os_memset(&iwr, 0, sizeof(iwr));
1651 	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1652 	iwr.u.encoding.flags = key_idx + 1;
1653 	iwr.u.encoding.flags |= IW_ENCODE_TEMP;
1654 	if (alg == WPA_ALG_NONE)
1655 		iwr.u.encoding.flags |= IW_ENCODE_DISABLED;
1656 	iwr.u.encoding.pointer = (caddr_t) ext;
1657 	iwr.u.encoding.length = sizeof(*ext) + key_len;
1658 
1659 	if (addr == NULL || is_broadcast_ether_addr(addr))
1660 		ext->ext_flags |= IW_ENCODE_EXT_GROUP_KEY;
1661 	if (set_tx)
1662 		ext->ext_flags |= IW_ENCODE_EXT_SET_TX_KEY;
1663 
1664 	ext->addr.sa_family = ARPHRD_ETHER;
1665 	if (addr)
1666 		os_memcpy(ext->addr.sa_data, addr, ETH_ALEN);
1667 	else
1668 		os_memset(ext->addr.sa_data, 0xff, ETH_ALEN);
1669 	if (key && key_len) {
1670 		os_memcpy(ext + 1, key, key_len);
1671 		ext->key_len = key_len;
1672 	}
1673 	switch (alg) {
1674 	case WPA_ALG_NONE:
1675 		ext->alg = IW_ENCODE_ALG_NONE;
1676 		break;
1677 	case WPA_ALG_WEP:
1678 		ext->alg = IW_ENCODE_ALG_WEP;
1679 		break;
1680 	case WPA_ALG_TKIP:
1681 		ext->alg = IW_ENCODE_ALG_TKIP;
1682 		break;
1683 	case WPA_ALG_CCMP:
1684 		ext->alg = IW_ENCODE_ALG_CCMP;
1685 		break;
1686 	case WPA_ALG_PMK:
1687 		ext->alg = IW_ENCODE_ALG_PMK;
1688 		break;
1689 #ifdef CONFIG_IEEE80211W
1690 	case WPA_ALG_IGTK:
1691 		ext->alg = IW_ENCODE_ALG_AES_CMAC;
1692 		break;
1693 #endif /* CONFIG_IEEE80211W */
1694 	default:
1695 		wpa_printf(MSG_DEBUG, "%s: Unknown algorithm %d",
1696 			   __FUNCTION__, alg);
1697 		os_free(ext);
1698 		return -1;
1699 	}
1700 
1701 	if (seq && seq_len) {
1702 		ext->ext_flags |= IW_ENCODE_EXT_RX_SEQ_VALID;
1703 		os_memcpy(ext->rx_seq, seq, seq_len);
1704 	}
1705 
1706 	if (ioctl(drv->ioctl_sock, SIOCSIWENCODEEXT, &iwr) < 0) {
1707 		ret = errno == EOPNOTSUPP ? -2 : -1;
1708 		if (errno == ENODEV) {
1709 			/*
1710 			 * ndiswrapper seems to be returning incorrect error
1711 			 * code.. */
1712 			ret = -2;
1713 		}
1714 
1715 		perror("ioctl[SIOCSIWENCODEEXT]");
1716 	}
1717 
1718 	os_free(ext);
1719 	return ret;
1720 }
1721 
1722 
1723 /**
1724  * wpa_driver_wext_set_key - Configure encryption key
1725  * @priv: Pointer to private wext data from wpa_driver_wext_init()
1726  * @priv: Private driver interface data
1727  * @alg: Encryption algorithm (%WPA_ALG_NONE, %WPA_ALG_WEP,
1728  *	%WPA_ALG_TKIP, %WPA_ALG_CCMP); %WPA_ALG_NONE clears the key.
1729  * @addr: Address of the peer STA or ff:ff:ff:ff:ff:ff for
1730  *	broadcast/default keys
1731  * @key_idx: key index (0..3), usually 0 for unicast keys
1732  * @set_tx: Configure this key as the default Tx key (only used when
1733  *	driver does not support separate unicast/individual key
1734  * @seq: Sequence number/packet number, seq_len octets, the next
1735  *	packet number to be used for in replay protection; configured
1736  *	for Rx keys (in most cases, this is only used with broadcast
1737  *	keys and set to zero for unicast keys)
1738  * @seq_len: Length of the seq, depends on the algorithm:
1739  *	TKIP: 6 octets, CCMP: 6 octets
1740  * @key: Key buffer; TKIP: 16-byte temporal key, 8-byte Tx Mic key,
1741  *	8-byte Rx Mic Key
1742  * @key_len: Length of the key buffer in octets (WEP: 5 or 13,
1743  *	TKIP: 32, CCMP: 16)
1744  * Returns: 0 on success, -1 on failure
1745  *
1746  * This function uses SIOCSIWENCODEEXT by default, but tries to use
1747  * SIOCSIWENCODE if the extended ioctl fails when configuring a WEP key.
1748  */
1749 int wpa_driver_wext_set_key(const char *ifname, void *priv, enum wpa_alg alg,
1750 			    const u8 *addr, int key_idx,
1751 			    int set_tx, const u8 *seq, size_t seq_len,
1752 			    const u8 *key, size_t key_len)
1753 {
1754 	struct wpa_driver_wext_data *drv = priv;
1755 	struct iwreq iwr;
1756 	int ret = 0;
1757 
1758 	wpa_printf(MSG_DEBUG, "%s: alg=%d key_idx=%d set_tx=%d seq_len=%lu "
1759 		   "key_len=%lu",
1760 		   __FUNCTION__, alg, key_idx, set_tx,
1761 		   (unsigned long) seq_len, (unsigned long) key_len);
1762 
1763 	ret = wpa_driver_wext_set_key_ext(drv, alg, addr, key_idx, set_tx,
1764 					  seq, seq_len, key, key_len);
1765 	if (ret == 0)
1766 		return 0;
1767 
1768 	if (ret == -2 &&
1769 	    (alg == WPA_ALG_NONE || alg == WPA_ALG_WEP)) {
1770 		wpa_printf(MSG_DEBUG, "Driver did not support "
1771 			   "SIOCSIWENCODEEXT, trying SIOCSIWENCODE");
1772 		ret = 0;
1773 	} else {
1774 		wpa_printf(MSG_DEBUG, "Driver did not support "
1775 			   "SIOCSIWENCODEEXT");
1776 		return ret;
1777 	}
1778 
1779 	os_memset(&iwr, 0, sizeof(iwr));
1780 	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1781 	iwr.u.encoding.flags = key_idx + 1;
1782 	iwr.u.encoding.flags |= IW_ENCODE_TEMP;
1783 	if (alg == WPA_ALG_NONE)
1784 		iwr.u.encoding.flags |= IW_ENCODE_DISABLED;
1785 	iwr.u.encoding.pointer = (caddr_t) key;
1786 	iwr.u.encoding.length = key_len;
1787 
1788 	if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) {
1789 		perror("ioctl[SIOCSIWENCODE]");
1790 		ret = -1;
1791 	}
1792 
1793 	if (set_tx && alg != WPA_ALG_NONE) {
1794 		os_memset(&iwr, 0, sizeof(iwr));
1795 		os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1796 		iwr.u.encoding.flags = key_idx + 1;
1797 		iwr.u.encoding.flags |= IW_ENCODE_TEMP;
1798 		iwr.u.encoding.pointer = (caddr_t) NULL;
1799 		iwr.u.encoding.length = 0;
1800 		if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) {
1801 			perror("ioctl[SIOCSIWENCODE] (set_tx)");
1802 			ret = -1;
1803 		}
1804 	}
1805 
1806 	return ret;
1807 }
1808 
1809 
1810 static int wpa_driver_wext_set_countermeasures(void *priv,
1811 					       int enabled)
1812 {
1813 	struct wpa_driver_wext_data *drv = priv;
1814 	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
1815 	return wpa_driver_wext_set_auth_param(drv,
1816 					      IW_AUTH_TKIP_COUNTERMEASURES,
1817 					      enabled);
1818 }
1819 
1820 
1821 static int wpa_driver_wext_set_drop_unencrypted(void *priv,
1822 						int enabled)
1823 {
1824 	struct wpa_driver_wext_data *drv = priv;
1825 	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
1826 	drv->use_crypt = enabled;
1827 	return wpa_driver_wext_set_auth_param(drv, IW_AUTH_DROP_UNENCRYPTED,
1828 					      enabled);
1829 }
1830 
1831 
1832 static int wpa_driver_wext_mlme(struct wpa_driver_wext_data *drv,
1833 				const u8 *addr, int cmd, int reason_code)
1834 {
1835 	struct iwreq iwr;
1836 	struct iw_mlme mlme;
1837 	int ret = 0;
1838 
1839 	os_memset(&iwr, 0, sizeof(iwr));
1840 	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1841 	os_memset(&mlme, 0, sizeof(mlme));
1842 	mlme.cmd = cmd;
1843 	mlme.reason_code = reason_code;
1844 	mlme.addr.sa_family = ARPHRD_ETHER;
1845 	os_memcpy(mlme.addr.sa_data, addr, ETH_ALEN);
1846 	iwr.u.data.pointer = (caddr_t) &mlme;
1847 	iwr.u.data.length = sizeof(mlme);
1848 
1849 	if (ioctl(drv->ioctl_sock, SIOCSIWMLME, &iwr) < 0) {
1850 		perror("ioctl[SIOCSIWMLME]");
1851 		ret = -1;
1852 	}
1853 
1854 	return ret;
1855 }
1856 
1857 
1858 static void wpa_driver_wext_disconnect(struct wpa_driver_wext_data *drv)
1859 {
1860 	struct iwreq iwr;
1861 	const u8 null_bssid[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
1862 #ifndef ANDROID
1863 	u8 ssid[32];
1864 	int i;
1865 #endif /* ANDROID */
1866 
1867 	/*
1868 	 * Only force-disconnect when the card is in infrastructure mode,
1869 	 * otherwise the driver might interpret the cleared BSSID and random
1870 	 * SSID as an attempt to create a new ad-hoc network.
1871 	 */
1872 	os_memset(&iwr, 0, sizeof(iwr));
1873 	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1874 	if (ioctl(drv->ioctl_sock, SIOCGIWMODE, &iwr) < 0) {
1875 		perror("ioctl[SIOCGIWMODE]");
1876 		iwr.u.mode = IW_MODE_INFRA;
1877 	}
1878 
1879 	if (iwr.u.mode == IW_MODE_INFRA) {
1880 		/* Clear the BSSID selection */
1881 		if (wpa_driver_wext_set_bssid(drv, null_bssid) < 0) {
1882 			wpa_printf(MSG_DEBUG, "WEXT: Failed to clear BSSID "
1883 				   "selection on disconnect");
1884 		}
1885 
1886 #ifndef ANDROID
1887 		if (drv->cfg80211) {
1888 			/*
1889 			 * cfg80211 supports SIOCSIWMLME commands, so there is
1890 			 * no need for the random SSID hack, but clear the
1891 			 * SSID.
1892 			 */
1893 			if (wpa_driver_wext_set_ssid(drv, (u8 *) "", 0) < 0) {
1894 				wpa_printf(MSG_DEBUG, "WEXT: Failed to clear "
1895 					   "SSID on disconnect");
1896 			}
1897 			return;
1898 		}
1899 
1900 		/*
1901 		 * Set a random SSID to make sure the driver will not be trying
1902 		 * to associate with something even if it does not understand
1903 		 * SIOCSIWMLME commands (or tries to associate automatically
1904 		 * after deauth/disassoc).
1905 		 */
1906 		for (i = 0; i < 32; i++)
1907 			ssid[i] = rand() & 0xFF;
1908 		if (wpa_driver_wext_set_ssid(drv, ssid, 32) < 0) {
1909 			wpa_printf(MSG_DEBUG, "WEXT: Failed to set bogus "
1910 				   "SSID to disconnect");
1911 		}
1912 #endif /* ANDROID */
1913 	}
1914 }
1915 
1916 
1917 static int wpa_driver_wext_deauthenticate(void *priv, const u8 *addr,
1918 					  int reason_code)
1919 {
1920 	struct wpa_driver_wext_data *drv = priv;
1921 	int ret;
1922 	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
1923 	ret = wpa_driver_wext_mlme(drv, addr, IW_MLME_DEAUTH, reason_code);
1924 	wpa_driver_wext_disconnect(drv);
1925 	return ret;
1926 }
1927 
1928 
1929 static int wpa_driver_wext_disassociate(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_DISASSOC, 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 const struct wpa_driver_ops wpa_driver_wext_ops = {
2344 	.name = "wext",
2345 	.desc = "Linux wireless extensions (generic)",
2346 	.get_bssid = wpa_driver_wext_get_bssid,
2347 	.get_ssid = wpa_driver_wext_get_ssid,
2348 	.set_key = wpa_driver_wext_set_key,
2349 	.set_countermeasures = wpa_driver_wext_set_countermeasures,
2350 	.scan2 = wpa_driver_wext_scan,
2351 	.get_scan_results2 = wpa_driver_wext_get_scan_results,
2352 	.deauthenticate = wpa_driver_wext_deauthenticate,
2353 	.disassociate = wpa_driver_wext_disassociate,
2354 	.associate = wpa_driver_wext_associate,
2355 	.init = wpa_driver_wext_init,
2356 	.deinit = wpa_driver_wext_deinit,
2357 	.add_pmkid = wpa_driver_wext_add_pmkid,
2358 	.remove_pmkid = wpa_driver_wext_remove_pmkid,
2359 	.flush_pmkid = wpa_driver_wext_flush_pmkid,
2360 	.get_capa = wpa_driver_wext_get_capa,
2361 	.set_operstate = wpa_driver_wext_set_operstate,
2362 	.get_radio_name = wext_get_radio_name,
2363 };
2364