summaryrefslogtreecommitdiffstats
path: root/package/hostapd-rtk/patches
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
parent9e96cd6c1bdccc1f9d2d6978ae12523f00bd7f85 (diff)
Add hostapd-rtk and librtk-inband packages
Signed-off-by: Roman Yeryomin <roman@advem.lv>
Diffstat (limited to 'package/hostapd-rtk/patches')
-rw-r--r--package/hostapd-rtk/patches/001-common-diff.patch264
-rw-r--r--package/hostapd-rtk/patches/002-common-files.patch2948
-rw-r--r--package/hostapd-rtk/patches/003-hostapd-diff.patch300
-rw-r--r--package/hostapd-rtk/patches/004-hostapd-files.patch3529
-rw-r--r--package/hostapd-rtk/patches/005-supplicant-diff.patch207
-rw-r--r--package/hostapd-rtk/patches/008-no-inband.patch26
6 files changed, 7274 insertions, 0 deletions
diff --git a/package/hostapd-rtk/patches/001-common-diff.patch b/package/hostapd-rtk/patches/001-common-diff.patch
new file mode 100644
index 000000000..ac942ddcb
--- /dev/null
+++ b/package/hostapd-rtk/patches/001-common-diff.patch
@@ -0,0 +1,264 @@
+Index: hostapd-0.6.10-try/src/drivers/drivers.c
+===================================================================
+--- hostapd-0.6.10-try.orig/src/drivers/drivers.c
++++ hostapd-0.6.10-try/src/drivers/drivers.c
+@@ -33,6 +33,12 @@ extern struct wpa_driver_ops wpa_driver_
+ #ifdef CONFIG_DRIVER_MADWIFI
+ extern struct wpa_driver_ops wpa_driver_madwifi_ops; /* driver_madwifi.c */
+ #endif /* CONFIG_DRIVER_MADWIFI */
++#ifdef CONFIG_DRIVER_REALTEK
++extern struct wpa_driver_ops wpa_driver_realtek_ops; /* driver_madwifi.c */
++#endif /* CONFIG_DRIVER_REALTEK */
++#ifdef CONFIG_DRIVER_REALTEK
++extern struct wpa_driver_ops wpa_driver_realtek_ops; /* driver_realtek.c */
++#endif /* CONFIG_DRIVER_REALTEK */
+ #ifdef CONFIG_DRIVER_ATMEL
+ extern struct wpa_driver_ops wpa_driver_atmel_ops; /* driver_atmel.c */
+ #endif /* CONFIG_DRIVER_ATMEL */
+@@ -96,6 +102,12 @@ struct wpa_driver_ops *wpa_supplicant_dr
+ #ifdef CONFIG_DRIVER_MADWIFI
+ &wpa_driver_madwifi_ops,
+ #endif /* CONFIG_DRIVER_MADWIFI */
++#ifdef CONFIG_DRIVER_REALTEK
++ &wpa_driver_realtek_ops,
++#endif /* CONFIG_DRIVER_REALTEK */
++#ifdef CONFIG_DRIVER_REALTEK
++ &wpa_driver_realtek_ops,
++#endif /* CONFIG_DRIVER_REALTEK */
+ #ifdef CONFIG_DRIVER_ATMEL
+ &wpa_driver_atmel_ops,
+ #endif /* CONFIG_DRIVER_ATMEL */
+Index: hostapd-0.6.10-try/src/rsn_supp/wpa.c
+===================================================================
+--- hostapd-0.6.10-try.orig/src/rsn_supp/wpa.c
++++ hostapd-0.6.10-try/src/rsn_supp/wpa.c
+@@ -426,9 +426,14 @@ static void wpa_supplicant_process_1_of_
+ ptk = &sm->tptk;
+ wpa_derive_ptk(sm, src_addr, key, ptk);
+ /* Supplicant: swap tx/rx Mic keys */
++#ifdef RTK_WPAS
++ printf("NOT SWAP PTK\n");
++#else
++ printf("SWAP PTK\n");
+ os_memcpy(buf, ptk->u.auth.tx_mic_key, 8);
+ os_memcpy(ptk->u.auth.tx_mic_key, ptk->u.auth.rx_mic_key, 8);
+ os_memcpy(ptk->u.auth.rx_mic_key, buf, 8);
++#endif
+ sm->tptk_set = 1;
+
+ if (wpa_supplicant_send_2_of_4(sm, sm->bssid, key, ver, sm->snonce,
+@@ -633,10 +638,16 @@ static int wpa_supplicant_install_gtk(st
+ gd->gtk_len);
+ wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, gd->key_rsc_len);
+ if (sm->group_cipher == WPA_CIPHER_TKIP) {
++#ifdef RTK_WPAS
++ printf("NOT SWAP GTK\n");
++ os_memcpy(gtk_buf, gd->gtk, gd->gtk_len);
++#else
++ printf("SWAP GTK\n");
+ /* Swap Tx/Rx keys for Michael MIC */
+ os_memcpy(gtk_buf, gd->gtk, 16);
+ os_memcpy(gtk_buf + 16, gd->gtk + 24, 8);
+ os_memcpy(gtk_buf + 24, gd->gtk + 16, 8);
++#endif
+ _gtk = gtk_buf;
+ }
+ if (sm->pairwise_cipher == WPA_CIPHER_NONE) {
+@@ -1010,6 +1021,15 @@ static void wpa_supplicant_process_3_of_
+ if (key_info & WPA_KEY_INFO_INSTALL) {
+ if (wpa_supplicant_install_ptk(sm, key))
+ goto failed;
++#ifdef RTK_WPAS
++ else if(sm->key_mgmt == WPA_KEY_MGMT_PSK)
++ {
++ wpa_sm_mlme_setprotection(
++ sm, sm->bssid, MLME_SETPROTECTION_PROTECT_TYPE_RX,
++ MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
++ eapol_sm_notify_portValid(sm->eapol, TRUE);
++ }
++#endif
+ }
+
+ if (key_info & WPA_KEY_INFO_SECURE) {
+Index: hostapd-0.6.10-try/src/utils/common.h
+===================================================================
+--- hostapd-0.6.10-try.orig/src/utils/common.h
++++ hostapd-0.6.10-try/src/utils/common.h
+@@ -455,4 +455,11 @@ static inline int is_zero_ether_addr(con
+ void * __hide_aliasing_typecast(void *foo);
+ #define aliasing_hide_typecast(a,t) (t *) __hide_aliasing_typecast((a))
+
++#define RTK_WPAS
++
++#ifdef RTK_WPAS
++#define RTK_INBAND
++#define RTK_INBAND_LE
++#endif
++
+ #endif /* COMMON_H */
+Index: hostapd-0.6.10-try/src/utils/os_unix.c
+===================================================================
+--- hostapd-0.6.10-try.orig/src/utils/os_unix.c
++++ hostapd-0.6.10-try/src/utils/os_unix.c
+@@ -116,7 +116,7 @@ int os_daemonize(const char *pid_file)
+ #ifdef __uClinux__
+ return -1;
+ #else /* __uClinux__ */
+- if (os_daemon(0, 0)) {
++ if (os_daemon(0, 1)) {
+ perror("daemon");
+ return -1;
+ }
+Index: hostapd-0.6.10-try/src/wps/wps.h
+===================================================================
+--- hostapd-0.6.10-try.orig/src/wps/wps.h
++++ hostapd-0.6.10-try/src/wps/wps.h
+@@ -507,6 +507,10 @@ struct wps_context {
+
+ /* Pending messages from UPnP PutWLANResponse */
+ struct upnp_pending_message *upnp_msgs;
++
++#if defined(RTK_HAPD) || (1)
++ volatile int set_selected_registrar; //add this item to help AP determine to use proxy mode or handle msg by itself.
++#endif
+ };
+
+
+Index: hostapd-0.6.10-try/src/wps/wps_registrar.c
+===================================================================
+--- hostapd-0.6.10-try.orig/src/wps/wps_registrar.c
++++ hostapd-0.6.10-try/src/wps/wps_registrar.c
+@@ -461,6 +461,10 @@ int wps_registrar_add_pin(struct wps_reg
+ wps_registrar_set_selected_timeout,
+ reg, NULL);
+
++#if defined(RTK_HAPD) || (1)
++ reg->wps->set_selected_registrar = 0;
++#endif
++
+ return 0;
+ }
+
+@@ -649,6 +653,11 @@ int wps_registrar_button_pushed(struct w
+ eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL);
+ eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wps_registrar_pbc_timeout,
+ reg, NULL);
++
++#if defined(RTK_HAPD) || (1)
++ reg->wps->set_selected_registrar = 0;
++#endif
++
+ return 0;
+ }
+
+@@ -1040,10 +1049,32 @@ static int wps_build_cred_encr_type(stru
+ static int wps_build_cred_network_key(struct wpabuf *msg,
+ struct wps_credential *cred)
+ {
++
++#if defined(RTK_HAPD) || (1) //If authtication is WEP, always tell enrollee use wepkey1.
++ if(cred->encr_type == 0x2)
++ {
++ wpabuf_put_be16(msg, ATTR_NETWORK_KEY_INDEX);
++ wpabuf_put_be16(msg, 1);
++ wpabuf_put_u8(msg, 1);
++ }
++#endif
++
+ wpa_printf(MSG_DEBUG, "WPS: * Network Key");
+ wpabuf_put_be16(msg, ATTR_NETWORK_KEY);
+ wpabuf_put_be16(msg, cred->key_len);
+ wpabuf_put_data(msg, cred->key, cred->key_len);
++
++#if defined(RTK_HAPD) || (1)
++ if(cred->encr_type == 0x2)
++ {
++ wpabuf_put_be16(msg, ATTR_WEPTRANSMITKEY);
++ wpabuf_put_be16(msg, 1);
++ wpabuf_put_u8(msg, 1);
++ }
++#endif
++
++
++
+ return 0;
+ }
+
+@@ -1446,6 +1477,10 @@ struct wpabuf * wps_registrar_get_msg(st
+ struct wpabuf *msg;
+
+ #ifdef CONFIG_WPS_UPNP
++
++#if defined(RTK_HAPD) || (1)
++ if(wps->wps->set_selected_registrar == 1)
++#endif
+ if (wps->wps->wps_upnp) {
+ struct upnp_pending_message *p, *prev = NULL;
+ if (wps->ext_reg > 1)
+@@ -2523,6 +2558,19 @@ enum wps_process_res wps_registrar_proce
+ }
+ if (wps->ext_reg > 1)
+ wps_registrar_free_pending_m2(wps->wps);
++
++#if defined (RTK_HAPD) || (1)
++ wpa_printf(MSG_DEBUG, "WPS: set_selected_registrar = %d", wps->wps->set_selected_registrar);
++ if( wps->wps->wps_upnp && (wps->wps->set_selected_registrar == 1)
++ && upnp_wps_subscribers(wps->wps->wps_upnp))
++ {
++ if(wps->ext_reg == 0)
++ wps->ext_reg = 1;
++ }
++ else
++ wps->ext_reg = 0;
++#endif
++
+ if (wps->wps->wps_upnp && wps->ext_reg &&
+ wps->wps->upnp_msgs == NULL &&
+ (op_code == WSC_MSG || op_code == WSC_Done || op_code == WSC_NACK))
+Index: hostapd-0.6.10-try/src/wps/wps_upnp_event.c
+===================================================================
+--- hostapd-0.6.10-try.orig/src/wps/wps_upnp_event.c
++++ hostapd-0.6.10-try/src/wps/wps_upnp_event.c
+@@ -485,8 +485,14 @@ void event_send_all_later(struct upnp_wp
+ if (sm->event_send_all_queued)
+ return;
+ sm->event_send_all_queued = 1;
++
++#if defined(RTK_HAPD) || (1)
++ event_send_all_later_handler(NULL, sm);
++#else
+ eloop_register_timeout(EVENT_DELAY_SECONDS, EVENT_DELAY_MSEC,
+ event_send_all_later_handler, NULL, sm);
++#endif
++
+ }
+
+
+Index: hostapd-0.6.10-try/src/wps/wps_upnp_web.c
+===================================================================
+--- hostapd-0.6.10-try.orig/src/wps/wps_upnp_web.c
++++ hostapd-0.6.10-try/src/wps/wps_upnp_web.c
+@@ -1053,6 +1053,11 @@ web_process_set_selected_registrar(struc
+ enum http_reply_code ret;
+
+ wpa_printf(MSG_DEBUG, "WPS UPnP: SetSelectedRegistrar");
++
++#if defined(RTK_HAPD) || (1)
++ sm->wps->set_selected_registrar = 0;
++#endif
++
+ msg = web_get_item(data, "NewMessage", &ret);
+ if (msg == NULL)
+ return ret;
+@@ -1064,6 +1069,11 @@ web_process_set_selected_registrar(struc
+ wpabuf_free(msg);
+ *replyname = NULL;
+ *reply = NULL;
++
++#if defined(RTK_HAPD) || (1)
++ sm->wps->set_selected_registrar = 1;
++#endif
++
+ return HTTP_OK;
+ }
+
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 */
diff --git a/package/hostapd-rtk/patches/003-hostapd-diff.patch b/package/hostapd-rtk/patches/003-hostapd-diff.patch
new file mode 100644
index 000000000..108bca5d8
--- /dev/null
+++ b/package/hostapd-rtk/patches/003-hostapd-diff.patch
@@ -0,0 +1,300 @@
+Index: hostapd-0.6.10-try/hostapd/accounting.c
+===================================================================
+--- hostapd-0.6.10-try.orig/hostapd/accounting.c
++++ hostapd-0.6.10-try/hostapd/accounting.c
+@@ -28,10 +28,6 @@
+ * input/output octets and updates Acct-{Input,Output}-Gigawords. */
+ #define ACCT_DEFAULT_UPDATE_INTERVAL 300
+
+-static void accounting_sta_get_id(struct hostapd_data *hapd,
+- struct sta_info *sta);
+-
+-
+ static struct radius_msg * accounting_msg(struct hostapd_data *hapd,
+ struct sta_info *sta,
+ int status_type)
+@@ -400,7 +396,7 @@ void accounting_sta_stop(struct hostapd_
+ }
+
+
+-static void accounting_sta_get_id(struct hostapd_data *hapd,
++void accounting_sta_get_id(struct hostapd_data *hapd,
+ struct sta_info *sta)
+ {
+ sta->acct_session_id_lo = hapd->acct_session_id_lo++;
+Index: hostapd-0.6.10-try/hostapd/accounting.h
+===================================================================
+--- hostapd-0.6.10-try.orig/hostapd/accounting.h
++++ hostapd-0.6.10-try/hostapd/accounting.h
+@@ -22,5 +22,7 @@ int accounting_init(struct hostapd_data
+ void accounting_deinit(struct hostapd_data *hapd);
+ int accounting_reconfig(struct hostapd_data *hapd,
+ struct hostapd_config *oldconf);
++void accounting_sta_get_id(struct hostapd_data *hapd,
++ struct sta_info *sta);
+
+ #endif /* ACCOUNTING_H */
+Index: hostapd-0.6.10-try/hostapd/config.c
+===================================================================
+--- hostapd-0.6.10-try.orig/hostapd/config.c
++++ hostapd-0.6.10-try/hostapd/config.c
+@@ -1461,6 +1461,7 @@ struct hostapd_config * hostapd_config_r
+ conf->driver = hostapd_drivers[j];
+ break;
+ }
++ wpa_printf(MSG_ERROR, "Index:%d driver name:%s, choice:%s",j,hostapd_drivers[j]->name,pos);
+ }
+ if (conf->driver == NULL) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid/"
+@@ -2251,7 +2252,9 @@ struct hostapd_config * hostapd_config_r
+ } else {
+ wpa_printf(MSG_ERROR, "Line %d: unknown configuration "
+ "item '%s'", line, buf);
++#ifndef RTK_HAPD //In order to support realtek private configurations
+ errors++;
++#endif
+ }
+ }
+
+Index: hostapd-0.6.10-try/hostapd/defconfig
+===================================================================
+--- hostapd-0.6.10-try.orig/hostapd/defconfig
++++ hostapd-0.6.10-try/hostapd/defconfig
+@@ -10,7 +10,7 @@
+ # to override previous values of the variables.
+
+ # Driver interface for Host AP driver
+-CONFIG_DRIVER_HOSTAP=y
++#CONFIG_DRIVER_HOSTAP=y
+
+ # Driver interface for wired authenticator
+ #CONFIG_DRIVER_WIRED=y
+@@ -19,6 +19,9 @@ CONFIG_DRIVER_HOSTAP=y
+ #CONFIG_DRIVER_MADWIFI=y
+ #CFLAGS += -I../../madwifi # change to the madwifi source directory
+
++# Driver interface for realtek driver
++CONFIG_DRIVER_REALTEK=y
++
+ # Driver interface for Prism54 driver
+ #CONFIG_DRIVER_PRISM54=y
+
+@@ -107,9 +110,9 @@ CONFIG_EAP_TTLS=y
+ #CONFIG_EAP_FAST=y
+
+ # Wi-Fi Protected Setup (WPS)
+-#CONFIG_WPS=y
++CONFIG_WPS=y
+ # Enable UPnP support for external WPS Registrars
+-#CONFIG_WPS_UPNP=y
++CONFIG_WPS_UPNP=y
+
+ # EAP-IKEv2
+ #CONFIG_EAP_IKEV2=y
+Index: hostapd-0.6.10-try/hostapd/driver.h
+===================================================================
+--- hostapd-0.6.10-try.orig/hostapd/driver.h
++++ hostapd-0.6.10-try/hostapd/driver.h
+@@ -195,6 +195,10 @@ struct wpa_driver_ops {
+ const u8 *ie, size_t len);
+ int (*set_wps_probe_resp_ie)(const char *ifname, void *priv,
+ const u8 *ie, size_t len);
++
++#ifdef RTK_HAPD
++ int (*driver_on)(void *priv, int on);
++#endif
+ };
+
+ static inline void *
+Index: hostapd-0.6.10-try/hostapd/drivers.c
+===================================================================
+--- hostapd-0.6.10-try.orig/hostapd/drivers.c
++++ hostapd-0.6.10-try/hostapd/drivers.c
+@@ -27,6 +27,9 @@ extern struct wpa_driver_ops wpa_driver_
+ #ifdef CONFIG_DRIVER_MADWIFI
+ extern struct wpa_driver_ops wpa_driver_madwifi_ops; /* driver_madwifi.c */
+ #endif /* CONFIG_DRIVER_MADWIFI */
++#ifdef CONFIG_DRIVER_REALTEK
++extern struct wpa_driver_ops wpa_driver_realtek_ops; /* driver_realtek.c */
++#endif /* CONFIG_DRIVER_REALTEK */
+ #ifdef CONFIG_DRIVER_ATHEROS
+ extern struct wpa_driver_ops wpa_driver_atheros_ops; /* driver_atheros.c */
+ #endif /* CONFIG_DRIVER_ATHEROS */
+@@ -58,6 +61,9 @@ struct wpa_driver_ops *hostapd_drivers[]
+ #ifdef CONFIG_DRIVER_MADWIFI
+ &wpa_driver_madwifi_ops,
+ #endif /* CONFIG_DRIVER_MADWIFI */
++#ifdef CONFIG_DRIVER_REALTEK
++ &wpa_driver_realtek_ops,
++#endif /* CONFIG_DRIVER_REALTEK */
+ #ifdef CONFIG_DRIVER_ATHEROS
+ &wpa_driver_atheros_ops,
+ #endif /* CONFIG_DRIVER_ATHEROS */
+Index: hostapd-0.6.10-try/hostapd/hostapd.c
+===================================================================
+--- hostapd-0.6.10-try.orig/hostapd/hostapd.c
++++ hostapd-0.6.10-try/hostapd/hostapd.c
+@@ -361,6 +361,10 @@ int hostapd_reload_config(struct hostapd
+ hapd->conf = &newconf->bss[0];
+ iface->conf = newconf;
+
++#ifdef RTK_HAPD //Configuration works only after driver OFF -> ON
++ hapd->driver->driver_on(hapd->drv_priv, 0);
++#endif
++
+ if (hostapd_setup_wpa_psk(hapd->conf)) {
+ wpa_printf(MSG_ERROR, "Failed to re-configure WPA PSK "
+ "after reloading configuration");
+@@ -387,11 +391,22 @@ int hostapd_reload_config(struct hostapd
+ /* try to continue */
+ }
+
++#ifdef RTK_HAPD
++ hostapd_deinit_wps(hapd);
++
++ if(hostapd_init_wps(hapd, hapd->conf))
++ wpa_printf(MSG_ERROR, "Could not init wps when reloading");
++#endif
++
+ if (hapd->conf->ieee802_1x || hapd->conf->wpa)
+ hostapd_set_ieee8021x(hapd->conf->iface, hapd, 1);
+
+ hostapd_config_free(oldconf);
+
++#ifdef RTK_HAPD //Configuration works only after driver OFF -> ON
++ hapd->driver->driver_on(hapd->drv_priv, 1);
++#endif
++
+ wpa_printf(MSG_DEBUG, "Reconfigured interface %s", hapd->conf->iface);
+
+ return 0;
+@@ -1321,6 +1336,7 @@ static int hostapd_setup_bss(struct host
+ }
+
+ hostapd_flush_old_stations(hapd);
++
+ hostapd_set_privacy(hapd, 0);
+
+ hostapd_broadcast_wep_clear(hapd);
+Index: hostapd-0.6.10-try/hostapd/hostapd.h
+===================================================================
+--- hostapd-0.6.10-try.orig/hostapd/hostapd.h
++++ hostapd-0.6.10-try/hostapd/hostapd.h
+@@ -17,6 +17,8 @@
+ #ifndef HOSTAPD_H
+ #define HOSTAPD_H
+
++#define RTK_HAPD //For realtek driver support
++
+ #include "common.h"
+ #include "ap.h"
+
+Index: hostapd-0.6.10-try/hostapd/iapp.c
+===================================================================
+--- hostapd-0.6.10-try.orig/hostapd/iapp.c
++++ hostapd-0.6.10-try/hostapd/iapp.c
+@@ -461,6 +461,16 @@ struct iapp_data * iapp_init(struct host
+ return NULL;
+ }
+
++#ifdef RTK_HAPD //Add these cmd to make IAPP init successful
++ {
++ char cmd[128];
++ sprintf(cmd, "route delete -net 224.0.0.0 netmask 240.0.0.0 dev %s", iface);
++ system(cmd);
++ sprintf(cmd, "route add -net 224.0.0.0 netmask 240.0.0.0 dev %s", iface);
++ system(cmd);
++ }
++#endif
++
+ os_memset(&mreq, 0, sizeof(mreq));
+ mreq.imr_multiaddr = iapp->multicast;
+ mreq.imr_address.s_addr = INADDR_ANY;
+Index: hostapd-0.6.10-try/hostapd/wps_hostapd.c
+===================================================================
+--- hostapd-0.6.10-try.orig/hostapd/wps_hostapd.c
++++ hostapd-0.6.10-try/hostapd/wps_hostapd.c
+@@ -364,6 +364,10 @@ static int hostapd_wps_cred_cb(void *ctx
+ fprintf(nconf, "%02x", cred->key[i]);
+ }
+ fprintf(nconf, "\n");
++
++#ifdef RTK_HAPD
++ fprintf(nconf, "wep_key_len_unicast=%d\n", (cred->key_len)/2);
++#endif
+ }
+ }
+
+@@ -382,6 +386,12 @@ static int hostapd_wps_cred_cb(void *ctx
+ str_starts(buf, "wpa_pairwise=") ||
+ str_starts(buf, "rsn_pairwise=") ||
+ str_starts(buf, "wpa_key_mgmt=") ||
++#ifdef RTK_HAPD
++ str_starts(buf, "wep_default_key=") ||
++ str_starts(buf, "wep_key0=") ||
++ str_starts(buf, "wep_key_len_unicast=") ||
++ str_starts(buf, "ieee8021x=") ||
++#endif
+ str_starts(buf, "wpa_passphrase="))) {
+ fprintf(nconf, "#WPS# %s", buf);
+ } else
+@@ -403,8 +413,11 @@ static int hostapd_wps_cred_cb(void *ctx
+ /* Schedule configuration reload after short period of time to allow
+ * EAP-WSC to be finished.
+ */
+- eloop_register_timeout(0, 100000, wps_reload_config, hapd->iface,
+- NULL);
++#ifdef RTK_HAPD
++ eloop_register_timeout(5, 0, wps_reload_config, hapd->iface, NULL);
++#else
++ eloop_register_timeout(0, 100000, wps_reload_config, hapd->iface, NULL);
++#endif
+
+ /* TODO: dualband AP may need to update multiple configuration files */
+
+@@ -666,6 +679,10 @@ int hostapd_init_wps(struct hostapd_data
+ wps->model_url = hapd->conf->model_url;
+ wps->upc = hapd->conf->upc;
+
++#if defined(RTK_HAPD) || (1)
++ wps->set_selected_registrar = 0;
++#endif
++
+ if (hostapd_wps_upnp_init(hapd, wps) < 0) {
+ wpa_printf(MSG_ERROR, "Failed to initialize WPS UPnP");
+ wps_registrar_deinit(wps->registrar);
+Index: hostapd-0.6.10-try/hostapd/wpa.c
+===================================================================
+--- hostapd-0.6.10-try.orig/hostapd/wpa.c
++++ hostapd-0.6.10-try/hostapd/wpa.c
+@@ -49,7 +49,11 @@ static int wpa_gtk_update(struct wpa_aut
+
+ static const u32 dot11RSNAConfigGroupUpdateCount = 4;
+ static const u32 dot11RSNAConfigPairwiseUpdateCount = 4;
++#ifdef INBAND_CTRL
++static const u32 eapol_key_timeout_first = 1000; /* ms */
++#else
+ static const u32 eapol_key_timeout_first = 100; /* ms */
++#endif
+ static const u32 eapol_key_timeout_subseq = 1000; /* ms */
+
+ /* TODO: make these configurable */
+Index: hostapd-0.6.10-try/hostapd/Makefile
+===================================================================
+--- hostapd-0.6.10-try.orig/hostapd/Makefile
++++ hostapd-0.6.10-try/hostapd/Makefile
+@@ -122,6 +122,14 @@ OBJS += driver_atheros.o
+ CONFIG_L2_PACKET=y
+ endif
+
++ifdef CONFIG_DRIVER_REALTEK
++CFLAGS += -DCONFIG_DRIVER_REALTEK
++CFLAGS += -DINBAND_CTRL
++LIBS += -linband
++OBJS += driver_realtek.o
++CONFIG_L2_PACKET=y
++endif
++
+ ifdef CONFIG_DRIVER_PRISM54
+ CFLAGS += -DCONFIG_DRIVER_PRISM54
+ OBJS += driver_prism54.o
diff --git a/package/hostapd-rtk/patches/004-hostapd-files.patch b/package/hostapd-rtk/patches/004-hostapd-files.patch
new file mode 100644
index 000000000..a25374ef4
--- /dev/null
+++ b/package/hostapd-rtk/patches/004-hostapd-files.patch
@@ -0,0 +1,3529 @@
+Index: hostapd-rtk-0.6.10/hostapd/driver_realtek.c
+===================================================================
+--- /dev/null
++++ hostapd-rtk-0.6.10/hostapd/driver_realtek.c
+@@ -0,0 +1,3251 @@
++/*
++ * hostapd / Driver interaction with Realtek 802.11 driver
++ * Copyright (c)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * Alternatively, this software may be distributed under the terms of BSD
++ * license.
++ *
++ * See README and COPYING for more details.
++ */
++
++#include "includes.h"
++#include "common.h"
++#include <net/if.h>
++#include <sys/ioctl.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 */
++
++#include <net/if_arp.h>
++#include "wireless_copy.h"
++//#include <linux/wireless.h>
++
++//#include <netpacket/packet.h>
++
++#include "hostapd.h"
++#include "driver.h"
++#include "ieee802_1x.h"
++#include "eloop.h"
++#include "priv_netlink.h"
++#include "sta_info.h"
++#include "l2_packet/l2_packet.h"
++
++#include "eapol_sm.h"
++#include "wpa.h"
++#include "radius/radius.h"
++#include "ieee802_11.h"
++#include "accounting.h"
++#include "common.h"
++#include "wps_hostapd.h"
++
++#ifndef EAP_WPS
++#define EAP_WPS
++#endif
++
++#include "./driver_realtek.h"
++
++#ifdef CONFIG_WPS
++#ifdef IEEE80211_IOCTL_FILTERFRAME
++//#include <netpacket/packet.h>
++#ifndef __LINUX_IF_PACKET_H
++//#ifndef __NETPACKET_PACKET_H
++#include <linux/if_packet.h>
++//#include <netpacket/packet.h>
++#endif
++
++#ifndef ETH_P_80211_RAW
++#define ETH_P_80211_RAW 0x0019
++#endif
++#endif /* IEEE80211_IOCTL_FILTERFRAME */
++#endif /* CONFIG_WPS */
++
++/*
++ * Avoid conflicts with hostapd definitions by undefining couple of defines
++ * from madwifi header files.
++ */
++#undef RSN_VERSION
++#undef WPA_VERSION
++#undef WPA_OUI_TYPE
++#undef WME_OUI_TYPE
++
++#if defined(INBAND_CTRL)
++#ifndef __IOH_H
++#include <librtk-inband/ioh.h>
++#endif
++#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
++#undef STAND_ALONE
++#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)
++#else
++#define STAND_ALONE
++#endif
++
++//#define HOST_LITTLE_ENDIAN 1 //mark_endian
++
++#ifdef RTK_MBSSID
++
++struct i802_bss {
++ //void *ctx; //back pointer to hapd per bss data
++ struct realtek_driver_data *drv;
++ struct i802_bss *next;
++ int ifindex;
++ char ifname[IFNAMSIZ + 1];
++ struct l2_packet_data *sock_xmit; /* raw packet xmit socket */
++ //unsigned int beacon_set:1;
++};
++
++#endif
++
++
++struct realtek_driver_data {
++ //struct driver_ops ops; /* base class */
++ struct hostapd_data *hapd; /* back pointer */
++
++ char iface[IFNAMSIZ + 1];
++ int ifindex;
++ struct l2_packet_data *sock_xmit; /* raw packet xmit socket */
++#ifdef RTK_MBSSID
++ int sock_recv;
++#else
++ struct l2_packet_data *sock_recv; /* raw packet recv socket */
++#endif
++ int ioctl_sock; /* socket for ioctl() use */
++ int wext_sock; /* socket for wireless events */
++ int we_version;
++ u8 acct_mac[ETH_ALEN];
++ struct hostap_sta_driver_data acct_data;
++#if defined(INBAND_CTRL)
++ struct ioh_class netlink_ioh_obj;
++#endif
++
++#ifdef RTK_MBSSID
++ struct i802_bss first_bss;
++ int if_indices[RTK_MAX_IF_INDEX];
++ int num_if_indices;
++#endif
++};
++
++struct rtk_hapd_config rtk_config;
++
++const struct wpa_driver_ops wpa_driver_realtek_ops;
++
++static void realtek_deinit(void *priv);
++static int realtek_sta_deauth(void *priv, const u8 *addr, int reason_code);
++
++#ifdef EAP_WPS
++static int realtek_set_wps_beacon_ie(const char *ifname, void *priv, const u8 *iebuf, size_t iebuflen);
++static int realtek_set_wps_probe_resp_ie(const char *ifname, void *priv, const u8 *iebuf, size_t iebuflen);
++static int realtek_set_wps_assoc_resp_ie(const char *ifname, void *priv, const u8 *iebuf, size_t iebuflen);
++static int realtek_start_receive_prob_req(void *priv);
++#endif /* EAP_WPS */
++
++#ifdef RTK_HAPD
++static int realtek_driver_on(void *priv, int on);
++static int realtek_hapd_config(void *priv);
++#endif
++
++static int realtek_read_priv_vap_cfg(const char *ifname,void *priv, struct rtk_hapd_config* config);
++static int realtek_config_rate(int *rate_list, unsigned int *rate_config);
++static int realtek_read_hapd_cfg(struct hostapd_data *hapd,void *priv, struct rtk_hapd_config* config);
++
++
++#ifdef MODIFIED_BY_SONY
++static int wext_set_key(void *priv, int alg,
++ const u8 *addr, int key_idx,
++ int set_tx, const u8 *seq, size_t seq_len,
++ const u8 *key, size_t key_len);
++#endif /* MODIFIED_BY_SONY */
++
++#ifdef RTK_MBSSID
++static int add_ifidx(struct realtek_driver_data *drv, int ifidx)
++{
++ int i;
++ wpa_printf(MSG_DEBUG, "nl80211: Add own interface ifindex %d",
++ ifidx);
++ for (i = 0; i < drv->num_if_indices; i++) {
++ if (drv->if_indices[i] == 0) {
++ drv->if_indices[i] = ifidx;
++ return;
++ }
++ }
++
++ return -1;
++}
++
++static int have_ifidx(struct realtek_driver_data *drv, int ifidx)
++{
++ int i;
++
++ for (i = 0; i < drv->num_if_indices; i++)
++ if (drv->if_indices[i] == ifidx)
++ return 1;
++ return 0;
++}
++
++
++static struct hostapd_data *find_hapd_by_ifname(void *priv,const char *ifname)
++{
++ struct realtek_driver_data *drv = priv;
++ struct hostapd_data *hapd = drv->hapd,*bss_hapd=hapd;
++ struct hostapd_iface *iface = hapd->iface;
++ struct hostapd_bss_config *conf;
++ int j;
++
++
++ for (j = 0; j < iface->num_bss; j++)
++ {
++ bss_hapd = iface->bss[j] ;
++ conf = bss_hapd->conf;
++ if(os_strcmp(conf->iface, ifname) == 0) //find the entry
++ break;
++
++ }
++
++ return bss_hapd;
++}
++
++static struct hostapd_data *find_hapd_by_ifindex(void *priv,int ifindex)
++{
++ struct realtek_driver_data *drv = priv;
++ struct hostapd_data *hapd = drv->hapd;
++ struct i802_bss *tbss = &drv->first_bss,*bss;
++
++
++ if( drv->ifindex == ifindex) //if it's for Root AP
++ goto end;
++
++ while (tbss) { //find the VAP
++
++ bss = tbss->next;
++
++ if(bss == NULL)
++ break;
++
++ if( bss->ifindex == ifindex ) //find the entry
++ {
++ hapd = (struct hostapd_data *)find_hapd_by_ifname(drv,bss->ifname);
++ break;
++ }
++ tbss = tbss->next;
++ }
++end:
++ return hapd;
++}
++
++static struct hostapd_data *find_hapd_by_sta(void *priv,u8 *sta_addr)
++{
++ struct realtek_driver_data *drv = priv;
++ struct hostapd_data *hapd = drv->hapd;
++ struct hostapd_iface *iface = hapd->iface;
++ int j;
++
++ for (j = 0; j < iface->num_bss; j++) {
++ if (ap_get_sta(iface->bss[j], sta_addr)) {
++ hapd = iface->bss[j];
++ break;
++ }
++ }
++
++ return hapd;
++}
++
++static int rtk_free_bss_by_ifname(void *priv, const char *ifname)
++{
++ struct realtek_driver_data *drv = priv;
++ struct i802_bss *tbss = &drv->first_bss,*bss;
++
++ while (tbss) {
++
++ bss = tbss->next;
++ if(bss == NULL)
++ break;
++ if(os_strcmp(bss->ifname, ifname) == 0) //find the entry
++ {
++ if (bss->sock_xmit != NULL) //deinit socket
++ l2_packet_deinit(bss->sock_xmit);
++
++ tbss->next = bss->next;
++ os_free(bss);
++ break;
++ }
++ tbss = tbss->next ;
++ }
++ return 0;
++}
++
++static struct l2_packet_data *rtk_find_l2sock_by_ifname(void *priv, const char *ifname)
++{
++ struct realtek_driver_data *drv = priv;
++ struct i802_bss *tbss = &drv->first_bss,*bss;
++ struct l2_packet_data *eapol_sock=drv->sock_xmit;
++
++ if(os_strcmp(drv->iface,ifname)==0) //if it's for Root AP
++ goto end;
++
++
++ while (tbss) { //find the VAP
++
++ bss = tbss->next;
++
++ if(bss == NULL)
++ break;
++
++ if(os_strcmp(bss->ifname, ifname) == 0) //find the entry
++ {
++ eapol_sock = bss->sock_xmit;
++ break;
++ }
++ tbss = tbss->next;
++ }
++
++end:
++ return eapol_sock;
++}
++
++static void handle_eapol(int sock, void *eloop_ctx, void *sock_ctx)
++{
++ struct realtek_driver_data *drv = eloop_ctx;
++ struct hostapd_data *hapd = drv->hapd;
++ struct sockaddr_ll lladdr;
++ unsigned char buf[3000];
++ int len,j;
++ socklen_t fromlen = sizeof(lladdr);
++ struct hostapd_iface *iface = hapd->iface;
++ unsigned char *sa;
++ len = recvfrom(sock, buf, sizeof(buf), 0,
++ (struct sockaddr *)&lladdr, &fromlen);
++
++ if (len < 0) {
++ perror("recv");
++ return;
++ }
++ sa = (unsigned char *)lladdr.sll_addr;
++ //if (have_ifidx(drv, lladdr.sll_ifindex)) //mark_mbssid , if br0 rcv??
++ //{
++ for (j = 0; j < iface->num_bss; j++) {
++ if (ap_get_sta(iface->bss[j], sa)) {
++ hapd = iface->bss[j];
++ break;
++ }
++ }
++
++ /*printf("handle_eapol if=%s src_mac=%x:%x:%x:%x:%x:%x\n",hapd->conf->iface,
++ sa[0],sa[1],sa[2],sa[3],sa[4],sa[5]);*/
++ ieee802_1x_receive(hapd, sa, buf, len);
++ //}
++}
++#endif
++
++#ifdef INBAND_CTRL // HOST_LITTLE_ENDIAN
++static void rtk_cfg_to_bigEndian(struct rtk_hapd_config *config_ptr)
++{
++ config_ptr->band = htonl(config_ptr->band);
++ config_ptr->channel = htonl(config_ptr->channel);
++ config_ptr->bcnint = htonl(config_ptr->bcnint);
++ config_ptr->dtimperiod = htonl(config_ptr->dtimperiod);
++ config_ptr->stanum = htonl(config_ptr->stanum);
++ config_ptr->rtsthres = htonl(config_ptr->rtsthres);
++ config_ptr->fragthres = htonl(config_ptr->fragthres);
++ config_ptr->oprates = htonl(config_ptr->oprates);
++ config_ptr->basicrates = htonl(config_ptr->basicrates);
++ config_ptr->preamble = htonl(config_ptr->preamble);
++ config_ptr->aclmode = htonl(config_ptr->aclmode);
++ config_ptr->aclnum = htonl(config_ptr->aclnum);
++ config_ptr->hiddenAP = htonl(config_ptr->hiddenAP);
++ config_ptr->qos_enable = htonl(config_ptr->qos_enable);
++ config_ptr->expired_time = htonl(config_ptr->expired_time);
++ config_ptr->block_relay = htonl(config_ptr->block_relay);
++ config_ptr->shortGI20M = htonl(config_ptr->shortGI20M);
++ config_ptr->shortGI40M = htonl(config_ptr->shortGI40M);
++ //Above are for Hostapd owned configurations //====================================================
++ config_ptr->phyBandSelect = htonl(config_ptr->phyBandSelect);
++ config_ptr->ther = htonl(config_ptr->ther);
++ config_ptr->swcrypto = htonl(config_ptr->swcrypto);
++ config_ptr->regdomain = htonl(config_ptr->regdomain);
++ config_ptr->autorate = htonl(config_ptr->autorate);
++ config_ptr->fixrate = htonl(config_ptr->fixrate);
++ config_ptr->disable_protection = htonl(config_ptr->disable_protection);
++ config_ptr->disable_olbc = htonl(config_ptr->disable_olbc);
++ config_ptr->deny_legacy = htonl(config_ptr->deny_legacy);
++ config_ptr->opmode = htonl(config_ptr->opmode);
++ config_ptr->vap_enable = htonl(config_ptr->vap_enable);
++ config_ptr->use40M = htonl(config_ptr->use40M);
++ config_ptr->_2ndchoffset = htonl(config_ptr->_2ndchoffset);
++ config_ptr->ampdu = htonl(config_ptr->ampdu);
++ config_ptr->coexist = htonl(config_ptr->coexist);
++ config_ptr->rssi_dump = htonl(config_ptr->rssi_dump);
++ config_ptr->mp_specific = htonl(config_ptr->mp_specific);
++ config_ptr->use_ext_pa = htonl(config_ptr->use_ext_pa);
++ config_ptr->macPhyMode = htonl(config_ptr->macPhyMode);
++ //Below are for RTK private configurations
++ }
++#endif
++
++
++static int
++set80211priv(const char *ifname,struct realtek_driver_data *drv, int op, void *data, int len)
++{
++ struct iwreq iwr;
++ int do_inline = (len < IFNAMSIZ);
++
++ /* Poorly thought out inteface -- certain ioctls MUST use
++ * the non-inline method:
++ */
++ if (
++ #ifdef IEEE80211_IOCTL_SET_APPIEBUF
++ op == IEEE80211_IOCTL_SET_APPIEBUF ||
++ #endif
++ #ifdef IEEE80211_IOCTL_FILTERFRAME
++ op == IEEE80211_IOCTL_FILTERFRAME ||
++ #endif
++ 0
++ ) {
++ do_inline = 0;
++ }
++
++ memset(&iwr, 0, sizeof(iwr));
++ strncpy(iwr.ifr_name, ifname, IFNAMSIZ);
++
++ if (do_inline) {
++ memcpy(iwr.u.name, data, len);
++ } else {
++ /*
++ * Argument data MAY BE 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 STAND_ALONE
++ if (ioctl(drv->ioctl_sock, op, &iwr) < 0) {
++ {
++ int err = errno;
++ perror("set80211priv ioctl failed");
++ wpa_printf(MSG_ERROR, "ioctl 0x%x failed errno=%d",
++ op, err);
++ }
++ return -1;
++ }
++#endif
++#if defined(INBAND_CTRL)
++ INBAND_IOCTLPKT_DUMP(&iwr,sizeof(iwr));
++
++ if ( inband_ioctl(op, &iwr) < 0) {
++ perror("set80211priv ioctl failed");
++ wpa_printf(MSG_ERROR, "ioctl 0x%x failed", op);
++ return -1;
++ }
++#endif
++
++
++ return 0;
++}
++
++static int
++set80211param(const char *ifname,struct realtek_driver_data *drv, int op, int arg)
++{
++ struct iwreq iwr;
++
++ memset(&iwr, 0, sizeof(iwr));
++ strncpy(iwr.ifr_name, ifname, IFNAMSIZ);
++#ifdef INBAND_CTRL //HOST_LITTLE_ENDIAN
++// int need endian swap
++ op = htonl(op);
++ arg = htonl(arg);
++#endif
++ iwr.u.mode = op;
++ memcpy(iwr.u.name+sizeof(__u32), &arg, sizeof(arg));
++
++#ifdef STAND_ALONE
++ if (ioctl(drv->ioctl_sock, IEEE80211_IOCTL_SETPARAM, &iwr) < 0) {
++ perror("ioctl[IEEE80211_IOCTL_SETPARAM]");
++ wpa_printf(MSG_DEBUG, "%s: Failed to set parameter (op %d "
++ "arg %d)", __func__, op, arg);
++ return -1;
++ }
++#endif
++#if defined(INBAND_CTRL)
++ INBAND_IOCTLPKT_DUMP(&iwr,sizeof(iwr));
++ if (inband_ioctl(IEEE80211_IOCTL_SETPARAM, &iwr) < 0) {
++ perror("ioctl[IEEE80211_IOCTL_SETPARAM]");
++ wpa_printf(MSG_DEBUG, "%s: Failed to set parameter (op %d "
++ "arg %d)", __func__, op, arg);
++ return -1;
++ }
++#endif
++
++ return 0;
++}
++
++static const char *
++ether_sprintf(const u8 *addr)
++{
++ static char buf[sizeof(MACSTR)];
++
++ if (addr != NULL)
++ snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
++ else
++ snprintf(buf, sizeof(buf), MACSTR, 0,0,0,0,0,0);
++ return buf;
++}
++
++
++static int
++realtek_set_wpa(char *ifname,struct realtek_driver_data *drv, int wpa, int psk, int cipher)
++{
++
++ if(psk & WPA_KEY_MGMT_PSK)
++ {//PSK mode, set PSK & cipher
++ if (set80211param(ifname,drv, IEEE80211_PARAM_KEYMGTALGS, wpa))
++ {
++ wpa_printf(MSG_ERROR, "Unable to set key management algorithms");
++ return -1;
++ }
++ if (set80211param(ifname,drv, IEEE80211_PARAM_UCASTCIPHERS, cipher))
++ {
++ wpa_printf(MSG_ERROR, "Unable to set pairwise key ciphers");
++ return -1;
++ }
++
++ }
++ else
++ {//Enterprise mode, Disable PSK & set cipher.
++ if (set80211param(ifname,drv, IEEE80211_PARAM_KEYMGTALGS, 0))
++ {
++ wpa_printf(MSG_ERROR, "Unable to set key management algorithms");
++ return -1;
++ }
++ if (set80211param(ifname,drv, IEEE80211_PARAM_UCASTCIPHERS, cipher))
++ {
++ wpa_printf(MSG_ERROR, "Unable to set pairwise key ciphers");
++ return -1;
++ }
++
++ }
++
++ if (set80211param(ifname,drv, IEEE80211_PARAM_WPA, wpa))
++ {
++ wpa_printf(MSG_ERROR, "Unable to set WPA");
++ return -1;
++ }
++
++ return set80211param(ifname,drv, IEEE80211_PARAM_AUTHMODE, IEEE80211_AUTH_WPA);
++
++}
++
++/*
++ * Configure WPA parameters.
++ */
++static int
++realtek_configure_wpa(struct hostapd_data *hapd,struct realtek_driver_data *drv)
++{
++ struct hostapd_bss_config *conf = hapd->conf;
++ int v;
++
++ //delete conf->wpa_group & conf->rsn_preauth related parts (like ralink)
++
++ wpa_printf(MSG_DEBUG, "realtek_configure_wpa +++ wpa=0x%x, psk=0x%x, cipher=0x%x",
++ conf->wpa, conf->wpa_key_mgmt, conf->wpa_pairwise);
++
++ v = 0;
++ if (conf->wpa_pairwise & WPA_CIPHER_CCMP)
++ v |= 1<<IEEE80211_CIPHER_AES_CCM;
++ if (conf->wpa_pairwise & WPA_CIPHER_TKIP)
++ v |= 1<<IEEE80211_CIPHER_TKIP;
++ if (conf->wpa_pairwise & WPA_CIPHER_NONE)
++ v |= 1<<IEEE80211_CIPHER_NONE;
++
++ if((conf->wpa == 0) || (conf->wpa > (HOSTAPD_WPA_VERSION_WPA|HOSTAPD_WPA_VERSION_WPA2)))
++ return -1;
++ else
++ return realtek_set_wpa(conf->iface,drv, conf->wpa , conf->wpa_key_mgmt, v);
++
++}
++
++static int
++realtek_set_iface_hwMac(const char *ifname,void *priv, char *addr)
++{
++ struct realtek_driver_data *drv = priv;
++ struct ifreq ifreq;
++
++ if (drv->ioctl_sock < 0)
++ return -1;
++
++ os_memset(&ifreq, 0, sizeof(ifreq));
++ os_strlcpy(ifreq.ifr_name, ifname, IFNAMSIZ);
++
++ memcpy(ifreq.ifr_hwaddr.sa_data, addr, ETH_ALEN);
++ ifreq.ifr_hwaddr.sa_family = ARPHRD_ETHER;
++
++#if defined(INBAND_CTRL)
++ INBAND_IOCTLPKT_DUMP(&ifreq,sizeof(ifreq));
++ if (inband_ioctl(SIOCSIFHWADDR, &ifreq) < 0) {
++ perror("inband_ioctl[SIOCSIFHWADDR]");
++ return -1;
++ }
++#else
++ if (ioctl(drv->ioctl_sock, SIOCSIFHWADDR, &ifreq) != 0) {
++ perror("ioctl[SIOCSIFHWADDR]");
++ return -1;
++ }
++#endif
++
++
++ return 0;
++}
++
++static int
++realtek_set_iface_flags(const char *ifname,void *priv, int dev_up)
++{
++ struct realtek_driver_data *drv = priv;
++ struct ifreq ifr;
++
++ wpa_printf(MSG_DEBUG, "realtek_set_iface_flags +++ dev_up = %d", dev_up);
++
++ if (drv->ioctl_sock < 0)
++ return -1;
++
++ if (dev_up) {
++ memset(&ifr, 0, sizeof(ifr));
++ snprintf(ifr.ifr_name, IFNAMSIZ, "%s", ifname);
++ ifr.ifr_mtu = HOSTAPD_MTU;
++#ifdef STAND_ALONE
++ if (ioctl(drv->ioctl_sock, SIOCSIFMTU, &ifr) != 0) {
++ perror("ioctl[SIOCSIFMTU]");
++ printf("Setting MTU failed - trying to survive with "
++ "current value\n");
++ }
++#endif
++#if defined(INBAND_CTRL)
++ INBAND_IOCTLPKT_DUMP(&ifr,sizeof(ifr));
++ if (inband_ioctl(SIOCSIFMTU, &ifr) < 0) {
++ perror("inband_ioctl[SIOCSIFMTU]");
++ printf("Setting MTU failed - trying to survive with "
++ "current value\n");
++ }
++#endif
++ }
++
++ memset(&ifr, 0, sizeof(ifr));
++ snprintf(ifr.ifr_name, IFNAMSIZ, "%s", ifname);
++#ifdef STAND_ALONE
++ if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, &ifr) != 0) {
++ perror("ioctl[SIOCGIFFLAGS]");
++ return -1;
++ }
++#endif
++#if defined(INBAND_CTRL)
++ INBAND_IOCTLPKT_DUMP(&ifr,sizeof(ifr));
++ if (inband_ioctl(SIOCGIFFLAGS, &ifr) < 0) {
++ perror("inband_ioctl[SIOCGIFFLAGS]");
++ printf("inband_ioctl[SIOCGIFFLAGS] fail");
++ return -1;
++ }
++#endif
++
++ if (dev_up)
++ ifr.ifr_flags |= IFF_UP;
++ else
++ ifr.ifr_flags &= ~IFF_UP;
++#ifdef STAND_ALONE
++ if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, &ifr) != 0) {
++ perror("ioctl[SIOCSIFFLAGS]");
++ return -1;
++ }
++#endif
++#if defined(INBAND_CTRL)
++ INBAND_IOCTLPKT_DUMP(&ifr,sizeof(ifr));
++ if (inband_ioctl(SIOCSIFFLAGS, &ifr) < 0) {
++ perror("inband_ioctl[SIOCSIFFLAGS]");
++ printf("inband_ioctl[SIOCGIFFLAGS] fail");
++ return -1;
++ }
++#endif
++
++ wpa_printf(MSG_DEBUG, "realtek_set_iface_flags ---");
++ return 0;
++}
++
++static int realtek_set_ieee8021x(const char *ifname, void *priv, int enabled)
++{
++ struct realtek_driver_data *drv = priv;
++ struct hostapd_data *hapd = drv->hapd;
++ struct hostapd_bss_config *conf = hapd->conf;
++ struct hostapd_wep_keys wep = conf->ssid.wep;
++
++#ifdef RTK_MBSSID //find the real VAP
++ hapd =(struct hostapd_data *) find_hapd_by_ifname(priv,ifname);
++ conf = hapd->conf;
++ wep = conf->ssid.wep;
++#endif
++
++ wpa_printf(MSG_DEBUG, "realtek_set_ieee8021x+++ \n"
++ "enabled=%d, conf->auth_algs=%d, wep.keys_set=%d, conf->ieee802_1x=%d"
++ ,enabled, conf->auth_algs, wep.keys_set, conf->ieee802_1x);
++
++ if(set80211param(ifname,priv, IEEE80211_PARAM_UCASTKEYLEN, conf->individual_wep_key_len))
++ return -1;
++
++ if (!enabled) {
++ wpa_printf(MSG_DEBUG, "set WEP");
++ /* Set interface up flags after setting authentication modes,
++ done atlast in realtek_commit() */
++ if(conf->auth_algs==1 && wep.keys_set==0)
++ return set80211param(ifname,priv, IEEE80211_PARAM_AUTHMODE, IEEE80211_AUTH_OPEN);
++ else if(conf->auth_algs==1 && wep.keys_set==1){
++ return set80211param(ifname,priv, IEEE80211_PARAM_AUTHMODE, IEEE80211_AUTH_OPEN);
++ /*Fix for open wep when run using hostapd*/
++ //return set80211param(priv, IEEE80211_PARAM_PRIVACY, 1);
++ }
++ else if(conf->auth_algs==2)
++ return set80211param(ifname,priv, IEEE80211_PARAM_AUTHMODE, IEEE80211_AUTH_SHARED);
++ else if(conf->auth_algs==3)
++ return set80211param(ifname,priv, IEEE80211_PARAM_AUTHMODE, IEEE80211_AUTH_AUTO);
++ else if(conf->auth_algs==8) //RTK_HAPD, add auth_algs=BIT(3) as value of none authentication.
++ return set80211param(ifname,priv, IEEE80211_PARAM_AUTHMODE, IEEE80211_AUTH_NONE);
++ }
++
++ if (!conf->wpa && !conf->ieee802_1x) {
++ hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER,
++ HOSTAPD_LEVEL_WARNING, "No 802.1X or WPA enabled!");
++ return -1;
++ }
++
++ if((conf->wpa == 0) && (conf->ieee802_1x))
++ {
++ if(set80211param(ifname,priv, IEEE80211_PARAM_AUTHMODE, IEEE80211_AUTH_8021X))
++ return -1;
++ }
++
++ if (conf->wpa)
++ {
++ return realtek_configure_wpa(hapd,drv);
++ }
++
++ return 0;
++}
++
++static int
++realtek_set_privacy(const char *ifname, void *priv, int enabled)
++{
++ struct realtek_driver_data *drv = priv;
++ struct hostapd_data *hapd = drv->hapd;
++
++ wpa_printf(MSG_DEBUG, "realtek_set_privacy +++");
++
++ return set80211param(ifname,priv, IEEE80211_PARAM_PRIVACY, enabled);
++}
++
++static int
++realtek_set_sta_authorized(void *priv, const u8 *addr, int authorized)
++{
++ struct realtek_driver_data *drv = priv;
++ struct hostapd_data *hapd = drv->hapd;
++ struct hostapd_bss_config *conf = hapd->conf;
++ struct ieee80211req_mlme mlme;
++ int ret;
++
++#ifdef RTK_MBSSID
++ hapd = (struct hostapd_data *)find_hapd_by_sta(priv,addr);
++ conf = hapd->conf;
++#endif
++
++ if (authorized)
++ mlme.im_op = IEEE80211_MLME_AUTHORIZE;
++ else
++ mlme.im_op = IEEE80211_MLME_UNAUTHORIZE;
++ mlme.im_reason = 0;
++ memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
++ ret = set80211priv(conf->iface,priv, IEEE80211_IOCTL_SETMLME, &mlme,
++ sizeof(mlme));
++ if (ret < 0) {
++ wpa_printf(MSG_DEBUG, "%s: Failed to %sauthorize STA " MACSTR,
++ __func__, authorized ? "" : "un", MAC2STR(addr));
++ }
++
++ return ret;
++}
++
++static int
++realtek_sta_set_flags(void *priv, const u8 *addr, int flags_or, int flags_and)
++{
++
++ wpa_printf(MSG_DEBUG, "realtek_sta_set_flags +++");
++
++ /* For now, only support setting Authorized flag */
++ if (flags_or & WLAN_STA_AUTHORIZED)
++ return realtek_set_sta_authorized(priv, addr, 1);
++ if (!(flags_and & WLAN_STA_AUTHORIZED))
++ return realtek_set_sta_authorized(priv, addr, 0);
++ return 0;
++}
++
++static int
++realtek_del_key(const char *ifname,void *priv, const u8 *addr, int key_idx)
++{
++ struct realtek_driver_data *drv = priv;
++ struct hostapd_data *hapd = drv->hapd;
++ struct ieee80211req_del_key wk;
++ int ret;
++
++ wpa_printf(MSG_DEBUG, "realtek_del_key +++");
++
++ memset(&wk, 0, sizeof(wk));
++ if (addr != NULL) {
++ memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN);
++ wk.idk_keyix = (u8) IEEE80211_KEYIX_NONE;
++ } else {
++ wk.idk_keyix = key_idx;
++ }
++
++ ret = set80211priv(ifname ,priv, IEEE80211_IOCTL_DELKEY, &wk, sizeof(wk));
++ if (ret < 0) {
++ wpa_printf(MSG_DEBUG, "%s: Failed to delete key (addr %s"
++ " key_idx %d)", __func__, ether_sprintf(addr),
++ key_idx);
++ }
++
++ wpa_printf(MSG_DEBUG, "realtek_del_key ---");
++ return ret;
++}
++
++static int
++realtek_set_key(const char *ifname, void *priv, const char *alg,
++ const u8 *addr, int key_idx,
++ const u8 *key, size_t key_len, int txkey)
++{
++ struct realtek_driver_data *drv = priv;
++ struct hostapd_data *hapd = drv->hapd;
++ struct hostapd_bss_config *conf = hapd->conf;
++ struct hostapd_wep_keys wep = conf->ssid.wep;
++ struct ieee80211req_key wk;
++ u_int8_t cipher;
++ int ret;
++
++#ifdef RTK_MBSSID //find the real VAP
++ hapd = (struct hostapd_data *)find_hapd_by_ifname(priv,ifname);
++ conf = hapd->conf;
++ wep = conf->ssid.wep;
++#endif
++
++ wpa_printf(MSG_DEBUG, "realtek_set_key +++");
++ wpa_printf(MSG_DEBUG, "alg = %s\n, addr = %s\n, key_index = %d", alg, ether_sprintf(addr), key_idx);
++
++ if (strcmp(alg, "none") == 0)
++ return realtek_del_key(ifname,priv, addr, key_idx);
++
++ if ((strcmp(alg, "WEP") == 0) && ((wep.keys_set >= 1) && (wep.keys_set <= 4)))
++ cipher = IEEE80211_CIPHER_WEP;
++ else if (strcmp(alg, "TKIP") == 0)
++ cipher = IEEE80211_CIPHER_TKIP;
++ else if (strcmp(alg, "CCMP") == 0)
++ cipher = IEEE80211_CIPHER_AES_CCM;
++ else {
++ printf("%s: unknown/unsupported algorithm %s\n",
++ __func__, alg);
++ return -1;
++ }
++
++ if (key_len > sizeof(wk.ik_keydata)) {
++ printf("%s: key length %lu too big\n", __func__,
++ (unsigned long) key_len);
++ return -3;
++ }
++
++ memset(&wk, 0, sizeof(wk));
++ wk.ik_type = cipher;
++ wk.ik_flags = IEEE80211_KEY_RECV | IEEE80211_KEY_XMIT;
++ if (addr == NULL) {
++ memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN);
++ wk.ik_keyix = key_idx;
++ wk.ik_flags |= IEEE80211_KEY_DEFAULT;
++ } else {
++ memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
++ wk.ik_keyix = key_idx;
++ //wk.ik_keyix = IEEE80211_KEYIX_NONE;
++ }
++ wk.ik_keylen = key_len;
++ memcpy(wk.ik_keydata, key, key_len);
++
++#ifdef INBAND_CTRL //HOST_LITTLE_ENDIAN
++ // ik_keyix int16 need endian-swap
++ wk.ik_keyix = htons(wk.ik_keyix);
++ wk.ik_keylen = htonl(key_len);
++#endif
++ ret = set80211priv(ifname,priv, IEEE80211_IOCTL_SETKEY, &wk, sizeof(wk));
++ if (ret < 0) {
++ wpa_printf(MSG_DEBUG, "%s: Failed to set key (addr %s"
++ " key_idx %d alg '%s' key_len %lu txkey %d)",
++ __func__, ether_sprintf(wk.ik_macaddr), key_idx,
++ alg, (unsigned long) key_len, txkey);
++ }
++
++ wpa_printf(MSG_DEBUG, "realtek_set_key ---");
++ return ret;
++}
++
++
++static int
++realtek_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx,
++ u8 *seq)
++{
++//do nothing like broadcom & ralink, even madwifi did not call back for hosapd.
++
++ wpa_printf(MSG_DEBUG, "realtek_get_seqnum +++");
++ wpa_printf(MSG_DEBUG, "realtek_get_seqnum ---");
++
++ return 0;
++}
++
++
++static int
++realtek_flush(void *priv)
++{
++//do nothing like broadcom & ralink
++ wpa_printf(MSG_DEBUG, "realtek_flush +++");
++ wpa_printf(MSG_DEBUG, "realtek_flush ---");
++ return 0;
++}
++
++
++static int
++realtek_read_sta_driver_data(void *priv, struct hostap_sta_driver_data *data,
++ const u8 *addr)
++{
++#if 0 //not use now
++ struct realtek_driver_data *drv = priv;
++ wpa_printf(MSG_DEBUG, "realtek_read_sta_driver_data +++");
++
++#ifdef REALTEK_BSD
++ struct ieee80211req_sta_stats stats;
++
++ memset(data, 0, sizeof(*data));
++
++ /*
++ * Fetch statistics for station from the system.
++ */
++ memset(&stats, 0, sizeof(stats));
++ memcpy(stats.is_u.macaddr, addr, IEEE80211_ADDR_LEN);
++ if (set80211priv(drv,
++#ifdef REALTEK_NG
++ IEEE80211_IOCTL_STA_STATS,
++#else /* REALTEK_NG */
++ IEEE80211_IOCTL_GETSTASTATS,
++#endif /* REALTEK_NG */
++ &stats, sizeof(stats))) {
++ wpa_printf(MSG_DEBUG, "%s: Failed to fetch STA stats (addr "
++ MACSTR ")", __func__, MAC2STR(addr));
++ if (memcmp(addr, drv->acct_mac, ETH_ALEN) == 0) {
++ memcpy(data, &drv->acct_data, sizeof(*data));
++ return 0;
++ }
++
++ printf("Failed to get station stats information element.\n");
++ return -1;
++ }
++#ifdef INBAND_CTRL //HOST_LITTLE_ENDIAN
++ stats.is_stats.ns_rx_data = ntohl(stats.is_stats.ns_rx_data);
++ stats.is_stats.ns_rx_bytes = ntohl(stats.is_stats.ns_rx_bytes);
++ stats.is_stats.ns_tx_data = ntohl(stats.is_stats.ns_tx_data);
++ stats.is_stats.ns_tx_bytes = ntohl(stats.is_stats.ns_tx_bytes);
++#endif
++ data->rx_packets = stats.is_stats.ns_rx_data;
++ data->rx_bytes = stats.is_stats.ns_rx_bytes;
++ data->tx_packets = stats.is_stats.ns_tx_data;
++ data->tx_bytes = stats.is_stats.ns_tx_bytes;
++ return 0;
++
++#else /* REALTEK_BSD */
++
++ char buf[1024], line[128], *pos;
++ FILE *f;
++ unsigned long val;
++
++ memset(data, 0, sizeof(*data));
++ snprintf(buf, sizeof(buf), "/proc/net/realtek/%s/" MACSTR,
++ drv->iface, MAC2STR(addr));
++
++ f = fopen(buf, "r");
++ if (!f) {
++ if (memcmp(addr, drv->acct_mac, ETH_ALEN) != 0)
++ return -1;
++ memcpy(data, &drv->acct_data, sizeof(*data));
++ return 0;
++ }
++ /* Need to read proc file with in one piece, so use large enough
++ * buffer. */
++ setbuffer(f, buf, sizeof(buf));
++
++ while (fgets(line, sizeof(line), f)) {
++ pos = strchr(line, '=');
++ if (!pos)
++ continue;
++ *pos++ = '\0';
++ val = strtoul(pos, NULL, 10);
++ if (strcmp(line, "rx_packets") == 0)
++ data->rx_packets = val;
++ else if (strcmp(line, "tx_packets") == 0)
++ data->tx_packets = val;
++ else if (strcmp(line, "rx_bytes") == 0)
++ data->rx_bytes = val;
++ else if (strcmp(line, "tx_bytes") == 0)
++ data->tx_bytes = val;
++ }
++
++ fclose(f);
++
++ return 0;
++#endif /* REALTEK_BSD */
++#endif
++return 0;
++}
++
++
++static int
++realtek_sta_clear_stats(void *priv, const u8 *addr)
++{
++#if 0 //not support now
++#if defined(REALTEK_BSD) && defined(IEEE80211_MLME_CLEAR_STATS)
++ struct realtek_driver_data *drv = priv;
++ struct hostapd_data *hapd = drv->hapd;
++ struct ieee80211req_mlme mlme;
++ int ret;
++
++ wpa_printf(MSG_DEBUG, "realtek_sta_clear_stats (BSD) +++");
++
++ mlme.im_op = IEEE80211_MLME_CLEAR_STATS;
++ memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
++ ret = set80211priv(priv, IEEE80211_IOCTL_SETMLME, &mlme,
++ sizeof(mlme));
++ if (ret < 0) {
++ wpa_printf(MSG_DEBUG, "%s: Failed to clear STA stats (addr "
++ MACSTR ")", __func__, MAC2STR(addr));
++ }
++
++ return ret;
++#else /* REALTEK_BSD && IEEE80211_MLME_CLEAR_STATS */
++ wpa_printf(MSG_DEBUG, "realtek_sta_clear_stats +++");
++ return 0; /* FIX */
++#endif /* REALTEK_BSD && IEEE80211_MLME_CLEAR_STATS */
++#endif
++return 0;
++}
++
++
++static int
++realtek_set_opt_ie(const char *ifname, void *priv, const u8 *ie, size_t ie_len)
++{
++//do nothing like broadcom & ralink & madwifi
++
++ wpa_printf(MSG_DEBUG, "realtek_set_opt_ie +++");
++ wpa_printf(MSG_DEBUG, "realtek_set_opt_ie ---");
++ return 0;
++}
++
++static int
++realtek_is_ifup(const char *ifname,struct realtek_driver_data *drv)
++{
++ struct ifreq ifr;
++
++ if (drv->ioctl_sock < 0)
++ return 0;
++
++ memset(&ifr, 0, sizeof(ifr));
++ snprintf(ifr.ifr_name, IFNAMSIZ, "%s", ifname);
++#ifdef STAND_ALONE
++ if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, &ifr) != 0) {
++ perror("ioctl[SIOCGIFFLAGS]");
++ return 0;
++ }
++#endif
++#if defined(INBAND_CTRL)
++ INBAND_IOCTLPKT_DUMP(&ifr,sizeof(ifr));
++ if (inband_ioctl(SIOCGIFFLAGS, &ifr) < 0) {
++ perror("ioctl[SIOCGIFFLAGS]");
++ return 0;
++ }
++#endif
++
++ return ((ifr.ifr_flags & IFF_UP) == IFF_UP);
++}
++
++static int
++realtek_sta_deauth(void *priv, const u8 *addr, int reason_code)
++{
++ struct realtek_driver_data *drv = priv;
++ struct hostapd_data *hapd = drv->hapd;
++ struct hostapd_bss_config *conf = hapd->conf;
++ struct ieee80211req_mlme mlme;
++ int ret;
++
++#ifdef RTK_MBSSID //find the sta belong to which MBSSID
++ hapd = (struct hostapd_data *)find_hapd_by_sta(priv,addr);
++ conf = hapd->conf;
++#endif
++
++ wpa_printf(MSG_DEBUG, "realtek_sta_deauth +++");
++
++ mlme.im_op = IEEE80211_MLME_DEAUTH;
++ mlme.im_reason = reason_code;
++ memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
++ if (!realtek_is_ifup(conf->iface,drv)) {
++ return EINVAL;
++ }
++#ifdef INBAND_CTRL //HOST_LITTLE_ENDIAN
++ //im_reason need swap
++ mlme.im_reason = htons(mlme.im_reason);
++#endif
++ ret = set80211priv(conf->iface,priv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme));
++ if (ret < 0) {
++ wpa_printf(MSG_DEBUG, "%s: Failed to deauth STA (addr " MACSTR
++ " reason %d)",
++ __func__, MAC2STR(addr), reason_code);
++ }
++
++ return ret;
++}
++
++static int
++realtek_sta_disassoc(void *priv, const u8 *addr, int reason_code)
++{
++ struct realtek_driver_data *drv = priv;
++ struct hostapd_data *hapd = drv->hapd;
++ struct hostapd_bss_config *conf = hapd->conf;
++ struct ieee80211req_mlme mlme;
++ int ret;
++
++#ifdef RTK_MBSSID //find the sta belong to which MBSSID
++ hapd = (struct hostapd_data *)find_hapd_by_sta(priv,addr);
++ conf = hapd->conf;
++#endif
++
++ wpa_printf(MSG_DEBUG, "realtek_sta_disassoc +++");
++
++ mlme.im_op = IEEE80211_MLME_DISASSOC;
++ mlme.im_reason = reason_code;
++ memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
++#ifdef INBAND_CTRL //HOST_LITTLE_ENDIAN
++ //im_reason need swap
++ mlme.im_reason = htons(mlme.im_reason);
++#endif
++ ret = set80211priv(conf->iface,priv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme));
++ if (ret < 0) {
++ wpa_printf(MSG_DEBUG, "%s: Failed to disassoc STA (addr "
++ MACSTR " reason %d)",
++ __func__, MAC2STR(addr), reason_code);
++ }
++
++ return ret;
++}
++
++#ifdef RTK_HAPD
++//Announce driver to remove sta list for IAPP function
++static int
++realtek_sta_remove(void *priv, const u8 *addr)
++{
++ struct realtek_driver_data *drv = priv;
++ struct hostapd_data *hapd = drv->hapd;
++ struct hostapd_bss_config *conf = hapd->conf;
++ unsigned char para[32];
++ struct iwreq wrq;
++
++#ifdef RTK_MBSSID //find the sta belong to which MBSSID
++ hapd = (struct hostapd_data *)find_hapd_by_sta(priv,addr);
++ conf = hapd->conf;
++#endif
++ wpa_printf(MSG_DEBUG, "realtek_sta_remove +++");
++ memset(para, 0, 32);
++ sprintf(para, "%02x%02x%02x%02x%02x%02x", addr[0], addr[1],
++ addr[2], addr[3], addr[4], addr[5]);
++ wrq.u.data.pointer = para;
++ wrq.u.data.length = strlen(para);
++ strncpy(wrq.ifr_name, conf->iface, IFNAMSIZ);
++#ifdef STAND_ALONE
++ ioctl(drv->ioctl_sock, RTL8192CD_IOCTL_DEL_STA, &wrq);
++#endif
++#ifdef INBAND_CTRL
++ inband_ioctl(RTL8192CD_IOCTL_DEL_STA, &wrq);
++#endif
++
++ wpa_printf(MSG_DEBUG, "realtek_sta_remove ---");
++
++ return 0;
++}
++#endif
++
++static int
++realtek_del_sta(struct hostapd_data *hapd,struct realtek_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN])
++{
++ struct sta_info *sta;
++
++ hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
++ HOSTAPD_LEVEL_INFO, "disassociated");
++
++ sta = ap_get_sta(hapd, addr);
++ if (sta != NULL) {
++ sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
++ wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
++ sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
++ ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
++ ap_free_sta(hapd, sta);
++ }
++ return 0;
++}
++
++static int
++realtek_process_wpa_ie(struct hostapd_data *hapd,struct realtek_driver_data *drv, struct sta_info *sta)
++{
++ struct ieee80211req_wpaie ie;
++ int ielen, res;
++ u8 *iebuf = NULL;
++ struct hostapd_bss_config *conf = hapd->conf;
++
++ wpa_printf(MSG_DEBUG, "realtek_process_wpa_ie +++");
++
++ /*
++ * Fetch negotiated WPA/RSN parameters from the system.
++ */
++ memset(&ie, 0, sizeof(ie));
++ memcpy(ie.wpa_macaddr, sta->addr, IEEE80211_ADDR_LEN);
++
++ if (set80211priv(conf->iface,drv, HAPD_IOCTL_GETWPAIE, &ie, sizeof(ie)))
++ {
++ wpa_printf(MSG_ERROR, "%s: Failed to get WPA/RSN IE", __func__);
++ printf("Failed to get WPA/RSN information element.\n");
++ return -1;
++ }
++
++ //wpa_printf(MSG_DEBUG, "get wpa_ie = 0x%02x, 0x%02x, 0x%02x", ie.wpa_ie[0], ie.wpa_ie[1], ie.wpa_ie[2]);
++ //wpa_printf(MSG_DEBUG, "get wps_ie = 0x%02x, 0x%02x, 0x%02x", ie.wps_ie[0], ie.wps_ie[1], ie.wps_ie[2]);
++
++ do {
++ iebuf = 0; ielen = 0;
++ if (conf->wpa & HOSTAPD_WPA_VERSION_WPA) {
++ iebuf = ie.wpa_ie; ielen = 0;
++ if ((iebuf[0] == WLAN_EID_VENDOR_SPECIFIC) && iebuf[1]) {
++ wpa_printf(MSG_DEBUG, "get wpa_ie");
++ ielen = iebuf[1];
++ break;
++ }
++ }
++ if (conf->wpa & HOSTAPD_WPA_VERSION_WPA2) {
++ iebuf = ie.rsn_ie; ielen = 0;
++ if ((iebuf[0] == WLAN_EID_RSN) && iebuf[1]) {
++ wpa_printf(MSG_DEBUG, "get rsn_ie");
++ ielen = iebuf[1];
++ break;
++ }
++ }
++ } while (0);
++
++ wpabuf_free(sta->wps_ie);
++ if ((ie.wps_ie[0] == WLAN_EID_VENDOR_SPECIFIC) && ie.wps_ie[1])
++ {
++ //Test rtl8192su usb-dongle wps_pbc/wps_pin ok via here.
++ wpa_printf(MSG_DEBUG, "get wps_ie");
++ ielen = ie.wps_ie[1] + 2;
++
++ sta->wps_ie = wpabuf_alloc(0);
++ sta->wps_ie->size = ielen;
++ sta->wps_ie->used = ielen;
++ sta->wps_ie->ext_data = os_malloc(ielen);
++ memcpy(sta->wps_ie->ext_data, ie.wps_ie, ielen);
++
++ sta->flags |= WLAN_STA_WPS;
++ return 0;
++ }
++ else
++ {
++ sta->wps_ie = wpabuf_alloc(0);
++ sta->wps_ie->used = 0;
++ sta->wps_ie->ext_data = NULL;
++
++ sta->flags &= ~WLAN_STA_WPS;
++
++
++ if((ielen == 0) && (conf->wps_state)){
++ wpa_printf(MSG_DEBUG, "STA did not include WPA/RSN/WPS IE in (Re)Association Request "
++ "but WPS enabled at hostapd conf file - possible WPS use");
++ sta->flags |= WLAN_STA_MAYBE_WPS; // Test dwa140 and wn111 wps_pbc/wps_pin ok because of here!!!! --zj
++ }
++ else{
++ sta->flags &= ~WLAN_STA_MAYBE_WPS;
++ }
++ }
++
++ if(ielen != 0) //_For WPS, neglect wpa_ie??
++ {
++ if (sta->wpa_sm == NULL)
++ sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, sta->addr);
++
++ if (sta->wpa_sm == NULL)
++ {
++ wpa_printf(MSG_ERROR, "Failed to initialize WPA state machine");
++ return -1;
++ }
++
++ ielen += 2;
++ res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, iebuf, ielen, NULL, 0);
++
++ if (res != WPA_IE_OK)
++ {
++ wpa_printf(MSG_ERROR, "WPA/RSN information element rejected? (res %u)", res);
++ return -1;
++ }
++ else
++ wpa_printf(MSG_DEBUG, "WPA_IE_OK");
++ }
++
++
++ return 0;
++}
++
++static int
++realtek_issue_asocrsp(char *ifname,struct realtek_driver_data *drv, struct sta_info *sta)
++{
++ int retVal = 0;
++ struct iwreq iwr;
++ DOT11_ASSOCIATION_RSP Association_Rsp;
++
++ wpa_printf(MSG_DEBUG, "realtek_issue_asocrsp +++");
++
++ strncpy(iwr.ifr_name, ifname, IFNAMSIZ);
++
++ iwr.u.data.pointer = (caddr_t)&Association_Rsp;
++ iwr.u.data.length = sizeof(DOT11_ASSOCIATION_RSP);
++
++ Association_Rsp.EventId = DOT11_EVENT_ASSOCIATION_RSP;
++
++ //?? Re-Association case??
++ //Association_Rsp.EventId = DOT11_EVENT_REASSOCIATION_RSP;
++
++ Association_Rsp.IsMoreEvent = FALSE;
++ Association_Rsp.Status = _STATS_SUCCESSFUL_;
++ memcpy(&Association_Rsp.MACAddr, sta->addr, IEEE80211_ADDR_LEN);
++
++#ifdef STAND_ALONE
++ if(ioctl(drv->ioctl_sock, SIOCGIWIND, &iwr) < 0)
++ retVal = -1;
++ else
++ retVal = 0;
++#endif
++#if defined(INBAND_CTRL)
++ INBAND_IOCTLPKT_DUMP(&iwr,sizeof(iwr));
++ if (inband_ioctl(SIOCGIWIND, &iwr) < 0)
++ retVal = -1;
++ else
++ retVal = 0;
++#endif
++ return retVal;
++
++}
++
++
++static int
++realtek_new_sta(struct hostapd_data *hapd,struct realtek_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN])
++{
++ struct hostapd_bss_config *conf = hapd->conf;
++ struct sta_info *sta;
++ int new_assoc;
++
++ hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
++ HOSTAPD_LEVEL_INFO, "associated");
++
++ sta = ap_get_sta(hapd, addr);
++ if (sta) {
++ accounting_sta_stop(hapd, sta);
++ } else {
++ //printf("realtek_new_sta hapd=%s \n",conf->iface);
++ sta = ap_sta_add(hapd, addr);
++ if (sta == NULL)
++ return -1;
++ }
++ //mark_mbssid , acct_mac ? per VAP?
++ if (memcmp(addr, drv->acct_mac, ETH_ALEN) == 0) {
++ /* Cached accounting data is not valid anymore. */
++ memset(drv->acct_mac, 0, ETH_ALEN);
++ memset(&drv->acct_data, 0, sizeof(drv->acct_data));
++ }
++ accounting_sta_get_id(hapd, sta);
++
++ if (hapd->conf->wpa || hapd->conf->wps_state) {
++ if (realtek_process_wpa_ie(hapd,drv, sta))
++ return -1;
++ if((sta->wps_ie->used == 0) && ((conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) == 0) && (conf->ieee802_1x != 0))
++ {//do issue Association response just for RADIUS authentication.
++ if(realtek_issue_asocrsp(hapd->conf->iface,drv, sta))
++ return -1;
++ }
++ }
++ else
++ {
++ if(conf->ieee802_1x != 0)
++ if(realtek_issue_asocrsp(hapd->conf->iface,drv, sta))
++ return -1;
++ }
++
++ /*
++ * Now that the internal station state is setup
++ * kick the authenticator into action.
++ */
++
++ wpa_printf(MSG_DEBUG, "Try to kick the authenticator into action");
++
++ new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
++ sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
++ wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
++ hostapd_new_assoc_sta(hapd, sta, !new_assoc);
++ ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
++ return 0;
++}
++
++
++
++int realtek_set_wds(void *priv, struct rtk_wds_config wds)
++{
++ struct realtek_driver_data *drv = priv;
++ struct hostapd_data *hapd = drv->hapd;
++ struct hostapd_bss_config *conf = hapd->conf;
++ struct iwreq iwr;
++ int op = 0;
++
++ wpa_printf(MSG_DEBUG, "realtek_set_wds +++");
++
++ memset(&iwr, 0, sizeof(iwr));
++ strncpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
++
++ iwr.u.data.pointer = &wds;
++ iwr.u.data.length = sizeof(struct rtk_wds_config);
++
++ if(wds.wdsEnabled)
++ op = IEEE80211_IOCTL_WDSADDMAC;
++ else
++ op = IEEE80211_IOCTL_WDSDELMAC;
++#ifdef STAND_ALONE
++ if (ioctl(drv->ioctl_sock, op, &iwr) < 0)
++ {
++ {
++ int err = errno;
++ perror("set WDS ioctl failed");
++ wpa_printf(MSG_ERROR, "ioctl 0x%x failed errno=%d",
++ op, err);
++ }
++ return -1;
++ }
++#endif
++#if defined(INBAND_CTRL)
++ INBAND_IOCTLPKT_DUMP(&iwr,sizeof(iwr));
++ if (inband_ioctl(op, &iwr) < 0)
++ {
++ {
++ perror("set80211priv ioctl failed");
++ wpa_printf(MSG_ERROR, "ioctl 0x%x failed", op);
++ }
++ return -1;
++ }
++#endif
++
++
++ return 0;
++}
++
++
++static void
++realtek_wireless_event_wireless_custom(struct hostapd_data *hapd,struct realtek_driver_data *drv, u16 flags, char * custom, size_t len)
++{
++ wpa_printf(MSG_DEBUG, "custom event =%d, len=%d", flags, len);
++
++ switch(flags)
++ {
++ case HAPD_MIC_FAILURE:
++ {
++ unsigned char * mac = (unsigned char *)custom;
++ wpa_printf(MSG_DEBUG, "MIC failed sta: %02x %02x %02x %02x %02x %02x"
++ , mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
++ ieee80211_michael_mic_failure(hapd, mac, 1);
++ break;
++ }
++ case HAPD_WPS_PROBEREQ:
++ {
++ struct _DOT11_PROBE_REQUEST_IND *wps_ie = (struct _DOT11_PROBE_REQUEST_IND *) custom;
++ wpa_printf(MSG_DEBUG, "IsMoreEvent =%d, ProbeIELen =%d", wps_ie->IsMoreEvent, wps_ie->ProbeIELen);
++ hostapd_wps_probe_req_rx(hapd, wps_ie->MACAddr, wps_ie->ProbeIE, wps_ie->ProbeIELen);
++ break;
++ }
++ }
++
++}
++
++
++static void
++realtek_wireless_event_wireless(struct hostapd_data *hapd,struct realtek_driver_data *drv,
++ u8 *data, int len)
++{
++ struct iw_event iwe_buf, *iwe = &iwe_buf;
++ u8 *pos, *end, *custom, *buf;
++ u8 macaddr[ETH_ALEN] = {};
++
++ pos = data;
++ end = data + len;
++
++ wpa_printf(MSG_DEBUG, "realtek_wireless_event_wireless +++");
++
++ while (pos + IW_EV_LCP_LEN <= end) {
++ /* Event data may be unaligned, so make a local, aligned copy
++ * before processing. */
++ memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
++
++#ifdef INBAND_CTRL //HOST_LITTLE_ENDIAN
++ iwe->len = ntohs(iwe->len);
++ iwe->cmd = ntohs(iwe->cmd);
++#endif
++ if (iwe->len <= IW_EV_LCP_LEN)
++ return;
++
++ custom = pos + IW_EV_POINT_LEN;
++ if (drv->we_version > 18 &&
++ (iwe->cmd == IWEVMICHAELMICFAILURE ||
++ iwe->cmd == SIOCGIWESSID ||
++ iwe->cmd == SIOCGIWENCODE ||
++ iwe->cmd == IWEVGENIE ||
++ iwe->cmd == IWEVASSOCREQIE ||
++ iwe->cmd == IWEVASSOCRESPIE ||
++ iwe->cmd == IWEVCUSTOM)) {
++ /* WE-19 removed the pointer from struct iw_point */
++ char *dpos = (char *) &iwe_buf.u.data.length;
++ int dlen = dpos - (char *) &iwe_buf;
++ memcpy(dpos, pos + IW_EV_LCP_LEN,
++ sizeof(struct iw_event) - dlen);
++ } else {
++ memcpy(&iwe_buf, pos, sizeof(struct iw_event));
++ custom += IW_EV_POINT_OFF;
++#ifdef INBAND_CTRL //HOST_LITTLE_ENDIAN
++ iwe->len = ntohs(iwe->len);
++ iwe->cmd = ntohs(iwe->cmd);
++#endif
++ }
++
++ switch (iwe->cmd) {
++ case IWEVEXPIRED:
++ wpa_printf(MSG_DEBUG, "case IWEVEXPIRED");
++ realtek_del_sta(hapd,drv, (u8 *) iwe->u.addr.sa_data);
++ break;
++ case IWEVREGISTERED:
++ wpa_printf(MSG_DEBUG, "case IWEVREGISTERED");
++ realtek_new_sta(hapd,drv, (u8 *) iwe->u.addr.sa_data);
++ break;
++ case IWEVCUSTOM:
++ case IWEVGENIE:
++ wpa_printf(MSG_DEBUG, "case IWEVCUSTOM|IWEVGENIE");
++#ifdef INBAND_CTRL //HOST_LITTLE_ENDIAN
++ 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)
++ return;
++ buf = malloc(iwe->u.data.length + 1);
++ if (buf == NULL)
++ return; /* XXX */
++ memcpy(buf, custom, iwe->u.data.length);
++ buf[iwe->u.data.length] = '\0';
++ realtek_wireless_event_wireless_custom(hapd,drv, iwe->u.data.flags, buf, iwe->u.data.length);
++ free(buf);
++ break;
++ }
++ pos += iwe->len;
++ }
++}
++
++
++static void
++realtek_wireless_event_rtm_newlink(struct realtek_driver_data *drv,
++ struct nlmsghdr *h, int len)
++{
++ struct ifinfomsg *ifi;
++ int attrlen, nlmsg_len, rta_len;
++ struct rtattr * attr;
++ struct hostapd_data *hapd = drv->hapd;
++
++ wpa_printf(MSG_DEBUG, "realtek_wireless_event_rtm_newlink +++");
++
++ if (len < (int) sizeof(*ifi))
++ return;
++
++ ifi = NLMSG_DATA(h);
++#ifdef INBAND_CTRL //HOST_LITTLE_ENDIAN
++ ifi->ifi_index = ntohl(ifi->ifi_index);
++#endif
++#ifdef RTK_MBSSID
++ if(!have_ifidx(drv, ifi->ifi_index))
++ return;
++ hapd = find_hapd_by_ifindex(drv,ifi->ifi_index);
++#else
++ if (ifi->ifi_index != drv->ifindex)
++ return;
++#endif
++ 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 INBAND_CTRL //HOST_LITTLE_ENDIAN
++ 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) {
++ realtek_wireless_event_wireless(hapd,
++ drv, ((u8 *) attr) + rta_len,
++ attr->rta_len - rta_len);
++ }
++ attr = RTA_NEXT(attr, attrlen);
++#ifdef INBAND_CTRL //HOST_LITTLE_ENDIAN
++ attr->rta_len = ntohs(attr->rta_len);
++ attr->rta_type = ntohs(attr->rta_type);
++#endif
++ }
++}
++
++
++static void
++realtek_wireless_event_receive(int sock, void *eloop_ctx, void *sock_ctx)
++{
++ //char buf[256];
++ char buf[1024], cmd_type=0x01; //increse size for IWEVGENIE event
++ int left;
++ struct sockaddr_nl from;
++ socklen_t fromlen;
++ struct nlmsghdr *h;
++ struct realtek_driver_data *drv = eloop_ctx;
++#ifdef INBAND_CTRL
++ left = ioh_recv(&drv->netlink_ioh_obj, 3000);
++ if (left < 0) {
++ perror("recvfrom(rawsock)");
++ return;
++ }
++ INBAND_IOCTLPKT_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 INBAND_CTRL //HOST_LITTLE_ENDIAN //mark_x86
++ 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) {
++ printf("Malformed netlink message: "
++ "len=%d left=%d plen=%d\n",
++ len, left, plen);
++ break;
++ }
++
++ switch (h->nlmsg_type) {
++ case RTM_NEWLINK:
++ realtek_wireless_event_rtm_newlink(drv, h, plen);
++ break;
++ }
++
++ len = NLMSG_ALIGN(len);
++ left -= len;
++ h = (struct nlmsghdr *) ((char *) h + len);
++ }
++
++ if (left > 0) {
++ printf("%d extra bytes in the end of netlink message\n", left);
++ }
++}
++
++
++static int
++realtek_get_we_version(struct realtek_driver_data *drv)
++{
++ struct iw_range *range;
++ struct iwreq iwr;
++ int minlen;
++ size_t buflen;
++
++ drv->we_version = 0;
++
++ /*
++ * 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;
++
++ memset(&iwr, 0, sizeof(iwr));
++ strncpy(iwr.ifr_name, drv->iface, 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 STAND_ALONE
++ if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) {
++ perror("ioctl[SIOCGIWRANGE]");
++ free(range);
++ return -1;
++ }
++ else 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->we_version = range->we_version_compiled;
++ }
++#endif
++#if defined(INBAND_CTRL)
++ INBAND_IOCTLPKT_DUMP(&iwr,sizeof(iwr));
++ if (inband_ioctl(SIOCGIWRANGE, &iwr) < 0) {
++ perror("inband_ioctl[SIOCGIWRANGE]");
++ free(range);
++ return -1;
++ } else 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->we_version = range->we_version_compiled;
++ }
++#endif
++
++
++ free(range);
++ return 0;
++}
++
++
++static int
++realtek_wireless_event_init(void *priv)
++{
++ struct realtek_driver_data *drv = priv;
++ int s;
++ struct sockaddr_nl local;
++
++ realtek_get_we_version(drv);
++
++ drv->wext_sock = -1;
++#ifdef INBAND_CTRL
++ 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)");
++ return -1;
++ }
++
++ 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);
++ return -1;
++ }
++#endif
++
++#ifdef INBAND_CTRL
++ eloop_register_read_sock(drv->netlink_ioh_obj.sockfd, realtek_wireless_event_receive, drv, NULL);
++#else
++ eloop_register_read_sock(s, realtek_wireless_event_receive, drv, NULL);
++#endif
++#ifdef INBAND_CTRL
++ drv->wext_sock = drv->netlink_ioh_obj.sockfd;
++#else
++ drv->wext_sock = 0;
++#endif
++
++ return 0;
++}
++
++
++static void
++realtek_wireless_event_deinit(void *priv)
++{
++ struct realtek_driver_data *drv = priv;
++
++ wpa_printf(MSG_DEBUG, "realtek_wireless_event_deinit +++");
++
++ if (drv != NULL) {
++ if (drv->wext_sock < 0)
++ return;
++ eloop_unregister_read_sock(drv->wext_sock);
++ close(drv->wext_sock);
++ }
++}
++
++
++static int
++realtek_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len,
++ int encrypt, const u8 *own_addr)
++{
++ struct realtek_driver_data *drv = priv;
++ unsigned char buf[3000];
++ unsigned char *bp = buf;
++ struct l2_ethhdr *eth;
++ size_t len;
++ int status;
++ struct l2_packet_data *eapol_sock=drv->sock_xmit;
++#ifdef RTK_MBSSID
++#ifndef INBAND_CTRL
++ struct hostapd_data *hapd = drv->hapd;
++
++ hapd = (struct hostapd_data *)find_hapd_by_sta(priv,addr);
++ eapol_sock = (struct l2_packet_data *)rtk_find_l2sock_by_ifname(priv,hapd->conf->iface);
++#endif
++#endif
++ wpa_printf(MSG_DEBUG, "realtek_send_eapol +++");
++
++ /*
++ * Prepend the Ethernet header. If the caller left us
++ * space at the front we could just insert it but since
++ * we don't know we copy to a local buffer. Given the frequency
++ * and size of frames this probably doesn't matter.
++ */
++ len = data_len + sizeof(struct l2_ethhdr);
++ if (len > sizeof(buf)) {
++ bp = malloc(len);
++ if (bp == NULL) {
++ printf("EAPOL frame discarded, cannot malloc temp "
++ "buffer of size %lu!\n", (unsigned long) len);
++ return -1;
++ }
++ }
++ eth = (struct l2_ethhdr *) bp;
++ memcpy(eth->h_dest, addr, ETH_ALEN);
++ memcpy(eth->h_source, drv->hapd->own_addr, ETH_ALEN);
++ eth->h_proto = htons(ETH_P_EAPOL);
++ memcpy(eth+1, data, data_len);
++
++ //mark wpa_hexdump because both ralink & broadcom NOT call this function
++ //wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", bp, len);
++
++ status = l2_packet_send(eapol_sock, addr, ETH_P_EAPOL, bp, len);
++ if (bp != buf)
++ free(bp);
++ return status;
++}
++
++static void
++handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len)
++{
++ struct realtek_driver_data *drv = ctx;
++ struct hostapd_data *hapd = drv->hapd;
++ struct sta_info *sta;
++
++ //printf("handle_read +++");
++#ifndef RTK_MBSSID
++ sta = ap_get_sta(hapd, src_addr);
++ if (!sta || !(sta->flags & WLAN_STA_ASSOC)) {
++ printf("Data frame from not associated STA %s\n",
++ ether_sprintf(src_addr));
++ /* XXX cannot happen */
++ return;
++ }
++
++ ieee802_1x_receive(hapd, src_addr, buf + sizeof(struct l2_ethhdr),
++ len - sizeof(struct l2_ethhdr));
++#else
++ return; // do nothing here , all handle in handle_eapol
++#endif
++}
++
++#ifdef INBAND_CTRL
++static int rtk_l2_packet_get_own_addr(struct realtek_driver_data *drv, u8 *addr)
++{
++ unsigned char cmd[100];
++ struct ifreq ifr;
++
++ os_memset(&ifr, 0, sizeof(ifr));
++ os_strlcpy(ifr.ifr_name, INBAND_INTF, sizeof(INBAND_INTF));
++
++ if(ioctl(drv->ioctl_sock,SIOCGIFHWADDR, &ifr ) < 0){
++ return -1;
++ }
++
++ sprintf(cmd,"echo %d:%d:%d:%d:%d:%d > /proc/br_hostmac",ifr.ifr_hwaddr.sa_data[0],
++ ifr.ifr_hwaddr.sa_data[1],ifr.ifr_hwaddr.sa_data[2],ifr.ifr_hwaddr.sa_data[3],
++ ifr.ifr_hwaddr.sa_data[4],ifr.ifr_hwaddr.sa_data[5]);
++
++ if (inband_remote_cmd(cmd) < 0)
++ return -1;
++
++ os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name));
++ if (inband_ioctl(SIOCGIFHWADDR,&ifr) < 0)
++ return -1;
++ else
++ os_memcpy(addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
++ return 0;
++}
++#endif
++
++#ifdef RTK_MBSSID
++static int realtek_bss_add(void *priv, const char *ifname, const u8 *bssid)
++{
++ struct realtek_driver_data *drv = priv;
++ struct i802_bss *new_bss = NULL;
++ struct ifreq ifr;
++ struct rtk_hapd_config config;
++ struct hostapd_data *hapd = drv->hapd;
++
++ //printf("realtek_bss_add : ifname = %s\n",ifname);
++
++ new_bss = os_zalloc(sizeof(*new_bss));
++ if (new_bss == NULL)
++ return -1;
++
++
++ memset(&ifr, 0, sizeof(ifr));
++ snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", ifname);
++#ifdef STAND_ALONE
++ if (ioctl(drv->ioctl_sock, SIOCGIFINDEX, &ifr) != 0) {
++ perror("ioctl(SIOCGIFINDEX)");
++ goto bad;
++ }
++#endif
++#if defined(INBAND_CTRL)
++ INBAND_IOCTLPKT_DUMP(&ifr,sizeof(ifr));
++ if (inband_ioctl(SIOCGIFINDEX, &ifr) < 0) {
++ perror("inband_ioctl(SIOCGIFINDEX)");
++ goto bad;
++ }
++#endif
++ os_strlcpy(new_bss->ifname, ifname, IFNAMSIZ);
++
++#ifdef INBAND_CTRL
++ new_bss->sock_xmit = drv->sock_xmit;
++#else
++ new_bss->sock_xmit = l2_packet_init(new_bss->ifname, NULL, ETH_P_EAPOL, handle_read, drv, 1);
++#endif
++ if (new_bss->sock_xmit == NULL)
++ goto bad;
++
++ //do we nee to set HW addr to VAP??
++ realtek_set_iface_flags(new_bss->ifname,drv, 0); //down the interface ...... , bring up in realtek_commit!!
++
++ if (bssid[0] | bssid[1] | bssid[2] | bssid[3] | bssid[4] | bssid[5])
++ realtek_set_iface_hwMac(new_bss->ifname,drv, bssid);
++ else
++ printf("Warning !!! VAP no HW addr setting \n");
++
++ //memset(&config, 0, sizeof(struct rtk_hapd_config));
++ os_memcpy(&config, &rtk_config, sizeof(struct rtk_hapd_config)); //get some val from root
++ hapd =(struct hostapd_data *) find_hapd_by_ifname(priv,ifname);
++
++ realtek_set_privacy(ifname, drv, 0); /* default to no privacy */
++
++ if(realtek_read_hapd_cfg(hapd,priv, &config))
++ goto bad;
++
++ //if(realtek_read_priv_cfg(priv, &config)) //already read in init
++ // goto bad;
++ if(realtek_read_priv_vap_cfg(ifname,priv, &config)) //already read in init
++ goto bad;
++
++
++#ifdef INBAND_CTRL //HOST_LITTLE_ENDIAN
++ // rtk_hapd_config need to swap , write a function to do it
++ rtk_cfg_to_bigEndian(&config);
++#endif
++
++ if(set80211priv(ifname,drv, HAPD_IOCTL_SETCONFIG, &config, sizeof(config)))
++ {
++ wpa_printf(MSG_ERROR, "%s: Failed to set Configurations", __func__);
++ goto bad;
++ }
++
++ /*if(realtek_read_wds_cfg(priv, &wds)) //mark_mbssid , wds for vap ??
++ return -1;*/
++
++ if((hapd->conf->wpa == 0) && (hapd->conf->ieee802_1x == 0 ))
++ realtek_set_ieee8021x(ifname, drv, 0);
++
++ new_bss->ifindex = ifr.ifr_ifindex;
++ new_bss->drv = drv;
++ new_bss->next = drv->first_bss.next;
++ drv->first_bss.next = new_bss;
++ add_ifidx(drv, new_bss->ifindex);
++
++ return 0;
++
++bad :
++ os_free(new_bss);
++ return -1;
++}
++
++static int realtek_bss_remove(void *priv, const char *ifname)
++{
++
++ //printf("realtek_bss_remove : ifname = %s\n",ifname);
++
++ rtk_free_bss_by_ifname(priv,ifname);
++
++ realtek_set_iface_flags(ifname,priv, 0); //down VAP
++
++ return 0;
++}
++
++static void *
++realtek_driver_init(struct hostapd_data *hapd)
++{
++ struct realtek_driver_data *drv;
++ struct ifreq ifr;
++ struct iwreq iwr;
++ struct i802_bss *bss;
++
++ wpa_printf(MSG_DEBUG, "realtek_init +++");
++
++ drv = os_zalloc(sizeof(struct realtek_driver_data));
++ if (drv == NULL) {
++ printf("Could not allocate memory for realtek driver data\n");
++ goto bad;
++ }
++
++ drv->hapd = hapd;
++ bss = &drv->first_bss;
++ bss->drv = drv;
++ os_strlcpy(bss->ifname, hapd->conf->iface, sizeof(bss->ifname));
++
++ drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
++ if (drv->ioctl_sock < 0) {
++ perror("socket[PF_INET,SOCK_DGRAM]");
++ goto bad;
++ }
++ memcpy(drv->iface, hapd->conf->iface, sizeof(drv->iface));
++
++ memset(&ifr, 0, sizeof(ifr));
++ snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", drv->iface);
++#ifdef STAND_ALONE
++ if (ioctl(drv->ioctl_sock, SIOCGIFINDEX, &ifr) != 0) {
++ perror("ioctl(SIOCGIFINDEX)");
++ goto bad;
++ }
++#endif
++#if defined(INBAND_CTRL)
++ INBAND_IOCTLPKT_DUMP(&ifr,sizeof(ifr));
++ if (inband_ioctl(SIOCGIFINDEX, &ifr) < 0) {
++ perror("inband_ioctl(SIOCGIFINDEX)");
++ goto bad;
++ }
++#endif
++ drv->ifindex = ifr.ifr_ifindex;
++ bss->ifindex = drv->ifindex;
++#ifdef INBAND_CTRL
++ drv->sock_xmit = l2_packet_init(INBAND_INTF, NULL, ETH_P_EAPOL, handle_read, drv, 1);
++#else
++ drv->sock_xmit = l2_packet_init(drv->iface, NULL, ETH_P_EAPOL, handle_read, drv, 1);
++#endif
++ if (drv->sock_xmit == NULL)
++ goto bad;
++#ifdef INBAND_CTRL
++ if( rtk_l2_packet_get_own_addr(drv,hapd->own_addr) )
++#else
++ if (l2_packet_get_own_addr(drv->sock_xmit, hapd->own_addr))
++#endif
++ goto bad;
++
++ //mark_mbssid , now recv all EAPOL from one socket
++ drv->sock_recv = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_EAPOL));
++ if (drv->sock_recv < 0) {
++ perror("socket(PF_PACKET, SOCK_DGRAM, ETH_P_EAPOL)");
++ goto bad;
++ }
++ if (eloop_register_read_sock(drv->sock_recv, handle_eapol, drv, NULL))
++ {
++ printf("Could not register read socket for eapol\n");
++ goto bad;
++ }
++
++ memset(&iwr, 0, sizeof(iwr));
++ strncpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
++
++ realtek_set_iface_flags(drv->iface,drv, 0); /* mark down during setup */
++ realtek_set_privacy(drv->iface, drv, 0); /* default to no privacy */
++
++ if(realtek_hapd_config(drv))
++ goto bad;
++
++ if((hapd->conf->wpa == 0) && (hapd->conf->ieee802_1x == 0 ))
++ realtek_set_ieee8021x(drv->iface, drv, 0);
++
++ wpa_printf(MSG_DEBUG, "realtek_init ---");
++ return bss;
++bad:
++ wpa_printf(MSG_ERROR, "realtek_init failed!");
++
++ if (drv != NULL)
++ realtek_deinit(drv);
++
++ return NULL;
++}
++
++static void *
++realtek_init(struct hostapd_data *hapd)
++{
++ struct realtek_driver_data *drv;
++ struct i802_bss *bss;
++ int i;
++
++ bss = realtek_driver_init(hapd);
++
++ if (bss == NULL)
++ return NULL;
++
++ drv = bss->drv;
++
++ drv->num_if_indices = RTK_MAX_IF_INDEX;
++ for(i=0;i<drv->num_if_indices;i++)
++ drv->if_indices[i]=0;
++
++ add_ifidx(drv, drv->ifindex);
++
++ //below maybe add bridge control in the future
++ //return bss;
++ return drv;
++
++}
++
++#else //mark_mbssid , remove below in future
++
++static void *
++realtek_init(struct hostapd_data *hapd)
++{
++ struct realtek_driver_data *drv;
++ struct ifreq ifr;
++ struct iwreq iwr;
++
++ wpa_printf(MSG_DEBUG, "realtek_init +++");
++
++ drv = os_zalloc(sizeof(struct realtek_driver_data));
++ if (drv == NULL) {
++ printf("Could not allocate memory for realtek driver data\n");
++ goto bad;
++ }
++
++ drv->hapd = hapd;
++ drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
++ if (drv->ioctl_sock < 0) {
++ perror("socket[PF_INET,SOCK_DGRAM]");
++ goto bad;
++ }
++ memcpy(drv->iface, hapd->conf->iface, sizeof(drv->iface));
++
++ memset(&ifr, 0, sizeof(ifr));
++ snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", drv->iface);
++#ifdef STAND_ALONE
++ if (ioctl(drv->ioctl_sock, SIOCGIFINDEX, &ifr) != 0) {
++ perror("ioctl(SIOCGIFINDEX)");
++ goto bad;
++ }
++#endif
++#if defined(INBAND_CTRL)
++ INBAND_IOCTLPKT_DUMP(&ifr,sizeof(ifr));
++ if (inband_ioctl(SIOCGIFINDEX, &ifr) < 0) {
++ perror("inband_ioctl(SIOCGIFINDEX)");
++ goto bad;
++ }
++#endif
++ drv->ifindex = ifr.ifr_ifindex;
++#ifdef INBAND_CTRL
++ drv->sock_xmit = l2_packet_init(INBAND_INTF, NULL, ETH_P_EAPOL, handle_read, drv, 1);
++#else
++ drv->sock_xmit = l2_packet_init(drv->iface, NULL, ETH_P_EAPOL, handle_read, drv, 1);
++#endif
++ if (drv->sock_xmit == NULL)
++ goto bad;
++#ifdef INBAND_CTRL
++ if( rtk_l2_packet_get_own_addr(drv,hapd->own_addr) )
++#else
++ if (l2_packet_get_own_addr(drv->sock_xmit, hapd->own_addr))
++#endif
++ goto bad;
++ if (hapd->conf->bridge[0] != '\0') {
++ drv->sock_recv = l2_packet_init(hapd->conf->bridge, NULL,
++ ETH_P_EAPOL, handle_read, drv,
++ 1); //fix receive sock??
++ if (drv->sock_recv == NULL)
++ goto bad;
++ } else
++ drv->sock_recv = drv->sock_xmit;
++
++ memset(&iwr, 0, sizeof(iwr));
++ strncpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
++
++ realtek_set_iface_flags(drv->iface,drv, 0); /* mark down during setup */
++ realtek_set_privacy(drv->iface, drv, 0); /* default to no privacy */
++
++ if(realtek_hapd_config(drv))
++ goto bad;
++
++ if((hapd->conf->wpa == 0) && (hapd->conf->ieee802_1x == 0 ))
++ realtek_set_ieee8021x(drv->iface, drv, 0);
++
++ wpa_printf(MSG_DEBUG, "realtek_init ---");
++ return drv;
++bad:
++ wpa_printf(MSG_ERROR, "realtek_init failed!");
++
++ if (drv != NULL)
++ realtek_deinit(drv);
++
++ return -1;
++}
++#endif
++
++static void
++realtek_deinit(void *priv)
++{
++ struct realtek_driver_data *drv = priv;
++
++ wpa_printf(MSG_DEBUG, "realtek_deinit +++");
++
++ drv->hapd->driver = NULL;
++
++ realtek_set_iface_flags(drv->iface,drv, 0);
++ #if 0 /* OLD */
++ if (drv->probe_recv != NULL)
++ l2_packet_deinit(drv->probe_recv);
++ #endif
++ if (drv->ioctl_sock >= 0)
++ close(drv->ioctl_sock);
++#ifdef RTK_MBSSID
++ if (drv->sock_recv >= 0) {
++ eloop_unregister_read_sock(drv->sock_recv);
++ close(drv->sock_recv);
++ }
++#else
++ if (drv->sock_recv != NULL && drv->sock_recv != drv->sock_xmit)
++ l2_packet_deinit(drv->sock_recv);
++#endif
++ if (drv->sock_xmit != NULL)
++ l2_packet_deinit(drv->sock_xmit);
++ free(drv);
++
++ wpa_printf(MSG_DEBUG, "realtek_deinit ---");
++}
++
++static int
++realtek_set_ssid(const char *ifname, void *priv, const u8 *buf, int len)
++{
++ struct realtek_driver_data *drv = priv;
++ struct iwreq iwr;
++
++ wpa_printf(MSG_DEBUG, "realtek_set_ssid +++");
++
++ memset(&iwr, 0, sizeof(iwr));
++ strncpy(iwr.ifr_name, ifname, IFNAMSIZ);
++ iwr.u.essid.flags = 1; /* SSID active */
++ iwr.u.essid.pointer = (caddr_t) buf;
++ iwr.u.essid.length = len + 1;
++#ifdef STAND_ALONE
++ if (ioctl(drv->ioctl_sock, SIOCSIWESSID, &iwr) < 0) {
++ perror("ioctl[SIOCSIWESSID]");
++ printf("len=%d\n", len);
++ return -1;
++ }
++#endif
++#if defined(INBAND_CTRL)
++ INBAND_IOCTLPKT_DUMP(&iwr,sizeof(iwr));
++ if (inband_ioctl(SIOCSIWESSID, &iwr) < 0) {
++ perror("inband_ioctl[SIOCSIWESSID]");
++ printf("len=%d\n", len);
++ return -1;
++ }
++#endif
++ return 0;
++}
++
++static int
++realtek_get_ssid(const char *ifname, void *priv, u8 *buf, int len)
++{
++ struct realtek_driver_data *drv = priv;
++ struct iwreq iwr;
++ int ret = 0;
++
++ wpa_printf(MSG_DEBUG, "realtek_get_ssid +++");
++
++ memset(&iwr, 0, sizeof(iwr));
++ strncpy(iwr.ifr_name, ifname, IFNAMSIZ);
++ iwr.u.essid.pointer = (caddr_t) buf;
++ iwr.u.essid.length = len;
++#ifdef STAND_ALONE
++ if (ioctl(drv->ioctl_sock, SIOCGIWESSID, &iwr) < 0) {
++ perror("ioctl[SIOCGIWESSID]");
++ ret = -1;
++ } else
++ ret = iwr.u.essid.length;
++#endif
++#if defined(INBAND_CTRL)
++ INBAND_IOCTLPKT_DUMP(&iwr,sizeof(iwr));
++ if (inband_ioctl(SIOCGIWESSID, &iwr) < 0) {
++ perror("ioctl[SIOCGIWESSID]");
++ ret = -1;
++ }
++#endif
++ return ret;
++}
++
++static int
++realtek_set_countermeasures(void *priv, int enabled)
++{
++ struct realtek_driver_data *drv = priv;
++ wpa_printf(MSG_DEBUG, "realtek_set_countermeasures +++");
++ wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
++ return set80211param(drv->iface,drv, IEEE80211_PARAM_COUNTERMEASURES, enabled);
++}
++
++#ifdef INBAND_CTRL
++/* inband ioctl start */
++inline void realtek_priviwr(struct iwreq *iwr, unsigned char *param, void *value)
++{
++ unsigned char buf[1024] = {0};
++
++ sprintf(buf,"%s=%d",param,*(unsigned int *)value);
++ iwr->u.data.length = os_strlen(buf);
++ iwr->u.data.pointer = os_malloc(iwr->u.data.length+1);
++ if( iwr->u.data.pointer )
++ os_memcpy(iwr->u.data.pointer,buf,iwr->u.data.length+1);
++ else
++ printf("Err: Alloc memory failed while %s\n",__FUNCTION__);
++}
++#endif
++
++
++static int
++realtek_commit(void *priv)
++{
++ struct realtek_driver_data *drv = priv;
++#ifdef RTK_MBSSID
++ struct i802_bss *tbss = &drv->first_bss,*bss;
++ wpa_printf(MSG_DEBUG, "realtek_commit +++");
++
++ //up root interface here
++ if(realtek_set_iface_flags(drv->iface,priv, 1) < 0)
++ return -1;
++ //up other VAP
++ while (tbss) {
++
++ bss = tbss->next;
++ if(bss == NULL)
++ break;
++
++ if(realtek_set_iface_flags(bss->ifname,priv, 1)<0)
++ return -1;
++ tbss = tbss->next ;
++ }
++ return 0;
++#else
++ return realtek_set_iface_flags(drv->iface,priv, 1);
++#endif
++}
++
++#ifdef EAP_WPS
++static int
++realtek_set_wps_ie(const char *ifname,void *priv, u8 *iebuf, int iebuflen, u32 frametype)
++{
++ struct realtek_driver_data *drv = priv;
++ u8 buf[256];
++ struct ieee80211req_getset_appiebuf * ie;
++ // int i;
++
++ ie = (struct ieee80211req_getset_appiebuf *) buf;
++ ie->app_frmtype = frametype;
++ ie->app_buflen = iebuflen;
++ if (iebuflen > 0)
++ os_memcpy(&(ie->app_buf[0]), iebuf, iebuflen);
++
++#ifdef INBAND_CTRL //HOST_LITTLE_ENDIAN
++ // int32 need to swap
++ ie->app_frmtype = htonl(ie->app_frmtype);
++ ie->app_buflen = htonl(ie->app_buflen);
++#endif
++ return set80211priv(ifname,priv, IEEE80211_IOCTL_SET_APPIEBUF, ie,
++ sizeof(struct ieee80211req_getset_appiebuf) + iebuflen);
++}
++
++
++static int
++realtek_set_wps_beacon_ie(const char *ifname, void *priv, const u8 *iebuf, size_t iebuflen)
++{
++ wpa_printf(MSG_DEBUG, "realtek_set_wps_beacon_ie +++");
++ return realtek_set_wps_ie(ifname,priv, iebuf, iebuflen,
++ IEEE80211_APPIE_FRAME_BEACON);
++}
++
++
++static int
++realtek_set_wps_probe_resp_ie(const char *ifname, void *priv, const u8 *iebuf, size_t iebuflen)
++{
++ wpa_printf(MSG_DEBUG, "realtek_set_wps_probe_resp_ie +++");
++ return realtek_set_wps_ie(ifname,priv, iebuf, iebuflen,
++ IEEE80211_APPIE_FRAME_PROBE_RESP);
++}
++
++
++static int
++realtek_set_wps_assoc_resp_ie(const char *ifname, void *priv, const u8 *iebuf, size_t iebuflen)
++{
++ wpa_printf(MSG_DEBUG, "realtek_set_wps_assoc_resp_ie +++");
++ return realtek_set_wps_ie(ifname,priv, iebuf, iebuflen,
++ IEEE80211_APPIE_FRAME_ASSOC_RESP);
++}
++
++
++/* Ask to receive copies of all probe requests received.
++ */
++static int
++realtek_start_receive_prob_req(void *priv)
++{
++#if 0 //this function is not used now!!
++ struct ieee80211req_set_filter filt;
++
++ wpa_printf(MSG_DEBUG, "%s Enter\n", __FUNCTION__);
++ filt.app_filterype = IEEE80211_FILTER_TYPE_PROBE_REQ;
++#ifdef INBAND_CTRL //HOST_LITTLE_ENDIAN
++ // int32 need to swap
++ filt.app_filterype = htonl(filt.app_filterype);
++#endif
++ return set80211priv(priv, IEEE80211_IOCTL_FILTERFRAME, &filt,
++ sizeof(struct ieee80211req_set_filter));
++#endif
++ return 0;
++}
++
++#endif /* EAP_WPS */
++
++#ifdef RTK_HAPD
++//Turn ON|OFF driver for hostapd reload.
++//mark_mbssid , realtek_driver_on , it's only for WPS in root hapd reload
++static int realtek_driver_on(void *priv, int on)
++{
++ struct realtek_driver_data *drv = priv;
++ struct hostapd_data *hapd = drv->hapd;
++
++ wpa_printf(MSG_DEBUG, "realtek_driver_on = %d +++", on);
++
++ if((hapd->conf->wpa == 0) && (hapd->conf->ieee802_1x ==0 ) && (on == 1))
++ realtek_set_ieee8021x(drv->iface, drv, 0);
++
++ return realtek_set_iface_flags(drv->iface,priv, on);
++}
++
++static int realtek_config_rate(int *rate_list, unsigned int *rate_config)
++{
++ // bit mask value. bit0-bit11 as 1,2,5.5,11,6,9,12,18,24,36,48,54
++ int temp = 0;
++
++ while(1)
++ {
++ int rate;
++ rate = rate_list[temp];
++ if((rate == -1) || (rate == 0))
++ break;
++
++ if(rate == 10)
++ *rate_config |= BIT(0);
++ else if(rate == 20)
++ *rate_config |= BIT(1);
++ else if(rate == 55)
++ *rate_config |= BIT(2);
++ else if(rate == 110)
++ *rate_config |= BIT(3);
++ else if(rate == 60)
++ *rate_config |= BIT(4);
++ else if(rate == 90)
++ *rate_config |= BIT(5);
++ else if(rate == 120)
++ *rate_config |= BIT(6);
++ else if(rate == 180)
++ *rate_config |= BIT(7);
++ else if(rate == 240)
++ *rate_config |= BIT(8);
++ else if(rate == 360)
++ *rate_config |= BIT(9);
++ else if(rate == 480)
++ *rate_config |= BIT(10);
++ else if(rate == 540)
++ *rate_config |= BIT(11);
++
++ temp++;
++
++ if(temp > 12)
++ {
++ wpa_printf(MSG_ERROR, "Config Rates NUM > 12!!!");
++ return -1;
++ }
++
++ }
++
++ return 0;
++
++}
++
++static int realtek_parse_pwrlevel(unsigned char* pwr_list, char *val)
++{
++ int count;
++ char *pos, *end;
++
++ pos = val;
++ count = 0;
++ while (*pos != '\0') {
++ if (*pos == ' ')
++ count++;
++ pos++;
++ }
++
++ pos = val;
++ count = 0;
++
++ while (*pos != '\0') {
++ end = os_strchr(pos, ' ');
++ if (end)
++ *end = '\0';
++
++ pwr_list[count] = atoi(pos);
++
++ if (!end)
++ break;
++
++ count ++;
++ if(count >=MAX_2G_CHANNEL_NUM)
++ break;
++
++ pos = end + 1;
++ }
++
++ return 0;
++}
++
++
++static int realtek_read_hapd_cfg(struct hostapd_data *hapd,void *priv, struct rtk_hapd_config* config)
++{
++ struct realtek_driver_data *drv = priv;
++ struct hostapd_config *iconf = hapd->iconf;
++ struct hostapd_bss_config *conf = hapd->conf;
++
++ int temp = 0;
++
++ wpa_printf(MSG_DEBUG, "realtek_read_hapd_cfg +++");
++
++ config->band |= BIT(iconf->hw_mode);
++ if(iconf->ieee80211n)
++ config->band |= BIT(3);
++
++ config->channel = iconf->channel;
++
++ config->bcnint = iconf->beacon_int;
++
++ config->dtimperiod = conf->dtim_period;
++
++ //if(conf->max_num_sta > RTK_MAX_STA)//mark_mbssid ,issue how to sync conf and rtk real support
++ config->stanum = conf->max_num_sta;
++
++ config->rtsthres = iconf->rts_threshold;
++
++ config->fragthres = iconf->fragm_threshold;
++
++ if(realtek_config_rate(iconf->supported_rates, &(config->oprates)))
++ return -1;
++
++ if(realtek_config_rate(iconf->basic_rates, &(config->basicrates)))
++ return -1;
++
++ config->preamble = iconf->preamble;
++
++ config->aclmode = conf->macaddr_acl;
++
++ if(config->aclmode == ACCEPT_UNLESS_DENIED)
++ {
++ int x = 0, y =0;
++ config->aclnum = conf->num_deny_mac;
++
++ if(config->aclnum > 0)
++ {
++ for(x=0; x < config->aclnum; x++)
++ {
++ struct mac_acl_entry *deny_mac = &conf->deny_mac[x];
++ for(y=0; y<MACADDRLEN; y++)
++ {
++ config->acladdr[x][y] = deny_mac->addr[y];
++ }
++ wpa_printf(MSG_DEBUG, "DENY ACL# %d = %s", x, ether_sprintf(config->acladdr[x]));
++ }
++ }
++ }
++ else if(config->aclmode == DENY_UNLESS_ACCEPTED)
++ {
++ int x = 0, y = 0;
++ config->aclnum = conf->num_accept_mac;
++
++ if(config->aclnum > 0)
++ {
++ for(x=0; x<config->aclnum; x++)
++ {
++ struct mac_acl_entry *accept_mac = &conf->accept_mac[x];
++ for(y=0; y<MACADDRLEN; y++)
++ {
++ config->acladdr[x][y] = accept_mac->addr[y];
++ }
++ wpa_printf(MSG_DEBUG, "ACCEPT ACL# %d = %s", x, ether_sprintf(config->acladdr[x]));
++ }
++ }
++ }
++
++ config->hiddenAP = conf->ignore_broadcast_ssid;
++
++ config->qos_enable = conf->wmm_enabled;
++
++ config->expired_time = conf->ap_max_inactivity;
++
++ config->block_relay = iconf->bridge_packets;
++
++ if(iconf->ht_capab &= HT_CAP_INFO_SHORT_GI20MHZ)
++ config->shortGI20M = 1;
++
++ if(iconf->ht_capab &= HT_CAP_INFO_SHORT_GI40MHZ)
++ config->shortGI40M = 1;
++
++ wpa_printf(MSG_DEBUG, "realtek_read_hapd_cfg ---");
++
++ return 0;
++
++}
++
++static int realtek_read_priv_vap_cfg(const char *ifname,void *priv, struct rtk_hapd_config* config)
++{
++
++ struct realtek_driver_data *drv = priv;
++ FILE *f;
++ char buf[256], *pos;
++ int errors = 0;
++ int line = 0;
++ int in_bss_section=0;
++
++ f = fopen(drv->hapd->iface->config_fname, "r");
++ if (f == NULL)
++ {
++ wpa_printf(MSG_ERROR, "Could not open configuration file '%s' "
++ "for reading.", drv->hapd->iface->config_fname);
++ return -1;
++ }
++
++ while (fgets(buf, sizeof(buf), f))
++ {
++ line++;
++ if (buf[0] == '#')
++ continue;
++ pos = buf;
++ while (*pos != '\0')
++ {
++ if (*pos == '\n')
++ {
++ *pos = '\0';
++ break;
++ }
++ pos++;
++ }
++
++ if (buf[0] == '\0')
++ continue;
++
++ pos = os_strchr(buf, '=');
++ if (pos == NULL)
++ {
++ wpa_printf(MSG_ERROR, "Line %d: invalid line '%s'", line, buf);
++ errors++;
++ continue;
++ }
++ *pos = '\0';
++ pos++;
++ if (os_strcmp(buf, "bss") == 0) {
++
++ if(in_bss_section) //already in section , then scan finished;
++ break;
++ if(os_strcmp(pos, ifname) == 0)
++ {
++ in_bss_section = 1;
++ }
++ continue;
++ }
++ //below is the rtk parameter for per VAP
++ if(in_bss_section){
++ /*else if (os_strcmp(buf, "autorate") == 0) { //mark_issue
++ config->autorate = atoi(pos);
++ }*/
++ if (os_strcmp(buf, "fixrate") == 0) {
++ unsigned int select=0;
++ select = atoi(pos);
++ if(select == 0)
++ {
++ config->autorate = 1;
++ config->fixrate = 0;
++ }
++ else
++ {
++ config->autorate = 0;
++ config->fixrate = (1 << (select-1));
++ }
++ //mark_issue , need to validate the rate with hw_mode(G? , N?)
++ }else if (os_strcmp(buf, "guest_access") == 0) {
++ config->guest_access= atoi(pos);
++ }
++ }
++ }
++
++ fclose(f);
++
++ if (errors)
++ wpa_printf(MSG_ERROR, "%d errors found in configuration file "
++ "'%s'", errors, drv->hapd->iface->config_fname);
++
++ return errors;
++
++}
++
++
++static int realtek_read_priv_cfg(void *priv, struct rtk_hapd_config* config)
++{
++
++ struct realtek_driver_data *drv = priv;
++ FILE *f;
++ char buf[256], *pos;
++ int errors = 0;
++ int line = 0;
++
++ wpa_printf(MSG_DEBUG, "realtek_read_priv_cfg +++");
++
++ f = fopen(drv->hapd->iface->config_fname, "r");
++ if (f == NULL)
++ {
++ wpa_printf(MSG_ERROR, "Could not open configuration file '%s' "
++ "for reading.", drv->hapd->iface->config_fname);
++ return -1;
++ }
++
++ while (fgets(buf, sizeof(buf), f))
++ {
++ line++;
++ if (buf[0] == '#')
++ continue;
++ pos = buf;
++ while (*pos != '\0')
++ {
++ if (*pos == '\n')
++ {
++ *pos = '\0';
++ break;
++ }
++ pos++;
++ }
++
++ if (buf[0] == '\0')
++ continue;
++
++ pos = os_strchr(buf, '=');
++ if (pos == NULL)
++ {
++ wpa_printf(MSG_ERROR, "Line %d: invalid line '%s'", line, buf);
++ errors++;
++ continue;
++ }
++ *pos = '\0';
++ pos++;
++ if (os_strcmp(buf, "bss") == 0) {
++ break; //only read interface section
++ }
++ if (os_strcmp(buf, "pwrlevelCCK_A") == 0) {
++ realtek_parse_pwrlevel(config->pwrlevelCCK_A, pos);
++ }
++ else if (os_strcmp(buf, "pwrlevelCCK_B") == 0) {
++ realtek_parse_pwrlevel(config->pwrlevelCCK_B, pos);
++ }
++ else if (os_strcmp(buf, "pwrlevelHT40_1S_A") == 0) {
++ realtek_parse_pwrlevel(config->pwrlevelHT40_1S_A, pos);
++ }
++ else if (os_strcmp(buf, "pwrlevelHT40_1S_B") == 0) {
++ realtek_parse_pwrlevel(config->pwrlevelHT40_1S_B, pos);
++ }
++ else if (os_strcmp(buf, "pwrdiffHT40_2S") == 0) {
++ realtek_parse_pwrlevel(config->pwrdiffHT40_2S, pos);
++ }
++ else if (os_strcmp(buf, "pwrdiffHT20") == 0) {
++ realtek_parse_pwrlevel(config->pwrdiffHT20, pos);
++ }
++ else if (os_strcmp(buf, "pwrdiffOFDM") == 0) {
++ realtek_parse_pwrlevel(config->pwrdiffOFDM, pos);
++ }
++ else if (os_strcmp(buf, "phyBandSelect") == 0) {
++ config->phyBandSelect = atoi(pos);
++ }
++ else if (os_strcmp(buf, "macPhyMode") == 0) {
++ config->macPhyMode = atoi(pos);
++ }
++ else if (os_strcmp(buf, "ther") == 0) {
++ config->ther = atoi(pos);
++ }
++ else if (os_strcmp(buf, "swcrypto") == 0) {
++ config->swcrypto = atoi(pos);
++ }
++ else if (os_strcmp(buf, "regdomain") == 0) {
++ config->regdomain = atoi(pos);
++ }
++ /*else if (os_strcmp(buf, "autorate") == 0) { //mark_issue
++ config->autorate = atoi(pos);
++ }*/
++ else if (os_strcmp(buf, "fixrate") == 0) {
++ unsigned int select=0;
++ select = atoi(pos);
++ if(select == 0)
++ {
++ config->autorate = 1;
++ config->fixrate = 0;
++ }
++ else
++ {
++ config->autorate = 0;
++ config->fixrate = (1 << (select-1));
++ }
++ //mark_issue , need to validate the rate with hw_mode(G? , N?)
++ }
++ else if (os_strcmp(buf, "disable_protection") == 0) {
++ config->disable_protection = atoi(pos);
++ }
++ else if (os_strcmp(buf, "disable_olbc") == 0) {
++ config->disable_olbc = atoi(pos);
++ }
++ else if (os_strcmp(buf, "deny_legacy") == 0) {
++ config->deny_legacy = atoi(pos);
++ }
++ else if (os_strcmp(buf, "opmode") == 0) {
++ config->opmode = atoi(pos);
++ }
++ else if (os_strcmp(buf, "vap_enable") == 0) {
++ config->vap_enable = atoi(pos);
++ }
++ else if (os_strcmp(buf, "use40M") == 0) {
++ config->use40M = atoi(pos);
++ }
++ else if (os_strcmp(buf, "2ndchoffset") == 0) {
++ config->_2ndchoffset = atoi(pos);
++ }
++ else if (os_strcmp(buf, "ampdu") == 0) {
++ config->ampdu = atoi(pos);
++ }
++ else if (os_strcmp(buf, "coexist") == 0) {
++ config->coexist = atoi(pos);
++ }
++ else if (os_strcmp(buf, "rssi_dump") == 0) {
++ config->rssi_dump = atoi(pos);
++ }
++ else if (os_strcmp(buf, "mp_specific") == 0) {
++ config->mp_specific = atoi(pos);
++ }
++ else if (os_strcmp(buf, "use_ext_pa") == 0) {
++ config->use_ext_pa = atoi(pos);
++ }
++ else if (os_strcmp(buf, "guest_access") == 0) {
++ config->guest_access= atoi(pos);
++ }
++
++ }
++
++ fclose(f);
++
++ if (errors)
++ wpa_printf(MSG_ERROR, "%d errors found in configuration file "
++ "'%s'", errors, drv->hapd->iface->config_fname);
++
++ wpa_printf(MSG_DEBUG, "realtek_read_priv_cfg ---");
++
++ return errors;
++
++}
++
++
++
++static int realtek_read_wds_cfg(void *priv, struct rtk_wds_config* wds)
++{
++
++ struct realtek_driver_data *drv = priv;
++ FILE *f;
++ char buf[256], *pos;
++ int errors = 0;
++ int line = 0;
++
++ wpa_printf(MSG_DEBUG, "realtek_read_wds_cfg +++");
++
++ f = fopen(drv->hapd->iface->config_fname, "r");
++ if (f == NULL)
++ {
++ wpa_printf(MSG_ERROR, "Could not open configuration file '%s' "
++ "for reading.", drv->hapd->iface->config_fname);
++ return -1;
++ }
++
++ while (fgets(buf, sizeof(buf), f))
++ {
++ line++;
++ if (buf[0] == '#')
++ continue;
++ pos = buf;
++ while (*pos != '\0')
++ {
++ if (*pos == '\n')
++ {
++ *pos = '\0';
++ break;
++ }
++ pos++;
++ }
++
++ if (buf[0] == '\0')
++ continue;
++
++ pos = os_strchr(buf, '=');
++ if (pos == NULL)
++ {
++ wpa_printf(MSG_ERROR, "Line %d: invalid line '%s'", line, buf);
++ errors++;
++ continue;
++ }
++ *pos = '\0';
++ pos++;
++
++ if (strcmp(buf, "wds_enable") == 0) {
++ wds->wdsEnabled = atoi(pos);
++ }
++ else if (strcmp(buf, "wds_num") == 0) {
++ wds->wdsNum = atoi(pos);
++ }
++ else if (strcmp(buf, "wds_mac1") == 0) {
++ if (hwaddr_aton(pos, wds->macAddr[0])) {
++ wpa_printf(MSG_ERROR, "Line %d: invalid MAC address '%s'\n", line, pos);
++ errors++;
++ }
++ }
++ else if (strcmp(buf, "wds_mac2") == 0) {
++ if (hwaddr_aton(pos, wds->macAddr[1])) {
++ wpa_printf(MSG_ERROR, "Line %d: invalid MAC address '%s'\n", line, pos);
++ errors++;
++ }
++ }
++ else if (strcmp(buf, "wds_mac3") == 0) {
++ if (hwaddr_aton(pos, wds->macAddr[2])) {
++ wpa_printf(MSG_ERROR, "Line %d: invalid MAC address '%s'\n", line, pos);
++ errors++;
++ }
++ }
++ else if (strcmp(buf, "wds_mac4") == 0) {
++ if (hwaddr_aton(pos, wds->macAddr[3])) {
++ wpa_printf(MSG_ERROR, "Line %d: invalid MAC address '%s'\n", line, pos);
++ errors++;
++ }
++ }
++ else if (strcmp(buf, "wds_ssid") == 0) {
++ int ssid_len = strlen(pos);
++ if (ssid_len > HOSTAPD_MAX_SSID_LEN || ssid_len < 1) {
++ wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'\n", line, pos);
++ errors++;
++ } else {
++ memcpy(wds->ssid, pos, ssid_len);
++ wds->ssid[ssid_len] = '\0';
++ }
++ }
++ else if (strcmp(buf, "wds_enc_type") == 0) {
++ wds->wdsPrivacy = atoi(pos);
++ }
++ else if (strcmp(buf, "wds_wepkey") == 0) {
++ int len = strlen(pos);
++ int tmp_error = 0;
++
++ //free(wds->wdsWepKey);
++ wds->wdsWepKey = NULL;
++ wds->wdsWepKeyLen = 0;
++
++ if (pos[0] == '"') {
++ if (len < 2 || pos[len - 1] != '"')
++ tmp_error++;
++ else{
++ len -= 2;
++ if (len > 0) {
++ wds->wdsWepKey = malloc(len);
++ if (wds->wdsWepKey == NULL)
++ tmp_error++;
++ else
++ memcpy(wds->wdsWepKey, pos + 1, len);
++ }
++ }
++ }
++ else
++ {
++ if (len & 1)
++ tmp_error++;
++
++ len /= 2;
++ if (len > 0)
++ {
++ wds->wdsWepKey = malloc(len);
++ if (wds->wdsWepKey == NULL)
++ tmp_error++;
++
++ if (hexstr2bin(pos, wds->wdsWepKey, len) < 0)
++ tmp_error++;
++ }
++ }
++
++ wds->wdsWepKeyLen = len;
++
++ if(tmp_error)
++ {
++ wpa_printf(MSG_ERROR, "Line %d: invalid wds_wepkey '%s'\n", line, pos);
++ errors++;
++ }
++ }
++ else if (strcmp(buf, "wds_passphrase") == 0) {
++ int len = strlen(pos);
++ //free(wds->wdsPskPassPhrase);
++ wds->wdsPskPassPhrase = NULL;
++ if (len < 8 || len > 63) {
++ wpa_printf(MSG_ERROR, "Line %d: invalid WPA passphrase length"
++ " %d (expected 8..63)\n", line, len);
++ errors++;
++ } else {
++ if ((wds->wdsPskPassPhrase = strdup(pos)) == NULL)
++ errors++;
++ }
++ }
++
++ }
++
++ fclose(f);
++
++ if (errors)
++ wpa_printf(MSG_ERROR, "%d errors found in configuration file "
++ "'%s'", errors, drv->hapd->iface->config_fname);
++
++ wpa_printf(MSG_DEBUG, "realtek_read_wds_cfg ---");
++
++ return errors;
++
++}
++
++static int realtek_hapd_config(void *priv)
++{
++ struct realtek_driver_data *drv = priv;
++ struct hostapd_data *hapd = drv->hapd;
++ struct rtk_hapd_config *config=&rtk_config;
++ struct rtk_wds_config wds;
++
++ wpa_printf(MSG_DEBUG, "realtek_hapd_config +++");
++
++ memset(config, 0, sizeof(struct rtk_hapd_config));
++
++ config->is_hapd = 1; //RTK_WPAS
++
++ if(realtek_read_hapd_cfg(hapd,priv, config))
++ return -1;
++
++ if(realtek_read_priv_cfg(priv, config))
++ return -1;
++
++#ifdef INBAND_CTRL //HOST_LITTLE_ENDIAN
++ // rtk_hapd_config need to swap , write a function to do it
++ rtk_cfg_to_bigEndian(config);
++#endif
++
++ if(set80211priv(drv->iface,drv, HAPD_IOCTL_SETCONFIG, config, sizeof(struct rtk_hapd_config)))
++ {
++ wpa_printf(MSG_ERROR, "%s: Failed to set Configurations", __func__);
++ return -1;
++ }
++
++ if(realtek_read_wds_cfg(priv, &wds)) //mark_mbssid , wds for vap ??
++ return -1;
++
++ /*
++ if(realtek_set_wds(priv, wds))
++ return -1;
++ */
++
++ wpa_printf(MSG_DEBUG, "realtek_hapd_config ---");
++
++ return 0;
++
++}
++
++
++#endif
++
++
++const struct wpa_driver_ops wpa_driver_realtek_ops = {
++ .name = "realtek",
++ .init = realtek_init,
++ .deinit = realtek_deinit,
++ .set_ieee8021x = realtek_set_ieee8021x,
++ .set_privacy = realtek_set_privacy,
++ .set_encryption = realtek_set_key,
++ .get_seqnum = realtek_get_seqnum,
++ .flush = realtek_flush,
++ .set_generic_elem = realtek_set_opt_ie,
++ .wireless_event_init = realtek_wireless_event_init,
++ .wireless_event_deinit = realtek_wireless_event_deinit,
++ .sta_set_flags = realtek_sta_set_flags,
++ //mark read_sta_data because both ralink & broadcom NOT support
++ //.read_sta_data = realtek_read_sta_driver_data,
++ .send_eapol = realtek_send_eapol,
++ .sta_disassoc = realtek_sta_disassoc,
++ .sta_deauth = realtek_sta_deauth,
++#ifdef RTK_MBSSID
++ .bss_add = realtek_bss_add,
++ .bss_remove = realtek_bss_remove,
++#endif
++#ifdef RTK_HAPD
++ .sta_remove = realtek_sta_remove,
++#endif
++ .set_ssid = realtek_set_ssid,
++ .get_ssid = realtek_get_ssid,
++ .set_countermeasures = realtek_set_countermeasures,
++ //mark sta_clear_stats because both ralink & broadcom NOT support
++ //.sta_clear_stats = realtek_sta_clear_stats,
++ .commit = realtek_commit,
++#ifdef EAP_WPS
++ .set_wps_beacon_ie = realtek_set_wps_beacon_ie,
++ .set_wps_probe_resp_ie = realtek_set_wps_probe_resp_ie,
++ //.set_wps_assoc_resp_ie = realtek_set_wps_assoc_resp_ie,
++#endif /* EAP_WPS */
++#ifdef RTK_HAPD
++ .driver_on = realtek_driver_on,
++#endif
++};
++
++#ifdef MODIFIED_BY_SONY
++int wext_set_key(void *priv, int 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 realtek_driver_data *drv = priv;
++ struct hostapd_data *hapd = drv->hapd;
++ struct hostapd_bss_config *conf = hapd->conf;
++ struct iwreq iwr;
++ int ret = 0;
++ int ioctl_sock;
++
++ wpa_printf(MSG_DEBUG,"%s: alg=%d key_idx=%d set_tx=%d seq_len=%lu "
++ "key_len=%lu", __FUNCTION__, alg, key_idx, set_tx,
++ (unsigned long) seq_len, (unsigned long) key_len);
++
++ ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
++ if (ioctl_sock < 0) {
++ perror("socket(PF_INET,SOCK_DGRAM)");
++ return -1;
++ }
++
++ os_memset(&iwr, 0, sizeof(iwr));
++ os_strncpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
++ iwr.u.encoding.flags = key_idx + 1;
++ if (alg == WPA_ALG_NONE)
++ iwr.u.encoding.flags |= IW_ENCODE_DISABLED;
++ if (conf->auth_algs & HOSTAPD_AUTH_OPEN)
++ iwr.u.encoding.flags |= IW_ENCODE_OPEN;
++ if (conf->auth_algs & HOSTAPD_AUTH_SHARED_KEY)
++ iwr.u.encoding.flags |= IW_ENCODE_RESTRICTED;
++ iwr.u.encoding.pointer = (caddr_t) key;
++ iwr.u.encoding.length = key_len;
++#ifdef STAND_ALONE
++ if (ioctl(ioctl_sock, SIOCSIWENCODE, &iwr) < 0) {
++ perror("ioctl[SIOCSIWENCODE]");
++ ret = -1;
++ }
++#endif
++#if defined(INBAND_CTRL)
++ INBAND_IOCTLPKT_DUMP(&iwr,sizeof(iwr));
++ if (inband_ioctl(&drv->ioctl_ioh_obj,SIOCSIWENCODE, &iwr) < 0) {
++ perror("inband_ioctl[SIOCSIWENCODE]");
++ ret = -1;
++ }
++#endif
++
++ if (set_tx && alg != WPA_ALG_NONE) {
++ os_memset(&iwr, 0, sizeof(iwr));
++ os_strncpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
++ iwr.u.encoding.flags = key_idx + 1;
++ iwr.u.encoding.pointer = (caddr_t) key;
++ iwr.u.encoding.length = 0;
++#ifdef STAND_ALONE
++ if (ioctl(ioctl_sock, SIOCSIWENCODE, &iwr) < 0) {
++ perror("ioctl[SIOCSIWENCODE] (set_tx)");
++ ret = -1;
++ }
++#endif
++#if defined(INBAND_CTRL)
++ INBAND_IOCTLPKT_DUMP(&iwr,sizeof(iwr));
++ if (inband_ioctl(&drv->ioctl_ioh_obj,SIOCSIWENCODE, &iwr) < 0) {
++ perror("inband_ioctl[SIOCSIWENCODE] (set_tx)");
++ ret = -1;
++ }
++#endif
++
++ }
++ close(ioctl_sock);
++ return ret;
++}
++#endif /* MODIFIED_BY_SONY */
+Index: hostapd-rtk-0.6.10/hostapd/driver_realtek.h
+===================================================================
+--- /dev/null
++++ hostapd-rtk-0.6.10/hostapd/driver_realtek.h
+@@ -0,0 +1,147 @@
++
++#define MACADDRLEN 6
++#define PROBEIELEN 260
++
++#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 RTK_MBSSID 1
++#define RTK_MAX_STA 32
++#define RTK_MAX_IF_INDEX 16
++
++enum HAPD_EVENT{
++ HAPD_EXIRED = 0,
++ HAPD_REGISTERED = 1,
++ HAPD_MIC_FAILURE = 2,
++ HAPD_TRAFFIC_STAT = 3,
++ HAPD_PUSH_BUTTON = 4,
++ HAPD_WPS_PROBEREQ = 5,
++ HAPD_WDS_SETWPA = 6
++};
++
++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;
++
+Index: hostapd-rtk-0.6.10/hostapd/README-REALTEK_WIFI
+===================================================================
+--- /dev/null
++++ hostapd-rtk-0.6.10/hostapd/README-REALTEK_WIFI
+@@ -0,0 +1,116 @@
++==================================================================================
++Introduction
++ This document is the guideline for building/using/porting the Hostapd
++application to support Realtek's Wifi device.
++
++==================================================================================
++
++1.Build the hostapd daemon
++-----------------------------
++ If the Wifi device is connected to your platform using GMII/MII interface
++then the inband libary must be built and enabled in hostapd.control. Please follow
++the steps below to build the hostapd daemon.()
++
++ a. Build the inband libary (#This step can be skipped,if you dont need inband-cotrol)
++
++ - Enter the inband_dir directory.(default:../../inband_dir)
++
++ - Modify the definition of CC and LD in /inband_lib/Makefile to fit your
++ toolchain setting.
++
++ - type make and the inband.a libray will be built on your platform.
++
++ b. Enable/Disable the inband-control support in Hostapd.
++
++ - Enable the lines below in hostapd-0.6.10/hostapd/Makefile to enable the
++ inband-support.In the other hand,disable these lines to disable the inband-control.
++
++ CFLAGS += -DINBAND_CTRL
++ CFLAGS += -I../../inband_lib
++ LIBS += ../../inband_lib/inband.a
++
++ c. Make the Hostapd
++
++ - enter the directory : hostapd-0.6.10/hostapd/
++
++ - Modify hostapd-0.6.10/hostapd/Makefile to include your openssl libary.Below
++ lines are the default setting in Realtek's WIFI-AP SDK.
++
++ LIBS += -ldl ../../openssl-0.9.8b/libssl.a ../../openssl-0.9.8b/libcrypto.a
++ LIBS_p += ../../openssl-0.9.8b/libcrypto.a
++ LIBS_h += ../../openssl-0.9.8b/libcrypto.a
++
++ - Modify the definition of CC and LD in hostapd-0.6.10/hostapd/Makefile to
++ fit your toolchain setting.
++
++ - type 'make' under hostapd-0.6.10/hostapd ,then the hostapd daemon will be built.
++
++NOTEs:
++ - Because of the ethernet type 0x8899 and 0x9000 is used for inband control
++ please do not use them in other applications.
++
++ - The default local interface for inband control is "br0', you can change the definition
++ in drv_realtek.c(the line list below) to fit your MII interface setting.
++
++ #define INBAND_INTF "br0"
++
++ - The default MAC address for inband-control is "00:12:34:56:78:99", it
++ can be changed in drv_realtek.c.
++
++==================================================================================
++
++2.Realtek proprietary configuration options
++----------------------------
++
++ - Please refer to file hostapd.test_conf(under hostapd-0.6.10/hostapd/conf)
++ for detail descriptions about the new added realtek private configurations. All these
++ configurations are directly mapped to realtek WiFi mibs.
++
++ - Other inherently hostapd configurations are same as before.
++
++ - 'auth_algs' has new values for supporting Open Networking & WEP+802.1x
++ ## ======== Modify auth_algs support==========
++ ## bit 0 = Open System Authentication
++ ## bit 1 = Shared Key Authentication (requires WEP)
++ ## bit 0 + bit 1 = Auto WEP mode
++ ## bit 2 = WEP + 802.1x
++ ## bit 3 = Open Networking(no security)
++
++ - These hostapd configuration files(under /hostapd-0.6.10/hostapd/conf) can be examples for testing
++ - hostapd.none_security :WPS configured, Open Networking.
++ - hostapd.wpa_psk :WPS configured, WPA-PSK CCMP.
++ - NOT Supported yet:
++ - Some IEEE 802.11 related configurations
++ - IEEE 802.11r configuration
++ - Passive scanning
++ - Multiple BSSID support
++
++
++==================================================================================
++
++3.Porting notes
++-----------------------------
++ The Hostapd for Realtek WiFi device is based on hostapd 0.6.10 and patch the realtek's implementation.
++Some notes are listed below to help you to port this package to your platform(for example ,
++you are using hostapd 0.6.9 on your platform not 0.6.10).
++
++ - Driver_realtek.c & Driver_realtek.h under /hostapd-0.6.10/hostapd are the main added files
++ for supporting realtek WiFi device.
++
++ - Other modifications about Hostapd-0.6.10 were labeled with compile tag 'RTK_HAPD'.
++ You can check these patches by searching the keyword 'RTK_HAPD'.
++
++ - List of modified source files in hostapd v0.6.10:
++ - Config.c
++ - Driver.h
++ - Hostapd.c
++ - Hostapd.h
++ - Iapp.c
++ - Os_unix.c
++ - Wps.h
++ - Wps_hostapd.c
++ - Wps_registrar.c
++ - Wps_upnp_event.c
++ - Wps_upnp_web.c
++
++=================================================================================
diff --git a/package/hostapd-rtk/patches/005-supplicant-diff.patch b/package/hostapd-rtk/patches/005-supplicant-diff.patch
new file mode 100644
index 000000000..329194bb5
--- /dev/null
+++ b/package/hostapd-rtk/patches/005-supplicant-diff.patch
@@ -0,0 +1,207 @@
+Index: hostapd-rtk-0.6.10/wpa_supplicant/config_file.c
+===================================================================
+--- hostapd-rtk-0.6.10.orig/wpa_supplicant/config_file.c
++++ hostapd-rtk-0.6.10/wpa_supplicant/config_file.c
+@@ -458,6 +458,10 @@ static const struct global_parse_data gl
+ { FUNC(os_version) },
+ { INT_RANGE(wps_cred_processing, 0, 2) },
+ #endif /* CONFIG_WPS */
++#ifdef RTK_WPAS
++ { INT(macPhyMode) },
++ { INT(phyBandSelect) },
++#endif
+ { FUNC(country) }
+ };
+
+@@ -886,6 +890,10 @@ static void wpa_config_write_global(FILE
+ fprintf(f, "wps_cred_processing=%d\n",
+ config->wps_cred_processing);
+ #endif /* CONFIG_WPS */
++#ifdef RTK_WPAS
++ fprintf(f, "macPhyMode=%d\n", config->macPhyMode);
++ fprintf(f, "phyBandSelect=%d\n", config->phyBandSelect);
++#endif
+ if (config->country[0] && config->country[1]) {
+ fprintf(f, "country=%c%c\n",
+ config->country[0], config->country[1]);
+Index: hostapd-rtk-0.6.10/wpa_supplicant/config.h
+===================================================================
+--- hostapd-rtk-0.6.10.orig/wpa_supplicant/config.h
++++ hostapd-rtk-0.6.10/wpa_supplicant/config.h
+@@ -323,6 +323,11 @@ struct wpa_config {
+ * ctrl_iface to external program(s)
+ */
+ int wps_cred_processing;
++
++#if (1)//RTK_HAPD
++ int macPhyMode;
++ int phyBandSelect;
++#endif
+ };
+
+
+Index: hostapd-rtk-0.6.10/wpa_supplicant/defconfig
+===================================================================
+--- hostapd-rtk-0.6.10.orig/wpa_supplicant/defconfig
++++ hostapd-rtk-0.6.10/wpa_supplicant/defconfig
+@@ -41,7 +41,7 @@
+
+
+ # Driver interface for Host AP driver
+-CONFIG_DRIVER_HOSTAP=y
++#CONFIG_DRIVER_HOSTAP=y
+
+ # Driver interface for Agere driver
+ #CONFIG_DRIVER_HERMES=y
+@@ -55,6 +55,9 @@ CONFIG_DRIVER_HOSTAP=y
+ # Set include directory to the madwifi source tree
+ #CFLAGS += -I../../madwifi
+
++# Driver interface for Realtek driver
++CONFIG_DRIVER_REALTEK=y
++
+ # Driver interface for Prism54 driver
+ # (Note: Prism54 is not yet supported, i.e., this will not work as-is and is
+ # for developers only)
+@@ -65,7 +68,7 @@ CONFIG_DRIVER_HOSTAP=y
+ #CONFIG_DRIVER_NDISWRAPPER=y
+
+ # Driver interface for Atmel driver
+-CONFIG_DRIVER_ATMEL=y
++#CONFIG_DRIVER_ATMEL=y
+
+ # Driver interface for old Broadcom driver
+ # Please note that the newer Broadcom driver ("hybrid Linux driver") supports
+@@ -83,7 +86,7 @@ CONFIG_DRIVER_ATMEL=y
+ #CONFIG_DRIVER_RALINK=y
+
+ # Driver interface for generic Linux wireless extensions
+-CONFIG_DRIVER_WEXT=y
++#CONFIG_DRIVER_WEXT=y
+
+ # Driver interface for Linux drivers using the nl80211 kernel interface
+ #CONFIG_DRIVER_NL80211=y
+@@ -113,7 +116,7 @@ CONFIG_DRIVER_WEXT=y
+ #CONFIG_DRIVER_TEST=y
+
+ # Driver interface for wired Ethernet drivers
+-CONFIG_DRIVER_WIRED=y
++#CONFIG_DRIVER_WIRED=y
+
+ # Driver interface for the Broadcom RoboSwitch family
+ #CONFIG_DRIVER_ROBOSWITCH=y
+Index: hostapd-rtk-0.6.10/wpa_supplicant/events.c
+===================================================================
+--- hostapd-rtk-0.6.10.orig/wpa_supplicant/events.c
++++ hostapd-rtk-0.6.10/wpa_supplicant/events.c
+@@ -259,6 +259,9 @@ static int wpa_supplicant_match_privacy(
+ for (i = 0; i < NUM_WEP_KEYS; i++) {
+ if (ssid->wep_key_len[i]) {
+ privacy = 1;
++#ifdef RTK_WPAS
++ bss->caps |= IEEE80211_CAP_PRIVACY;
++#endif
+ break;
+ }
+ }
+Index: hostapd-rtk-0.6.10/wpa_supplicant/wpa_supplicant.c
+===================================================================
+--- hostapd-rtk-0.6.10.orig/wpa_supplicant/wpa_supplicant.c
++++ hostapd-rtk-0.6.10/wpa_supplicant/wpa_supplicant.c
+@@ -40,6 +40,11 @@
+ #include "wpas_glue.h"
+ #include "wps_supplicant.h"
+
++#ifdef RTK_INBAND
++#include <net/if.h>
++#include <sys/ioctl.h>
++#endif
++
+ const char *wpa_supplicant_version =
+ "wpa_supplicant v" VERSION_STR "\n"
+ "Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi> and contributors";
+@@ -1603,25 +1608,52 @@ void wpa_supplicant_sta_rx(void *ctx, co
+ int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
+ {
+ static int interface_count = 0;
++#ifdef RTK_INBAND
++ struct ifreq ifr;
++#endif
++
+
+ if (wpa_s->driver->send_eapol) {
+ const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
+ if (addr)
+ os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
+ } else {
++
++#ifdef RTK_INBAND
++ wpa_s->l2 = l2_packet_init("eth0",
++ wpa_drv_get_mac_addr(wpa_s),
++ ETH_P_EAPOL,
++ wpa_supplicant_rx_eapol, wpa_s, 0);
++#else
+ wpa_s->l2 = l2_packet_init(wpa_s->ifname,
+ wpa_drv_get_mac_addr(wpa_s),
+ ETH_P_EAPOL,
+ wpa_supplicant_rx_eapol, wpa_s, 0);
++#endif
+ if (wpa_s->l2 == NULL)
+ return -1;
+ }
+
++#ifdef RTK_INBAND
++
++ os_memset(&ifr, 0, sizeof(ifr));
++
++ os_strlcpy(ifr.ifr_name, wpa_s->ifname, sizeof(ifr.ifr_name));
++
++ if (inband_ioctl(SIOCGIFHWADDR,&ifr) < 0)
++ printf("SIOCGIFHWADDR error !! Failed to get own address\n");
++ else
++ os_memcpy(wpa_s->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
++
++#else
++
+ if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
+ wpa_printf(MSG_ERROR, "Failed to get own L2 address");
+ return -1;
+ }
+
++#endif
++
+ wpa_printf(MSG_DEBUG, "Own MAC address: " MACSTR,
+ MAC2STR(wpa_s->own_addr));
+
+Index: hostapd-rtk-0.6.10/wpa_supplicant/Makefile
+===================================================================
+--- hostapd-rtk-0.6.10.orig/wpa_supplicant/Makefile
++++ hostapd-rtk-0.6.10/wpa_supplicant/Makefile
+@@ -157,6 +157,14 @@ OBJS_d += ../src/drivers/driver_madwifi.
+ CONFIG_WIRELESS_EXTENSION=y
+ endif
+
++ifdef CONFIG_DRIVER_REALTEK
++CFLAGS += -DCONFIG_DRIVER_REALTEK
++CFLAGS += -DINBAND_CTRL
++LIBS += -linband
++OBJS_d += ../src/drivers/driver_realtek.o
++CONFIG_WIRELESS_EXTENSION=y
++endif
++
+ ifdef CONFIG_DRIVER_ATMEL
+ CFLAGS += -DCONFIG_DRIVER_ATMEL
+ OBJS_d += ../src/drivers/driver_atmel.o
+@@ -859,8 +867,12 @@ CFLAGS += -DNEED_SHA256
+ endif
+
+ ifdef CONFIG_WIRELESS_EXTENSION
++ifdef CONFIG_DRIVER_REALTEK
++OBJS_d += ../src/drivers/driver_realtek_wext.o
++else
+ OBJS_d += ../src/drivers/driver_wext.o
+ endif
++endif
+
+ ifdef CONFIG_CTRL_IFACE
+ ifeq ($(CONFIG_CTRL_IFACE), y)
diff --git a/package/hostapd-rtk/patches/008-no-inband.patch b/package/hostapd-rtk/patches/008-no-inband.patch
new file mode 100644
index 000000000..ef71b897b
--- /dev/null
+++ b/package/hostapd-rtk/patches/008-no-inband.patch
@@ -0,0 +1,26 @@
+Index: hostapd-rtk-0.6.10/hostapd/Makefile
+===================================================================
+--- hostapd-rtk-0.6.10.orig/hostapd/Makefile
++++ hostapd-rtk-0.6.10/hostapd/Makefile
+@@ -124,7 +124,7 @@ endif
+
+ ifdef CONFIG_DRIVER_REALTEK
+ CFLAGS += -DCONFIG_DRIVER_REALTEK
+-CFLAGS += -DINBAND_CTRL
++#CFLAGS += -DINBAND_CTRL
+ LIBS += -linband
+ OBJS += driver_realtek.o
+ CONFIG_L2_PACKET=y
+Index: hostapd-rtk-0.6.10/wpa_supplicant/Makefile
+===================================================================
+--- hostapd-rtk-0.6.10.orig/wpa_supplicant/Makefile
++++ hostapd-rtk-0.6.10/wpa_supplicant/Makefile
+@@ -159,7 +159,7 @@ endif
+
+ ifdef CONFIG_DRIVER_REALTEK
+ CFLAGS += -DCONFIG_DRIVER_REALTEK
+-CFLAGS += -DINBAND_CTRL
++#CFLAGS += -DINBAND_CTRL
+ LIBS += -linband
+ OBJS_d += ../src/drivers/driver_realtek.o
+ CONFIG_WIRELESS_EXTENSION=y