summaryrefslogtreecommitdiffstats
path: root/package/hostapd-rtk/patches/002-common-files.patch
diff options
context:
space:
mode:
authorRoman Yeryomin <roman@advem.lv>2012-09-22 19:44:27 +0300
committerRoman Yeryomin <roman@advem.lv>2012-12-03 00:13:22 +0200
commit709e200be3507c4f1eed2f4f2e0628b7cfba32c9 (patch)
tree2db687e9619cf0f83d4f7bac1f5bd8d3b75d6e6b /package/hostapd-rtk/patches/002-common-files.patch
parent9e96cd6c1bdccc1f9d2d6978ae12523f00bd7f85 (diff)
Add hostapd-rtk and librtk-inband packages
Signed-off-by: Roman Yeryomin <roman@advem.lv>
Diffstat (limited to 'package/hostapd-rtk/patches/002-common-files.patch')
-rw-r--r--package/hostapd-rtk/patches/002-common-files.patch2948
1 files changed, 2948 insertions, 0 deletions
diff --git a/package/hostapd-rtk/patches/002-common-files.patch b/package/hostapd-rtk/patches/002-common-files.patch
new file mode 100644
index 000000000..30641f7b8
--- /dev/null
+++ b/package/hostapd-rtk/patches/002-common-files.patch
@@ -0,0 +1,2948 @@
+Index: hostapd-rtk-0.6.10/src/drivers/driver_realtek.c
+===================================================================
+--- /dev/null
++++ hostapd-rtk-0.6.10/src/drivers/driver_realtek.c
+@@ -0,0 +1,876 @@
++/*
++ * WPA Supplicant - driver interaction with realtek 802.11 driver
++ * Copyright (c) 2004, Sam Leffler <sam@errno.com>
++ * Copyright (c) 2004-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.
++ *
++ * Please note that realtek supports WPA configuration via Linux wireless
++ * extensions and if the kernel includes support for this, driver_wext.c should
++ * be used instead of this driver wrapper.
++ */
++
++#include "includes.h"
++#include <sys/ioctl.h>
++
++#include "common.h"
++#include "driver.h"
++#include "driver_realtek_wext.h"
++#include "eloop.h"
++#include "ieee802_11_defs.h"
++#include "wireless_copy.h"
++
++#include "driver_realtek.h"
++
++#include "../wpa_supplicant/config.h"
++#include "../wpa_supplicant/wpa_supplicant_i.h"
++#include "../wpa_supplicant/wps_supplicant.h"
++
++
++/*
++ * Avoid conflicts with wpa_supplicant definitions by undefining a definition.
++ */
++#undef WME_OUI_TYPE
++
++//#include <include/compat.h>
++#include <net80211/ieee80211.h>
++#ifdef WME_NUM_AC
++/* Assume this is built against BSD branch of realtek driver. */
++#define realtek_BSD
++#include <net80211/_ieee80211.h>
++#endif /* WME_NUM_AC */
++#include <net80211/ieee80211_crypto.h>
++#include <net80211/ieee80211_ioctl.h>
++
++
++#ifdef IEEE80211_IOCTL_SETWMMPARAMS
++/* Assume this is built against realtek-ng */
++#define realtek_NG
++#endif /* IEEE80211_IOCTL_SETWMMPARAMS */
++
++struct wpa_driver_realtek_data {
++ void *wext; /* private data for driver_wext */
++ void *ctx;
++ char ifname[IFNAMSIZ + 1];
++ int sock;
++};
++
++static int
++set80211priv(struct wpa_driver_realtek_data *drv, int op, void *data, int len,
++ int show_err)
++{
++ struct iwreq iwr;
++
++ printf("Wpa_supplicant: %s +++\n", __FUNCTION__);
++
++ os_memset(&iwr, 0, sizeof(iwr));
++ os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
++ if (len < IFNAMSIZ &&
++ op != IEEE80211_IOCTL_SET_APPIEBUF) {
++ /*
++ * Argument data fits inline; put it there.
++ */
++ os_memcpy(iwr.u.name, data, len);
++ } else {
++ /*
++ * Argument data too big for inline transfer; setup a
++ * parameter block instead; the kernel will transfer
++ * the data for the driver.
++ */
++ iwr.u.data.pointer = data;
++ iwr.u.data.length = len;
++ }
++
++
++#ifdef RTK_INBAND
++ if (inband_ioctl(op, &iwr) < 0)
++#else
++ if (ioctl(drv->sock, op, &iwr) < 0)
++#endif
++ {
++ if (show_err) {
++#ifdef realtek_NG
++ int first = IEEE80211_IOCTL_SETPARAM;
++ int last = IEEE80211_IOCTL_KICKMAC;
++ static const char *opnames[] = {
++ "ioctl[IEEE80211_IOCTL_SETPARAM]",
++ "ioctl[IEEE80211_IOCTL_GETPARAM]",
++ "ioctl[IEEE80211_IOCTL_SETMODE]",
++ "ioctl[IEEE80211_IOCTL_GETMODE]",
++ "ioctl[IEEE80211_IOCTL_SETWMMPARAMS]",
++ "ioctl[IEEE80211_IOCTL_GETWMMPARAMS]",
++ "ioctl[IEEE80211_IOCTL_SETCHANLIST]",
++ "ioctl[IEEE80211_IOCTL_GETCHANLIST]",
++ "ioctl[IEEE80211_IOCTL_CHANSWITCH]",
++ NULL,
++ "ioctl[IEEE80211_IOCTL_SET_APPIEBUF]",
++ "ioctl[IEEE80211_IOCTL_GETSCANRESULTS]",
++ NULL,
++ "ioctl[IEEE80211_IOCTL_GETCHANINFO]",
++ "ioctl[IEEE80211_IOCTL_SETOPTIE]",
++ "ioctl[IEEE80211_IOCTL_GETOPTIE]",
++ "ioctl[IEEE80211_IOCTL_SETMLME]",
++ NULL,
++ "ioctl[IEEE80211_IOCTL_SETKEY]",
++ NULL,
++ "ioctl[IEEE80211_IOCTL_DELKEY]",
++ NULL,
++ "ioctl[IEEE80211_IOCTL_ADDMAC]",
++ NULL,
++ "ioctl[IEEE80211_IOCTL_DELMAC]",
++ NULL,
++ "ioctl[IEEE80211_IOCTL_WDSMAC]",
++ NULL,
++ "ioctl[IEEE80211_IOCTL_WDSDELMAC]",
++ NULL,
++ "ioctl[IEEE80211_IOCTL_KICKMAC]",
++ };
++#else /* realtek_NG */
++ int first = IEEE80211_IOCTL_SETPARAM;
++ int last = IEEE80211_IOCTL_CHANLIST;
++ static const char *opnames[] = {
++ "ioctl[IEEE80211_IOCTL_SETPARAM]",
++ "ioctl[IEEE80211_IOCTL_GETPARAM]",
++ "ioctl[IEEE80211_IOCTL_SETKEY]",
++ "ioctl[IEEE80211_IOCTL_GETKEY]",
++ "ioctl[IEEE80211_IOCTL_DELKEY]",
++ NULL,
++ "ioctl[IEEE80211_IOCTL_SETMLME]",
++ NULL,
++ "ioctl[IEEE80211_IOCTL_SETOPTIE]",
++ "ioctl[IEEE80211_IOCTL_GETOPTIE]",
++ "ioctl[IEEE80211_IOCTL_ADDMAC]",
++ NULL,
++ "ioctl[IEEE80211_IOCTL_DELMAC]",
++ NULL,
++ "ioctl[IEEE80211_IOCTL_CHANLIST]",
++ };
++#endif /* realtek_NG */
++ int idx = op - first;
++ if (first <= op && op <= last &&
++ idx < (int) (sizeof(opnames) / sizeof(opnames[0]))
++ && opnames[idx])
++ perror(opnames[idx]);
++ else
++ perror("ioctl[unknown???]");
++ }
++ return -1;
++ }
++ return 0;
++}
++
++static int
++set80211param(struct wpa_driver_realtek_data *drv, int op, int arg,
++ int show_err)
++{
++ struct iwreq iwr;
++
++ printf("Wpa_supplicant: %s +++\n", __FUNCTION__);
++
++#ifdef RTK_INBAND_LE
++ op = htonl(op);
++ arg = htonl(arg);
++#endif
++
++ os_memset(&iwr, 0, sizeof(iwr));
++ os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
++ iwr.u.mode = op;
++ os_memcpy(iwr.u.name+sizeof(u32), &arg, sizeof(arg));
++
++
++#ifdef RTK_INBAND
++ if (inband_ioctl(IEEE80211_IOCTL_SETPARAM, &iwr) < 0)
++#else
++ if (ioctl(drv->sock, IEEE80211_IOCTL_SETPARAM, &iwr) < 0)
++#endif
++ {
++ if (show_err)
++ perror("ioctl[IEEE80211_IOCTL_SETPARAM]");
++ return -1;
++ }
++
++ return 0;
++}
++
++
++static int
++realtek_configure_wpa(struct wpa_driver_realtek_data *drv, struct wpa_driver_associate_params *params)
++{
++ int cipher = 0;
++ int wpa = 0;
++ int psk = 0;
++
++ wpa_printf(MSG_DEBUG, "realtek_configure_wpa +++ pairwise: 0x%x key_mgmt: 0x%x",
++ params->pairwise_suite, params->key_mgmt_suite);
++
++ //wpa_hexdump(999, "wpa_ie", params->wpa_ie, params->wpa_ie_len); //_Eric
++
++ if (params->pairwise_suite & CIPHER_CCMP)
++ cipher |= 1<<IEEE80211_CIPHER_AES_CCM;
++ if (params->pairwise_suite & CIPHER_TKIP)
++ cipher |= 1<<IEEE80211_CIPHER_TKIP;
++ if (params->pairwise_suite & CIPHER_NONE)
++ cipher |= 1<<IEEE80211_CIPHER_NONE;
++
++ if(params->wpa_ie[0] == 0x30)
++ wpa = 2;
++ else if (params->wpa_ie[0] == 0xdd)
++ {
++ if(params->wpa_ie[5] == 0x1)
++ wpa = 1;
++ else if(params->wpa_ie[5] == 0x4) //for WPS
++ return wpa_driver_realtek_set_wpa_ie(drv, params->wpa_ie, params->wpa_ie_len);
++ }
++
++ wpa_printf(MSG_DEBUG, "wpa:%d, pairwise: 0x%x, cipher:0x%x", wpa, params->pairwise_suite, params->key_mgmt_suite);
++
++ if(params->key_mgmt_suite & KEY_MGMT_PSK)
++ {//PSK mode, set PSK & cipher
++
++ if (set80211param(drv, IEEE80211_PARAM_KEYMGTALGS, wpa, 1))
++ {
++ wpa_printf(MSG_ERROR, "Unable to set key management algorithms");
++ return -1;
++ }
++
++ if (set80211param(drv, IEEE80211_PARAM_UCASTCIPHERS, cipher, 1))
++ {
++ wpa_printf(MSG_ERROR, "Unable to set pairwise key ciphers");
++ return -1;
++ }
++
++ }
++ else
++ {//Enterprise mode, Disable PSK & set cipher.
++ if (set80211param(drv, IEEE80211_PARAM_KEYMGTALGS, 0, 1))
++ {
++ wpa_printf(MSG_ERROR, "Unable to set key management algorithms");
++ return -1;
++ }
++ if (set80211param(drv, IEEE80211_PARAM_UCASTCIPHERS, cipher, 1))
++ {
++ wpa_printf(MSG_ERROR, "Unable to set pairwise key ciphers");
++ return -1;
++ }
++
++ }
++
++ if (set80211param(drv, IEEE80211_PARAM_WPA, wpa, 1))
++ {
++ wpa_printf(MSG_ERROR, "Unable to set WPA");
++ return -1;
++ }
++
++ if (set80211param(drv, IEEE80211_PARAM_AUTHMODE, IEEE80211_AUTH_WPA, 1))
++ {
++ wpa_printf(MSG_ERROR, "Unable to Authmode");
++ return -1;
++ }
++
++ return wpa_driver_realtek_set_wpa_ie(drv, params->wpa_ie, params->wpa_ie_len);
++
++
++}
++
++
++static int
++realtek_config_security(struct wpa_driver_realtek_data *drv, struct wpa_driver_associate_params *params)
++{
++ int wep_keyidx = params->wep_tx_keyidx;
++ int wep_keylen = params->wep_key_len[wep_keyidx];
++
++ printf("Wpa_supplicant: %s +++\n", __FUNCTION__);
++
++ if(set80211param(drv, IEEE80211_PARAM_UCASTKEYLEN, wep_keylen, 1))
++ return -1;
++
++ if(params->wep_key_len[wep_keyidx] > 0)
++ {
++
++ struct rtk_wpas_config config;
++
++ wpa_printf(MSG_DEBUG, "wep_key_len %d", params->wep_key_len[wep_keyidx]);
++
++ memset(&config, 0, sizeof(config));
++
++ config.type = WPAS_CONFIG_WEPKEY;
++
++ config.wep_keyidx = wep_keyidx;
++ config.wep_keylen = wep_keylen;
++
++ memcpy(config.wep_key, params->wep_key[wep_keyidx], wep_keylen);
++
++#ifdef RTK_INBAND_LE
++ config.wep_keyidx = htonl(config.wep_keyidx);
++ config.wep_keylen = htonl(config.wep_keylen);
++#endif
++
++ if(set80211priv(drv, WPAS_IOCTL_CUSTOM, &config, sizeof(config), 1))
++ {
++ wpa_printf(MSG_ERROR, "%s: Failed to set Configurations", __func__);
++ return -1;
++ }
++ }
++
++ if (params->wpa_ie_len == 0)
++ {
++ wpa_driver_realtek_set_wpa_ie(drv, params->wpa_ie, params->wpa_ie_len);
++
++ wpa_printf(MSG_DEBUG, "set WEP: auth_alg %d", params->auth_alg);
++ /* Set interface up flags after setting authentication modes,
++ done atlast in realtek_commit() */
++ if(params->auth_alg == AUTH_ALG_OPEN_SYSTEM)
++ return set80211param(drv, IEEE80211_PARAM_AUTHMODE, IEEE80211_AUTH_OPEN, 1);
++ else if(params->auth_alg == AUTH_ALG_SHARED_KEY)
++ return set80211param(drv, IEEE80211_PARAM_AUTHMODE, IEEE80211_AUTH_SHARED, 1);
++ else if(params->auth_alg == 0x3)
++ return set80211param(drv, IEEE80211_PARAM_AUTHMODE, IEEE80211_AUTH_AUTO, 1);
++ else if(params->auth_alg == 0x8) //RTK_WPAS, add auth_algs=BIT(3) as value of none authentication.
++ return set80211param(drv, IEEE80211_PARAM_AUTHMODE, IEEE80211_AUTH_NONE, 1);
++ }
++
++ if (params->key_mgmt_suite & KEY_MGMT_802_1X )
++ {
++ wpa_printf(MSG_DEBUG, "set 8021X");
++ if(set80211param(drv, IEEE80211_PARAM_AUTHMODE, IEEE80211_AUTH_8021X, 1))
++ return -1;
++ }
++ else if (params->wpa_ie_len > 0 )
++ {
++ return realtek_configure_wpa(drv, params);
++ }
++ else
++ {
++ printf("No 802.1X or WPA enabled!");
++ return -1;
++ }
++
++ return 0;
++
++}
++
++//_Eric ?? static int error on PC ??
++int
++wpa_driver_realtek_set_wpa_ie(struct wpa_driver_realtek_data *drv, const u8 *wpa_ie, size_t wpa_ie_len)
++{
++ struct iwreq iwr;
++
++ printf("Wpa_supplicant: %s +++\n", __FUNCTION__);
++
++ os_memset(&iwr, 0, sizeof(iwr));
++ os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
++ /* NB: SETOPTIE is not fixed-size so must not be inlined */
++ iwr.u.data.pointer = (void *) wpa_ie;
++ iwr.u.data.length = wpa_ie_len;
++
++#ifdef RTK_INBAND
++ if (inband_ioctl(IEEE80211_IOCTL_SETOPTIE, &iwr) < 0)
++#else
++ if (ioctl(drv->sock, IEEE80211_IOCTL_SETOPTIE, &iwr) < 0)
++#endif
++ {
++ perror("ioctl[IEEE80211_IOCTL_SETOPTIE]");
++ return -1;
++ }
++
++ return 0;
++}
++
++static int
++wpa_driver_realtek_del_key(struct wpa_driver_realtek_data *drv, int key_idx,
++ const u8 *addr)
++{
++ struct ieee80211req_del_key wk;
++
++ printf("Wpa_supplicant: %s +++\n", __FUNCTION__);
++
++ wpa_printf(MSG_DEBUG, "%s: keyidx=%d", __FUNCTION__, key_idx);
++ os_memset(&wk, 0, sizeof(wk));
++
++ wk.idk_keyix = key_idx;
++
++ if (addr != NULL)
++ os_memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN);
++
++ return set80211priv(drv, IEEE80211_IOCTL_DELKEY, &wk, sizeof(wk), 1);
++
++}
++
++static int
++wpa_driver_realtek_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_realtek_data *drv = priv;
++ struct ieee80211req_key wk;
++ char *alg_name;
++ u_int8_t cipher;
++
++
++ if (alg == WPA_ALG_NONE)
++ return wpa_driver_realtek_del_key(drv, key_idx, addr);
++
++ printf("Wpa_supplicant: %s +++\n", __FUNCTION__);
++
++ switch (alg) {
++ case WPA_ALG_WEP:
++ alg_name = "WEP";
++ cipher = IEEE80211_CIPHER_WEP;
++ break;
++ case WPA_ALG_TKIP:
++ alg_name = "TKIP";
++ cipher = IEEE80211_CIPHER_TKIP;
++ break;
++ case WPA_ALG_CCMP:
++ alg_name = "CCMP";
++ cipher = IEEE80211_CIPHER_AES_CCM;
++ break;
++ default:
++ wpa_printf(MSG_DEBUG, "%s: unknown/unsupported algorithm %d",
++ __FUNCTION__, alg);
++ return -1;
++ }
++
++ wpa_printf(MSG_DEBUG, "%s: alg=%s key_idx=%d set_tx=%d seq_len=%lu "
++ "key_len=%lu", __FUNCTION__, alg_name, key_idx, set_tx,
++ (unsigned long) seq_len, (unsigned long) key_len);
++
++ if (seq_len > sizeof(u_int64_t)) {
++ wpa_printf(MSG_DEBUG, "%s: seq_len %lu too big",
++ __FUNCTION__, (unsigned long) seq_len);
++ return -2;
++ }
++ if (key_len > sizeof(wk.ik_keydata)) {
++ wpa_printf(MSG_DEBUG, "%s: key length %lu too big",
++ __FUNCTION__, (unsigned long) key_len);
++ return -3;
++ }
++
++ os_memset(&wk, 0, sizeof(wk));
++ wk.ik_type = cipher;
++ wk.ik_flags = IEEE80211_KEY_RECV;
++ if (addr == NULL ||
++ os_memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0)
++ wk.ik_flags |= IEEE80211_KEY_GROUP;
++ if (set_tx) {
++ wk.ik_flags |= IEEE80211_KEY_XMIT | IEEE80211_KEY_DEFAULT;
++ os_memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
++ } else
++ os_memset(wk.ik_macaddr, 0, IEEE80211_ADDR_LEN);
++ wk.ik_keyix = key_idx;
++ wk.ik_keylen = key_len;
++#ifdef WORDS_BIGENDIAN //_Eric ?? Endian problem ? HAPD not identify ?
++#define WPA_KEY_RSC_LEN 8
++ {
++ size_t i;
++ u8 tmp[WPA_KEY_RSC_LEN];
++ os_memset(tmp, 0, sizeof(tmp));
++ for (i = 0; i < seq_len; i++)
++ tmp[WPA_KEY_RSC_LEN - i - 1] = seq[i];
++ os_memcpy(&wk.ik_keyrsc, tmp, WPA_KEY_RSC_LEN);
++ }
++#else /* WORDS_BIGENDIAN */
++ os_memcpy(&wk.ik_keyrsc, seq, seq_len);
++#endif /* WORDS_BIGENDIAN */
++
++ os_memcpy(wk.ik_keydata, key, key_len);
++
++#ifdef RTK_INBAND_LE
++ wk.ik_keyix = htons(wk.ik_keyix);
++ wk.ik_keyrsc = htonll(wk.ik_keyrsc);
++#endif
++
++ return set80211priv(drv, IEEE80211_IOCTL_SETKEY, &wk, sizeof(wk), 1);
++}
++
++static int
++wpa_driver_realtek_set_countermeasures(void *priv, int enabled)
++{
++ struct wpa_driver_realtek_data *drv = priv;
++
++ printf("Wpa_supplicant: %s +++\n", __FUNCTION__);
++ wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
++ return set80211param(drv, IEEE80211_PARAM_COUNTERMEASURES, enabled, 1);
++}
++
++
++static int
++wpa_driver_realtek_set_drop_unencrypted(void *priv, int enabled)
++{
++ struct wpa_driver_realtek_data *drv = priv;
++
++ printf("Wpa_supplicant: %s +++\n", __FUNCTION__);
++ wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
++ return set80211param(drv, IEEE80211_PARAM_DROPUNENCRYPTED, enabled, 1);
++}
++
++static int
++wpa_driver_realtek_deauthenticate(void *priv, const u8 *addr, int reason_code)
++{
++ struct wpa_driver_realtek_data *drv = priv;
++ struct ieee80211req_mlme mlme;
++
++ printf("Wpa_supplicant: %s +++\n", __FUNCTION__);
++ wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
++ mlme.im_op = IEEE80211_MLME_DEAUTH;
++ mlme.im_reason = reason_code;
++ os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
++
++#ifdef RTK_INBAND_LE
++ mlme.im_reason = htons(mlme.im_reason);
++#endif
++ return set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme), 1);
++}
++
++static int
++wpa_driver_realtek_disassociate(void *priv, const u8 *addr, int reason_code)
++{
++ struct wpa_driver_realtek_data *drv = priv;
++ struct ieee80211req_mlme mlme;
++
++ printf("Wpa_supplicant: %s +++\n", __FUNCTION__);
++
++ wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
++ mlme.im_op = IEEE80211_MLME_DISASSOC;
++ mlme.im_reason = reason_code;
++ os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
++
++#ifdef RTK_INBAND_LE
++ mlme.im_reason = htons(mlme.im_reason);
++#endif
++ return set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme), 1);
++}
++
++static int
++wpa_driver_realtek_associate(void *priv,
++ struct wpa_driver_associate_params *params)
++{
++ struct wpa_driver_realtek_data *drv = priv;
++ struct ieee80211req_mlme mlme;
++ int ret = 0, privacy = 1;
++
++ printf("Wpa_supplicant: %s +++\n", __FUNCTION__);
++
++ wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
++
++ //_Eric ?? if ret = -1, why still run continuously?
++
++ if(realtek_config_security(drv, params) < 0)
++ ret = -9;
++
++ if (params->bssid == NULL) {
++
++ //_Eric ?? it means no MAC but have SSID(name), driver shall try to find this AP automatically?
++
++ if (set80211param(drv, IEEE80211_PARAM_ROAMING, 0, 1) < 0)
++ ret = -2;
++
++ if (wpa_driver_wext_set_ssid(drv->wext, params->ssid,
++ params->ssid_len) < 0)
++ ret = -3;
++
++ } else {
++ if (set80211param(drv, IEEE80211_PARAM_ROAMING, 2, 1) < 0)
++ ret = -4;
++ if (wpa_driver_wext_set_ssid(drv->wext, params->ssid,
++ params->ssid_len) < 0)
++ ret = -5;
++ os_memset(&mlme, 0, sizeof(mlme));
++ mlme.im_op = IEEE80211_MLME_ASSOC;
++ os_memcpy(mlme.im_macaddr, params->bssid, IEEE80211_ADDR_LEN);
++
++ printf("Try to assoc %02x:%02x:%02x:%02x:%02x:%02x \n",
++ params->bssid[0], params->bssid[1], params->bssid[2],
++ params->bssid[3], params->bssid[4], params->bssid[5]);
++
++ if (set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme,
++ sizeof(mlme), 1) < 0) {
++ wpa_printf(MSG_DEBUG, "%s: SETMLME[ASSOC] failed",
++ __func__);
++ ret = -1;
++ }
++ }
++
++ printf("Wpa_supplicant: %s --- ret = %d\n", __FUNCTION__, ret);
++
++ return ret;
++
++}
++
++static int
++wpa_driver_realtek_set_auth_alg(void *priv, int auth_alg)
++{
++ struct wpa_driver_realtek_data *drv = priv;
++ int authmode;
++
++ printf("Wpa_supplicant: %s +++ auth_alg = %d\n", __FUNCTION__, auth_alg);
++
++ if ((auth_alg & AUTH_ALG_OPEN_SYSTEM) &&
++ (auth_alg & AUTH_ALG_SHARED_KEY))
++ authmode = IEEE80211_AUTH_AUTO;
++ else if (auth_alg & AUTH_ALG_SHARED_KEY)
++ authmode = IEEE80211_AUTH_SHARED;
++ else
++ authmode = IEEE80211_AUTH_OPEN;
++
++ return set80211param(drv, IEEE80211_PARAM_AUTHMODE, authmode, 1);
++}
++
++static int
++wpa_driver_realtek_scan(void *priv, const u8 *ssid, size_t ssid_len)
++{
++ struct wpa_driver_realtek_data *drv = priv;
++ struct iwreq iwr;
++ int ret = 0;
++
++ printf("Wpa_supplicant: %s +++\n", __FUNCTION__);
++
++ os_memset(&iwr, 0, sizeof(iwr));
++ os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
++
++ if (wpa_driver_wext_set_ssid(drv->wext, ssid, ssid_len) < 0)
++ ret = -1;
++
++#ifdef RTK_INBAND
++ if (inband_ioctl(SIOCSIWSCAN, &iwr) < 0)
++#else
++ if (ioctl(drv->sock, SIOCSIWSCAN, &iwr) < 0)
++#endif
++ {
++ perror("ioctl[SIOCSIWSCAN]");
++ ret = -1;
++ }
++
++ eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv->wext,
++ drv->ctx);
++ eloop_register_timeout(30, 0, wpa_driver_wext_scan_timeout, drv->wext,
++ drv->ctx);
++
++ return ret;
++}
++
++static int wpa_driver_realtek_get_bssid(void *priv, u8 *bssid)
++{
++ struct wpa_driver_realtek_data *drv = priv;
++ printf("Wpa_supplicant: %s +++\n", __FUNCTION__);
++ return wpa_driver_wext_get_bssid(drv->wext, bssid);
++}
++
++
++static int wpa_driver_realtek_get_ssid(void *priv, u8 *ssid)
++{
++ struct wpa_driver_realtek_data *drv = priv;
++ printf("Wpa_supplicant: %s +++\n", __FUNCTION__);
++ return wpa_driver_wext_get_ssid(drv->wext, ssid);
++}
++
++
++static struct wpa_scan_results *
++wpa_driver_realtek_get_scan_results(void *priv)
++{
++ struct wpa_driver_realtek_data *drv = priv;
++ printf("Wpa_supplicant: %s +++\n", __FUNCTION__);
++ return wpa_driver_wext_get_scan_results(drv->wext);
++}
++
++
++static int wpa_driver_realtek_set_operstate(void *priv, int state)
++{
++ struct wpa_driver_realtek_data *drv = priv;
++ printf("Wpa_supplicant: %s +++\n", __FUNCTION__);
++ return wpa_driver_wext_set_operstate(drv->wext, state);
++}
++
++
++static int wpa_driver_realtek_mlme_setprotection(void *priv, const u8 *addr, int protect_type, int key_type)
++{
++ struct wpa_driver_realtek_data *drv = priv;
++ struct ieee80211req_mlme mlme;
++
++ printf("Wpa_supplicant: %s +++\n", __FUNCTION__);
++
++ if(protect_type == MLME_SETPROTECTION_KEY_TYPE_PAIRWISE)
++ {
++ if(protect_type != MLME_SETPROTECTION_PROTECT_TYPE_NONE)
++ mlme.im_op = IEEE80211_MLME_AUTHORIZE;
++ else
++ mlme.im_op = IEEE80211_MLME_UNAUTHORIZE;
++ }
++ else
++ return 0;
++
++ os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
++
++ return set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme), 1);
++
++}
++
++
++static int wpa_driver_realtek_set_probe_req_ie(void *priv, const u8 *ies,
++ size_t ies_len)
++{
++ struct ieee80211req_getset_appiebuf *probe_req_ie;
++ int ret;
++
++ printf("Wpa_supplicant: %s +++\n", __FUNCTION__);
++
++ probe_req_ie = os_malloc(sizeof(*probe_req_ie) + ies_len);
++ if (probe_req_ie == NULL)
++ return -1;
++
++ probe_req_ie->app_frmtype = IEEE80211_APPIE_FRAME_PROBE_REQ;
++ probe_req_ie->app_buflen = ies_len;
++ os_memcpy(probe_req_ie->app_buf, ies, ies_len);
++
++#ifdef RTK_INBAND_LE
++ probe_req_ie->app_frmtype = htonl(probe_req_ie->app_frmtype);
++ probe_req_ie->app_buflen = htonl(probe_req_ie->app_buflen);
++#endif
++
++ ret = set80211priv(priv, IEEE80211_IOCTL_SET_APPIEBUF, probe_req_ie,
++ sizeof(struct ieee80211req_getset_appiebuf) +
++ ies_len, 1);
++
++ os_free(probe_req_ie);
++
++ return ret;
++}
++
++
++static void * wpa_driver_realtek_init(void *ctx, const char *ifname)
++{
++ struct wpa_driver_realtek_data *drv;
++ struct iwreq iwr;
++ struct rtk_wpas_config config;
++ struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)ctx;
++
++ printf("Wpa_supplicant: %s +++\n", __FUNCTION__);
++
++ drv = os_zalloc(sizeof(*drv));
++ if (drv == NULL)
++ return NULL;
++
++ drv->ctx = ctx;
++ os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
++ drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
++ if (drv->sock < 0)
++ goto fail;
++
++ if (set80211param(drv, IEEE80211_PARAM_ROAMING, 2, 1) < 0) {
++ wpa_printf(MSG_DEBUG, "%s: failed to set wpa_supplicant-based "
++ "roaming", __FUNCTION__);
++ goto fail;
++ }
++
++ if (set80211param(drv, IEEE80211_PARAM_WPA, 3, 1) < 0) {
++ wpa_printf(MSG_DEBUG, "%s: failed to enable WPA support",
++ __FUNCTION__);
++ goto fail;
++ }
++
++
++ memset(&config, 0, sizeof(config));
++
++ config.is_hapd = 0;
++ config.type = WPAS_CONFIG_MIB;
++ config.bandmode = wpa_s->conf->macPhyMode;
++ config.phymode = wpa_s->conf->phyBandSelect;
++
++ if(set80211priv(drv, WPAS_IOCTL_CUSTOM, &config, sizeof(config), 1)) {
++ wpa_printf(MSG_ERROR, "%s: Failed to set Configurations",
++ __FUNCTION__);
++ goto fail;
++ }
++
++ drv->wext = wpa_driver_wext_init(ctx, ifname);
++ if (drv->wext == NULL)
++ goto fail;
++
++ printf("Wait 5 seconds for driver init ...\n");
++ sleep(5);
++
++ os_memset(&iwr, 0, sizeof(iwr));
++ os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
++
++#ifdef RTK_INBAND
++ if (inband_ioctl(SIOCSIWSCAN, &iwr) < 0)
++#else
++ if (ioctl(drv->sock, SIOCSIWSCAN, &iwr) < 0)
++#endif
++ {
++ perror("ioctl[SIOCSIWSCAN] of init");
++ goto fail;
++ }
++ else{
++ printf("Wait 5 seconds for scanning ...\n");
++ sleep(5);
++ }
++
++ return drv;
++
++
++fail:
++ close(drv->sock);
++ os_free(drv);
++ return NULL;
++}
++
++
++static void wpa_driver_realtek_deinit(void *priv)
++{
++ struct wpa_driver_realtek_data *drv = priv;
++
++ printf("Wpa_supplicant: %s +++\n", __FUNCTION__);
++
++ if (wpa_driver_realtek_set_wpa_ie(drv, NULL, 0) < 0) {
++ wpa_printf(MSG_DEBUG, "%s: failed to clear WPA IE",
++ __FUNCTION__);
++ }
++ if (set80211param(drv, IEEE80211_PARAM_ROAMING, 0, 1) < 0) {
++ wpa_printf(MSG_DEBUG, "%s: failed to enable driver-based "
++ "roaming", __FUNCTION__);
++ }
++ if (set80211param(drv, IEEE80211_PARAM_PRIVACY, 0, 1) < 0) {
++ wpa_printf(MSG_DEBUG, "%s: failed to disable forced Privacy "
++ "flag", __FUNCTION__);
++ }
++ if (set80211param(drv, IEEE80211_PARAM_WPA, 0, 1) < 0) {
++ wpa_printf(MSG_DEBUG, "%s: failed to disable WPA",
++ __FUNCTION__);
++ }
++
++ wpa_driver_wext_deinit(drv->wext);
++
++ close(drv->sock);
++ os_free(drv);
++}
++
++
++const struct wpa_driver_ops wpa_driver_realtek_ops = {
++ .name = "realtek",
++ .desc = "realtek 802.11 support (Atheros, etc.)",
++ .get_bssid = wpa_driver_realtek_get_bssid,
++ .get_ssid = wpa_driver_realtek_get_ssid,
++ .set_key = wpa_driver_realtek_set_key,
++ .init = wpa_driver_realtek_init,
++ .deinit = wpa_driver_realtek_deinit,
++ .set_countermeasures = wpa_driver_realtek_set_countermeasures,
++ .set_drop_unencrypted = wpa_driver_realtek_set_drop_unencrypted,
++ .scan = wpa_driver_realtek_scan,
++ .get_scan_results2 = wpa_driver_realtek_get_scan_results,
++ .deauthenticate = wpa_driver_realtek_deauthenticate,
++ .disassociate = wpa_driver_realtek_disassociate,
++ .associate = wpa_driver_realtek_associate,
++ .set_auth_alg = wpa_driver_realtek_set_auth_alg,
++ .set_operstate = wpa_driver_realtek_set_operstate,
++ .mlme_setprotection = wpa_driver_realtek_mlme_setprotection,
++ .set_probe_req_ie = wpa_driver_realtek_set_probe_req_ie,
++};
+Index: hostapd-rtk-0.6.10/src/drivers/driver_realtek.h
+===================================================================
+--- /dev/null
++++ hostapd-rtk-0.6.10/src/drivers/driver_realtek.h
+@@ -0,0 +1,159 @@
++
++
++#define MACADDRLEN 6
++#define PROBEIELEN 260
++
++#define REQIELEN 123
++#define RESPIELEN 123
++
++#define HAPD_IOCTL_GETWPAIE IEEE80211_IOCTL_GET_APPIEBUF
++#define HAPD_IOCTL_SETCONFIG SIOCIWLASTPRIV
++#define RTL8192CD_IOCTL_DEL_STA 0x89f7
++#define SIOCGIWIND 0x89ff
++
++#define HOSTAPD_WPA_VERSION_WPA BIT(0)
++#define HOSTAPD_WPA_VERSION_WPA2 BIT(1)
++
++#define WPAS_IOCTL_CUSTOM SIOCIWLASTPRIV //0x8BFF
++
++enum WPAS_EVENT{
++ WPAS_EXIRED = 10,
++ WPAS_REGISTERED = 11,
++ WPAS_MIC_FAILURE = 12,
++ WPAS_ASSOC_INFO = 13,
++ WPAS_SCAN_DONE = 14
++};
++
++enum WIFI_STATUS_CODE {
++ _STATS_SUCCESSFUL_ = 0, // Success.
++ _STATS_FAILURE_ = 1, // Failure.
++ _STATS_CAP_FAIL_ = 10, // Capability too wide, can't support
++ _STATS_NO_ASOC_ = 11, // Denial reassociate
++ _STATS_OTHER_ = 12, // Denial connect, not 802.11 standard.
++ _STATS_NO_SUPP_ALG_ = 13, // Authenticate algorithm not support .
++ _STATS_OUT_OF_AUTH_SEQ_ = 14, // Out of authenticate sequence number.
++ _STATS_CHALLENGE_FAIL_ = 15, // Denial authenticate, Response message fail.
++ _STATS_AUTH_TIMEOUT_ = 16, // Denial authenticate, timeout.
++ _STATS_UNABLE_HANDLE_STA_ = 17, // Denial authenticate, BS resoruce insufficient.
++ _STATS_RATE_FAIL_ = 18, // Denial authenticate, STA not support BSS request datarate.
++ _STATS_REQ_DECLINED_ = 37,
++/*#if defined(CONFIG_RTL_WAPI_SUPPORT)*/
++ __STATS_INVALID_IE_ = 40,
++ __STATS_INVALID_AKMP_ = 43,
++ __STATS_CIPER_REJECT_ = 46,
++ __STATS_INVALID_USK_ = 47,
++ __STATS_INVALID_MSK_ = 48,
++ __STATS_INVALID_WAPI_VERSION_ = 49,
++ __STATS_INVALID_WAPI_CAPABILITY_ = 50,
++/*#endif*/
++
++#ifdef CONFIG_RTK_MESH // CATUTION: below undefine !! (Refer: Draft 1.06, Page 17, 7.3.1.9, Table 7-23, 2007/08/13 by popen)
++ _STATS_MESH_LINK_ESTABLISHED_ = 55, //The mesh peer link has been successfully
++ _STATS_MESH_LINK_CLOSED_ = 56, // The mesh peer link has been closed completely
++ _STATS_MESH_UNDEFINE1_ = 57, // No listed Key Holder Transport type is supported.
++ _STATS_MESH_UNDEFINE2_ = 58, // The Mesh Key Holder Security Handshake message was malformed.
++#endif
++};
++
++typedef enum{
++ DOT11_EVENT_NO_EVENT = 1,
++ DOT11_EVENT_REQUEST = 2,
++ DOT11_EVENT_ASSOCIATION_IND = 3,
++ DOT11_EVENT_ASSOCIATION_RSP = 4,
++ DOT11_EVENT_AUTHENTICATION_IND = 5,
++ DOT11_EVENT_REAUTHENTICATION_IND = 6,
++ DOT11_EVENT_DEAUTHENTICATION_IND = 7,
++ DOT11_EVENT_DISASSOCIATION_IND = 8,
++ DOT11_EVENT_DISCONNECT_REQ = 9,
++ DOT11_EVENT_SET_802DOT11 = 10,
++ DOT11_EVENT_SET_KEY = 11,
++ DOT11_EVENT_SET_PORT = 12,
++ DOT11_EVENT_DELETE_KEY = 13,
++ DOT11_EVENT_SET_RSNIE = 14,
++ DOT11_EVENT_GKEY_TSC = 15,
++ DOT11_EVENT_MIC_FAILURE = 16,
++ DOT11_EVENT_ASSOCIATION_INFO = 17,
++ DOT11_EVENT_INIT_QUEUE = 18,
++ DOT11_EVENT_EAPOLSTART = 19,
++//2003-07-30 ------------
++ DOT11_EVENT_ACC_SET_EXPIREDTIME = 31,
++ DOT11_EVENT_ACC_QUERY_STATS = 32,
++ DOT11_EVENT_ACC_QUERY_STATS_ALL = 33,
++//-----------------------
++
++// --- 2003-08-04 ---
++ DOT11_EVENT_REASSOCIATION_IND = 34,
++ DOT11_EVENT_REASSOCIATION_RSP = 35,
++//-----------------------
++ DOT11_EVENT_STA_QUERY_BSSID = 36,
++ DOT11_EVENT_STA_QUERY_SSID = 37,
++
++// jimmylin: pass EAP packet by event queue
++ DOT11_EVENT_EAP_PACKET = 41,
++
++#ifdef RTL_WPA2
++ DOT11_EVENT_EAPOLSTART_PREAUTH = 45,
++ DOT11_EVENT_EAP_PACKET_PREAUTH = 46,
++#endif
++
++#ifdef RTL_WPA2_CLIENT
++ DOT11_EVENT_WPA2_MULTICAST_CIPHER = 47,
++#endif
++
++ DOT11_EVENT_WPA_MULTICAST_CIPHER = 48,
++
++#ifdef AUTO_CONFIG
++ DOT11_EVENT_AUTOCONF_ASSOCIATION_IND = 50,
++ DOT11_EVENT_AUTOCONF_ASSOCIATION_CONFIRM = 51,
++ DOT11_EVENT_AUTOCONF_PACKET = 52,
++ DOT11_EVENT_AUTOCONF_LINK_IND = 53,
++#endif
++
++#ifdef WIFI_SIMPLE_CONFIG
++ DOT11_EVENT_WSC_SET_IE = 55,
++ DOT11_EVENT_WSC_PROBE_REQ_IND = 56,
++ DOT11_EVENT_WSC_PIN_IND = 57,
++ DOT11_EVENT_WSC_ASSOC_REQ_IE_IND = 58,
++#ifdef CONFIG_IWPRIV_INTF
++ DOT11_EVENT_WSC_START_IND = 70,
++ //EV_MODE, EV_STATUS, EV_MEHOD, EV_STEP, EV_OOB
++ DOT11_EVENT_WSC_MODE_IND = 71,
++ DOT11_EVENT_WSC_STATUS_IND = 72,
++ DOT11_EVENT_WSC_METHOD_IND = 73,
++ DOT11_EVENT_WSC_STEP_IND = 74,
++ DOT11_EVENT_WSC_OOB_IND = 75,
++#endif //ifdef CONFIG_IWPRIV_INTF
++#endif
++
++ DOT11_EVENT_MAX = 59,
++} DOT11_EVENT;
++
++
++typedef struct _DOT11_PROBE_REQUEST_IND{
++ unsigned char EventId;
++ unsigned char IsMoreEvent;
++ char MACAddr[MACADDRLEN];
++ unsigned short ProbeIELen;
++ char ProbeIE[PROBEIELEN];
++}DOT11_PROBE_REQUEST_IND;
++
++
++typedef struct _DOT11_ASSOCIATION_RSP{
++ unsigned char EventId;
++ unsigned char IsMoreEvent;
++ char MACAddr[MACADDRLEN];
++ unsigned char Status;
++}DOT11_ASSOCIATION_RSP;
++
++
++typedef struct _WPAS_ASSOCIATION_INFO
++{
++ unsigned short ReqIELen;
++ char ReqIE[REQIELEN];
++ unsigned short RespIELen;
++ char RespIE[RESPIELEN];
++} WPAS_ASSOCIATION_INFO;
++
++
++//_Eric ?? Put these inot net80211 will be better??
++
+Index: hostapd-rtk-0.6.10/src/drivers/driver_realtek_wext.c
+===================================================================
+--- /dev/null
++++ hostapd-rtk-0.6.10/src/drivers/driver_realtek_wext.c
+@@ -0,0 +1,1787 @@
++/*
++ * WPA Supplicant - driver interaction with generic Linux Wireless Extensions
++ * Copyright (c) 2003-2007, 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.
++ *
++ * This file implements a driver interface for the Linux Wireless Extensions.
++ * When used with WE-18 or newer, this interface can be used as-is with number
++ * of drivers. In addition to this, some of the common functions in this file
++ * can be used by other driver interface implementations that use generic WE
++ * ioctls, but require private ioctls for some of the functionality.
++ */
++
++#include "includes.h"
++#include <sys/ioctl.h>
++#include <net/if_arp.h>
++
++#include "wireless_copy.h"
++#include "common.h"
++#include "driver.h"
++#include "eloop.h"
++#include "priv_netlink.h"
++#include "driver_realtek_wext.h"
++#include "ieee802_11_defs.h"
++#include "wpa_common.h"
++
++#include "driver_realtek.h"
++
++
++#ifdef RTK_INBAND
++#define INBAND_INTF "br0"
++#define INBAND_SLAVE ("001234567899")
++#define INBAND_IOCTL_TYPE 0x8899
++#define INBAND_NETLINK_TYPE 0x9000
++#define INBAND_DEBUG 0
++#define INBAND_IOCTLPKT_DUMP //hex_dump
++#define IWREQ_LEN 32
++#define INBAND_IOCTLTYPE_LEN 4
++#define INBAND_IOCTLHDR_LEN 6
++#define INBAND_PENDING_START(data) data+INBAND_IOCTLHDR_LEN+IWREQ_LEN
++#define INBAND_IOCTLRET_PTR(data) data+INBAND_IOCTLTYPE_LEN
++#define IOH_HDR_LEN sizeof(struct ioh_header)
++#endif
++
++
++static int wpa_driver_wext_flush_pmkid(void *priv);
++static int wpa_driver_wext_get_range(void *priv);
++static void wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv);
++static void wpa_driver_wext_disconnect(struct wpa_driver_wext_data *drv);
++
++
++void convert_to_net (const char *name, void *data, int data_size)
++{
++ //_Eric ?? signed ?? unsigned ??
++
++ if(data_size == 16)
++ {
++ u16 *tmp = (u16 *)data;
++ printf("htons +++ %s = 0x%x", name, *tmp);
++ *tmp = htons(*tmp);
++ printf("htons --- %s = 0x%x", name, *tmp);
++ }
++ else if(data_size == 32)
++ {
++ u32 *tmp = (u32 *)data;
++ printf("htonl +++ %s = 0x%x", name, *tmp);
++ *tmp = htonl(*tmp);
++ printf("htonl --- %s = 0x%x", name, *tmp);
++ }
++ else
++ printf("Unknown data type !!!! %s size = %d\n", name, data_size);
++
++}
++
++
++void convert_to_host (const char *name, void *data, int data_size)
++{
++ //_Eric ?? signed ?? unsigned ??
++
++ if(data_size == 16)
++ {
++ u16 *tmp = (u16 *)data;
++ printf("ntohs +++ %s = 0x%x", name, *tmp);
++ *tmp = ntohs(*tmp);
++ printf("ntohs --- %s = 0x%x", name, *tmp);
++ }
++ else if(data_size == 32)
++ {
++ u32 *tmp = (u32 *)data;
++ printf("ntohl +++ %s = 0x%x", name, *tmp);
++ *tmp = ntohl(*tmp);
++ printf("ntohl --- %s = 0x%x", name, *tmp);
++ }
++ else
++ printf("Unknown data type !!!! %s size = %d\n", name, data_size);
++
++}
++
++
++//_Eric ??
++static int wpa_driver_wext_send_oper_ifla(struct wpa_driver_wext_data *drv,
++ int linkmode, int operstate)
++{
++ struct {
++ struct nlmsghdr hdr;
++ struct ifinfomsg ifinfo;
++ char opts[16];
++ } req;
++ struct rtattr *rta;
++ static int nl_seq;
++ ssize_t ret;
++
++ os_memset(&req, 0, sizeof(req));
++
++ req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
++ req.hdr.nlmsg_type = RTM_SETLINK;
++ req.hdr.nlmsg_flags = NLM_F_REQUEST;
++ req.hdr.nlmsg_seq = ++nl_seq;
++ req.hdr.nlmsg_pid = 0;
++
++ req.ifinfo.ifi_family = AF_UNSPEC;
++ req.ifinfo.ifi_type = 0;
++ req.ifinfo.ifi_index = drv->ifindex;
++ req.ifinfo.ifi_flags = 0;
++ req.ifinfo.ifi_change = 0;
++
++ if (linkmode != -1) {
++ rta = aliasing_hide_typecast(
++ ((char *) &req + NLMSG_ALIGN(req.hdr.nlmsg_len)),
++ struct rtattr);
++ rta->rta_type = IFLA_LINKMODE;
++ rta->rta_len = RTA_LENGTH(sizeof(char));
++ *((char *) RTA_DATA(rta)) = linkmode;
++ req.hdr.nlmsg_len = NLMSG_ALIGN(req.hdr.nlmsg_len) +
++ RTA_LENGTH(sizeof(char));
++ }
++ if (operstate != -1) {
++ rta = (struct rtattr *)
++ ((char *) &req + NLMSG_ALIGN(req.hdr.nlmsg_len));
++ rta->rta_type = IFLA_OPERSTATE;
++ rta->rta_len = RTA_LENGTH(sizeof(char));
++ *((char *) RTA_DATA(rta)) = operstate;
++ req.hdr.nlmsg_len = NLMSG_ALIGN(req.hdr.nlmsg_len) +
++ RTA_LENGTH(sizeof(char));
++ }
++
++ wpa_printf(MSG_DEBUG, "WEXT: Operstate: linkmode=%d, operstate=%d",
++ linkmode, operstate);
++
++ ret = send(drv->event_sock, &req, req.hdr.nlmsg_len, 0); //_Eric ?? "Send" relates to driver or not ?
++ if (ret < 0) {
++ wpa_printf(MSG_DEBUG, "WEXT: Sending operstate IFLA failed: "
++ "%s (assume operstate is not supported)",
++ strerror(errno));
++ }
++
++ return ret < 0 ? -1 : 0;
++}
++
++
++
++/**
++ * wpa_driver_wext_get_bssid - Get BSSID, SIOCGIWAP
++ * @priv: Pointer to private wext data from wpa_driver_wext_init()
++ * @bssid: Buffer for BSSID
++ * Returns: 0 on success, -1 on failure
++ */
++int wpa_driver_wext_get_bssid(void *priv, u8 *bssid)
++{
++ struct wpa_driver_wext_data *drv = priv;
++ struct iwreq iwr;
++ int ret = 0;
++
++ os_memset(&iwr, 0, sizeof(iwr));
++ os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
++
++#ifdef RTK_INBAND
++ if (inband_ioctl(SIOCGIWAP, &iwr) < 0)
++#else
++ if (ioctl(drv->ioctl_sock, SIOCGIWAP, &iwr) < 0)
++#endif
++ {
++ perror("ioctl[SIOCGIWAP]");
++ ret = -1;
++ }
++ os_memcpy(bssid, iwr.u.ap_addr.sa_data, ETH_ALEN);
++
++ return ret;
++}
++
++
++
++/**
++ * wpa_driver_wext_set_bssid - Set BSSID, SIOCSIWAP
++ * @priv: Pointer to private wext data from wpa_driver_wext_init()
++ * @bssid: BSSID
++ * Returns: 0 on success, -1 on failure
++ */
++int wpa_driver_wext_set_bssid(void *priv, const u8 *bssid)
++{
++ struct wpa_driver_wext_data *drv = priv;
++ struct iwreq iwr;
++ int ret = 0;
++
++ os_memset(&iwr, 0, sizeof(iwr));
++ os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
++ iwr.u.ap_addr.sa_family = ARPHRD_ETHER;
++ if (bssid)
++ os_memcpy(iwr.u.ap_addr.sa_data, bssid, ETH_ALEN);
++ else
++ os_memset(iwr.u.ap_addr.sa_data, 0, ETH_ALEN);
++
++#ifdef RTK_INBAND
++ if (inband_ioctl(SIOCSIWAP, &iwr) < 0)
++#else
++ if (ioctl(drv->ioctl_sock, SIOCSIWAP, &iwr) < 0)
++#endif
++ {
++ perror("ioctl[SIOCSIWAP]");
++ ret = -1;
++ }
++
++ return ret;
++}
++
++
++
++/**
++ * wpa_driver_wext_get_ssid - Get SSID, SIOCGIWESSID
++ * @priv: Pointer to private wext data from wpa_driver_wext_init()
++ * @ssid: Buffer for the SSID; must be at least 32 bytes long
++ * Returns: SSID length on success, -1 on failure
++ */
++int wpa_driver_wext_get_ssid(void *priv, u8 *ssid)
++{
++ struct wpa_driver_wext_data *drv = priv;
++ struct iwreq iwr;
++ int ret = 0;
++
++ os_memset(&iwr, 0, sizeof(iwr));
++ os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
++ iwr.u.essid.pointer = (caddr_t) ssid;
++ iwr.u.essid.length = 32;
++
++#ifdef RTK_INBAND
++ if (inband_ioctl(SIOCGIWESSID, &iwr) < 0)
++#else
++ if (ioctl(drv->ioctl_sock, SIOCGIWESSID, &iwr) < 0)
++#endif
++ {
++ perror("ioctl[SIOCGIWESSID]");
++ ret = -1;
++ } else {
++ ret = iwr.u.essid.length;
++ if (ret > 32)
++ ret = 32;
++ /* Some drivers include nul termination in the SSID, so let's
++ * remove it here before further processing. WE-21 changes this
++ * to explicitly require the length _not_ to include nul
++ * termination. */
++ if (ret > 0 && ssid[ret - 1] == '\0' &&
++ drv->we_version_compiled < 21)
++ ret--;
++ }
++
++ return ret;
++}
++
++
++
++/**
++ * wpa_driver_wext_set_ssid - Set SSID, SIOCSIWESSID
++ * @priv: Pointer to private wext data from wpa_driver_wext_init()
++ * @ssid: SSID
++ * @ssid_len: Length of SSID (0..32)
++ * Returns: 0 on success, -1 on failure
++ */
++int wpa_driver_wext_set_ssid(void *priv, const u8 *ssid, size_t ssid_len)
++{
++ struct wpa_driver_wext_data *drv = priv;
++ struct iwreq iwr;
++ int ret = 0;
++ char buf[33];
++
++ printf("wpa_driver_wext_set_ssid ssid_len %d \n ", ssid_len);
++
++ if (ssid_len > 32)
++ return -1;
++
++ os_memset(&iwr, 0, sizeof(iwr));
++ os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
++ /* flags: 1 = ESSID is active, 0 = not (promiscuous) */
++ iwr.u.essid.flags = (ssid_len != 0);
++ os_memset(buf, 0, sizeof(buf));
++ os_memcpy(buf, ssid, ssid_len);
++ iwr.u.essid.pointer = (caddr_t) buf;
++ if (drv->we_version_compiled < 21) {
++ /* For historic reasons, set SSID length to include one extra
++ * character, C string nul termination, even though SSID is
++ * really an octet string that should not be presented as a C
++ * string. Some Linux drivers decrement the length by one and
++ * can thus end up missing the last octet of the SSID if the
++ * length is not incremented here. WE-21 changes this to
++ * explicitly require the length _not_ to include nul
++ * termination. */
++ if (ssid_len)
++ ssid_len++;
++ }
++ iwr.u.essid.length = ssid_len;
++
++ printf("wpa_driver_wext_set_ssid len %d \n ", iwr.u.essid.length);
++
++#ifdef RTK_INBAND
++ if (inband_ioctl(SIOCSIWESSID, &iwr) < 0)
++#else
++ if (ioctl(drv->ioctl_sock, SIOCSIWESSID, &iwr) < 0)
++#endif
++ {
++ perror("ioctl[SIOCSIWESSID]");
++ ret = -1;
++ }
++
++ return ret;
++}
++
++
++
++static void
++wpa_driver_wext_event_wireless_custom(void *ctx, char *custom, u16 flags, size_t len)
++{
++ union wpa_event_data data;
++
++ os_memset(&data, 0, sizeof(data));
++
++ wpa_printf(MSG_DEBUG, "custom event =%d, len=%d", flags, len);
++
++ switch(flags)
++ {
++ case WPAS_MIC_FAILURE:
++ {
++ unsigned char * unicast = (unsigned char *)custom;
++ data.michael_mic_failure.unicast = unicast[0];
++ wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
++ break;
++ }
++ case WPAS_ASSOC_INFO:
++ {
++ struct _WPAS_ASSOCIATION_INFO *assoc_info = (struct _WPAS_ASSOCIATION_INFO *) custom;
++
++ data.assoc_info.req_ies = NULL;
++ data.assoc_info.resp_ies = NULL;
++ data.assoc_info.beacon_ies = NULL;
++
++#ifdef RTK_INBAND_LE
++ assoc_info->ReqIELen = ntohs(assoc_info->ReqIELen);
++ assoc_info->RespIELen = ntohs(assoc_info->RespIELen);
++#endif
++
++ if((assoc_info->ReqIELen == 0) && (assoc_info->RespIELen == 0))
++ goto done;
++
++ data.assoc_info.req_ies_len = assoc_info->ReqIELen;
++ data.assoc_info.resp_ies_len = assoc_info->RespIELen;
++
++ if(data.assoc_info.req_ies_len > 0)
++ {
++ data.assoc_info.req_ies = os_malloc(assoc_info->ReqIELen);
++
++ if (data.assoc_info.req_ies == NULL)
++ goto done;
++
++ os_memcpy(data.assoc_info.req_ies, assoc_info->ReqIE, assoc_info->ReqIELen);
++ }
++
++
++ if(data.assoc_info.resp_ies_len > 0)
++ {
++
++ data.assoc_info.resp_ies = os_malloc(assoc_info->RespIELen);
++ if (data.assoc_info.resp_ies == NULL)
++ goto done;
++
++ os_memcpy(data.assoc_info.resp_ies, assoc_info->RespIE, assoc_info->RespIELen);
++ }
++
++ wpa_supplicant_event(ctx, EVENT_ASSOCINFO, &data);
++
++done:
++
++ if(data.assoc_info.req_ies_len > 0)
++ os_free(data.assoc_info.req_ies);
++
++ if(data.assoc_info.resp_ies_len > 0)
++ os_free(data.assoc_info.resp_ies);
++
++ break;
++ }
++ default:
++ break;
++
++ }
++
++}
++
++
++
++static int wpa_driver_wext_event_wireless_michaelmicfailure(
++ void *ctx, const char *ev, size_t len)
++{
++ const struct iw_michaelmicfailure *mic;
++ union wpa_event_data data;
++
++ if (len < sizeof(*mic))
++ return -1;
++
++ mic = (const struct iw_michaelmicfailure *) ev;
++
++ wpa_printf(MSG_DEBUG, "Michael MIC failure wireless event: "
++ "flags=0x%x src_addr=" MACSTR, mic->flags,
++ MAC2STR(mic->src_addr.sa_data));
++
++ os_memset(&data, 0, sizeof(data));
++ data.michael_mic_failure.unicast = !(mic->flags & IW_MICFAILURE_GROUP);
++ wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
++
++ return 0;
++}
++
++
++
++static void wpa_driver_wext_event_assoc_ies(struct wpa_driver_wext_data *drv)
++{
++ union wpa_event_data data;
++
++ if (drv->assoc_req_ies == NULL && drv->assoc_resp_ies == NULL)
++ return;
++
++ os_memset(&data, 0, sizeof(data));
++ if (drv->assoc_req_ies) {
++ data.assoc_info.req_ies = drv->assoc_req_ies;
++ drv->assoc_req_ies = NULL;
++ data.assoc_info.req_ies_len = drv->assoc_req_ies_len;
++ }
++ if (drv->assoc_resp_ies) {
++ data.assoc_info.resp_ies = drv->assoc_resp_ies;
++ drv->assoc_resp_ies = NULL;
++ data.assoc_info.resp_ies_len = drv->assoc_resp_ies_len;
++ }
++
++ wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &data);
++
++ os_free(data.assoc_info.req_ies);
++ os_free(data.assoc_info.resp_ies);
++}
++
++
++
++static void wpa_driver_wext_event_wireless(struct wpa_driver_wext_data *drv,
++ void *ctx, char *data, int len)
++{
++ struct iw_event iwe_buf, *iwe = &iwe_buf;
++ char *pos, *end, *custom, *buf;
++
++ pos = data;
++ end = data + len;
++
++ while (pos + IW_EV_LCP_LEN <= end) {
++ /* Event data may be unaligned, so make a local, aligned copy
++ * before processing. */
++ os_memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
++
++#ifdef RTK_INBAND_LE
++ iwe->len = ntohs(iwe->len);
++ iwe->cmd = ntohs(iwe->cmd);
++#endif
++
++ wpa_printf(MSG_DEBUG, "Wireless event: cmd=0x%x len=%d",
++ iwe->cmd, iwe->len);
++
++ if (iwe->len <= IW_EV_LCP_LEN)
++ return;
++
++ custom = pos + IW_EV_POINT_LEN;
++ if (drv->we_version_compiled > 18 &&
++ (iwe->cmd == IWEVMICHAELMICFAILURE ||
++ iwe->cmd == IWEVCUSTOM ||
++ iwe->cmd == IWEVASSOCREQIE ||
++ iwe->cmd == IWEVASSOCRESPIE ||
++ iwe->cmd == IWEVPMKIDCAND)) {
++ /* WE-19 removed the pointer from struct iw_point */
++ char *dpos = (char *) &iwe_buf.u.data.length;
++ int dlen = dpos - (char *) &iwe_buf;
++ os_memcpy(dpos, pos + IW_EV_LCP_LEN,
++ sizeof(struct iw_event) - dlen);
++ } else {
++ os_memcpy(&iwe_buf, pos, sizeof(struct iw_event));
++ custom += IW_EV_POINT_OFF;
++
++#ifdef RTK_INBAND_LE
++ iwe->len = ntohs(iwe->len);
++ iwe->cmd = ntohs(iwe->cmd);
++#endif
++
++ }
++
++ switch (iwe->cmd) {
++ case SIOCGIWAP: //_Eric ?? sa_data is get from parsing ??
++ wpa_printf(MSG_DEBUG, "Wireless event: new AP: "
++ MACSTR,
++ MAC2STR((u8 *) iwe->u.ap_addr.sa_data));
++ if (is_zero_ether_addr(
++ (const u8 *) iwe->u.ap_addr.sa_data) ||
++ os_memcmp(iwe->u.ap_addr.sa_data,
++ "\x44\x44\x44\x44\x44\x44", ETH_ALEN) ==
++ 0) {
++ os_free(drv->assoc_req_ies);
++ drv->assoc_req_ies = NULL;
++ os_free(drv->assoc_resp_ies);
++ drv->assoc_resp_ies = NULL;
++ wpa_supplicant_event(ctx, EVENT_DISASSOC,
++ NULL);
++
++ } else {
++ wpa_driver_wext_event_assoc_ies(drv);
++ wpa_supplicant_event(ctx, EVENT_ASSOC, NULL);
++ }
++ break;
++ case IWEVCUSTOM:
++
++#ifdef RTK_INBAND_LE
++ iwe->u.data.length = ntohs(iwe->u.data.length);
++ iwe->u.data.flags = ntohs(iwe->u.data.flags);
++#endif
++
++ if (custom + iwe->u.data.length > end) {
++ wpa_printf(MSG_DEBUG, "WEXT: Invalid "
++ "IWEVCUSTOM length");
++ return;
++ }
++ buf = os_malloc(iwe->u.data.length + 1);
++ if (buf == NULL)
++ return;
++ os_memcpy(buf, custom, iwe->u.data.length);
++ buf[iwe->u.data.length] = '\0';
++ wpa_driver_wext_event_wireless_custom(ctx, buf, iwe->u.data.flags, iwe->u.data.length);
++ os_free(buf);
++ break;
++ case SIOCGIWSCAN:
++ drv->scan_complete_events = 1;
++ eloop_cancel_timeout(wpa_driver_wext_scan_timeout,
++ drv, ctx);
++ wpa_supplicant_event(ctx, EVENT_SCAN_RESULTS, NULL);
++ break;
++ }
++
++ pos += iwe->len;
++ }
++}
++
++
++static void wpa_driver_wext_event_rtm_newlink(struct wpa_driver_wext_data *drv,
++ void *ctx, struct nlmsghdr *h,
++ size_t len)
++{
++ struct ifinfomsg *ifi;
++ int attrlen, nlmsg_len, rta_len;
++ struct rtattr * attr;
++
++ if (len < sizeof(*ifi))
++ return;
++
++ ifi = NLMSG_DATA(h);
++
++#ifdef RTK_INBAND_LE
++ ifi->ifi_index = ntohl(ifi->ifi_index);
++#endif
++
++
++ if (drv->ifindex != ifi->ifi_index)
++ {
++ wpa_printf(MSG_DEBUG, "Ignore event for foreign ifindex %d, drv->ifindex %d",
++ ifi->ifi_index, drv->ifindex);
++ //_Eric ?? return;
++ }
++
++ wpa_printf(MSG_DEBUG, "RTM_NEWLINK: operstate=%d ifi_flags=0x%x "
++ "(%s%s%s%s)",
++ drv->operstate, ifi->ifi_flags,
++ (ifi->ifi_flags & IFF_UP) ? "[UP]" : "",
++ (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
++ (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
++ (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
++
++ nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));
++
++ attrlen = h->nlmsg_len - nlmsg_len;
++ if (attrlen < 0)
++ return;
++
++ attr = (struct rtattr *) (((char *) ifi) + nlmsg_len);
++
++#ifdef RTK_INBAND_LE
++ attr->rta_len = ntohs(attr->rta_len);
++ attr->rta_type = ntohs(attr->rta_type);
++#endif
++
++ rta_len = RTA_ALIGN(sizeof(struct rtattr));
++ while (RTA_OK(attr, attrlen))
++ {
++ if (attr->rta_type == IFLA_WIRELESS)
++ {
++ wpa_driver_wext_event_wireless(
++ drv, ctx, ((char *) attr) + rta_len,
++ attr->rta_len - rta_len);
++ }
++
++ attr = RTA_NEXT(attr, attrlen);
++
++#ifdef RTK_INBAND_LE
++ attr->rta_len = ntohs(attr->rta_len);
++ attr->rta_type = ntohs(attr->rta_type);
++#endif
++
++ }
++
++}
++
++
++
++static void wpa_driver_wext_event_receive(int sock, void *eloop_ctx,
++ void *sock_ctx)
++{
++ char buf[8192];
++ int left;
++ struct sockaddr_nl from;
++ socklen_t fromlen;
++ struct nlmsghdr *h;
++ int max_events = 10;
++ struct wpa_driver_wext_data *drv = eloop_ctx;
++
++try_again:
++
++#ifdef RTK_INBAND
++ left = ioh_recv(&drv->netlink_ioh_obj, 3000);
++
++ if (left < 0) {
++ perror("recvfrom(rawsock)");
++ return;
++ }
++
++ //hex_dump(drv->netlink_ioh_obj.rx_data,left);
++
++ left -= IOH_HDR_LEN;
++
++ h = (struct nlmsghdr *)drv->netlink_ioh_obj.rx_data ;
++#else
++
++ fromlen = sizeof(from);
++ left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT,
++ (struct sockaddr *) &from, &fromlen);
++ if (left < 0) {
++ if (errno != EINTR && errno != EAGAIN)
++ perror("recvfrom(netlink)");
++ return;
++ }
++
++ h = (struct nlmsghdr *) buf;
++
++#endif
++
++
++ while (left >= (int) sizeof(*h)) {
++ int len, plen;
++
++#ifdef RTK_INBAND_LE
++ h->nlmsg_len = ntohl(h->nlmsg_len);
++ h->nlmsg_type = ntohs(h->nlmsg_type);
++ h->nlmsg_flags = ntohs(h->nlmsg_flags);
++ h->nlmsg_seq = ntohl(h->nlmsg_seq);
++ h->nlmsg_pid = ntohl(h->nlmsg_pid);
++#endif
++
++
++ len = h->nlmsg_len;
++ plen = len - sizeof(*h);
++ if (len > left || plen < 0) {
++ wpa_printf(MSG_DEBUG, "Malformed netlink message: "
++ "len=%d left=%d plen=%d",
++ len, left, plen);
++ break;
++ }
++
++ switch (h->nlmsg_type) {
++ case RTM_NEWLINK:
++ wpa_driver_wext_event_rtm_newlink(eloop_ctx, sock_ctx,
++ h, plen);
++ break;
++ }
++
++ len = NLMSG_ALIGN(len);
++ left -= len;
++ h = (struct nlmsghdr *) ((char *) h + len);
++ }
++
++ if (left > 0) {
++ wpa_printf(MSG_DEBUG, "%d extra bytes in the end of netlink "
++ "message", left);
++ }
++
++ if (--max_events > 0) {
++ /*
++ * Try to receive all events in one eloop call in order to
++ * limit race condition on cases where AssocInfo event, Assoc
++ * event, and EAPOL frames are received more or less at the
++ * same time. We want to process the event messages first
++ * before starting EAPOL processing.
++ */
++ goto try_again;
++ }
++}
++
++
++
++static int wpa_driver_wext_get_ifflags_ifname(struct wpa_driver_wext_data *drv,
++ const char *ifname, int *flags)
++{
++ struct ifreq ifr;
++
++ os_memset(&ifr, 0, sizeof(ifr));
++ os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
++
++#ifdef RTK_INBAND
++ if (inband_ioctl(SIOCGIFFLAGS, (caddr_t) &ifr) < 0)
++#else
++ if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, (caddr_t) &ifr) < 0)
++#endif
++ {
++ perror("ioctl[SIOCGIFFLAGS]");
++ return -1;
++ }
++ *flags = ifr.ifr_flags & 0xffff;
++ return 0;
++}
++
++
++
++/**
++ * wpa_driver_wext_get_ifflags - Get interface flags (SIOCGIFFLAGS)
++ * @drv: driver_wext private data
++ * @flags: Pointer to returned flags value
++ * Returns: 0 on success, -1 on failure
++ */
++int wpa_driver_wext_get_ifflags(struct wpa_driver_wext_data *drv, int *flags)
++{
++ return wpa_driver_wext_get_ifflags_ifname(drv, drv->ifname, flags);
++}
++
++
++
++static int wpa_driver_wext_set_ifflags_ifname(struct wpa_driver_wext_data *drv,
++ const char *ifname, int flags)
++{
++ struct ifreq ifr;
++
++ os_memset(&ifr, 0, sizeof(ifr));
++ os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
++ ifr.ifr_flags = flags & 0xffff;
++
++#ifdef RTK_INBAND
++ if (inband_ioctl(SIOCSIFFLAGS, (caddr_t) &ifr) < 0)
++#else
++ if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, (caddr_t) &ifr) < 0)
++#endif
++ {
++ perror("SIOCSIFFLAGS");
++ return -1;
++ }
++ return 0;
++}
++
++
++
++/**
++ * wpa_driver_wext_set_ifflags - Set interface flags (SIOCSIFFLAGS)
++ * @drv: driver_wext private data
++ * @flags: New value for flags
++ * Returns: 0 on success, -1 on failure
++ */
++int wpa_driver_wext_set_ifflags(struct wpa_driver_wext_data *drv, int flags)
++{
++ return wpa_driver_wext_set_ifflags_ifname(drv, drv->ifname, flags);
++}
++
++
++
++/**
++ * wpa_driver_wext_init - Initialize WE driver interface
++ * @ctx: context to be used when calling wpa_supplicant functions,
++ * e.g., wpa_supplicant_event()
++ * @ifname: interface name, e.g., wlan0
++ * Returns: Pointer to private data, %NULL on failure
++ */
++void * wpa_driver_wext_init(void *ctx, const char *ifname)
++{
++ int s;
++ struct sockaddr_nl local;
++ struct wpa_driver_wext_data *drv;
++
++ drv = os_zalloc(sizeof(*drv));
++ if (drv == NULL)
++ return NULL;
++ drv->ctx = ctx;
++ os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
++
++ drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
++ if (drv->ioctl_sock < 0) {
++ perror("socket(PF_INET,SOCK_DGRAM)");
++ os_free(drv);
++ return NULL;
++ }
++
++
++#ifdef RTK_INBAND
++ s = ioh_open(&drv->netlink_ioh_obj,INBAND_INTF,INBAND_SLAVE,INBAND_NETLINK_TYPE,INBAND_DEBUG);
++ if (s < 0) {
++ perror("socket(PF_PACKET,SOCK_RAW,INBAND_NETLINK_TYPE)");
++ return -1;
++ }
++#else
++ s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
++ if (s < 0) {
++ perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)");
++ close(drv->ioctl_sock);
++ os_free(drv);
++ return NULL;
++ }
++
++ os_memset(&local, 0, sizeof(local));
++ local.nl_family = AF_NETLINK;
++ local.nl_groups = RTMGRP_LINK;
++ if (bind(s, (struct sockaddr *) &local, sizeof(local)) < 0) {
++ perror("bind(netlink)");
++ close(s);
++ close(drv->ioctl_sock);
++ os_free(drv);
++ return NULL;
++ }
++#endif
++
++#ifdef RTK_INBAND
++ eloop_register_read_sock(drv->netlink_ioh_obj.sockfd, wpa_driver_wext_event_receive, drv, ctx);
++ drv->event_sock = drv->netlink_ioh_obj.sockfd;
++#else
++ eloop_register_read_sock(s, wpa_driver_wext_event_receive, drv, ctx);
++ drv->event_sock = s;
++#endif
++
++ drv->mlme_sock = -1;
++
++ wpa_driver_wext_finish_drv_init(drv);
++
++ return drv;
++}
++
++
++
++static void wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv)
++{
++ int flags;
++
++ if (wpa_driver_wext_get_ifflags(drv, &flags) != 0)
++ printf("Could not get interface '%s' flags\n", drv->ifname);
++
++ if (wpa_driver_wext_set_ifflags(drv, flags &= ~IFF_UP) != 0)
++ printf("Could not set interface '%s' DOWN\n", drv->ifname);
++
++ if (wpa_driver_wext_set_mode(drv, 0) < 0)
++ printf("Could not configure driver to use managed mode\n");
++
++ if (wpa_driver_wext_set_ifflags(drv, flags | IFF_UP) != 0)
++ printf("Could not set interface '%s' UP\n", drv->ifname);
++
++ wpa_driver_wext_get_range(drv);
++
++ wpa_driver_wext_disconnect(drv);
++
++ drv->ifindex = if_nametoindex(drv->ifname);
++
++}
++
++
++
++/**
++ * wpa_driver_wext_deinit - Deinitialize WE driver interface
++ * @priv: Pointer to private wext data from wpa_driver_wext_init()
++ *
++ * Shut down driver interface and processing of driver events. Free
++ * private data buffer if one was allocated in wpa_driver_wext_init().
++ */
++void wpa_driver_wext_deinit(void *priv)
++{
++ struct wpa_driver_wext_data *drv = priv;
++ int flags;
++
++ eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv, drv->ctx);
++
++ /*
++ * Clear possibly configured driver parameters in order to make it
++ * easier to use the driver after wpa_supplicant has been terminated.
++ */
++ wpa_driver_wext_disconnect(drv);
++
++ wpa_driver_wext_send_oper_ifla(priv, 0, IF_OPER_UP);
++
++ eloop_unregister_read_sock(drv->event_sock);
++ if (drv->mlme_sock >= 0)
++ eloop_unregister_read_sock(drv->mlme_sock);
++
++ if (wpa_driver_wext_get_ifflags(drv, &flags) == 0)
++ (void) wpa_driver_wext_set_ifflags(drv, flags & ~IFF_UP);
++
++ close(drv->event_sock);
++ close(drv->ioctl_sock);
++ if (drv->mlme_sock >= 0)
++ close(drv->mlme_sock);
++ os_free(drv->assoc_req_ies);
++ os_free(drv->assoc_resp_ies);
++ os_free(drv);
++}
++
++
++
++/**
++ * wpa_driver_wext_scan_timeout - Scan timeout to report scan completion
++ * @eloop_ctx: Unused
++ * @timeout_ctx: ctx argument given to wpa_driver_wext_init()
++ *
++ * This function can be used as registered timeout when starting a scan to
++ * generate a scan completed event if the driver does not report this.
++ */
++void wpa_driver_wext_scan_timeout(void *eloop_ctx, void *timeout_ctx)
++{
++ wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
++ wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
++}
++
++
++
++/**
++ * wpa_driver_wext_scan - Request the driver to initiate scan
++ * @priv: Pointer to private wext data from wpa_driver_wext_init()
++ * @ssid: Specific SSID to scan for (ProbeReq) or %NULL to scan for
++ * all SSIDs (either active scan with broadcast SSID or passive
++ * scan
++ * @ssid_len: Length of the SSID
++ * Returns: 0 on success, -1 on failure
++ */
++int wpa_driver_wext_scan(void *priv, const u8 *ssid, size_t ssid_len)
++{
++ struct wpa_driver_wext_data *drv = priv;
++ struct iwreq iwr;
++ int ret = 0, timeout;
++ struct iw_scan_req req;
++
++ if (ssid_len > IW_ESSID_MAX_SIZE) {
++ wpa_printf(MSG_DEBUG, "%s: too long SSID (%lu)",
++ __FUNCTION__, (unsigned long) ssid_len);
++ return -1;
++ }
++
++ os_memset(&iwr, 0, sizeof(iwr));
++ os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
++
++ if (ssid && ssid_len) {
++ os_memset(&req, 0, sizeof(req));
++ req.essid_len = ssid_len;
++ req.bssid.sa_family = ARPHRD_ETHER;
++ os_memset(req.bssid.sa_data, 0xff, ETH_ALEN);
++ os_memcpy(req.essid, ssid, ssid_len);
++ iwr.u.data.pointer = (caddr_t) &req;
++ iwr.u.data.length = sizeof(req);
++ iwr.u.data.flags = IW_SCAN_THIS_ESSID;
++ }
++
++#ifdef RTK_INBAND
++ if (inband_ioctl(SIOCSIWSCAN, &iwr) < 0)
++#else
++ if (ioctl(drv->ioctl_sock, SIOCSIWSCAN, &iwr) < 0)
++#endif
++ {
++ perror("ioctl[SIOCSIWSCAN]");
++ ret = -1;
++ }
++
++ /* Not all drivers generate "scan completed" wireless event, so try to
++ * read results after a timeout. */
++ timeout = 5;
++ if (drv->scan_complete_events) {
++ /*
++ * The driver seems to deliver SIOCGIWSCAN events to notify
++ * when scan is complete, so use longer timeout to avoid race
++ * conditions with scanning and following association request.
++ */
++ timeout = 30;
++ }
++ wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d "
++ "seconds", ret, timeout);
++ eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv, drv->ctx);
++ eloop_register_timeout(timeout, 0, wpa_driver_wext_scan_timeout, drv,
++ drv->ctx);
++
++ return ret;
++}
++
++
++
++static u8 * wpa_driver_wext_giwscan(struct wpa_driver_wext_data *drv,
++ size_t *len)
++{
++ struct iwreq iwr;
++ u8 *res_buf;
++ size_t res_buf_len;
++
++ res_buf_len = IW_SCAN_MAX_DATA;
++ for (;;) {
++ res_buf = os_malloc(res_buf_len);
++ if (res_buf == NULL)
++ return NULL;
++ os_memset(&iwr, 0, sizeof(iwr));
++ os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
++ iwr.u.data.pointer = res_buf;
++ iwr.u.data.length = res_buf_len;
++
++#ifdef RTK_INBAND
++ if (inband_ioctl(SIOCGIWSCAN, &iwr) == 0)
++#else
++ if (ioctl(drv->ioctl_sock, SIOCGIWSCAN, &iwr) == 0)
++#endif
++ break;
++
++ if (errno == E2BIG && res_buf_len < 65535) {
++ os_free(res_buf);
++ res_buf = NULL;
++ res_buf_len *= 2;
++ if (res_buf_len > 65535)
++ res_buf_len = 65535; /* 16-bit length field */
++ wpa_printf(MSG_DEBUG, "Scan results did not fit - "
++ "trying larger buffer (%lu bytes)",
++ (unsigned long) res_buf_len);
++ } else {
++ perror("ioctl[SIOCGIWSCAN]");
++ os_free(res_buf);
++ return NULL;
++ }
++ }
++
++ if (iwr.u.data.length > res_buf_len) {
++ os_free(res_buf);
++ return NULL;
++ }
++ *len = iwr.u.data.length;
++
++ return res_buf;
++}
++
++
++
++/*
++ * Data structure for collecting WEXT scan results. This is needed to allow
++ * the various methods of reporting IEs to be combined into a single IE buffer.
++ */
++struct wext_scan_data {
++ struct wpa_scan_res res;
++ u8 *ie;
++ size_t ie_len;
++ u8 ssid[32];
++ size_t ssid_len;
++ int maxrate;
++};
++
++
++
++static void wext_get_scan_mode(struct iw_event *iwe,
++ struct wext_scan_data *res)
++{
++ if (iwe->u.mode == IW_MODE_ADHOC)
++ res->res.caps |= IEEE80211_CAP_IBSS;
++ else if (iwe->u.mode == IW_MODE_MASTER || iwe->u.mode == IW_MODE_INFRA)
++ res->res.caps |= IEEE80211_CAP_ESS;
++}
++
++
++
++static void wext_get_scan_ssid(struct iw_event *iwe,
++ struct wext_scan_data *res, char *custom,
++ char *end)
++{
++ int ssid_len = iwe->u.essid.length;
++ if (custom + ssid_len > end)
++ return;
++ if (iwe->u.essid.flags &&
++ ssid_len > 0 &&
++ ssid_len <= IW_ESSID_MAX_SIZE) {
++ os_memcpy(res->ssid, custom, ssid_len);
++ res->ssid_len = ssid_len;
++ }
++}
++
++
++
++static void wext_get_scan_freq(struct iw_event *iwe,
++ struct wext_scan_data *res)
++{
++ int divi = 1000000, i;
++
++ if (iwe->u.freq.e == 0) {
++ /*
++ * Some drivers do not report frequency, but a channel.
++ * Try to map this to frequency by assuming they are using
++ * IEEE 802.11b/g. But don't overwrite a previously parsed
++ * frequency if the driver sends both frequency and channel,
++ * since the driver may be sending an A-band channel that we
++ * don't handle here.
++ */
++
++ if (res->res.freq)
++ return;
++
++ if (iwe->u.freq.m >= 1 && iwe->u.freq.m <= 13) {
++ res->res.freq = 2407 + 5 * iwe->u.freq.m;
++ return;
++ } else if (iwe->u.freq.m == 14) {
++ res->res.freq = 2484;
++ return;
++ }
++ }
++
++ if (iwe->u.freq.e > 6) {
++ wpa_printf(MSG_DEBUG, "Invalid freq in scan results (BSSID="
++ MACSTR " m=%d e=%d)",
++ MAC2STR(res->res.bssid), iwe->u.freq.m,
++ iwe->u.freq.e);
++ return;
++ }
++
++ for (i = 0; i < iwe->u.freq.e; i++)
++ divi /= 10;
++ res->res.freq = iwe->u.freq.m / divi;
++}
++
++
++
++static void wext_get_scan_qual(struct iw_event *iwe,
++ struct wext_scan_data *res)
++{
++ res->res.qual = iwe->u.qual.qual;
++ res->res.noise = iwe->u.qual.noise;
++ res->res.level = iwe->u.qual.level;
++}
++
++
++
++static void wext_get_scan_encode(struct iw_event *iwe,
++ struct wext_scan_data *res)
++{
++ if (!(iwe->u.data.flags & IW_ENCODE_DISABLED))
++ res->res.caps |= IEEE80211_CAP_PRIVACY;
++}
++
++
++static void wext_get_scan_rate(struct iw_event *iwe,
++ struct wext_scan_data *res, char *pos,
++ char *end)
++{
++ int maxrate;
++ char *custom = pos + IW_EV_LCP_LEN;
++ struct iw_param p;
++ size_t clen;
++
++ clen = iwe->len;
++ if (custom + clen > end)
++ return;
++ maxrate = 0;
++ while (((ssize_t) clen) >= (ssize_t) sizeof(struct iw_param)) {
++ /* Note: may be misaligned, make a local, aligned copy */
++ os_memcpy(&p, custom, sizeof(struct iw_param));
++ if (p.value > maxrate)
++ maxrate = p.value;
++ clen -= sizeof(struct iw_param);
++ custom += sizeof(struct iw_param);
++ }
++
++ /* Convert the maxrate from WE-style (b/s units) to
++ * 802.11 rates (500000 b/s units).
++ */
++ res->maxrate = maxrate / 500000;
++}
++
++
++
++static void wext_get_scan_iwevgenie(struct iw_event *iwe,
++ struct wext_scan_data *res, char *custom,
++ char *end)
++{
++ char *genie, *gpos, *gend;
++ u8 *tmp;
++
++ if (iwe->u.data.length == 0)
++ return;
++
++ gpos = genie = custom;
++ gend = genie + iwe->u.data.length;
++ if (gend > end) {
++ wpa_printf(MSG_INFO, "IWEVGENIE overflow");
++ return;
++ }
++
++ tmp = os_realloc(res->ie, res->ie_len + gend - gpos);
++ if (tmp == NULL)
++ return;
++ os_memcpy(tmp + res->ie_len, gpos, gend - gpos);
++ res->ie = tmp;
++ res->ie_len += gend - gpos;
++}
++
++
++
++static void wext_get_scan_custom(struct iw_event *iwe,
++ struct wext_scan_data *res, char *custom,
++ char *end)
++{
++ size_t clen;
++ u8 *tmp;
++
++ clen = iwe->u.data.length;
++ if (custom + clen > end)
++ return;
++
++ if (clen > 7 && os_strncmp(custom, "wpa_ie=", 7) == 0) {
++ char *spos;
++ int bytes;
++ spos = custom + 7;
++ bytes = custom + clen - spos;
++ if (bytes & 1 || bytes == 0)
++ return;
++ bytes /= 2;
++ tmp = os_realloc(res->ie, res->ie_len + bytes);
++ if (tmp == NULL)
++ return;
++ hexstr2bin(spos, tmp + res->ie_len, bytes);
++ res->ie = tmp;
++ res->ie_len += bytes;
++ } else if (clen > 7 && os_strncmp(custom, "rsn_ie=", 7) == 0) {
++ char *spos;
++ int bytes;
++ spos = custom + 7;
++ bytes = custom + clen - spos;
++ if (bytes & 1 || bytes == 0)
++ return;
++ bytes /= 2;
++ tmp = os_realloc(res->ie, res->ie_len + bytes);
++ if (tmp == NULL)
++ return;
++ hexstr2bin(spos, tmp + res->ie_len, bytes);
++ res->ie = tmp;
++ res->ie_len += bytes;
++ } else if (clen > 4 && os_strncmp(custom, "tsf=", 4) == 0) {
++ char *spos;
++ int bytes;
++ u8 bin[8];
++ spos = custom + 4;
++ bytes = custom + clen - spos;
++ if (bytes != 16) {
++ wpa_printf(MSG_INFO, "Invalid TSF length (%d)", bytes);
++ return;
++ }
++ bytes /= 2;
++ hexstr2bin(spos, bin, bytes);
++ res->res.tsf += WPA_GET_BE64(bin);
++ }
++}
++
++
++
++static int wext_19_iw_point(struct wpa_driver_wext_data *drv, u16 cmd)
++{
++ return drv->we_version_compiled > 18 &&
++ (cmd == SIOCGIWESSID || cmd == SIOCGIWENCODE ||
++ cmd == IWEVGENIE || cmd == IWEVCUSTOM);
++}
++
++
++
++static void wpa_driver_wext_add_scan_entry(struct wpa_scan_results *res,
++ struct wext_scan_data *data)
++{
++ struct wpa_scan_res **tmp;
++ struct wpa_scan_res *r;
++ size_t extra_len;
++ u8 *pos, *end, *ssid_ie = NULL, *rate_ie = NULL;
++
++ /* Figure out whether we need to fake any IEs */
++ pos = data->ie;
++ end = pos + data->ie_len;
++ while (pos && pos + 1 < end) {
++ if (pos + 2 + pos[1] > end)
++ break;
++ if (pos[0] == WLAN_EID_SSID)
++ ssid_ie = pos;
++ else if (pos[0] == WLAN_EID_SUPP_RATES)
++ rate_ie = pos;
++ else if (pos[0] == WLAN_EID_EXT_SUPP_RATES)
++ rate_ie = pos;
++ pos += 2 + pos[1];
++ }
++
++ extra_len = 0;
++ if (ssid_ie == NULL)
++ extra_len += 2 + data->ssid_len;
++ if (rate_ie == NULL && data->maxrate)
++ extra_len += 3;
++
++ r = os_zalloc(sizeof(*r) + extra_len + data->ie_len);
++ if (r == NULL)
++ return;
++ os_memcpy(r, &data->res, sizeof(*r));
++ r->ie_len = extra_len + data->ie_len;
++ pos = (u8 *) (r + 1);
++ if (ssid_ie == NULL) {
++ /*
++ * Generate a fake SSID IE since the driver did not report
++ * a full IE list.
++ */
++ *pos++ = WLAN_EID_SSID;
++ *pos++ = data->ssid_len;
++ os_memcpy(pos, data->ssid, data->ssid_len);
++ pos += data->ssid_len;
++ }
++ if (rate_ie == NULL && data->maxrate) {
++ /*
++ * Generate a fake Supported Rates IE since the driver did not
++ * report a full IE list.
++ */
++ *pos++ = WLAN_EID_SUPP_RATES;
++ *pos++ = 1;
++ *pos++ = data->maxrate;
++ }
++ if (data->ie)
++ os_memcpy(pos, data->ie, data->ie_len);
++
++ tmp = os_realloc(res->res,
++ (res->num + 1) * sizeof(struct wpa_scan_res *));
++ if (tmp == NULL) {
++ os_free(r);
++ return;
++ }
++ tmp[res->num++] = r;
++ res->res = tmp;
++}
++
++
++
++/**
++ * wpa_driver_wext_get_scan_results - Fetch the latest scan results
++ * @priv: Pointer to private wext data from wpa_driver_wext_init()
++ * Returns: Scan results on success, -1 on failure
++ */
++struct wpa_scan_results * wpa_driver_wext_get_scan_results(void *priv)
++{
++ struct wpa_driver_wext_data *drv = priv;
++ size_t ap_num = 0, len;
++ int first;
++ u8 *res_buf;
++ struct iw_event iwe_buf, *iwe = &iwe_buf;
++ char *pos, *end, *custom;
++ struct wpa_scan_results *res;
++ struct wext_scan_data data;
++#ifdef RTK_INBAND_LE
++ unsigned char cur_ap_num = 0;
++ unsigned char prev_ap_num = 0;
++#endif
++
++
++ res_buf = wpa_driver_wext_giwscan(drv, &len);
++
++ if (res_buf == NULL)
++ return NULL;
++
++ ap_num = 0;
++ first = 1;
++
++ res = os_zalloc(sizeof(*res));
++ if (res == NULL) {
++ os_free(res_buf);
++ return NULL;
++ }
++
++ pos = (char *) res_buf;
++ end = (char *) res_buf + len;
++ os_memset(&data, 0, sizeof(data));
++
++ while (pos + IW_EV_LCP_LEN <= end) {
++ /* Event data may be unaligned, so make a local, aligned copy
++ * before processing. */
++ os_memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
++
++#ifdef RTK_INBAND_LE
++ iwe->len = ntohs(iwe->len);
++ iwe->cmd = ntohs(iwe->cmd);
++#endif
++
++ if (iwe->len <= IW_EV_LCP_LEN)
++ break;
++
++ custom = pos + IW_EV_POINT_LEN;
++ if (wext_19_iw_point(drv, iwe->cmd)) {
++
++#ifdef RTK_INBAND_LE
++ //iwe_buf.u.data.length = ntohs(iwe_buf.u.data.length);
++ //iwe_buf.u.data.flags = ntohs(iwe_buf.u.data.flags);
++#endif
++
++ /* WE-19 removed the pointer from struct iw_point */
++ char *dpos = (char *) &iwe_buf.u.data.length;
++ int dlen = dpos - (char *) &iwe_buf;
++ os_memcpy(dpos, pos + IW_EV_LCP_LEN,
++ sizeof(struct iw_event) - dlen);
++ } else {
++ os_memcpy(&iwe_buf, pos, sizeof(struct iw_event));
++ custom += IW_EV_POINT_OFF;
++
++#ifdef RTK_INBAND_LE
++ iwe->len = ntohs(iwe->len);
++ iwe->cmd = ntohs(iwe->cmd);
++#endif
++ }
++
++
++#ifdef RTK_INBAND_LE
++
++ if(cur_ap_num > prev_ap_num)
++ {
++
++ struct wext_scan_data* scan_data = (struct wext_scan_data*)&data;
++
++ if(first)
++ scan_data->ie_len = ntohl(scan_data->ie_len);
++
++ scan_data->ssid_len = ntohl(scan_data->ssid_len);
++ scan_data->maxrate = ntohl(scan_data->maxrate);
++ scan_data->res.freq = ntohl(scan_data->res.freq);
++ scan_data->res.beacon_int= ntohs(scan_data->res.beacon_int);
++ scan_data->res.caps = ntohs(scan_data->res.caps);
++ scan_data->res.qual = ntohl(scan_data->res.qual);
++ scan_data->res.noise = ntohl(scan_data->res.noise);
++ scan_data->res.level = ntohl(scan_data->res.level);
++ scan_data->res.tsf = ntohll(scan_data->res.tsf);
++ scan_data->res.ie_len = ntohl(scan_data->res.ie_len);
++
++ prev_ap_num = cur_ap_num;
++
++ }
++
++ iwe_buf.u.data.length = ntohs(iwe_buf.u.data.length);
++ iwe_buf.u.data.flags = ntohs(iwe_buf.u.data.flags);
++
++#endif
++
++ switch (iwe->cmd) {
++ case SIOCGIWAP:
++
++#ifdef RTK_INBAND_LE
++ if (!first)
++ cur_ap_num ++;
++#endif
++
++ if (!first)
++ wpa_driver_wext_add_scan_entry(res, &data);
++
++ first = 0;
++ os_free(data.ie);
++
++ os_memset(&data, 0, sizeof(data));
++
++ os_memcpy(data.res.bssid,
++ iwe->u.ap_addr.sa_data, ETH_ALEN);
++
++#ifdef RTK_INBAND_LE //_Eric ?? ????
++ data.res.bssid[2] = iwe->u.ap_addr.sa_data[3];
++ data.res.bssid[3] = iwe->u.ap_addr.sa_data[2];
++ data.res.bssid[4] = iwe->u.ap_addr.sa_data[5];
++ data.res.bssid[5] = iwe->u.ap_addr.sa_data[4];
++#endif
++
++ break;
++ case SIOCGIWMODE:
++ wext_get_scan_mode(iwe, &data);
++ break;
++ case SIOCGIWESSID:
++ wext_get_scan_ssid(iwe, &data, custom, end);
++ break;
++ case SIOCGIWFREQ:
++ wext_get_scan_freq(iwe, &data);
++ break;
++ case IWEVQUAL:
++ wext_get_scan_qual(iwe, &data);
++ break;
++ case SIOCGIWENCODE:
++ wext_get_scan_encode(iwe, &data);
++ break;
++ case SIOCGIWRATE: //_Eric ?? rate genie custom & NO name
++ wext_get_scan_rate(iwe, &data, pos, end);
++ break;
++ case IWEVGENIE:
++ wext_get_scan_iwevgenie(iwe, &data, custom, end);
++ break;
++ case IWEVCUSTOM:
++ wext_get_scan_custom(iwe, &data, custom, end);
++ break;
++ }
++
++ pos += iwe->len;
++ }
++ os_free(res_buf);
++ res_buf = NULL;
++ if (!first)
++ wpa_driver_wext_add_scan_entry(res, &data);
++ os_free(data.ie);
++
++ wpa_printf(MSG_DEBUG, "Received %lu bytes of scan results (%lu BSSes)",
++ (unsigned long) len, (unsigned long) res->num);
++
++ return res;
++}
++
++
++
++static int wpa_driver_wext_get_range(void *priv)
++{
++ struct wpa_driver_wext_data *drv = priv;
++ struct iw_range *range;
++ struct iwreq iwr;
++ int minlen;
++ size_t buflen;
++
++ /*
++ * Use larger buffer than struct iw_range in order to allow the
++ * structure to grow in the future.
++ */
++ buflen = sizeof(struct iw_range) + 500;
++ range = os_zalloc(buflen);
++ if (range == NULL)
++ return -1;
++
++ os_memset(&iwr, 0, sizeof(iwr));
++ os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
++ iwr.u.data.pointer = (caddr_t) range;
++ iwr.u.data.length = buflen;
++
++ minlen = ((char *) &range->enc_capa) - (char *) range +
++ sizeof(range->enc_capa);
++
++#ifdef RTK_INBAND
++ if (inband_ioctl(SIOCGIWRANGE, &iwr) < 0)
++#else
++ if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0)
++#endif
++ {
++ perror("ioctl[SIOCGIWRANGE]");
++ os_free(range);
++ return -1;
++ }
++
++#ifdef RTK_INBAND_LE
++ //_Eric ?? Only convert what used below
++ range->enc_capa = ntohl(range->enc_capa);
++#endif
++
++ if (iwr.u.data.length >= minlen &&
++ range->we_version_compiled >= 18) {
++ wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: WE(compiled)=%d "
++ "WE(source)=%d enc_capa=0x%x",
++ range->we_version_compiled,
++ range->we_version_source,
++ range->enc_capa);
++ drv->has_capability = 1;
++ drv->we_version_compiled = range->we_version_compiled;
++ if (range->enc_capa & IW_ENC_CAPA_WPA) {
++ drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA |
++ WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK;
++ }
++ if (range->enc_capa & IW_ENC_CAPA_WPA2) {
++ drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
++ WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;
++ }
++ drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 |
++ WPA_DRIVER_CAPA_ENC_WEP104;
++ if (range->enc_capa & IW_ENC_CAPA_CIPHER_TKIP)
++ drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP;
++ if (range->enc_capa & IW_ENC_CAPA_CIPHER_CCMP)
++ drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP;
++ if (range->enc_capa & IW_ENC_CAPA_4WAY_HANDSHAKE)
++ drv->capa.flags |= WPA_DRIVER_FLAGS_4WAY_HANDSHAKE;
++ drv->capa.auth = WPA_DRIVER_AUTH_OPEN |
++ WPA_DRIVER_AUTH_SHARED |
++ WPA_DRIVER_AUTH_LEAP;
++
++ wpa_printf(MSG_DEBUG, " capabilities: key_mgmt 0x%x enc 0x%x "
++ "flags 0x%x",
++ drv->capa.key_mgmt, drv->capa.enc, drv->capa.flags);
++ } else {
++ wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: too old (short) data - "
++ "assuming WPA is not supported");
++ }
++
++ os_free(range);
++ return 0;
++}
++
++
++
++static void wpa_driver_wext_disconnect(struct wpa_driver_wext_data *drv)
++{
++ struct iwreq iwr;
++ const u8 null_bssid[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
++ u8 ssid[32];
++ int i;
++
++ /*
++ * Only force-disconnect when the card is in infrastructure mode,
++ * otherwise the driver might interpret the cleared BSSID and random
++ * SSID as an attempt to create a new ad-hoc network.
++ */
++ os_memset(&iwr, 0, sizeof(iwr));
++ os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
++
++#ifdef RTK_INBAND
++ if (inband_ioctl(SIOCGIWMODE, &iwr) < 0)
++#else
++ if (ioctl(drv->ioctl_sock, SIOCGIWMODE, &iwr) < 0)
++#endif
++ {
++ perror("ioctl[SIOCGIWMODE]");
++ iwr.u.mode = IW_MODE_INFRA;
++ }
++
++ if (iwr.u.mode == IW_MODE_INFRA) {
++ /*
++ * Clear the BSSID selection and set a random SSID to make sure
++ * the driver will not be trying to associate with something
++ * even if it does not understand SIOCSIWMLME commands (or
++ * tries to associate automatically after deauth/disassoc).
++ */
++ wpa_driver_wext_set_bssid(drv, null_bssid);
++
++ for (i = 0; i < 32; i++)
++ ssid[i] = rand() & 0xFF;
++ wpa_driver_wext_set_ssid(drv, ssid, 32);
++ }
++}
++
++
++
++/**
++ * wpa_driver_wext_set_mode - Set wireless mode (infra/adhoc), SIOCSIWMODE
++ * @priv: Pointer to private wext data from wpa_driver_wext_init()
++ * @mode: 0 = infra/BSS (associate with an AP), 1 = adhoc/IBSS
++ * Returns: 0 on success, -1 on failure
++ */
++int wpa_driver_wext_set_mode(void *priv, int mode)
++{
++ struct wpa_driver_wext_data *drv = priv;
++ struct iwreq iwr;
++ int ret = -1, flags;
++ unsigned int new_mode = mode ? IW_MODE_ADHOC : IW_MODE_INFRA;
++
++ os_memset(&iwr, 0, sizeof(iwr));
++ os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
++ iwr.u.mode = new_mode;
++
++#ifdef RTK_INBAND
++ if (inband_ioctl(SIOCSIWMODE, &iwr) == 0)
++#else
++ if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) == 0)
++#endif
++ {
++ ret = 0;
++ goto done;
++ }
++
++ if (errno != EBUSY) {
++ perror("ioctl[SIOCSIWMODE]");
++ goto done;
++ }
++
++ /* mac80211 doesn't allow mode changes while the device is up, so if
++ * the device isn't in the mode we're about to change to, take device
++ * down, try to set the mode again, and bring it back up.
++ */
++
++#ifdef RTK_INBAND
++ if (inband_ioctl(SIOCGIWMODE, &iwr) < 0)
++#else
++ if (ioctl(drv->ioctl_sock, SIOCGIWMODE, &iwr) < 0)
++#endif
++ {
++ perror("ioctl[SIOCGIWMODE]");
++ goto done;
++ }
++
++ if (iwr.u.mode == new_mode) {
++ ret = 0;
++ goto done;
++ }
++
++ if (wpa_driver_wext_get_ifflags(drv, &flags) == 0) {
++ (void) wpa_driver_wext_set_ifflags(drv, flags & ~IFF_UP);
++
++ /* Try to set the mode again while the interface is down */
++ iwr.u.mode = new_mode;
++
++#ifdef RTK_INBAND
++ if (inband_ioctl(SIOCSIWMODE, &iwr) < 0)
++#else
++ if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0)
++#endif
++ perror("ioctl[SIOCSIWMODE]");
++ else
++ ret = 0;
++
++ /* Ignore return value of get_ifflags to ensure that the device
++ * is always up like it was before this function was called.
++ */
++ (void) wpa_driver_wext_get_ifflags(drv, &flags);
++ (void) wpa_driver_wext_set_ifflags(drv, flags | IFF_UP);
++ }
++
++done:
++ return ret;
++}
++
++
++
++int wpa_driver_wext_set_operstate(void *priv, int state)
++{
++ struct wpa_driver_wext_data *drv = priv;
++
++ wpa_printf(MSG_DEBUG, "%s: operstate %d->%d (%s)",
++ __func__, drv->operstate, state, state ? "UP" : "DORMANT");
++ drv->operstate = state;
++ return wpa_driver_wext_send_oper_ifla(
++ drv, -1, state ? IF_OPER_UP : IF_OPER_DORMANT);
++}
++
++
++
++const struct wpa_driver_ops wpa_driver_wext_ops = {
++ .name = "wext",
++ .desc = "Linux wireless extensions (generic)",
++ .get_bssid = wpa_driver_wext_get_bssid,
++ .get_ssid = wpa_driver_wext_get_ssid,
++ //.set_wpa = wpa_driver_wext_set_wpa,
++ //.set_key = wpa_driver_wext_set_key,
++ //.set_countermeasures = wpa_driver_wext_set_countermeasures,
++ //.set_drop_unencrypted = wpa_driver_wext_set_drop_unencrypted,
++ .scan = wpa_driver_wext_scan,
++ .get_scan_results2 = wpa_driver_wext_get_scan_results,
++ //.deauthenticate = wpa_driver_wext_deauthenticate,
++ //.disassociate = wpa_driver_wext_disassociate,
++ //.set_mode = wpa_driver_wext_set_mode,
++ //.associate = wpa_driver_wext_associate,
++ //.set_auth_alg = wpa_driver_wext_set_auth_alg,
++ .init = wpa_driver_wext_init,
++ .deinit = wpa_driver_wext_deinit,
++ //.add_pmkid = wpa_driver_wext_add_pmkid,
++ //.remove_pmkid = wpa_driver_wext_remove_pmkid,
++ //.flush_pmkid = wpa_driver_wext_flush_pmkid,
++ //.get_capa = wpa_driver_wext_get_capa,
++ .set_operstate = wpa_driver_wext_set_operstate,
++};
+Index: hostapd-rtk-0.6.10/src/drivers/driver_realtek_wext.h
+===================================================================
+--- /dev/null
++++ hostapd-rtk-0.6.10/src/drivers/driver_realtek_wext.h
+@@ -0,0 +1,106 @@
++/*
++ * 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_WEXT_H
++#define DRIVER_WEXT_H
++
++#include <net/if.h>
++
++#ifdef RTK_INBAND
++#ifndef __IOH_H
++#include <librtk-inband/ioh.h>
++#endif
++#endif
++
++#ifndef ntohll
++#define ntohll(x) (((u64)(ntohl((u32)((x << 32) >> 32))) << 32) | (u32)ntohl(((u32)(x >> 32))))
++#endif
++
++#ifndef htonll
++#define htonll(x) (((u64)(htonl((u32)((x << 32) >> 32))) << 32) | (u32)htonl(((u32)(x >> 32))))
++#endif
++
++
++
++struct wpa_driver_wext_data {
++ void *ctx;
++ int event_sock;
++ int ioctl_sock;
++ int mlme_sock;
++ char ifname[IFNAMSIZ + 1];
++ int ifindex;
++ int ifindex2;
++ int if_removed;
++ u8 *assoc_req_ies;
++ size_t assoc_req_ies_len;
++ u8 *assoc_resp_ies;
++ size_t assoc_resp_ies_len;
++ struct wpa_driver_capa capa;
++ int has_capability;
++ int we_version_compiled;
++
++ /* for set_auth_alg fallback */
++ int use_crypt;
++ int auth_alg_fallback;
++
++ int operstate;
++
++ char mlmedev[IFNAMSIZ + 1];
++
++ int scan_complete_events;
++
++#ifdef RTK_INBAND
++ struct ioh_class netlink_ioh_obj;
++#endif
++
++};
++
++void convert_to_net (const char *name, void *data, int data_size);
++void convert_to_host (const char *name, void *data, int data_size);
++
++int wpa_driver_wext_get_ifflags(struct wpa_driver_wext_data *drv, int *flags);
++int wpa_driver_wext_set_ifflags(struct wpa_driver_wext_data *drv, int flags);
++int wpa_driver_wext_get_bssid(void *priv, u8 *bssid);
++int wpa_driver_wext_set_bssid(void *priv, const u8 *bssid);
++int wpa_driver_wext_get_ssid(void *priv, u8 *ssid);
++int wpa_driver_wext_set_ssid(void *priv, const u8 *ssid, size_t ssid_len);
++//int wpa_driver_wext_set_freq(void *priv, int freq);
++int wpa_driver_wext_set_mode(void *priv, int mode);
++//int wpa_driver_wext_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_wext_scan(void *priv, const u8 *ssid, size_t ssid_len);
++struct wpa_scan_results * wpa_driver_wext_get_scan_results(void *priv);
++
++void wpa_driver_wext_scan_timeout(void *eloop_ctx, void *timeout_ctx);
++
++//int wpa_driver_wext_alternative_ifindex(struct wpa_driver_wext_data *drv,
++ //const char *ifname);
++
++void * wpa_driver_wext_init(void *ctx, const char *ifname);
++void wpa_driver_wext_deinit(void *priv);
++
++int wpa_driver_wext_set_operstate(void *priv, int state);
++//int wpa_driver_wext_get_version(struct wpa_driver_wext_data *drv);
++
++//int wpa_driver_wext_associate(void *priv,
++ // struct wpa_driver_associate_params *params);
++//int wpa_driver_wext_get_capa(void *priv, struct wpa_driver_capa *capa);
++//int wpa_driver_wext_set_auth_param(struct wpa_driver_wext_data *drv,
++ //int idx, u32 value);
++//int wpa_driver_wext_cipher2wext(int cipher);
++//int wpa_driver_wext_keymgmt2wext(int keymgmt);
++
++#endif /* DRIVER_WEXT_H */