diff options
author | Roman Yeryomin <roman@advem.lv> | 2012-09-22 19:44:27 +0300 |
---|---|---|
committer | Roman Yeryomin <roman@advem.lv> | 2012-12-03 00:13:22 +0200 |
commit | 709e200be3507c4f1eed2f4f2e0628b7cfba32c9 (patch) | |
tree | 2db687e9619cf0f83d4f7bac1f5bd8d3b75d6e6b /package/hostapd-rtk/patches | |
parent | 9e96cd6c1bdccc1f9d2d6978ae12523f00bd7f85 (diff) |
Add hostapd-rtk and librtk-inband packages
Signed-off-by: Roman Yeryomin <roman@advem.lv>
Diffstat (limited to 'package/hostapd-rtk/patches')
-rw-r--r-- | package/hostapd-rtk/patches/001-common-diff.patch | 264 | ||||
-rw-r--r-- | package/hostapd-rtk/patches/002-common-files.patch | 2948 | ||||
-rw-r--r-- | package/hostapd-rtk/patches/003-hostapd-diff.patch | 300 | ||||
-rw-r--r-- | package/hostapd-rtk/patches/004-hostapd-files.patch | 3529 | ||||
-rw-r--r-- | package/hostapd-rtk/patches/005-supplicant-diff.patch | 207 | ||||
-rw-r--r-- | package/hostapd-rtk/patches/008-no-inband.patch | 26 |
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 |