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