driver_wext.c revision 04949598a23f501be6eec21697465fd46a28840a
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Driver interaction with generic Linux Wireless Extensions 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2003-2010, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This file implements a driver interface for the Linux Wireless Extensions. 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * When used with WE-18 or newer, this interface can be used as-is with number 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * of drivers. In addition to this, some of the common functions in this file 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * can be used by other driver interface implementations that use generic WE 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ioctls, but require private ioctls for some of the functionality. 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <sys/ioctl.h> 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <sys/types.h> 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <sys/stat.h> 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <fcntl.h> 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <net/if_arp.h> 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "linux_wext.h" 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eloop.h" 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h" 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/wpa_common.h" 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "priv_netlink.h" 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "netlink.h" 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "linux_ioctl.h" 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "rfkill.h" 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "driver.h" 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "driver_wext.h" 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef ANDROID 351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "android_drv.h" 361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* ANDROID */ 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_wext_flush_pmkid(void *priv); 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_wext_get_range(void *priv); 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv); 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_wext_disconnect(struct wpa_driver_wext_data *drv); 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_wext_set_auth_alg(void *priv, int auth_alg); 43886c3ff164ee2c0e281f4b1f31ce2b00f045f9deDmitry Shmidt#ifdef ANDROID 44886c3ff164ee2c0e281f4b1f31ce2b00f045f9deDmitry Shmidtextern int wpa_driver_wext_driver_cmd(void *priv, char *cmd, char *buf, 45886c3ff164ee2c0e281f4b1f31ce2b00f045f9deDmitry Shmidt size_t buf_len); 46886c3ff164ee2c0e281f4b1f31ce2b00f045f9deDmitry Shmidtextern int wpa_driver_wext_combo_scan(void *priv, 47886c3ff164ee2c0e281f4b1f31ce2b00f045f9deDmitry Shmidt struct wpa_driver_scan_params *params); 482b7fea278e437f1fe13970a1e65ca51149223d96Dmitry Shmidtextern int wpa_driver_signal_poll(void *priv, struct wpa_signal_info *si); 49886c3ff164ee2c0e281f4b1f31ce2b00f045f9deDmitry Shmidt#endif 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_driver_wext_set_auth_param(struct wpa_driver_wext_data *drv, 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int idx, u32 value) 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iwreq iwr; 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0; 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&iwr, 0, sizeof(iwr)); 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.param.flags = idx & IW_AUTH_INDEX; 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.param.value = value; 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ioctl(drv->ioctl_sock, SIOCSIWAUTH, &iwr) < 0) { 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (errno != EOPNOTSUPP) { 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WEXT: SIOCSIWAUTH(param %d " 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "value 0x%x) failed: %s)", 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt idx, value, strerror(errno)); 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = errno == EOPNOTSUPP ? -2 : -1; 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_driver_wext_get_bssid - Get BSSID, SIOCGIWAP 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @priv: Pointer to private wext data from wpa_driver_wext_init() 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @bssid: Buffer for BSSID 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_driver_wext_get_bssid(void *priv, u8 *bssid) 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_wext_data *drv = priv; 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iwreq iwr; 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0; 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&iwr, 0, sizeof(iwr)); 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ioctl(drv->ioctl_sock, SIOCGIWAP, &iwr) < 0) { 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("ioctl[SIOCGIWAP]"); 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(bssid, iwr.u.ap_addr.sa_data, ETH_ALEN); 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_driver_wext_set_bssid - Set BSSID, SIOCSIWAP 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @priv: Pointer to private wext data from wpa_driver_wext_init() 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @bssid: BSSID 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_driver_wext_set_bssid(void *priv, const u8 *bssid) 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_wext_data *drv = priv; 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iwreq iwr; 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0; 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&iwr, 0, sizeof(iwr)); 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.ap_addr.sa_family = ARPHRD_ETHER; 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bssid) 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(iwr.u.ap_addr.sa_data, bssid, ETH_ALEN); 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(iwr.u.ap_addr.sa_data, 0, ETH_ALEN); 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ioctl(drv->ioctl_sock, SIOCSIWAP, &iwr) < 0) { 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("ioctl[SIOCSIWAP]"); 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_driver_wext_get_ssid - Get SSID, SIOCGIWESSID 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @priv: Pointer to private wext data from wpa_driver_wext_init() 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ssid: Buffer for the SSID; must be at least 32 bytes long 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: SSID length on success, -1 on failure 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_driver_wext_get_ssid(void *priv, u8 *ssid) 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_wext_data *drv = priv; 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iwreq iwr; 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0; 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&iwr, 0, sizeof(iwr)); 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.essid.pointer = (caddr_t) ssid; 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.essid.length = 32; 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ioctl(drv->ioctl_sock, SIOCGIWESSID, &iwr) < 0) { 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("ioctl[SIOCGIWESSID]"); 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = iwr.u.essid.length; 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret > 32) 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 32; 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Some drivers include nul termination in the SSID, so let's 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * remove it here before further processing. WE-21 changes this 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to explicitly require the length _not_ to include nul 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * termination. */ 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret > 0 && ssid[ret - 1] == '\0' && 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->we_version_compiled < 21) 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret--; 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_driver_wext_set_ssid - Set SSID, SIOCSIWESSID 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @priv: Pointer to private wext data from wpa_driver_wext_init() 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ssid: SSID 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ssid_len: Length of SSID (0..32) 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_driver_wext_set_ssid(void *priv, const u8 *ssid, size_t ssid_len) 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_wext_data *drv = priv; 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iwreq iwr; 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0; 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char buf[33]; 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid_len > 32) 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&iwr, 0, sizeof(iwr)); 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* flags: 1 = ESSID is active, 0 = not (promiscuous) */ 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.essid.flags = (ssid_len != 0); 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(buf, 0, sizeof(buf)); 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(buf, ssid, ssid_len); 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.essid.pointer = (caddr_t) buf; 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->we_version_compiled < 21) { 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* For historic reasons, set SSID length to include one extra 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * character, C string nul termination, even though SSID is 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * really an octet string that should not be presented as a C 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * string. Some Linux drivers decrement the length by one and 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * can thus end up missing the last octet of the SSID if the 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * length is not incremented here. WE-21 changes this to 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * explicitly require the length _not_ to include nul 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * termination. */ 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid_len) 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid_len++; 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.essid.length = ssid_len; 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ioctl(drv->ioctl_sock, SIOCSIWESSID, &iwr) < 0) { 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("ioctl[SIOCSIWESSID]"); 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_driver_wext_set_freq - Set frequency/channel, SIOCSIWFREQ 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @priv: Pointer to private wext data from wpa_driver_wext_init() 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @freq: Frequency in MHz 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_driver_wext_set_freq(void *priv, int freq) 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_wext_data *drv = priv; 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iwreq iwr; 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0; 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&iwr, 0, sizeof(iwr)); 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.freq.m = freq * 100000; 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.freq.e = 1; 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ioctl(drv->ioctl_sock, SIOCSIWFREQ, &iwr) < 0) { 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("ioctl[SIOCSIWFREQ]"); 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_driver_wext_event_wireless_custom(void *ctx, char *custom) 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wpa_event_data data; 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_MSGDUMP, "WEXT: Custom wireless event: '%s'", 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt custom); 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&data, 0, sizeof(data)); 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Host AP driver */ 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) { 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.michael_mic_failure.unicast = 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strstr(custom, " unicast ") != NULL; 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: parse parameters(?) */ 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data); 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (os_strncmp(custom, "ASSOCINFO(ReqIEs=", 17) == 0) { 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *spos; 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int bytes; 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *req_ies = NULL, *resp_ies = NULL; 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt spos = custom + 17; 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bytes = strspn(spos, "0123456789abcdefABCDEF"); 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!bytes || (bytes & 1)) 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bytes /= 2; 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req_ies = os_malloc(bytes); 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (req_ies == NULL || 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hexstr2bin(spos, req_ies, bytes) < 0) 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto done; 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.assoc_info.req_ies = req_ies; 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.assoc_info.req_ies_len = bytes; 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt spos += bytes * 2; 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.assoc_info.resp_ies = NULL; 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.assoc_info.resp_ies_len = 0; 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncmp(spos, " RespIEs=", 9) == 0) { 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt spos += 9; 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bytes = strspn(spos, "0123456789abcdefABCDEF"); 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!bytes || (bytes & 1)) 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto done; 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bytes /= 2; 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp_ies = os_malloc(bytes); 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp_ies == NULL || 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hexstr2bin(spos, resp_ies, bytes) < 0) 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto done; 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.assoc_info.resp_ies = resp_ies; 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.assoc_info.resp_ies_len = bytes; 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(ctx, EVENT_ASSOCINFO, &data); 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt done: 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(resp_ies); 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(req_ies); 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (os_strncmp(custom, "STKSTART.request=", 17) == 0) { 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hwaddr_aton(custom + 17, data.stkstart.peer)) { 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WEXT: unrecognized " 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "STKSTART.request '%s'", custom + 17); 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(ctx, EVENT_STKSTART, &data); 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */ 308886c3ff164ee2c0e281f4b1f31ce2b00f045f9deDmitry Shmidt#ifdef ANDROID 309886c3ff164ee2c0e281f4b1f31ce2b00f045f9deDmitry Shmidt } else if (os_strncmp(custom, "STOP", 4) == 0) { 310886c3ff164ee2c0e281f4b1f31ce2b00f045f9deDmitry Shmidt wpa_msg(ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STOPPED"); 311886c3ff164ee2c0e281f4b1f31ce2b00f045f9deDmitry Shmidt } else if (os_strncmp(custom, "START", 5) == 0) { 312886c3ff164ee2c0e281f4b1f31ce2b00f045f9deDmitry Shmidt wpa_msg(ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STARTED"); 313886c3ff164ee2c0e281f4b1f31ce2b00f045f9deDmitry Shmidt } else if (os_strncmp(custom, "HANG", 4) == 0) { 314886c3ff164ee2c0e281f4b1f31ce2b00f045f9deDmitry Shmidt wpa_msg(ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED"); 315886c3ff164ee2c0e281f4b1f31ce2b00f045f9deDmitry Shmidt#endif /* ANDROID */ 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_wext_event_wireless_michaelmicfailure( 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *ctx, const char *ev, size_t len) 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct iw_michaelmicfailure *mic; 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wpa_event_data data; 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < sizeof(*mic)) 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mic = (const struct iw_michaelmicfailure *) ev; 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Michael MIC failure wireless event: " 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "flags=0x%x src_addr=" MACSTR, mic->flags, 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(mic->src_addr.sa_data)); 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&data, 0, sizeof(data)); 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.michael_mic_failure.unicast = !(mic->flags & IW_MICFAILURE_GROUP); 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data); 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_wext_event_wireless_pmkidcand( 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_wext_data *drv, const char *ev, size_t len) 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct iw_pmkid_cand *cand; 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wpa_event_data data; 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr; 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < sizeof(*cand)) 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cand = (const struct iw_pmkid_cand *) ev; 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr = (const u8 *) cand->bssid.sa_data; 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "PMKID candidate wireless event: " 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "flags=0x%x index=%d bssid=" MACSTR, cand->flags, 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cand->index, MAC2STR(addr)); 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&data, 0, sizeof(data)); 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data.pmkid_candidate.bssid, addr, ETH_ALEN); 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.pmkid_candidate.index = cand->index; 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.pmkid_candidate.preauth = cand->flags & IW_PMKID_CAND_PREAUTH; 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE, &data); 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_wext_event_wireless_assocreqie( 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_wext_data *drv, const char *ev, int len) 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < 0) 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "AssocReq IE wireless event", (const u8 *) ev, 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len); 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(drv->assoc_req_ies); 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->assoc_req_ies = os_malloc(len); 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->assoc_req_ies == NULL) { 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->assoc_req_ies_len = 0; 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(drv->assoc_req_ies, ev, len); 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->assoc_req_ies_len = len; 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_wext_event_wireless_assocrespie( 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_wext_data *drv, const char *ev, int len) 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < 0) 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "AssocResp IE wireless event", (const u8 *) ev, 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len); 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(drv->assoc_resp_ies); 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->assoc_resp_ies = os_malloc(len); 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->assoc_resp_ies == NULL) { 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->assoc_resp_ies_len = 0; 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(drv->assoc_resp_ies, ev, len); 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->assoc_resp_ies_len = len; 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_wext_event_assoc_ies(struct wpa_driver_wext_data *drv) 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wpa_event_data data; 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->assoc_req_ies == NULL && drv->assoc_resp_ies == NULL) 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&data, 0, sizeof(data)); 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->assoc_req_ies) { 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.assoc_info.req_ies = drv->assoc_req_ies; 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.assoc_info.req_ies_len = drv->assoc_req_ies_len; 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->assoc_resp_ies) { 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.assoc_info.resp_ies = drv->assoc_resp_ies; 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.assoc_info.resp_ies_len = drv->assoc_resp_ies_len; 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &data); 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(drv->assoc_req_ies); 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->assoc_req_ies = NULL; 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(drv->assoc_resp_ies); 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->assoc_resp_ies = NULL; 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_wext_event_wireless(struct wpa_driver_wext_data *drv, 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *data, int len) 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iw_event iwe_buf, *iwe = &iwe_buf; 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *pos, *end, *custom, *buf; 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = data; 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = data + len; 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pos + IW_EV_LCP_LEN <= end) { 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Event data may be unaligned, so make a local, aligned copy 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * before processing. */ 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&iwe_buf, pos, IW_EV_LCP_LEN); 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Wireless event: cmd=0x%x len=%d", 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwe->cmd, iwe->len); 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iwe->len <= IW_EV_LCP_LEN) 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt custom = pos + IW_EV_POINT_LEN; 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->we_version_compiled > 18 && 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (iwe->cmd == IWEVMICHAELMICFAILURE || 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwe->cmd == IWEVCUSTOM || 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwe->cmd == IWEVASSOCREQIE || 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwe->cmd == IWEVASSOCRESPIE || 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwe->cmd == IWEVPMKIDCAND)) { 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* WE-19 removed the pointer from struct iw_point */ 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *dpos = (char *) &iwe_buf.u.data.length; 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int dlen = dpos - (char *) &iwe_buf; 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(dpos, pos + IW_EV_LCP_LEN, 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(struct iw_event) - dlen); 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&iwe_buf, pos, sizeof(struct iw_event)); 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt custom += IW_EV_POINT_OFF; 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (iwe->cmd) { 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SIOCGIWAP: 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Wireless event: new AP: " 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR, 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR((u8 *) iwe->u.ap_addr.sa_data)); 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (is_zero_ether_addr( 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (const u8 *) iwe->u.ap_addr.sa_data) || 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(iwe->u.ap_addr.sa_data, 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "\x44\x44\x44\x44\x44\x44", ETH_ALEN) == 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) { 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(drv->assoc_req_ies); 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->assoc_req_ies = NULL; 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(drv->assoc_resp_ies); 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->assoc_resp_ies = NULL; 48729991f40caccd6c45cd7c56ca597f370a4f2b9ebDmitry Shmidt#ifdef ANDROID 48829991f40caccd6c45cd7c56ca597f370a4f2b9ebDmitry Shmidt if (!drv->skip_disconnect) { 48929991f40caccd6c45cd7c56ca597f370a4f2b9ebDmitry Shmidt drv->skip_disconnect = 1; 49029991f40caccd6c45cd7c56ca597f370a4f2b9ebDmitry Shmidt#endif 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL); 49329991f40caccd6c45cd7c56ca597f370a4f2b9ebDmitry Shmidt#ifdef ANDROID 49429991f40caccd6c45cd7c56ca597f370a4f2b9ebDmitry Shmidt } 49529991f40caccd6c45cd7c56ca597f370a4f2b9ebDmitry Shmidt#endif 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 49729991f40caccd6c45cd7c56ca597f370a4f2b9ebDmitry Shmidt#ifdef ANDROID 49829991f40caccd6c45cd7c56ca597f370a4f2b9ebDmitry Shmidt drv->skip_disconnect = 0; 49929991f40caccd6c45cd7c56ca597f370a4f2b9ebDmitry Shmidt#endif 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_wext_event_assoc_ies(drv); 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_ASSOC, 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL); 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IWEVMICHAELMICFAILURE: 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (custom + iwe->u.data.length > end) { 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WEXT: Invalid " 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "IWEVMICHAELMICFAILURE length"); 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_wext_event_wireless_michaelmicfailure( 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->ctx, custom, iwe->u.data.length); 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IWEVCUSTOM: 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (custom + iwe->u.data.length > end) { 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WEXT: Invalid " 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "IWEVCUSTOM length"); 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_malloc(iwe->u.data.length + 1); 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(buf, custom, iwe->u.data.length); 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf[iwe->u.data.length] = '\0'; 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_wext_event_wireless_custom(drv->ctx, buf); 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SIOCGIWSCAN: 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->scan_complete_events = 1; 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_driver_wext_scan_timeout, 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv, drv->ctx); 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL); 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IWEVASSOCREQIE: 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (custom + iwe->u.data.length > end) { 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WEXT: Invalid " 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "IWEVASSOCREQIE length"); 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_wext_event_wireless_assocreqie( 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv, custom, iwe->u.data.length); 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IWEVASSOCRESPIE: 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (custom + iwe->u.data.length > end) { 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WEXT: Invalid " 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "IWEVASSOCRESPIE length"); 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_wext_event_wireless_assocrespie( 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv, custom, iwe->u.data.length); 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IWEVPMKIDCAND: 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (custom + iwe->u.data.length > end) { 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WEXT: Invalid " 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "IWEVPMKIDCAND length"); 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_wext_event_wireless_pmkidcand( 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv, custom, iwe->u.data.length); 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += iwe->len; 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_wext_event_link(struct wpa_driver_wext_data *drv, 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *buf, size_t len, int del) 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wpa_event_data event; 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&event, 0, sizeof(event)); 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len > sizeof(event.interface_status.ifname)) 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = sizeof(event.interface_status.ifname) - 1; 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(event.interface_status.ifname, buf, len); 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.interface_status.ievent = del ? EVENT_INTERFACE_REMOVED : 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EVENT_INTERFACE_ADDED; 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RTM_%sLINK, IFLA_IFNAME: Interface '%s' %s", 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt del ? "DEL" : "NEW", 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.interface_status.ifname, 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt del ? "removed" : "added"); 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strcmp(drv->ifname, event.interface_status.ifname) == 0) { 58704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (del) { 58804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (drv->if_removed) { 58904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "WEXT: if_removed " 59004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "already set - ignore event"); 59104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 59204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->if_removed = 1; 59404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } else { 59504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (if_nametoindex(drv->ifname) == 0) { 59604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "WEXT: Interface %s " 59704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "does not exist - ignore " 59804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "RTM_NEWLINK", 59904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt drv->ifname); 60004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 60104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 60204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!drv->if_removed) { 60304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "WEXT: if_removed " 60404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "already cleared - ignore event"); 60504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 60604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->if_removed = 0; 60804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event); 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_wext_own_ifname(struct wpa_driver_wext_data *drv, 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, size_t len) 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int attrlen, rta_len; 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rtattr *attr; 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attrlen = len; 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr = (struct rtattr *) buf; 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rta_len = RTA_ALIGN(sizeof(struct rtattr)); 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (RTA_OK(attr, attrlen)) { 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->rta_type == IFLA_IFNAME) { 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strcmp(((char *) attr) + rta_len, drv->ifname) 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt == 0) 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr = RTA_NEXT(attr, attrlen); 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_wext_own_ifindex(struct wpa_driver_wext_data *drv, 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ifindex, u8 *buf, size_t len) 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->ifindex == ifindex || drv->ifindex2 == ifindex) 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->if_removed && wpa_driver_wext_own_ifname(drv, buf, len)) { 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->ifindex = if_nametoindex(drv->ifname); 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WEXT: Update ifindex for a removed " 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "interface"); 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_wext_finish_drv_init(drv); 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_wext_event_rtm_newlink(void *ctx, struct ifinfomsg *ifi, 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, size_t len) 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_wext_data *drv = ctx; 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int attrlen, rta_len; 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rtattr *attr; 66404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt char namebuf[IFNAMSIZ]; 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_driver_wext_own_ifindex(drv, ifi->ifi_index, buf, len)) { 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Ignore event for foreign ifindex %d", 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ifi->ifi_index); 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RTM_NEWLINK: operstate=%d ifi_flags=0x%x " 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(%s%s%s%s)", 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->operstate, ifi->ifi_flags, 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (ifi->ifi_flags & IFF_UP) ? "[UP]" : "", 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "", 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "", 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : ""); 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!drv->if_disabled && !(ifi->ifi_flags & IFF_UP)) { 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WEXT: Interface down"); 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->if_disabled = 1; 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_DISABLED, NULL); 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->if_disabled && (ifi->ifi_flags & IFF_UP)) { 68704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (if_indextoname(ifi->ifi_index, namebuf) && 68804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt linux_iface_up(drv->ioctl_sock, drv->ifname) == 0) { 68904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "WEXT: Ignore interface up " 69004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "event since interface %s is down", 69104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt namebuf); 69204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } else if (if_nametoindex(drv->ifname) == 0) { 69304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "WEXT: Ignore interface up " 69404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "event since interface %s does not exist", 69504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt drv->ifname); 69604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } else if (drv->if_removed) { 69704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "WEXT: Ignore interface up " 69804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "event since interface %s is marked " 69904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "removed", drv->ifname); 70004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } else { 70104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "WEXT: Interface up"); 70204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt drv->if_disabled = 0; 70304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED, 70404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt NULL); 70504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Some drivers send the association event before the operup event--in 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * this case, lifting operstate in wpa_driver_wext_set_operstate() 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * fails. This will hit us when wpa_supplicant does not need to do 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IEEE 802.1X authentication 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->operstate == 1 && 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (ifi->ifi_flags & (IFF_LOWER_UP | IFF_DORMANT)) == IFF_LOWER_UP && 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(ifi->ifi_flags & IFF_RUNNING)) 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt netlink_send_oper_ifla(drv->netlink, drv->ifindex, 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt -1, IF_OPER_UP); 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attrlen = len; 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr = (struct rtattr *) buf; 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rta_len = RTA_ALIGN(sizeof(struct rtattr)); 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (RTA_OK(attr, attrlen)) { 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->rta_type == IFLA_WIRELESS) { 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_wext_event_wireless( 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv, ((char *) attr) + rta_len, 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr->rta_len - rta_len); 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (attr->rta_type == IFLA_IFNAME) { 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_wext_event_link(drv, 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ((char *) attr) + rta_len, 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr->rta_len - rta_len, 0); 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr = RTA_NEXT(attr, attrlen); 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_wext_event_rtm_dellink(void *ctx, struct ifinfomsg *ifi, 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, size_t len) 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_wext_data *drv = ctx; 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int attrlen, rta_len; 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rtattr *attr; 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attrlen = len; 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr = (struct rtattr *) buf; 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rta_len = RTA_ALIGN(sizeof(struct rtattr)); 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (RTA_OK(attr, attrlen)) { 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->rta_type == IFLA_IFNAME) { 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_wext_event_link(drv, 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ((char *) attr) + rta_len, 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr->rta_len - rta_len, 1); 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr = RTA_NEXT(attr, attrlen); 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_wext_rfkill_blocked(void *ctx) 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WEXT: RFKILL blocked"); 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This may be for any interface; use ifdown event to disable 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * interface. 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_wext_rfkill_unblocked(void *ctx) 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_wext_data *drv = ctx; 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WEXT: RFKILL unblocked"); 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1)) { 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WEXT: Could not set interface UP " 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "after rfkill unblock"); 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* rtnetlink ifup handler will report interface as enabled */ 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wext_get_phy_name(struct wpa_driver_wext_data *drv) 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Find phy (radio) to which this interface belongs */ 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char buf[90], *pos; 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int f, rv; 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->phyname[0] = '\0'; 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt snprintf(buf, sizeof(buf) - 1, "/sys/class/net/%s/phy80211/name", 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->ifname); 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt f = open(buf, O_RDONLY); 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (f < 0) { 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Could not open file %s: %s", 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf, strerror(errno)); 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rv = read(f, drv->phyname, sizeof(drv->phyname) - 1); 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt close(f); 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rv < 0) { 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Could not read file %s: %s", 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf, strerror(errno)); 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->phyname[rv] = '\0'; 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = os_strchr(drv->phyname, '\n'); 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos) 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos = '\0'; 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "wext: interface %s phy: %s", 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->ifname, drv->phyname); 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_driver_wext_init - Initialize WE driver interface 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ctx: context to be used when calling wpa_supplicant functions, 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * e.g., wpa_supplicant_event() 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ifname: interface name, e.g., wlan0 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to private data, %NULL on failure 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid * wpa_driver_wext_init(void *ctx, const char *ifname) 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_wext_data *drv; 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct netlink_config *cfg; 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rfkill_config *rcfg; 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char path[128]; 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct stat buf; 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv = os_zalloc(sizeof(*drv)); 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv == NULL) 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->ctx = ctx; 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_snprintf(path, sizeof(path), "/sys/class/net/%s/phy80211", ifname); 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (stat(path, &buf) == 0) { 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WEXT: cfg80211-based driver detected"); 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->cfg80211 = 1; 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wext_get_phy_name(drv); 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->ioctl_sock < 0) { 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("socket(PF_INET,SOCK_DGRAM)"); 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto err1; 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg = os_zalloc(sizeof(*cfg)); 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cfg == NULL) 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto err1; 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg->ctx = drv; 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg->newlink_cb = wpa_driver_wext_event_rtm_newlink; 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg->dellink_cb = wpa_driver_wext_event_rtm_dellink; 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->netlink = netlink_init(cfg); 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->netlink == NULL) { 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(cfg); 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto err2; 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rcfg = os_zalloc(sizeof(*rcfg)); 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rcfg == NULL) 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto err3; 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rcfg->ctx = drv; 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(rcfg->ifname, ifname, sizeof(rcfg->ifname)); 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rcfg->blocked_cb = wpa_driver_wext_rfkill_blocked; 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rcfg->unblocked_cb = wpa_driver_wext_rfkill_unblocked; 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->rfkill = rfkill_init(rcfg); 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->rfkill == NULL) { 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WEXT: RFKILL status not available"); 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(rcfg); 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->mlme_sock = -1; 8771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 878886c3ff164ee2c0e281f4b1f31ce2b00f045f9deDmitry Shmidt#ifdef ANDROID 879886c3ff164ee2c0e281f4b1f31ce2b00f045f9deDmitry Shmidt drv->errors = 0; 880886c3ff164ee2c0e281f4b1f31ce2b00f045f9deDmitry Shmidt drv->driver_is_started = TRUE; 881886c3ff164ee2c0e281f4b1f31ce2b00f045f9deDmitry Shmidt drv->skip_disconnect = 0; 882886c3ff164ee2c0e281f4b1f31ce2b00f045f9deDmitry Shmidt drv->bgscan_enabled = 0; 8831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* ANDROID */ 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_driver_wext_finish_drv_init(drv) < 0) 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto err3; 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_wext_set_auth_param(drv, IW_AUTH_WPA_ENABLED, 1); 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return drv; 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidterr3: 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rfkill_deinit(drv->rfkill); 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt netlink_deinit(drv->netlink); 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidterr2: 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt close(drv->ioctl_sock); 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidterr1: 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(drv); 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_wext_send_rfkill(void *eloop_ctx, void *timeout_ctx) 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(timeout_ctx, EVENT_INTERFACE_DISABLED, NULL); 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv) 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int send_rfkill_event = 0; 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1) < 0) { 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rfkill_is_blocked(drv->rfkill)) { 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WEXT: Could not yet enable " 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "interface '%s' due to rfkill", 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->ifname); 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->if_disabled = 1; 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt send_rfkill_event = 1; 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "WEXT: Could not set " 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "interface '%s' UP", drv->ifname); 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Make sure that the driver does not have any obsolete PMKID entries. 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_wext_flush_pmkid(drv); 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_driver_wext_set_mode(drv, 0) < 0) { 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Could not configure driver to use " 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "managed mode"); 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Try to use it anyway */ 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_wext_get_range(drv); 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Unlock the driver's BSSID and force to a random SSID to clear any 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * previous association the driver might have when the supplicant 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * starts up. 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_wext_disconnect(drv); 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->ifindex = if_nametoindex(drv->ifname); 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncmp(drv->ifname, "wlan", 4) == 0) { 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Host AP driver may use both wlan# and wifi# interface in 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wireless events. Since some of the versions included WE-18 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * support, let's add the alternative ifindex also from 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * driver_wext.c for the time being. This may be removed at 9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * some point once it is believed that old versions of the 9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * driver are not in use anymore. 9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char ifname2[IFNAMSIZ + 1]; 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(ifname2, drv->ifname, sizeof(ifname2)); 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ifname2, "wifi", 4); 9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_wext_alternative_ifindex(drv, ifname2); 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt netlink_send_oper_ifla(drv->netlink, drv->ifindex, 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1, IF_OPER_DORMANT); 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (send_rfkill_event) { 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(0, 0, wpa_driver_wext_send_rfkill, 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv, drv->ctx); 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_driver_wext_deinit - Deinitialize WE driver interface 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @priv: Pointer to private wext data from wpa_driver_wext_init() 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Shut down driver interface and processing of driver events. Free 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * private data buffer if one was allocated in wpa_driver_wext_init(). 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_driver_wext_deinit(void *priv) 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_wext_data *drv = priv; 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_wext_set_auth_param(drv, IW_AUTH_WPA_ENABLED, 0); 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv, drv->ctx); 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Clear possibly configured driver parameters in order to make it 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * easier to use the driver after wpa_supplicant has been terminated. 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_wext_disconnect(drv); 9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt netlink_send_oper_ifla(drv->netlink, drv->ifindex, 0, IF_OPER_UP); 9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt netlink_deinit(drv->netlink); 9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rfkill_deinit(drv->rfkill); 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->mlme_sock >= 0) 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_unregister_read_sock(drv->mlme_sock); 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (void) linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 0); 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt close(drv->ioctl_sock); 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->mlme_sock >= 0) 10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt close(drv->mlme_sock); 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(drv->assoc_req_ies); 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(drv->assoc_resp_ies); 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(drv); 10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_driver_wext_scan_timeout - Scan timeout to report scan completion 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @eloop_ctx: Unused 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @timeout_ctx: ctx argument given to wpa_driver_wext_init() 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function can be used as registered timeout when starting a scan to 10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * generate a scan completed event if the driver does not report this. 10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_driver_wext_scan_timeout(void *eloop_ctx, void *timeout_ctx) 10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Scan timeout - try to get results"); 10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL); 10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_driver_wext_scan - Request the driver to initiate scan 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @priv: Pointer to private wext data from wpa_driver_wext_init() 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @param: Scan parameters (specific SSID to scan for (ProbeReq), etc.) 10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_driver_wext_scan(void *priv, struct wpa_driver_scan_params *params) 10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_wext_data *drv = priv; 10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iwreq iwr; 10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0, timeout; 10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iw_scan_req req; 10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *ssid = params->ssids[0].ssid; 10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t ssid_len = params->ssids[0].ssid_len; 10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1045886c3ff164ee2c0e281f4b1f31ce2b00f045f9deDmitry Shmidt#ifdef ANDROID 1046886c3ff164ee2c0e281f4b1f31ce2b00f045f9deDmitry Shmidt if (drv->capa.max_scan_ssids > 1) { 1047886c3ff164ee2c0e281f4b1f31ce2b00f045f9deDmitry Shmidt ret = wpa_driver_wext_combo_scan(priv, params); 1048886c3ff164ee2c0e281f4b1f31ce2b00f045f9deDmitry Shmidt goto scan_out; 1049886c3ff164ee2c0e281f4b1f31ce2b00f045f9deDmitry Shmidt } 1050886c3ff164ee2c0e281f4b1f31ce2b00f045f9deDmitry Shmidt#endif 1051886c3ff164ee2c0e281f4b1f31ce2b00f045f9deDmitry Shmidt 10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid_len > IW_ESSID_MAX_SIZE) { 10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: too long SSID (%lu)", 10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __FUNCTION__, (unsigned long) ssid_len); 10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&iwr, 0, sizeof(iwr)); 10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid && ssid_len) { 10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&req, 0, sizeof(req)); 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req.essid_len = ssid_len; 10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req.bssid.sa_family = ARPHRD_ETHER; 10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(req.bssid.sa_data, 0xff, ETH_ALEN); 10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(req.essid, ssid, ssid_len); 10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.data.pointer = (caddr_t) &req; 10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.data.length = sizeof(req); 10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.data.flags = IW_SCAN_THIS_ESSID; 10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ioctl(drv->ioctl_sock, SIOCSIWSCAN, &iwr) < 0) { 10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("ioctl[SIOCSIWSCAN]"); 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1077886c3ff164ee2c0e281f4b1f31ce2b00f045f9deDmitry Shmidt#ifdef ANDROID 1078886c3ff164ee2c0e281f4b1f31ce2b00f045f9deDmitry Shmidtscan_out: 1079886c3ff164ee2c0e281f4b1f31ce2b00f045f9deDmitry Shmidt#endif 10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Not all drivers generate "scan completed" wireless event, so try to 10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * read results after a timeout. */ 1082886c3ff164ee2c0e281f4b1f31ce2b00f045f9deDmitry Shmidt timeout = 10; 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->scan_complete_events) { 10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The driver seems to deliver SIOCGIWSCAN events to notify 10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * when scan is complete, so use longer timeout to avoid race 10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * conditions with scanning and following association request. 10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt timeout = 30; 10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d " 10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "seconds", ret, timeout); 10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv, drv->ctx); 10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(timeout, 0, wpa_driver_wext_scan_timeout, drv, 10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->ctx); 10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * wpa_driver_wext_giwscan(struct wpa_driver_wext_data *drv, 11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t *len) 11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iwreq iwr; 11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *res_buf; 11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t res_buf_len; 11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res_buf_len = IW_SCAN_MAX_DATA; 11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (;;) { 11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res_buf = os_malloc(res_buf_len); 11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res_buf == NULL) 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&iwr, 0, sizeof(iwr)); 11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.data.pointer = res_buf; 11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.data.length = res_buf_len; 11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ioctl(drv->ioctl_sock, SIOCGIWSCAN, &iwr) == 0) 11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (errno == E2BIG && res_buf_len < 65535) { 11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(res_buf); 11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res_buf = NULL; 11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res_buf_len *= 2; 11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res_buf_len > 65535) 11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res_buf_len = 65535; /* 16-bit length field */ 11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Scan results did not fit - " 11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "trying larger buffer (%lu bytes)", 11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) res_buf_len); 11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("ioctl[SIOCGIWSCAN]"); 11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(res_buf); 11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iwr.u.data.length > res_buf_len) { 11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(res_buf); 11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = iwr.u.data.length; 11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return res_buf; 11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Data structure for collecting WEXT scan results. This is needed to allow 11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the various methods of reporting IEs to be combined into a single IE buffer. 11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wext_scan_data { 11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_res res; 11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *ie; 11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t ie_len; 11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ssid[32]; 11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t ssid_len; 11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int maxrate; 11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wext_get_scan_mode(struct iw_event *iwe, 11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wext_scan_data *res) 11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iwe->u.mode == IW_MODE_ADHOC) 11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res->res.caps |= IEEE80211_CAP_IBSS; 11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (iwe->u.mode == IW_MODE_MASTER || iwe->u.mode == IW_MODE_INFRA) 11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res->res.caps |= IEEE80211_CAP_ESS; 11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wext_get_scan_ssid(struct iw_event *iwe, 11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wext_scan_data *res, char *custom, 11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *end) 11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ssid_len = iwe->u.essid.length; 11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (custom + ssid_len > end) 11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iwe->u.essid.flags && 11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid_len > 0 && 11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid_len <= IW_ESSID_MAX_SIZE) { 11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(res->ssid, custom, ssid_len); 11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res->ssid_len = ssid_len; 11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wext_get_scan_freq(struct iw_event *iwe, 11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wext_scan_data *res) 11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int divi = 1000000, i; 11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iwe->u.freq.e == 0) { 11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Some drivers do not report frequency, but a channel. 11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Try to map this to frequency by assuming they are using 11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IEEE 802.11b/g. But don't overwrite a previously parsed 11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * frequency if the driver sends both frequency and channel, 11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * since the driver may be sending an A-band channel that we 11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * don't handle here. 12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res->res.freq) 12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iwe->u.freq.m >= 1 && iwe->u.freq.m <= 13) { 12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res->res.freq = 2407 + 5 * iwe->u.freq.m; 12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (iwe->u.freq.m == 14) { 12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res->res.freq = 2484; 12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iwe->u.freq.e > 6) { 12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Invalid freq in scan results (BSSID=" 12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR " m=%d e=%d)", 12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(res->res.bssid), iwe->u.freq.m, 12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwe->u.freq.e); 12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < iwe->u.freq.e; i++) 12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt divi /= 10; 12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res->res.freq = iwe->u.freq.m / divi; 12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wext_get_scan_qual(struct wpa_driver_wext_data *drv, 12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iw_event *iwe, 12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wext_scan_data *res) 12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res->res.qual = iwe->u.qual.qual; 12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res->res.noise = iwe->u.qual.noise; 12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res->res.level = iwe->u.qual.level; 12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iwe->u.qual.updated & IW_QUAL_QUAL_INVALID) 12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res->res.flags |= WPA_SCAN_QUAL_INVALID; 12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iwe->u.qual.updated & IW_QUAL_LEVEL_INVALID) 12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res->res.flags |= WPA_SCAN_LEVEL_INVALID; 12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iwe->u.qual.updated & IW_QUAL_NOISE_INVALID) 12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res->res.flags |= WPA_SCAN_NOISE_INVALID; 12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iwe->u.qual.updated & IW_QUAL_DBM) 12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res->res.flags |= WPA_SCAN_LEVEL_DBM; 12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((iwe->u.qual.updated & IW_QUAL_DBM) || 12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ((iwe->u.qual.level != 0) && 12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (iwe->u.qual.level > drv->max_level))) { 12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iwe->u.qual.level >= 64) 12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res->res.level -= 0x100; 12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iwe->u.qual.noise >= 64) 12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res->res.noise -= 0x100; 12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wext_get_scan_encode(struct iw_event *iwe, 12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wext_scan_data *res) 12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!(iwe->u.data.flags & IW_ENCODE_DISABLED)) 12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res->res.caps |= IEEE80211_CAP_PRIVACY; 12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wext_get_scan_rate(struct iw_event *iwe, 12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wext_scan_data *res, char *pos, 12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *end) 12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int maxrate; 12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *custom = pos + IW_EV_LCP_LEN; 12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iw_param p; 12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t clen; 12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt clen = iwe->len; 12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (custom + clen > end) 12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt maxrate = 0; 12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (((ssize_t) clen) >= (ssize_t) sizeof(struct iw_param)) { 12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Note: may be misaligned, make a local, aligned copy */ 12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&p, custom, sizeof(struct iw_param)); 12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (p.value > maxrate) 12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt maxrate = p.value; 12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt clen -= sizeof(struct iw_param); 12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt custom += sizeof(struct iw_param); 12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Convert the maxrate from WE-style (b/s units) to 12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 802.11 rates (500000 b/s units). 12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res->maxrate = maxrate / 500000; 12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wext_get_scan_iwevgenie(struct iw_event *iwe, 12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wext_scan_data *res, char *custom, 12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *end) 12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *genie, *gpos, *gend; 12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *tmp; 12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iwe->u.data.length == 0) 12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gpos = genie = custom; 13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gend = genie + iwe->u.data.length; 13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (gend > end) { 13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IWEVGENIE overflow"); 13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp = os_realloc(res->ie, res->ie_len + gend - gpos); 13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tmp == NULL) 13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(tmp + res->ie_len, gpos, gend - gpos); 13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res->ie = tmp; 13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res->ie_len += gend - gpos; 13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wext_get_scan_custom(struct iw_event *iwe, 13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wext_scan_data *res, char *custom, 13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *end) 13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t clen; 13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *tmp; 13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt clen = iwe->u.data.length; 13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (custom + clen > end) 13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (clen > 7 && os_strncmp(custom, "wpa_ie=", 7) == 0) { 13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *spos; 13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int bytes; 13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt spos = custom + 7; 13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bytes = custom + clen - spos; 13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bytes & 1 || bytes == 0) 13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bytes /= 2; 13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp = os_realloc(res->ie, res->ie_len + bytes); 13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tmp == NULL) 13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res->ie = tmp; 13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hexstr2bin(spos, tmp + res->ie_len, bytes) < 0) 13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res->ie_len += bytes; 13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (clen > 7 && os_strncmp(custom, "rsn_ie=", 7) == 0) { 13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *spos; 13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int bytes; 13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt spos = custom + 7; 13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bytes = custom + clen - spos; 13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bytes & 1 || bytes == 0) 13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bytes /= 2; 13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp = os_realloc(res->ie, res->ie_len + bytes); 13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tmp == NULL) 13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res->ie = tmp; 13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hexstr2bin(spos, tmp + res->ie_len, bytes) < 0) 13568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res->ie_len += bytes; 13588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (clen > 4 && os_strncmp(custom, "tsf=", 4) == 0) { 13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *spos; 13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int bytes; 13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 bin[8]; 13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt spos = custom + 4; 13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bytes = custom + clen - spos; 13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bytes != 16) { 13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "Invalid TSF length (%d)", bytes); 13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bytes /= 2; 13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hexstr2bin(spos, bin, bytes) < 0) { 13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WEXT: Invalid TSF value"); 13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res->res.tsf += WPA_GET_BE64(bin); 13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wext_19_iw_point(struct wpa_driver_wext_data *drv, u16 cmd) 13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return drv->we_version_compiled > 18 && 13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (cmd == SIOCGIWESSID || cmd == SIOCGIWENCODE || 13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cmd == IWEVGENIE || cmd == IWEVCUSTOM); 13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_wext_add_scan_entry(struct wpa_scan_results *res, 13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wext_scan_data *data) 13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_res **tmp; 13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_res *r; 13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t extra_len; 13928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos, *end, *ssid_ie = NULL, *rate_ie = NULL; 13938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Figure out whether we need to fake any IEs */ 13958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = data->ie; 13968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = pos + data->ie_len; 13978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pos && pos + 1 < end) { 13988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos + 2 + pos[1] > end) 13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 14008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos[0] == WLAN_EID_SSID) 14018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid_ie = pos; 14028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (pos[0] == WLAN_EID_SUPP_RATES) 14038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rate_ie = pos; 14048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (pos[0] == WLAN_EID_EXT_SUPP_RATES) 14058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rate_ie = pos; 14068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 + pos[1]; 14078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt extra_len = 0; 14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid_ie == NULL) 14118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt extra_len += 2 + data->ssid_len; 14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rate_ie == NULL && data->maxrate) 14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt extra_len += 3; 14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt r = os_zalloc(sizeof(*r) + extra_len + data->ie_len); 14168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (r == NULL) 14178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 14188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(r, &data->res, sizeof(*r)); 14198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt r->ie_len = extra_len + data->ie_len; 14208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (r + 1); 14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid_ie == NULL) { 14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 14238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Generate a fake SSID IE since the driver did not report 14248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * a full IE list. 14258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 14268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = WLAN_EID_SSID; 14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = data->ssid_len; 14288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, data->ssid, data->ssid_len); 14298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += data->ssid_len; 14308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rate_ie == NULL && data->maxrate) { 14328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 14338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Generate a fake Supported Rates IE since the driver did not 14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * report a full IE list. 14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 14368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = WLAN_EID_SUPP_RATES; 14378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 1; 14388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = data->maxrate; 14398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->ie) 14418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, data->ie, data->ie_len); 14428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp = os_realloc(res->res, 14448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (res->num + 1) * sizeof(struct wpa_scan_res *)); 14458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tmp == NULL) { 14468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(r); 14478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 14488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp[res->num++] = r; 14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res->res = tmp; 14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 14558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_driver_wext_get_scan_results - Fetch the latest scan results 14568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @priv: Pointer to private wext data from wpa_driver_wext_init() 14578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Scan results on success, -1 on failure 14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_scan_results * wpa_driver_wext_get_scan_results(void *priv) 14608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_wext_data *drv = priv; 14621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt size_t len; 14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int first; 14648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *res_buf; 14658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iw_event iwe_buf, *iwe = &iwe_buf; 14668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *pos, *end, *custom; 14678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_results *res; 14688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wext_scan_data data; 14698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res_buf = wpa_driver_wext_giwscan(drv, &len); 14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res_buf == NULL) 14728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt first = 1; 14758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = os_zalloc(sizeof(*res)); 14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == NULL) { 14788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(res_buf); 14798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 14808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (char *) res_buf; 14838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = (char *) res_buf + len; 14848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&data, 0, sizeof(data)); 14858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pos + IW_EV_LCP_LEN <= end) { 14878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Event data may be unaligned, so make a local, aligned copy 14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * before processing. */ 14898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&iwe_buf, pos, IW_EV_LCP_LEN); 14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iwe->len <= IW_EV_LCP_LEN) 14918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 14928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt custom = pos + IW_EV_POINT_LEN; 14948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wext_19_iw_point(drv, iwe->cmd)) { 14958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* WE-19 removed the pointer from struct iw_point */ 14968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *dpos = (char *) &iwe_buf.u.data.length; 14978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int dlen = dpos - (char *) &iwe_buf; 14988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(dpos, pos + IW_EV_LCP_LEN, 14998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(struct iw_event) - dlen); 15008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 15018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&iwe_buf, pos, sizeof(struct iw_event)); 15028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt custom += IW_EV_POINT_OFF; 15038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (iwe->cmd) { 15068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SIOCGIWAP: 15078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!first) 15088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_wext_add_scan_entry(res, &data); 15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt first = 0; 15108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data.ie); 15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&data, 0, sizeof(data)); 15128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data.res.bssid, 15138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwe->u.ap_addr.sa_data, ETH_ALEN); 15148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 15158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SIOCGIWMODE: 15168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wext_get_scan_mode(iwe, &data); 15178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 15188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SIOCGIWESSID: 15198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wext_get_scan_ssid(iwe, &data, custom, end); 15208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 15218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SIOCGIWFREQ: 15228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wext_get_scan_freq(iwe, &data); 15238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 15248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IWEVQUAL: 15258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wext_get_scan_qual(drv, iwe, &data); 15268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 15278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SIOCGIWENCODE: 15288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wext_get_scan_encode(iwe, &data); 15298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 15308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SIOCGIWRATE: 15318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wext_get_scan_rate(iwe, &data, pos, end); 15328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 15338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IWEVGENIE: 15348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wext_get_scan_iwevgenie(iwe, &data, custom, end); 15358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 15368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IWEVCUSTOM: 15378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wext_get_scan_custom(iwe, &data, custom, end); 15388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 15398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += iwe->len; 15428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(res_buf); 15448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res_buf = NULL; 15458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!first) 15468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_wext_add_scan_entry(res, &data); 15478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data.ie); 15488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Received %lu bytes of scan results (%lu BSSes)", 15508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) len, (unsigned long) res->num); 15518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return res; 15538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_wext_get_range(void *priv) 15578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_wext_data *drv = priv; 15598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iw_range *range; 15608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iwreq iwr; 15618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int minlen; 15628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t buflen; 15638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 15658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Use larger buffer than struct iw_range in order to allow the 15668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * structure to grow in the future. 15678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 15688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buflen = sizeof(struct iw_range) + 500; 15698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt range = os_zalloc(buflen); 15708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (range == NULL) 15718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 15728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&iwr, 0, sizeof(iwr)); 15748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 15758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.data.pointer = (caddr_t) range; 15768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.data.length = buflen; 15778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt minlen = ((char *) &range->enc_capa) - (char *) range + 15798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(range->enc_capa); 15808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) { 15828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("ioctl[SIOCGIWRANGE]"); 15838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(range); 15848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 15858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (iwr.u.data.length >= minlen && 15868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt range->we_version_compiled >= 18) { 15878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: WE(compiled)=%d " 15888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WE(source)=%d enc_capa=0x%x", 15898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt range->we_version_compiled, 15908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt range->we_version_source, 15918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt range->enc_capa); 15928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->has_capability = 1; 15938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->we_version_compiled = range->we_version_compiled; 15948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (range->enc_capa & IW_ENC_CAPA_WPA) { 15958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA | 15968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK; 15978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (range->enc_capa & IW_ENC_CAPA_WPA2) { 15998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | 16008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK; 16018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 | 16038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_DRIVER_CAPA_ENC_WEP104; 160404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP128; 16058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (range->enc_capa & IW_ENC_CAPA_CIPHER_TKIP) 16068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP; 16078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (range->enc_capa & IW_ENC_CAPA_CIPHER_CCMP) 16088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP; 16098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (range->enc_capa & IW_ENC_CAPA_4WAY_HANDSHAKE) 16108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->capa.flags |= WPA_DRIVER_FLAGS_4WAY_HANDSHAKE; 16118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->capa.auth = WPA_DRIVER_AUTH_OPEN | 16128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_DRIVER_AUTH_SHARED | 16138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_DRIVER_AUTH_LEAP; 1614886c3ff164ee2c0e281f4b1f31ce2b00f045f9deDmitry Shmidt#ifdef ANDROID 1615886c3ff164ee2c0e281f4b1f31ce2b00f045f9deDmitry Shmidt drv->capa.max_scan_ssids = WEXT_CSCAN_AMOUNT; 1616886c3ff164ee2c0e281f4b1f31ce2b00f045f9deDmitry Shmidt#else 16178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->capa.max_scan_ssids = 1; 1618886c3ff164ee2c0e281f4b1f31ce2b00f045f9deDmitry Shmidt#endif 16198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " capabilities: key_mgmt 0x%x enc 0x%x " 16218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "flags 0x%x", 16228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->capa.key_mgmt, drv->capa.enc, drv->capa.flags); 16238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 16248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: too old (short) data - " 16258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "assuming WPA is not supported"); 16268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->max_level = range->max_qual.level; 16298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(range); 16318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 16328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 16338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_wext_set_psk(struct wpa_driver_wext_data *drv, 16368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *psk) 16378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 16388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iw_encode_ext *ext; 16398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iwreq iwr; 16408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 16418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); 16438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!(drv->capa.flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE)) 16458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 16468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!psk) 16488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 16498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&iwr, 0, sizeof(iwr)); 16518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 16528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ext = os_zalloc(sizeof(*ext) + PMK_LEN); 16548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ext == NULL) 16558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 16568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.encoding.pointer = (caddr_t) ext; 16588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.encoding.length = sizeof(*ext) + PMK_LEN; 16598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ext->key_len = PMK_LEN; 16608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&ext->key, psk, ext->key_len); 16618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ext->alg = IW_ENCODE_ALG_PMK; 16628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = ioctl(drv->ioctl_sock, SIOCSIWENCODEEXT, &iwr); 16648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) 16658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("ioctl[SIOCSIWENCODEEXT] PMK"); 16668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ext); 16678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 16698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 16708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_wext_set_key_ext(void *priv, enum wpa_alg alg, 16738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr, int key_idx, 16748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int set_tx, const u8 *seq, 16758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t seq_len, 16768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *key, size_t key_len) 16778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 16788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_wext_data *drv = priv; 16798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iwreq iwr; 16808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0; 16818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iw_encode_ext *ext; 16828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (seq_len > IW_ENCODE_SEQ_MAX_SIZE) { 16848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: Invalid seq_len %lu", 16858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __FUNCTION__, (unsigned long) seq_len); 16868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 16878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ext = os_zalloc(sizeof(*ext) + key_len); 16908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ext == NULL) 16918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 16928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&iwr, 0, sizeof(iwr)); 16938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 16948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.encoding.flags = key_idx + 1; 16958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.encoding.flags |= IW_ENCODE_TEMP; 16968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (alg == WPA_ALG_NONE) 16978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.encoding.flags |= IW_ENCODE_DISABLED; 16988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.encoding.pointer = (caddr_t) ext; 16998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.encoding.length = sizeof(*ext) + key_len; 17008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (addr == NULL || is_broadcast_ether_addr(addr)) 17028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ext->ext_flags |= IW_ENCODE_EXT_GROUP_KEY; 17038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (set_tx) 17048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ext->ext_flags |= IW_ENCODE_EXT_SET_TX_KEY; 17058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ext->addr.sa_family = ARPHRD_ETHER; 17078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (addr) 17088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ext->addr.sa_data, addr, ETH_ALEN); 17098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 17108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(ext->addr.sa_data, 0xff, ETH_ALEN); 17118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key && key_len) { 17128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ext + 1, key, key_len); 17138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ext->key_len = key_len; 17148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (alg) { 17168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_ALG_NONE: 17178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ext->alg = IW_ENCODE_ALG_NONE; 17188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 17198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_ALG_WEP: 17208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ext->alg = IW_ENCODE_ALG_WEP; 17218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 17228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_ALG_TKIP: 17238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ext->alg = IW_ENCODE_ALG_TKIP; 17248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 17258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_ALG_CCMP: 17268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ext->alg = IW_ENCODE_ALG_CCMP; 17278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 17288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_ALG_PMK: 17298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ext->alg = IW_ENCODE_ALG_PMK; 17308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 17318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 17328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_ALG_IGTK: 17338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ext->alg = IW_ENCODE_ALG_AES_CMAC; 17348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 17358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 17368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 17378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: Unknown algorithm %d", 17388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __FUNCTION__, alg); 17398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ext); 17408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 17418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (seq && seq_len) { 17448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ext->ext_flags |= IW_ENCODE_EXT_RX_SEQ_VALID; 17458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ext->rx_seq, seq, seq_len); 17468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ioctl(drv->ioctl_sock, SIOCSIWENCODEEXT, &iwr) < 0) { 17498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = errno == EOPNOTSUPP ? -2 : -1; 17508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (errno == ENODEV) { 17518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 17528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ndiswrapper seems to be returning incorrect error 17538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * code.. */ 17548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -2; 17558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("ioctl[SIOCSIWENCODEEXT]"); 17588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ext); 17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 17638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 17668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_driver_wext_set_key - Configure encryption key 17678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @priv: Pointer to private wext data from wpa_driver_wext_init() 17688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @priv: Private driver interface data 17698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @alg: Encryption algorithm (%WPA_ALG_NONE, %WPA_ALG_WEP, 17708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * %WPA_ALG_TKIP, %WPA_ALG_CCMP); %WPA_ALG_NONE clears the key. 17718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: Address of the peer STA or ff:ff:ff:ff:ff:ff for 17728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * broadcast/default keys 17738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key_idx: key index (0..3), usually 0 for unicast keys 17748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @set_tx: Configure this key as the default Tx key (only used when 17758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * driver does not support separate unicast/individual key 17768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @seq: Sequence number/packet number, seq_len octets, the next 17778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * packet number to be used for in replay protection; configured 17788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * for Rx keys (in most cases, this is only used with broadcast 17798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * keys and set to zero for unicast keys) 17808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @seq_len: Length of the seq, depends on the algorithm: 17818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TKIP: 6 octets, CCMP: 6 octets 17828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key: Key buffer; TKIP: 16-byte temporal key, 8-byte Tx Mic key, 17838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 8-byte Rx Mic Key 17848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key_len: Length of the key buffer in octets (WEP: 5 or 13, 17858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TKIP: 32, CCMP: 16) 17868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 17878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 17888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function uses SIOCSIWENCODEEXT by default, but tries to use 17898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * SIOCSIWENCODE if the extended ioctl fails when configuring a WEP key. 17908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 17918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_driver_wext_set_key(const char *ifname, void *priv, enum wpa_alg alg, 17928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr, int key_idx, 17938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int set_tx, const u8 *seq, size_t seq_len, 17948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *key, size_t key_len) 17958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 17968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_wext_data *drv = priv; 17978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iwreq iwr; 17988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0; 17998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: alg=%d key_idx=%d set_tx=%d seq_len=%lu " 18018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "key_len=%lu", 18028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __FUNCTION__, alg, key_idx, set_tx, 18038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) seq_len, (unsigned long) key_len); 18048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = wpa_driver_wext_set_key_ext(drv, alg, addr, key_idx, set_tx, 18068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt seq, seq_len, key, key_len); 18078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret == 0) 18088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 18098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret == -2 && 18118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (alg == WPA_ALG_NONE || alg == WPA_ALG_WEP)) { 18128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Driver did not support " 18138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "SIOCSIWENCODEEXT, trying SIOCSIWENCODE"); 18148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 0; 18158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 18168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Driver did not support " 18178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "SIOCSIWENCODEEXT"); 18188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 18198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&iwr, 0, sizeof(iwr)); 18228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 18238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.encoding.flags = key_idx + 1; 18248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.encoding.flags |= IW_ENCODE_TEMP; 18258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (alg == WPA_ALG_NONE) 18268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.encoding.flags |= IW_ENCODE_DISABLED; 18278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.encoding.pointer = (caddr_t) key; 18288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.encoding.length = key_len; 18298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) { 18318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("ioctl[SIOCSIWENCODE]"); 18328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 18338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (set_tx && alg != WPA_ALG_NONE) { 18368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&iwr, 0, sizeof(iwr)); 18378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 18388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.encoding.flags = key_idx + 1; 18398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.encoding.flags |= IW_ENCODE_TEMP; 18408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.encoding.pointer = (caddr_t) NULL; 18418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.encoding.length = 0; 18428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) { 18438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("ioctl[SIOCSIWENCODE] (set_tx)"); 18448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 18458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 18498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_wext_set_countermeasures(void *priv, 18538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int enabled) 18548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_wext_data *drv = priv; 18568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); 18578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_driver_wext_set_auth_param(drv, 18588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IW_AUTH_TKIP_COUNTERMEASURES, 18598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enabled); 18608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_wext_set_drop_unencrypted(void *priv, 18648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int enabled) 18658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_wext_data *drv = priv; 18678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); 18688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->use_crypt = enabled; 18698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_driver_wext_set_auth_param(drv, IW_AUTH_DROP_UNENCRYPTED, 18708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enabled); 18718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_wext_mlme(struct wpa_driver_wext_data *drv, 18758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr, int cmd, int reason_code) 18768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iwreq iwr; 18788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iw_mlme mlme; 18798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0; 18808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&iwr, 0, sizeof(iwr)); 18828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 18838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&mlme, 0, sizeof(mlme)); 18848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mlme.cmd = cmd; 18858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mlme.reason_code = reason_code; 18868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mlme.addr.sa_family = ARPHRD_ETHER; 18878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(mlme.addr.sa_data, addr, ETH_ALEN); 18888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.data.pointer = (caddr_t) &mlme; 18898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.data.length = sizeof(mlme); 18908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ioctl(drv->ioctl_sock, SIOCSIWMLME, &iwr) < 0) { 18928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("ioctl[SIOCSIWMLME]"); 18938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 18948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 18978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_wext_disconnect(struct wpa_driver_wext_data *drv) 19018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iwreq iwr; 19038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 null_bssid[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; 19041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifndef ANDROID 19058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ssid[32]; 19068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 19071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* ANDROID */ 19088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 19108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Only force-disconnect when the card is in infrastructure mode, 19118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * otherwise the driver might interpret the cleared BSSID and random 19128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * SSID as an attempt to create a new ad-hoc network. 19138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 19148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&iwr, 0, sizeof(iwr)); 19158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 19168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ioctl(drv->ioctl_sock, SIOCGIWMODE, &iwr) < 0) { 19178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("ioctl[SIOCGIWMODE]"); 19188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.mode = IW_MODE_INFRA; 19198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iwr.u.mode == IW_MODE_INFRA) { 19221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* Clear the BSSID selection */ 19231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_driver_wext_set_bssid(drv, null_bssid) < 0) { 19241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "WEXT: Failed to clear BSSID " 19251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "selection on disconnect"); 19261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 19271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 19281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifndef ANDROID 19298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->cfg80211) { 19308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 19318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * cfg80211 supports SIOCSIWMLME commands, so there is 19328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * no need for the random SSID hack, but clear the 19331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * SSID. 19348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 19351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_driver_wext_set_ssid(drv, (u8 *) "", 0) < 0) { 19368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WEXT: Failed to clear " 19371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "SSID on disconnect"); 19388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 19408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 19428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 19431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Set a random SSID to make sure the driver will not be trying 19441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * to associate with something even if it does not understand 19451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * SIOCSIWMLME commands (or tries to associate automatically 19461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * after deauth/disassoc). 19478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 19488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < 32; i++) 19498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid[i] = rand() & 0xFF; 19501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_driver_wext_set_ssid(drv, ssid, 32) < 0) { 19518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WEXT: Failed to set bogus " 19521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "SSID to disconnect"); 19538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* ANDROID */ 19558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 19578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_wext_deauthenticate(void *priv, const u8 *addr, 19608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int reason_code) 19618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_wext_data *drv = priv; 19638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 19648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); 19658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = wpa_driver_wext_mlme(drv, addr, IW_MLME_DEAUTH, reason_code); 19668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_wext_disconnect(drv); 19678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 19688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 19698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_wext_disassociate(void *priv, const u8 *addr, 19728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int reason_code) 19738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_wext_data *drv = priv; 19758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 19768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); 19778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = wpa_driver_wext_mlme(drv, addr, IW_MLME_DISASSOC, reason_code); 19788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_wext_disconnect(drv); 19798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 19808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 19818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_wext_set_gen_ie(void *priv, const u8 *ie, 19848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t ie_len) 19858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_wext_data *drv = priv; 19878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iwreq iwr; 19888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0; 19898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&iwr, 0, sizeof(iwr)); 19918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 19928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.data.pointer = (caddr_t) ie; 19938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.data.length = ie_len; 19948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ioctl(drv->ioctl_sock, SIOCSIWGENIE, &iwr) < 0) { 19968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("ioctl[SIOCSIWGENIE]"); 19978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 19988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 20018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 20028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_driver_wext_cipher2wext(int cipher) 20058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 20068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (cipher) { 20078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CIPHER_NONE: 20088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return IW_AUTH_CIPHER_NONE; 20098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CIPHER_WEP40: 20108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return IW_AUTH_CIPHER_WEP40; 20118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CIPHER_TKIP: 20128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return IW_AUTH_CIPHER_TKIP; 20138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CIPHER_CCMP: 20148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return IW_AUTH_CIPHER_CCMP; 20158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CIPHER_WEP104: 20168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return IW_AUTH_CIPHER_WEP104; 20178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 20188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 20198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 20218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_driver_wext_keymgmt2wext(int keymgmt) 20248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 20258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (keymgmt) { 20268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case KEY_MGMT_802_1X: 20278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case KEY_MGMT_802_1X_NO_WPA: 20288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return IW_AUTH_KEY_MGMT_802_1X; 20298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case KEY_MGMT_PSK: 20308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return IW_AUTH_KEY_MGMT_PSK; 20318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 20328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 20338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 20358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int 20388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_driver_wext_auth_alg_fallback(struct wpa_driver_wext_data *drv, 20398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_associate_params *params) 20408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 20418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iwreq iwr; 20428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0; 20438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WEXT: Driver did not support " 20458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "SIOCSIWAUTH for AUTH_ALG, trying SIOCSIWENCODE"); 20468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&iwr, 0, sizeof(iwr)); 20488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 20498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Just changing mode, not actual keys */ 20508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.encoding.flags = 0; 20518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.encoding.pointer = (caddr_t) NULL; 20528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.encoding.length = 0; 20538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 20558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Note: IW_ENCODE_{OPEN,RESTRICTED} can be interpreted to mean two 20568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * different things. Here they are used to indicate Open System vs. 20578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Shared Key authentication algorithm. However, some drivers may use 20588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * them to select between open/restricted WEP encrypted (open = allow 20598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * both unencrypted and encrypted frames; restricted = only allow 20608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * encrypted frames). 20618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 20628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!drv->use_crypt) { 20648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.encoding.flags |= IW_ENCODE_DISABLED; 20658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 20668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->auth_alg & WPA_AUTH_ALG_OPEN) 20678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.encoding.flags |= IW_ENCODE_OPEN; 20688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->auth_alg & WPA_AUTH_ALG_SHARED) 20698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.encoding.flags |= IW_ENCODE_RESTRICTED; 20708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) { 20738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("ioctl[SIOCSIWENCODE]"); 20748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 20758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 20788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 20798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_driver_wext_associate(void *priv, 20828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_associate_params *params) 20838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 20848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_wext_data *drv = priv; 20858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0; 20868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int allow_unencrypted_eapol; 20878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int value; 20888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); 209029991f40caccd6c45cd7c56ca597f370a4f2b9ebDmitry Shmidt#ifdef ANDROID 209129991f40caccd6c45cd7c56ca597f370a4f2b9ebDmitry Shmidt drv->skip_disconnect = 0; 209229991f40caccd6c45cd7c56ca597f370a4f2b9ebDmitry Shmidt#endif 20938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->cfg80211) { 20948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 20958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Stop cfg80211 from trying to associate before we are done 20968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * with all parameters. 20978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 20988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_wext_set_ssid(drv, (u8 *) "", 0); 20998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_driver_wext_set_drop_unencrypted(drv, params->drop_unencrypted) 21028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt < 0) 21038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 21048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_driver_wext_set_auth_alg(drv, params->auth_alg) < 0) 21058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 21068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_driver_wext_set_mode(drv, params->mode) < 0) 21078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 21088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 21108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * If the driver did not support SIOCSIWAUTH, fallback to 21118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * SIOCSIWENCODE here. 21128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 21138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->auth_alg_fallback && 21148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_wext_auth_alg_fallback(drv, params) < 0) 21158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 21168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!params->bssid && 21188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_wext_set_bssid(drv, NULL) < 0) 21198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 21208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: should consider getting wpa version and cipher/key_mgmt suites 21228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * from configuration, not from here, where only the selected suite is 21238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * available */ 21248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_driver_wext_set_gen_ie(drv, params->wpa_ie, params->wpa_ie_len) 21258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt < 0) 21268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 21278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->wpa_ie == NULL || params->wpa_ie_len == 0) 21288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt value = IW_AUTH_WPA_VERSION_DISABLED; 21298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (params->wpa_ie[0] == WLAN_EID_RSN) 21308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt value = IW_AUTH_WPA_VERSION_WPA2; 21318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 21328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt value = IW_AUTH_WPA_VERSION_WPA; 21338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_driver_wext_set_auth_param(drv, 21348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IW_AUTH_WPA_VERSION, value) < 0) 21358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 21368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt value = wpa_driver_wext_cipher2wext(params->pairwise_suite); 21378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_driver_wext_set_auth_param(drv, 21388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IW_AUTH_CIPHER_PAIRWISE, value) < 0) 21398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 21408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt value = wpa_driver_wext_cipher2wext(params->group_suite); 21418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_driver_wext_set_auth_param(drv, 21428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IW_AUTH_CIPHER_GROUP, value) < 0) 21438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 21448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt value = wpa_driver_wext_keymgmt2wext(params->key_mgmt_suite); 21458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_driver_wext_set_auth_param(drv, 21468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IW_AUTH_KEY_MGMT, value) < 0) 21478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 21488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt value = params->key_mgmt_suite != KEY_MGMT_NONE || 21498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->pairwise_suite != CIPHER_NONE || 21508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->group_suite != CIPHER_NONE || 21518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->wpa_ie_len; 21528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_driver_wext_set_auth_param(drv, 21538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IW_AUTH_PRIVACY_INVOKED, value) < 0) 21548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 21558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Allow unencrypted EAPOL messages even if pairwise keys are set when 21578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * not using WPA. IEEE 802.1X specifies that these frames are not 21588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * encrypted, but WPA encrypts them when pairwise keys are in use. */ 21598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->key_mgmt_suite == KEY_MGMT_802_1X || 21608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->key_mgmt_suite == KEY_MGMT_PSK) 21618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt allow_unencrypted_eapol = 0; 21628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 21638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt allow_unencrypted_eapol = 1; 21648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_driver_wext_set_psk(drv, params->psk) < 0) 21668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 21678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_driver_wext_set_auth_param(drv, 21688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IW_AUTH_RX_UNENCRYPTED_EAPOL, 21698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt allow_unencrypted_eapol) < 0) 21708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 21718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 21728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (params->mgmt_frame_protection) { 21738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NO_MGMT_FRAME_PROTECTION: 21748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt value = IW_AUTH_MFP_DISABLED; 21758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 21768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case MGMT_FRAME_PROTECTION_OPTIONAL: 21778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt value = IW_AUTH_MFP_OPTIONAL; 21788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 21798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case MGMT_FRAME_PROTECTION_REQUIRED: 21808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt value = IW_AUTH_MFP_REQUIRED; 21818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 21828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 21838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_driver_wext_set_auth_param(drv, IW_AUTH_MFP, value) < 0) 21848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 21858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 21868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->freq && wpa_driver_wext_set_freq(drv, params->freq) < 0) 21878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 21888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!drv->cfg80211 && 21898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_wext_set_ssid(drv, params->ssid, params->ssid_len) < 0) 21908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 21918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->bssid && 21928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_wext_set_bssid(drv, params->bssid) < 0) 21938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 21948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->cfg80211 && 21958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_wext_set_ssid(drv, params->ssid, params->ssid_len) < 0) 21968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 21978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 21998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 22008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_wext_set_auth_alg(void *priv, int auth_alg) 22038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 22048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_wext_data *drv = priv; 22058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int algs = 0, res; 22068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (auth_alg & WPA_AUTH_ALG_OPEN) 22088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt algs |= IW_AUTH_ALG_OPEN_SYSTEM; 22098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (auth_alg & WPA_AUTH_ALG_SHARED) 22108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt algs |= IW_AUTH_ALG_SHARED_KEY; 22118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (auth_alg & WPA_AUTH_ALG_LEAP) 22128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt algs |= IW_AUTH_ALG_LEAP; 22138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (algs == 0) { 22148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* at least one algorithm should be set */ 22158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt algs = IW_AUTH_ALG_OPEN_SYSTEM; 22168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = wpa_driver_wext_set_auth_param(drv, IW_AUTH_80211_AUTH_ALG, 22198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt algs); 22208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->auth_alg_fallback = res == -2; 22218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return res; 22228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 22238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 22268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_driver_wext_set_mode - Set wireless mode (infra/adhoc), SIOCSIWMODE 22278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @priv: Pointer to private wext data from wpa_driver_wext_init() 22288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @mode: 0 = infra/BSS (associate with an AP), 1 = adhoc/IBSS 22298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 22308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 22318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_driver_wext_set_mode(void *priv, int mode) 22328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 22338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_wext_data *drv = priv; 22348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iwreq iwr; 22358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = -1; 22368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int new_mode = mode ? IW_MODE_ADHOC : IW_MODE_INFRA; 22378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&iwr, 0, sizeof(iwr)); 22398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 22408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.mode = new_mode; 22418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) == 0) { 22428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 0; 22438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto done; 22448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (errno != EBUSY) { 22478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("ioctl[SIOCSIWMODE]"); 22488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto done; 22498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* mac80211 doesn't allow mode changes while the device is up, so if 22528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the device isn't in the mode we're about to change to, take device 22538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * down, try to set the mode again, and bring it back up. 22548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 22558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ioctl(drv->ioctl_sock, SIOCGIWMODE, &iwr) < 0) { 22568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("ioctl[SIOCGIWMODE]"); 22578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto done; 22588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iwr.u.mode == new_mode) { 22618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 0; 22628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto done; 22638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 0) == 0) { 22668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Try to set the mode again while the interface is down */ 22678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.mode = new_mode; 22688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0) 22698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("ioctl[SIOCSIWMODE]"); 22708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 22718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 0; 22728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (void) linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1); 22748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtdone: 22778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 22788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 22798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_wext_pmksa(struct wpa_driver_wext_data *drv, 22828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 cmd, const u8 *bssid, const u8 *pmkid) 22838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 22848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iwreq iwr; 22858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iw_pmksa pmksa; 22868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0; 22878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&iwr, 0, sizeof(iwr)); 22898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 22908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&pmksa, 0, sizeof(pmksa)); 22918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa.cmd = cmd; 22928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa.bssid.sa_family = ARPHRD_ETHER; 22938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bssid) 22948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pmksa.bssid.sa_data, bssid, ETH_ALEN); 22958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pmkid) 22968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pmksa.pmkid, pmkid, IW_PMKID_LEN); 22978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.data.pointer = (caddr_t) &pmksa; 22988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iwr.u.data.length = sizeof(pmksa); 22998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ioctl(drv->ioctl_sock, SIOCSIWPMKSA, &iwr) < 0) { 23018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (errno != EOPNOTSUPP) 23028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("ioctl[SIOCSIWPMKSA]"); 23038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 23048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 23078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 23088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_wext_add_pmkid(void *priv, const u8 *bssid, 23118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pmkid) 23128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 23138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_wext_data *drv = priv; 23148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_driver_wext_pmksa(drv, IW_PMKSA_ADD, bssid, pmkid); 23158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 23168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_wext_remove_pmkid(void *priv, const u8 *bssid, 23198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pmkid) 23208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 23218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_wext_data *drv = priv; 23228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_driver_wext_pmksa(drv, IW_PMKSA_REMOVE, bssid, pmkid); 23238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 23248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_wext_flush_pmkid(void *priv) 23278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 23288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_wext_data *drv = priv; 23298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_driver_wext_pmksa(drv, IW_PMKSA_FLUSH, NULL, NULL); 23308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 23318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_driver_wext_get_capa(void *priv, struct wpa_driver_capa *capa) 23348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 23358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_wext_data *drv = priv; 23368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!drv->has_capability) 23378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 23388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(capa, &drv->capa, sizeof(*capa)); 23398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 23408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 23418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_driver_wext_alternative_ifindex(struct wpa_driver_wext_data *drv, 23448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *ifname) 23458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 23468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ifname == NULL) { 23478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->ifindex2 = -1; 23488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 23498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->ifindex2 = if_nametoindex(ifname); 23528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->ifindex2 <= 0) 23538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 23548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Added alternative ifindex %d (%s) for " 23568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "wireless events", drv->ifindex2, ifname); 23578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 23598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 23608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_driver_wext_set_operstate(void *priv, int state) 23638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 23648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_wext_data *drv = priv; 23658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: operstate %d->%d (%s)", 23678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, drv->operstate, state, state ? "UP" : "DORMANT"); 23688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->operstate = state; 23698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return netlink_send_oper_ifla(drv->netlink, drv->ifindex, -1, 23708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt state ? IF_OPER_UP : IF_OPER_DORMANT); 23718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 23728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_driver_wext_get_version(struct wpa_driver_wext_data *drv) 23758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 23768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return drv->we_version_compiled; 23778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 23788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * wext_get_radio_name(void *priv) 23818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 23828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_wext_data *drv = priv; 23838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return drv->phyname; 23848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 23858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef ANDROID 23881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 23891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int android_wext_cmd(struct wpa_driver_wext_data *drv, const char *cmd) 23901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 23911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct iwreq iwr; 23921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt char buf[MAX_DRV_CMD_SIZE]; 23931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int ret; 23941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 23951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memset(&iwr, 0, sizeof(iwr)); 23961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 23971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 23981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memset(buf, 0, sizeof(buf)); 23991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_strlcpy(buf, cmd, sizeof(buf)); 24001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 24011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt iwr.u.data.pointer = buf; 24021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt iwr.u.data.length = sizeof(buf); 24031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 24041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ret = ioctl(drv->ioctl_sock, SIOCSIWPRIV, &iwr); 24051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 24061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ret < 0) { 24071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_ERROR, "%s failed (%d): %s", __func__, ret, 24081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt cmd); 24091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt drv->errors++; 24101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (drv->errors > DRV_NUMBER_SEQUENTIAL_ERRORS) { 24111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt drv->errors = 0; 24121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE 24131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "HANGED"); 24141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 24151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return ret; 24161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 24171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 24181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt drv->errors = 0; 24191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 24201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 24211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 24221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 24231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int wext_sched_scan(void *priv, struct wpa_driver_scan_params *params, 24241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u32 interval) 24251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 24261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_driver_wext_data *drv = priv; 24271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct iwreq iwr; 24281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int ret = 0, i = 0, bp; 24291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt char buf[WEXT_PNO_MAX_COMMAND_SIZE]; 24301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 24311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt bp = WEXT_PNOSETUP_HEADER_SIZE; 24321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(buf, WEXT_PNOSETUP_HEADER, bp); 24331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt buf[bp++] = WEXT_PNO_TLV_PREFIX; 24341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt buf[bp++] = WEXT_PNO_TLV_VERSION; 24351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt buf[bp++] = WEXT_PNO_TLV_SUBVERSION; 24361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt buf[bp++] = WEXT_PNO_TLV_RESERVED; 24371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 24381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt while (i < WEXT_PNO_AMOUNT && (size_t) i < params->num_ssids) { 24391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* 24401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Check that there is enough space needed for 1 more SSID, the 24411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * other sections and null termination. 24421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 24431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if ((bp + WEXT_PNO_SSID_HEADER_SIZE + IW_ESSID_MAX_SIZE + 24441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WEXT_PNO_NONSSID_SECTIONS_SIZE + 1) >= (int) sizeof(buf)) 24451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 24461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 24471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "For PNO Scan", 24481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt params->ssids[i].ssid, 24491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt params->ssids[i].ssid_len); 24501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt buf[bp++] = WEXT_PNO_SSID_SECTION; 24511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt buf[bp++] = params->ssids[i].ssid_len; 24521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(&buf[bp], params->ssids[i].ssid, 24531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt params->ssids[i].ssid_len); 24541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt bp += params->ssids[i].ssid_len; 24551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt i++; 24561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 24571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 24581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt buf[bp++] = WEXT_PNO_SCAN_INTERVAL_SECTION; 24591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* TODO: consider using interval parameter (interval in msec) instead 24601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * of hardcoded value here */ 24611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_snprintf(&buf[bp], WEXT_PNO_SCAN_INTERVAL_LENGTH + 1, "%x", 24621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WEXT_PNO_SCAN_INTERVAL); 24631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt bp += WEXT_PNO_SCAN_INTERVAL_LENGTH; 24641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 24651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt buf[bp++] = WEXT_PNO_REPEAT_SECTION; 24661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_snprintf(&buf[bp], WEXT_PNO_REPEAT_LENGTH + 1, "%x", 24671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WEXT_PNO_REPEAT); 24681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt bp += WEXT_PNO_REPEAT_LENGTH; 24691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 24701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt buf[bp++] = WEXT_PNO_MAX_REPEAT_SECTION; 24711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_snprintf(&buf[bp], WEXT_PNO_MAX_REPEAT_LENGTH + 1, "%x", 24721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WEXT_PNO_MAX_REPEAT); 24731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt bp += WEXT_PNO_MAX_REPEAT_LENGTH + 1; 24741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 24751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memset(&iwr, 0, sizeof(iwr)); 24761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 24771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt iwr.u.data.pointer = buf; 24781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt iwr.u.data.length = bp; 24791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 24801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ret = ioctl(drv->ioctl_sock, SIOCSIWPRIV, &iwr); 24811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ret < 0) { 24821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_ERROR, "ioctl[SIOCSIWPRIV] (pnosetup): %d", 24831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ret); 24841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt drv->errors++; 24851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (drv->errors > DRV_NUMBER_SEQUENTIAL_ERRORS) { 24861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt drv->errors = 0; 24871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_msg(drv->ctx, MSG_INFO, 24881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WPA_EVENT_DRIVER_STATE "HANGED"); 24891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 24901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return ret; 24911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 24921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 24931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt drv->errors = 0; 24941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt drv->bgscan_enabled = 1; 24951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 24961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return android_wext_cmd(drv, "PNOFORCE 1"); 24971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 24981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 24991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 25001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int wext_stop_sched_scan(void *priv) 25011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 25021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_driver_wext_data *drv = priv; 25031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt drv->bgscan_enabled = 0; 25041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return android_wext_cmd(drv, "PNOFORCE 0"); 25051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 25061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 25071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* ANDROID */ 25081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 25091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 25108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst struct wpa_driver_ops wpa_driver_wext_ops = { 25118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .name = "wext", 25128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .desc = "Linux wireless extensions (generic)", 25138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .get_bssid = wpa_driver_wext_get_bssid, 25148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .get_ssid = wpa_driver_wext_get_ssid, 25158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .set_key = wpa_driver_wext_set_key, 25168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .set_countermeasures = wpa_driver_wext_set_countermeasures, 25178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .scan2 = wpa_driver_wext_scan, 25188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .get_scan_results2 = wpa_driver_wext_get_scan_results, 25198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .deauthenticate = wpa_driver_wext_deauthenticate, 25208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .disassociate = wpa_driver_wext_disassociate, 25218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .associate = wpa_driver_wext_associate, 25228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .init = wpa_driver_wext_init, 25238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .deinit = wpa_driver_wext_deinit, 25248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .add_pmkid = wpa_driver_wext_add_pmkid, 25258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .remove_pmkid = wpa_driver_wext_remove_pmkid, 25268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .flush_pmkid = wpa_driver_wext_flush_pmkid, 25278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .get_capa = wpa_driver_wext_get_capa, 25288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .set_operstate = wpa_driver_wext_set_operstate, 25298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .get_radio_name = wext_get_radio_name, 2530886c3ff164ee2c0e281f4b1f31ce2b00f045f9deDmitry Shmidt#ifdef ANDROID 25311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt .sched_scan = wext_sched_scan, 25321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt .stop_sched_scan = wext_stop_sched_scan, 25331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* ANDROID */ 25348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 2535