diff options
author | Roman Yeryomin <roman@advem.lv> | 2012-09-22 19:44:27 +0300 |
---|---|---|
committer | Roman Yeryomin <roman@advem.lv> | 2012-12-03 00:13:22 +0200 |
commit | 709e200be3507c4f1eed2f4f2e0628b7cfba32c9 (patch) | |
tree | 2db687e9619cf0f83d4f7bac1f5bd8d3b75d6e6b /package/hostapd-rtk/patches/002-common-files.patch | |
parent | 9e96cd6c1bdccc1f9d2d6978ae12523f00bd7f85 (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.patch | 2948 |
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 */ |