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