OSDN Git Service

Added a separate driver awext to emulate Android driver commands
authorNicu Pavel <npavel@linuxconsulting.ro>
Mon, 25 Oct 2010 00:12:05 +0000 (08:12 +0800)
committerChih-Wei Huang <cwhuang@linux.org.tw>
Fri, 20 May 2011 02:34:45 +0000 (10:34 +0800)
Change-Id: I5e14cfc5dd16c9429387b5a5acc39c55edd2fa4e

wpa_supplicant/Android.mk
wpa_supplicant/src/drivers/driver_awext.c [new file with mode: 0644]
wpa_supplicant/src/drivers/driver_awext.h [new file with mode: 0644]
wpa_supplicant/src/drivers/drivers.c

index d3ab3dd..86e9445 100644 (file)
@@ -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 (file)
index 0000000..a7c7c91
--- /dev/null
@@ -0,0 +1,913 @@
+/*
+ * WEXT Emulation for Android SIOCSIWPRIV ioctl with generic Linux Wireless Extensions
+ * Copyright (c) 2010, Nicu Pavel <npavel@linuxconsulting.ro>
+ * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
+ *
+ * Code based on Jim Huang <jserv@0xlab.org> 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 <sys/ioctl.h>
+#include <net/if_arp.h>
+#include <net/if.h>
+
+#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 <netpacket/packet.h>
+#include <hostapd_ioctl.h>
+#include <ieee80211_common.h>
+/* 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 (file)
index 0000000..71c30f2
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * WPA Supplicant - driver_wext exported functions
+ * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
+ *
+ * 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 */
index 29e0cd4..368e978 100644 (file)
@@ -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 */