From da3c29ee267409e9ae31bfd47a3821cef798435b Mon Sep 17 00:00:00 2001 From: Nicu Pavel Date: Mon, 25 Oct 2010 08:12:05 +0800 Subject: [PATCH] Added a separate driver awext to emulate Android driver commands Change-Id: I5e14cfc5dd16c9429387b5a5acc39c55edd2fa4e --- wpa_supplicant/Android.mk | 6 + wpa_supplicant/src/drivers/driver_awext.c | 913 ++++++++++++++++++++++++++++++ wpa_supplicant/src/drivers/driver_awext.h | 57 ++ wpa_supplicant/src/drivers/drivers.c | 6 + 4 files changed, 982 insertions(+) create mode 100644 wpa_supplicant/src/drivers/driver_awext.c create mode 100644 wpa_supplicant/src/drivers/driver_awext.h diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk index d3ab3dd..86e9445 100644 --- a/wpa_supplicant/Android.mk +++ b/wpa_supplicant/Android.mk @@ -144,6 +144,12 @@ OBJS_d += src/drivers/driver_hostap.c CONFIG_WIRELESS_EXTENSION=y endif +ifdef CONFIG_DRIVER_AWEXT +L_CFLAGS += -DCONFIG_DRIVER_AWEXT +OBJS_d += src/drivers/driver_awext.c +CONFIG_WIRELESS_EXTENSION=y +endif + ifdef CONFIG_DRIVER_WEXT L_CFLAGS += -DCONFIG_DRIVER_WEXT CONFIG_WIRELESS_EXTENSION=y diff --git a/wpa_supplicant/src/drivers/driver_awext.c b/wpa_supplicant/src/drivers/driver_awext.c new file mode 100644 index 0000000..a7c7c91 --- /dev/null +++ b/wpa_supplicant/src/drivers/driver_awext.c @@ -0,0 +1,913 @@ +/* + * WEXT Emulation for Android SIOCSIWPRIV ioctl with generic Linux Wireless Extensions + * Copyright (c) 2010, Nicu Pavel + * Copyright (c) 2003-2007, Jouni Malinen + * + * Code based on Jim Huang e9bd7cc3d137eb56ebd4220d4077563743ab6723 + * patch for 0xdroid + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + * + */ + +#include "includes.h" +#include +#include +#include + +#include "wireless_copy.h" +#include "common.h" +#include "driver.h" +#include "l2_packet.h" +#include "eloop.h" +#include "priv_netlink.h" +#include "driver_awext.h" +#include "wpa.h" +#include "wpa_ctrl.h" +#include "wpa_supplicant_i.h" +#include "config_ssid.h" + +#ifdef CONFIG_CLIENT_MLME +#include +#include +#include +/* from net/mac80211.h */ +enum { + MODE_IEEE80211A = 0 /* IEEE 802.11a */, + MODE_IEEE80211B = 1 /* IEEE 802.11b only */, + MODE_ATHEROS_TURBO = 2 /* Atheros Turbo mode (2x.11a at 5 GHz) */, + MODE_IEEE80211G = 3 /* IEEE 802.11g (and 802.11b compatibility) */, + MODE_ATHEROS_TURBOG = 4 /* Atheros Turbo mode (2x.11g at 2.4 GHz) */, + NUM_IEEE80211_MODES = 5 +}; + +#include "mlme.h" + +#ifndef ETH_P_ALL +#define ETH_P_ALL 0x0003 +#endif +#endif /* CONFIG_CLIENT_MLME */ + +struct wpa_driver_awext_data { + struct wpa_driver_wext_data *wext; /* structure for wext */ + u8 ssid[32]; + unsigned int ssid_len; +}; + +static int wpa_driver_awext_set_auth_param(struct wpa_driver_awext_data *drv, + int idx, u32 value) +{ + struct iwreq iwr; + int ret = 0; + + os_memset(&iwr, 0, sizeof(iwr)); + os_strncpy(iwr.ifr_name, drv->wext->ifname, IFNAMSIZ); + iwr.u.param.flags = idx & IW_AUTH_INDEX; + iwr.u.param.value = value; + + if (ioctl(drv->wext->ioctl_sock, SIOCSIWAUTH, &iwr) < 0) { + if (errno != EOPNOTSUPP) { + wpa_printf(MSG_DEBUG, "WEXT: SIOCSIWAUTH(param %d " + "value 0x%x) failed: %s)", + idx, value, strerror(errno)); + } + ret = errno == EOPNOTSUPP ? -2 : -1; + } + + return ret; +} + +static int wpa_driver_awext_set_auth_alg(void *priv, int auth_alg) +{ + struct wpa_driver_awext_data *drv = priv; + int algs = 0, res; + + if (auth_alg & AUTH_ALG_OPEN_SYSTEM) + algs |= IW_AUTH_ALG_OPEN_SYSTEM; + if (auth_alg & AUTH_ALG_SHARED_KEY) + algs |= IW_AUTH_ALG_SHARED_KEY; + if (auth_alg & AUTH_ALG_LEAP) + algs |= IW_AUTH_ALG_LEAP; + if (algs == 0) { + /* at least one algorithm should be set */ + algs = IW_AUTH_ALG_OPEN_SYSTEM; + } + + res = wpa_driver_awext_set_auth_param(drv, IW_AUTH_80211_AUTH_ALG, algs); + drv->wext->auth_alg_fallback = res == -2; + return res; +} + +static int wpa_driver_awext_set_gen_ie(void *priv, const u8 *ie, + size_t ie_len) +{ + struct wpa_driver_awext_data *drv = priv; + struct iwreq iwr; + int ret = 0; + + os_memset(&iwr, 0, sizeof(iwr)); + os_strncpy(iwr.ifr_name, drv->wext->ifname, IFNAMSIZ); + iwr.u.data.pointer = (caddr_t) ie; + iwr.u.data.length = ie_len; + + if (ioctl(drv->wext->ioctl_sock, SIOCSIWGENIE, &iwr) < 0) { + perror("ioctl[SIOCSIWGENIE]"); + ret = -1; + } + + return ret; +} + +static int wpa_driver_awext_cipher2wext(int cipher) +{ + switch (cipher) { + case CIPHER_NONE: + return IW_AUTH_CIPHER_NONE; + case CIPHER_WEP40: + return IW_AUTH_CIPHER_WEP40; + case CIPHER_TKIP: + return IW_AUTH_CIPHER_TKIP; + case CIPHER_CCMP: + return IW_AUTH_CIPHER_CCMP; + case CIPHER_WEP104: + return IW_AUTH_CIPHER_WEP104; + default: + return 0; + } +} + + +static int wpa_driver_awext_keymgmt2wext(int keymgmt) +{ + switch (keymgmt) { + case KEY_MGMT_802_1X: + case KEY_MGMT_802_1X_NO_WPA: + return IW_AUTH_KEY_MGMT_802_1X; + case KEY_MGMT_PSK: + return IW_AUTH_KEY_MGMT_PSK; + default: + return 0; + } +} + + +static int +wpa_driver_awext_auth_alg_fallback(struct wpa_driver_awext_data *drv, + struct wpa_driver_associate_params *params) +{ + struct iwreq iwr; + int ret = 0; + + wpa_printf(MSG_DEBUG, "WEXT: Driver did not support " + "SIOCSIWAUTH for AUTH_ALG, trying SIOCSIWENCODE"); + + os_memset(&iwr, 0, sizeof(iwr)); + os_strncpy(iwr.ifr_name, drv->wext->ifname, IFNAMSIZ); + /* Just changing mode, not actual keys */ + iwr.u.encoding.flags = 0; + iwr.u.encoding.pointer = (caddr_t) NULL; + iwr.u.encoding.length = 0; + + /* + * Note: IW_ENCODE_{OPEN,RESTRICTED} can be interpreted to mean two + * different things. Here they are used to indicate Open System vs. + * Shared Key authentication algorithm. However, some drivers may use + * them to select between open/restricted WEP encrypted (open = allow + * both unencrypted and encrypted frames; restricted = only allow + * encrypted frames). + */ + + if (!drv->wext->use_crypt) { + iwr.u.encoding.flags |= IW_ENCODE_DISABLED; + } else { + if (params->auth_alg & AUTH_ALG_OPEN_SYSTEM) + iwr.u.encoding.flags |= IW_ENCODE_OPEN; + if (params->auth_alg & AUTH_ALG_SHARED_KEY) + iwr.u.encoding.flags |= IW_ENCODE_RESTRICTED; + } + + if (ioctl(drv->wext->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) { + perror("ioctl[SIOCSIWENCODE]"); + ret = -1; + } + + return ret; +} + + + +static int +wpa_driver_awext_associate(void *priv, + struct wpa_driver_associate_params *params) +{ + struct wpa_driver_awext_data *drv = priv; + int ret = 0; + int allow_unencrypted_eapol; + int value, flags; + + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); + + if (wpa_driver_awext_get_ifflags(drv, &flags) == 0) { + if (!(flags & IFF_UP)) { + wpa_driver_awext_set_ifflags(drv, flags | IFF_UP); + } + } + + /* + * If the driver did not support SIOCSIWAUTH, fallback to + * SIOCSIWENCODE here. + */ + if (drv->wext->auth_alg_fallback && + wpa_driver_awext_auth_alg_fallback(drv, params) < 0) + ret = -1; + + if (!params->bssid && + wpa_driver_awext_set_bssid(drv, NULL) < 0) + ret = -1; + + if (wpa_driver_awext_set_mode(drv, params->mode) < 0) + ret = -1; + /* TODO: should consider getting wpa version and cipher/key_mgmt suites + * from configuration, not from here, where only the selected suite is + * available */ + if (wpa_driver_awext_set_gen_ie(drv, params->wpa_ie, params->wpa_ie_len) + < 0) + ret = -1; + if (params->wpa_ie == NULL || params->wpa_ie_len == 0) + value = IW_AUTH_WPA_VERSION_DISABLED; +// else if (params->wpa_ie[0] == RSN_INFO_ELEM) +// value = IW_AUTH_WPA_VERSION_WPA2; + else + value = IW_AUTH_WPA_VERSION_WPA; + if (wpa_driver_awext_set_auth_param(drv, + IW_AUTH_WPA_VERSION, value) < 0) + ret = -1; + value = wpa_driver_awext_cipher2wext(params->pairwise_suite); + if (wpa_driver_awext_set_auth_param(drv, + IW_AUTH_CIPHER_PAIRWISE, value) < 0) + ret = -1; + value = wpa_driver_awext_cipher2wext(params->group_suite); + if (wpa_driver_awext_set_auth_param(drv, + IW_AUTH_CIPHER_GROUP, value) < 0) + ret = -1; + value = wpa_driver_awext_keymgmt2wext(params->key_mgmt_suite); + if (wpa_driver_awext_set_auth_param(drv, + IW_AUTH_KEY_MGMT, value) < 0) + ret = -1; + value = params->key_mgmt_suite != KEY_MGMT_NONE || + params->pairwise_suite != CIPHER_NONE || + params->group_suite != CIPHER_NONE || + params->wpa_ie_len; + if (wpa_driver_awext_set_auth_param(drv, + IW_AUTH_PRIVACY_INVOKED, value) < 0) + ret = -1; + + /* Allow unencrypted EAPOL messages even if pairwise keys are set when + * not using WPA. IEEE 802.1X specifies that these frames are not + * encrypted, but WPA encrypts them when pairwise keys are in use. */ + if (params->key_mgmt_suite == KEY_MGMT_802_1X || + params->key_mgmt_suite == KEY_MGMT_PSK) + allow_unencrypted_eapol = 0; + else + allow_unencrypted_eapol = 1; + + if (wpa_driver_awext_set_auth_param(drv, + IW_AUTH_RX_UNENCRYPTED_EAPOL, + allow_unencrypted_eapol) < 0) + ret = -1; + if (params->freq && wpa_driver_awext_set_freq(drv, params->freq) < 0) + ret = -1; + if (wpa_driver_awext_set_ssid(drv, params->ssid, params->ssid_len) < 0) + ret = -1; + if (params->bssid && + wpa_driver_awext_set_bssid(drv, params->bssid) < 0) + ret = -1; + + return ret; +} + + +static int wpa_driver_awext_set_countermeasures(void *priv, + int enabled) +{ + struct wpa_driver_awext_data *drv = priv; + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); + return wpa_driver_awext_set_auth_param(drv, + IW_AUTH_TKIP_COUNTERMEASURES, + enabled); +} + +static int wpa_driver_awext_set_drop_unencrypted(void *priv, + int enabled) +{ + struct wpa_driver_awext_data *drv = priv; + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); + drv->wext->use_crypt = enabled; + return wpa_driver_awext_set_auth_param(drv, IW_AUTH_DROP_UNENCRYPTED, + enabled); +} + +static int wpa_driver_awext_mlme(struct wpa_driver_awext_data *drv, + const u8 *addr, int cmd, int reason_code) +{ + struct iwreq iwr; + struct iw_mlme mlme; + int ret = 0; + + os_memset(&iwr, 0, sizeof(iwr)); + os_strncpy(iwr.ifr_name, drv->wext->ifname, IFNAMSIZ); + os_memset(&mlme, 0, sizeof(mlme)); + mlme.cmd = cmd; + mlme.reason_code = reason_code; + mlme.addr.sa_family = ARPHRD_ETHER; + os_memcpy(mlme.addr.sa_data, addr, ETH_ALEN); + iwr.u.data.pointer = (caddr_t) &mlme; + iwr.u.data.length = sizeof(mlme); + + if (ioctl(drv->wext->ioctl_sock, SIOCSIWMLME, &iwr) < 0) { + perror("ioctl[SIOCSIWMLME]"); + ret = -1; + } + + return ret; +} +#ifdef CONFIG_CLIENT_MLME +static int wpa_driver_awext_open_mlme(struct wpa_driver_awext_data *drv) +{ + int flags, ifindex, s, *i; + struct sockaddr_ll addr; + struct iwreq iwr; + + os_memset(&iwr, 0, sizeof(iwr)); + os_strncpy(iwr.ifr_name, drv->wext->ifname, IFNAMSIZ); + i = (int *) iwr.u.name; + *i++ = PRISM2_PARAM_USER_SPACE_MLME; + *i++ = 1; + + if (ioctl(drv->wext->ioctl_sock, PRISM2_IOCTL_PRISM2_PARAM, &iwr) < 0) { + wpa_printf(MSG_ERROR, "WEXT: Failed to configure driver to " + "use user space MLME"); + return -1; + } + + ifindex = if_nametoindex(drv->wext->mlmedev); + if (ifindex == 0) { + wpa_printf(MSG_ERROR, "WEXT: mlmedev='%s' not found", + drv->mlmedev); + return -1; + } + + if (wpa_driver_awext_get_ifflags_ifname(drv, drv->wext->mlmedev, &flags) != 0 + || wpa_driver_awext_set_ifflags_ifname(drv, drv->wext->mlmedev, + flags | IFF_UP) != 0) { + wpa_printf(MSG_ERROR, "WEXT: Could not set interface " + "'%s' UP", drv->mlmedev); + return -1; + } + + s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); + if (s < 0) { + perror("socket[PF_PACKET,SOCK_RAW]"); + return -1; + } + + os_memset(&addr, 0, sizeof(addr)); + addr.sll_family = AF_PACKET; + addr.sll_ifindex = ifindex; + + if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + perror("bind(MLME)"); + return -1; + } + + if (eloop_register_read_sock(s, wpa_driver_awext_mlme_read, drv, NULL)) + { + wpa_printf(MSG_ERROR, "WEXT: Could not register MLME read " + "socket"); + close(s); + return -1; + } + + return s; +} + + +#endif /* CONFIG_CLIENT_MLME */ + +static int wpa_driver_awext_pmksa(struct wpa_driver_awext_data *drv, + u32 cmd, const u8 *bssid, const u8 *pmkid) +{ + struct iwreq iwr; + struct iw_pmksa pmksa; + int ret = 0; + + os_memset(&iwr, 0, sizeof(iwr)); + os_strncpy(iwr.ifr_name, drv->wext->ifname, IFNAMSIZ); + os_memset(&pmksa, 0, sizeof(pmksa)); + pmksa.cmd = cmd; + pmksa.bssid.sa_family = ARPHRD_ETHER; + if (bssid) + os_memcpy(pmksa.bssid.sa_data, bssid, ETH_ALEN); + if (pmkid) + os_memcpy(pmksa.pmkid, pmkid, IW_PMKID_LEN); + iwr.u.data.pointer = (caddr_t) &pmksa; + iwr.u.data.length = sizeof(pmksa); + + if (ioctl(drv->wext->ioctl_sock, SIOCSIWPMKSA, &iwr) < 0) { + if (errno != EOPNOTSUPP) + perror("ioctl[SIOCSIWPMKSA]"); + ret = -1; + } + + return ret; +} + +static int wpa_driver_awext_add_pmkid(void *priv, const u8 *bssid, + const u8 *pmkid) +{ + struct wpa_driver_awext_data *drv = priv; + return wpa_driver_awext_pmksa(drv, IW_PMKSA_ADD, bssid, pmkid); +} + + +static int wpa_driver_awext_remove_pmkid(void *priv, const u8 *bssid, + const u8 *pmkid) +{ + struct wpa_driver_awext_data *drv = priv; + return wpa_driver_awext_pmksa(drv, IW_PMKSA_REMOVE, bssid, pmkid); +} + + +static int wpa_driver_awext_flush_pmkid(void *priv) +{ + struct wpa_driver_awext_data *drv = priv; + return wpa_driver_awext_pmksa(drv, IW_PMKSA_FLUSH, NULL, NULL); +} + + +static int wpa_driver_awext_get_capa(void *priv, struct wpa_driver_capa *capa) +{ + struct wpa_driver_awext_data *drv = priv; + if (!drv->wext->has_capability) + return -1; + os_memcpy(capa, &drv->wext->capa, sizeof(*capa)); + return 0; +} + + +static int wpa_driver_awext_set_param(void *priv, const char *param) +{ +#ifdef CONFIG_CLIENT_MLME + struct wpa_driver_awext_data *drv = priv; + const char *pos, *pos2; + size_t len; + + if (param == NULL) + return 0; + + wpa_printf(MSG_DEBUG, "%s: param='%s'", __func__, param); + + pos = os_strstr(param, "mlmedev="); + if (pos) { + pos += 8; + pos2 = os_strchr(pos, ' '); + if (pos2) + len = pos2 - pos; + else + len = os_strlen(pos); + if (len + 1 > sizeof(drv->wext->mlmedev)) + return -1; + os_memcpy(drv->wext->mlmedev, pos, len); + drv->wext->mlmedev[len] = '\0'; + wpa_printf(MSG_DEBUG, "WEXT: Using user space MLME with " + "mlmedev='%s'", drv->wext->mlmedev); + drv->wext->capa.flags |= WPA_DRIVER_FLAGS_USER_SPACE_MLME; + + drv->wext->mlme_sock = wpa_driver_awext_open_mlme(drv->wext); + if (drv->wext->mlme_sock < 0) + return -1; + } +#endif /* CONFIG_CLIENT_MLME */ + + return 0; +} + +static int wpa_driver_awext_deauthenticate(void *priv, const u8 *addr, + int reason_code) +{ + struct wpa_driver_awext_data *drv = priv; + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); + return wpa_driver_awext_mlme(drv, addr, IW_MLME_DEAUTH, reason_code); +} + +static int wpa_driver_awext_disassociate(void *priv, const u8 *addr, + int reason_code) +{ + struct wpa_driver_awext_data *drv = priv; + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); + return wpa_driver_awext_mlme(drv, addr, IW_MLME_DISASSOC, + reason_code); +} + +int wpa_driver_awext_get_bssid(void *priv, u8 *bssid) +{ + struct wpa_driver_awext_data *drv = priv; + return wpa_driver_wext_get_bssid(drv->wext, bssid); +} + +int wpa_driver_awext_set_bssid(void *priv, const u8 *bssid) +{ + struct wpa_driver_awext_data *drv = priv; + return wpa_driver_wext_set_bssid(drv->wext, bssid); +} + +int wpa_driver_awext_get_ssid(void *priv, u8 *ssid) +{ + struct wpa_driver_awext_data *drv = priv; + return wpa_driver_wext_get_ssid(drv->wext, ssid); +} + +int wpa_driver_awext_set_ssid(void *priv, const u8 *ssid, size_t ssid_len) +{ + struct wpa_driver_awext_data *drv = priv; + + if (ssid_len > 32) + return -1; + + os_memset(drv->ssid, 0, 32); + os_memcpy(drv->ssid, ssid, ssid_len); + drv->ssid_len = ssid_len; + + return wpa_driver_wext_set_ssid(drv->wext, ssid, ssid_len); +} + +int wpa_driver_awext_set_freq(void *priv, int freq) +{ + struct wpa_driver_awext_data *drv = priv; + return wpa_driver_wext_set_freq(drv->wext, freq); +} + +int wpa_driver_awext_get_ifflags(void *priv, int *flags) +{ + struct wpa_driver_awext_data *drv = priv; + return wpa_driver_wext_get_ifflags(drv->wext, flags); +} + +int wpa_driver_awext_set_ifflags(struct wpa_driver_awext_data *drv, int flags) +{ + return wpa_driver_wext_set_ifflags(drv->wext, flags); +} + +void * wpa_driver_awext_init(void *ctx, const char *ifname) +{ + struct wpa_driver_awext_data *drv; + drv = os_zalloc(sizeof(*drv)); + if (drv == NULL) + return NULL; + drv->wext = wpa_driver_wext_init(ctx, ifname); + if (drv->wext == NULL) + { + os_free(drv); + return NULL; + } + + drv->wext->ctx = ctx; + + os_strncpy(drv->wext->ifname, ifname, sizeof(drv->wext->ifname)); + drv->wext->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); + if (drv->wext->ioctl_sock < 0) + { + wpa_driver_wext_deinit(drv->wext); + os_free(drv); + return NULL; + } + + return drv; +} + +void wpa_driver_awext_deinit(void *priv) +{ + struct wpa_driver_awext_data *drv = priv; + wpa_driver_wext_deinit(drv->wext); + close(drv->wext->ioctl_sock); + os_free(drv); +} + +void wpa_driver_awext_scan_timeout(void *eloop_ctx, void *timeout_ctx) +{ + return wpa_driver_wext_scan_timeout(eloop_ctx, timeout_ctx); +} + +int wpa_driver_awext_scan(void *priv, const u8 *ssid, size_t ssid_len) +{ + struct wpa_driver_awext_data *drv = priv; + return wpa_driver_wext_scan(drv->wext, ssid, ssid_len); +} + +struct wpa_scan_result * wpa_driver_awext_get_scan_results(void *priv) +{ + struct wpa_driver_awext_data *drv = priv; + return wpa_driver_wext_get_scan_results(drv->wext); +} + +int wpa_driver_awext_set_key(void *priv, wpa_alg alg, + const u8 *addr, int key_idx, + int set_tx, const u8 *seq, size_t seq_len, + const u8 *key, size_t key_len) +{ + struct wpa_driver_awext_data *drv = priv; + return wpa_driver_wext_set_key(drv->wext, alg, addr, key_idx, set_tx, seq, seq_len, key, key_len); +} + +int wpa_driver_awext_set_mode(void *priv, int mode) +{ + struct wpa_driver_awext_data *drv = priv; + return wpa_driver_wext_set_mode(drv->wext, mode); +} + +int wpa_driver_awext_alternative_ifindex(struct wpa_driver_awext_data *drv, + const char *ifname) +{ + return wpa_driver_wext_alternative_ifindex(drv->wext, ifname); +} + +int wpa_driver_awext_set_operstate(void *priv, int state) +{ + struct wpa_driver_awext_data *drv = priv; + return wpa_driver_wext_set_operstate(drv->wext, state); +} + +int wpa_driver_awext_set_channel(void *priv, wpa_hw_mode phymode, int chan, + int freq) +{ + struct wpa_driver_awext_data *drv = priv; + return wpa_driver_awext_set_freq(drv->wext, freq); +} + +int wpa_driver_awext_get_version(struct wpa_driver_awext_data *drv) +{ + return wpa_driver_wext_get_version(drv->wext); +} + +int wpa_driver_awext_set_wpa(void *priv, int enabled) +{ + struct wpa_driver_awext_data *drv = priv; + return wpa_driver_awext_set_auth_param(drv, IW_AUTH_WPA_ENABLED, enabled); +} + +#ifdef ANDROID +static int wpa_driver_priv_driver_cmd(void *priv, char *cmd, char *buf, size_t buf_len) +{ + + struct wpa_driver_awext_data *drv = priv; + int ret = -1; + int flags; + + wpa_printf(MSG_DEBUG, "AWEXT: %s %s", __func__, cmd); + + if (os_strcasecmp(cmd, "start") == 0) { + wpa_printf(MSG_DEBUG,"Start command"); + return (ret); + } + + if (os_strcasecmp(cmd, "stop") == 0) { + wpa_printf(MSG_DEBUG,"Stop command"); + if ((wpa_driver_awext_get_ifflags(drv, &flags) == 0) && + (flags & IFF_UP)) { + wpa_printf(MSG_ERROR, "WEXT: %s when iface is UP", cmd); + wpa_driver_awext_set_ifflags(drv, flags & ~IFF_UP); + } + + } + else if (os_strcasecmp(cmd, "reload") == 0) { + wpa_printf(MSG_DEBUG,"Reload command"); + wpa_msg(drv->wext->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED"); + return ret; + } + else if (os_strcasecmp(cmd, "macaddr") == 0) { + struct ifreq ifr; + os_memset(&ifr, 0, sizeof(ifr)); + os_strncpy(ifr.ifr_name, drv->wext->ifname, IFNAMSIZ); + + if (ioctl(drv->wext->ioctl_sock, SIOCGIFHWADDR, &ifr) < 0) { + perror("ioctl[SIOCGIFHWADDR]"); + ret = -1; + } else { + u8 *macaddr = (u8 *) ifr.ifr_hwaddr.sa_data; + ret = snprintf(buf, buf_len, "Macaddr = " MACSTR "\n", + MAC2STR(macaddr)); + } + } + else if (os_strcasecmp(cmd, "scan-passive") == 0) { + wpa_printf(MSG_DEBUG,"Scan Passive command"); + } + else if (os_strcasecmp(cmd, "scan-active") == 0) { + wpa_printf(MSG_DEBUG,"Scan Active command"); + } + else if (os_strcasecmp(cmd, "linkspeed") == 0) { + struct iwreq wrq; + unsigned int linkspeed; + os_strncpy(wrq.ifr_name, drv->wext->ifname, IFNAMSIZ); + wpa_printf(MSG_DEBUG,"Link Speed command"); + if (ioctl(drv->wext->ioctl_sock, SIOCGIWRATE, &wrq) < 0) { + perror("ioctl[SIOCGIWRATE]"); + ret = -1; + } else { + linkspeed = wrq.u.bitrate.value / 1000000; + ret = snprintf(buf, buf_len, "LinkSpeed %d\n", linkspeed); + } + } + else if (os_strncasecmp(cmd, "scan-channels", 13) == 0) { + } + else if ((os_strcasecmp(cmd, "rssi") == 0) || (os_strcasecmp(cmd, "rssi-approx") == 0)) { + struct iwreq wrq; + struct iw_statistics stats; + signed int rssi; + wpa_printf(MSG_DEBUG, ">>>. DRIVER AWEXT RSSI "); + wrq.u.data.pointer = (caddr_t) &stats; + wrq.u.data.length = sizeof(stats); + wrq.u.data.flags = 1; /* Clear updated flag */ + strncpy(wrq.ifr_name, drv->wext->ifname, IFNAMSIZ); + + if (ioctl(drv->wext->ioctl_sock, SIOCGIWSTATS, &wrq) < 0) { + perror("ioctl[SIOCGIWSTATS]"); + ret = -1; + } else { + if (stats.qual.updated & IW_QUAL_DBM) { + /* Values in dBm, stored in u8 with range 63 : -192 */ + rssi = ( stats.qual.level > 63 ) ? + stats.qual.level - 0x100 : + stats.qual.level; + } else { + rssi = stats.qual.level; + } + + if (drv->ssid_len != 0 && drv->ssid_len < buf_len) { + os_memcpy((void *) buf, (void *) (drv->ssid), + drv->ssid_len ); + ret = drv->ssid_len; + ret += snprintf(&buf[ret], buf_len-ret, + " rssi %d\n", rssi); + if (ret < (int)buf_len) { + return( ret ); + } + ret = -1; + } + } + } + else if (os_strncasecmp(cmd, "powermode", 9) == 0) { + } + else if (os_strncasecmp(cmd, "getpower", 8) == 0) { + } + else if (os_strncasecmp(cmd, "get-rts-threshold", 17) == 0) { + struct iwreq wrq; + unsigned int rtsThreshold; + + strncpy(wrq.ifr_name, drv->wext->ifname, IFNAMSIZ); + + if (ioctl(drv->wext->ioctl_sock, SIOCGIWRTS, &wrq) < 0) { + perror("ioctl[SIOCGIWRTS]"); + ret = -1; + } else { + rtsThreshold = wrq.u.rts.value; + wpa_printf(MSG_DEBUG,"Get RTS Threshold command = %d", + rtsThreshold); + ret = snprintf(buf, buf_len, "rts-threshold = %u\n", + rtsThreshold); + if (ret < (int)buf_len) { + return( ret ); + } + } + } + else if (os_strncasecmp(cmd, "set-rts-threshold", 17) == 0) { + struct iwreq wrq; + unsigned int rtsThreshold; + char *cp = cmd + 17; + char *endp; + + strncpy(wrq.ifr_name, drv->wext->ifname, IFNAMSIZ); + + if (*cp != '\0') { + rtsThreshold = (unsigned int)strtol(cp, &endp, 0); + if (endp != cp) { + wrq.u.rts.value = rtsThreshold; + wrq.u.rts.fixed = 1; + wrq.u.rts.disabled = 0; + + if (ioctl(drv->wext->ioctl_sock, SIOCSIWRTS, &wrq) < 0) { + perror("ioctl[SIOCGIWRTS]"); + ret = -1; + } else { + rtsThreshold = wrq.u.rts.value; + wpa_printf(MSG_DEBUG,"Set RTS Threshold command = %d", rtsThreshold); + ret = 0; + } + } + } + } + else if (os_strcasecmp(cmd, "btcoexscan-start") == 0) { + } + else if (os_strcasecmp(cmd, "btcoexscan-stop") == 0) { + } + else if (os_strcasecmp(cmd, "rxfilter-start") == 0) { + wpa_printf(MSG_DEBUG,"Rx Data Filter Start command"); + } + else if (os_strcasecmp(cmd, "rxfilter-stop") == 0) { + wpa_printf(MSG_DEBUG,"Rx Data Filter Stop command"); + } + else if (os_strcasecmp(cmd, "rxfilter-statistics") == 0) { + } + else if (os_strncasecmp(cmd, "rxfilter-add", 12) == 0 ) { + } + else if (os_strncasecmp(cmd, "rxfilter-remove",15) == 0) { + } + else if (os_strcasecmp(cmd, "snr") == 0) { + struct iwreq wrq; + struct iw_statistics stats; + int snr, rssi, noise; + + wrq.u.data.pointer = (caddr_t) &stats; + wrq.u.data.length = sizeof(stats); + wrq.u.data.flags = 1; /* Clear updated flag */ + strncpy(wrq.ifr_name, drv->wext->ifname, IFNAMSIZ); + + if (ioctl(drv->wext->ioctl_sock, SIOCGIWSTATS, &wrq) < 0) { + perror("ioctl[SIOCGIWSTATS]"); + ret = -1; + } else { + if (stats.qual.updated & IW_QUAL_DBM) { + /* Values in dBm, stored in u8 with range 63 : -192 */ + rssi = ( stats.qual.level > 63 ) ? + stats.qual.level - 0x100 : + stats.qual.level; + noise = ( stats.qual.noise > 63 ) ? + stats.qual.noise - 0x100 : + stats.qual.noise; + } else { + rssi = stats.qual.level; + noise = stats.qual.noise; + } + + snr = rssi - noise; + + ret = snprintf(buf, buf_len, "snr = %u\n", (unsigned int)snr); + if (ret < (int)buf_len) { + return( ret ); + } + } + } + else if (os_strncasecmp(cmd, "btcoexmode", 10) == 0) { + } + else if( os_strcasecmp(cmd, "btcoexstat") == 0 ) { + } + else { + wpa_printf(MSG_DEBUG,"Unsupported command"); + } + return (ret); +} +#endif + +const struct wpa_driver_ops wpa_driver_awext_ops = { + .name = "awext", + .desc = "Android wireless extensions emulation", + .get_bssid = wpa_driver_awext_get_bssid, + .get_ssid = wpa_driver_awext_get_ssid, + .set_wpa = wpa_driver_awext_set_wpa, + .set_key = wpa_driver_awext_set_key, + .set_countermeasures = wpa_driver_awext_set_countermeasures, + .set_drop_unencrypted = wpa_driver_awext_set_drop_unencrypted, + .scan = wpa_driver_awext_scan, + .get_scan_results2 = wpa_driver_awext_get_scan_results, + .deauthenticate = wpa_driver_awext_deauthenticate, + .disassociate = wpa_driver_awext_disassociate, + .associate = wpa_driver_awext_associate, + .set_auth_alg = wpa_driver_awext_set_auth_alg, + .init = wpa_driver_awext_init, + .deinit = wpa_driver_awext_deinit, + + .set_param = wpa_driver_awext_set_param, + .add_pmkid = wpa_driver_awext_add_pmkid, + .remove_pmkid = wpa_driver_awext_remove_pmkid, + .flush_pmkid = wpa_driver_awext_flush_pmkid, + .get_capa = wpa_driver_awext_get_capa, + .set_operstate = wpa_driver_awext_set_operstate, +#ifdef CONFIG_CLIENT_MLME + .get_hw_feature_data = wpa_driver_awext_get_hw_feature_data, + .set_channel = wpa_driver_awext_set_channel, + .set_ssid = wpa_driver_awext_set_ssid, + .set_bssid = wpa_driver_awext_set_bssid, + .send_mlme = wpa_driver_awext_send_mlme, + .mlme_add_sta = wpa_driver_awext_mlme_add_sta, + .mlme_remove_sta = wpa_driver_awext_mlme_remove_sta, +#endif /* CONFIG_CLIENT_MLME */ +#ifdef ANDROID + .driver_cmd = wpa_driver_priv_driver_cmd, +#endif +}; diff --git a/wpa_supplicant/src/drivers/driver_awext.h b/wpa_supplicant/src/drivers/driver_awext.h new file mode 100644 index 0000000..71c30f2 --- /dev/null +++ b/wpa_supplicant/src/drivers/driver_awext.h @@ -0,0 +1,57 @@ +/* + * WPA Supplicant - driver_wext exported functions + * Copyright (c) 2003-2005, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#ifndef DRIVER_AWEXT_H +#define DRIVER_AWEXT_H + +#include "driver_wext.h" + +struct wpa_driver_awext_data; + +int wpa_driver_awext_get_ifflags(void *priv, int *flags); +int wpa_driver_awext_set_ifflags(struct wpa_driver_awext_data *drv, int flags); +int wpa_driver_awext_get_bssid(void *priv, u8 *bssid); +int wpa_driver_awext_set_bssid(void *priv, const u8 *bssid); +int wpa_driver_awext_get_ssid(void *priv, u8 *ssid); +int wpa_driver_awext_set_ssid(void *priv, const u8 *ssid, size_t ssid_len); +int wpa_driver_awext_set_freq(void *priv, int freq); +int wpa_driver_awext_set_mode(void *priv, int mode); +int wpa_driver_awext_set_key(void *priv, wpa_alg alg, + const u8 *addr, int key_idx, + int set_tx, const u8 *seq, size_t seq_len, + const u8 *key, size_t key_len); +int wpa_driver_awext_scan(void *priv, const u8 *ssid, size_t ssid_len); +struct wpa_scan_result * wpa_driver_awext_get_scan_results(void *priv); + +void wpa_driver_awext_scan_timeout(void *eloop_ctx, void *timeout_ctx); + +int wpa_driver_awext_alternative_ifindex(struct wpa_driver_awext_data *drv, + const char *ifname); + +void * wpa_driver_awext_init(void *ctx, const char *ifname); +void wpa_driver_awext_deinit(void *priv); + +int wpa_driver_awext_set_operstate(void *priv, int state); +int wpa_driver_awext_get_version(struct wpa_driver_awext_data *drv); + +#ifdef ANDROID +#define WEXT_NUMBER_SCAN_CHANNELS_FCC 11 +#define WEXT_NUMBER_SCAN_CHANNELS_ETSI 13 +#define WEXT_NUMBER_SCAN_CHANNELS_MKK1 14 + +#define WPA_DRIVER_WEXT_WAIT_US 400000 +#define MAX_DRV_CMD_SIZE 248 +#endif + +#endif /* DRIVER_AWEXT_H */ diff --git a/wpa_supplicant/src/drivers/drivers.c b/wpa_supplicant/src/drivers/drivers.c index 29e0cd4..368e978 100644 --- a/wpa_supplicant/src/drivers/drivers.c +++ b/wpa_supplicant/src/drivers/drivers.c @@ -15,6 +15,9 @@ #include "includes.h" +#ifdef CONFIG_DRIVER_AWEXT +extern struct wpa_driver_ops wpa_driver_awext_ops; /* driver_awext.c */ +#endif /* CONFIG_DRIVER_AWEXT */ #ifdef CONFIG_DRIVER_WEXT extern struct wpa_driver_ops wpa_driver_wext_ops; /* driver_wext.c */ #endif /* CONFIG_DRIVER_WEXT */ @@ -81,6 +84,9 @@ extern struct wpa_driver_ops wpa_driver_custom_ops; struct wpa_driver_ops *wpa_supplicant_drivers[] = { +#ifdef CONFIG_DRIVER_AWEXT + &wpa_driver_awext_ops, +#endif /* CONFIG_DRIVER_AWEXT */ #ifdef CONFIG_DRIVER_WEXT &wpa_driver_wext_ops, #endif /* CONFIG_DRIVER_WEXT */ -- 2.11.0