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