summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--package/hostapd-rtk/Makefile199
-rw-r--r--package/hostapd-rtk/files/hostapd.config147
-rw-r--r--package/hostapd-rtk/files/hostapd.sh278
-rw-r--r--package/hostapd-rtk/files/wpa_supplicant.config147
-rw-r--r--package/hostapd-rtk/files/wpa_supplicant.sh149
-rw-r--r--package/hostapd-rtk/patches/001-common-diff.patch264
-rw-r--r--package/hostapd-rtk/patches/002-common-files.patch2948
-rw-r--r--package/hostapd-rtk/patches/003-hostapd-diff.patch300
-rw-r--r--package/hostapd-rtk/patches/004-hostapd-files.patch3529
-rw-r--r--package/hostapd-rtk/patches/005-supplicant-diff.patch207
-rw-r--r--package/hostapd-rtk/patches/008-no-inband.patch26
-rw-r--r--package/librtk-inband/Makefile54
-rw-r--r--package/librtk-inband/files/librtk-inband.pc10
-rw-r--r--package/librtk-inband/src/Makefile21
-rw-r--r--package/librtk-inband/src/hapd_api.c447
-rw-r--r--package/librtk-inband/src/inband_cmd.c465
-rw-r--r--package/librtk-inband/src/inband_if.c443
-rw-r--r--package/librtk-inband/src/inband_if.h30
-rw-r--r--package/librtk-inband/src/include/net80211/_ieee80211.h246
-rw-r--r--package/librtk-inband/src/include/net80211/ieee80211.h947
-rw-r--r--package/librtk-inband/src/include/net80211/ieee80211_crypto.h205
-rw-r--r--package/librtk-inband/src/include/net80211/ieee80211_ioctl.h787
-rw-r--r--package/librtk-inband/src/ioh.c315
-rw-r--r--package/librtk-inband/src/ioh.h64
-rw-r--r--package/librtk-inband/src/wireless_copy.h1099
25 files changed, 13327 insertions, 0 deletions
diff --git a/package/hostapd-rtk/Makefile b/package/hostapd-rtk/Makefile
new file mode 100644
index 000000000..8253e213b
--- /dev/null
+++ b/package/hostapd-rtk/Makefile
@@ -0,0 +1,199 @@
+#
+# Copyright (C) 2006-2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+QUILT=1
+PKG_NAME:=hostapd-rtk
+PKG_VERSION:=0.6.10
+PKG_RELEASE:=1
+
+SOURCE_LEAF1=hostapd-$(PKG_VERSION).tar.gz
+SOURCE_LEAF2=wpa_supplicant-$(PKG_VERSION).tar.gz
+
+SOURCE_URL=http://hostap.epitest.fi/releases/
+
+define Download/hostapd
+ FILE:=$(SOURCE_LEAF1)
+ URL:=$(SOURCE_URL)
+ VERSION:=$(PKG_VERSION)
+ MD5SUM:=1ac442d1f984273f108b3de579c1b70d
+endef
+
+define Download/wpa_supplicant
+ FILE:=$(SOURCE_LEAF2)
+ URL:=$(SOURCE_URL)
+ VERSION:=$(PKG_VERSION)
+ MD5SUM:=8985b1030d753e5f74f8acfc34e591bb
+endef
+
+PKG_BUILD_DEPENDS:=\
+ libopenssl \
+ librtk-inband
+
+PKG_CONFIG_DEPENDS:= \
+ CONFIG_WPA_SUPPLICANT_OPENSSL
+
+LOCAL_TYPE=$(strip \
+ $(if $(findstring supplicant,$(BUILD_VARIANT)),supplicant-rtk, \
+ hostapd-rtk \
+ ))
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Download/two-parts
+ $(call Download,hostapd)
+ $(call Download,wpa_supplicant)
+ $(call Build/Autoclean)
+endef
+
+
+UNPACK_CMD1=gzip -dc $(DL_DIR)/$(SOURCE_LEAF1) | $(HOST_TAR) -C $(1) $(TAR_OPTIONS);
+UNPACK_CMD2=gzip -dc $(DL_DIR)/$(SOURCE_LEAF2) | $(HOST_TAR) -C $(1) $(TAR_OPTIONS);
+UNPACK_CMD3=mv \
+ $(1)/hostapd-$(PKG_VERSION)/hostapd \
+ $(1)/hostapd-$(PKG_VERSION)/patches \
+ $(1)/hostapd-$(PKG_VERSION)/src \
+ $(1); \
+ rm -rf $(1)/hostapd-$(PKG_VERSION);
+UNPACK_CMD4=mv \
+ $(1)/wpa_supplicant-$(PKG_VERSION)/wpa_supplicant \
+ $(1); \
+ rm -rf $(1)/wpa_supplicant-$(PKG_VERSION);
+
+
+PKG_UNPACK= $(SH_FUNC) \
+ $(call UNPACK_CMD1,$(PKG_BUILD_DIR)) \
+ $(call UNPACK_CMD2,$(PKG_BUILD_DIR)) \
+ $(call UNPACK_CMD3,$(PKG_BUILD_DIR)) \
+ $(call UNPACK_CMD4,$(PKG_BUILD_DIR)) \
+ $(call CRLF_CMD,$(PKG_BUILD_DIR))
+
+Hooks/Download += Download/two-parts
+
+
+DRIVER_MAKEOPTS=
+TARGET_CFLAGS += -DNO_TIMESTAMP_CHECK
+TARGET_LDFLAGS += -lrtk-inband -lcrypto -lssl
+
+
+define Package/hostapd-rtk
+ SECTION:=net
+ CATEGORY:=Network
+ TITLE:=IEEE 802.1x Authenticator for rtl8196
+ URL:=http://hostap.epitest.fi/
+ DEPENDS:=libopenssl librtk-inband
+ VARIANT:=hostapd-rtk
+endef
+
+define Package/hostapd-rtk/description
+ This package contains a full featured IEEE 802.1x/WPA/EAP/RADIUS
+ Authenticator for rtl8196.
+endef
+
+#define Package/hostapd-utils
+# $(call Package/hostapd/Default)
+# TITLE+= (utils)
+# DEPENDS:=@PACKAGE_hostapd||PACKAGE_hostapd-mini||PACKAGE_wpad||PACKAGE_wpad-mini
+#endef
+
+#define Package/hostapd-utils/description
+# This package contains a command line utility to control the
+# IEEE 802.1x/WPA/EAP/RADIUS Authenticator.
+#endef
+
+
+define Package/wpa-supplicant-rtk
+ SECTION:=net
+ CATEGORY:=Network
+ TITLE:=WPA Supplicant
+ URL:=http://hostap.epitest.fi/wpa_supplicant/
+ DEPENDS:=libopenssl librtk-inband
+ VARIANT:=wpa-supplicant-rtk
+endef
+
+define Package/wpa-supplicant-rtk/Description
+ WPA Supplicant
+endef
+
+ifneq ($(wildcard $(PKG_BUILD_DIR)/.config_*),$(subst .configured_,.config_,$(STAMP_CONFIGURED)))
+ define Build/Configure/rebuild
+ $(FIND) $(PKG_BUILD_DIR) -name \*.o -or -name \*.a | $(XARGS) rm -f
+ rm -f $(PKG_BUILD_DIR)/hostapd/hostapd
+ rm -f $(PKG_BUILD_DIR)/wpa_supplicant/wpa_supplicant
+ rm -f $(PKG_BUILD_DIR)/.config_*
+ touch $(subst .configured_,.config_,$(STAMP_CONFIGURED))
+ endef
+endif
+
+define Build/Configure
+ $(Build/Configure/rebuild)
+ $(CP) ./files/hostapd.config $(PKG_BUILD_DIR)/hostapd/.config
+ $(CP) ./files/wpa_supplicant.config $(PKG_BUILD_DIR)/wpa_supplicant/.config
+endef
+
+TARGET_CPPFLAGS := \
+ $(TARGET_CPPFLAGS) \
+ -D_GNU_SOURCE
+
+TARGET_CFLAGS += -ffunction-sections -fdata-sections
+TARGET_LDFLAGS += -Wl,--gc-sections
+
+TARGET_LDFLAGS += -lrtk-inband
+
+define Build/RunMake
+ CFLAGS="$(TARGET_CPPFLAGS) $(TARGET_CFLAGS)" \
+ $(MAKE) -C $(PKG_BUILD_DIR)/$(1) \
+ $(TARGET_CONFIGURE_OPTS) \
+ $(DRIVER_MAKEOPTS) \
+ LIBS="$(TARGET_LDFLAGS)" \
+ $(2)
+endef
+
+define Build/Compile/hostapd-rtk
+ $(call Build/RunMake,hostapd, \
+ hostapd hostapd_cli \
+ )
+endef
+
+define Build/Compile/supplicant-rtk
+ $(call Build/RunMake,wpa_supplicant, \
+ wpa_cli wpa_supplicant \
+ )
+endef
+
+define Build/Compile
+ $(Build/Compile/$(LOCAL_TYPE))
+endef
+
+define Install/hostapd-rtk
+ $(INSTALL_DIR) $(1)/lib/wifi
+ $(INSTALL_DATA) ./files/hostapd.sh $(1)/lib/wifi/hostapd.sh
+ $(INSTALL_DIR) $(1)/usr/sbin
+endef
+
+define Install/supplicant-rtk
+ $(INSTALL_DIR) $(1)/lib/wifi
+ $(INSTALL_DATA) ./files/wpa_supplicant.sh $(1)/lib/wifi/wpa_supplicant.sh
+ $(INSTALL_DIR) $(1)/usr/sbin
+endef
+
+define Package/hostapd-rtk/install
+ $(call Install/hostapd-rtk,$(1))
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/hostapd/hostapd $(1)/usr/sbin/
+endef
+
+define Package/wpa-supplicant-rtk/install
+ $(call Install/supplicant-rtk,$(1))
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/wpa_supplicant/wpa_supplicant $(1)/usr/sbin/
+endef
+
+
+$(eval $(call BuildPackage,hostapd-rtk))
+$(eval $(call BuildPackage,wpa-supplicant-rtk))
diff --git a/package/hostapd-rtk/files/hostapd.config b/package/hostapd-rtk/files/hostapd.config
new file mode 100644
index 000000000..1d3d46dd0
--- /dev/null
+++ b/package/hostapd-rtk/files/hostapd.config
@@ -0,0 +1,147 @@
+# Example hostapd build time configuration
+#
+# This file lists the configuration options that are used when building the
+# hostapd binary. All lines starting with # are ignored. Configuration option
+# lines must be commented out complete, if they are not to be included, i.e.,
+# just setting VARIABLE=n is not disabling that variable.
+#
+# This file is included in Makefile, so variables like CFLAGS and LIBS can also
+# be modified from here. In most cass, these lines should use += in order not
+# to override previous values of the variables.
+
+# Driver interface for Host AP driver
+#CONFIG_DRIVER_HOSTAP=y
+
+# Driver interface for wired authenticator
+#CONFIG_DRIVER_WIRED=y
+
+# Driver interface for madwifi driver
+#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
+
+# Driver interface for drivers using the nl80211 kernel interface
+#CONFIG_DRIVER_NL80211=y
+# driver_nl80211.c requires a rather new libnl (version 1.1) which may not be
+# shipped with your distribution yet. If that is the case, you need to build
+# newer libnl version and point the hostapd build to use it.
+#LIBNL=/usr/src/libnl
+#CFLAGS += -I$(LIBNL)/include
+#LIBS += -L$(LIBNL)/lib
+
+# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
+#CONFIG_DRIVER_BSD=y
+#CFLAGS += -I/usr/local/include
+#LIBS += -L/usr/local/lib
+
+# Driver interface for no driver (e.g., RADIUS server only)
+#CONFIG_DRIVER_NONE=y
+
+# IEEE 802.11F/IAPP
+CONFIG_IAPP=y
+
+# WPA2/IEEE 802.11i RSN pre-authentication
+CONFIG_RSN_PREAUTH=y
+
+# PeerKey handshake for Station to Station Link (IEEE 802.11e DLS)
+CONFIG_PEERKEY=y
+
+# IEEE 802.11w (management frame protection)
+# This version is an experimental implementation based on IEEE 802.11w/D1.0
+# draft and is subject to change since the standard has not yet been finalized.
+# Driver support is also needed for IEEE 802.11w.
+#CONFIG_IEEE80211W=y
+
+# Integrated EAP server
+CONFIG_EAP=y
+
+# EAP-MD5 for the integrated EAP server
+CONFIG_EAP_MD5=y
+
+# EAP-TLS for the integrated EAP server
+CONFIG_EAP_TLS=y
+
+# EAP-MSCHAPv2 for the integrated EAP server
+CONFIG_EAP_MSCHAPV2=y
+
+# EAP-PEAP for the integrated EAP server
+CONFIG_EAP_PEAP=y
+
+# EAP-GTC for the integrated EAP server
+CONFIG_EAP_GTC=y
+
+# EAP-TTLS for the integrated EAP server
+CONFIG_EAP_TTLS=y
+
+# EAP-SIM for the integrated EAP server
+#CONFIG_EAP_SIM=y
+
+# EAP-AKA for the integrated EAP server
+#CONFIG_EAP_AKA=y
+
+# EAP-AKA' for the integrated EAP server
+# This requires CONFIG_EAP_AKA to be enabled, too.
+#CONFIG_EAP_AKA_PRIME=y
+
+# EAP-PAX for the integrated EAP server
+#CONFIG_EAP_PAX=y
+
+# EAP-PSK for the integrated EAP server (this is _not_ needed for WPA-PSK)
+#CONFIG_EAP_PSK=y
+
+# EAP-SAKE for the integrated EAP server
+#CONFIG_EAP_SAKE=y
+
+# EAP-GPSK for the integrated EAP server
+#CONFIG_EAP_GPSK=y
+# Include support for optional SHA256 cipher suite in EAP-GPSK
+#CONFIG_EAP_GPSK_SHA256=y
+
+# EAP-FAST for the integrated EAP server
+# Note: Default OpenSSL package does not include support for all the
+# functionality needed for EAP-FAST. If EAP-FAST is enabled with OpenSSL,
+# the OpenSSL library must be patched (openssl-0.9.9-session-ticket.patch)
+# to add the needed functions.
+#CONFIG_EAP_FAST=y
+
+# Wi-Fi Protected Setup (WPS)
+CONFIG_WPS=y
+# Enable UPnP support for external WPS Registrars
+CONFIG_WPS_UPNP=y
+
+# EAP-IKEv2
+#CONFIG_EAP_IKEV2=y
+
+# Trusted Network Connect (EAP-TNC)
+#CONFIG_EAP_TNC=y
+
+# PKCS#12 (PFX) support (used to read private key and certificate file from
+# a file that usually has extension .p12 or .pfx)
+CONFIG_PKCS12=y
+
+# RADIUS authentication server. This provides access to the integrated EAP
+# server from external hosts using RADIUS.
+#CONFIG_RADIUS_SERVER=y
+
+# Build IPv6 support for RADIUS operations
+CONFIG_IPV6=y
+
+# IEEE Std 802.11r-2008 (Fast BSS Transition)
+#CONFIG_IEEE80211R=y
+
+# Use the hostapd's IEEE 802.11 authentication (ACL), but without
+# the IEEE 802.11 Management capability (e.g., madwifi or FreeBSD/net80211)
+#CONFIG_DRIVER_RADIUS_ACL=y
+
+# IEEE 802.11n (High Throughput) support
+CONFIG_IEEE80211N=y
+
+# Remove debugging code that is printing out debug messages to stdout.
+# This can be used to reduce the size of the hostapd considerably if debugging
+# code is not needed.
+#CONFIG_NO_STDOUT_DEBUG=y
diff --git a/package/hostapd-rtk/files/hostapd.sh b/package/hostapd-rtk/files/hostapd.sh
new file mode 100644
index 000000000..067e890c9
--- /dev/null
+++ b/package/hostapd-rtk/files/hostapd.sh
@@ -0,0 +1,278 @@
+hostapd_set_bss_options() {
+ local var="$1"
+ local vif="$2"
+ local enc wep_rekey wpa_group_rekey wpa_pair_rekey wpa_master_rekey wps_possible
+
+ config_get enc "$vif" encryption
+ config_get wep_rekey "$vif" wep_rekey # 300
+ config_get wpa_group_rekey "$vif" wpa_group_rekey # 300
+ config_get wpa_pair_rekey "$vif" wpa_pair_rekey # 300
+ config_get wpa_master_rekey "$vif" wpa_master_rekey # 640
+ config_get_bool ap_isolate "$vif" isolate 0
+
+ config_get device "$vif" device
+ config_get hwmode "$device" hwmode
+ config_get phy "$device" phy
+
+ config_get supported_rates "$device" supported_rates
+ [ -n $supported_rates ] && supported_rates="10 20 55 110 60 90 120 180 240 360 480 540"
+ append "$var" "supported_rates=$supported_rates" "$N"
+
+ config_get basic_rates "$device" basic_rates
+ [ -n $basic_rates ] && basic_rates="10 20"
+ append "$var" "basic_rates=$supported_rates" "$N"
+
+ config_get max_num_sta "$device" max_num_sta
+ [ -n $max_num_sta ] && max_num_sta="31"
+ append "$var" "max_num_sta=$max_num_sta" "$N"
+
+ append "$var" "ctrl_interface=/var/run/hostapd-$phy" "$N"
+ append "$var" "ctrl_interface=/var/run/hostapd-$phy" "$N"
+
+ append "$var" "ctrl_interface=/var/run/hostapd-$phy" "$N"
+
+ if [ "$ap_isolate" -gt 0 ]; then
+ append "$var" "ap_isolate=$ap_isolate" "$N"
+ fi
+
+ # Examples:
+ # psk-mixed/tkip => WPA1+2 PSK, TKIP
+ # wpa-psk2/tkip+aes => WPA2 PSK, CCMP+TKIP
+ # wpa2/tkip+aes => WPA2 RADIUS, CCMP+TKIP
+ # ...
+
+ # TODO: move this parsing function somewhere generic, so that
+ # later it can be reused by drivers that don't use hostapd
+
+ # crypto defaults: WPA2 vs WPA1
+ case "$enc" in
+ wpa2*|*psk2*)
+ wpa=2
+ crypto="CCMP"
+ ;;
+ *mixed*)
+ wpa=3
+ crypto="CCMP TKIP"
+ ;;
+ *)
+ wpa=1
+ crypto="TKIP"
+ ;;
+ esac
+
+ # explicit override for crypto setting
+ case "$enc" in
+ *tkip+aes|*tkip+ccmp|*aes+tkip|*ccmp+tkip) crypto="CCMP TKIP";;
+ *aes|*ccmp) crypto="CCMP";;
+ *tkip) crypto="TKIP";;
+ esac
+
+ # enforce CCMP for 11ng and 11na
+ case "$hwmode:$crypto" in
+ *ng:TKIP|*na:TKIP) crypto="CCMP TKIP";;
+ esac
+
+ # use crypto/auth settings for building the hostapd config
+ case "$enc" in
+ *psk*)
+ config_get psk "$vif" key
+ if [ ${#psk} -eq 64 ]; then
+ append "$var" "wpa_psk=$psk" "$N"
+ else
+ append "$var" "wpa_passphrase=$psk" "$N"
+ fi
+ wps_possible=1
+ [ -n "$wpa_group_rekey" ] && append "$var" "wpa_group_rekey=$wpa_group_rekey" "$N"
+ [ -n "$wpa_pair_rekey" ] && append "$var" "wpa_ptk_rekey=$wpa_pair_rekey" "$N"
+ [ -n "$wpa_master_rekey" ] && append "$var" "wpa_gmk_rekey=$wpa_master_rekey" "$N"
+ ;;
+ *wpa*)
+ # required fields? formats?
+ # hostapd is particular, maybe a default configuration for failures
+ config_get auth_server "$vif" auth_server
+ [ -z "$auth_server" ] && config_get auth_server "$vif" server
+ append "$var" "auth_server_addr=$auth_server" "$N"
+ config_get auth_port "$vif" auth_port
+ [ -z "$auth_port" ] && config_get auth_port "$vif" port
+ auth_port=${auth_port:-1812}
+ append "$var" "auth_server_port=$auth_port" "$N"
+ config_get auth_secret "$vif" auth_secret
+ [ -z "$auth_secret" ] && config_get auth_secret "$vif" key
+ append "$var" "auth_server_shared_secret=$auth_secret" "$N"
+ config_get acct_server "$vif" acct_server
+ [ -n "$acct_server" ] && append "$var" "acct_server_addr=$acct_server" "$N"
+ config_get acct_port "$vif" acct_port
+ [ -n "$acct_port" ] && acct_port=${acct_port:-1813}
+ [ -n "$acct_port" ] && append "$var" "acct_server_port=$acct_port" "$N"
+ config_get acct_secret "$vif" acct_secret
+ [ -n "$acct_secret" ] && append "$var" "acct_server_shared_secret=$acct_secret" "$N"
+ config_get nasid "$vif" nasid
+ append "$var" "nas_identifier=$nasid" "$N"
+ append "$var" "eapol_key_index_workaround=1" "$N"
+ append "$var" "ieee8021x=1" "$N"
+ append "$var" "wpa_key_mgmt=WPA-EAP" "$N"
+ [ -n "$wpa_group_rekey" ] && append "$var" "wpa_group_rekey=$wpa_group_rekey" "$N"
+ [ -n "$wpa_pair_rekey" ] && append "$var" "wpa_ptk_rekey=$wpa_pair_rekey" "$N"
+ [ -n "$wpa_master_rekey" ] && append "$var" "wpa_gmk_rekey=$wpa_master_rekey" "$N"
+ ;;
+ *wep*)
+ config_get key "$vif" key
+ key="${key:-1}"
+ case "$key" in
+ [1234])
+ for idx in 1 2 3 4; do
+ local zidx
+ zidx=$(($idx - 1))
+ config_get ckey "$vif" "key${idx}"
+ [ -n "$ckey" ] && \
+ append "$var" "wep_key${zidx}=$(prepare_key_wep "$ckey")" "$N"
+ done
+ append "$var" "wep_default_key=$((key - 1))" "$N"
+ ;;
+ *)
+ append "$var" "wep_key0=$(prepare_key_wep "$key")" "$N"
+ append "$var" "wep_default_key=0" "$N"
+ [ -n "$wep_rekey" ] && append "$var" "wep_rekey_period=$wep_rekey" "$N"
+ ;;
+ esac
+ case "$enc" in
+ *shared*)
+ auth_algs=2
+ ;;
+ *mixed*)
+ auth_algs=3
+ ;;
+ esac
+ wpa=0
+ crypto=
+ ;;
+ *)
+ wpa=0
+ crypto=
+ ;;
+ esac
+ append "$var" "auth_algs=${auth_algs:-1}" "$N"
+ append "$var" "wpa=$wpa" "$N"
+ [ -n "$crypto" ] && append "$var" "wpa_pairwise=$crypto" "$N"
+ [ -n "$wpa_group_rekey" ] && append "$var" "wpa_group_rekey=$wpa_group_rekey" "$N"
+
+ config_get ssid "$vif" ssid
+ config_get bridge "$vif" bridge
+ config_get ieee80211d "$vif" ieee80211d
+ config_get iapp_interface "$vif" iapp_interface
+
+ config_get_bool wps_pbc "$vif" wps_pushbutton 0
+ config_get_bool wps_label "$vif" wps_label 0
+
+ config_get config_methods "$vif" wps_config
+ [ "$wps_pbc" -gt 0 ] && append config_methods push_button
+
+ [ -n "$wps_possible" -a -n "$config_methods" ] && {
+ config_get device_type "$vif" wps_device_type "6-0050F204-1"
+ config_get device_name "$vif" wps_device_name "OpenWrt AP"
+ config_get manufacturer "$vif" wps_manufacturer "openwrt.org"
+
+ append "$var" "eap_server=1" "$N"
+ append "$var" "wps_state=2" "$N"
+ append "$var" "ap_setup_locked=1" "$N"
+ append "$var" "device_type=$device_type" "$N"
+ append "$var" "device_name=$device_name" "$N"
+ append "$var" "manufacturer=$manufacturer" "$N"
+ append "$var" "config_methods=$config_methods" "$N"
+ }
+
+ append "$var" "ssid=$ssid" "$N"
+ [ -n "$bridge" ] && append "$var" "bridge=$bridge" "$N"
+ [ -n "$ieee80211d" ] && append "$var" "ieee80211d=$ieee80211d" "$N"
+ [ -n "$iapp_interface" ] && append "$var" iapp_interface=$(uci_get_state network "$iapp_interface" ifname "$iapp_interface") "$N"
+
+ if [ "$wpa" -ge "2" ]
+ then
+ # RSN -> allow preauthentication
+ config_get rsn_preauth "$vif" rsn_preauth
+ if [ -n "$bridge" -a "$rsn_preauth" = 1 ]
+ then
+ append "$var" "rsn_preauth=1" "$N"
+ append "$var" "rsn_preauth_interfaces=$bridge" "$N"
+ fi
+
+ # RSN -> allow management frame protection
+ config_get ieee80211w "$vif" ieee80211w
+ case "$ieee80211w" in
+ [012])
+ append "$var" "ieee80211w=$ieee80211w" "$N"
+ [ "$ieee80211w" -gt "0" ] && {
+ config_get ieee80211w_max_timeout "$vif" ieee80211w_max_timeout
+ config_get ieee80211w_retry_timeout "$vif" ieee80211w_retry_timeout
+ [ -n "$ieee80211w_max_timeout" ] && \
+ append "$var" "assoc_sa_query_max_timeout=$ieee80211w_max_timeout" "$N"
+ [ -n "$ieee80211w_retry_timeout" ] && \
+ append "$var" "assoc_sa_query_retry_timeout=$ieee80211w_retry_timeout" "$N"
+ }
+ ;;
+ esac
+ fi
+}
+
+hostapd_set_log_options() {
+ local var="$1"
+ local cfg="$2"
+ local log_level log_80211 log_8021x log_radius log_wpa log_driver log_iapp log_mlme
+
+ config_get log_level "$cfg" log_level 2
+
+ config_get_bool log_80211 "$cfg" log_80211 1
+ config_get_bool log_8021x "$cfg" log_8021x 1
+ config_get_bool log_radius "$cfg" log_radius 1
+ config_get_bool log_wpa "$cfg" log_wpa 1
+ config_get_bool log_driver "$cfg" log_driver 1
+ config_get_bool log_iapp "$cfg" log_iapp 1
+ config_get_bool log_mlme "$cfg" log_mlme 1
+
+ local log_mask=$(( \
+ ($log_80211 << 0) | \
+ ($log_8021x << 1) | \
+ ($log_radius << 2) | \
+ ($log_wpa << 3) | \
+ ($log_driver << 4) | \
+ ($log_iapp << 5) | \
+ ($log_mlme << 6) \
+ ))
+
+ append "$var" "logger_syslog=$log_mask" "$N"
+ append "$var" "logger_syslog_level=$log_level" "$N"
+ append "$var" "logger_stdout=$log_mask" "$N"
+ append "$var" "logger_stdout_level=$log_level" "$N"
+}
+
+hostapd_setup_vif() {
+ local vif="$1"
+ local driver="$2"
+ local ifname device channel hwmode
+
+ hostapd_cfg=
+
+ config_get ifname "$vif" ifname
+ config_get device "$vif" device
+ config_get channel "$device" channel
+ config_get hwmode "$device" hwmode
+
+ hostapd_set_log_options hostapd_cfg "$device"
+ hostapd_set_bss_options hostapd_cfg "$vif"
+
+ case "$hwmode" in
+ *bg|*gdt|*gst|*fh) hwmode=g;;
+ *adt|*ast) hwmode=a;;
+ esac
+ [ "$channel" = auto ] && channel=
+ [ -n "$channel" -a -z "$hwmode" ] && wifi_fixup_hwmode "$device"
+ cat > /var/run/hostapd-$ifname.conf <<EOF
+driver=$driver
+interface=$ifname
+${hwmode:+hw_mode=${hwmode#11}}
+${channel:+channel=$channel}
+$hostapd_cfg
+EOF
+ hostapd -P /var/run/wifi-$ifname.pid -B /var/run/hostapd-$ifname.conf
+}
+
diff --git a/package/hostapd-rtk/files/wpa_supplicant.config b/package/hostapd-rtk/files/wpa_supplicant.config
new file mode 100644
index 000000000..1d3d46dd0
--- /dev/null
+++ b/package/hostapd-rtk/files/wpa_supplicant.config
@@ -0,0 +1,147 @@
+# Example hostapd build time configuration
+#
+# This file lists the configuration options that are used when building the
+# hostapd binary. All lines starting with # are ignored. Configuration option
+# lines must be commented out complete, if they are not to be included, i.e.,
+# just setting VARIABLE=n is not disabling that variable.
+#
+# This file is included in Makefile, so variables like CFLAGS and LIBS can also
+# be modified from here. In most cass, these lines should use += in order not
+# to override previous values of the variables.
+
+# Driver interface for Host AP driver
+#CONFIG_DRIVER_HOSTAP=y
+
+# Driver interface for wired authenticator
+#CONFIG_DRIVER_WIRED=y
+
+# Driver interface for madwifi driver
+#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
+
+# Driver interface for drivers using the nl80211 kernel interface
+#CONFIG_DRIVER_NL80211=y
+# driver_nl80211.c requires a rather new libnl (version 1.1) which may not be
+# shipped with your distribution yet. If that is the case, you need to build
+# newer libnl version and point the hostapd build to use it.
+#LIBNL=/usr/src/libnl
+#CFLAGS += -I$(LIBNL)/include
+#LIBS += -L$(LIBNL)/lib
+
+# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
+#CONFIG_DRIVER_BSD=y
+#CFLAGS += -I/usr/local/include
+#LIBS += -L/usr/local/lib
+
+# Driver interface for no driver (e.g., RADIUS server only)
+#CONFIG_DRIVER_NONE=y
+
+# IEEE 802.11F/IAPP
+CONFIG_IAPP=y
+
+# WPA2/IEEE 802.11i RSN pre-authentication
+CONFIG_RSN_PREAUTH=y
+
+# PeerKey handshake for Station to Station Link (IEEE 802.11e DLS)
+CONFIG_PEERKEY=y
+
+# IEEE 802.11w (management frame protection)
+# This version is an experimental implementation based on IEEE 802.11w/D1.0
+# draft and is subject to change since the standard has not yet been finalized.
+# Driver support is also needed for IEEE 802.11w.
+#CONFIG_IEEE80211W=y
+
+# Integrated EAP server
+CONFIG_EAP=y
+
+# EAP-MD5 for the integrated EAP server
+CONFIG_EAP_MD5=y
+
+# EAP-TLS for the integrated EAP server
+CONFIG_EAP_TLS=y
+
+# EAP-MSCHAPv2 for the integrated EAP server
+CONFIG_EAP_MSCHAPV2=y
+
+# EAP-PEAP for the integrated EAP server
+CONFIG_EAP_PEAP=y
+
+# EAP-GTC for the integrated EAP server
+CONFIG_EAP_GTC=y
+
+# EAP-TTLS for the integrated EAP server
+CONFIG_EAP_TTLS=y
+
+# EAP-SIM for the integrated EAP server
+#CONFIG_EAP_SIM=y
+
+# EAP-AKA for the integrated EAP server
+#CONFIG_EAP_AKA=y
+
+# EAP-AKA' for the integrated EAP server
+# This requires CONFIG_EAP_AKA to be enabled, too.
+#CONFIG_EAP_AKA_PRIME=y
+
+# EAP-PAX for the integrated EAP server
+#CONFIG_EAP_PAX=y
+
+# EAP-PSK for the integrated EAP server (this is _not_ needed for WPA-PSK)
+#CONFIG_EAP_PSK=y
+
+# EAP-SAKE for the integrated EAP server
+#CONFIG_EAP_SAKE=y
+
+# EAP-GPSK for the integrated EAP server
+#CONFIG_EAP_GPSK=y
+# Include support for optional SHA256 cipher suite in EAP-GPSK
+#CONFIG_EAP_GPSK_SHA256=y
+
+# EAP-FAST for the integrated EAP server
+# Note: Default OpenSSL package does not include support for all the
+# functionality needed for EAP-FAST. If EAP-FAST is enabled with OpenSSL,
+# the OpenSSL library must be patched (openssl-0.9.9-session-ticket.patch)
+# to add the needed functions.
+#CONFIG_EAP_FAST=y
+
+# Wi-Fi Protected Setup (WPS)
+CONFIG_WPS=y
+# Enable UPnP support for external WPS Registrars
+CONFIG_WPS_UPNP=y
+
+# EAP-IKEv2
+#CONFIG_EAP_IKEV2=y
+
+# Trusted Network Connect (EAP-TNC)
+#CONFIG_EAP_TNC=y
+
+# PKCS#12 (PFX) support (used to read private key and certificate file from
+# a file that usually has extension .p12 or .pfx)
+CONFIG_PKCS12=y
+
+# RADIUS authentication server. This provides access to the integrated EAP
+# server from external hosts using RADIUS.
+#CONFIG_RADIUS_SERVER=y
+
+# Build IPv6 support for RADIUS operations
+CONFIG_IPV6=y
+
+# IEEE Std 802.11r-2008 (Fast BSS Transition)
+#CONFIG_IEEE80211R=y
+
+# Use the hostapd's IEEE 802.11 authentication (ACL), but without
+# the IEEE 802.11 Management capability (e.g., madwifi or FreeBSD/net80211)
+#CONFIG_DRIVER_RADIUS_ACL=y
+
+# IEEE 802.11n (High Throughput) support
+CONFIG_IEEE80211N=y
+
+# Remove debugging code that is printing out debug messages to stdout.
+# This can be used to reduce the size of the hostapd considerably if debugging
+# code is not needed.
+#CONFIG_NO_STDOUT_DEBUG=y
diff --git a/package/hostapd-rtk/files/wpa_supplicant.sh b/package/hostapd-rtk/files/wpa_supplicant.sh
new file mode 100644
index 000000000..1ab6c663e
--- /dev/null
+++ b/package/hostapd-rtk/files/wpa_supplicant.sh
@@ -0,0 +1,149 @@
+wpa_supplicant_setup_vif() {
+ local vif="$1"
+ local driver="$2"
+ local key="$key"
+ local options="$3"
+
+ # wpa_supplicant should use wext for mac80211 cards
+ [ "$driver" = "mac80211" ] && driver='wext'
+
+ # make sure we have the encryption type and the psk
+ [ -n "$enc" ] || {
+ config_get enc "$vif" encryption
+ }
+ [ -n "$key" ] || {
+ config_get key "$vif" key
+ }
+
+ local net_cfg bridge
+ config_get bridge "$vif" bridge
+ [ -z "$bridge" ] && {
+ net_cfg="$(find_net_config "$vif")"
+ [ -z "$net_cfg" ] || bridge="$(bridge_interface "$net_cfg")"
+ config_set "$vif" bridge "$bridge"
+ }
+
+ local mode ifname wds
+ config_get mode "$vif" mode
+ config_get ifname "$vif" ifname
+ config_get_bool wds "$vif" wds 0
+ [ -z "$bridge" ] || [ "$mode" = ap ] || [ "$mode" = sta -a $wds -eq 1 ] || {
+ echo "wpa_supplicant_setup_vif($ifname): Refusing to bridge $mode mode interface"
+ return 1
+ }
+
+ case "$enc" in
+ *none*)
+ key_mgmt='NONE'
+ ;;
+ *wep*)
+ key_mgmt='NONE'
+ config_get key "$vif" key
+ key="${key:-1}"
+ case "$key" in
+ [1234])
+ for idx in 1 2 3 4; do
+ local zidx
+ zidx=$(($idx - 1))
+ config_get ckey "$vif" "key${idx}"
+ [ -n "$ckey" ] && \
+ append "wep_key${zidx}" "wep_key${zidx}=$(prepare_key_wep "$ckey")"
+ done
+ wep_tx_keyidx="wep_tx_keyidx=$((key - 1))"
+ ;;
+ *)
+ wep_key0="wep_key0=$(prepare_key_wep "$key")"
+ wep_tx_keyidx="wep_tx_keyidx=0"
+ ;;
+ esac
+ ;;
+ *psk*)
+ key_mgmt='WPA-PSK'
+ config_get_bool usepassphrase "$vif" passphrase 1
+ if [ "$usepassphrase" = "1" ]; then
+ passphrase="psk=\"${key}\""
+ else
+ passphrase="psk=${key}"
+ fi
+ case "$enc" in
+ *psk2*)
+ proto='proto=RSN'
+ config_get ieee80211w "$vif" ieee80211w
+ ;;
+ *psk*)
+ proto='proto=WPA'
+ ;;
+ esac
+ ;;
+ *wpa*|*8021x*)
+ proto='proto=WPA2'
+ key_mgmt='WPA-EAP'
+ config_get ieee80211w "$vif" ieee80211w
+ config_get ca_cert "$vif" ca_cert
+ config_get eap_type "$vif" eap_type
+ ca_cert=${ca_cert:+"ca_cert=\"$ca_cert\""}
+ case "$eap_type" in
+ tls)
+ pairwise='pairwise=CCMP'
+ group='group=CCMP'
+ config_get identity "$vif" identity
+ config_get priv_key "$vif" priv_key
+ config_get priv_key_pwd "$vif" priv_key_pwd
+ identity="identity=\"$identity\""
+ priv_key="private_key=\"$priv_key\""
+ priv_key_pwd="private_key_passwd=\"$priv_key_pwd\""
+ ;;
+ peap|ttls)
+ config_get auth "$vif" auth
+ config_get identity "$vif" identity
+ config_get password "$vif" password
+ phase2="phase2=\"auth=${auth:-MSCHAPV2}\""
+ identity="identity=\"$identity\""
+ password="password=\"$password\""
+ ;;
+ esac
+ eap_type="eap=$(echo $eap_type | tr 'a-z' 'A-Z')"
+ ;;
+ esac
+
+ case "$ieee80211w" in
+ [012])
+ ieee80211w="ieee80211w=$ieee80211w"
+ ;;
+ esac
+
+ config_get ifname "$vif" ifname
+ config_get bridge "$vif" bridge
+ config_get ssid "$vif" ssid
+ config_get bssid "$vif" bssid
+ bssid=${bssid:+"bssid=$bssid"}
+ rm -rf /var/run/wpa_supplicant-$ifname
+ cat > /var/run/wpa_supplicant-$ifname.conf <<EOF
+ctrl_interface=/var/run/wpa_supplicant-$ifname
+network={
+ scan_ssid=1
+ ssid="$ssid"
+ $bssid
+ key_mgmt=$key_mgmt
+ $proto
+ $ieee80211w
+ $passphrase
+ $pairwise
+ $group
+ $eap_type
+ $ca_cert
+ $priv_key
+ $priv_key_pwd
+ $phase2
+ $identity
+ $password
+ $wep_key0
+ $wep_key1
+ $wep_key2
+ $wep_key3
+ $wep_tx_keyidx
+}
+EOF
+ [ -z "$proto" -a "$key_mgmt" != "NONE" ] || \
+ wpa_supplicant ${bridge:+ -b $bridge} -B -P "/var/run/wifi-${ifname}.pid" -D ${driver:-wext} -i "$ifname" -c /var/run/wpa_supplicant-$ifname.conf $options
+}
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
diff --git a/package/librtk-inband/Makefile b/package/librtk-inband/Makefile
new file mode 100644
index 000000000..1ed6c8d53
--- /dev/null
+++ b/package/librtk-inband/Makefile
@@ -0,0 +1,54 @@
+#
+# Copyright (C) 2006-2009 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=librtk-inband
+PKG_VERSION:=0.1
+PKG_RELEASE:=2
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/librtk-inband
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=realtek wireless device in-band configuration library
+endef
+
+define Package/librtk-inband/description
+ realtek wireless device in-band configuration library
+endef
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+TARGET_CFLAGS += $(FPIC)
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ $(TARGET_CONFIGURE_OPTS) \
+ CFLAGS="$(TARGET_CFLAGS)" \
+ all
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/lib/pkgconfig $(1)/usr/include/
+ $(INSTALL_DIR) $(1)/usr/lib/pkgconfig $(1)/usr/include/librtk-inband
+ $(CP) $(PKG_BUILD_DIR)/include/* $(1)/usr/include/
+ $(CP) $(PKG_BUILD_DIR)/ioh.h $(1)/usr/include/librtk-inband
+ $(CP) $(PKG_BUILD_DIR)/librtk-inband.so $(1)/usr/lib/
+ $(CP) ./files/librtk-inband.pc $(1)/usr/lib/pkgconfig
+endef
+
+define Package/librtk-inband/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_BUILD_DIR)/librtk-inband.so $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,librtk-inband))
diff --git a/package/librtk-inband/files/librtk-inband.pc b/package/librtk-inband/files/librtk-inband.pc
new file mode 100644
index 000000000..eb20fdb94
--- /dev/null
+++ b/package/librtk-inband/files/librtk-inband.pc
@@ -0,0 +1,10 @@
+prefix=/usr
+exec_prefix=/usr
+libdir=${exec_prefix}/lib
+includedir=${prefix}/include/librtk-inband
+
+Name: librtk-inband
+Description: library for inband configuration of realtek wireless devices
+Version: 1.0
+Libs: -L${libdir} -lrtk-inband
+Cflags:
diff --git a/package/librtk-inband/src/Makefile b/package/librtk-inband/src/Makefile
new file mode 100644
index 000000000..fa0cb9a71
--- /dev/null
+++ b/package/librtk-inband/src/Makefile
@@ -0,0 +1,21 @@
+INCLUDES=-Iinclude
+
+LIBNAME=librtk-inband.so
+APPNAME=rtk-inband
+
+all: $(LIBNAME) $(APPNAME)
+
+%.o: %.c
+ $(CC) -c -o $@ $(INCLUDES) $(CFLAGS) $<
+
+OBJ=inband_if.o ioh.o
+
+LIB_OBJ=hapd_api.o $(OBJ)
+APP_OBJ=inband_cmd.o $(OBJ)
+
+
+$(APPNAME):$(APP_OBJ)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
+
+$(LIBNAME): $(LIB_OBJ)
+ $(CC) $(CFLAGS) -shared -o $@ $^
diff --git a/package/librtk-inband/src/hapd_api.c b/package/librtk-inband/src/hapd_api.c
new file mode 100644
index 000000000..252a7b467
--- /dev/null
+++ b/package/librtk-inband/src/hapd_api.c
@@ -0,0 +1,447 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+#include <linux/if_ether.h>
+#include <linux/if_packet.h>
+#ifndef __IOH_H
+#include "ioh.h"
+#endif
+#include <linux/if_arp.h>
+#include "wireless_copy.h"
+#include <net80211/ieee80211.h>
+#include <net80211/ieee80211_crypto.h>
+#include <net80211/ieee80211_ioctl.h>
+
+#define INBAND_INTF "wlan0"
+#define INBAND_SLAVE ("001234567899")
+#define INBAND_IOCTL_TYPE 0x8899
+#define INBAND_NETLINK_TYPE 0x9000
+#define INBAND_DEBUG 0
+#define RX_EXPIRE_PERIOD 3 //in secs
+
+#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)
+
+#ifdef IEEE80211_IOCTL_SETWMMPARAMS
+/* Assume this is built against realtek-ng */
+#define REALTEK_NG
+#endif /* IEEE80211_IOCTL_SETWMMPARAMS */
+//#define RTL8192CD_IOCTL_DEL_STA 0x89f7
+//#define SIOCGIWIND 0x89ff
+//#defein SIOCIWLASTPRIV 0x8BFF
+
+unsigned int get_random(int max)
+{
+ struct timeval tod;
+
+ gettimeofday(&tod , NULL);
+ srand(tod.tv_usec);
+ return rand()%max;
+}
+
+static int rx_expired(struct timeval *start)
+{
+ struct timeval now;
+
+ gettimeofday(&now , NULL);
+
+ return (now.tv_sec-start->tv_sec<RX_EXPIRE_PERIOD)?0:1;
+}
+
+/****************************************************
+
+ tx_data will be formatted as following:
+ +--------------+------------+--------------+--------------+
+ | ioctl number | req length | struct iwreq | pending data |
+ +--------------+------------+--------------+--------------+
+
+
+ ****************************************************/
+int
+inband_ioctl(int ioctl_op, void *req)
+{
+ int ret=-1, ext_len=0, sq=0, rcv_sq=0, inband_channel=-1, iw=0;
+ unsigned char cmd_type=0x01, buf[BUF_SIZE], *rx_buf;
+ struct iwreq *local_iwr;
+ struct timeval start;
+ int ioctl_op_endian;
+ int local_iwr_pointer;
+ struct ifreq *ifr_ptr;
+#ifdef WPAS_INB
+ char* data_set_ptr;
+ int data_set_len = 0;
+ char* data_get_ptr;
+ int data_get_len = 0;
+
+ int rx_retry_cnt = 0;
+ int tx_retry_cnt = 0;
+#endif
+
+/*_Eric WPAS_INB ========
+
+[iw]
+Byte(0): 0, u.name
+ 1, u.data.pointer
+ 2, u."Others" - get
+ 3, u."Others" - set
+Byte(1): 0, ifreq
+ 1, iwreq
+
+=====================*/
+
+ switch(ioctl_op) {
+
+ case IEEE80211_IOCTL_FILTERFRAME:
+ case IEEE80211_IOCTL_SETPARAM:
+ case IEEE80211_IOCTL_DELKEY:
+ iw = 0x10;
+ break;
+ case IEEE80211_IOCTL_SETMLME:
+ case IEEE80211_IOCTL_SETKEY:
+ //printf("~~~%s %d\n",__FUNCTION__,__LINE__);
+ //hex_dump(((struct iwreq *)req)->u.data.pointer,((struct iwreq *)req)->u.data.length);
+#ifdef REALTEK_NG
+ case IEEE80211_IOCTL_STA_STATS:
+#else
+ case IEEE80211_IOCTL_GETSTASTATS:
+#endif
+ case IEEE80211_IOCTL_SET_APPIEBUF:
+ //WPAS_INB case SIOCGIWRANGE:
+ //WPAS_INB case SIOCSIWESSID:
+ //WPAS_INB case SIOCGIWESSID:
+ case SIOCSIWENCODE:
+ case IEEE80211_IOCTL_WDSADDMAC:
+ case IEEE80211_IOCTL_WDSDELMAC:
+ case IEEE80211_IOCTL_GET_APPIEBUF:
+ case 0x89f7: //RTL8192CD_IOCTL_DEL_STA
+ case 0x89ff: //SIOCGIWIND
+ case 0x8bff: //SIOCIWLASTPRIV
+#ifdef WPAS_INB
+ case IEEE80211_IOCTL_SETOPTIE://0x8bee
+#endif
+ iw = 0x11;
+ break;
+ case SIOCGIFINDEX:
+ case SIOCGIFFLAGS:
+ case SIOCGIFHWADDR:
+ iw = 0x0;
+ break;
+ case SIOCSIFHWADDR:
+ ifr_ptr = (struct ifreq *)req;
+ ifr_ptr->ifr_hwaddr.sa_family = htons(ifr_ptr->ifr_hwaddr.sa_family);
+ iw = 0x0;
+ break;
+ case SIOCSIFFLAGS:
+ ifr_ptr = (struct ifreq *)req;
+ ifr_ptr->ifr_flags = htons(ifr_ptr->ifr_flags);
+ iw = 0x0;
+ break;
+ case SIOCSIFMTU:
+ ifr_ptr = (struct ifreq *)req;
+ ifr_ptr->ifr_mtu = htonl(ifr_ptr->ifr_mtu);
+ iw = 0x0;
+ break;
+#ifdef WPAS_INB
+ case SIOCSIWSCAN:
+ iw = 0x10;
+ break;
+
+ case SIOCGIWAP:
+ case SIOCGIWESSID:
+ case SIOCGIWSCAN:
+ case SIOCGIWRANGE:
+ case SIOCGIWMODE:
+ iw = 0x12;
+ break;
+
+ case SIOCSIWAP:
+ case SIOCSIWESSID:
+ case SIOCSIWMODE:
+ iw = 0x13;
+ break;
+#endif
+ default:
+ printf("Unknown ioctl number:%d\n",ioctl_op);
+ return -1;
+ }
+
+ inband_channel = inband_open(INBAND_INTF, INBAND_SLAVE, INBAND_IOCTL_TYPE, INBAND_DEBUG);
+ if( inband_channel < 0 ) {
+ printf("ioctl(inband channel open) failed \n");
+ goto out;
+ }
+
+ ioctl_op_endian = htonl(ioctl_op);//mark_endian
+ memset(buf,0,BUF_SIZE);
+ memcpy(buf,(unsigned char *)&ioctl_op_endian,INBAND_IOCTLTYPE_LEN);
+#ifdef WPAS_INB
+ if( (iw & 0x1) && ((iw != 0x13) && (iw != 0x12)) )
+#else
+ if( iw & 0x1 )
+#endif
+ {
+ local_iwr = (struct iwreq *)req;
+ ext_len = local_iwr->u.data.length;
+ local_iwr_pointer = (int)local_iwr->u.data.pointer;
+ local_iwr->u.data.length = htons(ext_len);
+ local_iwr->u.data.flags = htons(local_iwr->u.data.flags);
+ //memcpy(INBAND_PENDING_START(buf),local_iwr->u.data.pointer, local_iwr->u.data.length);
+ memcpy(INBAND_PENDING_START(buf),local_iwr->u.data.pointer, ext_len);
+ }
+
+#ifdef WPAS_INB
+ if( iw == 0x12 ) {
+
+ local_iwr = (struct iwreq *)req;
+
+ if(ioctl_op == SIOCGIWAP)
+ {
+ ;
+ }
+ else if(ioctl_op == SIOCGIWESSID)
+ {
+ local_iwr = (struct iwreq *)req;
+ local_iwr->u.essid.flags = htons(local_iwr->u.essid.flags);
+ local_iwr->u.essid.length = htons(local_iwr->u.essid.length);
+ }
+ else if(ioctl_op == SIOCGIWSCAN)
+ {
+ local_iwr = (struct iwreq *)req;
+ local_iwr->u.data.length = htons(local_iwr->u.data.length);
+ local_iwr->u.data.flags = htons(local_iwr->u.data.flags);
+ ext_len = 0;
+ }
+ else if(ioctl_op == SIOCGIWRANGE)
+ {
+ local_iwr = (struct iwreq *)req;
+ local_iwr->u.data.length = htons(local_iwr->u.data.length);
+ local_iwr->u.data.flags = htons(local_iwr->u.data.flags);
+ ext_len = 0;
+ }
+ else if(ioctl_op == SIOCGIWMODE)
+ {
+ ;
+ }
+
+ }
+
+ if( iw == 0x13 ) {
+
+ local_iwr = (struct iwreq *)req;
+ data_set_len = 0;
+
+ if(ioctl_op == SIOCSIWAP)
+ {
+ data_set_len = ETH_ALEN;
+ data_set_ptr = (char *)local_iwr->u.ap_addr.sa_data;
+ }
+ else if(ioctl_op == SIOCSIWESSID)
+ {
+ data_set_len = local_iwr->u.essid.length;
+ data_set_ptr = (char*)local_iwr->u.essid.pointer;
+ local_iwr->u.essid.length = htons(local_iwr->u.essid.length);
+ }
+ else if(ioctl_op == SIOCSIWMODE)
+ {
+ local_iwr->u.mode = htonl(local_iwr->u.mode);
+ }
+
+
+ memcpy(INBAND_PENDING_START(buf), data_set_ptr, data_set_len);
+ ext_len = data_set_len;
+
+ }
+#endif
+
+
+ memcpy(buf+INBAND_IOCTLHDR_LEN,(unsigned char *)req,IWREQ_LEN);
+
+
+#ifdef WPAS_INB
+ if(iw >= 0x10)
+ buf[INBAND_IOCTLTYPE_LEN] = 0x1;
+ else
+ buf[INBAND_IOCTLTYPE_LEN] = 0x0;
+
+ buf[INBAND_IOCTLTYPE_LEN+1] = iw&0x3;
+#else
+ buf[INBAND_IOCTLTYPE_LEN] = iw&0x10>>4;
+ buf[INBAND_IOCTLTYPE_LEN+1] = iw&0x1;
+#endif
+
+
+ sq = get_random(65536);
+
+#ifdef WPAS_INB
+ tx_retry_cnt = 0;
+
+tx_retry:
+
+ rx_retry_cnt = 0;
+ tx_retry_cnt ++;
+
+ if(tx_retry_cnt > 3)
+ {
+ printf("CAN NOT RECEIVE INBAND RESPONSE !!!! EXIT ~~~ \n");
+ ret = -1;
+ goto out;
+ }
+#endif
+
+ //printf("inband ioctl %d %d >>> \n", sq, ext_len);
+
+
+ if( inband_write(inband_channel, sq, cmd_type, buf, INBAND_IOCTLHDR_LEN+IWREQ_LEN+ext_len, 0) < 0) {
+ printf("inband ioctl message send failed\n");
+ goto out;
+ }
+ else {
+ gettimeofday(&start,NULL);
+rx_retry:
+
+ //_Eric timeout shall set ??
+ if( inband_rcv_data_and_seq(inband_channel, &rcv_sq, &cmd_type, &rx_buf, 500000) < 0 && !rx_expired(&start) ) {
+ printf("inband ioctl message not receive response\n");
+
+#ifdef WPAS_INB
+ rx_retry_cnt ++;
+
+ if(rx_retry_cnt >= 3)
+ goto tx_retry;
+
+ sleep(1);
+ goto rx_retry;
+#else
+ ret = -1;
+ goto out;
+#endif
+ }
+ //printf(" >>> inband ioctl %d \n",rcv_sq);
+
+
+#ifdef WPAS_INB
+ if( sq != rcv_sq )
+ goto tx_retry;
+#else
+ if( sq != rcv_sq )
+ goto rx_retry;
+#endif
+
+
+ ret = *(int *)rx_buf;
+
+#ifdef WPAS_INB
+ ret = ntohl(ret);
+#endif
+
+
+#ifdef WPAS_INB
+ if(iw != 0x12)
+#endif
+ memcpy((unsigned char *)req,rx_buf+INBAND_IOCTLHDR_LEN,IWREQ_LEN);
+
+#ifdef WPAS_INB
+ if( (iw & 0x1) && (iw != 0x12) && (iw != 0x13))
+#else
+ if( iw & 0x1 )
+#endif
+ {
+ local_iwr = (struct iwreq *)req;
+ memcpy((int *)local_iwr_pointer, INBAND_PENDING_START(rx_buf), ext_len);
+ local_iwr->u.data.length = ext_len;
+ local_iwr->u.data.pointer = (int *)local_iwr_pointer;
+ local_iwr->u.data.flags = ntohs(local_iwr->u.data.flags);
+ }
+ else if (iw == 0x0) //ifreq ;
+ {
+ switch(ioctl_op) {
+ case SIOCGIFINDEX:
+ ifr_ptr = (struct ifreq *)req;
+ ifr_ptr->ifr_ifindex = ntohl(ifr_ptr->ifr_ifindex);
+ break;
+ case SIOCGIFFLAGS:
+ ifr_ptr = (struct ifreq *)req;
+ ifr_ptr->ifr_flags = ntohs(ifr_ptr->ifr_flags);
+ break;
+ //case SIOCGIFHWADDR:
+ default:
+ break;
+ }
+
+ }
+
+
+#ifdef WPAS_INB
+ if(iw == 0x12)
+ {
+ memcpy(&data_get_len, (rx_buf + INBAND_IOCTLHDR_LEN + IWREQ_LEN + ext_len), 4);
+ data_get_len = ntohl(data_get_len);
+ data_get_ptr = (char *)(rx_buf + INBAND_IOCTLHDR_LEN + IWREQ_LEN + ext_len + 4);
+
+ switch(ioctl_op){
+ case SIOCGIWAP:
+ local_iwr = (struct iwreq *)req;
+ memcpy(local_iwr->u.ap_addr.sa_data, data_get_ptr, data_get_len);
+ break;
+ case SIOCGIWESSID:
+ local_iwr = (struct iwreq *)req;
+ local_iwr->u.essid.length = data_get_len;
+ memcpy(local_iwr->u.essid.pointer, data_get_ptr, data_get_len);
+ break;
+ case SIOCGIWSCAN:
+ local_iwr = (struct iwreq *)req;
+ local_iwr->u.data.length = data_get_len;
+ memcpy(local_iwr->u.data.pointer, data_get_ptr, data_get_len);
+ break;
+ case SIOCGIWRANGE:
+ local_iwr = (struct iwreq *)req;
+ local_iwr->u.data.length = data_get_len;
+ memcpy(local_iwr->u.data.pointer, data_get_ptr, data_get_len);
+ break;
+ case SIOCGIWMODE:
+ local_iwr = (struct iwreq *)req;
+ local_iwr->u.mode = ntohl(local_iwr->u.mode);
+ break;
+ default:
+ break;
+ }
+ }
+
+#endif
+
+ }
+out:
+ if( inband_channel >= 0 )
+ inband_close(inband_channel);
+
+ return ret;
+}
+
+
+int
+inband_remote_cmd(unsigned char *cmd)
+{
+ unsigned char cmd_type=0x02, *buf;
+ unsigned int channel = -1;
+
+ channel = inband_open(INBAND_INTF,INBAND_SLAVE,INBAND_IOCTL_TYPE,0);
+ if( channel < 0 || inband_write(channel, get_random(65535), cmd_type, cmd, strlen(cmd), 0) < 0) {
+ printf("inband sent remote command failed\n");
+ } else {
+ if( inband_rcv_data(channel, &cmd_type, &buf, -1) < 0 )
+ printf("inband try to receive respone but failed\n");
+ inband_close(channel);
+ }
+}
+
+
+
diff --git a/package/librtk-inband/src/inband_cmd.c b/package/librtk-inband/src/inband_cmd.c
new file mode 100644
index 000000000..a85a04f8a
--- /dev/null
+++ b/package/librtk-inband/src/inband_cmd.c
@@ -0,0 +1,465 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+
+#include <sys/stat.h> //mark_file
+
+#include "inband_if.h"
+
+#define HOST_NETIF ("wlan0")
+#define SLAVE_MAC ("001234567899")
+#define ETH_P_RTK 0x8899 // Realtek Remote Control Protocol (RRCP)
+int hcd_inband_chan=0;
+
+// command ID
+#define id_ioctl 0x01
+#define id_systemcall 0x02
+#define id_firm_upgrade 0x03
+#define id_hostcmd_only 0xff //only for new hostcmd implement ,if the cmd is not real "inband cmd"
+
+// Command Table
+struct inband_cmd_table_t {
+ char cmd_id;
+ const char *cmd; // Input command string
+ int (*func)(int index,int argc, char *argv[]);
+ void (*print_func)(char *para,char *data,int len);
+ const char *msg; // Help message
+};
+
+/*firmware define*/
+#define __PACK__ __attribute__ ((packed))
+
+#define SIGNATURE_LEN 4
+#define FW_HEADER_WITH_ROOT ((char *)"cr6c")
+#define FW_HEADER ((char *)"cs6c")
+#define ROOT_HEADER ((char *)"r6cr")
+#define WEB_HEADER ((char *)"w6cg") //no ap sign now //mark_issue
+
+typedef struct img_header {
+ unsigned char signature[SIGNATURE_LEN] __PACK__;
+ unsigned int startAddr __PACK__;
+ unsigned int burnAddr __PACK__;
+ unsigned int len __PACK__;
+} IMG_HEADER_T, *IMG_HEADER_Tp;
+
+
+unsigned int host_inband_seq=0; //use to do requset <-> response check
+
+int cmd_systemcall(int index,int argc, char *argv[]);
+int cmd_firmware_upgrade(int index,int argc, char *argv[]);
+void print_systemcall(char *para,char *data,int len);
+
+
+struct inband_cmd_table_t inband_cmd_table[]=
+{
+ //
+ {id_systemcall,"systemcall", cmd_systemcall, print_systemcall, "inband systemcall \'cmd_string\'"},
+ {id_firm_upgrade,"firm_upgrade", cmd_firmware_upgrade, NULL,"inband firm_upgrade /var/linux.bin"},
+ //{id_hostcmd_only,"send_conf", cmd_sendconf, NULL,"inband send_conf /etc/xxx.conf"},
+ {NULL, NULL, NULL},
+};
+
+
+unsigned int get_random(int max)
+{
+ struct timeval tod;
+
+ gettimeofday(&tod , NULL);
+ srand(tod.tv_usec);
+ return rand()%max;
+}
+
+void print_command_list(void)
+{
+ int i;
+
+ printf("\n==========commands for debugging============\n");
+ i = 0;
+ while (inband_cmd_table[i].cmd != NULL) {
+ printf("%s\n", inband_cmd_table[i].msg);
+ i++;
+ }
+}
+
+void print_systemcall(char *para,char *data,int len)
+{
+ int i=0;
+ unsigned char *value;
+
+ data[len] = '\0';
+ printf("cmd_cfgread \n");
+ printf("%s",data);
+}
+
+static int host_inband_write(char cmd_id,char *data,int data_len)
+{
+ int ret;
+
+ host_inband_seq = get_random(65536);
+
+ ret = inband_write(hcd_inband_chan,host_inband_seq,cmd_id,data,data_len,0); //send request
+ return ret;
+}
+
+static inline int CHECKSUM_OK(unsigned char *data, int len)
+{
+ int i;
+ unsigned char sum=0;
+
+ for (i=0; i<len; i++)
+ sum += data[i];
+
+ if (sum == 0)
+ return 1;
+ else
+ return 0;
+}
+
+static int fwChecksumOk(char *data, int len)
+{
+ unsigned short sum=0;
+ int i;
+
+ for (i=0; i<len; i+=2) {
+#ifdef _LITTLE_ENDIAN_
+ sum += WORD_SWAP( *((unsigned short *)&data[i]) );
+#else
+ sum += *((unsigned short *)&data[i]);
+#endif
+
+ }
+ return( (sum==0) ? 1 : 0);
+}
+static int host_firmware_write(char *data,int len)
+{
+ unsigned int tx_seq,rx_seq;
+ int ret=0,count;
+ char rx_cmd_type;
+ char *buf_p;
+
+ ret = host_inband_write(id_firm_upgrade,data,len); //send request
+
+ tx_seq = host_inband_seq;
+
+ if(ret < 0)
+ return -1;
+
+ ret = inband_rcv_data_and_seq(hcd_inband_chan,&rx_seq,&rx_cmd_type,&buf_p,20000); //return data length
+
+ if(ret < 0)
+ {
+ ret=-1;
+ goto out;
+ }
+
+ if( (rx_cmd_type == id_firm_upgrade) && (tx_seq == rx_seq))
+ printf("host_firmware_write ok!\n");
+ else
+ {
+ ret=-1;
+ printf("host_firmware_write fail!\n");
+ }
+
+out:
+ inband_free_buf(buf_p, count);
+ return ret;
+
+}
+
+static int rtk_firmware_update(char *upload_data, int upload_len)
+{
+int head_offset=0 ;
+int isIncludeRoot=0;
+int len;
+ int numLeft;
+int numWrite;
+IMG_HEADER_Tp pHeader;
+int fh;
+int fwSizeLimit = 0x200000;
+char buffer[100];
+int flag=0;
+
+while(head_offset < upload_len) {
+
+ pHeader = (IMG_HEADER_Tp) &upload_data[head_offset];
+ len = pHeader->len;
+#ifdef _LITTLE_ENDIAN_
+ len = DWORD_SWAP(len);
+#endif
+
+ numLeft = len + sizeof(IMG_HEADER_T) ;
+
+ // check header and checksum
+ if (!memcmp(&upload_data[head_offset], FW_HEADER, SIGNATURE_LEN) ||
+ !memcmp(&upload_data[head_offset], FW_HEADER_WITH_ROOT, SIGNATURE_LEN))
+ flag = 1;
+ else if (!memcmp(&upload_data[head_offset], WEB_HEADER, SIGNATURE_LEN))
+ flag = 2;
+ else if (!memcmp(&upload_data[head_offset], ROOT_HEADER, SIGNATURE_LEN)){
+ flag = 3;
+ isIncludeRoot = 1;
+ }
+ else {
+ strcpy(buffer, "Invalid file format!");
+ goto ret_upload;
+ }
+
+ if(len > fwSizeLimit){ //len check by sc_yang
+ sprintf(buffer, "Image len exceed max size 0x%x ! len=0x%x",fwSizeLimit, len);
+ goto ret_upload;
+ }
+ if ( (flag == 1) || (flag == 3)) {
+ if ( !fwChecksumOk(&upload_data[sizeof(IMG_HEADER_T)+head_offset], len)) {
+ sprintf(buffer, "Image checksum mismatched! len=0x%x, checksum=0x%x", len,
+ *((unsigned short *)&upload_data[len-2]) );
+ goto ret_upload;
+ }
+ }
+ else {
+ char *ptr = &upload_data[sizeof(IMG_HEADER_T)+head_offset];
+ if ( !CHECKSUM_OK(ptr, len) ) {
+ sprintf(buffer, "Image checksum mismatched! len=0x%x", len);
+ goto ret_upload;
+ }
+ }
+
+ //numWrite = write(fh, &(upload_data[locWrite+head_offset]), numLeft);
+ //inband write , and check ack
+ if(host_firmware_write(&(upload_data[head_offset]),numLeft) < 0 )
+ {
+ sprintf(buffer, "host_firmware_write! numLeft=0x%x", numLeft);
+ goto ret_upload;
+ }
+
+ head_offset += len + sizeof(IMG_HEADER_T) ;
+ }
+
+ return 0;
+
+ ret_upload:
+ fprintf(stderr, "%s\n", buffer);
+ return -1;
+} //while //sc_yang
+
+int cmd_firmware_upgrade(int index,int argc, char *argv[])
+{
+ int len,ret,count;
+ //char data[1480];
+ char filename[50];
+ char *data;
+ int fd,rc;
+ struct stat ffstat;
+ int flen=0;
+
+ //sprintf(data,"%s",argv[2]);
+ sprintf(filename,"%s",argv[2]);
+
+ fd = open(filename, O_RDONLY);
+
+ if (fd < 0) {
+ printf("Cannot Open file %s!\n", filename);
+ return -1;
+ }
+ fstat(fd, &ffstat);
+ flen = ffstat.st_size;
+ printf("flen = %d \n",flen);
+
+ if((data = (char *)malloc(flen)) == NULL)
+ {
+ printf("data buffer allocation failed!\n");
+ return -1;
+ }
+
+ // rc = read(fd, data, 1480);
+ rc = read(fd, data, flen);
+
+ //if (rc != 1480) {
+ if (rc != flen) {
+ printf("Reading error\n");
+ free(data); //need free before return!!!!!
+ return -1;
+ }
+
+ close(fd);
+
+ ret = rtk_firmware_update(data, flen);
+
+ if(ret < 0)
+ printf("rtk_firmware_update fail \n");
+ else
+ printf("rtk_firmware_update ok \n");
+
+ free(data); //need free before return!!!!!
+
+ return ret;
+}
+
+#if 0
+int cmd_sendconf(int index,int argc, char *argv[])
+{
+ int len,ret,count;
+ //char data[1480];
+ char cmd_id,rx_cmd_type;
+ char *buf_p;
+ unsigned int tx_seq,rx_seq;
+ char filename[50];
+ char *data;
+ int fd,rc;
+ struct stat ffstat;
+ int flen=0;
+
+ cmd_id = id_set_mib;
+
+ //sprintf(data,"%s",argv[2]);
+ sprintf(filename,"%s",argv[2]);
+
+ fd = open(filename, O_RDONLY);
+
+ if (fd < 0) {
+ printf("Cannot Open file %s!\n", filename);
+ return -1;
+ }
+ fstat(fd, &ffstat);
+ flen = ffstat.st_size;
+ printf("flen = %d \n",flen);
+
+ if((data = (char *)malloc(flen)) == NULL)
+ {
+ printf("data buffer allocation failed!\n");
+ return -1;
+ }
+
+ // rc = read(fd, data, 1480);
+ rc = read(fd, data, flen);
+
+ //if (rc != 1480) {
+ if (rc != flen) {
+ printf("Reading error\n");
+ free(data); //need free before return!!!!!
+ return -1;
+ }
+
+ close(fd);
+ //len = 1480;
+ len = flen;
+ tx_seq = host_inband_seq;
+ ret = host_inband_write(cmd_id,data,len); //send request
+
+ free(data); //need free before return!!!!!
+
+ if(ret < 0)
+ return -1;
+
+ //count = inband_rcv_data(&rx_cmd_type,&buf_p,1000); //return data length
+ count = inband_rcv_data_and_seq(hcd_inband_chan,&rx_seq,&rx_cmd_type,&buf_p,3000); //return data length
+ if(count < 0)
+ {
+ ret=-1;
+ goto out;
+ }
+
+ if( (rx_cmd_type == cmd_id) && (tx_seq == rx_seq))
+ printf("remote write ok!\n");
+ else
+ {
+ ret=-1;
+ printf("remote write fail!\n");
+ }
+
+ out:
+ inband_free_buf(buf_p, count);
+
+ return ret;
+}
+#endif
+int cmd_systemcall(int index,int argc, char *argv[])
+{
+ int len,ret,count;
+ char data[1480];
+ char cmd_id,rx_cmd_type;
+ char *buf_p;
+ unsigned int tx_seq,rx_seq;
+
+ cmd_id = inband_cmd_table[index].cmd_id;
+
+ if(argc > 3)
+ sprintf(data,"%s %s",argv[2],argv[3]);
+ else
+ sprintf(data,"%s",argv[2]);
+
+ len = strlen(data);
+
+
+ ret = host_inband_write(cmd_id,data,len); //send request
+
+ tx_seq = host_inband_seq;
+
+ if(ret < 0)
+ return -1;
+
+ //count = inband_rcv_data(&rx_cmd_type,&buf_p,1000); //return data length
+ count = inband_rcv_data_and_seq(hcd_inband_chan,&rx_seq,&rx_cmd_type,&buf_p,1000); //return data length
+
+ if(count < 0)
+ return -1;
+ //printf("count=%d rx_cmd_type=%x,cmd_id=%x,tx_seq=%d,rx_seq=%d",count,rx_cmd_type,cmd_id,tx_seq,rx_seq);
+
+ if((rx_cmd_type == cmd_id) && (tx_seq == rx_seq))
+ {
+ if(inband_cmd_table[index].print_func)
+ inband_cmd_table[index].print_func(data,buf_p,count);
+ }
+ else
+ return -1;
+
+ return 0;
+
+}
+
+int main(int argc, char *argv[])
+{
+ //int fdflags;
+ //unsigned int arg;
+ int i, ret;
+ int chan;
+
+ if (argc < 2) {
+ print_command_list();
+ return 0;
+ }
+
+ //open inband
+ chan = inband_open(HOST_NETIF,SLAVE_MAC,ETH_P_RTK,0);
+ if (chan < 0) {
+ printf("open inband failed!\n");
+ return -1;
+ }
+ hcd_inband_chan = chan;
+
+ i = 0;
+ while (inband_cmd_table[i].cmd != NULL) {
+ if (0 == strcmp(argv[1], inband_cmd_table[i].cmd)) {
+ if (inband_cmd_table[i].func) {
+ ret = inband_cmd_table[i].func(i,argc, argv);
+ if (ret > 0)
+ printf("OK\n");
+ else if (ret < 0)
+ printf("FAIL\n");
+ }
+ break;
+ }
+ i++;
+ }
+
+ inband_close(hcd_inband_chan);
+
+ return 0;
+}
diff --git a/package/librtk-inband/src/inband_if.c b/package/librtk-inband/src/inband_if.c
new file mode 100644
index 000000000..a3ce40996
--- /dev/null
+++ b/package/librtk-inband/src/inband_if.c
@@ -0,0 +1,443 @@
+/*
+ * IOH daemon
+ * Copyright (C)2010, Realtek Semiconductor Corp. All rights reserved
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+
+#include <linux/if_packet.h>
+#include "ioh.h"
+#include "inband_if.h"
+
+struct inband_header {
+ struct ioh_header raw_header;
+ unsigned char rrcp_type; // should be RRCP_P_IOH
+ unsigned char inband_cmd;
+ unsigned short inband_seq;
+ unsigned short inband_frag;
+ unsigned char inband_reserved[2];
+ unsigned short inband_data_len;
+} __attribute__((packed));
+
+struct fragment_info{
+ unsigned char inband_cmd;
+ unsigned short inband_seq;
+ unsigned short inband_frag;
+ char *buf_ptr;
+ char *buf;
+ unsigned int data_len;
+};
+
+struct inband_class {
+ struct ioh_class ioh_obj;
+ struct inband_header *tx_header;
+ struct inband_header *rx_header;
+ unsigned char *tx_data;
+ unsigned char *rx_data;
+ struct fragment_info frag_info;
+ unsigned int in_used;
+};
+
+//header : 4 sign , 4 opttion , 4 offset, 4 len
+#define FM_HEADER_LEN_OFFSET 12
+
+#define MAX_INBAND_CHAN 1
+#define MAX_PREALLOC_INBAND_CHAN MAX_INBAND_CHAN
+
+int inband_rcv_timeout=0; //mark_issue, not implement now
+
+static struct inband_class inband_obj[MAX_INBAND_CHAN];
+static int inband_ready=0;
+
+static void init_inband_obj(struct inband_class *ib_obj)
+{
+ struct ioh_class *obj=&ib_obj->ioh_obj;
+
+ ib_obj->tx_header = (struct inband_header *)obj->tx_header;
+ ib_obj->rx_header = (struct inband_header *)obj->rx_header;
+
+ ib_obj->tx_data = (unsigned char *) obj->tx_buffer + sizeof(struct inband_header);
+ ib_obj->rx_data = (unsigned char *) obj->rx_buffer + sizeof(struct inband_header);
+
+ //frag_info?
+}
+
+static unsigned int get_free_chan()
+{
+ int i;
+ int chan=-1;
+
+ for(i=0;i<MAX_INBAND_CHAN;i++)
+ {
+ if(inband_obj[i].in_used ==0 )
+ {
+ inband_obj[i].in_used =1;
+ chan = i;
+ break;
+ }
+ }
+ return chan;
+}
+
+static struct inband_class *get_chan_obj(unsigned int chan)
+{
+ return (struct inband_class *)&inband_obj[chan];
+}
+
+static void inband_init_all()
+{
+ memset(&inband_obj[0],0,sizeof(struct inband_class)*MAX_INBAND_CHAN);
+}
+
+int inband_open(char *netif_name,char *slave_mac,unsigned short eth_type,int debug)
+{
+ int ret;
+ unsigned int chan;
+ struct inband_class *inband_obj_p;
+ struct ioh_class *ioh_obj_p;
+
+ if(inband_ready == 0)
+ {
+ inband_init_all();
+ inband_ready =1 ;
+ }
+
+ chan = get_free_chan();
+ if(chan < 0)
+ return -1;
+
+ inband_obj_p = (struct inband_class *)get_chan_obj(chan);
+
+ ioh_obj_p = &inband_obj_p->ioh_obj;
+
+ ret = ioh_open(ioh_obj_p, netif_name, slave_mac,eth_type, debug);
+
+ if(ret < 0 )
+ return -1;
+
+ init_inband_obj(inband_obj_p);
+
+ return chan;
+}
+
+int get_inband_socket(int chan)
+{
+ struct inband_class *inband_obj_p;
+ struct ioh_class *ioh_obj_p;
+
+ inband_obj_p = (struct inband_class *)get_chan_obj(chan);
+ ioh_obj_p = &inband_obj_p->ioh_obj;
+
+ return ioh_obj_p->sockfd;
+}
+
+int get_inband_destMac(int chan,char *destmac) //mark_test
+{
+ struct inband_class *inband_obj_p;
+ struct ioh_class *ioh_obj_p;
+
+ inband_obj_p = (struct inband_class *)get_chan_obj(chan);
+ ioh_obj_p = &inband_obj_p->ioh_obj;
+
+ memcpy(destmac,ioh_obj_p->dest_mac,6);
+
+ return 0;
+}
+
+void inband_close(int chan)
+{
+ //clear frag_info
+ struct inband_class *inband_obj_p;
+ struct ioh_class *ioh_obj_p;
+
+ inband_obj_p = (struct inband_class *)get_chan_obj(chan);
+ ioh_obj_p = &inband_obj_p->ioh_obj;
+ ioh_close(ioh_obj_p);
+ inband_obj_p->in_used =0; //free the obj
+}
+
+static int inband_recv(struct inband_class *ib_obj,int timeout)
+{
+ struct ioh_class *ioh_obj_p = &ib_obj->ioh_obj;
+ int rx_len;
+
+ rx_len = ioh_recv(ioh_obj_p, timeout);
+ if (rx_len < 0)
+ return ERROR_TIMOUT;
+ if(ib_obj->rx_header->rrcp_type != RRCP_P_IOH)
+ return -1;
+
+ return rx_len;
+}
+
+static int send_frag_ack(struct inband_class *ib_obj)
+{
+ struct ioh_class *ioh_obj_p = &ib_obj->ioh_obj;
+
+ ib_obj->tx_header->rrcp_type = RRCP_P_IOH; //mark_inband
+ ib_obj->tx_header->inband_cmd = ib_obj->rx_header->inband_cmd;
+ ib_obj->tx_header->inband_seq = ib_obj->rx_header->inband_seq;
+ ib_obj->tx_header->inband_frag = ib_obj->rx_header->inband_frag;
+ ib_obj->tx_header->inband_data_len = 0;
+
+ return ioh_send(ioh_obj_p,sizeof(struct inband_header)); //only send header for ack
+}
+static int check_frag_ack(struct inband_class *ib_obj)
+{
+ int rx_len;
+
+ rx_len = inband_recv(ib_obj, PER_FRAME_TIMEOUT); // -1 = wait until rec
+ if (rx_len < 0)
+ {
+ perror("check_frag_ack fail:");
+ return 0;
+ }
+ if((ib_obj->rx_header->inband_cmd == ib_obj->tx_header->inband_cmd) &&
+ (ib_obj->rx_header->inband_seq == ib_obj->tx_header->inband_seq) &&
+ (ib_obj->rx_header->inband_frag == ib_obj->tx_header->inband_frag) )
+ return 1; //ok
+
+ return 0; //fail
+}
+static char *inband_alloc_buf(struct inband_class *ib_obj)
+{
+ char *buf=NULL;
+ unsigned int buf_size=MAX_APP_DATA_SIZE;
+ unsigned char *image_len,header_len_offset=FM_HEADER_LEN_OFFSET;
+#if 1 //it's for firmware file
+ if(ib_obj->rx_header->inband_cmd == id_firm_upgrade)
+ {
+ //read firmware length from it's header
+ image_len = (char *)ib_obj->rx_data;
+ buf_size =(unsigned int)( ( image_len[header_len_offset+0] <<24 ) +
+ ( image_len[header_len_offset+1] <<16 ) +
+ ( image_len[header_len_offset+2] <<8 ) +
+ ( image_len[header_len_offset+3] <<0 ) + 16 ) ;
+
+ //printf("inband_alloc_buf buf_size=%x , image_len[0]= %x\n",buf_size,image_len[header_len_offset+0]);
+ }
+#endif
+ buf = (char *)malloc(buf_size);
+ return buf;
+}
+//mark_issue,defragment_reset
+static int init_defragment_process(struct inband_class *ib_obj)
+{
+ struct fragment_info *p_frag_info = &ib_obj->frag_info;
+
+ //check if the it is first fragment id
+ if(ib_obj->rx_header->inband_frag != FIRST_FRAG_ID)
+ return ERROR_DEFRAGMENT;
+
+ if((p_frag_info->buf = (char *)inband_alloc_buf(ib_obj)) == NULL)
+ {
+ printf("init_defragment_process : data buffer allocation failed!\n");
+ return ERROR_DEFRAGMENT;
+ }
+ p_frag_info->buf_ptr = p_frag_info->buf;
+ p_frag_info->inband_frag = FIRST_FRAG_ID;
+
+#ifdef WPAS_INB
+ p_frag_info->inband_cmd = ntohs(ib_obj->rx_header->inband_cmd);
+ p_frag_info->inband_seq = ntohs(ib_obj->rx_header->inband_seq);
+#else
+ p_frag_info->inband_cmd = ib_obj->rx_header->inband_cmd;
+ p_frag_info->inband_seq = ib_obj->rx_header->inband_seq;
+#endif
+
+ //copy first frame to buffer
+ memcpy(p_frag_info->buf,ib_obj->rx_data,ntohs(ib_obj->rx_header->inband_data_len));
+ p_frag_info->buf += ntohs(ib_obj->rx_header->inband_data_len);
+ p_frag_info->data_len = ntohs(ib_obj->rx_header->inband_data_len);
+ send_frag_ack(ib_obj);
+
+ return 0; //init ok
+}
+
+static int do_defragment_process(struct inband_class *ib_obj)
+{
+ int ret=0;
+ struct fragment_info *p_frag_info = &ib_obj->frag_info;
+
+ if(p_frag_info->inband_seq != ntohs(ib_obj->rx_header->inband_seq) )
+ return ERROR_DEFRAGMENT;
+
+ if( (p_frag_info->inband_frag+1) != (ntohs(ib_obj->rx_header->inband_frag) & FRAG_ID_MASK))
+ return ERROR_DEFRAGMENT;
+ else
+ p_frag_info->inband_frag = ntohs(ib_obj->rx_header->inband_frag);
+
+ memcpy(p_frag_info->buf,ib_obj->rx_data,ntohs(ib_obj->rx_header->inband_data_len));
+ p_frag_info->buf += (ntohs(ib_obj->rx_header->inband_data_len));
+ p_frag_info->data_len+= (ntohs(ib_obj->rx_header->inband_data_len));
+
+ if( (p_frag_info->inband_frag & EOF_BIT) == EOF_BIT)
+ ret = 1;
+
+ return ret; // return 1 means EOF rcv , return 0 means conitiune
+}
+
+static int get_defragment_info(struct inband_class *ib_obj,char *cmd_type,char **data)
+{
+ struct fragment_info *p_frag_info = &ib_obj->frag_info;
+
+ *cmd_type = p_frag_info->inband_cmd;
+ *data = p_frag_info->buf_ptr; //mark_issue,hwo to free the buffer ?
+ return p_frag_info->data_len;
+}
+
+static int inband_rcv_fragment(struct inband_class *ib_obj,char *cmd_type,char **data)
+{
+ int rx_len,ret=0;
+
+ ret = init_defragment_process(ib_obj) ;
+
+ if(ret < 0)
+ return ret;
+
+ while( (inband_rcv_timeout!=1))
+ {
+ rx_len = inband_recv(ib_obj, PER_FRAME_TIMEOUT);
+ if (rx_len < 0)
+ return ERROR_TIMOUT;
+ ret = do_defragment_process(ib_obj);
+ if (ret < 0)
+ return ret;
+ else if(ret == 1) //ret == 1 means defragment end , ret=0 means contiune
+ {
+ ret = get_defragment_info(ib_obj,cmd_type,data);
+ break;
+ }
+ send_frag_ack(ib_obj);
+ }
+ return ret;
+}
+void inband_free_buf(char *data_buf,int data_len)
+{
+ //only free allocated buffer from deframet process.
+ if( (data_buf != NULL) && ( data_len > MAX_INBAND_PAYLOAD_LEN ) )
+ free(data_buf);
+}
+int inband_rcv_data(int chan,char *cmd_type,char **data,int timout_ms) //return data length
+{
+ int rx_len,data_len=0;
+ struct inband_class *inband_obj_p;
+ struct ioh_class *ioh_obj_p;
+
+ inband_obj_p = (struct inband_class *)get_chan_obj(chan);
+ ioh_obj_p = &inband_obj_p->ioh_obj;
+
+
+ //timout_ms will be used only for the first pkt. if the pkt is fragmented then every packet will
+ //follow fragment_timout_ms
+ rx_len = inband_recv(inband_obj_p, timout_ms); // -1 = wait until rec
+ if (rx_len < 0)
+ {
+ perror("inband_rcv_data:");
+ return -1;
+ }
+ //printf("inband_rcv_data:\n");
+ //hex_dump(ioh_obj_p->rx_buffer, ntohs(inband_obj_p->rx_header->inband_data_len) + sizeof(*inband_obj_p->rx_header)); //mark_test
+
+ //cache for tx dest mac
+ if( memcmp(ioh_obj_p->dest_mac,ioh_obj_p->rx_header->sa,6)) //mark_test
+ memcpy(ioh_obj_p->dest_mac,ioh_obj_p->rx_header->sa,6);
+
+ //single pkt
+ if( inband_obj_p->rx_header->inband_frag == ntohs(SINGLE_FRAME)) //mark_endian
+ {
+ *cmd_type = inband_obj_p->rx_header->inband_cmd;
+ data_len = ntohs(inband_obj_p->rx_header->inband_data_len);
+ *data = inband_obj_p->rx_data ; //or memcpy;
+ }
+ else //fragment process
+ data_len = inband_rcv_fragment(inband_obj_p,cmd_type,data);
+
+ return data_len;
+
+}
+
+//if seq is need in your application
+int inband_rcv_data_and_seq(int chan,unsigned int *seq,char *cmd_type,char **data,int timout_ms) //return data length
+{
+ struct inband_class *inband_obj_p;
+ int ret=0;
+
+ inband_obj_p = (struct inband_class *)get_chan_obj(chan);
+ ret = inband_rcv_data(chan,cmd_type,data, timout_ms); //return data length
+ if(ret < 0)
+ return -1;
+
+ *seq = ntohs(inband_obj_p->rx_header->inband_seq);
+ return ret;
+}
+
+static int inband_send_data(struct inband_class *ib_obj,char *data,int data_len)
+{
+ char *frag_ptr;
+ unsigned short id=0,total_frag=0;
+ unsigned int last_num;
+ struct ioh_class *ioh_obj_p = &ib_obj->ioh_obj;
+
+ total_frag = (unsigned short)(data_len / MAX_INBAND_PAYLOAD_LEN);
+
+ if( total_frag > MAX_FRAG_ID)
+ return -1;
+
+ ib_obj->tx_header->inband_frag =0;
+ frag_ptr = data;
+
+ for(id=0;id<total_frag;id++)
+ {
+ ib_obj->tx_header->inband_data_len = htons(MAX_INBAND_PAYLOAD_LEN);
+ ib_obj->tx_header->inband_frag = htons(id );
+ memcpy(&ib_obj->tx_data[0], frag_ptr,MAX_INBAND_PAYLOAD_LEN );
+ if( ioh_send(ioh_obj_p, sizeof(struct inband_header) + MAX_INBAND_PAYLOAD_LEN ) < 0)
+ return -1;
+ //if(id>= 1){
+ if(check_frag_ack(ib_obj) != 1)
+ return -1;
+ //}
+ frag_ptr += MAX_INBAND_PAYLOAD_LEN;
+ }
+ last_num = data_len % MAX_INBAND_PAYLOAD_LEN;
+ //EOF fragment
+ ib_obj->tx_header->inband_frag = id;
+ ib_obj->tx_header->inband_frag |=EOF_BIT;
+ ib_obj->tx_header->inband_frag = htons(ib_obj->tx_header->inband_frag);
+ ib_obj->tx_header->inband_data_len = htons(last_num);
+ if(last_num >0)
+ memcpy(&ib_obj->tx_data[0], frag_ptr,last_num );
+
+ return ioh_send(ioh_obj_p,sizeof(struct inband_header)+last_num);
+}
+
+int inband_write(int chan,unsigned int seq,char cmd,char *data,int data_len,int reply)
+{
+ struct inband_class *inband_obj_p;
+
+ inband_obj_p = (struct inband_class *)get_chan_obj(chan);
+
+ inband_obj_p->tx_header->rrcp_type = RRCP_P_IOH; //mark_inband
+ //fill inband header , cmd
+ inband_obj_p->tx_header->inband_cmd = cmd;
+
+ //reply = 0(request) ,reply = 1(good reply),reply = 2(bad reply)
+ if(reply == 2)
+ inband_obj_p->tx_header->inband_cmd |= CMD_ERROR_REPLY_BIT;
+
+ //fill inband header , seq
+ if(!reply)
+ inband_obj_p->tx_header->inband_seq = htons(seq);
+ else //seq is not used when the packet is for reply
+ inband_obj_p->tx_header->inband_seq = inband_obj_p->rx_header->inband_seq;
+
+ //fill data, data_len , and send
+ return inband_send_data(inband_obj_p,data,data_len);
+}
+
diff --git a/package/librtk-inband/src/inband_if.h b/package/librtk-inband/src/inband_if.h
new file mode 100644
index 000000000..c37a3ca10
--- /dev/null
+++ b/package/librtk-inband/src/inband_if.h
@@ -0,0 +1,30 @@
+#ifndef INCLUDE_INBAND_IF_H
+#define INCLUDE_INBAND_IF_H
+
+#define MAX_APP_DATA_SIZE 65535
+#define CMD_ERROR_REPLY_BIT 0x80
+#define MAX_INBAND_PAYLOAD_LEN 1480
+#define MAX_FRAG_ID (0x8000 -1)
+#define FRAG_ID_MASK (~(0x8000))
+
+#define EOF_BIT 0x8000
+#define SINGLE_FRAME 0x8000
+#define FIRST_FRAG_ID 0x0000
+#define PER_FRAME_TIMEOUT 2000 //ms
+
+#define ERROR_TIMOUT -1
+#define ERROR_DEFRAGMENT -2
+
+#define RRCP_P_IOH 0x38 // RRCP IOH
+
+//mark_fm
+#define id_firm_upgrade 0x03
+
+int inband_open(char *netif_name,char *slave_mac,unsigned short eth_type,int debug);
+void inband_close(int chan);
+void inband_free_buf(char *data_buf,int data_len);
+int inband_rcv_data(int chan,char *cmd_type,char **data,int timout_ms); //return data length
+int inband_rcv_data_and_seq(int chan,unsigned int *seq,char *cmd_type,char **data,int timout_ms); //return data length
+int inband_write(int chan,unsigned int seq,char cmd,char *data,int data_len,int reply);
+
+#endif
diff --git a/package/librtk-inband/src/include/net80211/_ieee80211.h b/package/librtk-inband/src/include/net80211/_ieee80211.h
new file mode 100644
index 000000000..f536dcb02
--- /dev/null
+++ b/package/librtk-inband/src/include/net80211/_ieee80211.h
@@ -0,0 +1,246 @@
+/*-
+ * Copyright (c) 2001 Atsushi Onoe
+ * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: _ieee80211.h 2749 2007-10-16 08:58:14Z kelmo $
+ */
+#ifndef _NET80211__IEEE80211_H_
+#define _NET80211__IEEE80211_H_
+
+enum ieee80211_phytype {
+ IEEE80211_T_DS, /* direct sequence spread spectrum */
+ IEEE80211_T_FH, /* frequency hopping */
+ IEEE80211_T_OFDM, /* frequency division multiplexing */
+ IEEE80211_T_TURBO, /* high rate OFDM, aka turbo mode */
+};
+#define IEEE80211_T_CCK IEEE80211_T_DS /* more common nomenclature */
+
+/* XXX not really a mode; there are really multiple PHY's */
+enum ieee80211_phymode {
+ IEEE80211_MODE_AUTO = 0, /* autoselect */
+ IEEE80211_MODE_11A = 1, /* 5GHz, OFDM */
+ IEEE80211_MODE_11B = 2, /* 2GHz, CCK */
+ IEEE80211_MODE_11G = 3, /* 2GHz, OFDM */
+ IEEE80211_MODE_FH = 4, /* 2GHz, GFSK */
+ IEEE80211_MODE_TURBO_A = 5, /* 5GHz, OFDM, 2x clock dynamic turbo */
+ IEEE80211_MODE_TURBO_G = 6, /* 2GHz, OFDM, 2x clock dynamic turbo*/
+};
+#define IEEE80211_MODE_MAX (IEEE80211_MODE_TURBO_G+1)
+
+enum ieee80211_opmode {
+ IEEE80211_M_STA = 1, /* infrastructure station */
+ IEEE80211_M_IBSS = 0, /* IBSS (adhoc) station */
+ IEEE80211_M_AHDEMO = 3, /* Old lucent compatible adhoc demo */
+ IEEE80211_M_HOSTAP = 6, /* Software Access Point */
+ IEEE80211_M_MONITOR = 8, /* Monitor mode */
+ IEEE80211_M_WDS = 2 /* WDS link */
+};
+
+/*
+ * 802.11g protection mode.
+ */
+enum ieee80211_protmode {
+ IEEE80211_PROT_NONE = 0, /* no protection */
+ IEEE80211_PROT_CTSONLY = 1, /* CTS to self */
+ IEEE80211_PROT_RTSCTS = 2, /* RTS-CTS */
+};
+
+/*
+ * Authentication mode.
+ */
+enum ieee80211_authmode {
+ IEEE80211_AUTH_NONE = 0,
+ IEEE80211_AUTH_OPEN = 1, /* open */
+ IEEE80211_AUTH_SHARED = 2, /* shared-key */
+ IEEE80211_AUTH_8021X = 3, /* 802.1x */
+ IEEE80211_AUTH_AUTO = 4, /* auto-select/accept */
+ /* NB: these are used only for ioctls */
+ IEEE80211_AUTH_WPA = 5, /* WPA/RSN w/ 802.1x/PSK */
+};
+
+/*
+ * Roaming mode is effectively who controls the operation
+ * of the 802.11 state machine when operating as a station.
+ * State transitions are controlled either by the driver
+ * (typically when management frames are processed by the
+ * hardware/firmware), the host (auto/normal operation of
+ * the 802.11 layer), or explicitly through ioctl requests
+ * when applications like wpa_supplicant want control.
+ */
+enum ieee80211_roamingmode {
+ IEEE80211_ROAMING_DEVICE= 0, /* driver/hardware control */
+ IEEE80211_ROAMING_AUTO = 1, /* 802.11 layer control */
+ IEEE80211_ROAMING_MANUAL= 2, /* application control */
+};
+
+/*
+ * Scanning mode controls station scanning work; this is
+ * used only when roaming mode permits the host to select
+ * the bss to join/channel to use.
+ */
+enum ieee80211_scanmode {
+ IEEE80211_SCAN_DEVICE = 0, /* driver/hardware control */
+ IEEE80211_SCAN_BEST = 1, /* 802.11 layer selects best */
+ IEEE80211_SCAN_FIRST = 2, /* take first suitable candidate */
+};
+
+/*
+ * Channels are specified by frequency and attributes.
+ */
+struct ieee80211_channel {
+ u_int16_t ic_freq; /* setting in Mhz */
+ u_int16_t ic_flags; /* see below */
+ u_int8_t ic_ieee; /* IEEE channel number */
+ int8_t ic_maxregpower; /* maximum regulatory tx power in dBm */
+ int8_t ic_maxpower; /* maximum tx power in dBm */
+ int8_t ic_minpower; /* minimum tx power in dBm */
+};
+
+#define IEEE80211_CHAN_MAX 255
+#define IEEE80211_CHAN_BYTES 32 /* howmany(IEEE80211_CHAN_MAX, NBBY) */
+#define IEEE80211_CHAN_ANY 0xffff /* token for ``any channel'' */
+#define IEEE80211_CHAN_ANYC ((struct ieee80211_channel *) IEEE80211_CHAN_ANY)
+
+#define IEEE80211_RADAR_11HCOUNT 1
+#define IEEE80211_DEFAULT_CHANCHANGE_TBTT_COUNT 3
+#define IEEE80211_RADAR_TEST_MUTE_CHAN 36 /* Move to channel 36 for mute test */
+
+/* bits 0-3 are for private use by drivers */
+/* channel attributes */
+#define IEEE80211_CHAN_TURBO 0x0010 /* Turbo channel */
+#define IEEE80211_CHAN_CCK 0x0020 /* CCK channel */
+#define IEEE80211_CHAN_OFDM 0x0040 /* OFDM channel */
+#define IEEE80211_CHAN_2GHZ 0x0080 /* 2 GHz spectrum channel. */
+#define IEEE80211_CHAN_5GHZ 0x0100 /* 5 GHz spectrum channel */
+#define IEEE80211_CHAN_PASSIVE 0x0200 /* Only passive scan allowed */
+#define IEEE80211_CHAN_DYN 0x0400 /* Dynamic CCK-OFDM channel */
+#define IEEE80211_CHAN_GFSK 0x0800 /* GFSK channel (FHSS PHY) */
+#define IEEE80211_CHAN_RADAR 0x1000 /* Radar found on channel */
+#define IEEE80211_CHAN_STURBO 0x2000 /* 11a static turbo channel only */
+#define IEEE80211_CHAN_HALF 0x4000 /* Half rate channel */
+#define IEEE80211_CHAN_QUARTER 0x8000 /* Quarter rate channel */
+
+/*
+ * Useful combinations of channel characteristics.
+ */
+#define IEEE80211_CHAN_FHSS \
+ (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_GFSK)
+#define IEEE80211_CHAN_A \
+ (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM)
+#define IEEE80211_CHAN_B \
+ (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK)
+#define IEEE80211_CHAN_PUREG \
+ (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_OFDM)
+#define IEEE80211_CHAN_G \
+ (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN)
+#define IEEE80211_CHAN_108A \
+ (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM | IEEE80211_CHAN_TURBO)
+#define IEEE80211_CHAN_108G \
+ (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_OFDM | IEEE80211_CHAN_TURBO)
+#define IEEE80211_CHAN_ST \
+ (IEEE80211_CHAN_108A | IEEE80211_CHAN_STURBO)
+
+#define IEEE80211_CHAN_ALL \
+ (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_GFSK | \
+ IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM | IEEE80211_CHAN_DYN)
+#define IEEE80211_CHAN_ALLTURBO \
+ (IEEE80211_CHAN_ALL | IEEE80211_CHAN_TURBO | IEEE80211_CHAN_STURBO)
+
+#define IEEE80211_IS_CHAN_FHSS(_c) \
+ (((_c)->ic_flags & IEEE80211_CHAN_FHSS) == IEEE80211_CHAN_FHSS)
+#define IEEE80211_IS_CHAN_A(_c) \
+ (((_c)->ic_flags & IEEE80211_CHAN_A) == IEEE80211_CHAN_A)
+#define IEEE80211_IS_CHAN_B(_c) \
+ (((_c)->ic_flags & IEEE80211_CHAN_B) == IEEE80211_CHAN_B)
+#define IEEE80211_IS_CHAN_PUREG(_c) \
+ (((_c)->ic_flags & IEEE80211_CHAN_PUREG) == IEEE80211_CHAN_PUREG)
+#define IEEE80211_IS_CHAN_G(_c) \
+ (((_c)->ic_flags & IEEE80211_CHAN_G) == IEEE80211_CHAN_G)
+#define IEEE80211_IS_CHAN_ANYG(_c) \
+ (IEEE80211_IS_CHAN_PUREG(_c) || IEEE80211_IS_CHAN_G(_c))
+#define IEEE80211_IS_CHAN_ST(_c) \
+ (((_c)->ic_flags & IEEE80211_CHAN_ST) == IEEE80211_CHAN_ST)
+#define IEEE80211_IS_CHAN_108A(_c) \
+ (((_c)->ic_flags & IEEE80211_CHAN_108A) == IEEE80211_CHAN_108A)
+#define IEEE80211_IS_CHAN_108G(_c) \
+ (((_c)->ic_flags & IEEE80211_CHAN_108G) == IEEE80211_CHAN_108G)
+
+#define IEEE80211_IS_CHAN_2GHZ(_c) \
+ (((_c)->ic_flags & IEEE80211_CHAN_2GHZ) != 0)
+#define IEEE80211_IS_CHAN_5GHZ(_c) \
+ (((_c)->ic_flags & IEEE80211_CHAN_5GHZ) != 0)
+#define IEEE80211_IS_CHAN_OFDM(_c) \
+ (((_c)->ic_flags & IEEE80211_CHAN_OFDM) != 0)
+#define IEEE80211_IS_CHAN_CCK(_c) \
+ (((_c)->ic_flags & IEEE80211_CHAN_CCK) != 0)
+#define IEEE80211_IS_CHAN_GFSK(_c) \
+ (((_c)->ic_flags & IEEE80211_CHAN_GFSK) != 0)
+#define IEEE80211_IS_CHAN_TURBO(_c) \
+ (((_c)->ic_flags & IEEE80211_CHAN_TURBO) != 0)
+#define IEEE80211_IS_CHAN_STURBO(_c) \
+ (((_c)->ic_flags & IEEE80211_CHAN_STURBO) != 0)
+#define IEEE80211_IS_CHAN_DTURBO(_c) \
+ (((_c)->ic_flags & \
+ (IEEE80211_CHAN_TURBO | IEEE80211_CHAN_STURBO)) == IEEE80211_CHAN_TURBO)
+#define IEEE80211_IS_CHAN_HALF(_c) \
+ (((_c)->ic_flags & IEEE80211_CHAN_HALF) != 0)
+#define IEEE80211_IS_CHAN_QUARTER(_c) \
+ (((_c)->ic_flags & IEEE80211_CHAN_QUARTER) != 0)
+
+/* ni_chan encoding for FH phy */
+#define IEEE80211_FH_CHANMOD 80
+#define IEEE80211_FH_CHAN(set,pat) (((set) - 1) * IEEE80211_FH_CHANMOD + (pat))
+#define IEEE80211_FH_CHANSET(chan) ((chan) / IEEE80211_FH_CHANMOD + 1)
+#define IEEE80211_FH_CHANPAT(chan) ((chan) % IEEE80211_FH_CHANMOD)
+
+/*
+ * 802.11 rate set.
+ */
+#define IEEE80211_RATE_SIZE 8 /* 802.11 standard */
+#define IEEE80211_RATE_MAXSIZE 15 /* max rates we'll handle */
+#define IEEE80211_SANITISE_RATESIZE(_rsz) \
+ ((_rsz > IEEE80211_RATE_MAXSIZE) ? IEEE80211_RATE_MAXSIZE : _rsz)
+
+struct ieee80211_rateset {
+ u_int8_t rs_nrates;
+ u_int8_t rs_rates[IEEE80211_RATE_MAXSIZE];
+};
+
+struct ieee80211_roam {
+ int8_t rssi11a; /* rssi thresh for 11a bss */
+ int8_t rssi11b; /* for 11g sta in 11b bss */
+ int8_t rssi11bOnly; /* for 11b sta */
+ u_int8_t pad1;
+ u_int8_t rate11a; /* rate thresh for 11a bss */
+ u_int8_t rate11b; /* for 11g sta in 11b bss */
+ u_int8_t rate11bOnly; /* for 11b sta */
+ u_int8_t pad2;
+};
+#endif /* _NET80211__IEEE80211_H_ */
diff --git a/package/librtk-inband/src/include/net80211/ieee80211.h b/package/librtk-inband/src/include/net80211/ieee80211.h
new file mode 100644
index 000000000..c28e83df0
--- /dev/null
+++ b/package/librtk-inband/src/include/net80211/ieee80211.h
@@ -0,0 +1,947 @@
+/*-
+ * Copyright (c) 2001 Atsushi Onoe
+ * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: ieee80211.h 3313 2008-01-30 21:07:22Z proski $
+ */
+#ifndef _NET80211_IEEE80211_H_
+#define _NET80211_IEEE80211_H_
+
+#ifndef _LINUX_TYPES_H
+#include <linux/types.h>
+#endif
+
+#ifndef __packed
+#define __packed __attribute__((__packed__))
+#endif
+
+/*
+ * 802.11 protocol definitions.
+ */
+
+#define IEEE80211_ADDR_LEN 6 /* size of 802.11 address */
+/* is 802.11 address multicast/broadcast? */
+#define IEEE80211_IS_MULTICAST(_a) (*(_a) & 0x01)
+
+/* IEEE 802.11 PLCP header */
+struct ieee80211_plcp_hdr {
+ u_int16_t i_sfd;
+ u_int8_t i_signal;
+ u_int8_t i_service;
+ u_int16_t i_length;
+ u_int16_t i_crc;
+} __packed;
+
+#define IEEE80211_PLCP_SFD 0xF3A0
+#define IEEE80211_PLCP_SERVICE 0x00
+
+/*
+ * generic definitions for IEEE 802.11 frames
+ */
+struct ieee80211_frame {
+ u_int8_t i_fc[2];
+ __le16 i_dur;
+ u_int8_t i_addr1[IEEE80211_ADDR_LEN];
+ u_int8_t i_addr2[IEEE80211_ADDR_LEN];
+ u_int8_t i_addr3[IEEE80211_ADDR_LEN];
+ u_int8_t i_seq[2];
+ /* possibly followed by addr4[IEEE80211_ADDR_LEN]; */
+ /* see below */
+} __packed;
+
+struct ieee80211_qosframe {
+ u_int8_t i_fc[2];
+ __le16 i_dur;
+ u_int8_t i_addr1[IEEE80211_ADDR_LEN];
+ u_int8_t i_addr2[IEEE80211_ADDR_LEN];
+ u_int8_t i_addr3[IEEE80211_ADDR_LEN];
+ u_int8_t i_seq[2];
+ u_int8_t i_qos[2];
+ /* possibly followed by addr4[IEEE80211_ADDR_LEN]; */
+ /* see below */
+} __packed;
+
+struct ieee80211_qoscntl {
+ u_int8_t i_qos[2];
+};
+
+struct ieee80211_frame_addr4 {
+ u_int8_t i_fc[2];
+ __le16 i_dur;
+ u_int8_t i_addr1[IEEE80211_ADDR_LEN];
+ u_int8_t i_addr2[IEEE80211_ADDR_LEN];
+ u_int8_t i_addr3[IEEE80211_ADDR_LEN];
+ u_int8_t i_seq[2];
+ u_int8_t i_addr4[IEEE80211_ADDR_LEN];
+} __packed;
+
+
+struct ieee80211_qosframe_addr4 {
+ u_int8_t i_fc[2];
+ __le16 i_dur;
+ u_int8_t i_addr1[IEEE80211_ADDR_LEN];
+ u_int8_t i_addr2[IEEE80211_ADDR_LEN];
+ u_int8_t i_addr3[IEEE80211_ADDR_LEN];
+ u_int8_t i_seq[2];
+ u_int8_t i_addr4[IEEE80211_ADDR_LEN];
+ u_int8_t i_qos[2];
+} __packed;
+
+struct ieee80211_ctlframe_addr2 {
+ u_int8_t i_fc[2];
+ __le16 i_aidordur; /* AID or duration */
+ u_int8_t i_addr1[IEEE80211_ADDR_LEN];
+ u_int8_t i_addr2[IEEE80211_ADDR_LEN];
+} __packed;
+
+#define IEEE80211_FC0_VERSION_MASK 0x03
+#define IEEE80211_FC0_VERSION_SHIFT 0
+#define IEEE80211_FC0_VERSION_0 0x00
+#define IEEE80211_FC0_TYPE_MASK 0x0c
+#define IEEE80211_FC0_TYPE_SHIFT 2
+#define IEEE80211_FC0_TYPE_MGT 0x00
+#define IEEE80211_FC0_TYPE_CTL 0x04
+#define IEEE80211_FC0_TYPE_DATA 0x08
+
+#define IEEE80211_FC0_SUBTYPE_MASK 0xf0
+#define IEEE80211_FC0_SUBTYPE_SHIFT 4
+/* for TYPE_MGT */
+#define IEEE80211_FC0_SUBTYPE_ASSOC_REQ 0x00
+#define IEEE80211_FC0_SUBTYPE_ASSOC_RESP 0x10
+#define IEEE80211_FC0_SUBTYPE_REASSOC_REQ 0x20
+#define IEEE80211_FC0_SUBTYPE_REASSOC_RESP 0x30
+#define IEEE80211_FC0_SUBTYPE_PROBE_REQ 0x40
+#define IEEE80211_FC0_SUBTYPE_PROBE_RESP 0x50
+#define IEEE80211_FC0_SUBTYPE_BEACON 0x80
+#define IEEE80211_FC0_SUBTYPE_ATIM 0x90
+#define IEEE80211_FC0_SUBTYPE_DISASSOC 0xa0
+#define IEEE80211_FC0_SUBTYPE_AUTH 0xb0
+#define IEEE80211_FC0_SUBTYPE_DEAUTH 0xc0
+#define IEEE80211_FC0_SUBTYPE_ACTION 0xd0
+/* for TYPE_CTL */
+#define IEEE80211_FC0_SUBTYPE_PS_POLL 0xa0
+#define IEEE80211_FC0_SUBTYPE_RTS 0xb0
+#define IEEE80211_FC0_SUBTYPE_CTS 0xc0
+#define IEEE80211_FC0_SUBTYPE_ACK 0xd0
+#define IEEE80211_FC0_SUBTYPE_CF_END 0xe0
+#define IEEE80211_FC0_SUBTYPE_CF_END_ACK 0xf0
+/* for TYPE_DATA (bit combination) */
+#define IEEE80211_FC0_SUBTYPE_DATA 0x00
+#define IEEE80211_FC0_SUBTYPE_CF_ACK 0x10
+#define IEEE80211_FC0_SUBTYPE_CF_POLL 0x20
+#define IEEE80211_FC0_SUBTYPE_CF_ACPL 0x30
+#define IEEE80211_FC0_SUBTYPE_NODATA 0x40
+#define IEEE80211_FC0_SUBTYPE_CFACK 0x50
+#define IEEE80211_FC0_SUBTYPE_CFPOLL 0x60
+#define IEEE80211_FC0_SUBTYPE_CF_ACK_CF_ACK 0x70
+#define IEEE80211_FC0_SUBTYPE_QOS 0x80
+#define IEEE80211_FC0_SUBTYPE_QOS_NULL 0xc0
+
+#define IEEE80211_FC1_DIR_MASK 0x03
+#define IEEE80211_FC1_DIR_NODS 0x00 /* STA->STA */
+#define IEEE80211_FC1_DIR_TODS 0x01 /* STA->AP */
+#define IEEE80211_FC1_DIR_FROMDS 0x02 /* AP ->STA */
+#define IEEE80211_FC1_DIR_DSTODS 0x03 /* AP ->AP */
+
+#define IEEE80211_FC1_MORE_FRAG 0x04
+#define IEEE80211_FC1_RETRY 0x08
+#define IEEE80211_FC1_PWR_MGT 0x10
+#define IEEE80211_FC1_MORE_DATA 0x20
+#define IEEE80211_FC1_PROT 0x40
+#define IEEE80211_FC1_ORDER 0x80
+
+#define IEEE80211_SEQ_FRAG_MASK 0x000f
+#define IEEE80211_SEQ_FRAG_SHIFT 0
+#define IEEE80211_SEQ_SEQ_MASK 0xfff0
+#define IEEE80211_SEQ_SEQ_SHIFT 4
+
+#define IEEE80211_SEQ_LEQ(a,b) ((int)((a)-(b)) <= 0)
+
+#define IEEE80211_NWID_LEN 32
+
+#define IEEE80211_QOS_TXOP 0x00ff
+/* bit 8 is reserved */
+#define IEEE80211_QOS_ACKPOLICY 0x60
+#define IEEE80211_QOS_ACKPOLICY_S 5
+#define IEEE80211_QOS_EOSP 0x10
+#define IEEE80211_QOS_EOSP_S 4
+#define IEEE80211_QOS_TID 0x0f
+
+/*
+ * Country/Region Codes from MS WINNLS.H
+ * Numbering from ISO 3166
+ * XXX belongs elsewhere
+ */
+enum CountryCode {
+ CTRY_ALBANIA = 8, /* Albania */
+ CTRY_ALGERIA = 12, /* Algeria */
+ CTRY_ARGENTINA = 32, /* Argentina */
+ CTRY_ARMENIA = 51, /* Armenia */
+ CTRY_AUSTRALIA = 36, /* Australia */
+ CTRY_AUSTRIA = 40, /* Austria */
+ CTRY_AZERBAIJAN = 31, /* Azerbaijan */
+ CTRY_BAHRAIN = 48, /* Bahrain */
+ CTRY_BELARUS = 112, /* Belarus */
+ CTRY_BELGIUM = 56, /* Belgium */
+ CTRY_BELIZE = 84, /* Belize */
+ CTRY_BOLIVIA = 68, /* Bolivia */
+ CTRY_BRAZIL = 76, /* Brazil */
+ CTRY_BRUNEI_DARUSSALAM = 96, /* Brunei Darussalam */
+ CTRY_BULGARIA = 100, /* Bulgaria */
+ CTRY_CANADA = 124, /* Canada */
+ CTRY_CHILE = 152, /* Chile */
+ CTRY_CHINA = 156, /* People's Republic of China */
+ CTRY_COLOMBIA = 170, /* Colombia */
+ CTRY_COSTA_RICA = 188, /* Costa Rica */
+ CTRY_CROATIA = 191, /* Croatia */
+ CTRY_CYPRUS = 196,
+ CTRY_CZECH = 203, /* Czech Republic */
+ CTRY_DENMARK = 208, /* Denmark */
+ CTRY_DOMINICAN_REPUBLIC = 214, /* Dominican Republic */
+ CTRY_ECUADOR = 218, /* Ecuador */
+ CTRY_EGYPT = 818, /* Egypt */
+ CTRY_EL_SALVADOR = 222, /* El Salvador */
+ CTRY_ESTONIA = 233, /* Estonia */
+ CTRY_FAEROE_ISLANDS = 234, /* Faeroe Islands */
+ CTRY_FINLAND = 246, /* Finland */
+ CTRY_FRANCE = 250, /* France */
+ CTRY_FRANCE2 = 255, /* France2 */
+ CTRY_GEORGIA = 268, /* Georgia */
+ CTRY_GERMANY = 276, /* Germany */
+ CTRY_GREECE = 300, /* Greece */
+ CTRY_GUATEMALA = 320, /* Guatemala */
+ CTRY_HONDURAS = 340, /* Honduras */
+ CTRY_HONG_KONG = 344, /* Hong Kong S.A.R., P.R.C. */
+ CTRY_HUNGARY = 348, /* Hungary */
+ CTRY_ICELAND = 352, /* Iceland */
+ CTRY_INDIA = 356, /* India */
+ CTRY_INDONESIA = 360, /* Indonesia */
+ CTRY_IRAN = 364, /* Iran */
+ CTRY_IRAQ = 368, /* Iraq */
+ CTRY_IRELAND = 372, /* Ireland */
+ CTRY_ISRAEL = 376, /* Israel */
+ CTRY_ITALY = 380, /* Italy */
+ CTRY_JAMAICA = 388, /* Jamaica */
+ CTRY_JAPAN = 392, /* Japan */
+ CTRY_JAPAN1 = 393, /* Japan (JP1) */
+ CTRY_JAPAN2 = 394, /* Japan (JP0) */
+ CTRY_JAPAN3 = 395, /* Japan (JP1-1) */
+ CTRY_JAPAN4 = 396, /* Japan (JE1) */
+ CTRY_JAPAN5 = 397, /* Japan (JE2) */
+ CTRY_JAPAN6 = 399, /* Japan (JP6) */
+ CTRY_JAPAN7 = 900, /* Japan */
+ CTRY_JAPAN8 = 901, /* Japan */
+ CTRY_JAPAN9 = 902, /* Japan */
+ CTRY_JAPAN10 = 903, /* Japan */
+ CTRY_JAPAN11 = 904, /* Japan */
+ CTRY_JAPAN12 = 905, /* Japan */
+ CTRY_JAPAN13 = 906, /* Japan */
+ CTRY_JAPAN14 = 907, /* Japan */
+ CTRY_JAPAN15 = 908, /* Japan */
+ CTRY_JAPAN16 = 909, /* Japan */
+ CTRY_JAPAN17 = 910, /* Japan */
+ CTRY_JAPAN18 = 911, /* Japan */
+ CTRY_JAPAN19 = 912, /* Japan */
+ CTRY_JAPAN20 = 913, /* Japan */
+ CTRY_JAPAN21 = 914, /* Japan */
+ CTRY_JAPAN22 = 915, /* Japan */
+ CTRY_JAPAN23 = 916, /* Japan */
+ CTRY_JAPAN24 = 917, /* Japan */
+ CTRY_JAPAN25 = 918, /* Japan */
+ CTRY_JAPAN26 = 919, /* Japan */
+ CTRY_JAPAN27 = 920, /* Japan */
+ CTRY_JAPAN28 = 921, /* Japan */
+ CTRY_JAPAN29 = 922, /* Japan */
+ CTRY_JAPAN30 = 923, /* Japan */
+ CTRY_JAPAN31 = 924, /* Japan */
+ CTRY_JAPAN32 = 925, /* Japan */
+ CTRY_JAPAN33 = 926, /* Japan */
+ CTRY_JAPAN34 = 927, /* Japan */
+ CTRY_JAPAN35 = 928, /* Japan */
+ CTRY_JAPAN36 = 929, /* Japan */
+ CTRY_JAPAN37 = 930, /* Japan */
+ CTRY_JAPAN38 = 931, /* Japan */
+ CTRY_JAPAN39 = 932, /* Japan */
+ CTRY_JAPAN40 = 933, /* Japan */
+ CTRY_JAPAN41 = 934, /* Japan */
+ CTRY_JAPAN42 = 935, /* Japan */
+ CTRY_JAPAN43 = 936, /* Japan */
+ CTRY_JAPAN44 = 937, /* Japan */
+ CTRY_JAPAN45 = 938, /* Japan */
+ CTRY_JAPAN46 = 939, /* Japan */
+ CTRY_JAPAN47 = 940, /* Japan */
+ CTRY_JAPAN48 = 941, /* Japan */
+ CTRY_JORDAN = 400, /* Jordan */
+ CTRY_KAZAKHSTAN = 398, /* Kazakhstan */
+ CTRY_KENYA = 404, /* Kenya */
+ CTRY_KOREA_NORTH = 408, /* North Korea */
+ CTRY_KOREA_ROC = 410, /* South Korea */
+ CTRY_KOREA_ROC2 = 411, /* South Korea */
+ CTRY_KUWAIT = 414, /* Kuwait */
+ CTRY_LATVIA = 428, /* Latvia */
+ CTRY_LEBANON = 422, /* Lebanon */
+ CTRY_LIBYA = 434, /* Libya */
+ CTRY_LIECHTENSTEIN = 438, /* Liechtenstein */
+ CTRY_LITHUANIA = 440, /* Lithuania */
+ CTRY_LUXEMBOURG = 442, /* Luxembourg */
+ CTRY_MACAU = 446, /* Macau */
+ CTRY_MACEDONIA = 807, /* the Former Yugoslav Republic of Macedonia */
+ CTRY_MALAYSIA = 458, /* Malaysia */
+ CTRY_MEXICO = 484, /* Mexico */
+ CTRY_MONACO = 492, /* Principality of Monaco */
+ CTRY_MOROCCO = 504, /* Morocco */
+ CTRY_NETHERLANDS = 528, /* Netherlands */
+ CTRY_NEW_ZEALAND = 554, /* New Zealand */
+ CTRY_NICARAGUA = 558, /* Nicaragua */
+ CTRY_NORWAY = 578, /* Norway */
+ CTRY_OMAN = 512, /* Oman */
+ CTRY_PAKISTAN = 586, /* Islamic Republic of Pakistan */
+ CTRY_PANAMA = 591, /* Panama */
+ CTRY_PARAGUAY = 600, /* Paraguay */
+ CTRY_PERU = 604, /* Peru */
+ CTRY_PHILIPPINES = 608, /* Republic of the Philippines */
+ CTRY_POLAND = 616, /* Poland */
+ CTRY_PORTUGAL = 620, /* Portugal */
+ CTRY_PUERTO_RICO = 630, /* Puerto Rico */
+ CTRY_QATAR = 634, /* Qatar */
+ CTRY_ROMANIA = 642, /* Romania */
+ CTRY_RUSSIA = 643, /* Russia */
+ CTRY_SAUDI_ARABIA = 682, /* Saudi Arabia */
+ CTRY_SINGAPORE = 702, /* Singapore */
+ CTRY_SLOVAKIA = 703, /* Slovak Republic */
+ CTRY_SLOVENIA = 705, /* Slovenia */
+ CTRY_SOUTH_AFRICA = 710, /* South Africa */
+ CTRY_SPAIN = 724, /* Spain */
+ CTRY_SWEDEN = 752, /* Sweden */
+ CTRY_SWITZERLAND = 756, /* Switzerland */
+ CTRY_SYRIA = 760, /* Syria */
+ CTRY_TAIWAN = 158, /* Taiwan */
+ CTRY_THAILAND = 764, /* Thailand */
+ CTRY_TRINIDAD_Y_TOBAGO = 780, /* Trinidad y Tobago */
+ CTRY_TUNISIA = 788, /* Tunisia */
+ CTRY_TURKEY = 792, /* Turkey */
+ CTRY_UAE = 784, /* U.A.E. */
+ CTRY_UKRAINE = 804, /* Ukraine */
+ CTRY_UNITED_KINGDOM = 826, /* United Kingdom */
+ CTRY_UNITED_STATES = 840, /* United States */
+ CTRY_UNITED_STATES_FCC49 = 842, /* United States (Public Safety)*/
+ CTRY_URUGUAY = 858, /* Uruguay */
+ CTRY_UZBEKISTAN = 860, /* Uzbekistan */
+ CTRY_VENEZUELA = 862, /* Venezuela */
+ CTRY_VIET_NAM = 704, /* Viet Nam */
+ CTRY_YEMEN = 887, /* Yemen */
+ CTRY_ZIMBABWE = 716 /* Zimbabwe */
+};
+
+/*
+ * Generic information element
+ */
+struct ieee80211_ie {
+ u_int8_t id;
+ u_int8_t len;
+ u_int8_t info[0];
+} __packed;
+
+/*
+ * Country information element.
+ */
+#define IEEE80211_COUNTRY_MAX_TRIPLETS (83)
+struct ieee80211_ie_country {
+ u_int8_t country_id;
+ u_int8_t country_len;
+ u_int8_t country_str[3];
+ u_int8_t country_triplet[IEEE80211_COUNTRY_MAX_TRIPLETS * 3];
+} __packed;
+
+/*
+ * Channel Switch Announcement information element.
+ */
+struct ieee80211_ie_csa {
+ u_int8_t csa_id; /* IEEE80211_ELEMID_CHANSWITCHANN */
+ u_int8_t csa_len; /* == 3 */
+ u_int8_t csa_mode; /* Channel Switch Mode: 1 == stop transmission until CS */
+ u_int8_t csa_chan; /* New Channel Number */
+ u_int8_t csa_count; /* TBTTs until Channel Switch happens */
+} __packed;
+
+/* minimal Channel Switch Count in the initial announcement */
+#define IEEE80211_CSA_PROTECTION_PERIOD 3
+
+/* maximum allowed deviance of measurement of intervals between CSA in Beacons */
+#define IEEE80211_CSA_SANITY_THRESHOLD 100
+
+
+/* does frame have QoS sequence control data */
+#define IEEE80211_QOS_HAS_SEQ(wh) \
+ (((wh)->i_fc[0] & \
+ (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_QOS)) == \
+ (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS))
+
+#define WME_QOSINFO_COUNT 0x0f /* Mask for Param Set Count field */
+/*
+ * WME/802.11e information element.
+ */
+struct ieee80211_ie_wme {
+ u_int8_t wme_id; /* IEEE80211_ELEMID_VENDOR */
+ u_int8_t wme_len; /* length in bytes */
+ u_int8_t wme_oui[3]; /* 0x00, 0x50, 0xf2 */
+ u_int8_t wme_type; /* OUI type */
+ u_int8_t wme_subtype; /* OUI subtype */
+ u_int8_t wme_version; /* spec revision */
+ u_int8_t wme_info; /* QoS info */
+} __packed;
+
+/*
+ * WME/802.11e Tspec Element
+ */
+struct ieee80211_wme_tspec {
+ u_int8_t ts_id;
+ u_int8_t ts_len;
+ u_int8_t ts_oui[3];
+ u_int8_t ts_oui_type;
+ u_int8_t ts_oui_subtype;
+ u_int8_t ts_version;
+ u_int8_t ts_tsinfo[3];
+ u_int8_t ts_nom_msdu[2];
+ u_int8_t ts_max_msdu[2];
+ u_int8_t ts_min_svc[4];
+ u_int8_t ts_max_svc[4];
+ u_int8_t ts_inactv_intv[4];
+ u_int8_t ts_susp_intv[4];
+ u_int8_t ts_start_svc[4];
+ u_int8_t ts_min_rate[4];
+ u_int8_t ts_mean_rate[4];
+ u_int8_t ts_max_burst[4];
+ u_int8_t ts_min_phy[4];
+ u_int8_t ts_peak_rate[4];
+ u_int8_t ts_delay[4];
+ u_int8_t ts_surplus[2];
+ u_int8_t ts_medium_time[2];
+} __packed;
+
+/*
+ * WME AC parameter field
+ */
+
+struct ieee80211_wme_acparams {
+ u_int8_t acp_aci_aifsn;
+ u_int8_t acp_logcwminmax;
+ u_int16_t acp_txop;
+} __packed;
+
+#define IEEE80211_WME_PARAM_LEN 24
+#define WME_NUM_AC 4 /* 4 AC categories */
+
+#define WME_PARAM_ACI 0x60 /* Mask for ACI field */
+#define WME_PARAM_ACI_S 5 /* Shift for ACI field */
+#define WME_PARAM_ACM 0x10 /* Mask for ACM bit */
+#define WME_PARAM_ACM_S 4 /* Shift for ACM bit */
+#define WME_PARAM_AIFSN 0x0f /* Mask for aifsn field */
+#define WME_PARAM_AIFSN_S 0 /* Shift for aifsn field */
+#define WME_PARAM_LOGCWMIN 0x0f /* Mask for CwMin field (in log) */
+#define WME_PARAM_LOGCWMIN_S 0 /* Shift for CwMin field */
+#define WME_PARAM_LOGCWMAX 0xf0 /* Mask for CwMax field (in log) */
+#define WME_PARAM_LOGCWMAX_S 4 /* Shift for CwMax field */
+
+#define WME_AC_TO_TID(_ac) ( \
+ ((_ac) == WME_AC_VO) ? 6 : \
+ ((_ac) == WME_AC_VI) ? 5 : \
+ ((_ac) == WME_AC_BK) ? 1 : \
+ 0)
+
+#define TID_TO_WME_AC(_tid) ( \
+ ((_tid) < 1) ? WME_AC_BE : \
+ ((_tid) < 3) ? WME_AC_BK : \
+ ((_tid) < 6) ? WME_AC_VI : \
+ WME_AC_VO)
+
+/*
+ * WME Parameter Element
+ */
+
+struct ieee80211_wme_param {
+ u_int8_t param_id;
+ u_int8_t param_len;
+ u_int8_t param_oui[3];
+ u_int8_t param_oui_type;
+ u_int8_t param_oui_sybtype;
+ u_int8_t param_version;
+ u_int8_t param_qosInfo;
+ u_int8_t param_reserved;
+ struct ieee80211_wme_acparams params_acParams[WME_NUM_AC];
+} __packed;
+
+/*
+ * WME U-APSD qos info field defines
+ */
+#define WME_CAPINFO_UAPSD_EN 0x00000080
+#define WME_CAPINFO_UAPSD_VO 0x00000001
+#define WME_CAPINFO_UAPSD_VI 0x00000002
+#define WME_CAPINFO_UAPSD_BK 0x00000004
+#define WME_CAPINFO_UAPSD_BE 0x00000008
+#define WME_CAPINFO_UAPSD_ACFLAGS_SHIFT 0
+#define WME_CAPINFO_UAPSD_ACFLAGS_MASK 0xF
+#define WME_CAPINFO_UAPSD_MAXSP_SHIFT 5
+#define WME_CAPINFO_UAPSD_MAXSP_MASK 0x3
+#define WME_CAPINFO_IE_OFFSET 8
+#define WME_UAPSD_MAXSP(_qosinfo) (((_qosinfo) >> WME_CAPINFO_UAPSD_MAXSP_SHIFT) & WME_CAPINFO_UAPSD_MAXSP_MASK)
+#define WME_UAPSD_AC_ENABLED(_ac, _qosinfo) ( (1<<(3 - (_ac))) & \
+ (((_qosinfo) >> WME_CAPINFO_UAPSD_ACFLAGS_SHIFT) & WME_CAPINFO_UAPSD_ACFLAGS_MASK) )
+
+/*
+ * Atheros Advanced Capability information element.
+ */
+struct ieee80211_ie_athAdvCap {
+ u_int8_t athAdvCap_id; /* IEEE80211_ELEMID_VENDOR */
+ u_int8_t athAdvCap_len; /* length in bytes */
+ u_int8_t athAdvCap_oui[3]; /* 0x00, 0x03, 0x7f */
+ u_int8_t athAdvCap_type; /* OUI type */
+ u_int8_t athAdvCap_subtype; /* OUI subtype */
+ u_int8_t athAdvCap_version; /* spec revision */
+ u_int8_t athAdvCap_capability; /* Capability info */
+ u_int16_t athAdvCap_defKeyIndex;
+} __packed;
+
+/*
+ * Atheros XR information element.
+ */
+struct ieee80211_xr_param {
+ u_int8_t param_id;
+ u_int8_t param_len;
+ u_int8_t param_oui[3];
+ u_int8_t param_oui_type;
+ u_int8_t param_oui_sybtype;
+ u_int8_t param_version;
+ u_int8_t param_Info;
+ u_int8_t param_base_bssid[IEEE80211_ADDR_LEN];
+ u_int8_t param_xr_bssid[IEEE80211_ADDR_LEN];
+ u_int16_t param_xr_beacon_interval;
+ u_int8_t param_base_ath_capability;
+ u_int8_t param_xr_ath_capability;
+} __packed;
+
+/* Atheros capabilities */
+#define IEEE80211_ATHC_TURBOP 0x0001 /* Turbo Prime */
+#define IEEE80211_ATHC_COMP 0x0002 /* Compression */
+#define IEEE80211_ATHC_FF 0x0004 /* Fast Frames */
+#define IEEE80211_ATHC_XR 0x0008 /* Xtended Range support */
+#define IEEE80211_ATHC_AR 0x0010 /* Advanced Radar support */
+#define IEEE80211_ATHC_BURST 0x0020 /* Bursting - not negotiated */
+#define IEEE80211_ATHC_WME 0x0040 /* CWMin tuning */
+#define IEEE80211_ATHC_BOOST 0x0080 /* Boost */
+
+/*
+ * Management Notification Frame
+ */
+struct ieee80211_mnf {
+ u_int8_t mnf_category;
+ u_int8_t mnf_action;
+ u_int8_t mnf_dialog;
+ u_int8_t mnf_status;
+} __packed;
+#define MNF_SETUP_REQ 0
+#define MNF_SETUP_RESP 1
+#define MNF_TEARDOWN 2
+
+/*
+ * Control frames.
+ */
+struct ieee80211_frame_min {
+ u_int8_t i_fc[2];
+ __le16 i_dur;
+ u_int8_t i_addr1[IEEE80211_ADDR_LEN];
+ u_int8_t i_addr2[IEEE80211_ADDR_LEN];
+ /* FCS */
+} __packed;
+
+struct ieee80211_frame_rts {
+ u_int8_t i_fc[2];
+ __le16 i_dur;
+ u_int8_t i_ra[IEEE80211_ADDR_LEN];
+ u_int8_t i_ta[IEEE80211_ADDR_LEN];
+ /* FCS */
+} __packed;
+
+struct ieee80211_frame_cts {
+ u_int8_t i_fc[2];
+ __le16 i_dur;
+ u_int8_t i_ra[IEEE80211_ADDR_LEN];
+ /* FCS */
+} __packed;
+
+struct ieee80211_frame_ack {
+ u_int8_t i_fc[2];
+ __le16 i_dur;
+ u_int8_t i_ra[IEEE80211_ADDR_LEN];
+ /* FCS */
+} __packed;
+
+struct ieee80211_frame_pspoll {
+ u_int8_t i_fc[2];
+ u_int8_t i_aid[2];
+ u_int8_t i_bssid[IEEE80211_ADDR_LEN];
+ u_int8_t i_ta[IEEE80211_ADDR_LEN];
+ /* FCS */
+} __packed;
+
+struct ieee80211_frame_cfend { /* NB: also CF-End+CF-Ack */
+ u_int8_t i_fc[2];
+ __le16 i_dur; /* should be zero */
+ u_int8_t i_ra[IEEE80211_ADDR_LEN];
+ u_int8_t i_bssid[IEEE80211_ADDR_LEN];
+ /* FCS */
+} __packed;
+
+/*
+ * BEACON management packets
+ *
+ * octet timestamp[8]
+ * octet beacon interval[2]
+ * octet capability information[2]
+ * information element
+ * octet elemid
+ * octet length
+ * octet information[length]
+ */
+
+typedef u_int8_t *ieee80211_mgt_beacon_t;
+
+#define IEEE80211_BEACON_INTERVAL(beacon) \
+ ((beacon)[8] | ((beacon)[9] << 8))
+#define IEEE80211_BEACON_CAPABILITY(beacon) \
+ ((beacon)[10] | ((beacon)[11] << 8))
+
+#define IEEE80211_CAPINFO_ESS 0x0001
+#define IEEE80211_CAPINFO_IBSS 0x0002
+#define IEEE80211_CAPINFO_CF_POLLABLE 0x0004
+#define IEEE80211_CAPINFO_CF_POLLREQ 0x0008
+#define IEEE80211_CAPINFO_PRIVACY 0x0010
+#define IEEE80211_CAPINFO_SHORT_PREAMBLE 0x0020
+#define IEEE80211_CAPINFO_PBCC 0x0040
+#define IEEE80211_CAPINFO_CHNL_AGILITY 0x0080
+/* bits 8-9 are reserved (8 now for spectrum management) */
+#define IEEE80211_CAPINFO_SPECTRUM_MGMT 0x0100
+#define IEEE80211_CAPINFO_SHORT_SLOTTIME 0x0400
+#define IEEE80211_CAPINFO_RSN 0x0800
+/* bit 12 is reserved */
+#define IEEE80211_CAPINFO_DSSSOFDM 0x2000
+/* bits 14-15 are reserved */
+
+/*
+ * 802.11i/WPA information element (maximally sized).
+ */
+struct ieee80211_ie_wpa {
+ u_int8_t wpa_id; /* IEEE80211_ELEMID_VENDOR */
+ u_int8_t wpa_len; /* length in bytes */
+ u_int8_t wpa_oui[3]; /* 0x00, 0x50, 0xf2 */
+ u_int8_t wpa_type; /* OUI type */
+ u_int16_t wpa_version; /* spec revision */
+ u_int32_t wpa_mcipher[1]; /* multicast/group key cipher */
+ u_int16_t wpa_uciphercnt; /* # pairwise key ciphers */
+ u_int32_t wpa_uciphers[8]; /* ciphers */
+ u_int16_t wpa_authselcnt; /* authentication selector cnt*/
+ u_int32_t wpa_authsels[8]; /* selectors */
+ u_int16_t wpa_caps; /* 802.11i capabilities */
+ u_int16_t wpa_pmkidcnt; /* 802.11i pmkid count */
+ u_int16_t wpa_pmkids[8]; /* 802.11i pmkids */
+} __packed;
+
+/*
+ * Management information element payloads.
+ */
+
+enum {
+ IEEE80211_ELEMID_SSID = 0,
+ IEEE80211_ELEMID_RATES = 1,
+ IEEE80211_ELEMID_FHPARMS = 2,
+ IEEE80211_ELEMID_DSPARMS = 3,
+ IEEE80211_ELEMID_CFPARMS = 4,
+ IEEE80211_ELEMID_TIM = 5,
+ IEEE80211_ELEMID_IBSSPARMS = 6,
+ IEEE80211_ELEMID_COUNTRY = 7,
+ IEEE80211_ELEMID_REQINFO = 10,
+ IEEE80211_ELEMID_CHALLENGE = 16,
+ /* 17-31 reserved for challenge text extension */
+ IEEE80211_ELEMID_PWRCNSTR = 32,
+ IEEE80211_ELEMID_PWRCAP = 33,
+ IEEE80211_ELEMID_TPCREQ = 34,
+ IEEE80211_ELEMID_TPCREP = 35,
+ IEEE80211_ELEMID_SUPPCHAN = 36,
+ IEEE80211_ELEMID_CHANSWITCHANN = 37,
+ IEEE80211_ELEMID_MEASREQ = 38,
+ IEEE80211_ELEMID_MEASREP = 39,
+ IEEE80211_ELEMID_QUIET = 40,
+ IEEE80211_ELEMID_IBSSDFS = 41,
+ IEEE80211_ELEMID_ERP = 42,
+ IEEE80211_ELEMID_RSN = 48,
+ IEEE80211_ELEMID_XRATES = 50,
+ /* 128-129 proprietary elements used by Agere chipsets */
+ IEEE80211_ELEMID_AGERE1 = 128,
+ IEEE80211_ELEMID_AGERE2 = 129,
+ IEEE80211_ELEMID_TPC = 150,
+ IEEE80211_ELEMID_CCKM = 156,
+ IEEE80211_ELEMID_VENDOR = 221, /* vendor private */
+};
+
+#define IEEE80211_CHANSWITCHANN_BYTES 5
+
+struct ieee80211_tim_ie {
+ u_int8_t tim_ie; /* IEEE80211_ELEMID_TIM */
+ u_int8_t tim_len;
+ u_int8_t tim_count; /* DTIM count */
+ u_int8_t tim_period; /* DTIM period */
+ u_int8_t tim_bitctl; /* bitmap control */
+ u_int8_t tim_bitmap[1]; /* variable-length bitmap */
+} __packed;
+
+struct ieee80211_country_ie {
+ u_int8_t ie; /* IEEE80211_ELEMID_COUNTRY */
+ u_int8_t len;
+ u_int8_t cc[3]; /* ISO CC+(I)ndoor/(O)utdoor */
+ struct {
+ u_int8_t schan; /* starting channel */
+ u_int8_t nchan; /* number channels */
+ u_int8_t maxtxpwr; /* tx power cap */
+ } __packed band[4]; /* up to 4 sub bands */
+} __packed;
+
+#define IEEE80211_CHALLENGE_LEN 128
+
+#define IEEE80211_SUPPCHAN_LEN 26
+
+#define IEEE80211_RATE_BASIC 0x80
+#define IEEE80211_RATE_VAL 0x7f
+
+/* EPR information element flags */
+#define IEEE80211_ERP_NON_ERP_PRESENT 0x01
+#define IEEE80211_ERP_USE_PROTECTION 0x02
+#define IEEE80211_ERP_LONG_PREAMBLE 0x04
+
+/* Atheros private advanced capabilities info */
+#define ATHEROS_CAP_TURBO_PRIME 0x01
+#define ATHEROS_CAP_COMPRESSION 0x02
+#define ATHEROS_CAP_FAST_FRAME 0x04
+/* bits 3-6 reserved */
+#define ATHEROS_CAP_BOOST 0x80
+
+#define ATH_OUI 0x7f0300 /* Atheros OUI */
+#define ATH_OUI_TYPE 0x01
+#define ATH_OUI_SUBTYPE 0x01
+#define ATH_OUI_VERSION 0x00
+#define ATH_OUI_TYPE_XR 0x03
+#define ATH_OUI_VER_XR 0x01
+
+#define WPA_OUI 0xf25000
+#define WPA_OUI_TYPE 0x01
+#define WPA_VERSION 1 /* current supported version */
+
+#define WPA_CSE_NULL 0x00
+#define WPA_CSE_WEP40 0x01
+#define WPA_CSE_TKIP 0x02
+#define WPA_CSE_CCMP 0x04
+#define WPA_CSE_WEP104 0x05
+
+#define WPA_ASE_NONE 0x00
+#define WPA_ASE_8021X_UNSPEC 0x01
+#define WPA_ASE_8021X_PSK 0x02
+
+#define RSN_OUI 0xac0f00
+#define RSN_VERSION 1 /* current supported version */
+
+#define RSN_CSE_NULL 0x00
+#define RSN_CSE_WEP40 0x01
+#define RSN_CSE_TKIP 0x02
+#define RSN_CSE_WRAP 0x03
+#define RSN_CSE_CCMP 0x04
+#define RSN_CSE_WEP104 0x05
+
+#define RSN_ASE_NONE 0x00
+#define RSN_ASE_8021X_UNSPEC 0x01
+#define RSN_ASE_8021X_PSK 0x02
+
+#define RSN_CAP_PREAUTH 0x01
+
+#define WME_OUI 0xf25000
+#define WME_OUI_TYPE 0x02
+#define WME_INFO_OUI_SUBTYPE 0x00
+#define WME_PARAM_OUI_SUBTYPE 0x01
+#define WME_VERSION 1
+
+/* WME stream classes */
+#define WME_AC_BE 0 /* best effort */
+#define WME_AC_BK 1 /* background */
+#define WME_AC_VI 2 /* video */
+#define WME_AC_VO 3 /* voice */
+
+/*
+ * AUTH management packets
+ *
+ * octet algo[2]
+ * octet seq[2]
+ * octet status[2]
+ * octet chal.id
+ * octet chal.length
+ * octet chal.text[253]
+ */
+
+typedef u_int8_t *ieee80211_mgt_auth_t;
+
+#define IEEE80211_AUTH_ALGORITHM(auth) \
+ ((auth)[0] | ((auth)[1] << 8))
+#define IEEE80211_AUTH_TRANSACTION(auth) \
+ ((auth)[2] | ((auth)[3] << 8))
+#define IEEE80211_AUTH_STATUS(auth) \
+ ((auth)[4] | ((auth)[5] << 8))
+
+#define IEEE80211_AUTH_ALG_OPEN 0x0000
+#define IEEE80211_AUTH_ALG_SHARED 0x0001
+#define IEEE80211_AUTH_ALG_LEAP 0x0080
+
+enum {
+ IEEE80211_AUTH_OPEN_REQUEST = 1,
+ IEEE80211_AUTH_OPEN_RESPONSE = 2,
+};
+
+enum {
+ IEEE80211_AUTH_SHARED_REQUEST = 1,
+ IEEE80211_AUTH_SHARED_CHALLENGE = 2,
+ IEEE80211_AUTH_SHARED_RESPONSE = 3,
+ IEEE80211_AUTH_SHARED_PASS = 4,
+};
+
+/*
+ * Reason codes
+ *
+ * Unlisted codes are reserved
+ */
+
+enum {
+ IEEE80211_REASON_UNSPECIFIED = 1,
+ IEEE80211_REASON_AUTH_EXPIRE = 2,
+ IEEE80211_REASON_AUTH_LEAVE = 3,
+ IEEE80211_REASON_ASSOC_EXPIRE = 4,
+ IEEE80211_REASON_ASSOC_TOOMANY = 5,
+ IEEE80211_REASON_NOT_AUTHED = 6,
+ IEEE80211_REASON_NOT_ASSOCED = 7,
+ IEEE80211_REASON_ASSOC_LEAVE = 8,
+ IEEE80211_REASON_ASSOC_NOT_AUTHED = 9,
+
+ IEEE80211_REASON_RSN_REQUIRED = 11,
+ IEEE80211_REASON_RSN_INCONSISTENT = 12,
+ IEEE80211_REASON_IE_INVALID = 13,
+ IEEE80211_REASON_MIC_FAILURE = 14,
+
+ IEEE80211_STATUS_SUCCESS = 0,
+ IEEE80211_STATUS_UNSPECIFIED = 1,
+ IEEE80211_STATUS_CAPINFO = 10,
+ IEEE80211_STATUS_NOT_ASSOCED = 11,
+ IEEE80211_STATUS_OTHER = 12,
+ IEEE80211_STATUS_ALG = 13,
+ IEEE80211_STATUS_SEQUENCE = 14,
+ IEEE80211_STATUS_CHALLENGE = 15,
+ IEEE80211_STATUS_TIMEOUT = 16,
+ IEEE80211_STATUS_TOOMANY = 17,
+ IEEE80211_STATUS_BASIC_RATE = 18,
+ IEEE80211_STATUS_SP_REQUIRED = 19,
+ IEEE80211_STATUS_PBCC_REQUIRED = 20,
+ IEEE80211_STATUS_CA_REQUIRED = 21,
+ IEEE80211_STATUS_TOO_MANY_STATIONS = 22,
+ IEEE80211_STATUS_RATES = 23,
+ IEEE80211_STATUS_SHORTSLOT_REQUIRED = 25,
+ IEEE80211_STATUS_DSSSOFDM_REQUIRED = 26,
+};
+
+#define IEEE80211_WEP_KEYLEN 5 /* 40bit */
+#define IEEE80211_WEP_IVLEN 3 /* 24bit */
+#define IEEE80211_WEP_KIDLEN 1 /* 1 octet */
+#define IEEE80211_WEP_CRCLEN 4 /* CRC-32 */
+#define IEEE80211_WEP_NKID 4 /* number of key ids */
+
+/*
+ * 802.11i defines an extended IV for use with non-WEP ciphers.
+ * When the EXTIV bit is set in the key id byte an additional
+ * 4 bytes immediately follow the IV for TKIP. For CCMP the
+ * EXTIV bit is likewise set but the 8 bytes represent the
+ * CCMP header rather than IV+extended-IV.
+ */
+#define IEEE80211_WEP_EXTIV 0x20
+#define IEEE80211_WEP_EXTIVLEN 4 /* extended IV length */
+#define IEEE80211_WEP_MICLEN 8 /* trailing MIC */
+
+#define IEEE80211_CRC_LEN 4
+
+/*
+ * Maximum acceptable MTU is:
+ * IEEE80211_MAX_LEN - WEP overhead - CRC -
+ * QoS overhead - RSN/WPA overhead
+ * Min is arbitrarily chosen > IEEE80211_MIN_LEN. The default
+ * mtu is Ethernet-compatible; it's set by ether_ifattach.
+ */
+#define IEEE80211_MTU_MAX 2290
+#define IEEE80211_MTU_MIN 32
+
+#define IEEE80211_MAX_LEN (2300 + IEEE80211_CRC_LEN + \
+ (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN))
+#define IEEE80211_ACK_LEN \
+ (sizeof(struct ieee80211_frame_ack) + IEEE80211_CRC_LEN)
+#define IEEE80211_MIN_LEN \
+ (sizeof(struct ieee80211_frame_min) + IEEE80211_CRC_LEN)
+
+/*
+ * The 802.11 spec says at most 2007 stations may be
+ * associated at once. For most AP's this is way more
+ * than is feasible so we use a default of 128. This
+ * number may be overridden by the driver and/or by
+ * user configuration.
+ */
+#define IEEE80211_AID_MAX 2007
+#define IEEE80211_AID_DEF 128
+
+#define IEEE80211_AID(b) ((b) &~ 0xc000)
+
+/*
+ * RTS frame length parameters. The default is specified in
+ * the 802.11 spec. The max may be wrong for jumbo frames.
+ */
+#define IEEE80211_RTS_DEFAULT 512
+#define IEEE80211_RTS_MIN 1
+#define IEEE80211_RTS_MAX 2346
+
+/*
+ * Regulatory extension identifier for country IE.
+ */
+#define IEEE80211_REG_EXT_ID 201
+
+/*
+ * IEEE 802.11 timer synchronization function (TSF) timestamp length
+ */
+#define IEEE80211_TSF_LEN 8
+
+#endif /* _NET80211_IEEE80211_H_ */
diff --git a/package/librtk-inband/src/include/net80211/ieee80211_crypto.h b/package/librtk-inband/src/include/net80211/ieee80211_crypto.h
new file mode 100644
index 000000000..23d4c052a
--- /dev/null
+++ b/package/librtk-inband/src/include/net80211/ieee80211_crypto.h
@@ -0,0 +1,205 @@
+/*-
+ * Copyright (c) 2001 Atsushi Onoe
+ * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: ieee80211_crypto.h 1441 2006-02-06 16:03:21Z mrenzmann $
+ */
+#ifndef _NET80211_IEEE80211_CRYPTO_H_
+#define _NET80211_IEEE80211_CRYPTO_H_
+
+/*
+ * 802.11 protocol crypto-related definitions.
+ */
+#define IEEE80211_KEYBUF_SIZE 16
+#define IEEE80211_MICBUF_SIZE (8 + 8) /* space for both tx+rx keys */
+#define IEEE80211_TID_SIZE 17 /* total number of TIDs */
+
+/*
+ * Old WEP-style key. Deprecated.
+ */
+struct ieee80211_wepkey {
+ u_int wk_len; /* key length in bytes */
+ u_int8_t wk_key[IEEE80211_KEYBUF_SIZE];
+};
+
+struct ieee80211_cipher;
+
+/*
+ * Crypto key state. There is sufficient room for all supported
+ * ciphers (see below). The underlying ciphers are handled
+ * separately through loadable cipher modules that register with
+ * the generic crypto support. A key has a reference to an instance
+ * of the cipher; any per-key state is hung off wk_private by the
+ * cipher when it is attached. Ciphers are automatically called
+ * to detach and cleanup any such state when the key is deleted.
+ *
+ * The generic crypto support handles encap/decap of cipher-related
+ * frame contents for both hardware- and software-based implementations.
+ * A key requiring software crypto support is automatically flagged and
+ * the cipher is expected to honor this and do the necessary work.
+ * Ciphers such as TKIP may also support mixed hardware/software
+ * encrypt/decrypt and MIC processing.
+ */
+/* XXX need key index typedef */
+/* XXX pack better? */
+/* XXX 48-bit rsc/tsc */
+struct ieee80211_key {
+ u_int8_t wk_keylen; /* key length in bytes */
+ u_int8_t wk_flags;
+#define IEEE80211_KEY_XMIT 0x01 /* key used for xmit */
+#define IEEE80211_KEY_RECV 0x02 /* key used for recv */
+#define IEEE80211_KEY_GROUP 0x04 /* key used for WPA group operation */
+#define IEEE80211_KEY_SWCRYPT 0x10 /* host-based encrypt/decrypt */
+#define IEEE80211_KEY_SWMIC 0x20 /* host-based enmic/demic */
+ u_int16_t wk_keyix; /* key index */
+ u_int8_t wk_key[IEEE80211_KEYBUF_SIZE+IEEE80211_MICBUF_SIZE];
+#define wk_txmic wk_key+IEEE80211_KEYBUF_SIZE+0 /* XXX can't () right */
+#define wk_rxmic wk_key+IEEE80211_KEYBUF_SIZE+8 /* XXX can't () right */
+ u_int64_t wk_keyrsc[IEEE80211_TID_SIZE]; /* key receive sequence counter */
+ u_int64_t wk_keytsc; /* key transmit sequence counter */
+ const struct ieee80211_cipher *wk_cipher;
+ void *wk_private; /* private cipher state */
+};
+#define IEEE80211_KEY_COMMON /* common flags passed in by apps */\
+ (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV | IEEE80211_KEY_GROUP)
+
+/*
+ * NB: these values are ordered carefully; there are lots of
+ * of implications in any reordering. In particular beware
+ * that 4 is not used to avoid conflicting with IEEE80211_F_PRIVACY.
+ */
+#define IEEE80211_CIPHER_WEP 0
+#define IEEE80211_CIPHER_TKIP 1
+#define IEEE80211_CIPHER_AES_OCB 2
+#define IEEE80211_CIPHER_AES_CCM 3
+#define IEEE80211_CIPHER_CKIP 5
+#define IEEE80211_CIPHER_NONE 6 /* pseudo value */
+
+#define IEEE80211_CIPHER_MAX (IEEE80211_CIPHER_NONE+1)
+
+#define IEEE80211_KEYIX_NONE ((u_int16_t) - 1)
+
+#if defined(__KERNEL__) || defined(_KERNEL)
+
+struct ieee80211com;
+struct ieee80211vap;
+struct ieee80211_node;
+struct sk_buff;
+
+void ieee80211_crypto_attach(struct ieee80211com *);
+void ieee80211_crypto_detach(struct ieee80211com *);
+void ieee80211_crypto_vattach(struct ieee80211vap *);
+void ieee80211_crypto_vdetach(struct ieee80211vap *);
+int ieee80211_crypto_newkey(struct ieee80211vap *, int, int,
+ struct ieee80211_key *);
+int ieee80211_crypto_delkey(struct ieee80211vap *, struct ieee80211_key *,
+ struct ieee80211_node *);
+int ieee80211_crypto_setkey(struct ieee80211vap *, struct ieee80211_key *,
+ const u_int8_t macaddr[IEEE80211_ADDR_LEN], struct ieee80211_node *);
+void ieee80211_crypto_delglobalkeys(struct ieee80211vap *);
+
+/*
+ * Template for a supported cipher. Ciphers register with the
+ * crypto code and are typically loaded as separate modules
+ * (the null cipher is always present).
+ * XXX may need refcnts
+ */
+struct ieee80211_cipher {
+ const char *ic_name; /* printable name */
+ u_int ic_cipher; /* IEEE80211_CIPHER_* */
+ u_int ic_header; /* size of privacy header (bytes) */
+ u_int ic_trailer; /* size of privacy trailer (bytes) */
+ u_int ic_miclen; /* size of mic trailer (bytes) */
+ void *(*ic_attach)(struct ieee80211vap *, struct ieee80211_key *);
+ void (*ic_detach)(struct ieee80211_key *);
+ int (*ic_setkey)(struct ieee80211_key *);
+ int (*ic_encap)(struct ieee80211_key *, struct sk_buff *, u_int8_t);
+ int (*ic_decap)(struct ieee80211_key *, struct sk_buff *, int);
+ int (*ic_enmic)(struct ieee80211_key *, struct sk_buff *, int);
+ int (*ic_demic)(struct ieee80211_key *, struct sk_buff *, int);
+};
+extern const struct ieee80211_cipher ieee80211_cipher_none;
+
+void ieee80211_crypto_register(const struct ieee80211_cipher *);
+void ieee80211_crypto_unregister(const struct ieee80211_cipher *);
+int ieee80211_crypto_available(u_int);
+
+struct ieee80211_key *ieee80211_crypto_encap(struct ieee80211_node *,
+ struct sk_buff *);
+struct ieee80211_key *ieee80211_crypto_decap(struct ieee80211_node *,
+ struct sk_buff *, int);
+
+/*
+ * Check and remove any MIC.
+ */
+static __inline int
+ieee80211_crypto_demic(struct ieee80211vap *vap, struct ieee80211_key *k,
+ struct sk_buff *skb, int hdrlen)
+{
+ const struct ieee80211_cipher *cip = k->wk_cipher;
+ return (cip->ic_miclen > 0 ? cip->ic_demic(k, skb, hdrlen) : 1);
+}
+
+/*
+ * Add any MIC.
+ */
+static __inline int
+ieee80211_crypto_enmic(struct ieee80211vap *vap, struct ieee80211_key *k,
+ struct sk_buff *skb, int force)
+{
+ const struct ieee80211_cipher *cip = k->wk_cipher;
+ return (cip->ic_miclen > 0 ? cip->ic_enmic(k, skb, force) : 1);
+}
+
+/*
+ * Reset key state to an unused state. The crypto
+ * key allocation mechanism ensures other state (e.g.
+ * key data) is properly setup before a key is used.
+ */
+static __inline void
+ieee80211_crypto_resetkey(struct ieee80211vap *vap, struct ieee80211_key *k,
+ u_int16_t ix)
+{
+ k->wk_cipher = &ieee80211_cipher_none;;
+ k->wk_private = k->wk_cipher->ic_attach(vap, k);
+ k->wk_keyix = ix;
+ k->wk_flags = IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV;
+}
+
+/*
+ * Crypto-related notification methods.
+ */
+void ieee80211_notify_replay_failure(struct ieee80211vap *,
+ const struct ieee80211_frame *, const struct ieee80211_key *,
+ u_int64_t rsc);
+void ieee80211_notify_michael_failure(struct ieee80211vap *,
+ const struct ieee80211_frame *, u_int keyix);
+#endif /* defined(__KERNEL__) || defined(_KERNEL) */
+#endif /* _NET80211_IEEE80211_CRYPTO_H_ */
diff --git a/package/librtk-inband/src/include/net80211/ieee80211_ioctl.h b/package/librtk-inband/src/include/net80211/ieee80211_ioctl.h
new file mode 100644
index 000000000..51ad90a37
--- /dev/null
+++ b/package/librtk-inband/src/include/net80211/ieee80211_ioctl.h
@@ -0,0 +1,787 @@
+/*-
+ * Copyright (c) 2001 Atsushi Onoe
+ * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: ieee80211_ioctl.h 3313 2008-01-30 21:07:22Z proski $
+ */
+#ifndef _NET80211_IEEE80211_IOCTL_H_
+#define _NET80211_IEEE80211_IOCTL_H_
+
+/*
+ * IEEE 802.11 ioctls.
+ */
+#include <net80211/_ieee80211.h>
+#include <net80211/ieee80211.h>
+#include <net80211/ieee80211_crypto.h>
+
+/*
+ * Per/node (station) statistics available when operating as an AP.
+ */
+struct ieee80211_nodestats {
+ u_int32_t ns_rx_data; /* rx data frames */
+ u_int32_t ns_rx_mgmt; /* rx management frames */
+ u_int32_t ns_rx_ctrl; /* rx control frames */
+ u_int32_t ns_rx_ucast; /* rx unicast frames */
+ u_int32_t ns_rx_mcast; /* rx multi/broadcast frames */
+ u_int64_t ns_rx_bytes; /* rx data count (bytes) */
+ u_int64_t ns_rx_beacons; /* rx beacon frames */
+ u_int32_t ns_rx_proberesp; /* rx probe response frames */
+
+ u_int32_t ns_rx_dup; /* rx discard because it's a dup */
+ u_int32_t ns_rx_noprivacy; /* rx w/ wep but privacy off */
+ u_int32_t ns_rx_wepfail; /* rx wep processing failed */
+ u_int32_t ns_rx_demicfail; /* rx demic failed */
+ u_int32_t ns_rx_decap; /* rx decapsulation failed */
+ u_int32_t ns_rx_defrag; /* rx defragmentation failed */
+ u_int32_t ns_rx_disassoc; /* rx disassociation */
+ u_int32_t ns_rx_deauth; /* rx deauthentication */
+ u_int32_t ns_rx_decryptcrc; /* rx decrypt failed on crc */
+ u_int32_t ns_rx_unauth; /* rx on unauthorized port */
+ u_int32_t ns_rx_unencrypted; /* rx unecrypted w/ privacy */
+
+ u_int32_t ns_tx_data; /* tx data frames */
+ u_int32_t ns_tx_mgmt; /* tx management frames */
+ u_int32_t ns_tx_ucast; /* tx unicast frames */
+ u_int32_t ns_tx_mcast; /* tx multi/broadcast frames */
+ u_int64_t ns_tx_bytes; /* tx data count (bytes) */
+ u_int32_t ns_tx_probereq; /* tx probe request frames */
+ u_int32_t ns_tx_uapsd; /* tx on uapsd queue */
+
+ u_int32_t ns_tx_novlantag; /* tx discard due to no tag */
+ u_int32_t ns_tx_vlanmismatch; /* tx discard due to of bad tag */
+
+ u_int32_t ns_tx_eosplost; /* uapsd EOSP retried out */
+
+ u_int32_t ns_ps_discard; /* ps discard due to of age */
+
+ u_int32_t ns_uapsd_triggers; /* uapsd triggers */
+
+ /* MIB-related state */
+ u_int32_t ns_tx_assoc; /* [re]associations */
+ u_int32_t ns_tx_assoc_fail; /* [re]association failures */
+ u_int32_t ns_tx_auth; /* [re]authentications */
+ u_int32_t ns_tx_auth_fail; /* [re]authentication failures*/
+ u_int32_t ns_tx_deauth; /* deauthentications */
+ u_int32_t ns_tx_deauth_code; /* last deauth reason */
+ u_int32_t ns_tx_disassoc; /* disassociations */
+ u_int32_t ns_tx_disassoc_code; /* last disassociation reason */
+ u_int32_t ns_psq_drops; /* power save queue drops */
+};
+
+/*
+ * Summary statistics.
+ */
+struct ieee80211_stats {
+ u_int32_t is_rx_badversion; /* rx frame with bad version */
+ u_int32_t is_rx_tooshort; /* rx frame too short */
+ u_int32_t is_rx_wrongbss; /* rx from wrong bssid */
+ u_int32_t is_rx_dup; /* rx discard due to it's a dup */
+ u_int32_t is_rx_wrongdir; /* rx w/ wrong direction */
+ u_int32_t is_rx_mcastecho; /* rx discard due to of mcast echo */
+ u_int32_t is_rx_notassoc; /* rx discard due to sta !assoc */
+ u_int32_t is_rx_noprivacy; /* rx w/ wep but privacy off */
+ u_int32_t is_rx_unencrypted; /* rx w/o wep and privacy on */
+ u_int32_t is_rx_wepfail; /* rx wep processing failed */
+ u_int32_t is_rx_decap; /* rx decapsulation failed */
+ u_int32_t is_rx_mgtdiscard; /* rx discard mgt frames */
+ u_int32_t is_rx_ctl; /* rx discard ctrl frames */
+ u_int32_t is_rx_beacon; /* rx beacon frames */
+ u_int32_t is_rx_rstoobig; /* rx rate set truncated */
+ u_int32_t is_rx_elem_missing; /* rx required element missing*/
+ u_int32_t is_rx_elem_toobig; /* rx element too big */
+ u_int32_t is_rx_elem_toosmall; /* rx element too small */
+ u_int32_t is_rx_elem_unknown; /* rx element unknown */
+ u_int32_t is_rx_badchan; /* rx frame w/ invalid chan */
+ u_int32_t is_rx_chanmismatch; /* rx frame chan mismatch */
+ u_int32_t is_rx_nodealloc; /* rx frame dropped */
+ u_int32_t is_rx_ssidmismatch; /* rx frame ssid mismatch */
+ u_int32_t is_rx_auth_unsupported;/* rx w/ unsupported auth alg */
+ u_int32_t is_rx_auth_fail; /* rx sta auth failure */
+ u_int32_t is_rx_auth_countermeasures;/* rx auth discard due to CM */
+ u_int32_t is_rx_assoc_bss; /* rx assoc from wrong bssid */
+ u_int32_t is_rx_assoc_notauth; /* rx assoc w/o auth */
+ u_int32_t is_rx_assoc_capmismatch;/* rx assoc w/ cap mismatch */
+ u_int32_t is_rx_assoc_norate; /* rx assoc w/ no rate match */
+ u_int32_t is_rx_assoc_badwpaie; /* rx assoc w/ bad WPA IE */
+ u_int32_t is_rx_deauth; /* rx deauthentication */
+ u_int32_t is_rx_disassoc; /* rx disassociation */
+ u_int32_t is_rx_badsubtype; /* rx frame w/ unknown subtype*/
+ u_int32_t is_rx_nobuf; /* rx failed for lack of buf */
+ u_int32_t is_rx_decryptcrc; /* rx decrypt failed on crc */
+ u_int32_t is_rx_ahdemo_mgt; /* rx discard ahdemo mgt frame*/
+ u_int32_t is_rx_bad_auth; /* rx bad auth request */
+ u_int32_t is_rx_unauth; /* rx on unauthorized port */
+ u_int32_t is_rx_badkeyid; /* rx w/ incorrect keyid */
+ u_int32_t is_rx_ccmpreplay; /* rx seq# violation (CCMP) */
+ u_int32_t is_rx_ccmpformat; /* rx format bad (CCMP) */
+ u_int32_t is_rx_ccmpmic; /* rx MIC check failed (CCMP) */
+ u_int32_t is_rx_tkipreplay; /* rx seq# violation (TKIP) */
+ u_int32_t is_rx_tkipformat; /* rx format bad (TKIP) */
+ u_int32_t is_rx_tkipmic; /* rx MIC check failed (TKIP) */
+ u_int32_t is_rx_tkipicv; /* rx ICV check failed (TKIP) */
+ u_int32_t is_rx_badcipher; /* rx failed due to of key type */
+ u_int32_t is_rx_nocipherctx; /* rx failed due to key !setup */
+ u_int32_t is_rx_acl; /* rx discard due to of acl policy */
+ u_int32_t is_rx_ffcnt; /* rx fast frames */
+ u_int32_t is_rx_badathtnl; /* driver key alloc failed */
+ u_int32_t is_tx_nobuf; /* tx failed for lack of buf */
+ u_int32_t is_tx_nonode; /* tx failed for no node */
+ u_int32_t is_tx_unknownmgt; /* tx of unknown mgt frame */
+ u_int32_t is_tx_badcipher; /* tx failed due to of key type */
+ u_int32_t is_tx_nodefkey; /* tx failed due to no defkey */
+ u_int32_t is_tx_noheadroom; /* tx failed due to no space */
+ u_int32_t is_tx_ffokcnt; /* tx fast frames sent success */
+ u_int32_t is_tx_fferrcnt; /* tx fast frames sent success */
+ u_int32_t is_scan_active; /* active scans started */
+ u_int32_t is_scan_passive; /* passive scans started */
+ u_int32_t is_node_timeout; /* nodes timed out inactivity */
+ u_int32_t is_crypto_nomem; /* no memory for crypto ctx */
+ u_int32_t is_crypto_tkip; /* tkip crypto done in s/w */
+ u_int32_t is_crypto_tkipenmic; /* tkip en-MIC done in s/w */
+ u_int32_t is_crypto_tkipdemic; /* tkip de-MIC done in s/w */
+ u_int32_t is_crypto_tkipcm; /* tkip counter measures */
+ u_int32_t is_crypto_ccmp; /* ccmp crypto done in s/w */
+ u_int32_t is_crypto_wep; /* wep crypto done in s/w */
+ u_int32_t is_crypto_setkey_cipher;/* cipher rejected key */
+ u_int32_t is_crypto_setkey_nokey;/* no key index for setkey */
+ u_int32_t is_crypto_delkey; /* driver key delete failed */
+ u_int32_t is_crypto_badcipher; /* unknown cipher */
+ u_int32_t is_crypto_nocipher; /* cipher not available */
+ u_int32_t is_crypto_attachfail; /* cipher attach failed */
+ u_int32_t is_crypto_swfallback; /* cipher fallback to s/w */
+ u_int32_t is_crypto_keyfail; /* driver key alloc failed */
+ u_int32_t is_crypto_enmicfail; /* en-MIC failed */
+ u_int32_t is_ibss_capmismatch; /* merge failed-cap mismatch */
+ u_int32_t is_ibss_norate; /* merge failed-rate mismatch */
+ u_int32_t is_ps_unassoc; /* ps-poll for unassoc. sta */
+ u_int32_t is_ps_badaid; /* ps-poll w/ incorrect aid */
+ u_int32_t is_ps_qempty; /* ps-poll w/ nothing to send */
+};
+
+/*
+ * Max size of optional information elements. We artificially
+ * constrain this; it's limited only by the max frame size (and
+ * the max parameter size of the wireless extensions).
+ */
+#define IEEE80211_MAX_OPT_IE 256
+
+/*
+ * WPA/RSN get/set key request. Specify the key/cipher
+ * type and whether the key is to be used for sending and/or
+ * receiving. The key index should be set only when working
+ * with global keys (use IEEE80211_KEYIX_NONE for ``no index'').
+ * Otherwise a unicast/pairwise key is specified by the bssid
+ * (on a station) or mac address (on an ap). They key length
+ * must include any MIC key data; otherwise it should be no
+ more than IEEE80211_KEYBUF_SIZE.
+ */
+#pragma pack(1)
+
+struct ieee80211req_key {
+ u_int8_t ik_type; /* key/cipher type */
+ u_int8_t ik_pad;
+ u_int16_t ik_keyix; /* key index */
+ u_int8_t ik_keylen; /* key length in bytes */
+ u_int8_t ik_flags;
+/* NB: IEEE80211_KEY_XMIT and IEEE80211_KEY_RECV defined elsewhere */
+#define IEEE80211_KEY_DEFAULT 0x80 /* default xmit key */
+ u_int8_t ik_macaddr[IEEE80211_ADDR_LEN];
+ u_int64_t ik_keyrsc; /* key receive sequence counter */ //RTK_WPAS WIFI_WPAS
+ //u_int64_t ik_keytsc; /* key transmit sequence counter */
+ u_int8_t ik_keydata[IEEE80211_KEYBUF_SIZE+IEEE80211_MICBUF_SIZE];
+};
+
+#pragma pack(0)
+
+
+/*
+ * Delete a key either by index or address. Set the index
+ * to IEEE80211_KEYIX_NONE when deleting a unicast key.
+ */
+struct ieee80211req_del_key {
+ u_int8_t idk_keyix; /* key index */
+ u_int8_t idk_macaddr[IEEE80211_ADDR_LEN];
+};
+
+/*
+ * MLME state manipulation request. IEEE80211_MLME_ASSOC
+ * only makes sense when operating as a station. The other
+ * requests can be used when operating as a station or an
+ * ap (to effect a station).
+ */
+struct ieee80211req_mlme {
+ u_int8_t im_op; /* operation to perform */
+#define IEEE80211_MLME_ASSOC 1 /* associate station */
+#define IEEE80211_MLME_DISASSOC 2 /* disassociate station */
+#define IEEE80211_MLME_DEAUTH 3 /* deauthenticate station */
+#define IEEE80211_MLME_AUTHORIZE 4 /* authorize station */
+#define IEEE80211_MLME_UNAUTHORIZE 5 /* unauthorize station */
+#define IEEE80211_MLME_CLEAR_STATS 6 /* clear station statistic */
+ u_int8_t im_ssid_len; /* length of optional ssid */
+ u_int16_t im_reason; /* 802.11 reason code */
+ u_int8_t im_macaddr[IEEE80211_ADDR_LEN];
+ u_int8_t im_ssid[IEEE80211_NWID_LEN];
+};
+
+/*
+ * MAC ACL operations.
+ */
+enum {
+ IEEE80211_MACCMD_POLICY_OPEN = 0, /* set policy: no ACL's */
+ IEEE80211_MACCMD_POLICY_ALLOW = 1, /* set policy: allow traffic */
+ IEEE80211_MACCMD_POLICY_DENY = 2, /* set policy: deny traffic */
+ IEEE80211_MACCMD_FLUSH = 3, /* flush ACL database */
+ IEEE80211_MACCMD_DETACH = 4, /* detach ACL policy */
+};
+
+/*
+ * Set the active channel list. Note this list is
+ * intersected with the available channel list in
+ * calculating the set of channels actually used in
+ * scanning.
+ */
+struct ieee80211req_chanlist {
+ u_int8_t ic_channels[IEEE80211_CHAN_BYTES];
+};
+
+/*
+ * Get the active channel list info.
+ */
+struct ieee80211req_chaninfo {
+ u_int ic_nchans;
+ struct ieee80211_channel ic_chans[IEEE80211_CHAN_MAX];
+};
+
+/*
+ * Retrieve the WPA/RSN information element for an associated station.
+ */
+struct ieee80211req_wpaie {
+ u_int8_t wpa_macaddr[IEEE80211_ADDR_LEN];
+ u_int8_t wpa_ie[IEEE80211_MAX_OPT_IE];
+ u_int8_t rsn_ie[IEEE80211_MAX_OPT_IE];
+
+ u_int8_t wps_ie[IEEE80211_MAX_OPT_IE]; //RTK_HAPD WIFI_HAPD
+
+};
+
+/*
+ * Retrieve per-node statistics.
+ */
+struct ieee80211req_sta_stats {
+ union {
+ /* NB: explicitly force 64-bit alignment */
+ u_int8_t macaddr[IEEE80211_ADDR_LEN];
+ u_int64_t pad;
+ } is_u;
+ struct ieee80211_nodestats is_stats;
+};
+
+/*
+ * Station information block; the mac address is used
+ * to retrieve other data like stats, unicast key, etc.
+ */
+struct ieee80211req_sta_info {
+ u_int16_t isi_len; /* length (mult of 4) */
+ u_int16_t isi_freq; /* MHz */
+ u_int16_t isi_flags; /* channel flags */
+ u_int16_t isi_state; /* state flags */
+ u_int8_t isi_authmode; /* authentication algorithm */
+ u_int8_t isi_rssi;
+ u_int16_t isi_capinfo; /* capabilities */
+ u_int8_t isi_athflags; /* Atheros capabilities */
+ u_int8_t isi_erp; /* ERP element */
+ u_int8_t isi_macaddr[IEEE80211_ADDR_LEN];
+ u_int8_t isi_nrates; /* negotiated rates */
+ u_int8_t isi_rates[IEEE80211_RATE_MAXSIZE];
+ u_int8_t isi_txrate; /* index to isi_rates[] */
+ u_int16_t isi_ie_len; /* IE length */
+ u_int16_t isi_associd; /* assoc response */
+ u_int16_t isi_txpower; /* current tx power */
+ u_int16_t isi_vlan; /* vlan tag */
+ u_int16_t isi_txseqs[17]; /* seq to be transmitted */
+ u_int16_t isi_rxseqs[17]; /* seq previous for qos frames*/
+ u_int16_t isi_inact; /* inactivity timer */
+ u_int8_t isi_uapsd; /* UAPSD queues */
+ u_int8_t isi_opmode; /* sta operating mode */
+
+ /* XXX frag state? */
+ /* variable length IE data */
+};
+
+enum {
+ IEEE80211_STA_OPMODE_NORMAL,
+ IEEE80211_STA_OPMODE_XR
+};
+
+/*
+ * Retrieve per-station information; to retrieve all
+ * specify a mac address of ff:ff:ff:ff:ff:ff.
+ */
+struct ieee80211req_sta_req {
+ union {
+ /* NB: explicitly force 64-bit alignment */
+ u_int8_t macaddr[IEEE80211_ADDR_LEN];
+ u_int64_t pad;
+ } is_u;
+ struct ieee80211req_sta_info info[1]; /* variable length */
+};
+
+/*
+ * Get/set per-station tx power cap.
+ */
+struct ieee80211req_sta_txpow {
+ u_int8_t it_macaddr[IEEE80211_ADDR_LEN];
+ u_int8_t it_txpow;
+};
+
+/*
+ * WME parameters are set and return using i_val and i_len.
+ * i_val holds the value itself. i_len specifies the AC
+ * and, as appropriate, then high bit specifies whether the
+ * operation is to be applied to the BSS or ourself.
+ */
+#define IEEE80211_WMEPARAM_SELF 0x0000 /* parameter applies to self */
+#define IEEE80211_WMEPARAM_BSS 0x8000 /* parameter applies to BSS */
+#define IEEE80211_WMEPARAM_VAL 0x7fff /* parameter value */
+
+/*
+ * Scan result data returned for IEEE80211_IOC_SCAN_RESULTS.
+ */
+struct ieee80211req_scan_result {
+ u_int16_t isr_len; /* length (mult of 4) */
+ u_int16_t isr_freq; /* MHz */
+ u_int16_t isr_flags; /* channel flags */
+ u_int8_t isr_noise;
+ u_int8_t isr_rssi;
+ u_int8_t isr_intval; /* beacon interval */
+ u_int16_t isr_capinfo; /* capabilities */
+ u_int8_t isr_erp; /* ERP element */
+ u_int8_t isr_bssid[IEEE80211_ADDR_LEN];
+ u_int8_t isr_nrates;
+ u_int8_t isr_rates[IEEE80211_RATE_MAXSIZE];
+ u_int8_t isr_ssid_len; /* SSID length */
+ u_int8_t isr_ie_len; /* IE length */
+ u_int8_t isr_pad[5];
+ /* variable length SSID followed by IE data */
+};
+
+#ifdef __FreeBSD__
+/*
+ * FreeBSD-style ioctls.
+ */
+/* the first member must be matched with struct ifreq */
+struct ieee80211req {
+ char i_name[IFNAMSIZ]; /* if_name, e.g. "wi0" */
+ u_int16_t i_type; /* req type */
+ int16_t i_val; /* Index or simple value */
+ int16_t i_len; /* Index or simple value */
+ void *i_data; /* Extra data */
+};
+#define SIOCS80211 _IOW('i', 234, struct ieee80211req)
+#define SIOCG80211 _IOWR('i', 235, struct ieee80211req)
+#define SIOCG80211STATS _IOWR('i', 236, struct ifreq)
+#define SIOC80211IFCREATE _IOWR('i', 237, struct ifreq)
+#define SIOC80211IFDESTROY _IOW('i', 238, struct ifreq)
+
+#define IEEE80211_IOC_SSID 1
+#define IEEE80211_IOC_NUMSSIDS 2
+#define IEEE80211_IOC_WEP 3
+#define IEEE80211_WEP_NOSUP -1
+#define IEEE80211_WEP_OFF 0
+#define IEEE80211_WEP_ON 1
+#define IEEE80211_WEP_MIXED 2
+#define IEEE80211_IOC_WEPKEY 4
+#define IEEE80211_IOC_NUMWEPKEYS 5
+#define IEEE80211_IOC_WEPTXKEY 6
+#define IEEE80211_IOC_AUTHMODE 7
+#define IEEE80211_IOC_STATIONNAME 8
+#define IEEE80211_IOC_CHANNEL 9
+#define IEEE80211_IOC_POWERSAVE 10
+#define IEEE80211_POWERSAVE_NOSUP -1
+#define IEEE80211_POWERSAVE_OFF 0
+#define IEEE80211_POWERSAVE_CAM 1
+#define IEEE80211_POWERSAVE_PSP 2
+#define IEEE80211_POWERSAVE_PSP_CAM 3
+#define IEEE80211_POWERSAVE_ON IEEE80211_POWERSAVE_CAM
+#define IEEE80211_IOC_POWERSAVESLEEP 11
+#define IEEE80211_IOC_RTSTHRESHOLD 12
+#define IEEE80211_IOC_PROTMODE 13
+#define IEEE80211_PROTMODE_OFF 0
+#define IEEE80211_PROTMODE_CTS 1
+#define IEEE80211_PROTMODE_RTSCTS 2
+#define IEEE80211_IOC_TXPOWER 14 /* global tx power limit */
+#define IEEE80211_IOC_BSSID 15
+#define IEEE80211_IOC_ROAMING 16 /* roaming mode */
+#define IEEE80211_IOC_PRIVACY 17 /* privacy invoked */
+#define IEEE80211_IOC_DROPUNENCRYPTED 18 /* discard unencrypted frames */
+#define IEEE80211_IOC_WPAKEY 19
+#define IEEE80211_IOC_DELKEY 20
+#define IEEE80211_IOC_MLME 21
+#define IEEE80211_IOC_OPTIE 22 /* optional info. element */
+#define IEEE80211_IOC_SCAN_REQ 23
+#define IEEE80211_IOC_SCAN_RESULTS 24
+#define IEEE80211_IOC_COUNTERMEASURES 25 /* WPA/TKIP countermeasures */
+#define IEEE80211_IOC_WPA 26 /* WPA mode (0,1,2) */
+#define IEEE80211_IOC_CHANLIST 27 /* channel list */
+#define IEEE80211_IOC_WME 28 /* WME mode (on, off) */
+#define IEEE80211_IOC_HIDESSID 29 /* hide SSID mode (on, off) */
+#define IEEE80211_IOC_APBRIDGE 30 /* AP inter-sta bridging */
+#define IEEE80211_IOC_MCASTCIPHER 31 /* multicast/default cipher */
+#define IEEE80211_IOC_MCASTKEYLEN 32 /* multicast key length */
+#define IEEE80211_IOC_UCASTCIPHERS 33 /* unicast cipher suites */
+#define IEEE80211_IOC_UCASTCIPHER 34 /* unicast cipher */
+#define IEEE80211_IOC_UCASTKEYLEN 35 /* unicast key length */
+#define IEEE80211_IOC_DRIVER_CAPS 36 /* driver capabilities */
+#define IEEE80211_IOC_KEYMGTALGS 37 /* key management algorithms */
+#define IEEE80211_IOC_RSNCAPS 38 /* RSN capabilities */
+#define IEEE80211_IOC_WPAIE 39 /* WPA information element */
+#define IEEE80211_IOC_STA_STATS 40 /* per-station statistics */
+#define IEEE80211_IOC_MACCMD 41 /* MAC ACL operation */
+#define IEEE80211_IOC_TXPOWMAX 43 /* max tx power for channel */
+#define IEEE80211_IOC_STA_TXPOW 44 /* per-station tx power limit */
+#define IEEE80211_IOC_STA_INFO 45 /* station/neighbor info */
+#define IEEE80211_IOC_WME_CWMIN 46 /* WME: ECWmin */
+#define IEEE80211_IOC_WME_CWMAX 47 /* WME: ECWmax */
+#define IEEE80211_IOC_WME_AIFS 48 /* WME: AIFSN */
+#define IEEE80211_IOC_WME_TXOPLIMIT 49 /* WME: txops limit */
+#define IEEE80211_IOC_WME_ACM 50 /* WME: ACM (bss only) */
+#define IEEE80211_IOC_WME_ACKPOLICY 51 /* WME: ACK policy (!bss only)*/
+#define IEEE80211_IOC_DTIM_PERIOD 52 /* DTIM period (beacons) */
+#define IEEE80211_IOC_BEACON_INTERVAL 53 /* beacon interval (ms) */
+#define IEEE80211_IOC_ADDMAC 54 /* add sta to MAC ACL table */
+#define IEEE80211_IOC_DELMAC 55 /* del sta from MAC ACL table */
+#define IEEE80211_IOC_FF 56 /* ATH fast frames (on, off) */
+#define IEEE80211_IOC_TURBOP 57 /* ATH turbo' (on, off) */
+#define IEEE80211_IOC_APPIEBUF 58 /* IE in the management frame */
+#define IEEE80211_IOC_FILTERFRAME 59 /* management frame filter */
+
+/*
+ * Scan result data returned for IEEE80211_IOC_SCAN_RESULTS.
+ */
+struct ieee80211req_scan_result {
+ u_int16_t isr_len; /* length (mult of 4) */
+ u_int16_t isr_freq; /* MHz */
+ u_int16_t isr_flags; /* channel flags */
+ u_int8_t isr_noise;
+ u_int8_t isr_rssi;
+ u_int8_t isr_intval; /* beacon interval */
+ u_int16_t isr_capinfo; /* capabilities */
+ u_int8_t isr_erp; /* ERP element */
+ u_int8_t isr_bssid[IEEE80211_ADDR_LEN];
+ u_int8_t isr_nrates;
+ u_int8_t isr_rates[IEEE80211_RATE_MAXSIZE];
+ u_int8_t isr_ssid_len; /* SSID length */
+ u_int8_t isr_ie_len; /* IE length */
+ u_int8_t isr_pad[5];
+ /* variable length SSID followed by IE data */
+};
+
+#endif /* __FreeBSD__ */
+
+#ifdef __linux__
+/*
+ * Wireless Extensions API, private ioctl interfaces.
+ *
+ * NB: Even-numbered ioctl numbers have set semantics and are privileged!
+ * (regardless of the incorrect comment in wireless.h!)
+ */
+#ifdef __KERNEL__
+#include <linux/if.h>
+#endif
+#define IEEE80211_IOCTL_SETPARAM (SIOCIWFIRSTPRIV+0)
+#define IEEE80211_IOCTL_GETPARAM (SIOCIWFIRSTPRIV+1)
+#define IEEE80211_IOCTL_SETMODE (SIOCIWFIRSTPRIV+2)
+#define IEEE80211_IOCTL_GETMODE (SIOCIWFIRSTPRIV+3)
+#define IEEE80211_IOCTL_SETWMMPARAMS (SIOCIWFIRSTPRIV+4)
+#define IEEE80211_IOCTL_GETWMMPARAMS (SIOCIWFIRSTPRIV+5)
+#define IEEE80211_IOCTL_SETCHANLIST (SIOCIWFIRSTPRIV+6)
+#define IEEE80211_IOCTL_GETCHANLIST (SIOCIWFIRSTPRIV+7)
+#define IEEE80211_IOCTL_CHANSWITCH (SIOCIWFIRSTPRIV+8)
+#define IEEE80211_IOCTL_GET_APPIEBUF (SIOCIWFIRSTPRIV+9)
+#define IEEE80211_IOCTL_SET_APPIEBUF (SIOCIWFIRSTPRIV+10)
+#define IEEE80211_IOCTL_FILTERFRAME (SIOCIWFIRSTPRIV+12)
+#define IEEE80211_IOCTL_GETCHANINFO (SIOCIWFIRSTPRIV+13)
+#define IEEE80211_IOCTL_SETOPTIE (SIOCIWFIRSTPRIV+14)
+#define IEEE80211_IOCTL_GETOPTIE (SIOCIWFIRSTPRIV+15)
+#define IEEE80211_IOCTL_SETMLME (SIOCIWFIRSTPRIV+16)
+#define IEEE80211_IOCTL_SETKEY (SIOCIWFIRSTPRIV+18)
+#define IEEE80211_IOCTL_DELKEY (SIOCIWFIRSTPRIV+20)
+#define IEEE80211_IOCTL_ADDMAC (SIOCIWFIRSTPRIV+22)
+#define IEEE80211_IOCTL_DELMAC (SIOCIWFIRSTPRIV+24)
+#define IEEE80211_IOCTL_WDSADDMAC (SIOCIWFIRSTPRIV+26)
+#define IEEE80211_IOCTL_WDSDELMAC (SIOCIWFIRSTPRIV+28)
+#define IEEE80211_IOCTL_KICKMAC (SIOCIWFIRSTPRIV+30)
+
+enum {
+ IEEE80211_WMMPARAMS_CWMIN = 1,
+ IEEE80211_WMMPARAMS_CWMAX = 2,
+ IEEE80211_WMMPARAMS_AIFS = 3,
+ IEEE80211_WMMPARAMS_TXOPLIMIT = 4,
+ IEEE80211_WMMPARAMS_ACM = 5,
+ IEEE80211_WMMPARAMS_NOACKPOLICY = 6,
+};
+enum {
+ IEEE80211_PARAM_TURBO = 1, /* turbo mode */
+ IEEE80211_PARAM_MODE = 2, /* phy mode (11a, 11b, etc.) */
+ IEEE80211_PARAM_AUTHMODE = 3, /* authentication mode */
+ IEEE80211_PARAM_PROTMODE = 4, /* 802.11g protection */
+ IEEE80211_PARAM_MCASTCIPHER = 5, /* multicast/default cipher */
+ IEEE80211_PARAM_MCASTKEYLEN = 6, /* multicast key length */
+ IEEE80211_PARAM_UCASTCIPHERS = 7, /* unicast cipher suites */
+ IEEE80211_PARAM_UCASTCIPHER = 8, /* unicast cipher */
+ IEEE80211_PARAM_UCASTKEYLEN = 9, /* unicast key length */
+ IEEE80211_PARAM_WPA = 10, /* WPA mode (0,1,2) */
+ IEEE80211_PARAM_ROAMING = 12, /* roaming mode */
+ IEEE80211_PARAM_PRIVACY = 13, /* privacy invoked */
+ IEEE80211_PARAM_COUNTERMEASURES = 14, /* WPA/TKIP countermeasures */
+ IEEE80211_PARAM_DROPUNENCRYPTED = 15, /* discard unencrypted frames */
+ IEEE80211_PARAM_DRIVER_CAPS = 16, /* driver capabilities */
+ IEEE80211_PARAM_MACCMD = 17, /* MAC ACL operation */
+ IEEE80211_PARAM_WMM = 18, /* WMM mode (on, off) */
+ IEEE80211_PARAM_HIDESSID = 19, /* hide SSID mode (on, off) */
+ IEEE80211_PARAM_APBRIDGE = 20, /* AP inter-sta bridging */
+ IEEE80211_PARAM_KEYMGTALGS = 21, /* key management algorithms */
+ IEEE80211_PARAM_RSNCAPS = 22, /* RSN capabilities */
+ IEEE80211_PARAM_INACT = 23, /* station inactivity timeout */
+ IEEE80211_PARAM_INACT_AUTH = 24, /* station auth inact timeout */
+ IEEE80211_PARAM_INACT_INIT = 25, /* station init inact timeout */
+ IEEE80211_PARAM_ABOLT = 26, /* Atheros Adv. Capabilities */
+ IEEE80211_PARAM_DTIM_PERIOD = 28, /* DTIM period (beacons) */
+ IEEE80211_PARAM_BEACON_INTERVAL = 29, /* beacon interval (ms) */
+ IEEE80211_PARAM_DOTH = 30, /* 11.h is on/off */
+ IEEE80211_PARAM_PWRTARGET = 31, /* Current Channel Pwr Constraint */
+ IEEE80211_PARAM_GENREASSOC = 32, /* Generate a reassociation request */
+ IEEE80211_PARAM_COMPRESSION = 33, /* compression */
+ IEEE80211_PARAM_FF = 34, /* fast frames support */
+ IEEE80211_PARAM_XR = 35, /* XR support */
+ IEEE80211_PARAM_BURST = 36, /* burst mode */
+ IEEE80211_PARAM_PUREG = 37, /* pure 11g (no 11b stations) */
+ IEEE80211_PARAM_AR = 38, /* AR support */
+ IEEE80211_PARAM_WDS = 39, /* Enable 4 address processing */
+ IEEE80211_PARAM_BGSCAN = 40, /* bg scanning (on, off) */
+ IEEE80211_PARAM_BGSCAN_IDLE = 41, /* bg scan idle threshold */
+ IEEE80211_PARAM_BGSCAN_INTERVAL = 42, /* bg scan interval */
+ IEEE80211_PARAM_MCAST_RATE = 43, /* Multicast Tx Rate */
+ IEEE80211_PARAM_COVERAGE_CLASS = 44, /* coverage class */
+ IEEE80211_PARAM_COUNTRY_IE = 45, /* enable country IE */
+ IEEE80211_PARAM_SCANVALID = 46, /* scan cache valid threshold */
+ IEEE80211_PARAM_ROAM_RSSI_11A = 47, /* rssi threshold in 11a */
+ IEEE80211_PARAM_ROAM_RSSI_11B = 48, /* rssi threshold in 11b */
+ IEEE80211_PARAM_ROAM_RSSI_11G = 49, /* rssi threshold in 11g */
+ IEEE80211_PARAM_ROAM_RATE_11A = 50, /* tx rate threshold in 11a */
+ IEEE80211_PARAM_ROAM_RATE_11B = 51, /* tx rate threshold in 11b */
+ IEEE80211_PARAM_ROAM_RATE_11G = 52, /* tx rate threshold in 11g */
+ IEEE80211_PARAM_UAPSDINFO = 53, /* value for qos info field */
+ IEEE80211_PARAM_SLEEP = 54, /* force sleep/wake */
+ IEEE80211_PARAM_QOSNULL = 55, /* force sleep/wake */
+ IEEE80211_PARAM_PSPOLL = 56, /* force ps-poll generation (sta only) */
+ IEEE80211_PARAM_EOSPDROP = 57, /* force uapsd EOSP drop (ap only) */
+ IEEE80211_PARAM_MARKDFS = 58, /* mark a dfs interference channel when found */
+ IEEE80211_PARAM_REGCLASS = 59, /* enable regclass ids in country IE */
+ IEEE80211_PARAM_DROPUNENC_EAPOL = 60, /* drop unencrypted eapol frames */
+ IEEE80211_PARAM_SHPREAMBLE = 61, /* Short Preamble */
+};
+
+#define SIOCG80211STATS (SIOCDEVPRIVATE+2)
+/* NB: require in+out parameters so cannot use wireless extensions, yech */
+#define IEEE80211_IOCTL_GETKEY (SIOCDEVPRIVATE+3)
+#define IEEE80211_IOCTL_GETWPAIE (SIOCDEVPRIVATE+4)
+#define IEEE80211_IOCTL_STA_STATS (SIOCDEVPRIVATE+5)
+#define IEEE80211_IOCTL_STA_INFO (SIOCDEVPRIVATE+6)
+#define SIOC80211IFCREATE (SIOCDEVPRIVATE+7)
+#define SIOC80211IFDESTROY (SIOCDEVPRIVATE+8)
+#define IEEE80211_IOCTL_SCAN_RESULTS (SIOCDEVPRIVATE+9)
+
+struct ieee80211_clone_params {
+ char icp_name[IFNAMSIZ]; /* device name */
+ u_int16_t icp_opmode; /* operating mode */
+ u_int16_t icp_flags; /* see below */
+#define IEEE80211_CLONE_BSSID 0x0001 /* allocate unique mac/bssid */
+#define IEEE80211_NO_STABEACONS 0x0002 /* Do not setup the station beacon timers */
+};
+
+/* APPIEBUF related definitions */
+
+/* Management frame type to which application IE is added */
+enum {
+ IEEE80211_APPIE_FRAME_BEACON = 0,
+ IEEE80211_APPIE_FRAME_PROBE_REQ = 1,
+ IEEE80211_APPIE_FRAME_PROBE_RESP = 2,
+ IEEE80211_APPIE_FRAME_ASSOC_REQ = 3,
+ IEEE80211_APPIE_FRAME_ASSOC_RESP = 4,
+ IEEE80211_APPIE_NUM_OF_FRAME = 5
+};
+
+struct ieee80211req_getset_appiebuf {
+ u_int32_t app_frmtype; /* management frame type for which buffer is added */
+ u_int32_t app_buflen; /* application-supplied buffer length */
+ u_int8_t app_buf[0]; /* application-supplied IE(s) */
+};
+
+/* Flags ORed by application to set filter for receiving management frames */
+enum {
+ IEEE80211_FILTER_TYPE_BEACON = 1<<0,
+ IEEE80211_FILTER_TYPE_PROBE_REQ = 1<<1,
+ IEEE80211_FILTER_TYPE_PROBE_RESP = 1<<2,
+ IEEE80211_FILTER_TYPE_ASSOC_REQ = 1<<3,
+ IEEE80211_FILTER_TYPE_ASSOC_RESP = 1<<4,
+ IEEE80211_FILTER_TYPE_AUTH = 1<<5,
+ IEEE80211_FILTER_TYPE_DEAUTH = 1<<6,
+ IEEE80211_FILTER_TYPE_DISASSOC = 1<<7,
+ IEEE80211_FILTER_TYPE_ALL = 0xFF /* used to check the valid filter bits */
+};
+
+struct ieee80211req_set_filter {
+ u_int32_t app_filterype; /* management frame filter type */
+};
+
+
+//RTK_HAPD WIFI_HAPD
+
+#define MAX_2G_CHANNEL_NUM 14
+
+#ifdef CONFIG_RTL8196B_TLD
+#define NUM_ACL 64
+#else
+#define NUM_ACL 32
+#endif
+
+#define MACADDRLEN 6
+
+#pragma pack(1)
+
+struct rtk_hapd_config{
+ unsigned char is_hapd;
+ unsigned int band; // hw_mode, ieee80211n
+ unsigned int channel; //channel
+ unsigned int bcnint; //beacon_int
+ unsigned int dtimperiod; //dtim_period
+ unsigned int stanum; //max_num_sta
+ unsigned int rtsthres; //rts_threshold
+ unsigned int fragthres; //fragm_threshold
+ unsigned int oprates; //supported_rates
+ unsigned int basicrates; //basic_rates
+ unsigned int preamble; //preamble
+ unsigned int aclmode; //macaddr_acl, accept_mac_file, deny_mac_file
+ unsigned int aclnum; //macaddr_acl, accept_mac_file, deny_mac_file
+ unsigned char acladdr[NUM_ACL][MACADDRLEN]; //macaddr_acl, accept_mac_file, deny_mac_file
+ unsigned int hiddenAP; //ignore_broadcast_ssid
+ unsigned int qos_enable; //wmm_enable
+ unsigned int expired_time; //ap_max_inactivity
+ unsigned int block_relay; //bridge_packets
+ unsigned int shortGI20M; // ht_capab
+ unsigned int shortGI40M; // ht_capab
+
+ //Above are for Hostapd owned configurations
+ //=====================================================
+ //Below are for RTK private configurations
+
+ unsigned char pwrlevelCCK_A[MAX_2G_CHANNEL_NUM];
+ unsigned char pwrlevelCCK_B[MAX_2G_CHANNEL_NUM];
+ unsigned char pwrlevelHT40_1S_A[MAX_2G_CHANNEL_NUM];
+ unsigned char pwrlevelHT40_1S_B[MAX_2G_CHANNEL_NUM];
+ unsigned char pwrdiffHT40_2S[MAX_2G_CHANNEL_NUM];
+ unsigned char pwrdiffHT20[MAX_2G_CHANNEL_NUM];
+ unsigned char pwrdiffOFDM[MAX_2G_CHANNEL_NUM];
+ unsigned int phyBandSelect;
+ unsigned int ther;
+ unsigned int swcrypto;
+ unsigned int regdomain;
+ unsigned int autorate;
+ unsigned int fixrate;
+ unsigned int disable_protection;
+ unsigned int disable_olbc;
+ unsigned int deny_legacy;
+ unsigned int opmode;
+ unsigned int vap_enable;
+ unsigned int use40M;
+ unsigned int _2ndchoffset;
+ unsigned int ampdu;
+ unsigned int coexist;
+ unsigned int rssi_dump;
+ unsigned int mp_specific;
+ unsigned int use_ext_pa;
+ unsigned int guest_access;
+ unsigned int macPhyMode;
+
+};
+
+#pragma pack(0)
+
+
+
+#define MAX_WDS_NUM 4
+#define HOSTAPD_MAX_SSID_LEN 32
+
+struct rtk_wds_config {
+ int wdsEnabled;
+ unsigned char macAddr [MAX_WDS_NUM][6];
+ int wdsNum;
+ char ssid[HOSTAPD_MAX_SSID_LEN + 1];
+ int wdsPrivacy;
+ int wdsWepKeyLen;
+ char *wdsWepKey;
+ char *wdsPskPassPhrase;
+};
+
+
+//END --- RTK_HAPD WIFI_HAPD
+
+
+//RTK_WPAS WIFI_WPAS
+
+enum {
+ WPAS_CONFIG_MIB = 1,
+ WPAS_CONFIG_WEPKEY = 2,
+};
+
+#pragma pack(1)
+
+struct rtk_wpas_config {
+ unsigned char is_hapd;
+ unsigned char type;
+ unsigned char bandmode; // 1: selective 2: concurrent
+ unsigned char phymode; // 1: 2.4G 2: 5G
+ unsigned char wep_key[16];
+ int wep_keyidx;
+ int wep_keylen;
+
+};
+
+#pragma pack(0)
+
+
+//END --- RTK_WPAS WIFI_WPAS
+
+
+
+#endif /* __linux__ */
+
+#endif /* _NET80211_IEEE80211_IOCTL_H_ */
diff --git a/package/librtk-inband/src/ioh.c b/package/librtk-inband/src/ioh.c
new file mode 100644
index 000000000..71989dc1b
--- /dev/null
+++ b/package/librtk-inband/src/ioh.c
@@ -0,0 +1,315 @@
+/*
+ * IOH helper functions
+ * Copyright (C)2010, Realtek Semiconductor Corp. All rights reserved
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/ioctl.h>
+
+//#include <linux/if_packet.h>
+#include "ioh.h"
+
+#include <linux/if_arp.h>
+
+int bin2hex(const unsigned char *bin, char *hex, const int len)
+{
+ int i, idx;
+ char hex_char[] = "0123456789ABCDEF";
+
+ for (i=0, idx=0; i<len; i++)
+ {
+ hex[idx++] = hex_char[(bin[i] & 0xf0) >> 4];
+ hex[idx++] = hex_char[bin[i] & 0x0f];
+ }
+
+ hex[idx] = 0;
+ return 0;
+}
+
+int hex2bin(const char *hex, unsigned char *bin, const int len)
+{
+ int i, idx;
+ unsigned char bytes[2];
+
+ for (i=0, idx=0; hex[i]; i++)
+ {
+ if (hex[i & 0x01] == 0)
+ return -1; // hex length != even
+
+ if (hex[i] >= '0' && hex[i] <= '9')
+ bytes[i & 0x01] = hex[i] - '0';
+ else if (hex[i] >= 'A' && hex[i] <= 'F')
+ bytes[i & 0x01] = hex[i] - 'A' + 10;
+ else if (hex[i] >= 'a' && hex[i] <= 'f')
+ bytes[i & 0x01] = hex[i] - 'a' + 10;
+ else
+ return -1; // not hex
+
+ if (i & 0x01)
+ {
+ if (idx >= len)
+ return -1; // out of size
+
+ bin[idx++] = (bytes[0] << 4) | bytes[1];
+ }
+ }
+
+ return 0;
+}
+
+void hex_dump(void *data, int size)
+{
+ /* dumps size bytes of *data to stdout. Looks like:
+ * [0000] 75 6E 6B 6E 6F 77 6E 20
+ * 30 FF 00 00 00 00 39 00 unknown 0.....9.
+ * (in a single line of course)
+ */
+
+ unsigned char *p = data;
+ unsigned char c;
+ int n;
+ char bytestr[4] = {0};
+ char addrstr[10] = {0};
+ char hexstr[ 16*3 + 5] = {0};
+ char charstr[16*1 + 5] = {0};
+ for(n=1;n<=size;n++) {
+ if (n%16 == 1) {
+ /* store address for this line */
+ snprintf(addrstr, sizeof(addrstr), "%.4x",
+ ((unsigned int)p-(unsigned int)data) );
+ }
+
+ c = *p;
+ if (isalnum(c) == 0) {
+ c = '.';
+ }
+
+ /* store hex str (for left side) */
+ snprintf(bytestr, sizeof(bytestr), "%02X ", *p);
+ strncat(hexstr, bytestr, sizeof(hexstr)-strlen(hexstr)-1);
+
+ /* store char str (for right side) */
+ snprintf(bytestr, sizeof(bytestr), "%c", c);
+ strncat(charstr, bytestr, sizeof(charstr)-strlen(charstr)-1);
+
+ if(n%16 == 0) {
+ /* line completed */
+ printf("[%4.4s] %-50.50s %s\n", addrstr, hexstr, charstr);
+ hexstr[0] = 0;
+ charstr[0] = 0;
+ } else if(n%8 == 0) {
+ /* half line: add whitespaces */
+ strncat(hexstr, " ", sizeof(hexstr)-strlen(hexstr)-1);
+ strncat(charstr, " ", sizeof(charstr)-strlen(charstr)-1);
+ }
+ p++; /* next byte */
+ }
+
+ if (strlen(hexstr) > 0) {
+ /* print rest of buffer if not empty */
+ printf("[%4.4s] %-50.50s %s\n", addrstr, hexstr, charstr);
+ }
+}
+
+
+int ioh_open(struct ioh_class *obj, char *dev, char *da,unsigned short eth_type, int debug)
+{
+ struct ifreq ifr;
+ int ifindex;
+
+ strcpy(obj->dev, dev);
+
+ if (da == NULL)
+ ; // da == NULL if iohd
+ else
+ hex2bin(da, obj->dest_mac, ETH_MAC_LEN);
+
+ obj->debug = debug;
+
+ obj->tx_header = (void *) obj->tx_buffer;
+ obj->rx_header = (void *) obj->rx_buffer;
+ obj->tx_data = (unsigned char *) obj->tx_buffer + sizeof(*obj->tx_header);
+ obj->rx_data = (unsigned char *) obj->rx_buffer + sizeof(*obj->rx_header);
+ obj->eth_type = eth_type;
+ // create raw socket
+ obj->sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+ if (obj->sockfd == -1)
+ {
+ perror("socket():");
+ return -1;
+ }
+
+ if (obj->debug)
+ printf("Successfully opened socket: %i\n", obj->sockfd);
+
+ // retrieve ethernet interface index
+ bzero(&ifr, sizeof(ifr));
+ strncpy(ifr.ifr_name, obj->dev, IFNAMSIZ);
+ if (ioctl(obj->sockfd, SIOCGIFINDEX, &ifr) == -1)
+ {
+ perror("SIOCGIFINDEX");
+ return -1;
+ }
+ ifindex = ifr.ifr_ifindex;
+ if (obj->debug)
+ printf("Successfully got interface index: %i\n", ifindex);
+
+ // retrieve corresponding MAC
+ if (ioctl(obj->sockfd, SIOCGIFHWADDR, &ifr) == -1)
+ {
+ perror("SIOCGIFHWADDR");
+ return -1;
+ }
+
+ memcpy(obj->src_mac, ifr.ifr_hwaddr.sa_data, sizeof(obj->src_mac));
+ if (obj->debug)
+ {
+ printf("Successfully got our MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",
+ obj->src_mac[0], obj->src_mac[1], obj->src_mac[2],
+ obj->src_mac[3], obj->src_mac[4], obj->src_mac[5]);
+ }
+
+ // Bind our raw socket to this interface
+ bzero(&obj->socket_address, sizeof(obj->socket_address));
+ obj->socket_address.sll_family = PF_PACKET;
+ obj->socket_address.sll_protocol = htons(obj->eth_type);
+ obj->socket_address.sll_ifindex = ifindex;
+ if((bind(obj->sockfd, (struct sockaddr *) &obj->socket_address,
+ sizeof(obj->socket_address)))== -1)
+ {
+ perror("Error binding socket to interface\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+int ioh_close(struct ioh_class *obj)
+{
+ close(obj->sockfd);
+ return 0;
+}
+
+int ioh_send(struct ioh_class *obj , unsigned int send_len)
+{
+ int sent; // length of sent packet
+
+ //fill pkt header
+ memcpy(obj->tx_header->da, obj->dest_mac, ETH_MAC_LEN);
+ memcpy(obj->tx_header->sa, obj->src_mac, ETH_MAC_LEN);
+ obj->tx_header->eth_type = htons(obj->eth_type);
+
+ obj->socket_address.sll_hatype = ARPHRD_ETHER;
+ obj->socket_address.sll_pkttype = PACKET_OTHERHOST;
+ obj->socket_address.sll_halen = ETH_ALEN;
+ obj->socket_address.sll_addr[0] = obj->dest_mac[0];
+ obj->socket_address.sll_addr[1] = obj->dest_mac[1];
+ obj->socket_address.sll_addr[2] = obj->dest_mac[2];
+ obj->socket_address.sll_addr[3] = obj->dest_mac[3];
+ obj->socket_address.sll_addr[4] = obj->dest_mac[4];
+ obj->socket_address.sll_addr[5] = obj->dest_mac[5];
+ obj->socket_address.sll_addr[6] = 0x00;
+ obj->socket_address.sll_addr[7] = 0x00;
+
+ if (obj->debug)
+ {
+ printf("%s: tx len = %d\n", __FUNCTION__, send_len);
+ hex_dump(obj->tx_buffer, send_len);
+ }
+
+ sent = sendto(obj->sockfd, obj->tx_buffer,
+ send_len, 0,
+ (struct sockaddr*) &obj->socket_address, sizeof(obj->socket_address));
+
+ if (sent < 0)
+ {
+ perror("sendto():");
+ return -1;
+ }
+
+ return sent;
+}
+
+static int check_rcv_header(struct ioh_class *obj,int rx_len)
+{
+ if (rx_len < 0)
+ {
+ perror("check_rcv_header:");
+ return -1;
+ }
+
+ /* obj->rx_header->rrcp_type != RRCP_P_IOH) //mark_inband
+ return -1;*/
+
+ if (obj->rx_header->eth_type != ntohs(obj->eth_type) )
+ return -1;
+#if 0 //mark_inband
+ if (rx_len != ntohs(obj->rx_header->ioh_data_len) + sizeof(*obj->rx_header))
+ {
+ if (ntohs(obj->rx_header->ioh_data_len) + sizeof(*obj->rx_header) <
+ ETH_MIN_FRAME_LEN && rx_len == ETH_MIN_FRAME_LEN)
+ {
+ // its ok for min ethernet packet padding
+ }
+ else
+ {
+ printf("%s: rx len (%d) != %d\n", __FUNCTION__,
+ rx_len, ntohs(obj->rx_header->ioh_data_len) + sizeof(*obj->rx_header));
+ return -1;
+ }
+ }
+#endif
+
+ return rx_len;
+
+}
+
+int ioh_recv(struct ioh_class *obj, int timeout_ms)
+{
+ fd_set rfds;
+ struct timeval timeout;
+ int retval;
+ int rx_len;
+
+ FD_ZERO(&rfds);
+ FD_SET(obj->sockfd, &rfds);
+
+ if (timeout_ms < 0)
+ {
+ retval = select(obj->sockfd + 1, &rfds, NULL, NULL, NULL);
+ }
+ else
+ {
+ timeout.tv_sec = 0;
+ timeout.tv_usec = timeout_ms * 1000;
+ retval = select(obj->sockfd + 1, &rfds, NULL, NULL, &timeout);
+ }
+
+ if (retval && FD_ISSET(obj->sockfd, &rfds))
+ {
+ rx_len = recvfrom(obj->sockfd, obj->rx_buffer,
+ sizeof(obj->rx_buffer), 0, NULL, NULL);
+
+ return check_rcv_header(obj,rx_len);
+ }
+ else if (retval == 0)
+ {
+ if (obj->debug)
+ printf("Timeout!!!\n");
+
+ return -1;
+ }
+ else
+ {
+ perror("select():");
+ return -1;
+ }
+
+ return -2;
+}
+
diff --git a/package/librtk-inband/src/ioh.h b/package/librtk-inband/src/ioh.h
new file mode 100644
index 000000000..d017eab17
--- /dev/null
+++ b/package/librtk-inband/src/ioh.h
@@ -0,0 +1,64 @@
+/*
+ * IOH header
+ * Copyright (C)2010, Realtek Semiconductor Corp. All rights reserved
+ */
+
+
+#ifndef __IOH_H
+#define __IOH_H
+
+#include <netinet/in.h>
+#include <linux/if_ether.h>
+#ifndef __LINUX_IF_PACKET_H
+#include <linux/if_packet.h>
+#endif
+
+#define ETH_MAC_LEN ETH_ALEN /* Octets in one ethernet addr */
+#define ETH_HEADER_LEN ETH_HLEN /* Total octets in header. */
+#define ETH_MIN_FRAME_LEN ETH_ZLEN /* Min. octets in frame sans FCS */
+#define ETH_USER_DATA_LEN ETH_DATA_LEN /* Max. octets in payload */
+#define ETH_MAX_FRAME_LEN ETH_FRAME_LEN /* Max. octets in frame sans FCS */
+
+#define ETH_FRAME_TOTALLEN 1518 /*Header: 14 + User Data: 1500 FCS: 4*/
+
+#ifndef WPAS_INB
+#define WPAS_INB
+#endif
+
+struct ioh_header {
+ unsigned char da[ETH_ALEN];
+ unsigned char sa[ETH_ALEN];
+ unsigned short eth_type;
+};
+
+#define BUF_SIZE ETH_FRAME_TOTALLEN
+
+struct ioh_class {
+ int sockfd;
+ char dev[64];
+ unsigned char src_mac[ETH_MAC_LEN];
+ unsigned char dest_mac[ETH_MAC_LEN];
+ unsigned short eth_type;
+ struct sockaddr_ll socket_address;
+ char tx_buffer[BUF_SIZE];
+ char rx_buffer[BUF_SIZE];
+ struct ioh_header *tx_header;
+ struct ioh_header *rx_header;
+ unsigned char *tx_data;
+ unsigned char *rx_data;
+ int debug;
+};
+
+int ioh_open(struct ioh_class *obj, char *dev, char *da,unsigned short eth_type, int debug);
+int ioh_close(struct ioh_class *obj);
+int ioh_send(struct ioh_class *obj,unsigned int send_len);
+int ioh_recv(struct ioh_class *obj, int timeout_ms);
+
+#define mac2str(mac, str) bin2hex((mac), (str), 6)
+#define str2mac(str, mac) hex2bin((str), (mac), 6)
+
+int bin2hex(const unsigned char *bin, char *hex, const int len);
+int hex2bin(const char *hex, unsigned char *bin, const int len);
+void hex_dump(void *data, int size);
+
+#endif
diff --git a/package/librtk-inband/src/wireless_copy.h b/package/librtk-inband/src/wireless_copy.h
new file mode 100644
index 000000000..d93e0daf5
--- /dev/null
+++ b/package/librtk-inband/src/wireless_copy.h
@@ -0,0 +1,1099 @@
+/* This is based on Linux Wireless Extensions header file from WIRELESS_EXT 18.
+ * I have just removed kernel related headers and added some typedefs etc. to
+ * make this easier to include into user space programs.
+ * Jouni Malinen, 2005-03-12.
+ */
+
+
+/*
+ * This file define a set of standard wireless extensions
+ *
+ * Version : 19 18.3.05
+ *
+ * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
+ * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved.
+ */
+
+#ifndef _LINUX_WIRELESS_H
+#define _LINUX_WIRELESS_H
+
+/************************** DOCUMENTATION **************************/
+/*
+ * Initial APIs (1996 -> onward) :
+ * -----------------------------
+ * Basically, the wireless extensions are for now a set of standard ioctl
+ * call + /proc/net/wireless
+ *
+ * The entry /proc/net/wireless give statistics and information on the
+ * driver.
+ * This is better than having each driver having its entry because
+ * its centralised and we may remove the driver module safely.
+ *
+ * Ioctl are used to configure the driver and issue commands. This is
+ * better than command line options of insmod because we may want to
+ * change dynamically (while the driver is running) some parameters.
+ *
+ * The ioctl mechanimsm are copied from standard devices ioctl.
+ * We have the list of command plus a structure descibing the
+ * data exchanged...
+ * Note that to add these ioctl, I was obliged to modify :
+ * # net/core/dev.c (two place + add include)
+ * # net/ipv4/af_inet.c (one place + add include)
+ *
+ * /proc/net/wireless is a copy of /proc/net/dev.
+ * We have a structure for data passed from the driver to /proc/net/wireless
+ * Too add this, I've modified :
+ * # net/core/dev.c (two other places)
+ * # include/linux/netdevice.h (one place)
+ * # include/linux/proc_fs.h (one place)
+ *
+ * New driver API (2002 -> onward) :
+ * -------------------------------
+ * This file is only concerned with the user space API and common definitions.
+ * The new driver API is defined and documented in :
+ * # include/net/iw_handler.h
+ *
+ * Note as well that /proc/net/wireless implementation has now moved in :
+ * # net/core/wireless.c
+ *
+ * Wireless Events (2002 -> onward) :
+ * --------------------------------
+ * Events are defined at the end of this file, and implemented in :
+ * # net/core/wireless.c
+ *
+ * Other comments :
+ * --------------
+ * Do not add here things that are redundant with other mechanisms
+ * (drivers init, ifconfig, /proc/net/dev, ...) and with are not
+ * wireless specific.
+ *
+ * These wireless extensions are not magic : each driver has to provide
+ * support for them...
+ *
+ * IMPORTANT NOTE : As everything in the kernel, this is very much a
+ * work in progress. Contact me if you have ideas of improvements...
+ */
+
+/***************************** INCLUDES *****************************/
+
+ /* jkm - replaced linux headers with C library headers, added typedefs */
+#if 0
+/* To minimise problems in user space, I might remove those headers
+ * at some point. Jean II */
+#include <linux/types.h> /* for "caddr_t" et al */
+#include <linux/socket.h> /* for "struct sockaddr" et al */
+#include <linux/if.h> /* for IFNAMSIZ and co... */
+#else
+#include <sys/types.h>
+//#include <net/if.h>
+typedef __uint32_t __u32;
+typedef __int32_t __s32;
+typedef __uint16_t __u16;
+typedef __int16_t __s16;
+typedef __uint8_t __u8;
+#ifndef __user
+#define __user
+#endif /* __user */
+#endif
+
+/***************************** VERSION *****************************/
+/*
+ * This constant is used to know the availability of the wireless
+ * extensions and to know which version of wireless extensions it is
+ * (there is some stuff that will be added in the future...)
+ * I just plan to increment with each new version.
+ */
+#define WIRELESS_EXT 19
+
+/*
+ * Changes :
+ *
+ * V2 to V3
+ * --------
+ * Alan Cox start some incompatibles changes. I've integrated a bit more.
+ * - Encryption renamed to Encode to avoid US regulation problems
+ * - Frequency changed from float to struct to avoid problems on old 386
+ *
+ * V3 to V4
+ * --------
+ * - Add sensitivity
+ *
+ * V4 to V5
+ * --------
+ * - Missing encoding definitions in range
+ * - Access points stuff
+ *
+ * V5 to V6
+ * --------
+ * - 802.11 support (ESSID ioctls)
+ *
+ * V6 to V7
+ * --------
+ * - define IW_ESSID_MAX_SIZE and IW_MAX_AP
+ *
+ * V7 to V8
+ * --------
+ * - Changed my e-mail address
+ * - More 802.11 support (nickname, rate, rts, frag)
+ * - List index in frequencies
+ *
+ * V8 to V9
+ * --------
+ * - Support for 'mode of operation' (ad-hoc, managed...)
+ * - Support for unicast and multicast power saving
+ * - Change encoding to support larger tokens (>64 bits)
+ * - Updated iw_params (disable, flags) and use it for NWID
+ * - Extracted iw_point from iwreq for clarity
+ *
+ * V9 to V10
+ * ---------
+ * - Add PM capability to range structure
+ * - Add PM modifier : MAX/MIN/RELATIVE
+ * - Add encoding option : IW_ENCODE_NOKEY
+ * - Add TxPower ioctls (work like TxRate)
+ *
+ * V10 to V11
+ * ----------
+ * - Add WE version in range (help backward/forward compatibility)
+ * - Add retry ioctls (work like PM)
+ *
+ * V11 to V12
+ * ----------
+ * - Add SIOCSIWSTATS to get /proc/net/wireless programatically
+ * - Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space
+ * - Add new statistics (frag, retry, beacon)
+ * - Add average quality (for user space calibration)
+ *
+ * V12 to V13
+ * ----------
+ * - Document creation of new driver API.
+ * - Extract union iwreq_data from struct iwreq (for new driver API).
+ * - Rename SIOCSIWNAME as SIOCSIWCOMMIT
+ *
+ * V13 to V14
+ * ----------
+ * - Wireless Events support : define struct iw_event
+ * - Define additional specific event numbers
+ * - Add "addr" and "param" fields in union iwreq_data
+ * - AP scanning stuff (SIOCSIWSCAN and friends)
+ *
+ * V14 to V15
+ * ----------
+ * - Add IW_PRIV_TYPE_ADDR for struct sockaddr private arg
+ * - Make struct iw_freq signed (both m & e), add explicit padding
+ * - Add IWEVCUSTOM for driver specific event/scanning token
+ * - Add IW_MAX_GET_SPY for driver returning a lot of addresses
+ * - Add IW_TXPOW_RANGE for range of Tx Powers
+ * - Add IWEVREGISTERED & IWEVEXPIRED events for Access Points
+ * - Add IW_MODE_MONITOR for passive monitor
+ *
+ * V15 to V16
+ * ----------
+ * - Increase the number of bitrates in iw_range to 32 (for 802.11g)
+ * - Increase the number of frequencies in iw_range to 32 (for 802.11b+a)
+ * - Reshuffle struct iw_range for increases, add filler
+ * - Increase IW_MAX_AP to 64 for driver returning a lot of addresses
+ * - Remove IW_MAX_GET_SPY because conflict with enhanced spy support
+ * - Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy"
+ * - Add IW_ENCODE_TEMP and iw_range->encoding_login_index
+ *
+ * V16 to V17
+ * ----------
+ * - Add flags to frequency -> auto/fixed
+ * - Document (struct iw_quality *)->updated, add new flags (INVALID)
+ * - Wireless Event capability in struct iw_range
+ * - Add support for relative TxPower (yick !)
+ *
+ * V17 to V18 (From Jouni Malinen <j@w1.fi>)
+ * ----------
+ * - Add support for WPA/WPA2
+ * - Add extended encoding configuration (SIOCSIWENCODEEXT and
+ * SIOCGIWENCODEEXT)
+ * - Add SIOCSIWGENIE/SIOCGIWGENIE
+ * - Add SIOCSIWMLME
+ * - Add SIOCSIWPMKSA
+ * - Add struct iw_range bit field for supported encoding capabilities
+ * - Add optional scan request parameters for SIOCSIWSCAN
+ * - Add SIOCSIWAUTH/SIOCGIWAUTH for setting authentication and WPA
+ * related parameters (extensible up to 4096 parameter values)
+ * - Add wireless events: IWEVGENIE, IWEVMICHAELMICFAILURE,
+ * IWEVASSOCREQIE, IWEVASSOCRESPIE, IWEVPMKIDCAND
+ *
+ * V18 to V19
+ * ----------
+ * - Remove (struct iw_point *)->pointer from events and streams
+ * - Remove header includes to help user space
+ * - Increase IW_ENCODING_TOKEN_MAX from 32 to 64
+ * - Add IW_QUAL_ALL_UPDATED and IW_QUAL_ALL_INVALID macros
+ * - Add explicit flag to tell stats are in dBm : IW_QUAL_DBM
+ * - Add IW_IOCTL_IDX() and IW_EVENT_IDX() macros
+ */
+
+/**************************** CONSTANTS ****************************/
+
+/* -------------------------- IOCTL LIST -------------------------- */
+
+/* Wireless Identification */
+#define SIOCSIWCOMMIT 0x8B00 /* Commit pending changes to driver */
+#define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */
+/* SIOCGIWNAME is used to verify the presence of Wireless Extensions.
+ * Common values : "IEEE 802.11-DS", "IEEE 802.11-FH", "IEEE 802.11b"...
+ * Don't put the name of your driver there, it's useless. */
+
+/* Basic operations */
+#define SIOCSIWNWID 0x8B02 /* set network id (pre-802.11) */
+#define SIOCGIWNWID 0x8B03 /* get network id (the cell) */
+#define SIOCSIWFREQ 0x8B04 /* set channel/frequency (Hz) */
+#define SIOCGIWFREQ 0x8B05 /* get channel/frequency (Hz) */
+#define SIOCSIWMODE 0x8B06 /* set operation mode */
+#define SIOCGIWMODE 0x8B07 /* get operation mode */
+#define SIOCSIWSENS 0x8B08 /* set sensitivity (dBm) */
+#define SIOCGIWSENS 0x8B09 /* get sensitivity (dBm) */
+
+/* Informative stuff */
+#define SIOCSIWRANGE 0x8B0A /* Unused */
+#define SIOCGIWRANGE 0x8B0B /* Get range of parameters */
+#define SIOCSIWPRIV 0x8B0C /* Unused */
+#define SIOCGIWPRIV 0x8B0D /* get private ioctl interface info */
+#define SIOCSIWSTATS 0x8B0E /* Unused */
+#define SIOCGIWSTATS 0x8B0F /* Get /proc/net/wireless stats */
+/* SIOCGIWSTATS is strictly used between user space and the kernel, and
+ * is never passed to the driver (i.e. the driver will never see it). */
+
+/* Spy support (statistics per MAC address - used for Mobile IP support) */
+#define SIOCSIWSPY 0x8B10 /* set spy addresses */
+#define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */
+#define SIOCSIWTHRSPY 0x8B12 /* set spy threshold (spy event) */
+#define SIOCGIWTHRSPY 0x8B13 /* get spy threshold */
+
+/* Access Point manipulation */
+#define SIOCSIWAP 0x8B14 /* set access point MAC addresses */
+#define SIOCGIWAP 0x8B15 /* get access point MAC addresses */
+#define SIOCGIWAPLIST 0x8B17 /* Deprecated in favor of scanning */
+#define SIOCSIWSCAN 0x8B18 /* trigger scanning (list cells) */
+#define SIOCGIWSCAN 0x8B19 /* get scanning results */
+
+/* 802.11 specific support */
+#define SIOCSIWESSID 0x8B1A /* set ESSID (network name) */
+#define SIOCGIWESSID 0x8B1B /* get ESSID */
+#define SIOCSIWNICKN 0x8B1C /* set node name/nickname */
+#define SIOCGIWNICKN 0x8B1D /* get node name/nickname */
+/* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit
+ * within the 'iwreq' structure, so we need to use the 'data' member to
+ * point to a string in user space, like it is done for RANGE... */
+
+/* Other parameters useful in 802.11 and some other devices */
+#define SIOCSIWRATE 0x8B20 /* set default bit rate (bps) */
+#define SIOCGIWRATE 0x8B21 /* get default bit rate (bps) */
+#define SIOCSIWRTS 0x8B22 /* set RTS/CTS threshold (bytes) */
+#define SIOCGIWRTS 0x8B23 /* get RTS/CTS threshold (bytes) */
+#define SIOCSIWFRAG 0x8B24 /* set fragmentation thr (bytes) */
+#define SIOCGIWFRAG 0x8B25 /* get fragmentation thr (bytes) */
+#define SIOCSIWTXPOW 0x8B26 /* set transmit power (dBm) */
+#define SIOCGIWTXPOW 0x8B27 /* get transmit power (dBm) */
+#define SIOCSIWRETRY 0x8B28 /* set retry limits and lifetime */
+#define SIOCGIWRETRY 0x8B29 /* get retry limits and lifetime */
+
+/* Encoding stuff (scrambling, hardware security, WEP...) */
+#define SIOCSIWENCODE 0x8B2A /* set encoding token & mode */
+#define SIOCGIWENCODE 0x8B2B /* get encoding token & mode */
+/* Power saving stuff (power management, unicast and multicast) */
+#define SIOCSIWPOWER 0x8B2C /* set Power Management settings */
+#define SIOCGIWPOWER 0x8B2D /* get Power Management settings */
+
+/* WPA : Generic IEEE 802.11 informatiom element (e.g., for WPA/RSN/WMM).
+ * This ioctl uses struct iw_point and data buffer that includes IE id and len
+ * fields. More than one IE may be included in the request. Setting the generic
+ * IE to empty buffer (len=0) removes the generic IE from the driver. Drivers
+ * are allowed to generate their own WPA/RSN IEs, but in these cases, drivers
+ * are required to report the used IE as a wireless event, e.g., when
+ * associating with an AP. */
+#define SIOCSIWGENIE 0x8B30 /* set generic IE */
+#define SIOCGIWGENIE 0x8B31 /* get generic IE */
+
+/* WPA : IEEE 802.11 MLME requests */
+#define SIOCSIWMLME 0x8B16 /* request MLME operation; uses
+ * struct iw_mlme */
+/* WPA : Authentication mode parameters */
+#define SIOCSIWAUTH 0x8B32 /* set authentication mode params */
+#define SIOCGIWAUTH 0x8B33 /* get authentication mode params */
+
+/* WPA : Extended version of encoding configuration */
+#define SIOCSIWENCODEEXT 0x8B34 /* set encoding token & mode */
+#define SIOCGIWENCODEEXT 0x8B35 /* get encoding token & mode */
+
+/* WPA2 : PMKSA cache management */
+#define SIOCSIWPMKSA 0x8B36 /* PMKSA cache operation */
+
+/* -------------------- DEV PRIVATE IOCTL LIST -------------------- */
+
+/* These 32 ioctl are wireless device private, for 16 commands.
+ * Each driver is free to use them for whatever purpose it chooses,
+ * however the driver *must* export the description of those ioctls
+ * with SIOCGIWPRIV and *must* use arguments as defined below.
+ * If you don't follow those rules, DaveM is going to hate you (reason :
+ * it make mixed 32/64bit operation impossible).
+ */
+#define SIOCIWFIRSTPRIV 0x8BE0
+#define SIOCIWLASTPRIV 0x8BFF
+/* Previously, we were using SIOCDEVPRIVATE, but we now have our
+ * separate range because of collisions with other tools such as
+ * 'mii-tool'.
+ * We now have 32 commands, so a bit more space ;-).
+ * Also, all 'odd' commands are only usable by root and don't return the
+ * content of ifr/iwr to user (but you are not obliged to use the set/get
+ * convention, just use every other two command). More details in iwpriv.c.
+ * And I repeat : you are not forced to use them with iwpriv, but you
+ * must be compliant with it.
+ */
+
+/* ------------------------- IOCTL STUFF ------------------------- */
+
+/* The first and the last (range) */
+#define SIOCIWFIRST 0x8B00
+#define SIOCIWLAST SIOCIWLASTPRIV /* 0x8BFF */
+#define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST)
+
+/* Even : get (world access), odd : set (root access) */
+#define IW_IS_SET(cmd) (!((cmd) & 0x1))
+#define IW_IS_GET(cmd) ((cmd) & 0x1)
+
+/* ----------------------- WIRELESS EVENTS ----------------------- */
+/* Those are *NOT* ioctls, do not issue request on them !!! */
+/* Most events use the same identifier as ioctl requests */
+
+#define IWEVTXDROP 0x8C00 /* Packet dropped to excessive retry */
+#define IWEVQUAL 0x8C01 /* Quality part of statistics (scan) */
+#define IWEVCUSTOM 0x8C02 /* Driver specific ascii string */
+#define IWEVREGISTERED 0x8C03 /* Discovered a new node (AP mode) */
+#define IWEVEXPIRED 0x8C04 /* Expired a node (AP mode) */
+#define IWEVGENIE 0x8C05 /* Generic IE (WPA, RSN, WMM, ..)
+ * (scan results); This includes id and
+ * length fields. One IWEVGENIE may
+ * contain more than one IE. Scan
+ * results may contain one or more
+ * IWEVGENIE events. */
+#define IWEVMICHAELMICFAILURE 0x8C06 /* Michael MIC failure
+ * (struct iw_michaelmicfailure)
+ */
+#define IWEVASSOCREQIE 0x8C07 /* IEs used in (Re)Association Request.
+ * The data includes id and length
+ * fields and may contain more than one
+ * IE. This event is required in
+ * Managed mode if the driver
+ * generates its own WPA/RSN IE. This
+ * should be sent just before
+ * IWEVREGISTERED event for the
+ * association. */
+#define IWEVASSOCRESPIE 0x8C08 /* IEs used in (Re)Association
+ * Response. The data includes id and
+ * length fields and may contain more
+ * than one IE. This may be sent
+ * between IWEVASSOCREQIE and
+ * IWEVREGISTERED events for the
+ * association. */
+#define IWEVPMKIDCAND 0x8C09 /* PMKID candidate for RSN
+ * pre-authentication
+ * (struct iw_pmkid_cand) */
+
+#define IWEVFIRST 0x8C00
+#define IW_EVENT_IDX(cmd) ((cmd) - IWEVFIRST)
+
+/* ------------------------- PRIVATE INFO ------------------------- */
+/*
+ * The following is used with SIOCGIWPRIV. It allow a driver to define
+ * the interface (name, type of data) for its private ioctl.
+ * Privates ioctl are SIOCIWFIRSTPRIV -> SIOCIWLASTPRIV
+ */
+
+#define IW_PRIV_TYPE_MASK 0x7000 /* Type of arguments */
+#define IW_PRIV_TYPE_NONE 0x0000
+#define IW_PRIV_TYPE_BYTE 0x1000 /* Char as number */
+#define IW_PRIV_TYPE_CHAR 0x2000 /* Char as character */
+#define IW_PRIV_TYPE_INT 0x4000 /* 32 bits int */
+#define IW_PRIV_TYPE_FLOAT 0x5000 /* struct iw_freq */
+#define IW_PRIV_TYPE_ADDR 0x6000 /* struct sockaddr */
+
+#define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed number of args */
+
+#define IW_PRIV_SIZE_MASK 0x07FF /* Max number of those args */
+
+/*
+ * Note : if the number of args is fixed and the size < 16 octets,
+ * instead of passing a pointer we will put args in the iwreq struct...
+ */
+
+/* ----------------------- OTHER CONSTANTS ----------------------- */
+
+/* Maximum frequencies in the range struct */
+#define IW_MAX_FREQUENCIES 32
+/* Note : if you have something like 80 frequencies,
+ * don't increase this constant and don't fill the frequency list.
+ * The user will be able to set by channel anyway... */
+
+/* Maximum bit rates in the range struct */
+#define IW_MAX_BITRATES 32
+
+/* Maximum tx powers in the range struct */
+#define IW_MAX_TXPOWER 8
+/* Note : if you more than 8 TXPowers, just set the max and min or
+ * a few of them in the struct iw_range. */
+
+/* Maximum of address that you may set with SPY */
+#define IW_MAX_SPY 8
+
+/* Maximum of address that you may get in the
+ list of access points in range */
+#define IW_MAX_AP 64
+
+/* Maximum size of the ESSID and NICKN strings */
+#define IW_ESSID_MAX_SIZE 32
+
+/* Modes of operation */
+#define IW_MODE_AUTO 0 /* Let the driver decides */
+#define IW_MODE_ADHOC 1 /* Single cell network */
+#define IW_MODE_INFRA 2 /* Multi cell network, roaming, ... */
+#define IW_MODE_MASTER 3 /* Synchronisation master or Access Point */
+#define IW_MODE_REPEAT 4 /* Wireless Repeater (forwarder) */
+#define IW_MODE_SECOND 5 /* Secondary master/repeater (backup) */
+#define IW_MODE_MONITOR 6 /* Passive monitor (listen only) */
+
+/* Statistics flags (bitmask in updated) */
+#define IW_QUAL_QUAL_UPDATED 0x01 /* Value was updated since last read */
+#define IW_QUAL_LEVEL_UPDATED 0x02
+#define IW_QUAL_NOISE_UPDATED 0x04
+#define IW_QUAL_ALL_UPDATED 0x07
+#define IW_QUAL_DBM 0x08 /* Level + Noise are dBm */
+#define IW_QUAL_QUAL_INVALID 0x10 /* Driver doesn't provide value */
+#define IW_QUAL_LEVEL_INVALID 0x20
+#define IW_QUAL_NOISE_INVALID 0x40
+#define IW_QUAL_ALL_INVALID 0x70
+
+/* Frequency flags */
+#define IW_FREQ_AUTO 0x00 /* Let the driver decides */
+#define IW_FREQ_FIXED 0x01 /* Force a specific value */
+
+/* Maximum number of size of encoding token available
+ * they are listed in the range structure */
+#define IW_MAX_ENCODING_SIZES 8
+
+/* Maximum size of the encoding token in bytes */
+#define IW_ENCODING_TOKEN_MAX 64 /* 512 bits (for now) */
+
+/* Flags for encoding (along with the token) */
+#define IW_ENCODE_INDEX 0x00FF /* Token index (if needed) */
+#define IW_ENCODE_FLAGS 0xFF00 /* Flags defined below */
+#define IW_ENCODE_MODE 0xF000 /* Modes defined below */
+#define IW_ENCODE_DISABLED 0x8000 /* Encoding disabled */
+#define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */
+#define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */
+#define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */
+#define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */
+#define IW_ENCODE_TEMP 0x0400 /* Temporary key */
+
+/* Power management flags available (along with the value, if any) */
+#define IW_POWER_ON 0x0000 /* No details... */
+#define IW_POWER_TYPE 0xF000 /* Type of parameter */
+#define IW_POWER_PERIOD 0x1000 /* Value is a period/duration of */
+#define IW_POWER_TIMEOUT 0x2000 /* Value is a timeout (to go asleep) */
+#define IW_POWER_MODE 0x0F00 /* Power Management mode */
+#define IW_POWER_UNICAST_R 0x0100 /* Receive only unicast messages */
+#define IW_POWER_MULTICAST_R 0x0200 /* Receive only multicast messages */
+#define IW_POWER_ALL_R 0x0300 /* Receive all messages though PM */
+#define IW_POWER_FORCE_S 0x0400 /* Force PM procedure for sending unicast */
+#define IW_POWER_REPEATER 0x0800 /* Repeat broadcast messages in PM period */
+#define IW_POWER_MODIFIER 0x000F /* Modify a parameter */
+#define IW_POWER_MIN 0x0001 /* Value is a minimum */
+#define IW_POWER_MAX 0x0002 /* Value is a maximum */
+#define IW_POWER_RELATIVE 0x0004 /* Value is not in seconds/ms/us */
+
+/* Transmit Power flags available */
+#define IW_TXPOW_TYPE 0x00FF /* Type of value */
+#define IW_TXPOW_DBM 0x0000 /* Value is in dBm */
+#define IW_TXPOW_MWATT 0x0001 /* Value is in mW */
+#define IW_TXPOW_RELATIVE 0x0002 /* Value is in arbitrary units */
+#define IW_TXPOW_RANGE 0x1000 /* Range of value between min/max */
+
+/* Retry limits and lifetime flags available */
+#define IW_RETRY_ON 0x0000 /* No details... */
+#define IW_RETRY_TYPE 0xF000 /* Type of parameter */
+#define IW_RETRY_LIMIT 0x1000 /* Maximum number of retries*/
+#define IW_RETRY_LIFETIME 0x2000 /* Maximum duration of retries in us */
+#define IW_RETRY_MODIFIER 0x000F /* Modify a parameter */
+#define IW_RETRY_MIN 0x0001 /* Value is a minimum */
+#define IW_RETRY_MAX 0x0002 /* Value is a maximum */
+#define IW_RETRY_RELATIVE 0x0004 /* Value is not in seconds/ms/us */
+
+/* Scanning request flags */
+#define IW_SCAN_DEFAULT 0x0000 /* Default scan of the driver */
+#define IW_SCAN_ALL_ESSID 0x0001 /* Scan all ESSIDs */
+#define IW_SCAN_THIS_ESSID 0x0002 /* Scan only this ESSID */
+#define IW_SCAN_ALL_FREQ 0x0004 /* Scan all Frequencies */
+#define IW_SCAN_THIS_FREQ 0x0008 /* Scan only this Frequency */
+#define IW_SCAN_ALL_MODE 0x0010 /* Scan all Modes */
+#define IW_SCAN_THIS_MODE 0x0020 /* Scan only this Mode */
+#define IW_SCAN_ALL_RATE 0x0040 /* Scan all Bit-Rates */
+#define IW_SCAN_THIS_RATE 0x0080 /* Scan only this Bit-Rate */
+/* struct iw_scan_req scan_type */
+#define IW_SCAN_TYPE_ACTIVE 0
+#define IW_SCAN_TYPE_PASSIVE 1
+/* Maximum size of returned data */
+#define IW_SCAN_MAX_DATA 4096 /* In bytes */
+
+/* Max number of char in custom event - use multiple of them if needed */
+#define IW_CUSTOM_MAX 256 /* In bytes */
+
+/* Generic information element */
+#define IW_GENERIC_IE_MAX 1024
+
+/* MLME requests (SIOCSIWMLME / struct iw_mlme) */
+#define IW_MLME_DEAUTH 0
+#define IW_MLME_DISASSOC 1
+
+/* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */
+#define IW_AUTH_INDEX 0x0FFF
+#define IW_AUTH_FLAGS 0xF000
+/* SIOCSIWAUTH/SIOCGIWAUTH parameters (0 .. 4095)
+ * (IW_AUTH_INDEX mask in struct iw_param flags; this is the index of the
+ * parameter that is being set/get to; value will be read/written to
+ * struct iw_param value field) */
+#define IW_AUTH_WPA_VERSION 0
+#define IW_AUTH_CIPHER_PAIRWISE 1
+#define IW_AUTH_CIPHER_GROUP 2
+#define IW_AUTH_KEY_MGMT 3
+#define IW_AUTH_TKIP_COUNTERMEASURES 4
+#define IW_AUTH_DROP_UNENCRYPTED 5
+#define IW_AUTH_80211_AUTH_ALG 6
+#define IW_AUTH_WPA_ENABLED 7
+#define IW_AUTH_RX_UNENCRYPTED_EAPOL 8
+#define IW_AUTH_ROAMING_CONTROL 9
+#define IW_AUTH_PRIVACY_INVOKED 10
+#define IW_AUTH_CIPHER_GROUP_MGMT 11
+#define IW_AUTH_MFP 12
+
+/* IW_AUTH_WPA_VERSION values (bit field) */
+#define IW_AUTH_WPA_VERSION_DISABLED 0x00000001
+#define IW_AUTH_WPA_VERSION_WPA 0x00000002
+#define IW_AUTH_WPA_VERSION_WPA2 0x00000004
+
+/* IW_AUTH_PAIRWISE_CIPHER and IW_AUTH_GROUP_CIPHER values (bit field) */
+#define IW_AUTH_CIPHER_NONE 0x00000001
+#define IW_AUTH_CIPHER_WEP40 0x00000002
+#define IW_AUTH_CIPHER_TKIP 0x00000004
+#define IW_AUTH_CIPHER_CCMP 0x00000008
+#define IW_AUTH_CIPHER_WEP104 0x00000010
+
+/* IW_AUTH_KEY_MGMT values (bit field) */
+#define IW_AUTH_KEY_MGMT_802_1X 1
+#define IW_AUTH_KEY_MGMT_PSK 2
+
+/* IW_AUTH_80211_AUTH_ALG values (bit field) */
+#define IW_AUTH_ALG_OPEN_SYSTEM 0x00000001
+#define IW_AUTH_ALG_SHARED_KEY 0x00000002
+#define IW_AUTH_ALG_LEAP 0x00000004
+
+/* IW_AUTH_ROAMING_CONTROL values */
+#define IW_AUTH_ROAMING_ENABLE 0 /* driver/firmware based roaming */
+#define IW_AUTH_ROAMING_DISABLE 1 /* user space program used for roaming
+ * control */
+
+/* IW_AUTH_MFP (management frame protection) values */
+#define IW_AUTH_MFP_DISABLED 0 /* MFP disabled */
+#define IW_AUTH_MFP_OPTIONAL 1 /* MFP optional */
+#define IW_AUTH_MFP_REQUIRED 2 /* MFP required */
+
+/* SIOCSIWENCODEEXT definitions */
+#define IW_ENCODE_SEQ_MAX_SIZE 8
+/* struct iw_encode_ext ->alg */
+#define IW_ENCODE_ALG_NONE 0
+#define IW_ENCODE_ALG_WEP 1
+#define IW_ENCODE_ALG_TKIP 2
+#define IW_ENCODE_ALG_CCMP 3
+#define IW_ENCODE_ALG_PMK 4
+#define IW_ENCODE_ALG_AES_CMAC 5
+/* struct iw_encode_ext ->ext_flags */
+#define IW_ENCODE_EXT_TX_SEQ_VALID 0x00000001
+#define IW_ENCODE_EXT_RX_SEQ_VALID 0x00000002
+#define IW_ENCODE_EXT_GROUP_KEY 0x00000004
+#define IW_ENCODE_EXT_SET_TX_KEY 0x00000008
+
+/* IWEVMICHAELMICFAILURE : struct iw_michaelmicfailure ->flags */
+#define IW_MICFAILURE_KEY_ID 0x00000003 /* Key ID 0..3 */
+#define IW_MICFAILURE_GROUP 0x00000004
+#define IW_MICFAILURE_PAIRWISE 0x00000008
+#define IW_MICFAILURE_STAKEY 0x00000010
+#define IW_MICFAILURE_COUNT 0x00000060 /* 1 or 2 (0 = count not supported)
+ */
+
+/* Bit field values for enc_capa in struct iw_range */
+#define IW_ENC_CAPA_WPA 0x00000001
+#define IW_ENC_CAPA_WPA2 0x00000002
+#define IW_ENC_CAPA_CIPHER_TKIP 0x00000004
+#define IW_ENC_CAPA_CIPHER_CCMP 0x00000008
+#define IW_ENC_CAPA_4WAY_HANDSHAKE 0x00000010
+
+/* Event capability macros - in (struct iw_range *)->event_capa
+ * Because we have more than 32 possible events, we use an array of
+ * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */
+#define IW_EVENT_CAPA_BASE(cmd) ((cmd >= SIOCIWFIRSTPRIV) ? \
+ (cmd - SIOCIWFIRSTPRIV + 0x60) : \
+ (cmd - SIOCSIWCOMMIT))
+#define IW_EVENT_CAPA_INDEX(cmd) (IW_EVENT_CAPA_BASE(cmd) >> 5)
+#define IW_EVENT_CAPA_MASK(cmd) (1 << (IW_EVENT_CAPA_BASE(cmd) & 0x1F))
+/* Event capability constants - event autogenerated by the kernel
+ * This list is valid for most 802.11 devices, customise as needed... */
+#define IW_EVENT_CAPA_K_0 (IW_EVENT_CAPA_MASK(0x8B04) | \
+ IW_EVENT_CAPA_MASK(0x8B06) | \
+ IW_EVENT_CAPA_MASK(0x8B1A))
+#define IW_EVENT_CAPA_K_1 (IW_EVENT_CAPA_MASK(0x8B2A))
+/* "Easy" macro to set events in iw_range (less efficient) */
+#define IW_EVENT_CAPA_SET(event_capa, cmd) (event_capa[IW_EVENT_CAPA_INDEX(cmd)] |= IW_EVENT_CAPA_MASK(cmd))
+#define IW_EVENT_CAPA_SET_KERNEL(event_capa) {event_capa[0] |= IW_EVENT_CAPA_K_0; event_capa[1] |= IW_EVENT_CAPA_K_1; }
+
+
+/****************************** TYPES ******************************/
+
+/* --------------------------- SUBTYPES --------------------------- */
+/*
+ * Generic format for most parameters that fit in an int
+ */
+struct iw_param
+{
+ __s32 value; /* The value of the parameter itself */
+ __u8 fixed; /* Hardware should not use auto select */
+ __u8 disabled; /* Disable the feature */
+ __u16 flags; /* Various specifc flags (if any) */
+};
+
+/*
+ * For all data larger than 16 octets, we need to use a
+ * pointer to memory allocated in user space.
+ */
+struct iw_point
+{
+ void __user *pointer; /* Pointer to the data (in user space) */
+ __u16 length; /* number of fields or size in bytes */
+ __u16 flags; /* Optional params */
+};
+
+/*
+ * A frequency
+ * For numbers lower than 10^9, we encode the number in 'm' and
+ * set 'e' to 0
+ * For number greater than 10^9, we divide it by the lowest power
+ * of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')...
+ * The power of 10 is in 'e', the result of the division is in 'm'.
+ */
+struct iw_freq
+{
+ __s32 m; /* Mantissa */
+ __s16 e; /* Exponent */
+ __u8 i; /* List index (when in range struct) */
+ __u8 flags; /* Flags (fixed/auto) */
+};
+
+/*
+ * Quality of the link
+ */
+struct iw_quality
+{
+ __u8 qual; /* link quality (%retries, SNR,
+ %missed beacons or better...) */
+ __u8 level; /* signal level (dBm) */
+ __u8 noise; /* noise level (dBm) */
+ __u8 updated; /* Flags to know if updated */
+};
+
+/*
+ * Packet discarded in the wireless adapter due to
+ * "wireless" specific problems...
+ * Note : the list of counter and statistics in net_device_stats
+ * is already pretty exhaustive, and you should use that first.
+ * This is only additional stats...
+ */
+struct iw_discarded
+{
+ __u32 nwid; /* Rx : Wrong nwid/essid */
+ __u32 code; /* Rx : Unable to code/decode (WEP) */
+ __u32 fragment; /* Rx : Can't perform MAC reassembly */
+ __u32 retries; /* Tx : Max MAC retries num reached */
+ __u32 misc; /* Others cases */
+};
+
+/*
+ * Packet/Time period missed in the wireless adapter due to
+ * "wireless" specific problems...
+ */
+struct iw_missed
+{
+ __u32 beacon; /* Missed beacons/superframe */
+};
+
+/*
+ * Quality range (for spy threshold)
+ */
+struct iw_thrspy
+{
+ struct sockaddr addr; /* Source address (hw/mac) */
+ struct iw_quality qual; /* Quality of the link */
+ struct iw_quality low; /* Low threshold */
+ struct iw_quality high; /* High threshold */
+};
+
+/*
+ * Optional data for scan request
+ *
+ * Note: these optional parameters are controlling parameters for the
+ * scanning behavior, these do not apply to getting scan results
+ * (SIOCGIWSCAN). Drivers are expected to keep a local BSS table and
+ * provide a merged results with all BSSes even if the previous scan
+ * request limited scanning to a subset, e.g., by specifying an SSID.
+ * Especially, scan results are required to include an entry for the
+ * current BSS if the driver is in Managed mode and associated with an AP.
+ */
+struct iw_scan_req
+{
+ __u8 scan_type; /* IW_SCAN_TYPE_{ACTIVE,PASSIVE} */
+ __u8 essid_len;
+ __u8 num_channels; /* num entries in channel_list;
+ * 0 = scan all allowed channels */
+ __u8 flags; /* reserved as padding; use zero, this may
+ * be used in the future for adding flags
+ * to request different scan behavior */
+ struct sockaddr bssid; /* ff:ff:ff:ff:ff:ff for broadcast BSSID or
+ * individual address of a specific BSS */
+
+ /*
+ * Use this ESSID if IW_SCAN_THIS_ESSID flag is used instead of using
+ * the current ESSID. This allows scan requests for specific ESSID
+ * without having to change the current ESSID and potentially breaking
+ * the current association.
+ */
+ __u8 essid[IW_ESSID_MAX_SIZE];
+
+ /*
+ * Optional parameters for changing the default scanning behavior.
+ * These are based on the MLME-SCAN.request from IEEE Std 802.11.
+ * TU is 1.024 ms. If these are set to 0, driver is expected to use
+ * reasonable default values. min_channel_time defines the time that
+ * will be used to wait for the first reply on each channel. If no
+ * replies are received, next channel will be scanned after this. If
+ * replies are received, total time waited on the channel is defined by
+ * max_channel_time.
+ */
+ __u32 min_channel_time; /* in TU */
+ __u32 max_channel_time; /* in TU */
+
+ struct iw_freq channel_list[IW_MAX_FREQUENCIES];
+};
+
+/* ------------------------- WPA SUPPORT ------------------------- */
+
+/*
+ * Extended data structure for get/set encoding (this is used with
+ * SIOCSIWENCODEEXT/SIOCGIWENCODEEXT. struct iw_point and IW_ENCODE_*
+ * flags are used in the same way as with SIOCSIWENCODE/SIOCGIWENCODE and
+ * only the data contents changes (key data -> this structure, including
+ * key data).
+ *
+ * If the new key is the first group key, it will be set as the default
+ * TX key. Otherwise, default TX key index is only changed if
+ * IW_ENCODE_EXT_SET_TX_KEY flag is set.
+ *
+ * Key will be changed with SIOCSIWENCODEEXT in all cases except for
+ * special "change TX key index" operation which is indicated by setting
+ * key_len = 0 and ext_flags |= IW_ENCODE_EXT_SET_TX_KEY.
+ *
+ * tx_seq/rx_seq are only used when respective
+ * IW_ENCODE_EXT_{TX,RX}_SEQ_VALID flag is set in ext_flags. Normal
+ * TKIP/CCMP operation is to set RX seq with SIOCSIWENCODEEXT and start
+ * TX seq from zero whenever key is changed. SIOCGIWENCODEEXT is normally
+ * used only by an Authenticator (AP or an IBSS station) to get the
+ * current TX sequence number. Using TX_SEQ_VALID for SIOCSIWENCODEEXT and
+ * RX_SEQ_VALID for SIOCGIWENCODEEXT are optional, but can be useful for
+ * debugging/testing.
+ */
+struct iw_encode_ext
+{
+ __u32 ext_flags; /* IW_ENCODE_EXT_* */
+ __u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
+ __u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
+ struct sockaddr addr; /* ff:ff:ff:ff:ff:ff for broadcast/multicast
+ * (group) keys or unicast address for
+ * individual keys */
+ __u16 alg; /* IW_ENCODE_ALG_* */
+ __u16 key_len;
+ __u8 key[0];
+};
+
+/* SIOCSIWMLME data */
+struct iw_mlme
+{
+ __u16 cmd; /* IW_MLME_* */
+ __u16 reason_code;
+ struct sockaddr addr;
+};
+
+/* SIOCSIWPMKSA data */
+#define IW_PMKSA_ADD 1
+#define IW_PMKSA_REMOVE 2
+#define IW_PMKSA_FLUSH 3
+
+#define IW_PMKID_LEN 16
+
+struct iw_pmksa
+{
+ __u32 cmd; /* IW_PMKSA_* */
+ struct sockaddr bssid;
+ __u8 pmkid[IW_PMKID_LEN];
+};
+
+/* IWEVMICHAELMICFAILURE data */
+struct iw_michaelmicfailure
+{
+ __u32 flags;
+ struct sockaddr src_addr;
+ __u8 tsc[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
+};
+
+/* IWEVPMKIDCAND data */
+#define IW_PMKID_CAND_PREAUTH 0x00000001 /* RNS pre-authentication enabled */
+struct iw_pmkid_cand
+{
+ __u32 flags; /* IW_PMKID_CAND_* */
+ __u32 index; /* the smaller the index, the higher the
+ * priority */
+ struct sockaddr bssid;
+};
+
+/* ------------------------ WIRELESS STATS ------------------------ */
+/*
+ * Wireless statistics (used for /proc/net/wireless)
+ */
+struct iw_statistics
+{
+ __u16 status; /* Status
+ * - device dependent for now */
+
+ struct iw_quality qual; /* Quality of the link
+ * (instant/mean/max) */
+ struct iw_discarded discard; /* Packet discarded counts */
+ struct iw_missed miss; /* Packet missed counts */
+};
+
+/* ------------------------ IOCTL REQUEST ------------------------ */
+/*
+ * This structure defines the payload of an ioctl, and is used
+ * below.
+ *
+ * Note that this structure should fit on the memory footprint
+ * of iwreq (which is the same as ifreq), which mean a max size of
+ * 16 octets = 128 bits. Warning, pointers might be 64 bits wide...
+ * You should check this when increasing the structures defined
+ * above in this file...
+ */
+union iwreq_data
+{
+ /* Config - generic */
+ char name[IFNAMSIZ];
+ /* Name : used to verify the presence of wireless extensions.
+ * Name of the protocol/provider... */
+
+ struct iw_point essid; /* Extended network name */
+ struct iw_param nwid; /* network id (or domain - the cell) */
+ struct iw_freq freq; /* frequency or channel :
+ * 0-1000 = channel
+ * > 1000 = frequency in Hz */
+
+ struct iw_param sens; /* signal level threshold */
+ struct iw_param bitrate; /* default bit rate */
+ struct iw_param txpower; /* default transmit power */
+ struct iw_param rts; /* RTS threshold threshold */
+ struct iw_param frag; /* Fragmentation threshold */
+ __u32 mode; /* Operation mode */
+ struct iw_param retry; /* Retry limits & lifetime */
+
+ struct iw_point encoding; /* Encoding stuff : tokens */
+ struct iw_param power; /* PM duration/timeout */
+ struct iw_quality qual; /* Quality part of statistics */
+
+ struct sockaddr ap_addr; /* Access point address */
+ struct sockaddr addr; /* Destination address (hw/mac) */
+
+ struct iw_param param; /* Other small parameters */
+ struct iw_point data; /* Other large parameters */
+};
+
+/*
+ * The structure to exchange data for ioctl.
+ * This structure is the same as 'struct ifreq', but (re)defined for
+ * convenience...
+ * Do I need to remind you about structure size (32 octets) ?
+ */
+struct iwreq
+{
+ union
+ {
+ char ifrn_name[IFNAMSIZ]; /* if name, e.g. "eth0" */
+ } ifr_ifrn;
+
+ /* Data part (defined just above) */
+ union iwreq_data u;
+};
+
+/* -------------------------- IOCTL DATA -------------------------- */
+/*
+ * For those ioctl which want to exchange mode data that what could
+ * fit in the above structure...
+ */
+
+/*
+ * Range of parameters
+ */
+
+struct iw_range
+{
+ /* Informative stuff (to choose between different interface) */
+ __u32 throughput; /* To give an idea... */
+ /* In theory this value should be the maximum benchmarked
+ * TCP/IP throughput, because with most of these devices the
+ * bit rate is meaningless (overhead an co) to estimate how
+ * fast the connection will go and pick the fastest one.
+ * I suggest people to play with Netperf or any benchmark...
+ */
+
+ /* NWID (or domain id) */
+ __u32 min_nwid; /* Minimal NWID we are able to set */
+ __u32 max_nwid; /* Maximal NWID we are able to set */
+
+ /* Old Frequency (backward compat - moved lower ) */
+ __u16 old_num_channels;
+ __u8 old_num_frequency;
+
+ /* Wireless event capability bitmasks */
+ __u32 event_capa[6];
+
+ /* signal level threshold range */
+ __s32 sensitivity;
+
+ /* Quality of link & SNR stuff */
+ /* Quality range (link, level, noise)
+ * If the quality is absolute, it will be in the range [0 ; max_qual],
+ * if the quality is dBm, it will be in the range [max_qual ; 0].
+ * Don't forget that we use 8 bit arithmetics... */
+ struct iw_quality max_qual; /* Quality of the link */
+ /* This should contain the average/typical values of the quality
+ * indicator. This should be the threshold between a "good" and
+ * a "bad" link (example : monitor going from green to orange).
+ * Currently, user space apps like quality monitors don't have any
+ * way to calibrate the measurement. With this, they can split
+ * the range between 0 and max_qual in different quality level
+ * (using a geometric subdivision centered on the average).
+ * I expect that people doing the user space apps will feedback
+ * us on which value we need to put in each driver... */
+ struct iw_quality avg_qual; /* Quality of the link */
+
+ /* Rates */
+ __u8 num_bitrates; /* Number of entries in the list */
+ __s32 bitrate[IW_MAX_BITRATES]; /* list, in bps */
+
+ /* RTS threshold */
+ __s32 min_rts; /* Minimal RTS threshold */
+ __s32 max_rts; /* Maximal RTS threshold */
+
+ /* Frag threshold */
+ __s32 min_frag; /* Minimal frag threshold */
+ __s32 max_frag; /* Maximal frag threshold */
+
+ /* Power Management duration & timeout */
+ __s32 min_pmp; /* Minimal PM period */
+ __s32 max_pmp; /* Maximal PM period */
+ __s32 min_pmt; /* Minimal PM timeout */
+ __s32 max_pmt; /* Maximal PM timeout */
+ __u16 pmp_flags; /* How to decode max/min PM period */
+ __u16 pmt_flags; /* How to decode max/min PM timeout */
+ __u16 pm_capa; /* What PM options are supported */
+
+ /* Encoder stuff */
+ __u16 encoding_size[IW_MAX_ENCODING_SIZES]; /* Different token sizes */
+ __u8 num_encoding_sizes; /* Number of entry in the list */
+ __u8 max_encoding_tokens; /* Max number of tokens */
+ /* For drivers that need a "login/passwd" form */
+ __u8 encoding_login_index; /* token index for login token */
+
+ /* Transmit power */
+ __u16 txpower_capa; /* What options are supported */
+ __u8 num_txpower; /* Number of entries in the list */
+ __s32 txpower[IW_MAX_TXPOWER]; /* list, in bps */
+
+ /* Wireless Extension version info */
+ __u8 we_version_compiled; /* Must be WIRELESS_EXT */
+ __u8 we_version_source; /* Last update of source */
+
+ /* Retry limits and lifetime */
+ __u16 retry_capa; /* What retry options are supported */
+ __u16 retry_flags; /* How to decode max/min retry limit */
+ __u16 r_time_flags; /* How to decode max/min retry life */
+ __s32 min_retry; /* Minimal number of retries */
+ __s32 max_retry; /* Maximal number of retries */
+ __s32 min_r_time; /* Minimal retry lifetime */
+ __s32 max_r_time; /* Maximal retry lifetime */
+
+ /* Frequency */
+ __u16 num_channels; /* Number of channels [0; num - 1] */
+ __u8 num_frequency; /* Number of entry in the list */
+ struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */
+ /* Note : this frequency list doesn't need to fit channel numbers,
+ * because each entry contain its channel index */
+
+ __u32 enc_capa; /* IW_ENC_CAPA_* bit field */
+};
+
+/*
+ * Private ioctl interface information
+ */
+
+struct iw_priv_args
+{
+ __u32 cmd; /* Number of the ioctl to issue */
+ __u16 set_args; /* Type and number of args */
+ __u16 get_args; /* Type and number of args */
+ char name[IFNAMSIZ]; /* Name of the extension */
+};
+
+/* ----------------------- WIRELESS EVENTS ----------------------- */
+/*
+ * Wireless events are carried through the rtnetlink socket to user
+ * space. They are encapsulated in the IFLA_WIRELESS field of
+ * a RTM_NEWLINK message.
+ */
+
+/*
+ * A Wireless Event. Contains basically the same data as the ioctl...
+ */
+struct iw_event
+{
+ __u16 len; /* Real lenght of this stuff */
+ __u16 cmd; /* Wireless IOCTL */
+ union iwreq_data u; /* IOCTL fixed payload */
+};
+
+/* Size of the Event prefix (including padding and alignement junk) */
+#define IW_EV_LCP_LEN (sizeof(struct iw_event) - sizeof(union iwreq_data))
+/* Size of the various events */
+#define IW_EV_CHAR_LEN (IW_EV_LCP_LEN + IFNAMSIZ)
+#define IW_EV_UINT_LEN (IW_EV_LCP_LEN + sizeof(__u32))
+#define IW_EV_FREQ_LEN (IW_EV_LCP_LEN + sizeof(struct iw_freq))
+#define IW_EV_PARAM_LEN (IW_EV_LCP_LEN + sizeof(struct iw_param))
+#define IW_EV_ADDR_LEN (IW_EV_LCP_LEN + sizeof(struct sockaddr))
+#define IW_EV_QUAL_LEN (IW_EV_LCP_LEN + sizeof(struct iw_quality))
+
+/* iw_point events are special. First, the payload (extra data) come at
+ * the end of the event, so they are bigger than IW_EV_POINT_LEN. Second,
+ * we omit the pointer, so start at an offset. */
+#define IW_EV_POINT_OFF (((char *) &(((struct iw_point *) NULL)->length)) - \
+ (char *) NULL)
+#define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point) - \
+ IW_EV_POINT_OFF)
+
+#endif /* _LINUX_WIRELESS_H */