diff options
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 */ |