From 62fddff9e6d89ac16afc704b4380a89669cfffa0 Mon Sep 17 00:00:00 2001 From: Kim Gibyoung Date: Fri, 28 Dec 2012 20:57:44 +0900 Subject: [PATCH] Version Update with wpasupplicant 1.0 release Change-Id: I91636b4a9aec1c8573e73c5b5848d855cc6f48d2 --- README | 2 +- debian/changelog | 8 + doc/doxygen.conf | 4 +- doc/kerneldoc2doxygen.pl | 134 ++ hostapd/Android.mk | 12 +- hostapd/ChangeLog | 107 ++ hostapd/Makefile | 13 - hostapd/README | 2 +- hostapd/config_file.c | 46 +- hostapd/ctrl_iface.c | 15 +- hostapd/defconfig | 7 +- hostapd/hostapd.conf | 20 - hostapd/hostapd_cli.c | 2 +- hostapd/main.c | 6 +- packaging/wpasupplicant.spec | 4 +- radius_example/radius_example.c | 3 +- src/ap/accounting.c | 15 +- src/ap/ap_config.c | 4 - src/ap/ap_config.h | 14 +- src/ap/ap_drv_ops.c | 17 +- src/ap/ap_drv_ops.h | 6 +- src/ap/authsrv.c | 10 +- src/ap/beacon.c | 270 ++- src/ap/drv_callbacks.c | 32 +- src/ap/hostapd.c | 24 +- src/ap/hostapd.h | 11 +- src/ap/hw_features.c | 55 +- src/ap/hw_features.h | 5 +- src/ap/ieee802_11.c | 68 +- src/ap/ieee802_11.h | 2 - src/ap/ieee802_11_auth.c | 53 +- src/ap/ieee802_11_auth.h | 3 +- src/ap/ieee802_11_shared.c | 8 +- src/ap/ieee802_1x.c | 58 +- src/ap/ieee802_1x.h | 2 - src/ap/sta_info.c | 22 +- src/ap/sta_info.h | 2 - src/ap/wmm.c | 5 +- src/ap/wpa_auth.c | 15 +- src/ap/wpa_auth_ft.c | 1 + src/ap/wpa_auth_glue.c | 6 +- src/ap/wpa_auth_ie.c | 3 +- src/ap/wps_hostapd.c | 55 +- src/common/defs.h | 8 - src/common/ieee802_11_defs.h | 6 +- src/common/version.h | 2 +- src/common/wpa_ctrl.h | 1 + src/crypto/Makefile | 2 - src/crypto/aes-internal-dec.c | 2 +- src/crypto/aes-internal-enc.c | 2 +- src/crypto/crypto.h | 3 +- src/crypto/crypto_internal-rsa.c | 1 + src/crypto/crypto_internal.c | 78 +- src/crypto/dh_group5.c | 2 +- src/crypto/sha1-pbkdf2.c | 2 + src/crypto/sha1-tlsprf.c | 7 +- src/crypto/sha1.h | 6 +- src/crypto/sha256-internal.c | 22 +- src/crypto/sha256-tlsprf.c | 72 - src/crypto/sha256.h | 5 +- src/crypto/sha256_i.h | 31 - src/crypto/tls.h | 13 +- src/crypto/tls_internal.c | 43 +- src/crypto/tls_openssl.c | 1 - src/drivers/Apple80211.h | 156 ++ src/drivers/MobileApple80211.c | 189 ++ src/drivers/MobileApple80211.h | 43 + src/drivers/android_drv.h | 60 - src/drivers/driver.h | 91 +- src/drivers/driver_atheros.c | 2 +- src/drivers/driver_broadcom.c | 599 ++++++ src/drivers/driver_common.c | 1 - src/drivers/driver_hostap.c | 508 ++++- src/drivers/driver_iphone.m | 466 +++++ src/drivers/driver_madwifi.c | 560 +++++- src/drivers/driver_nl80211.c | 1938 +++++--------------- src/drivers/driver_osx.m | 459 +++++ src/drivers/driver_ralink.c | 1498 +++++++++++++++ src/drivers/driver_ralink.h | 383 ++++ src/drivers/driver_test.c | 10 +- src/drivers/driver_wext.c | 191 +- src/drivers/driver_wext.h | 6 - src/drivers/drivers.c | 24 + src/drivers/drivers.mak | 62 +- src/drivers/drivers.mk | 62 +- src/drivers/linux_wext.h | 51 - src/drivers/nl80211_copy.h | 146 +- src/drivers/wireless_copy.h | 1183 ++++++++++++ src/eap_common/eap_fast_common.c | 6 +- src/eap_common/eap_pwd_common.h | 7 +- src/eap_peer/eap.c | 5 + src/eap_peer/eap_aka.c | 45 +- src/eap_peer/eap_pwd.c | 5 +- src/eap_peer/eap_sim.c | 39 +- src/eap_peer/eap_tls_common.c | 6 +- src/eap_peer/eap_tnc.c | 1 + src/eap_peer/eap_ttls.c | 11 +- src/eap_server/eap.h | 2 + src/eap_server/eap_server_aka.c | 14 +- src/eap_server/eap_server_mschapv2.c | 9 +- src/eap_server/eap_server_peap.c | 2 + src/eap_server/eap_server_pwd.c | 9 +- src/eap_server/eap_server_sim.c | 14 +- src/eap_server/eap_server_tls_common.c | 6 +- src/p2p/p2p.c | 229 ++- src/p2p/p2p.h | 101 +- src/p2p/p2p_go_neg.c | 16 + src/p2p/p2p_group.c | 38 + src/p2p/p2p_i.h | 7 +- src/p2p/p2p_invitation.c | 2 + src/p2p/p2p_pd.c | 15 +- src/p2p/p2p_sd.c | 2 +- src/radius/radius.c | 116 -- src/radius/radius.h | 4 - src/radius/radius_client.c | 2 +- src/radius/radius_server.c | 32 +- src/radius/radius_server.h | 6 +- src/rsn_supp/preauth.c | 1 + src/rsn_supp/wpa_ft.c | 1 + src/tls/Makefile | 2 - src/tls/libtommath.c | 2 +- src/tls/pkcs5.c | 2 +- src/tls/tlsv1_client.c | 203 +- src/tls/tlsv1_client.h | 10 +- src/tls/tlsv1_client_i.h | 2 - src/tls/tlsv1_client_read.c | 34 +- src/tls/tlsv1_client_write.c | 85 +- src/tls/tlsv1_common.c | 91 +- src/tls/tlsv1_common.h | 49 +- src/tls/tlsv1_cred.c | 7 - src/tls/tlsv1_record.c | 66 +- src/tls/tlsv1_record.h | 4 +- src/tls/tlsv1_server.c | 82 +- src/tls/tlsv1_server.h | 4 +- src/tls/tlsv1_server_read.c | 114 +- src/tls/tlsv1_server_write.c | 28 +- src/utils/os_unix.c | 2 +- src/utils/radiotap.h | 1 - src/utils/wpa_debug.c | 32 + src/utils/wpa_debug.h | 2 +- src/wps/wps.h | 7 +- src/wps/wps_common.c | 1 + src/wps/wps_enrollee.c | 47 +- src/wps/wps_registrar.c | 1 + src/wps/wps_ufd.c | 1 + tests/Makefile | 9 +- tests/test-https.c | 234 --- tests/test-rc4.c | 256 --- tests/test-sha1.c | 5 +- wlantest/wlantest.c | 45 +- wpa_supplicant/Android.mk | 23 +- wpa_supplicant/ChangeLog | 174 ++ wpa_supplicant/Makefile | 50 +- wpa_supplicant/README | 61 +- wpa_supplicant/ap.c | 46 +- wpa_supplicant/ap.h | 2 - wpa_supplicant/bss.c | 19 + wpa_supplicant/bss.h | 2 + wpa_supplicant/config.c | 141 ++ wpa_supplicant/config.h | 3 + wpa_supplicant/config_file.c | 31 +- wpa_supplicant/config_ssid.h | 14 + wpa_supplicant/config_winreg.c | 4 +- wpa_supplicant/ctrl_iface.c | 204 +-- wpa_supplicant/dbus/Makefile | 12 - wpa_supplicant/dbus/dbus-wpa_supplicant.conf | 14 +- wpa_supplicant/dbus/dbus_new.c | 88 +- wpa_supplicant/dbus/dbus_new_handlers.c | 141 +- wpa_supplicant/dbus/dbus_new_handlers.h | 14 + wpa_supplicant/dbus/dbus_new_handlers_p2p.c | 568 ++++-- wpa_supplicant/dbus/dbus_new_handlers_p2p.h | 69 +- wpa_supplicant/dbus/dbus_new_introspect.c | 8 +- wpa_supplicant/dbus/dbus_old.c | 1 + .../fi.epitest.hostap.WPASupplicant.service.in | 1 + .../dbus/fi.w1.wpa_supplicant1.service.in | 1 + wpa_supplicant/defconfig | 14 +- wpa_supplicant/driver_i.h | 11 +- wpa_supplicant/eap_register.c | 1 - wpa_supplicant/eapol_test.c | 4 +- wpa_supplicant/events.c | 103 +- wpa_supplicant/examples/wpas-dbus-new-signals.py | 4 +- wpa_supplicant/examples/wps-ap-cli | 78 - wpa_supplicant/ibss_rsn.c | 4 +- wpa_supplicant/interworking.c | 8 +- wpa_supplicant/notify.c | 12 +- wpa_supplicant/notify.h | 3 +- wpa_supplicant/offchannel.c | 0 wpa_supplicant/p2p_supplicant.c | 399 +++- wpa_supplicant/p2p_supplicant.h | 18 +- wpa_supplicant/scan.c | 104 +- wpa_supplicant/sme.c | 22 +- .../systemd/wpa_supplicant-nl80211@.service.in | 2 +- .../systemd/wpa_supplicant-wired@.service.in | 2 +- wpa_supplicant/systemd/wpa_supplicant.service.in | 2 +- wpa_supplicant/systemd/wpa_supplicant@.service.in | 2 +- wpa_supplicant/wpa_cli.c | 29 +- wpa_supplicant/wpa_gui-qt4/scanresults.cpp | 4 +- wpa_supplicant/wpa_gui-qt4/signalbar.cpp | 64 - wpa_supplicant/wpa_gui-qt4/signalbar.h | 34 - wpa_supplicant/wpa_gui-qt4/wpa_gui.pro | 2 - wpa_supplicant/wpa_supplicant.c | 45 +- wpa_supplicant/wpa_supplicant_i.h | 11 +- wpa_supplicant/wps_supplicant.c | 10 +- 203 files changed, 9866 insertions(+), 5146 deletions(-) create mode 100755 doc/kerneldoc2doxygen.pl delete mode 100644 src/crypto/sha256-tlsprf.c delete mode 100644 src/crypto/sha256_i.h create mode 100644 src/drivers/Apple80211.h create mode 100644 src/drivers/MobileApple80211.c create mode 100644 src/drivers/MobileApple80211.h delete mode 100644 src/drivers/android_drv.h create mode 100644 src/drivers/driver_broadcom.c create mode 100644 src/drivers/driver_iphone.m mode change 100644 => 100755 src/drivers/driver_nl80211.c create mode 100644 src/drivers/driver_osx.m create mode 100644 src/drivers/driver_ralink.c create mode 100644 src/drivers/driver_ralink.h delete mode 100644 src/drivers/linux_wext.h create mode 100644 src/drivers/wireless_copy.h delete mode 100644 tests/test-https.c delete mode 100644 tests/test-rc4.c mode change 100644 => 100755 wpa_supplicant/dbus/dbus_new.c mode change 100644 => 100755 wpa_supplicant/dbus/dbus_new_handlers.c delete mode 100755 wpa_supplicant/examples/wps-ap-cli mode change 100644 => 100755 wpa_supplicant/offchannel.c mode change 100644 => 100755 wpa_supplicant/p2p_supplicant.c mode change 100644 => 100755 wpa_supplicant/scan.c delete mode 100644 wpa_supplicant/wpa_gui-qt4/signalbar.cpp delete mode 100644 wpa_supplicant/wpa_gui-qt4/signalbar.h mode change 100644 => 100755 wpa_supplicant/wpa_supplicant.c diff --git a/README b/README index 186e4b9..abdc18c 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ wpa_supplicant and hostapd -------------------------- -Copyright (c) 2002-2011, Jouni Malinen and contributors +Copyright (c) 2002-2012, Jouni Malinen and contributors All Rights Reserved. These programs are dual-licensed under both the GPL version 2 and BSD diff --git a/debian/changelog b/debian/changelog index cceb592..9cdd05f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,11 @@ +wpasupplicant (1.0.0-0slp2+1) unstable; urgency=low + + * Enable debug log for developers + * Git: framework/connectivity/wpasupplicant + * Tag: wpasupplicant_1.0.0-0slp2+1 + + -- Gibyoung Kim Fri, 28 Dec 2012 19:16:45 +0900 + wpasupplicant (0.8.0-0slp2+7) unstable; urgency=low * Enable debug log for developers diff --git a/doc/doxygen.conf b/doc/doxygen.conf index 6a1cb3e..d1032f2 100644 --- a/doc/doxygen.conf +++ b/doc/doxygen.conf @@ -674,9 +674,7 @@ IMAGE_PATH = doc # If FILTER_PATTERNS is specified, this tag will be # ignored. -# You can download the filter tool from -# http://w1.fi/tools/kerneldoc2doxygen-hostap.pl -INPUT_FILTER = kerneldoc2doxygen-hostap.pl +INPUT_FILTER = doc/kerneldoc2doxygen.pl # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. diff --git a/doc/kerneldoc2doxygen.pl b/doc/kerneldoc2doxygen.pl new file mode 100755 index 0000000..68c4aed --- /dev/null +++ b/doc/kerneldoc2doxygen.pl @@ -0,0 +1,134 @@ +#!/usr/bin/perl -w +# +########################################################################## +# Convert kernel-doc style comments to Doxygen comments. +########################################################################## +# +# This script reads a C source file from stdin, and writes +# to stdout. Normal usage: +# +# $ mv file.c file.c.gtkdoc +# $ kerneldoc2doxygen.pl file.c +# +# Or to do the same thing with multiple files: +# $ perl -i.gtkdoc kerneldoc2doxygen.pl *.c *.h +# +# This script may also be suitable for use as a Doxygen input filter, +# but that has not been tested. +# +# Back up your source files before using this script!! +# +########################################################################## +# Copyright (C) 2003 Jonathan Foster +# Copyright (C) 2005-2008 Jouni Malinen +# (modified for kerneldoc format used in wpa_supplicant) +# +# 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. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# or look at http://www.gnu.org/licenses/gpl.html +########################################################################## + + +########################################################################## +# +# This function converts a single comment from gtk-doc to Doxygen format. +# The parameter does not include the opening or closing lines +# (i.e. given a comment like this: +# "/**\n" +# " * FunctionName:\n" +# " * @foo: This describes the foo parameter\n" +# " * @bar: This describes the bar parameter\n" +# " * @Returns: This describes the return value\n" +# " *\n" +# " * This describes the function.\n" +# " */\n" +# This function gets: +# " * FunctionName:\n" +# " * @foo: This describes the foo parameter\n" +# " * @bar: This describes the bar parameter\n" +# " * @Returns: This describes the return value\n" +# " *\n" +# " * This describes the function.\n" +# And it returns: +# " * This describes the function.\n" +# " *\n" +# " * @param foo This describes the foo parameter\n" +# " * @param bar This describes the bar parameter\n" +# " * @return This describes the return value\n" +# ) +# +sub fixcomment { + $t = $_[0]; + + # wpa_supplicant -> %wpa_supplicant except for struct wpa_supplicant + $t =~ s/struct wpa_supplicant/struct STRUCTwpa_supplicant/sg; + $t =~ s/ wpa_supplicant/ \%wpa_supplicant/sg; + $t =~ s/struct STRUCTwpa_supplicant/struct wpa_supplicant/sg; + + # " * func: foo" --> "\brief foo\n" + # " * struct bar: foo" --> "\brief foo\n" + # If this fails, not a kernel-doc comment ==> return unmodified. + ($t =~ s/^[\t ]*\*[\t ]*(struct )?([^ \t\n]*) - ([^\n]*)/\\brief $3\n/s) + or return $t; + + # " * Returns: foo" --> "\return foo" + $t =~ s/\n[\t ]*\*[\t ]*Returns:/\n\\return/sig; + + # " * @foo: bar" --> "\param foo bar" + # Handle two common typos: No ":", or "," instead of ":". + $t =~ s/\n[\t ]*\*[\t ]*\@([^ :,]*)[:,]?[\t ]*/\n\\param $1 /sg; + + return $t; +} + +########################################################################## +# Start of main code + +# Read entire stdin into memory - one multi-line string. +$_ = do { local $/; <> }; + +s{^/\*\n \*}{/\*\* \\file\n\\brief}; +s{ \* Copyright}{\\par Copyright\nCopyright}; + +# Fix any comments like "/*************" so they don't match. +# "/***" ===> "/* *" +s{/\*\*\*}{/\* \*}gs; + +# The main comment-detection code. +s{ + ( # $1 = Open comment + /\*\* # Open comment + (?!\*) # Do not match /*** (redundant due to fixup above). + [\t ]*\n? # If 1st line is whitespace, match the lot (including the newline). + ) + (.*?) # $2 = Body of comment (multi-line) + ( # $3 = Close comment + ( # If possible, match the whitespace before the close-comment + (?<=\n) # This part only matches after a newline + [\t ]* # Eat whitespace + )? + \*/ # Close comment + ) + } + { + $1 . fixcomment($2) . $3 + }gesx; +# ^^^^ Modes: g - Global, match all occurrences. +# e - Evaluate the replacement as an expression. +# s - Single-line - allows the pattern to match across newlines. +# x - eXtended pattern, ignore embedded whitespace +# and allow comments. + +# Write results to stdout +print $_; + diff --git a/hostapd/Android.mk b/hostapd/Android.mk index 7f0ba5c..04fd771 100644 --- a/hostapd/Android.mk +++ b/hostapd/Android.mk @@ -1,13 +1,13 @@ LOCAL_PATH := $(call my-dir) WPA_BUILD_HOSTAPD := false -ifneq ($(BOARD_HOSTAPD_DRIVER),) - WPA_BUILD_HOSTAPD := true - CONFIG_DRIVER_$(BOARD_HOSTAPD_DRIVER) := y +ifneq ($(TARGET_SIMULATOR),true) + ifneq ($(BOARD_HOSTAPD_DRIVER),) + WPA_BUILD_HOSTAPD := true + CONFIG_DRIVER_$(BOARD_HOSTAPD_DRIVER) := y + endif endif -ifeq ($(WPA_BUILD_HOSTAPD),true) - include $(LOCAL_PATH)/.config # To ignore possible wrong network configurations @@ -793,6 +793,8 @@ else OBJS_c += src/utils/edit_simple.c endif +ifeq ($(WPA_BUILD_HOSTAPD),true) + ######################## include $(CLEAR_VARS) diff --git a/hostapd/ChangeLog b/hostapd/ChangeLog index 47f2423..3422da4 100644 --- a/hostapd/ChangeLog +++ b/hostapd/ChangeLog @@ -1,5 +1,112 @@ ChangeLog for hostapd +2012-04-18 - v1.0 + * Add channel selection support in hostapd. See hostapd.conf. + * Add support for IEEE 802.11v Time Advertisement mechanism with UTC + TSF offset. See hostapd.conf for config info. + * Delay STA entry removal until Deauth/Disassoc TX status in AP mode. + This allows the driver to use PS buffering of Deauthentication and + Disassociation frames when the STA is in power save sleep. Only + available with drivers that provide TX status events for Deauth/ + Disassoc frames (nl80211). + * Allow PMKSA caching to be disabled on the Authenticator. See + hostap.conf config parameter disable_pmksa_caching. + * atheros: Add support for IEEE 802.11w configuration. + * bsd: Add support for setting HT values in IFM_MMASK. + * Allow client isolation to be configured with ap_isolate. Client + isolation can be used to prevent low-level bridging of frames + between associated stations in the BSS. By default, this bridging + is allowed. + * Allow coexistance of HT BSSes with WEP/TKIP BSSes. + * Add require_ht config parameter, which can be used to configure + hostapd to reject association with any station that does not support + HT PHY. + * Add support for writing debug log to a file using "-f" option. Also + add relog CLI command to re-open the log file. + * Add bridge handling for WDS STA interfaces. By default they are + added to the configured bridge of the AP interface (if present), + but the user can also specify a separate bridge using cli command + wds_bridge. + * hostapd_cli: + - Add wds_bridge command for specifying bridge for WDS STA + interfaces. + - Add relog command for reopening log file. + - Send AP-STA-DISCONNECTED event when an AP disconnects a station + due to inactivity. + - Add wps_config ctrl_interface command for configuring AP. This + command can be used to configure the AP using the internal WPS + registrar. It works in the same way as new AP settings received + from an ER. + - Many WPS/WPS ER commands - see WPS/WPS ER sections for details. + - Add command get version, that returns hostapd version string. + * WNM: Add BSS Transition Management Request for ESS Disassoc Imminent. + Use hostapd_cli ess_disassoc (STA addr) (URL) to send the + notification to the STA. + * Allow AP mode to disconnect STAs based on low ACK condition (when + the data connection is not working properly, e.g., due to the STA + going outside the range of the AP). Disabled by default, enable by + config option disassoc_low_ack. + * Add WPA_IGNORE_CONFIG_ERRORS build option to continue in case of bad + config file. + * WPS: + - Send AP Settings as a wrapped Credential attribute to ctrl_iface + in WPS-NEW-AP-SETTINGS. + - Dispatch more WPS events through hostapd ctrl_iface. + - Add mechanism for indicating non-standard WPS errors. + - Change concurrent radio AP to use only one WPS UPnP instance. + - Add wps_check_pin command for processing PIN from user input. + UIs can use this command to process a PIN entered by a user and to + validate the checksum digit (if present). + - Add hostap_cli get_config command to display current AP config. + - Add new hostapd_cli command, wps_ap_pin, to manage AP PIN at + runtime and support dynamic AP PIN management. + - Disable AP PIN after 10 consecutive failures. Slow down attacks + on failures up to 10. + - Allow AP to start in Enrollee mode without AP PIN for probing, + to be compatible with Windows 7. + - Add Config Error into WPS-FAIL events to provide more info + to the user on how to resolve the issue. + - When controlling multiple interfaces: + - apply WPS commands to all interfaces configured to use WPS + - apply WPS config changes to all interfaces that use WPS + - when an attack is detected on any interface, disable AP PIN on + all interfaces + * WPS ER: + - Show SetSelectedRegistrar events as ctrl_iface events. + - Add special AP Setup Locked mode to allow read only ER. + ap_setup_locked=2 can now be used to enable a special mode where + WPS ER can learn the current AP settings, but cannot change them. + * WPS 2.0: Add support for WPS 2.0 (CONFIG_WPS2) + - Add build option CONFIG_WPS_EXTENSIBILITY_TESTING to enable tool + for testing protocol extensibility. + - Add build option CONFIG_WPS_STRICT to allow disabling of WPS + workarounds. + - Add support for AuthorizedMACs attribute. + * TDLS: + - Allow TDLS use or TDLS channel switching in the BSS to be + prohibited in the BSS, using config params tdls_prohibit and + tdls_prohibit_chan_switch. + * EAP server: Add support for configuring fragment size (see + fragment_size in hostapd.conf). + * wlantest: Add a tool wlantest for IEEE802.11 protocol testing. + wlantest can be used to capture frames from a monitor interface + for realtime capturing or from pcap files for offline analysis. + * Interworking: Support added for 802.11u. Enable in .config with + CONFIG_INTERWORKING. See hostapd.conf for config parameters for + interworking. + * Android: Add build and runtime support for Android hostapd. + * Add a new debug message level for excessive information. Use + -ddd to enable. + * TLS: Add support for tls_disable_time_checks=1 in client mode. + * Internal TLS: + - Add support for TLS v1.1 (RFC 4346). Enable with build parameter + CONFIG_TLSV11. + - Add domainComponent parser for X.509 names + * Reorder some IEs to get closer to IEEE 802.11 standard. Move + WMM into end of Beacon, Probe Resp and (Re)Assoc Resp frames. + Move HT IEs to be later in (Re)Assoc Resp. + * Many bugfixes. + 2010-04-18 - v0.7.2 * fix WPS internal Registrar use when an external Registrar is also active diff --git a/hostapd/Makefile b/hostapd/Makefile index d448402..e46561e 100644 --- a/hostapd/Makefile +++ b/hostapd/Makefile @@ -8,7 +8,6 @@ endif CFLAGS += -I../src CFLAGS += -I../src/utils -CFLAGS += -I../src/ap # Uncomment following line and set the path to your kernel tree include # directory if your C library does not include all header files. @@ -441,11 +440,6 @@ ifdef CONFIG_TLSV11 CFLAGS += -DCONFIG_TLSV11 endif -ifdef CONFIG_TLSV12 -CFLAGS += -DCONFIG_TLSV12 -NEED_SHA256=y -endif - ifeq ($(CONFIG_TLS), openssl) ifdef TLS_FUNCS OBJS += ../src/crypto/tls_openssl.o @@ -525,9 +519,6 @@ OBJS += ../src/tls/pkcs8.o NEED_SHA256=y NEED_BASE64=y NEED_TLS_PRF=y -ifdef CONFIG_TLSV12 -NEED_TLS_PRF_SHA256=y -endif NEED_MODEXP=y NEED_CIPHER=y CFLAGS += -DCONFIG_TLS_INTERNAL @@ -687,14 +678,10 @@ endif endif ifdef NEED_SHA256 -CFLAGS += -DCONFIG_SHA256 OBJS += ../src/crypto/sha256.o ifdef CONFIG_INTERNAL_SHA256 OBJS += ../src/crypto/sha256-internal.o endif -ifdef NEED_TLS_PRF_SHA256 -OBJS += ../src/crypto/sha256-tlsprf.o -endif endif ifdef NEED_DH_GROUPS diff --git a/hostapd/README b/hostapd/README index a211cdd..189983e 100644 --- a/hostapd/README +++ b/hostapd/README @@ -2,7 +2,7 @@ hostapd - user space IEEE 802.11 AP and IEEE 802.1X/WPA/WPA2/EAP Authenticator and RADIUS authentication server ================================================================ -Copyright (c) 2002-2011, Jouni Malinen and contributors +Copyright (c) 2002-2012, Jouni Malinen and contributors All Rights Reserved. This program is dual-licensed under both the GPL version 2 and BSD diff --git a/hostapd/config_file.c b/hostapd/config_file.c index ca79695..1bfd456 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -330,7 +330,7 @@ static int hostapd_config_read_eap_user(const char *fname, } num_methods++; - if (num_methods >= EAP_MAX_METHODS) + if (num_methods >= EAP_USER_MAX_METHODS) break; skip_eap: if (pos3 == NULL) @@ -1050,18 +1050,9 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, return -1; } - if (bss->wpa && bss->wpa_psk_radius != PSK_RADIUS_IGNORED && - bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH) { - wpa_printf(MSG_ERROR, "WPA-PSK using RADIUS enabled, but no " - "RADIUS checking (macaddr_acl=2) enabled."); - return -1; - } - if (bss->wpa && (bss->wpa_key_mgmt & WPA_KEY_MGMT_PSK) && bss->ssid.wpa_psk == NULL && bss->ssid.wpa_passphrase == NULL && - bss->ssid.wpa_psk_file == NULL && - (bss->wpa_psk_radius != PSK_RADIUS_REQUIRED || - bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH)) { + bss->ssid.wpa_psk_file == NULL) { wpa_printf(MSG_ERROR, "WPA-PSK enabled, but PSK or passphrase " "is not configured."); return -1; @@ -1084,7 +1075,8 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, } #ifdef CONFIG_IEEE80211R - if (wpa_key_mgmt_ft(bss->wpa_key_mgmt) && + if ((bss->wpa_key_mgmt & + (WPA_KEY_MGMT_FT_PSK | WPA_KEY_MGMT_FT_IEEE8021X)) && (bss->nas_identifier == NULL || os_strlen(bss->nas_identifier) < 1 || os_strlen(bss->nas_identifier) > FT_R0KH_ID_MAX_LEN)) { @@ -1638,16 +1630,6 @@ struct hostapd_config * hostapd_config_read(const char *fname) hostapd_config_parse_key_mgmt(line, pos); if (bss->wpa_key_mgmt == -1) errors++; - } else if (os_strcmp(buf, "wpa_psk_radius") == 0) { - bss->wpa_psk_radius = atoi(pos); - if (bss->wpa_psk_radius != PSK_RADIUS_IGNORED && - bss->wpa_psk_radius != PSK_RADIUS_ACCEPTED && - bss->wpa_psk_radius != PSK_RADIUS_REQUIRED) { - wpa_printf(MSG_ERROR, "Line %d: unknown " - "wpa_psk_radius %d", - line, bss->wpa_psk_radius); - errors++; - } } else if (os_strcmp(buf, "wpa_pairwise") == 0) { bss->wpa_pairwise = hostapd_config_parse_cipher(line, pos); @@ -1787,21 +1769,6 @@ struct hostapd_config * hostapd_config_read(const char *fname) "hw_mode '%s'", line, pos); errors++; } - } else if (os_strcmp(buf, "wps_rf_bands") == 0) { - if (os_strcmp(pos, "a") == 0) - bss->wps_rf_bands = WPS_RF_50GHZ; - else if (os_strcmp(pos, "g") == 0 || - os_strcmp(pos, "b") == 0) - bss->wps_rf_bands = WPS_RF_24GHZ; - else if (os_strcmp(pos, "ag") == 0 || - os_strcmp(pos, "ga") == 0) - bss->wps_rf_bands = - WPS_RF_24GHZ | WPS_RF_50GHZ; - else { - wpa_printf(MSG_ERROR, "Line %d: unknown " - "wps_rf_band '%s'", line, pos); - errors++; - } } else if (os_strcmp(buf, "channel") == 0) { conf->channel = atoi(pos); } else if (os_strcmp(buf, "beacon_int") == 0) { @@ -2174,11 +2141,6 @@ struct hostapd_config * hostapd_config_read(const char *fname) if (parse_roaming_consortium(bss, pos, line) < 0) errors++; #endif /* CONFIG_INTERWORKING */ -#ifdef CONFIG_RADIUS_TEST - } else if (os_strcmp(buf, "dump_msk_file") == 0) { - os_free(bss->dump_msk_file); - bss->dump_msk_file = os_strdup(pos); -#endif /* CONFIG_RADIUS_TEST */ } else { wpa_printf(MSG_ERROR, "Line %d: unknown configuration " "item '%s'", line, buf); diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index a38d77c..4a6e011 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -32,6 +32,7 @@ #include "ap/wpa_auth.h" #include "ap/ieee802_11.h" #include "ap/sta_info.h" +#include "ap/accounting.h" #include "ap/wps_hostapd.h" #include "ap/ctrl_iface_ap.h" #include "ap/ap_drv_ops.h" @@ -173,9 +174,9 @@ static int p2p_manager_disconnect(struct hostapd_data *hapd, u16 stype, if (mgmt == NULL) return -1; - wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "P2P: Disconnect STA " MACSTR - " with minor reason code %u (stype=%u)", - MAC2STR(addr), minor_reason_code, stype); + wpa_printf(MSG_DEBUG, "P2P: Disconnect STA " MACSTR " with minor " + "reason code %u (stype=%u)", + MAC2STR(addr), minor_reason_code, stype); mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, stype); os_memcpy(mgmt->da, addr, ETH_ALEN); @@ -218,8 +219,7 @@ static int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta; const char *pos; - wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "CTRL_IFACE DEAUTHENTICATE %s", - txtaddr); + wpa_printf(MSG_DEBUG, "CTRL_IFACE DEAUTHENTICATE %s", txtaddr); if (hwaddr_aton(txtaddr, addr)) return -1; @@ -275,8 +275,7 @@ static int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd, struct sta_info *sta; const char *pos; - wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "CTRL_IFACE DISASSOCIATE %s", - txtaddr); + wpa_printf(MSG_DEBUG, "CTRL_IFACE DISASSOCIATE %s", txtaddr); if (hwaddr_aton(txtaddr, addr)) return -1; @@ -568,7 +567,7 @@ static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd, os_memcpy(pos, url, url_len); pos += url_len; - if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) { + if (hostapd_drv_send_mlme(hapd, buf, pos - buf) < 0) { wpa_printf(MSG_DEBUG, "Failed to send BSS Transition " "Management Request frame"); return -1; diff --git a/hostapd/defconfig b/hostapd/defconfig index bae5ba2..f4c3666 100644 --- a/hostapd/defconfig +++ b/hostapd/defconfig @@ -84,6 +84,9 @@ CONFIG_EAP_TTLS=y # EAP-PSK for the integrated EAP server (this is _not_ needed for WPA-PSK) #CONFIG_EAP_PSK=y +# EAP-pwd for the integrated EAP server (secure authentication with a password) +#CONFIG_EAP_PWD=y + # EAP-SAKE for the integrated EAP server #CONFIG_EAP_SAKE=y @@ -221,10 +224,6 @@ CONFIG_IPV6=y # are used. #CONFIG_TLSV11=y -# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.2) -# can be enabled to enable use of stronger crypto algorithms. -#CONFIG_TLSV12=y - # If CONFIG_TLS=internal is used, additional library and include paths are # needed for LibTomMath. Alternatively, an integrated, minimal version of # LibTomMath can be used. See beginning of libtommath.c for details on benefits diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index 5272d58..a2e50bf 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -510,10 +510,6 @@ eap_server=0 # Fragment size for EAP methods #fragment_size=1400 -# Finite cyclic group for EAP-pwd. Number maps to group of domain parameters -# using the IANA repository for IKE (RFC 2409). -#pwd_group=19 - # Configuration data for EAP-SIM database/authentication gateway interface. # This is a text string in implementation specific format. The example # implementation in eap_sim_db.c uses this as the UNIX domain socket name for @@ -676,7 +672,6 @@ own_ip_addr=127.0.0.1 # Enable WPA. Setting this variable configures the AP to require WPA (either # WPA-PSK or WPA-RADIUS/EAP based on other configuration). For WPA-PSK, either # wpa_psk or wpa_passphrase must be set and wpa_key_mgmt must include WPA-PSK. -# Instead of wpa_psk / wpa_passphrase, wpa_psk_radius might suffice. # For WPA-RADIUS/EAP, ieee8021x must be set (but without dynamic WEP keys), # RADIUS authentication server must be configured, and WPA-EAP must be included # in wpa_key_mgmt. @@ -701,15 +696,6 @@ own_ip_addr=127.0.0.1 # configuration reloads. #wpa_psk_file=/etc/hostapd.wpa_psk -# Optionally, WPA passphrase can be received from RADIUS authentication server -# This requires macaddr_acl to be set to 2 (RADIUS) -# 0 = disabled (default) -# 1 = optional; use default passphrase/psk if RADIUS server does not include -# Tunnel-Password -# 2 = required; reject authentication if RADIUS server does not include -# Tunnel-Password -#wpa_psk_radius=0 - # Set of accepted key management algorithms (WPA-PSK, WPA-EAP, or both). The # entries are separated with a space. WPA-PSK-SHA256 and WPA-EAP-SHA256 can be # added to enable SHA256-based stronger algorithms. @@ -1021,12 +1007,6 @@ own_ip_addr=127.0.0.1 # 12-digit, all-numeric code that identifies the consumer package. #upc=123456789012 -# WPS RF Bands (a = 5G, b = 2.4G, g = 2.4G, ag = dual band) -# This value should be set according to RF band(s) supported by the AP if -# hw_mode is not set. For dual band dual concurrent devices, this needs to be -# set to ag to allow both RF bands to be advertized. -#wps_rf_bands=ag - ##### Wi-Fi Direct (P2P) ###################################################### # Enable P2P Device management diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c index 527860c..1d77c0a 100644 --- a/hostapd/hostapd_cli.c +++ b/hostapd/hostapd_cli.c @@ -24,7 +24,7 @@ static const char *hostapd_cli_version = "hostapd_cli v" VERSION_STR "\n" -"Copyright (c) 2004-2011, Jouni Malinen and contributors"; +"Copyright (c) 2004-2012, Jouni Malinen and contributors"; static const char *hostapd_cli_license = diff --git a/hostapd/main.c b/hostapd/main.c index da8135b..bf22559 100644 --- a/hostapd/main.c +++ b/hostapd/main.c @@ -303,10 +303,8 @@ static int hostapd_driver_init(struct hostapd_iface *iface) } if (hapd->driver->get_capa && - hapd->driver->get_capa(hapd->drv_priv, &capa) == 0) { + hapd->driver->get_capa(hapd->drv_priv, &capa) == 0) iface->drv_flags = capa.flags; - iface->probe_resp_offloads = capa.probe_resp_offloads; - } return 0; } @@ -513,7 +511,7 @@ static void show_version(void) "hostapd v" VERSION_STR "\n" "User space daemon for IEEE 802.11 AP management,\n" "IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n" - "Copyright (c) 2002-2011, Jouni Malinen " + "Copyright (c) 2002-2012, Jouni Malinen " "and contributors\n"); } diff --git a/packaging/wpasupplicant.spec b/packaging/wpasupplicant.spec index 0a92cb6..8d53bde 100644 --- a/packaging/wpasupplicant.spec +++ b/packaging/wpasupplicant.spec @@ -1,7 +1,7 @@ Name: wpasupplicant Summary: Support for WPA and WPA2 (IEEE 802.11i / RSN) -Version: 0.8.0 -Release: 7 +Version: 1.0.0 +Release: 1 Group: System/Network License: BSD license Source0: %{name}-%{version}.tar.gz diff --git a/radius_example/radius_example.c b/radius_example/radius_example.c index fd7dbae..51f4f99 100644 --- a/radius_example/radius_example.c +++ b/radius_example/radius_example.c @@ -94,7 +94,8 @@ static void start_example(void *eloop_ctx, void *timeout_ctx) return; } - radius_client_send(ctx->radius, msg, RADIUS_AUTH, NULL); + if (radius_client_send(ctx->radius, msg, RADIUS_AUTH, NULL) < 0) + radius_msg_free(msg); } diff --git a/src/ap/accounting.c b/src/ap/accounting.c index 03421b3..ad20fea 100644 --- a/src/ap/accounting.c +++ b/src/ap/accounting.c @@ -265,8 +265,9 @@ void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta) hapd, sta); msg = accounting_msg(hapd, sta, RADIUS_ACCT_STATUS_TYPE_START); - if (msg) - radius_client_send(hapd->radius, msg, RADIUS_ACCT, sta->addr); + if (msg && + radius_client_send(hapd->radius, msg, RADIUS_ACCT, sta->addr) < 0) + radius_msg_free(msg); sta->acct_session_started = 1; } @@ -364,9 +365,10 @@ static void accounting_sta_report(struct hostapd_data *hapd, goto fail; } - radius_client_send(hapd->radius, msg, - stop ? RADIUS_ACCT : RADIUS_ACCT_INTERIM, - sta->addr); + if (radius_client_send(hapd->radius, msg, + stop ? RADIUS_ACCT : RADIUS_ACCT_INTERIM, + sta->addr) < 0) + goto fail; return; fail: @@ -469,7 +471,8 @@ static void accounting_report_state(struct hostapd_data *hapd, int on) return; } - radius_client_send(hapd->radius, msg, RADIUS_ACCT, NULL); + if (radius_client_send(hapd->radius, msg, RADIUS_ACCT, NULL) < 0) + radius_msg_free(msg); } diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index b24cd90..cfb6b2d 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -471,10 +471,6 @@ static void hostapd_config_free_bss(struct hostapd_bss_config *conf) #endif /* CONFIG_WPS */ os_free(conf->roaming_consortium); - -#ifdef CONFIG_RADIUS_TEST - os_free(conf->dump_msk_file); -#endif /* CONFIG_RADIUS_TEST */ } diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index cc7122c..fe20fc2 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -104,6 +104,7 @@ struct hostapd_wpa_psk { u8 addr[ETH_ALEN]; }; +#define EAP_USER_MAX_METHODS 8 struct hostapd_eap_user { struct hostapd_eap_user *next; u8 *identity; @@ -111,7 +112,7 @@ struct hostapd_eap_user { struct { int vendor; u32 method; - } methods[EAP_MAX_METHODS]; + } methods[EAP_USER_MAX_METHODS]; u8 *password; size_t password_len; int phase2; @@ -219,11 +220,6 @@ struct hostapd_bss_config { /* dot11AssociationSAQueryRetryTimeout (in TUs) */ int assoc_sa_query_retry_timeout; #endif /* CONFIG_IEEE80211W */ - enum { - PSK_RADIUS_IGNORED = 0, - PSK_RADIUS_ACCEPTED = 1, - PSK_RADIUS_REQUIRED = 2 - } wpa_psk_radius; int wpa_pairwise; int wpa_group; int wpa_group_rekey; @@ -365,12 +361,6 @@ struct hostapd_bss_config { /* IEEE 802.11u - Roaming Consortium list */ unsigned int roaming_consortium_count; struct hostapd_roaming_consortium *roaming_consortium; - - u8 wps_rf_bands; /* RF bands for WPS (WPS_RF_*) */ - -#ifdef CONFIG_RADIUS_TEST - char *dump_msk_file; -#endif /* CONFIG_RADIUS_TEST */ }; diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c index 429c187..01c28b9 100644 --- a/src/ap/ap_drv_ops.c +++ b/src/ap/ap_drv_ops.c @@ -318,7 +318,7 @@ int hostapd_sta_add(struct hostapd_data *hapd, const u8 *supp_rates, size_t supp_rates_len, u16 listen_interval, const struct ieee80211_ht_capabilities *ht_capab, - u32 flags, u8 qosinfo) + u32 flags) { struct hostapd_sta_add_params params; @@ -336,7 +336,6 @@ int hostapd_sta_add(struct hostapd_data *hapd, params.listen_interval = listen_interval; params.ht_capabilities = ht_capab; params.flags = hostapd_sta_flags_to_drv(flags); - params.qosinfo = qosinfo; return hapd->driver->sta_add(hapd->drv_priv, ¶ms); } @@ -476,6 +475,16 @@ int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr, } +int hostapd_set_rate_sets(struct hostapd_data *hapd, int *supp_rates, + int *basic_rates, int mode) +{ + if (hapd->driver == NULL || hapd->driver->set_rate_sets == NULL) + return 0; + return hapd->driver->set_rate_sets(hapd->drv_priv, supp_rates, + basic_rates, mode); +} + + int hostapd_set_country(struct hostapd_data *hapd, const char *country) { if (hapd->driver == NULL || @@ -564,11 +573,11 @@ int hostapd_drv_set_key(const char *ifname, struct hostapd_data *hapd, int hostapd_drv_send_mlme(struct hostapd_data *hapd, - const void *msg, size_t len, int noack) + const void *msg, size_t len) { if (hapd->driver == NULL || hapd->driver->send_mlme == NULL) return 0; - return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack); + return hapd->driver->send_mlme(hapd->drv_priv, msg, len); } diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h index 835cdde..66e2cb8 100644 --- a/src/ap/ap_drv_ops.h +++ b/src/ap/ap_drv_ops.h @@ -43,7 +43,7 @@ int hostapd_sta_add(struct hostapd_data *hapd, const u8 *supp_rates, size_t supp_rates_len, u16 listen_interval, const struct ieee80211_ht_capabilities *ht_capab, - u32 flags, u8 qosinfo); + u32 flags); int hostapd_set_privacy(struct hostapd_data *hapd, int enabled); int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem, size_t elem_len); @@ -66,6 +66,8 @@ int hostapd_set_rts(struct hostapd_data *hapd, int rts); int hostapd_set_frag(struct hostapd_data *hapd, int frag); int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr, int total_flags, int flags_or, int flags_and); +int hostapd_set_rate_sets(struct hostapd_data *hapd, int *supp_rates, + int *basic_rates, int mode); int hostapd_set_country(struct hostapd_data *hapd, const char *country); int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs, int cw_min, int cw_max, int burst_time); @@ -87,7 +89,7 @@ int hostapd_drv_set_key(const char *ifname, const u8 *seq, size_t seq_len, const u8 *key, size_t key_len); int hostapd_drv_send_mlme(struct hostapd_data *hapd, - const void *msg, size_t len, int noack); + const void *msg, size_t len); int hostapd_drv_sta_deauth(struct hostapd_data *hapd, const u8 *addr, int reason); int hostapd_drv_sta_disassoc(struct hostapd_data *hapd, diff --git a/src/ap/authsrv.c b/src/ap/authsrv.c index 6f56c95..7c87fde 100644 --- a/src/ap/authsrv.c +++ b/src/ap/authsrv.c @@ -60,7 +60,7 @@ static int hostapd_radius_get_eap_user(void *ctx, const u8 *identity, struct eap_user *user) { const struct hostapd_eap_user *eap_user; - int i; + int i, count; eap_user = hostapd_get_eap_user(ctx, identity, identity_len, phase2); if (eap_user == NULL) @@ -70,7 +70,10 @@ static int hostapd_radius_get_eap_user(void *ctx, const u8 *identity, return 0; os_memset(user, 0, sizeof(*user)); - for (i = 0; i < EAP_MAX_METHODS; i++) { + count = EAP_USER_MAX_METHODS; + if (count > EAP_MAX_METHODS) + count = EAP_MAX_METHODS; + for (i = 0; i < count; i++) { user->methods[i].vendor = eap_user->methods[i].vendor; user->methods[i].method = eap_user->methods[i].method; } @@ -117,9 +120,6 @@ static int hostapd_setup_radius_srv(struct hostapd_data *hapd) srv.eap_req_id_text = conf->eap_req_id_text; srv.eap_req_id_text_len = conf->eap_req_id_text_len; srv.pwd_group = conf->pwd_group; -#ifdef CONFIG_RADIUS_TEST - srv.dump_msk_file = conf->dump_msk_file; -#endif /* CONFIG_RADIUS_TEST */ hapd->radius_srv = radius_server_init(&srv); if (hapd->radius_srv == NULL) { diff --git a/src/ap/beacon.c b/src/ap/beacon.c index 4d8b277..63b708a 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -186,122 +186,18 @@ static u8 * hostapd_eid_wpa(struct hostapd_data *hapd, u8 *eid, size_t len) } -static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, - struct sta_info *sta, - const struct ieee80211_mgmt *req, - int is_p2p, size_t *resp_len) -{ - struct ieee80211_mgmt *resp; - u8 *pos, *epos; - size_t buflen; - -#define MAX_PROBERESP_LEN 768 - buflen = MAX_PROBERESP_LEN; -#ifdef CONFIG_WPS - if (hapd->wps_probe_resp_ie) - buflen += wpabuf_len(hapd->wps_probe_resp_ie); -#endif /* CONFIG_WPS */ -#ifdef CONFIG_P2P - if (hapd->p2p_probe_resp_ie) - buflen += wpabuf_len(hapd->p2p_probe_resp_ie); -#endif /* CONFIG_P2P */ - resp = os_zalloc(buflen); - if (resp == NULL) - return NULL; - - epos = ((u8 *) resp) + MAX_PROBERESP_LEN; - - resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_PROBE_RESP); - if (req) - os_memcpy(resp->da, req->sa, ETH_ALEN); - os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN); - - os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN); - resp->u.probe_resp.beacon_int = - host_to_le16(hapd->iconf->beacon_int); - - /* hardware or low-level driver will setup seq_ctrl and timestamp */ - resp->u.probe_resp.capab_info = - host_to_le16(hostapd_own_capab_info(hapd, sta, 1)); - - pos = resp->u.probe_resp.variable; - *pos++ = WLAN_EID_SSID; - *pos++ = hapd->conf->ssid.ssid_len; - os_memcpy(pos, hapd->conf->ssid.ssid, hapd->conf->ssid.ssid_len); - pos += hapd->conf->ssid.ssid_len; - - /* Supported rates */ - pos = hostapd_eid_supp_rates(hapd, pos); - - /* DS Params */ - pos = hostapd_eid_ds_params(hapd, pos); - - pos = hostapd_eid_country(hapd, pos, epos - pos); - - /* ERP Information element */ - pos = hostapd_eid_erp_info(hapd, pos); - - /* Extended supported rates */ - pos = hostapd_eid_ext_supp_rates(hapd, pos); - - /* RSN, MDIE, WPA */ - pos = hostapd_eid_wpa(hapd, pos, epos - pos); - -#ifdef CONFIG_IEEE80211N - pos = hostapd_eid_ht_capabilities(hapd, pos); - pos = hostapd_eid_ht_operation(hapd, pos); -#endif /* CONFIG_IEEE80211N */ - - pos = hostapd_eid_ext_capab(hapd, pos); - - pos = hostapd_eid_time_adv(hapd, pos); - pos = hostapd_eid_time_zone(hapd, pos); - - pos = hostapd_eid_interworking(hapd, pos); - pos = hostapd_eid_adv_proto(hapd, pos); - pos = hostapd_eid_roaming_consortium(hapd, pos); - - /* Wi-Fi Alliance WMM */ - pos = hostapd_eid_wmm(hapd, pos); - -#ifdef CONFIG_WPS - if (hapd->conf->wps_state && hapd->wps_probe_resp_ie) { - os_memcpy(pos, wpabuf_head(hapd->wps_probe_resp_ie), - wpabuf_len(hapd->wps_probe_resp_ie)); - pos += wpabuf_len(hapd->wps_probe_resp_ie); - } -#endif /* CONFIG_WPS */ - -#ifdef CONFIG_P2P - if ((hapd->conf->p2p & P2P_ENABLED) && is_p2p && - hapd->p2p_probe_resp_ie) { - os_memcpy(pos, wpabuf_head(hapd->p2p_probe_resp_ie), - wpabuf_len(hapd->p2p_probe_resp_ie)); - pos += wpabuf_len(hapd->p2p_probe_resp_ie); - } -#endif /* CONFIG_P2P */ -#ifdef CONFIG_P2P_MANAGER - if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) == - P2P_MANAGE) - pos = hostapd_eid_p2p_manage(hapd, pos); -#endif /* CONFIG_P2P_MANAGER */ - - *resp_len = pos - (u8 *) resp; - return (u8 *) resp; -} - - void handle_probe_req(struct hostapd_data *hapd, const struct ieee80211_mgmt *mgmt, size_t len) { - u8 *resp; + struct ieee80211_mgmt *resp; struct ieee802_11_elems elems; + char *ssid; + u8 *pos, *epos; const u8 *ie; - size_t ie_len; + size_t ssid_len, ie_len; struct sta_info *sta = NULL; - size_t i, resp_len; - int noack; + size_t buflen; + size_t i; ie = mgmt->u.probe_req.variable; if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req)) @@ -323,6 +219,9 @@ void handle_probe_req(struct hostapd_data *hapd, return; } + ssid = NULL; + ssid_len = 0; + if ((!elems.ssid || !elems.supp_rates)) { wpa_printf(MSG_DEBUG, "STA " MACSTR " sent probe request " "without SSID or supported rates element", @@ -343,6 +242,18 @@ void handle_probe_req(struct hostapd_data *hapd, } wpabuf_free(wps); } + + if (hapd->p2p && elems.p2p) { + struct wpabuf *p2p; + p2p = ieee802_11_vendor_ie_concat(ie, ie_len, P2P_IE_VENDOR_TYPE); + if (p2p && !p2p_group_match_dev_id(hapd->p2p_group, p2p)) { + wpa_printf(MSG_MSGDUMP, "P2P: Ignore Probe Request " + "due to mismatch with Device ID"); + wpabuf_free(p2p); + return; + } + wpabuf_free(p2p); + } #endif /* CONFIG_P2P */ if (hapd->conf->ignore_broadcast_ssid && elems.ssid_len == 0) { @@ -367,9 +278,13 @@ void handle_probe_req(struct hostapd_data *hapd, (elems.ssid_len == hapd->conf->ssid.ssid_len && os_memcmp(elems.ssid, hapd->conf->ssid.ssid, elems.ssid_len) == 0)) { + ssid = hapd->conf->ssid.ssid; + ssid_len = hapd->conf->ssid.ssid_len; if (sta) sta->ssid_probe = &hapd->conf->ssid; - } else { + } + + if (!ssid) { if (!(mgmt->da[0] & 0x01)) { char ssid_txt[33]; ieee802_11_print_ssid(ssid_txt, elems.ssid, @@ -414,62 +329,104 @@ void handle_probe_req(struct hostapd_data *hapd, /* TODO: verify that supp_rates contains at least one matching rate * with AP configuration */ - - resp = hostapd_gen_probe_resp(hapd, sta, mgmt, elems.p2p != NULL, - &resp_len); +#define MAX_PROBERESP_LEN 768 + buflen = MAX_PROBERESP_LEN; +#ifdef CONFIG_WPS + if (hapd->wps_probe_resp_ie) + buflen += wpabuf_len(hapd->wps_probe_resp_ie); +#endif /* CONFIG_WPS */ +#ifdef CONFIG_P2P + if (hapd->p2p_probe_resp_ie) + buflen += wpabuf_len(hapd->p2p_probe_resp_ie); +#endif /* CONFIG_P2P */ + resp = os_zalloc(buflen); if (resp == NULL) return; + epos = ((u8 *) resp) + MAX_PROBERESP_LEN; - /* - * If this is a broadcast probe request, apply no ack policy to avoid - * excessive retries. - */ - noack = !!(elems.ssid_len == 0 && is_broadcast_ether_addr(mgmt->da)); + resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, + WLAN_FC_STYPE_PROBE_RESP); + os_memcpy(resp->da, mgmt->sa, ETH_ALEN); + os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN); - if (hostapd_drv_send_mlme(hapd, resp, resp_len, noack) < 0) - perror("handle_probe_req: send"); + os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN); + resp->u.probe_resp.beacon_int = + host_to_le16(hapd->iconf->beacon_int); - os_free(resp); + /* hardware or low-level driver will setup seq_ctrl and timestamp */ + resp->u.probe_resp.capab_info = + host_to_le16(hostapd_own_capab_info(hapd, sta, 1)); - wpa_printf(MSG_EXCESSIVE, "STA " MACSTR " sent probe request for %s " - "SSID", MAC2STR(mgmt->sa), - elems.ssid_len == 0 ? "broadcast" : "our"); -} + pos = resp->u.probe_resp.variable; + *pos++ = WLAN_EID_SSID; + *pos++ = ssid_len; + os_memcpy(pos, ssid, ssid_len); + pos += ssid_len; + /* Supported rates */ + pos = hostapd_eid_supp_rates(hapd, pos); -static u8 * hostapd_probe_resp_offloads(struct hostapd_data *hapd, - size_t *resp_len) -{ - /* check probe response offloading caps and print warnings */ - if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_PROBE_RESP_OFFLOAD)) - return NULL; + /* DS Params */ + pos = hostapd_eid_ds_params(hapd, pos); + + pos = hostapd_eid_country(hapd, pos, epos - pos); + + /* ERP Information element */ + pos = hostapd_eid_erp_info(hapd, pos); + + /* Extended supported rates */ + pos = hostapd_eid_ext_supp_rates(hapd, pos); + + /* RSN, MDIE, WPA */ + pos = hostapd_eid_wpa(hapd, pos, epos - pos); + +#ifdef CONFIG_IEEE80211N + pos = hostapd_eid_ht_capabilities(hapd, pos); + pos = hostapd_eid_ht_operation(hapd, pos); +#endif /* CONFIG_IEEE80211N */ + + pos = hostapd_eid_ext_capab(hapd, pos); + + pos = hostapd_eid_time_adv(hapd, pos); + pos = hostapd_eid_time_zone(hapd, pos); + + pos = hostapd_eid_interworking(hapd, pos); + pos = hostapd_eid_adv_proto(hapd, pos); + pos = hostapd_eid_roaming_consortium(hapd, pos); + + /* Wi-Fi Alliance WMM */ + pos = hostapd_eid_wmm(hapd, pos); #ifdef CONFIG_WPS - if (hapd->conf->wps_state && hapd->wps_probe_resp_ie && - (!(hapd->iface->probe_resp_offloads & - (WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS | - WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS2)))) - wpa_printf(MSG_WARNING, "Device is trying to offload WPS " - "Probe Response while not supporting this"); + if (hapd->conf->wps_state && hapd->wps_probe_resp_ie) { + os_memcpy(pos, wpabuf_head(hapd->wps_probe_resp_ie), + wpabuf_len(hapd->wps_probe_resp_ie)); + pos += wpabuf_len(hapd->wps_probe_resp_ie); + } #endif /* CONFIG_WPS */ #ifdef CONFIG_P2P - if ((hapd->conf->p2p & P2P_ENABLED) && hapd->p2p_probe_resp_ie && - !(hapd->iface->probe_resp_offloads & - WPA_DRIVER_PROBE_RESP_OFFLOAD_P2P)) - wpa_printf(MSG_WARNING, "Device is trying to offload P2P " - "Probe Response while not supporting this"); -#endif /* CONFIG_P2P */ + if ((hapd->conf->p2p & P2P_ENABLED) && elems.p2p && + hapd->p2p_probe_resp_ie) { + os_memcpy(pos, wpabuf_head(hapd->p2p_probe_resp_ie), + wpabuf_len(hapd->p2p_probe_resp_ie)); + pos += wpabuf_len(hapd->p2p_probe_resp_ie); + } +#endif /* CONFIG_P2P */ +#ifdef CONFIG_P2P_MANAGER + if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) == + P2P_MANAGE) + pos = hostapd_eid_p2p_manage(hapd, pos); +#endif /* CONFIG_P2P_MANAGER */ - if (hapd->conf->interworking && - !(hapd->iface->probe_resp_offloads & - WPA_DRIVER_PROBE_RESP_OFFLOAD_INTERWORKING)) - wpa_printf(MSG_WARNING, "Device is trying to offload " - "Interworking Probe Response while not supporting " - "this"); - - /* Generate a Probe Response template for the non-P2P case */ - return hostapd_gen_probe_resp(hapd, NULL, NULL, 0, resp_len); + if (hostapd_drv_send_mlme(hapd, resp, pos - (u8 *) resp) < 0) + perror("handle_probe_req: send"); + + os_free(resp); + + wpa_printf(MSG_EXCESSIVE, "STA " MACSTR " sent probe request for %s " + "SSID", MAC2STR(mgmt->sa), + elems.ssid_len == 0 ? "broadcast" : "our"); } #endif /* NEED_AP_MLME */ @@ -480,8 +437,6 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd) struct ieee80211_mgmt *head = NULL; u8 *tail = NULL; size_t head_len = 0, tail_len = 0; - u8 *resp = NULL; - size_t resp_len = 0; struct wpa_driver_ap_params params; struct wpabuf *beacon, *proberesp, *assocresp; #ifdef NEED_AP_MLME @@ -608,7 +563,6 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd) tail_len = tailpos > tail ? tailpos - tail : 0; - resp = hostapd_probe_resp_offloads(hapd, &resp_len); #endif /* NEED_AP_MLME */ os_memset(¶ms, 0, sizeof(params)); @@ -616,11 +570,8 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd) params.head_len = head_len; params.tail = tail; params.tail_len = tail_len; - params.proberesp = resp; - params.proberesp_len = resp_len; params.dtim_period = hapd->conf->dtim_period; params.beacon_int = hapd->iconf->beacon_int; - params.basic_rates = hapd->iconf->basic_rates; params.ssid = (u8 *) hapd->conf->ssid.ssid; params.ssid_len = hapd->conf->ssid.ssid_len; params.pairwise_ciphers = hapd->conf->rsn_pairwise ? @@ -676,7 +627,6 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd) os_free(tail); os_free(head); - os_free(resp); } diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index b7febdc..8844132 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -19,6 +19,7 @@ #include "drivers/driver.h" #include "common/ieee802_11_defs.h" #include "common/ieee802_11_common.h" +#include "common/wpa_ctrl.h" #include "crypto/random.h" #include "p2p/p2p.h" #include "wps/wps.h" @@ -27,8 +28,10 @@ #include "sta_info.h" #include "accounting.h" #include "tkip_countermeasures.h" +#include "iapp.h" #include "ieee802_1x.h" #include "wpa_auth.h" +#include "wmm.h" #include "wps_hostapd.h" #include "ap_drv_ops.h" #include "ap_config.h" @@ -84,6 +87,12 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, sta = ap_get_sta(hapd, addr); if (sta) { accounting_sta_stop(hapd, sta); + + /* + * Make sure that the previously registered inactivity timer + * will not remove the STA immediately. + */ + sta->timeout_next = STA_NULLFUNC; } else { sta = ap_sta_add(hapd, addr); if (sta == NULL) @@ -469,23 +478,6 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, union wpa_event_data *data) { struct hostapd_data *hapd = ctx; -#ifndef CONFIG_NO_STDOUT_DEBUG - int level = MSG_DEBUG; - - if (event == EVENT_RX_MGMT && data && data->rx_mgmt.frame && - data->rx_mgmt.frame_len >= 24) { - const struct ieee80211_hdr *hdr; - u16 fc; - hdr = (const struct ieee80211_hdr *) data->rx_mgmt.frame; - fc = le_to_host16(hdr->frame_control); - if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && - WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON) - level = MSG_EXCESSIVE; - } - - wpa_dbg(hapd->msg_ctx, level, "Event %s (%d) received", - event_to_string(event), event); -#endif /* CONFIG_NO_STDOUT_DEBUG */ switch (event) { case EVENT_MICHAEL_MIC_FAILURE: @@ -521,12 +513,6 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, break; } break; - case EVENT_EAPOL_TX_STATUS: - hostapd_eapol_tx_status(hapd, data->eapol_tx_status.dst, - data->eapol_tx_status.data, - data->eapol_tx_status.data_len, - data->eapol_tx_status.ack); - break; case EVENT_DRIVER_CLIENT_POLL_OK: hostapd_client_poll_ok(hapd, data->client_poll.addr); break; diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index 0c5ee2e..95aa008 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -38,7 +38,7 @@ #include "p2p_hostapd.h" -static int hostapd_flush_old_stations(struct hostapd_data *hapd); +static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason); static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd); static int hostapd_broadcast_wep_clear(struct hostapd_data *hapd); @@ -111,7 +111,8 @@ int hostapd_reload_config(struct hostapd_iface *iface) * allow them to use the BSS anymore. */ for (j = 0; j < iface->num_bss; j++) { - hostapd_flush_old_stations(iface->bss[j]); + hostapd_flush_old_stations(iface->bss[j], + WLAN_REASON_PREV_AUTH_NOT_VALID); hostapd_broadcast_wep_clear(iface->bss[j]); #ifndef CONFIG_NO_RADIUS @@ -291,8 +292,6 @@ static void hostapd_cleanup_iface(struct hostapd_iface *iface) iface->hw_features = NULL; os_free(iface->current_rates); iface->current_rates = NULL; - os_free(iface->basic_rates); - iface->basic_rates = NULL; ap_list_deinit(iface); hostapd_config_free(iface->conf); iface->conf = NULL; @@ -339,7 +338,7 @@ static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd) } -static int hostapd_flush_old_stations(struct hostapd_data *hapd) +static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason) { int ret = 0; u8 addr[ETH_ALEN]; @@ -347,15 +346,14 @@ static int hostapd_flush_old_stations(struct hostapd_data *hapd) if (hostapd_drv_none(hapd) || hapd->drv_priv == NULL) return 0; - wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "Flushing old station entries"); + wpa_printf(MSG_DEBUG, "Flushing old station entries"); if (hostapd_flush(hapd)) { - wpa_msg(hapd->msg_ctx, MSG_WARNING, "Could not connect to " - "kernel driver"); + wpa_printf(MSG_WARNING, "Could not connect to kernel driver."); ret = -1; } - wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "Deauthenticate all stations"); + wpa_printf(MSG_DEBUG, "Deauthenticate all stations"); os_memset(addr, 0xff, ETH_ALEN); - hostapd_drv_sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID); + hostapd_drv_sta_deauth(hapd, addr, reason); hostapd_free_stas(hapd); return ret; @@ -525,7 +523,7 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first) if (conf->wmm_enabled < 0) conf->wmm_enabled = hapd->iconf->ieee80211n; - hostapd_flush_old_stations(hapd); + hostapd_flush_old_stations(hapd, WLAN_REASON_PREV_AUTH_NOT_VALID); hostapd_set_privacy(hapd, 0); hostapd_broadcast_wep_clear(hapd); @@ -744,7 +742,7 @@ int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err) } if (iface->current_mode) { - if (hostapd_prepare_rates(iface, iface->current_mode)) { + if (hostapd_prepare_rates(hapd, iface->current_mode)) { wpa_printf(MSG_ERROR, "Failed to prepare rates " "table."); hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, @@ -879,7 +877,7 @@ void hostapd_interface_deinit(struct hostapd_iface *iface) for (j = 0; j < iface->num_bss; j++) { struct hostapd_data *hapd = iface->bss[j]; hostapd_free_stas(hapd); - hostapd_flush_old_stations(hapd); + hostapd_flush_old_stations(hapd, WLAN_REASON_DEAUTH_LEAVING); hostapd_cleanup(hapd); } } diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h index 5b72768..72cf012 100644 --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h @@ -125,6 +125,7 @@ struct hostapd_data { struct wpabuf *wps_probe_resp_ie; #ifdef CONFIG_WPS unsigned int ap_pin_failures; + unsigned int ap_pin_failures_consecutive; struct upnp_wps_device_sm *wps_upnp; unsigned int ap_pin_lockout_time; #endif /* CONFIG_WPS */ @@ -149,7 +150,7 @@ struct hostapd_data { void *wps_event_cb_ctx; void (*sta_authorized_cb)(void *ctx, const u8 *mac_addr, - int authorized); + int authorized, const u8 *p2p_dev_addr); void *sta_authorized_cb_ctx; void (*setup_complete_cb)(void *ctx); @@ -192,13 +193,6 @@ struct hostapd_iface { struct ap_info *ap_iter_list; unsigned int drv_flags; - - /* - * A bitmap of supported protocols for probe response offload. See - * struct wpa_driver_capa in driver.h - */ - unsigned int probe_resp_offloads; - struct hostapd_hw_modes *hw_features; int num_hw_features; struct hostapd_hw_modes *current_mode; @@ -206,7 +200,6 @@ struct hostapd_iface { * current_mode->channels */ int num_rates; struct hostapd_rate_data *current_rates; - int *basic_rates; int freq; u16 hw_flags; diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c index 8c6fef2..e723543 100644 --- a/src/ap/hw_features.c +++ b/src/ap/hw_features.c @@ -2,7 +2,7 @@ * hostapd / Hardware feature query and different modes * Copyright 2002-2003, Instant802 Networks, Inc. * Copyright 2005-2006, Devicescape Software, Inc. - * Copyright (c) 2008-2011, Jouni Malinen + * Copyright (c) 2008-2009, Jouni Malinen * * 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 @@ -101,7 +101,7 @@ int hostapd_get_hw_features(struct hostapd_iface *iface) } -int hostapd_prepare_rates(struct hostapd_iface *iface, +int hostapd_prepare_rates(struct hostapd_data *hapd, struct hostapd_hw_modes *mode) { int i, num_basic_rates = 0; @@ -110,8 +110,8 @@ int hostapd_prepare_rates(struct hostapd_iface *iface, int basic_rates_g[] = { 10, 20, 55, 110, -1 }; int *basic_rates; - if (iface->conf->basic_rates) - basic_rates = iface->conf->basic_rates; + if (hapd->iconf->basic_rates) + basic_rates = hapd->iconf->basic_rates; else switch (mode->mode) { case HOSTAPD_MODE_IEEE80211A: basic_rates = basic_rates_a; @@ -126,20 +126,18 @@ int hostapd_prepare_rates(struct hostapd_iface *iface, return -1; } - i = 0; - while (basic_rates[i] >= 0) - i++; - os_free(iface->basic_rates); - iface->basic_rates = os_malloc(i * sizeof(int)); - if (iface->basic_rates) - os_memcpy(iface->basic_rates, basic_rates, i * sizeof(int)); + if (hostapd_set_rate_sets(hapd, hapd->iconf->supported_rates, + basic_rates, mode->mode)) { + wpa_printf(MSG_ERROR, "Failed to update rate sets in kernel " + "module"); + } - os_free(iface->current_rates); - iface->num_rates = 0; + os_free(hapd->iface->current_rates); + hapd->iface->num_rates = 0; - iface->current_rates = + hapd->iface->current_rates = os_zalloc(mode->num_rates * sizeof(struct hostapd_rate_data)); - if (!iface->current_rates) { + if (!hapd->iface->current_rates) { wpa_printf(MSG_ERROR, "Failed to allocate memory for rate " "table."); return -1; @@ -148,27 +146,27 @@ int hostapd_prepare_rates(struct hostapd_iface *iface, for (i = 0; i < mode->num_rates; i++) { struct hostapd_rate_data *rate; - if (iface->conf->supported_rates && - !hostapd_rate_found(iface->conf->supported_rates, + if (hapd->iconf->supported_rates && + !hostapd_rate_found(hapd->iconf->supported_rates, mode->rates[i])) continue; - rate = &iface->current_rates[iface->num_rates]; + rate = &hapd->iface->current_rates[hapd->iface->num_rates]; rate->rate = mode->rates[i]; if (hostapd_rate_found(basic_rates, rate->rate)) { rate->flags |= HOSTAPD_RATE_BASIC; num_basic_rates++; } wpa_printf(MSG_DEBUG, "RATE[%d] rate=%d flags=0x%x", - iface->num_rates, rate->rate, rate->flags); - iface->num_rates++; + hapd->iface->num_rates, rate->rate, rate->flags); + hapd->iface->num_rates++; } - if ((iface->num_rates == 0 || num_basic_rates == 0) && - (!iface->conf->ieee80211n || !iface->conf->require_ht)) { + if ((hapd->iface->num_rates == 0 || num_basic_rates == 0) && + (!hapd->iconf->ieee80211n || !hapd->iconf->require_ht)) { wpa_printf(MSG_ERROR, "No rates remaining in supported/basic " "rate sets (%d,%d).", - iface->num_rates, num_basic_rates); + hapd->iface->num_rates, num_basic_rates); return -1; } @@ -631,15 +629,8 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface) if (chan->flag & HOSTAPD_CHAN_DISABLED) { wpa_printf(MSG_ERROR, "channel [%i] (%i) is disabled for " - "use in AP mode, flags: 0x%x%s%s%s", - j, chan->chan, chan->flag, - chan->flag & HOSTAPD_CHAN_NO_IBSS ? - " NO-IBSS" : "", - chan->flag & - HOSTAPD_CHAN_PASSIVE_SCAN ? - " PASSIVE-SCAN" : "", - chan->flag & HOSTAPD_CHAN_RADAR ? - " RADAR" : ""); + "use in AP mode, flags: 0x%x", + j, chan->chan, chan->flag); } else { ok = 1; break; diff --git a/src/ap/hw_features.h b/src/ap/hw_features.h index abadcd1..b84bca6 100644 --- a/src/ap/hw_features.h +++ b/src/ap/hw_features.h @@ -2,7 +2,6 @@ * hostapd / Hardware feature query and different modes * Copyright 2002-2003, Instant802 Networks, Inc. * Copyright 2005-2006, Devicescape Software, Inc. - * Copyright (c) 2008-2011, Jouni Malinen * * 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 @@ -26,7 +25,7 @@ const char * hostapd_hw_mode_txt(int mode); int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan); int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq); int hostapd_check_ht_capab(struct hostapd_iface *iface); -int hostapd_prepare_rates(struct hostapd_iface *iface, +int hostapd_prepare_rates(struct hostapd_data *hapd, struct hostapd_hw_modes *mode); #else /* NEED_AP_MLME */ static inline void @@ -60,7 +59,7 @@ static inline int hostapd_check_ht_capab(struct hostapd_iface *iface) return 0; } -static inline int hostapd_prepare_rates(struct hostapd_iface *iface, +static inline int hostapd_prepare_rates(struct hostapd_data *hapd, struct hostapd_hw_modes *mode) { return 0; diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index a1a7270..d30d5ae 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -269,7 +269,7 @@ static void send_auth_reply(struct hostapd_data *hapd, " auth_alg=%d auth_transaction=%d resp=%d (IE len=%lu)", MAC2STR(dst), auth_alg, auth_transaction, resp, (unsigned long) ies_len); - if (hostapd_drv_send_mlme(hapd, reply, rlen, 0) < 0) + if (hostapd_drv_send_mlme(hapd, reply, rlen) < 0) perror("send_auth_reply: send"); os_free(buf); @@ -313,8 +313,6 @@ static void handle_auth(struct hostapd_data *hapd, const u8 *challenge = NULL; u32 session_timeout, acct_interim_interval; int vlan_id = 0; - u8 psk[PMK_LEN]; - int has_psk = 0; u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN]; size_t resp_ies_len = 0; @@ -349,7 +347,9 @@ static void handle_auth(struct hostapd_data *hapd, if (!(((hapd->conf->auth_algs & WPA_AUTH_ALG_OPEN) && auth_alg == WLAN_AUTH_OPEN) || #ifdef CONFIG_IEEE80211R - (hapd->conf->wpa && wpa_key_mgmt_ft(hapd->conf->wpa_key_mgmt) && + (hapd->conf->wpa && + (hapd->conf->wpa_key_mgmt & + (WPA_KEY_MGMT_FT_IEEE8021X | WPA_KEY_MGMT_FT_PSK)) && auth_alg == WLAN_AUTH_FT) || #endif /* CONFIG_IEEE80211R */ ((hapd->conf->auth_algs & WPA_AUTH_ALG_SHARED) && @@ -377,9 +377,7 @@ static void handle_auth(struct hostapd_data *hapd, res = hostapd_allowed_address(hapd, mgmt->sa, (u8 *) mgmt, len, &session_timeout, - &acct_interim_interval, &vlan_id, - psk, &has_psk); - + &acct_interim_interval, &vlan_id); if (res == HOSTAPD_ACL_REJECT) { printf("Station " MACSTR " not allowed to authenticate.\n", MAC2STR(mgmt->sa)); @@ -417,16 +415,6 @@ static void handle_auth(struct hostapd_data *hapd, HOSTAPD_LEVEL_INFO, "VLAN ID %d", sta->vlan_id); } - if (has_psk && hapd->conf->wpa_psk_radius != PSK_RADIUS_IGNORED) { - os_free(sta->psk); - sta->psk = os_malloc(PMK_LEN); - if (sta->psk) - os_memcpy(sta->psk, psk, PMK_LEN); - } else { - os_free(sta->psk); - sta->psk = NULL; - } - sta->flags &= ~WLAN_STA_PREAUTH; ieee802_1x_notify_pre_auth(sta->eapol_sm, 0); @@ -551,22 +539,15 @@ static u16 check_wmm(struct hostapd_data *hapd, struct sta_info *sta, const u8 *wmm_ie, size_t wmm_ie_len) { sta->flags &= ~WLAN_STA_WMM; - sta->qosinfo = 0; if (wmm_ie && hapd->conf->wmm_enabled) { - struct wmm_information_element *wmm; - - if (!hostapd_eid_wmm_valid(hapd, wmm_ie, wmm_ie_len)) { + if (!hostapd_eid_wmm_valid(hapd, wmm_ie, wmm_ie_len)) hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, HOSTAPD_LEVEL_DEBUG, "invalid WMM element in association " "request"); - return WLAN_STATUS_UNSPECIFIED_FAILURE; - } - - sta->flags |= WLAN_STA_WMM; - wmm = (struct wmm_information_element *) wmm_ie; - sta->qosinfo = wmm->qos_info; + else + sta->flags |= WLAN_STA_WMM; } return WLAN_STATUS_SUCCESS; } @@ -824,7 +805,7 @@ static void send_deauth(struct hostapd_data *hapd, const u8 *addr, send_len = IEEE80211_HDRLEN + sizeof(reply.u.deauth); reply.u.deauth.reason_code = host_to_le16(reason_code); - if (hostapd_drv_send_mlme(hapd, &reply, send_len, 0) < 0) + if (hostapd_drv_send_mlme(hapd, &reply, send_len) < 0) wpa_printf(MSG_INFO, "Failed to send deauth: %s", strerror(errno)); } @@ -930,7 +911,7 @@ static void send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta, send_len += p - reply->u.assoc_resp.variable; - if (hostapd_drv_send_mlme(hapd, reply, send_len, 0) < 0) + if (hostapd_drv_send_mlme(hapd, reply, send_len) < 0) wpa_printf(MSG_INFO, "Failed to send assoc resp: %s", strerror(errno)); } @@ -1342,7 +1323,7 @@ static void handle_action(struct hostapd_data *hapd, os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN); resp->u.action.category |= 0x80; - hostapd_drv_send_mlme(hapd, resp, len, 0); + hostapd_drv_send_mlme(hapd, resp, len); os_free(resp); } } @@ -1569,7 +1550,7 @@ static void handle_assoc_cb(struct hostapd_data *hapd, sta->supported_rates, sta->supported_rates_len, sta->listen_interval, sta->flags & WLAN_STA_HT ? &ht_cap : NULL, - sta->flags, sta->qosinfo)) { + sta->flags)) { hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_NOTICE, "Could not add STA to kernel driver"); @@ -1744,7 +1725,7 @@ void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr, break; } } - if (sta == NULL) + if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) return; if (sta->flags & WLAN_STA_PENDING_POLL) { wpa_printf(MSG_DEBUG, "STA " MACSTR " %s pending " @@ -1758,29 +1739,6 @@ void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr, } -void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst, - const u8 *data, size_t len, int ack) -{ - struct sta_info *sta; - struct hostapd_iface *iface = hapd->iface; - - sta = ap_get_sta(hapd, dst); - if (sta == NULL && iface->num_bss > 1) { - size_t j; - for (j = 0; j < iface->num_bss; j++) { - hapd = iface->bss[j]; - sta = ap_get_sta(hapd, dst); - if (sta) - break; - } - } - if (sta == NULL) - return; - - ieee802_1x_eapol_tx_status(hapd, sta, data, len, ack); -} - - void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr) { struct sta_info *sta; diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h index 43042a5..b358060 100644 --- a/src/ap/ieee802_11.h +++ b/src/ap/ieee802_11.h @@ -62,8 +62,6 @@ u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta, void update_ht_state(struct hostapd_data *hapd, struct sta_info *sta); void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr, const u8 *buf, size_t len, int ack); -void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst, - const u8 *data, size_t len, int ack); void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src, int wds); u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd, diff --git a/src/ap/ieee802_11_auth.c b/src/ap/ieee802_11_auth.c index f3f313d..88f97b7 100644 --- a/src/ap/ieee802_11_auth.c +++ b/src/ap/ieee802_11_auth.c @@ -21,7 +21,6 @@ #include "utils/common.h" #include "utils/eloop.h" -#include "crypto/sha1.h" #include "radius/radius.h" #include "radius/radius_client.h" #include "hostapd.h" @@ -41,8 +40,6 @@ struct hostapd_cached_radius_acl { u32 session_timeout; u32 acct_interim_interval; int vlan_id; - int has_psk; - u8 psk[PMK_LEN]; }; @@ -71,8 +68,7 @@ static void hostapd_acl_cache_free(struct hostapd_cached_radius_acl *acl_cache) static int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr, u32 *session_timeout, - u32 *acct_interim_interval, int *vlan_id, - u8 *psk, int *has_psk) + u32 *acct_interim_interval, int *vlan_id) { struct hostapd_cached_radius_acl *entry; struct os_time now; @@ -93,10 +89,6 @@ static int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr, entry->acct_interim_interval; if (vlan_id) *vlan_id = entry->vlan_id; - if (psk) - os_memcpy(psk, entry->psk, PMK_LEN); - if (has_psk) - *has_psk = entry->has_psk; return entry->accepted; } @@ -199,7 +191,8 @@ static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr, goto fail; } - radius_client_send(hapd->radius, msg, RADIUS_AUTH, addr); + if (radius_client_send(hapd->radius, msg, RADIUS_AUTH, addr) < 0) + goto fail; return 0; fail: @@ -218,14 +211,11 @@ static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr, * @session_timeout: Buffer for returning session timeout (from RADIUS) * @acct_interim_interval: Buffer for returning account interval (from RADIUS) * @vlan_id: Buffer for returning VLAN ID - * @psk: Buffer for returning WPA PSK - * @has_psk: Buffer for indicating whether psk was filled * Returns: HOSTAPD_ACL_ACCEPT, HOSTAPD_ACL_REJECT, or HOSTAPD_ACL_PENDING */ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr, const u8 *msg, size_t len, u32 *session_timeout, - u32 *acct_interim_interval, int *vlan_id, - u8 *psk, int *has_psk) + u32 *acct_interim_interval, int *vlan_id) { if (session_timeout) *session_timeout = 0; @@ -233,10 +223,6 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr, *acct_interim_interval = 0; if (vlan_id) *vlan_id = 0; - if (has_psk) - *has_psk = 0; - if (psk) - os_memset(psk, 0, PMK_LEN); if (hostapd_maclist_found(hapd->conf->accept_mac, hapd->conf->num_accept_mac, addr, vlan_id)) @@ -261,7 +247,7 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr, /* Check whether ACL cache has an entry for this station */ int res = hostapd_acl_cache_get(hapd, addr, session_timeout, acct_interim_interval, - vlan_id, psk, has_psk); + vlan_id); if (res == HOSTAPD_ACL_ACCEPT || res == HOSTAPD_ACL_ACCEPT_TIMEOUT) return res; @@ -453,9 +439,6 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req, cache->timestamp = t.sec; os_memcpy(cache->addr, query->addr, sizeof(cache->addr)); if (hdr->code == RADIUS_CODE_ACCESS_ACCEPT) { - int passphraselen; - char *passphrase; - if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_SESSION_TIMEOUT, &cache->session_timeout) == 0) cache->accepted = HOSTAPD_ACL_ACCEPT_TIMEOUT; @@ -474,32 +457,6 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req, } cache->vlan_id = radius_msg_get_vlanid(msg); - - passphrase = radius_msg_get_tunnel_password( - msg, &passphraselen, - hapd->conf->radius->auth_server->shared_secret, - hapd->conf->radius->auth_server->shared_secret_len, - req); - cache->has_psk = passphrase != NULL; - if (passphrase != NULL) { - /* passphrase does not contain the NULL termination. - * Add it here as pbkdf2_sha1 requires it. */ - char *strpassphrase = os_zalloc(passphraselen + 1); - if (strpassphrase) { - os_memcpy(strpassphrase, passphrase, - passphraselen); - pbkdf2_sha1(strpassphrase, - hapd->conf->ssid.ssid, - hapd->conf->ssid.ssid_len, 4096, - cache->psk, PMK_LEN); - os_free(strpassphrase); - } - os_free(passphrase); - } - - if (hapd->conf->wpa_psk_radius == PSK_RADIUS_REQUIRED && - cache->psk == NULL) - cache->accepted = HOSTAPD_ACL_REJECT; } else cache->accepted = HOSTAPD_ACL_REJECT; cache->next = hapd->acl_cache; diff --git a/src/ap/ieee802_11_auth.h b/src/ap/ieee802_11_auth.h index a90571f..b2971e5 100644 --- a/src/ap/ieee802_11_auth.h +++ b/src/ap/ieee802_11_auth.h @@ -24,8 +24,7 @@ enum { int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr, const u8 *msg, size_t len, u32 *session_timeout, - u32 *acct_interim_interval, int *vlan_id, - u8 *psk, int *has_psk); + u32 *acct_interim_interval, int *vlan_id); int hostapd_acl_init(struct hostapd_data *hapd); void hostapd_acl_deinit(struct hostapd_data *hapd); diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c index 8503fce..c447bce 100644 --- a/src/ap/ieee802_11_shared.c +++ b/src/ap/ieee802_11_shared.c @@ -74,13 +74,13 @@ void ieee802_11_send_sa_query_req(struct hostapd_data *hapd, os_memcpy(mgmt.u.action.u.sa_query_req.trans_id, trans_id, WLAN_SA_QUERY_TR_ID_LEN); end = mgmt.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN; - if (hostapd_drv_send_mlme(hapd, &mgmt, end - (u8 *) &mgmt, 0) < 0) + if (hostapd_drv_send_mlme(hapd, &mgmt, end - (u8 *) &mgmt) < 0) perror("ieee802_11_send_sa_query_req: send"); } -static void ieee802_11_send_sa_query_resp(struct hostapd_data *hapd, - const u8 *sa, const u8 *trans_id) +void ieee802_11_send_sa_query_resp(struct hostapd_data *hapd, + const u8 *sa, const u8 *trans_id) { struct sta_info *sta; struct ieee80211_mgmt resp; @@ -112,7 +112,7 @@ static void ieee802_11_send_sa_query_resp(struct hostapd_data *hapd, os_memcpy(resp.u.action.u.sa_query_req.trans_id, trans_id, WLAN_SA_QUERY_TR_ID_LEN); end = resp.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN; - if (hostapd_drv_send_mlme(hapd, &resp, end - (u8 *) &resp, 0) < 0) + if (hostapd_drv_send_mlme(hapd, &resp, end - (u8 *) &resp) < 0) perror("ieee80211_mgmt_sa_query_request: send"); } diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c index 153b271..f9a0cbb 100644 --- a/src/ap/ieee802_1x.c +++ b/src/ap/ieee802_1x.c @@ -1,6 +1,6 @@ /* * hostapd / IEEE 802.1X-2004 Authenticator - * Copyright (c) 2002-2011, Jouni Malinen + * Copyright (c) 2002-2012, Jouni Malinen * * 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 @@ -20,6 +20,7 @@ #include "crypto/crypto.h" #include "crypto/random.h" #include "common/ieee802_11_defs.h" +#include "common/wpa_ctrl.h" #include "radius/radius.h" #include "radius/radius_client.h" #include "eap_server/eap.h" @@ -867,12 +868,22 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta) if (!force_1x && !hapd->conf->ieee802_1x) { wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore STA - " "802.1X not enabled or forced for WPS"); + /* + * Clear any possible EAPOL authenticator state to support + * reassociation change from WPS to PSK. + */ + ieee802_1x_free_station(sta); return; } key_mgmt = wpa_auth_sta_key_mgmt(sta->wpa_sm); if (key_mgmt != -1 && wpa_key_mgmt_wpa_psk(key_mgmt)) { wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore STA - using PSK"); + /* + * Clear any possible EAPOL authenticator state to support + * reassociation change from WPA-EAP to PSK. + */ + ieee802_1x_free_station(sta); return; } @@ -918,6 +929,7 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta) sta->eapol_sm->auth_pae_state = AUTH_PAE_AUTHENTICATING; sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS; sta->eapol_sm->authSuccess = TRUE; + sta->eapol_sm->authFail = FALSE; if (sta->eapol_sm->eap) eap_sm_notify_cached(sta->eapol_sm->eap); /* TODO: get vlan_id from R0KH using RRB message */ @@ -939,6 +951,7 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta) sta->eapol_sm->auth_pae_state = AUTH_PAE_AUTHENTICATING; sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS; sta->eapol_sm->authSuccess = TRUE; + sta->eapol_sm->authFail = FALSE; if (sta->eapol_sm->eap) eap_sm_notify_cached(sta->eapol_sm->eap); old_vlanid = sta->vlan_id; @@ -1417,9 +1430,6 @@ void ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta) * request and we cannot continue EAP processing (EAP-Failure * could only be sent if the EAP peer actually replied). */ - wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "EAP Timeout, STA " MACSTR, - MAC2STR(sta->addr)); - sm->eap_if->portEnabled = FALSE; ap_sta_disconnect(hapd, sta, sta->addr, WLAN_REASON_PREV_AUTH_NOT_VALID); @@ -1572,7 +1582,7 @@ static int ieee802_1x_get_eap_user(void *ctx, const u8 *identity, { struct hostapd_data *hapd = ctx; const struct hostapd_eap_user *eap_user; - int i; + int i, count; eap_user = hostapd_get_eap_user(hapd->conf, identity, identity_len, phase2); @@ -1581,7 +1591,10 @@ static int ieee802_1x_get_eap_user(void *ctx, const u8 *identity, os_memset(user, 0, sizeof(*user)); user->phase2 = phase2; - for (i = 0; i < EAP_MAX_METHODS; i++) { + count = EAP_USER_MAX_METHODS; + if (count > EAP_MAX_METHODS) + count = EAP_MAX_METHODS; + for (i = 0; i < count; i++) { user->methods[i].vendor = eap_user->methods[i].vendor; user->methods[i].method = eap_user->methods[i].method; } @@ -1770,13 +1783,15 @@ int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta, const u8 *buf, size_t len, int ack) { struct ieee80211_hdr *hdr; + struct ieee802_1x_hdr *xhdr; + struct ieee802_1x_eapol_key *key; u8 *pos; const unsigned char rfc1042_hdr[ETH_ALEN] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; if (sta == NULL) return -1; - if (len < sizeof(*hdr) + sizeof(rfc1042_hdr) + 2) + if (len < sizeof(*hdr) + sizeof(rfc1042_hdr) + 2 + sizeof(*xhdr)) return 0; hdr = (struct ieee80211_hdr *) buf; @@ -1788,30 +1803,16 @@ int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta, return 0; pos += 2; - return ieee802_1x_eapol_tx_status(hapd, sta, pos, buf + len - pos, - ack); -} - - -int ieee802_1x_eapol_tx_status(struct hostapd_data *hapd, struct sta_info *sta, - const u8 *buf, int len, int ack) -{ - const struct ieee802_1x_hdr *xhdr = - (const struct ieee802_1x_hdr *) buf; - const u8 *pos = buf + sizeof(*xhdr); - struct ieee802_1x_eapol_key *key; + xhdr = (struct ieee802_1x_hdr *) pos; + pos += sizeof(*xhdr); - if (len < (int) sizeof(*xhdr)) - return 0; wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR " TX status - version=%d " "type=%d length=%d - ack=%d", MAC2STR(sta->addr), xhdr->version, xhdr->type, be_to_host16(xhdr->length), ack); - if (xhdr->type != IEEE802_1X_TYPE_EAPOL_KEY) - return 0; - - if (pos + sizeof(struct wpa_eapol_key) <= buf + len) { + if (xhdr->type == IEEE802_1X_TYPE_EAPOL_KEY && + pos + sizeof(struct wpa_eapol_key) <= buf + len) { const struct wpa_eapol_key *wpa; wpa = (const struct wpa_eapol_key *) pos; if (wpa->type == EAPOL_KEY_TYPE_RSN || @@ -1825,7 +1826,8 @@ int ieee802_1x_eapol_tx_status(struct hostapd_data *hapd, struct sta_info *sta, * retransmitted in case of failure. Try to re-send failed EAPOL-Key * packets couple of times because otherwise STA keys become * unsynchronized with AP. */ - if (!ack && pos + sizeof(*key) <= buf + len) { + if (xhdr->type == IEEE802_1X_TYPE_EAPOL_KEY && !ack && + pos + sizeof(*key) <= buf + len) { key = (struct ieee802_1x_eapol_key *) pos; hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, HOSTAPD_LEVEL_DEBUG, "did not Ack EAPOL-Key " @@ -2097,8 +2099,8 @@ static void ieee802_1x_finished(struct hostapd_data *hapd, * EAP-FAST with anonymous provisioning, may require another * EAPOL authentication to be started to complete connection. */ - wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "IEEE 802.1X: Force " - "disconnection after EAP-Failure"); + wpa_printf(MSG_DEBUG, "IEEE 802.1X: Force disconnection after " + "EAP-Failure"); /* Add a small sleep to increase likelihood of previously * requested EAP-Failure TX getting out before this should the * driver reorder operations. diff --git a/src/ap/ieee802_1x.h b/src/ap/ieee802_1x.h index 267e22a..1a4d2eb 100644 --- a/src/ap/ieee802_1x.h +++ b/src/ap/ieee802_1x.h @@ -68,8 +68,6 @@ int ieee802_1x_init(struct hostapd_data *hapd); void ieee802_1x_deinit(struct hostapd_data *hapd); int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta, const u8 *buf, size_t len, int ack); -int ieee802_1x_eapol_tx_status(struct hostapd_data *hapd, struct sta_info *sta, - const u8 *data, int len, int ack); u8 * ieee802_1x_get_identity(struct eapol_state_machine *sm, size_t *len); u8 * ieee802_1x_get_radius_class(struct eapol_state_machine *sm, size_t *len, int idx); diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c index d9c348e..82a3f69 100644 --- a/src/ap/sta_info.c +++ b/src/ap/sta_info.c @@ -228,7 +228,6 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) wpabuf_free(sta->p2p_ie); os_free(sta->ht_capabilities); - os_free(sta->psk); os_free(sta); } @@ -284,8 +283,14 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx) if (inactive_sec == -1) { wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Check inactivity: Could not " - "get station info rom kernel driver for " + "get station info from kernel driver for " MACSTR, MAC2STR(sta->addr)); + /* + * The driver may not support this functionality. + * Anyway, try again after the next inactivity timeout, + * but do not disconnect the station now. + */ + next_time = hapd->conf->ap_max_inactivity; } else if (inactive_sec < hapd->conf->ap_max_inactivity && sta->flags & WLAN_STA_ASSOC) { /* station activity detected; reset timeout state */ @@ -330,10 +335,9 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx) } else if (sta->timeout_next != STA_REMOVE) { int deauth = sta->timeout_next == STA_DEAUTH; - wpa_dbg(hapd->msg_ctx, MSG_DEBUG, - "Timeout, sending %s info to STA " MACSTR, - deauth ? "deauthentication" : "disassociation", - MAC2STR(sta->addr)); + wpa_printf(MSG_DEBUG, "Sending %s info to STA " MACSTR, + deauth ? "deauthentication" : "disassociation", + MAC2STR(sta->addr)); if (deauth) { hostapd_drv_sta_deauth( @@ -374,7 +378,7 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx) case STA_REMOVE: hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "deauthenticated due to " - "inactivity (timer DEAUTH/REMOVE)"); + "inactivity"); if (!sta->acct_terminate_cause) sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT; @@ -824,7 +828,7 @@ void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta, if (hapd->sta_authorized_cb) hapd->sta_authorized_cb(hapd->sta_authorized_cb_ctx, - sta->addr, authorized); + sta->addr, authorized, dev_addr); } @@ -841,6 +845,8 @@ void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta, if (sta == NULL) return; ap_sta_set_authorized(hapd, sta, 0); + wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH); + ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); eloop_cancel_timeout(ap_handle_timer, hapd, sta); eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0, diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h index daa96bf..3ad00e2 100644 --- a/src/ap/sta_info.h +++ b/src/ap/sta_info.h @@ -52,7 +52,6 @@ struct sta_info { u16 listen_interval; /* or beacon_int for APs */ u8 supported_rates[WLAN_SUPP_RATES_MAX]; int supported_rates_len; - u8 qosinfo; /* Valid when WLAN_STA_WMM is set */ unsigned int nonerp_set:1; unsigned int no_short_slot_time_set:1; @@ -99,7 +98,6 @@ struct sta_info { struct hostapd_ssid *ssid_probe; /* SSID selection based on ProbeReq */ int vlan_id; - u8 *psk; /* PSK from RADIUS authentication server */ struct ieee80211_ht_capabilities *ht_capabilities; diff --git a/src/ap/wmm.c b/src/ap/wmm.c index d21c82f..82177f3 100644 --- a/src/ap/wmm.c +++ b/src/ap/wmm.c @@ -72,8 +72,7 @@ u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid) wmm->version = WMM_VERSION; wmm->qos_info = hapd->parameter_set_count & 0xf; - if (hapd->conf->wmm_uapsd && - (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_UAPSD)) + if (hapd->conf->wmm_uapsd) wmm->qos_info |= 0x80; wmm->reserved = 0; @@ -156,7 +155,7 @@ static void wmm_send_action(struct hostapd_data *hapd, const u8 *addr, os_memcpy(t, tspec, sizeof(struct wmm_tspec_element)); len = ((u8 *) (t + 1)) - buf; - if (hostapd_drv_send_mlme(hapd, m, len, 0) < 0) + if (hostapd_drv_send_mlme(hapd, m, len) < 0) perror("wmm_send_action: send"); } diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 1b5a5a2..34202b6 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -194,7 +194,6 @@ static void wpa_sta_disconnect(struct wpa_authenticator *wpa_auth, { if (wpa_auth->cb.disconnect == NULL) return; - wpa_printf(MSG_DEBUG, "wpa_sta_disconnect STA " MACSTR, MAC2STR(addr)); wpa_auth->cb.disconnect(wpa_auth->cb.ctx, addr, WLAN_REASON_PREV_AUTH_NOT_VALID); } @@ -780,7 +779,14 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, } if (sm->wpa == WPA_VERSION_WPA2) { - if (key->type != EAPOL_KEY_TYPE_RSN) { + if (key->type == EAPOL_KEY_TYPE_WPA) { + /* + * Some deployed station implementations seem to send + * msg 4/4 with incorrect type value in WPA2 mode. + */ + wpa_printf(MSG_DEBUG, "Workaround: Allow EAPOL-Key " + "with unexpected WPA type in RSN mode"); + } else if (key->type != EAPOL_KEY_TYPE_RSN) { wpa_printf(MSG_DEBUG, "Ignore EAPOL-Key with " "unexpected type %d in RSN mode", key->type); @@ -869,7 +875,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, if (!(key_info & WPA_KEY_INFO_REQUEST) && !wpa_replay_counter_valid(sm, key->replay_counter)) { int i; - wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, "received EAPOL-Key %s with unexpected " "replay counter", msgtxt); for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) { @@ -1070,9 +1076,6 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, "received EAPOL-Key Request for GTK " "rekeying"); - /* FIX: why was this triggering PTK rekeying for the - * STA that requested Group Key rekeying?? */ - /* wpa_request_new_ptk(sta->wpa_sm); */ eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL); wpa_rekey_gtk(wpa_auth, NULL); } diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index 2d1bbe4..4a7d619 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -24,6 +24,7 @@ #include "wmm.h" #include "wpa_auth.h" #include "wpa_auth_i.h" +#include "wpa_auth_ie.h" #ifdef CONFIG_IEEE80211R diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index 56bab23..d44381d 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -29,7 +29,6 @@ #include "ap_drv_ops.h" #include "ap_config.h" #include "wpa_auth.h" -#include "wpa_auth_glue.h" static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, @@ -186,9 +185,6 @@ static const u8 * hostapd_wpa_auth_get_psk(void *ctx, const u8 *addr, const u8 *prev_psk) { struct hostapd_data *hapd = ctx; - struct sta_info *sta = ap_get_sta(hapd, addr); - if (sta && sta->psk) - return sta->psk; return hostapd_get_psk(hapd->conf, addr, prev_psk); } @@ -419,7 +415,7 @@ static int hostapd_wpa_auth_send_ft_action(void *ctx, const u8 *dst, os_memcpy(m->bssid, hapd->own_addr, ETH_ALEN); os_memcpy(&m->u, data, data_len); - res = hostapd_drv_send_mlme(hapd, (u8 *) m, mlen, 0); + res = hostapd_drv_send_mlme(hapd, (u8 *) m, mlen); os_free(m); return res; } diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c index 4db04bb..5e8d134 100644 --- a/src/ap/wpa_auth_ie.c +++ b/src/ap/wpa_auth_ie.c @@ -341,7 +341,8 @@ int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth) pos += res; } #ifdef CONFIG_IEEE80211R - if (wpa_key_mgmt_ft(wpa_auth->conf.wpa_key_mgmt)) { + if (wpa_auth->conf.wpa_key_mgmt & + (WPA_KEY_MGMT_FT_IEEE8021X | WPA_KEY_MGMT_FT_PSK)) { res = wpa_write_mdie(&wpa_auth->conf, pos, buf + sizeof(buf) - pos); if (res < 0) diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c index 817012e..4b31d4f 100644 --- a/src/ap/wps_hostapd.c +++ b/src/ap/wps_hostapd.c @@ -512,6 +512,8 @@ static void hostapd_wps_reenable_ap_pin(void *eloop_data, void *user_ctx) if (hapd->conf->ap_setup_locked) return; + if (hapd->ap_pin_failures_consecutive >= 10) + return; wpa_printf(MSG_DEBUG, "WPS: Re-enable AP PIN"); wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_SETUP_UNLOCKED); @@ -533,8 +535,10 @@ static int wps_pwd_auth_fail(struct hostapd_data *hapd, void *ctx) * force attacks. */ hapd->ap_pin_failures++; - wpa_printf(MSG_DEBUG, "WPS: AP PIN authentication failure number %u", - hapd->ap_pin_failures); + hapd->ap_pin_failures_consecutive++; + wpa_printf(MSG_DEBUG, "WPS: AP PIN authentication failure number %u " + "(%u consecutive)", + hapd->ap_pin_failures, hapd->ap_pin_failures_consecutive); if (hapd->ap_pin_failures < 3) return 0; @@ -543,7 +547,15 @@ static int wps_pwd_auth_fail(struct hostapd_data *hapd, void *ctx) wps_registrar_update_ie(hapd->wps->registrar); - if (!hapd->conf->ap_setup_locked) { + if (!hapd->conf->ap_setup_locked && + hapd->ap_pin_failures_consecutive >= 10) { + /* + * In indefinite lockdown - disable automatic AP PIN + * reenablement. + */ + eloop_cancel_timeout(hostapd_wps_reenable_ap_pin, hapd, NULL); + wpa_printf(MSG_DEBUG, "WPS: AP PIN disabled indefinitely"); + } else if (!hapd->conf->ap_setup_locked) { if (hapd->ap_pin_lockout_time == 0) hapd->ap_pin_lockout_time = 60; else if (hapd->ap_pin_lockout_time < 365 * 24 * 60 * 60 && @@ -569,6 +581,29 @@ static void hostapd_pwd_auth_fail(struct hostapd_data *hapd, } +static int wps_ap_pin_success(struct hostapd_data *hapd, void *ctx) +{ + if (hapd->conf->ap_pin == NULL || hapd->wps == NULL) + return 0; + + if (hapd->ap_pin_failures_consecutive == 0) + return 0; + + wpa_printf(MSG_DEBUG, "WPS: Clear consecutive AP PIN failure counter " + "- total validation failures %u (%u consecutive)", + hapd->ap_pin_failures, hapd->ap_pin_failures_consecutive); + hapd->ap_pin_failures_consecutive = 0; + + return 0; +} + + +static void hostapd_wps_ap_pin_success(struct hostapd_data *hapd) +{ + hostapd_wps_for_each(hapd, wps_ap_pin_success, NULL); +} + + static const char * wps_event_fail_reason[NUM_WPS_EI_VALUES] = { "No Error", /* WPS_EI_NO_ERROR */ "TKIP Only Prohibited", /* WPS_EI_SECURITY_TKIP_ONLY_PROHIBITED */ @@ -628,6 +663,9 @@ static void hostapd_wps_event_cb(void *ctx, enum wps_event event, break; case WPS_EV_ER_SET_SELECTED_REGISTRAR: break; + case WPS_EV_AP_PIN_SUCCESS: + hostapd_wps_ap_pin_success(hapd); + break; } if (hapd->wps_event_cb) hapd->wps_event_cb(hapd->wps_event_cb_ctx, event, data); @@ -800,14 +838,8 @@ int hostapd_init_wps(struct hostapd_data *hapd, } wps->dev.os_version = WPA_GET_BE32(hapd->conf->os_version); - - if (conf->wps_rf_bands) { - wps->dev.rf_bands = conf->wps_rf_bands; - } else { - wps->dev.rf_bands = - hapd->iconf->hw_mode == HOSTAPD_MODE_IEEE80211A ? - WPS_RF_50GHZ : WPS_RF_24GHZ; /* FIX: dualband AP */ - } + wps->dev.rf_bands = hapd->iconf->hw_mode == HOSTAPD_MODE_IEEE80211A ? + WPS_RF_50GHZ : WPS_RF_24GHZ; /* FIX: dualband AP */ if (conf->wpa & WPA_PROTO_RSN) { if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) @@ -1293,6 +1325,7 @@ static void hostapd_wps_ap_pin_enable(struct hostapd_data *hapd, int timeout) { wpa_printf(MSG_DEBUG, "WPS: Enabling AP PIN (timeout=%d)", timeout); hapd->ap_pin_failures = 0; + hapd->ap_pin_failures_consecutive = 0; hapd->conf->ap_setup_locked = 0; if (hapd->wps->ap_setup_locked) { wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_SETUP_UNLOCKED); diff --git a/src/common/defs.h b/src/common/defs.h index 6082053..bfbb4b7 100644 --- a/src/common/defs.h +++ b/src/common/defs.h @@ -76,11 +76,6 @@ static inline int wpa_key_mgmt_wpa(int akm) wpa_key_mgmt_wpa_psk(akm); } -static inline int wpa_key_mgmt_wpa_any(int akm) -{ - return wpa_key_mgmt_wpa(akm) || (akm & WPA_KEY_MGMT_WPA_NONE); -} - #define WPA_PROTO_WPA BIT(0) #define WPA_PROTO_RSN BIT(1) @@ -286,7 +281,4 @@ enum wpa_ctrl_req_type { NUM_WPA_CTRL_REQS }; -/* Maximum number of EAP methods to store for EAP server user information */ -#define EAP_MAX_METHODS 8 - #endif /* DEFS_H */ diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 66801fd..4cbc535 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -618,7 +618,7 @@ struct ieee80211_ht_operation { #define OP_MODE_MIXED 3 #define HT_INFO_OPERATION_MODE_OP_MODE_MASK \ - (0x0001 | 0x0002) + ((le16) (0x0001 | 0x0002)) #define HT_INFO_OPERATION_MODE_OP_MODE_OFFSET 0 #define HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT ((u8) BIT(2)) #define HT_INFO_OPERATION_MODE_TRANSMIT_BURST_LIMIT ((u8) BIT(3)) @@ -677,10 +677,6 @@ struct wmm_information_element { } STRUCT_PACKED; -#define WMM_QOSINFO_STA_AC_MASK 0x0f -#define WMM_QOSINFO_STA_SP_MASK 0x03 -#define WMM_QOSINFO_STA_SP_SHIFT 5 - #define WMM_AC_AIFSN_MASK 0x0f #define WMM_AC_AIFNS_SHIFT 0 #define WMM_AC_ACM 0x10 diff --git a/src/common/version.h b/src/common/version.h index 7afba48..d3d6915 100644 --- a/src/common/version.h +++ b/src/common/version.h @@ -5,6 +5,6 @@ #define VERSION_STR_POSTFIX "" #endif /* VERSION_STR_POSTFIX */ -#define VERSION_STR "2.0-devel" VERSION_STR_POSTFIX +#define VERSION_STR "1.0" VERSION_STR_POSTFIX #endif /* VERSION_H */ diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h index 6cd9de5..d13ba02 100644 --- a/src/common/wpa_ctrl.h +++ b/src/common/wpa_ctrl.h @@ -128,6 +128,7 @@ extern "C" { #define P2P_EVENT_SERV_DISC_RESP "P2P-SERV-DISC-RESP " #define P2P_EVENT_INVITATION_RECEIVED "P2P-INVITATION-RECEIVED " #define P2P_EVENT_INVITATION_RESULT "P2P-INVITATION-RESULT " +#define P2P_EVENT_FIND_STOPPED "P2P-FIND-STOPPED " #define INTERWORKING_AP "INTERWORKING-AP " #define INTERWORKING_NO_MATCH "INTERWORKING-NO-MATCH " diff --git a/src/crypto/Makefile b/src/crypto/Makefile index b221dd4..0454827 100644 --- a/src/crypto/Makefile +++ b/src/crypto/Makefile @@ -12,7 +12,6 @@ include ../lib.rules CFLAGS += -DCONFIG_TLS_INTERNAL_CLIENT CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER #CFLAGS += -DALL_DH_GROUPS -CFLAGS += -DCONFIG_SHA256 LIB_OBJS= \ aes-cbc.o \ @@ -41,7 +40,6 @@ LIB_OBJS= \ sha1-tlsprf.o \ sha1-tprf.o \ sha256.o \ - sha256-tlsprf.o \ sha256-internal.o LIB_OBJS += crypto_internal.o diff --git a/src/crypto/aes-internal-dec.c b/src/crypto/aes-internal-dec.c index a0fc45b..2d32c03 100644 --- a/src/crypto/aes-internal-dec.c +++ b/src/crypto/aes-internal-dec.c @@ -32,7 +32,7 @@ * * @return the number of rounds for the given cipher key size. */ -static void rijndaelKeySetupDec(u32 rk[/*44*/], const u8 cipherKey[]) +void rijndaelKeySetupDec(u32 rk[/*44*/], const u8 cipherKey[]) { int Nr = 10, i, j; u32 temp; diff --git a/src/crypto/aes-internal-enc.c b/src/crypto/aes-internal-enc.c index 8726aa7..2f19826 100644 --- a/src/crypto/aes-internal-enc.c +++ b/src/crypto/aes-internal-enc.c @@ -27,7 +27,7 @@ #include "crypto.h" #include "aes_i.h" -static void rijndaelEncrypt(const u32 rk[/*44*/], const u8 pt[16], u8 ct[16]) +void rijndaelEncrypt(const u32 rk[/*44*/], const u8 pt[16], u8 ct[16]) { u32 s0, s1, s2, s3, t0, t1, t2, t3; const int Nr = 10; diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h index 6dca191..587b5a9 100644 --- a/src/crypto/crypto.h +++ b/src/crypto/crypto.h @@ -155,8 +155,7 @@ void aes_decrypt_deinit(void *ctx); enum crypto_hash_alg { CRYPTO_HASH_ALG_MD5, CRYPTO_HASH_ALG_SHA1, - CRYPTO_HASH_ALG_HMAC_MD5, CRYPTO_HASH_ALG_HMAC_SHA1, - CRYPTO_HASH_ALG_SHA256, CRYPTO_HASH_ALG_HMAC_SHA256 + CRYPTO_HASH_ALG_HMAC_MD5, CRYPTO_HASH_ALG_HMAC_SHA1 }; struct crypto_hash; diff --git a/src/crypto/crypto_internal-rsa.c b/src/crypto/crypto_internal-rsa.c index 7f0a5cf..205042c 100644 --- a/src/crypto/crypto_internal-rsa.c +++ b/src/crypto/crypto_internal-rsa.c @@ -17,6 +17,7 @@ #include "common.h" #include "crypto.h" #include "tls/rsa.h" +#include "tls/bignum.h" #include "tls/pkcs1.h" #include "tls/pkcs8.h" diff --git a/src/crypto/crypto_internal.c b/src/crypto/crypto_internal.c index 9362fe1..5f715a8 100644 --- a/src/crypto/crypto_internal.c +++ b/src/crypto/crypto_internal.c @@ -1,6 +1,6 @@ /* * Crypto wrapper for internal crypto implementation - * Copyright (c) 2006-2011, Jouni Malinen + * Copyright (c) 2006-2009, Jouni Malinen * * 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 @@ -16,7 +16,6 @@ #include "common.h" #include "crypto.h" -#include "sha256_i.h" #include "sha1_i.h" #include "md5_i.h" @@ -25,9 +24,6 @@ struct crypto_hash { union { struct MD5Context md5; struct SHA1Context sha1; -#ifdef CONFIG_SHA256 - struct sha256_state sha256; -#endif /* CONFIG_SHA256 */ } u; u8 key[64]; size_t key_len; @@ -39,7 +35,7 @@ struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, { struct crypto_hash *ctx; u8 k_pad[64]; - u8 tk[32]; + u8 tk[20]; size_t i; ctx = os_zalloc(sizeof(*ctx)); @@ -55,11 +51,6 @@ struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, case CRYPTO_HASH_ALG_SHA1: SHA1Init(&ctx->u.sha1); break; -#ifdef CONFIG_SHA256 - case CRYPTO_HASH_ALG_SHA256: - sha256_init(&ctx->u.sha256); - break; -#endif /* CONFIG_SHA256 */ case CRYPTO_HASH_ALG_HMAC_MD5: if (key_len > sizeof(k_pad)) { MD5Init(&ctx->u.md5); @@ -98,27 +89,6 @@ struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, SHA1Init(&ctx->u.sha1); SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad)); break; -#ifdef CONFIG_SHA256 - case CRYPTO_HASH_ALG_HMAC_SHA256: - if (key_len > sizeof(k_pad)) { - sha256_init(&ctx->u.sha256); - sha256_process(&ctx->u.sha256, key, key_len); - sha256_done(&ctx->u.sha256, tk); - key = tk; - key_len = 32; - } - os_memcpy(ctx->key, key, key_len); - ctx->key_len = key_len; - - os_memcpy(k_pad, key, key_len); - if (key_len < sizeof(k_pad)) - os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); - for (i = 0; i < sizeof(k_pad); i++) - k_pad[i] ^= 0x36; - sha256_init(&ctx->u.sha256); - sha256_process(&ctx->u.sha256, k_pad, sizeof(k_pad)); - break; -#endif /* CONFIG_SHA256 */ default: os_free(ctx); return NULL; @@ -142,14 +112,6 @@ void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) case CRYPTO_HASH_ALG_HMAC_SHA1: SHA1Update(&ctx->u.sha1, data, len); break; -#ifdef CONFIG_SHA256 - case CRYPTO_HASH_ALG_SHA256: - case CRYPTO_HASH_ALG_HMAC_SHA256: - sha256_process(&ctx->u.sha256, data, len); - break; -#endif /* CONFIG_SHA256 */ - default: - break; } } @@ -186,17 +148,6 @@ int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) *len = 20; SHA1Final(mac, &ctx->u.sha1); break; -#ifdef CONFIG_SHA256 - case CRYPTO_HASH_ALG_SHA256: - if (*len < 32) { - *len = 32; - os_free(ctx); - return -1; - } - *len = 32; - sha256_done(&ctx->u.sha256, mac); - break; -#endif /* CONFIG_SHA256 */ case CRYPTO_HASH_ALG_HMAC_MD5: if (*len < 16) { *len = 16; @@ -237,31 +188,6 @@ int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) SHA1Update(&ctx->u.sha1, mac, 20); SHA1Final(mac, &ctx->u.sha1); break; -#ifdef CONFIG_SHA256 - case CRYPTO_HASH_ALG_HMAC_SHA256: - if (*len < 32) { - *len = 32; - os_free(ctx); - return -1; - } - *len = 32; - - sha256_done(&ctx->u.sha256, mac); - - os_memcpy(k_pad, ctx->key, ctx->key_len); - os_memset(k_pad + ctx->key_len, 0, - sizeof(k_pad) - ctx->key_len); - for (i = 0; i < sizeof(k_pad); i++) - k_pad[i] ^= 0x5c; - sha256_init(&ctx->u.sha256); - sha256_process(&ctx->u.sha256, k_pad, sizeof(k_pad)); - sha256_process(&ctx->u.sha256, mac, 32); - sha256_done(&ctx->u.sha256, mac); - break; -#endif /* CONFIG_SHA256 */ - default: - os_free(ctx); - return -1; } os_free(ctx); diff --git a/src/crypto/dh_group5.c b/src/crypto/dh_group5.c index 2a67d99..8c475bf 100644 --- a/src/crypto/dh_group5.c +++ b/src/crypto/dh_group5.c @@ -22,7 +22,7 @@ void * dh5_init(struct wpabuf **priv, struct wpabuf **publ) { *publ = dh_init(dh_groups_get(5), priv); - if (*publ == NULL) + if (*publ == 0) return NULL; return (void *) 1; } diff --git a/src/crypto/sha1-pbkdf2.c b/src/crypto/sha1-pbkdf2.c index 9dac977..11323de 100644 --- a/src/crypto/sha1-pbkdf2.c +++ b/src/crypto/sha1-pbkdf2.c @@ -16,6 +16,8 @@ #include "common.h" #include "sha1.h" +#include "md5.h" +#include "crypto.h" static int pbkdf2_sha1_f(const char *passphrase, const char *ssid, size_t ssid_len, int iterations, unsigned int count, diff --git a/src/crypto/sha1-tlsprf.c b/src/crypto/sha1-tlsprf.c index f98fd65..2c8c029 100644 --- a/src/crypto/sha1-tlsprf.c +++ b/src/crypto/sha1-tlsprf.c @@ -17,10 +17,11 @@ #include "common.h" #include "sha1.h" #include "md5.h" +#include "crypto.h" /** - * tls_prf_sha1_md5 - Pseudo-Random Function for TLS (TLS-PRF, RFC 2246) + * tls_prf - Pseudo-Random Function for TLS (TLS-PRF, RFC 2246) * @secret: Key for PRF * @secret_len: Length of the key in bytes * @label: A unique label for each purpose of the PRF @@ -33,8 +34,8 @@ * This function is used to derive new, cryptographically separate keys from a * given key in TLS. This PRF is defined in RFC 2246, Chapter 5. */ -int tls_prf_sha1_md5(const u8 *secret, size_t secret_len, const char *label, - const u8 *seed, size_t seed_len, u8 *out, size_t outlen) +int tls_prf(const u8 *secret, size_t secret_len, const char *label, + const u8 *seed, size_t seed_len, u8 *out, size_t outlen) { size_t L_S1, L_S2, i; const u8 *S1, *S2; diff --git a/src/crypto/sha1.h b/src/crypto/sha1.h index f0c1a5f..c1a6233 100644 --- a/src/crypto/sha1.h +++ b/src/crypto/sha1.h @@ -25,9 +25,9 @@ int sha1_prf(const u8 *key, size_t key_len, const char *label, const u8 *data, size_t data_len, u8 *buf, size_t buf_len); int sha1_t_prf(const u8 *key, size_t key_len, const char *label, const u8 *seed, size_t seed_len, u8 *buf, size_t buf_len); -int __must_check tls_prf_sha1_md5(const u8 *secret, size_t secret_len, - const char *label, const u8 *seed, - size_t seed_len, u8 *out, size_t outlen); +int __must_check tls_prf(const u8 *secret, size_t secret_len, + const char *label, const u8 *seed, size_t seed_len, + u8 *out, size_t outlen); int pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len, int iterations, u8 *buf, size_t buflen); #endif /* SHA1_H */ diff --git a/src/crypto/sha256-internal.c b/src/crypto/sha256-internal.c index ef5751d..c3a74c3 100644 --- a/src/crypto/sha256-internal.c +++ b/src/crypto/sha256-internal.c @@ -16,9 +16,21 @@ #include "common.h" #include "sha256.h" -#include "sha256_i.h" #include "crypto.h" +#define SHA256_BLOCK_SIZE 64 + +struct sha256_state { + u64 length; + u32 state[8], curlen; + u8 buf[SHA256_BLOCK_SIZE]; +}; + +static void sha256_init(struct sha256_state *md); +static int sha256_process(struct sha256_state *md, const unsigned char *in, + unsigned long inlen); +static int sha256_done(struct sha256_state *md, unsigned char *out); + /** * sha256_vector - SHA256 hash for data vector @@ -127,7 +139,7 @@ static int sha256_compress(struct sha256_state *md, unsigned char *buf) /* Initialize the hash state */ -void sha256_init(struct sha256_state *md) +static void sha256_init(struct sha256_state *md) { md->curlen = 0; md->length = 0; @@ -148,8 +160,8 @@ void sha256_init(struct sha256_state *md) @param inlen The length of the data (octets) @return CRYPT_OK if successful */ -int sha256_process(struct sha256_state *md, const unsigned char *in, - unsigned long inlen) +static int sha256_process(struct sha256_state *md, const unsigned char *in, + unsigned long inlen) { unsigned long n; @@ -188,7 +200,7 @@ int sha256_process(struct sha256_state *md, const unsigned char *in, @param out [out] The destination of the hash (32 bytes) @return CRYPT_OK if successful */ -int sha256_done(struct sha256_state *md, unsigned char *out) +static int sha256_done(struct sha256_state *md, unsigned char *out) { int i; diff --git a/src/crypto/sha256-tlsprf.c b/src/crypto/sha256-tlsprf.c deleted file mode 100644 index 6763c96..0000000 --- a/src/crypto/sha256-tlsprf.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * TLS PRF P_SHA256 - * Copyright (c) 2011, Jouni Malinen - * - * 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 "sha256.h" - - -/** - * tls_prf_sha256 - Pseudo-Random Function for TLS v1.2 (P_SHA256, RFC 5246) - * @secret: Key for PRF - * @secret_len: Length of the key in bytes - * @label: A unique label for each purpose of the PRF - * @seed: Seed value to bind into the key - * @seed_len: Length of the seed - * @out: Buffer for the generated pseudo-random key - * @outlen: Number of bytes of key to generate - * Returns: 0 on success, -1 on failure. - * - * This function is used to derive new, cryptographically separate keys from a - * given key in TLS. This PRF is defined in RFC 2246, Chapter 5. - */ -void tls_prf_sha256(const u8 *secret, size_t secret_len, const char *label, - const u8 *seed, size_t seed_len, u8 *out, size_t outlen) -{ - size_t clen; - u8 A[SHA256_MAC_LEN]; - u8 P[SHA256_MAC_LEN]; - size_t pos; - const unsigned char *addr[3]; - size_t len[3]; - - addr[0] = A; - len[0] = SHA256_MAC_LEN; - addr[1] = (unsigned char *) label; - len[1] = os_strlen(label); - addr[2] = seed; - len[2] = seed_len; - - /* - * RFC 5246, Chapter 5 - * A(0) = seed, A(i) = HMAC(secret, A(i-1)) - * P_hash = HMAC(secret, A(1) + seed) + HMAC(secret, A(2) + seed) + .. - * PRF(secret, label, seed) = P_SHA256(secret, label + seed) - */ - - hmac_sha256_vector(secret, secret_len, 2, &addr[1], &len[1], A); - - pos = 0; - while (pos < outlen) { - hmac_sha256_vector(secret, secret_len, 3, addr, len, P); - hmac_sha256(secret, secret_len, A, SHA256_MAC_LEN, A); - - clen = outlen - pos; - if (clen > SHA256_MAC_LEN) - clen = SHA256_MAC_LEN; - os_memcpy(out + pos, P, clen); - pos += clen; - } -} diff --git a/src/crypto/sha256.h b/src/crypto/sha256.h index b1ce6af..dc597f0 100644 --- a/src/crypto/sha256.h +++ b/src/crypto/sha256.h @@ -1,6 +1,6 @@ /* * SHA256 hash implementation and interface functions - * Copyright (c) 2003-2011, Jouni Malinen + * Copyright (c) 2003-2006, Jouni Malinen * * 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 @@ -23,8 +23,5 @@ void hmac_sha256(const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac); void sha256_prf(const u8 *key, size_t key_len, const char *label, const u8 *data, size_t data_len, u8 *buf, size_t buf_len); -void tls_prf_sha256(const u8 *secret, size_t secret_len, - const char *label, const u8 *seed, size_t seed_len, - u8 *out, size_t outlen); #endif /* SHA256_H */ diff --git a/src/crypto/sha256_i.h b/src/crypto/sha256_i.h deleted file mode 100644 index 20ae488..0000000 --- a/src/crypto/sha256_i.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * SHA-256 internal definitions - * Copyright (c) 2003-2011, Jouni Malinen - * - * 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 SHA256_I_H -#define SHA256_I_H - -#define SHA256_BLOCK_SIZE 64 - -struct sha256_state { - u64 length; - u32 state[8], curlen; - u8 buf[SHA256_BLOCK_SIZE]; -}; - -void sha256_init(struct sha256_state *md); -int sha256_process(struct sha256_state *md, const unsigned char *in, - unsigned long inlen); -int sha256_done(struct sha256_state *md, unsigned char *out); - -#endif /* SHA256_I_H */ diff --git a/src/crypto/tls.h b/src/crypto/tls.h index d9d88cb..a5de3fb 100644 --- a/src/crypto/tls.h +++ b/src/crypto/tls.h @@ -305,7 +305,7 @@ int __must_check tls_connection_get_keys(void *tls_ctx, * not exported from the TLS library, tls_connection_prf() is required so that * further keying material can be derived from the master secret. If not * implemented, the function will still need to be defined, but it can just - * return -1. Example implementation of this function is in tls_prf_sha1_md5() + * return -1. Example implementation of this function is in tls_prf() function * when it is called with seed set to client_random|server_random (or * server_random|client_random). */ @@ -347,12 +347,6 @@ struct wpabuf * tls_connection_handshake(void *tls_ctx, const struct wpabuf *in_data, struct wpabuf **appl_data); -struct wpabuf * tls_connection_handshake2(void *tls_ctx, - struct tls_connection *conn, - const struct wpabuf *in_data, - struct wpabuf **appl_data, - int *more_data_needed); - /** * tls_connection_server_handshake - Process TLS handshake (server side) * @tls_ctx: TLS context data from tls_init() @@ -398,11 +392,6 @@ struct wpabuf * tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data); -struct wpabuf * tls_connection_decrypt2(void *tls_ctx, - struct tls_connection *conn, - const struct wpabuf *in_data, - int *more_data_needed); - /** * tls_connection_resumed - Was session resumption used * @tls_ctx: TLS context data from tls_init() diff --git a/src/crypto/tls_internal.c b/src/crypto/tls_internal.c index f5e31d9..eacb9bf 100644 --- a/src/crypto/tls_internal.c +++ b/src/crypto/tls_internal.c @@ -332,17 +332,6 @@ struct wpabuf * tls_connection_handshake(void *tls_ctx, const struct wpabuf *in_data, struct wpabuf **appl_data) { - return tls_connection_handshake2(tls_ctx, conn, in_data, appl_data, - NULL); -} - - -struct wpabuf * tls_connection_handshake2(void *tls_ctx, - struct tls_connection *conn, - const struct wpabuf *in_data, - struct wpabuf **appl_data, - int *need_more_data) -{ #ifdef CONFIG_TLS_INTERNAL_CLIENT u8 *res, *ad; size_t res_len, ad_len; @@ -355,7 +344,7 @@ struct wpabuf * tls_connection_handshake2(void *tls_ctx, res = tlsv1_client_handshake(conn->client, in_data ? wpabuf_head(in_data) : NULL, in_data ? wpabuf_len(in_data) : 0, - &res_len, &ad, &ad_len, need_more_data); + &res_len, &ad, &ad_len); if (res == NULL) return NULL; out = wpabuf_alloc_ext_data(res, res_len); @@ -466,23 +455,23 @@ struct wpabuf * tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data) { - return tls_connection_decrypt2(tls_ctx, conn, in_data, NULL); -} - - -struct wpabuf * tls_connection_decrypt2(void *tls_ctx, - struct tls_connection *conn, - const struct wpabuf *in_data, - int *need_more_data) -{ - if (need_more_data) - *need_more_data = 0; - #ifdef CONFIG_TLS_INTERNAL_CLIENT if (conn->client) { - return tlsv1_client_decrypt(conn->client, wpabuf_head(in_data), - wpabuf_len(in_data), - need_more_data); + struct wpabuf *buf; + int res; + buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3); + if (buf == NULL) + return NULL; + res = tlsv1_client_decrypt(conn->client, wpabuf_head(in_data), + wpabuf_len(in_data), + wpabuf_mhead(buf), + wpabuf_size(buf)); + if (res < 0) { + wpabuf_free(buf); + return NULL; + } + wpabuf_put(buf, res); + return buf; } #endif /* CONFIG_TLS_INTERNAL_CLIENT */ #ifdef CONFIG_TLS_INTERNAL_SERVER diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c index 8374096..6380ce0 100644 --- a/src/crypto/tls_openssl.c +++ b/src/crypto/tls_openssl.c @@ -1663,7 +1663,6 @@ static int tls_global_client_cert(SSL_CTX *ssl_ctx, const char *client_cert) if (SSL_CTX_use_certificate_file(ssl_ctx, client_cert, SSL_FILETYPE_ASN1) != 1 && - SSL_CTX_use_certificate_chain_file(ssl_ctx, client_cert) != 1 && SSL_CTX_use_certificate_file(ssl_ctx, client_cert, SSL_FILETYPE_PEM) != 1) { tls_show_errors(MSG_INFO, __func__, diff --git a/src/drivers/Apple80211.h b/src/drivers/Apple80211.h new file mode 100644 index 0000000..2a612e7 --- /dev/null +++ b/src/drivers/Apple80211.h @@ -0,0 +1,156 @@ +#ifndef APPLE80211_H +#define APPLE80211_H + +/* + * Apple80211 framework definitions + * This is an undocumented interface and the definitions here are based on + * information from MacStumbler (http://www.macstumbler.com/Apple80211.h) and + * whatever related information can be found with google and experiments ;-). + */ + +typedef struct __WirelessRef *WirelessRef; +typedef SInt32 WirelessError; +#define errWirelessNoError 0 + +typedef struct WirelessInfo { + UInt16 link_qual; + UInt16 comms_qual; + UInt16 signal; + UInt16 noise; + UInt16 port_stat; + UInt16 client_mode; + UInt16 res1; + UInt16 power; + UInt16 res2; + UInt8 bssID[6]; + UInt8 ssid[34]; +} WirelessInfo; + +typedef struct WirelessInfo2 { + /* TODO - these are probably not in correct order or complete */ + WirelessInfo info1; + UInt8 macAddress[6]; +} WirelessInfo2; + +typedef struct WirelessNetworkInfo { + UInt16 channel; + UInt16 noise; + UInt16 signal; + UInt8 bssid[6]; + UInt16 beacon_int; + UInt16 capability; + UInt16 ssid_len; + UInt8 ssid[32]; +} WirelessNetworkInfo; + +typedef int wirelessKeyType; /* TODO */ + +int WirelessIsAvailable(void); +WirelessError WirelessAttach(WirelessRef *ref, UInt32 res); +WirelessError WirelessDetach(WirelessRef ref); +WirelessError WirelessPrivate(WirelessRef ref, void *in_ptr, int in_bytes, + void *out_ptr, int out_bytes); +WirelessError WirelessSetEnabled(WirelessRef ref, UInt8 enabled); +WirelessError WirelessGetEnabled(WirelessRef ref, UInt8 *enabled); +WirelessError WirelessSetPower(WirelessRef ref, UInt8 power); +WirelessError WirelessGetPower(WirelessRef ref, UInt8 *power); +WirelessError WirelessGetInfo(WirelessRef ref, WirelessInfo *info); +WirelessError WirelessGetInfo2(WirelessRef ref, WirelessInfo2 *info); +WirelessError WirelessScan(WirelessRef ref, CFArrayRef *results, + UInt32 strip_dups); +WirelessError WirelessScanSplit(WirelessRef ref, CFArrayRef *ap_results, + CFArrayRef *ibss_results, UInt32 strip_dups); +WirelessError WirelessDirectedScan(WirelessRef ref, CFArrayRef *results, + UInt32 strip_dups, CFStringRef ssid); +WirelessError WirelessDirectedScan2(WirelessRef ref, CFDataRef ssid, + UInt32 strip_dups, CFArrayRef *results); +WirelessError WirelessJoin(WirelessRef ref, CFStringRef ssid); +WirelessError WirelessJoinWEP(WirelessRef ref, CFStringRef ssid, + CFStringRef passwd); +WirelessError WirelessJoin8021x(WirelessRef ref, CFStringRef ssid); +/* + * Set WEP key + * ref: wireless reference from WirelessAttach() + * type: ? + * key_idx: 0..3 + * key_len: 13 for WEP-104 or 0 for clearing the key + * key: Pointer to the key or %NULL if key_len = 0 + */ +WirelessError WirelessSetKey(WirelessRef ref, wirelessKeyType type, + int key_idx, int key_len, + const unsigned char *key); +/* + * Set WPA key (e.g., PMK for 4-way handshake) + * ref: wireless reference from WirelessAttach() + * type: 0..4; 1 = PMK + * key_len: 16, 32, or 0 + * key: Pointer to the key or %NULL if key_len = 0 + */ +WirelessError WirelessSetWPAKey(WirelessRef ref, wirelessKeyType type, + int key_len, const unsigned char *key); +WirelessError WirelessAssociate(WirelessRef ref, int type, CFDataRef ssid, + CFStringRef key); +WirelessError WirelessAssociate2(WirelessRef ref, CFDictionaryRef scan_res, + CFStringRef key); +WirelessError WirelessDisassociate(WirelessRef ref); + +/* + * Get a copy of scan results for the given SSID + * The returned dictionary includes following entries: + * beaconInterval: CFNumber(kCFNumberSInt32Type) + * SSID: CFData buffer of the SSID + * isWPA: CFNumber(kCFNumberSInt32Type); 0 = not used, 1 = WPA, -128 = WPA2 + * name: Name of the network (SSID string) + * BSSID: CFData buffer of the BSSID + * channel: CFNumber(kCFNumberSInt32Type) + * signal: CFNumber(kCFNumberSInt32Type) + * appleIE: CFData + * WPSNOPINRequired: CFBoolean + * noise: CFNumber(kCFNumberSInt32Type) + * capability: CFNumber(kCFNumberSInt32Type) + * uniCipher: CFArray of CFNumber(kCFNumberSInt32Type) + * appleIE_Version: CFNumber(kCFNumberSInt32Type) + * appleIE_Robust: CFBoolean + * WPSConfigured: CFBoolean + * scanWasDirected: CFBoolean + * appleIE_Product: CFNumber(kCFNumberSInt32Type) + * authModes: CFArray of CFNumber(kCFNumberSInt32Type) + * multiCipher: CFNumber(kCFNumberSInt32Type) + */ +CFDictionaryRef WirelessSafeDirectedScanCopy(WirelessRef ref, CFDataRef ssid); + +/* + * Get information about the current association + * The returned dictionary includes following entries: + * keyData: CFData buffer of the key (e.g., 32-octet PSK) + * multiCipher: CFNumber(kCFNumberSInt32Type); 0 = none, 5 = CCMP? + * channel: CFNumber(kCFNumberSInt32Type) + * isIBSS: CFBoolean + * authMode: CFNumber(kCFNumberSInt32Type); 2 = WPA-Personal; 3 = open, + * 129 = WPA2-Enterprise + * isWPA: CFNumber(kCFNumberSInt32Type); 0 = not used, 1 = WPA, -128 == WPA2 + * SSID: CFData buffer of the SSID + * cipherMode: CFNumber(kCFNumberSInt32Type); 0 = none, 4 = CCMP? + */ +CFDictionaryRef WirelessGetAssociationInfo(WirelessRef ref); + +WirelessError WirelessConfigure(WirelessRef ref); + +/* + * Get ASP information + * The returned dictionary includes following entries: + * Version: version number (e.g., 3.0) + * Channel: channel (e.g., 1) + * Vendor: vendor (e.g., 2) + */ +CFDictionaryRef WirelessGetInfoASP(void); + +/* + * Get a copy of the interface dictionary + * The returned dictionary has a key,value pairs for wireless interfaces. + * The key is the interface name and the value is the driver identifier, e.g., + * en1: com.apple.driver.AirPort.Atheros + */ +CFDictionaryRef WirelessCopyInterfaceDict(void); + +#endif /* APPLE80211_H */ diff --git a/src/drivers/MobileApple80211.c b/src/drivers/MobileApple80211.c new file mode 100644 index 0000000..ce004fe --- /dev/null +++ b/src/drivers/MobileApple80211.c @@ -0,0 +1,189 @@ +#include "includes.h" +#include + +#include "common.h" + +#include +#include "MobileApple80211.h" + +/* + * Code for dynamically loading Apple80211 functions from Aeropuerto to avoid + * having to link with full Preferences.framework. + */ + +static void *aeropuerto = NULL; + + +int _Apple80211Initialized(void) +{ + return aeropuerto ? 1 : 0; +} + + +static int (*__Apple80211Open)(Apple80211Ref *ctx) = NULL; + +int Apple80211Open(Apple80211Ref *ctx) +{ + return __Apple80211Open(ctx); +} + + +static int (*__Apple80211Close)(Apple80211Ref ctx) = NULL; + +int Apple80211Close(Apple80211Ref ctx) +{ + return __Apple80211Close(ctx); +} + + +static int (*__Apple80211GetIfListCopy)(Apple80211Ref handle, CFArrayRef *list) + = NULL; + +int Apple80211GetIfListCopy(Apple80211Ref handle, CFArrayRef *list) +{ + return __Apple80211GetIfListCopy(handle, list); +} + + +static int (*__Apple80211BindToInterface)(Apple80211Ref handle, + CFStringRef interface) = NULL; + +int Apple80211BindToInterface(Apple80211Ref handle, + CFStringRef interface) +{ + return __Apple80211BindToInterface(handle, interface); +} + + +static int (*__Apple80211GetInterfaceNameCopy)(Apple80211Ref handle, + CFStringRef *name) = NULL; + +int Apple80211GetInterfaceNameCopy(Apple80211Ref handle, + CFStringRef *name) +{ + return __Apple80211GetInterfaceNameCopy(handle, name); +} + + +static int (*__Apple80211GetInfoCopy)(Apple80211Ref handle, + CFDictionaryRef *info) = NULL; + +int Apple80211GetInfoCopy(Apple80211Ref handle, + CFDictionaryRef *info) +{ + return __Apple80211GetInfoCopy(handle, info); +} + + +static int (*__Apple80211GetPower)(Apple80211Ref handle, char *pwr) = NULL; + +int Apple80211GetPower(Apple80211Ref handle, char *pwr) +{ + return __Apple80211GetPower(handle, pwr); +} + + +static int (*__Apple80211SetPower)(Apple80211Ref handle, char pwr) = NULL; + +int Apple80211SetPower(Apple80211Ref handle, char pwr) +{ + return __Apple80211SetPower(handle, pwr); +} + + +static int (*__Apple80211Scan)(Apple80211Ref handle, CFArrayRef *list, + CFDictionaryRef parameters) = NULL; + +int Apple80211Scan(Apple80211Ref handle, CFArrayRef *list, + CFDictionaryRef parameters) +{ + return __Apple80211Scan(handle, list, parameters); +} + + +static int (*__Apple80211Associate)(Apple80211Ref handle, CFDictionaryRef bss, + CFStringRef password) = NULL; + +int Apple80211Associate(Apple80211Ref handle, CFDictionaryRef bss, + CFStringRef password) +{ + return __Apple80211Associate(handle, bss, password); +} + + +static int (*__Apple80211AssociateAndCopyInfo)(Apple80211Ref handle, + CFDictionaryRef bss, + CFStringRef password, + CFDictionaryRef *info) = + NULL; + +int Apple80211AssociateAndCopyInfo(Apple80211Ref handle, CFDictionaryRef bss, + CFStringRef password, CFDictionaryRef *info) +{ + return __Apple80211AssociateAndCopyInfo(handle, bss, password, info); +} + + +static int (*__Apple80211CopyValue)(Apple80211Ref handle, int field, + CFDictionaryRef arg2, void *value) = NULL; + +int Apple80211CopyValue(Apple80211Ref handle, int field, CFDictionaryRef arg2, + void *value) +{ + return __Apple80211CopyValue(handle, field, arg2, value); +} + + +#define DLSYM(s) \ +do { \ + __ ## s = dlsym(aeropuerto, #s); \ + if (__ ## s == NULL) { \ + wpa_printf(MSG_ERROR, "MobileApple80211: Could not resolve " \ + "symbol '" #s "' (%s)", dlerror()); \ + err = 1; \ + } \ +} while (0) + + +__attribute__ ((constructor)) +void _Apple80211_constructor(void) +{ + const char *fname = "/System/Library/SystemConfiguration/" + "Aeropuerto.bundle/Aeropuerto"; + int err = 0; + + aeropuerto = dlopen(fname, RTLD_LAZY); + if (!aeropuerto) { + wpa_printf(MSG_ERROR, "MobileApple80211: Failed to open %s " + "for symbols", fname); + return; + } + + DLSYM(Apple80211Open); + DLSYM(Apple80211Close); + DLSYM(Apple80211GetIfListCopy); + DLSYM(Apple80211BindToInterface); + DLSYM(Apple80211GetInterfaceNameCopy); + DLSYM(Apple80211GetInfoCopy); + DLSYM(Apple80211GetPower); + DLSYM(Apple80211SetPower); + DLSYM(Apple80211Scan); + DLSYM(Apple80211Associate); + DLSYM(Apple80211AssociateAndCopyInfo); + DLSYM(Apple80211CopyValue); + + if (err) { + dlclose(aeropuerto); + aeropuerto = NULL; + } +} + + +__attribute__ ((destructor)) +void _Apple80211_destructor(void) +{ + if (aeropuerto) { + dlclose(aeropuerto); + aeropuerto = NULL; + } +} diff --git a/src/drivers/MobileApple80211.h b/src/drivers/MobileApple80211.h new file mode 100644 index 0000000..64d439d --- /dev/null +++ b/src/drivers/MobileApple80211.h @@ -0,0 +1,43 @@ +#ifndef MOBILEAPPLE80211_H +#define MOBILEAPPLE80211_H + +/* + * MobileApple80211 interface for iPhone/iPod touch + * These functions are available from Aeropuerto. + */ + +struct Apple80211; +typedef struct Apple80211 *Apple80211Ref; + +int Apple80211Open(Apple80211Ref *ctx); +int Apple80211Close(Apple80211Ref ctx); +int Apple80211GetIfListCopy(Apple80211Ref handle, CFArrayRef *list); +int Apple80211BindToInterface(Apple80211Ref handle, + CFStringRef interface); +int Apple80211GetInterfaceNameCopy(Apple80211Ref handle, + CFStringRef *name); +int Apple80211GetInfoCopy(Apple80211Ref handle, + CFDictionaryRef *info); +int Apple80211GetPower(Apple80211Ref handle, char *pwr); +int Apple80211SetPower(Apple80211Ref handle, char pwr); + +/* parameters can be NULL; returns scan results in CFArrayRef *list; + * caller will need to free with CFRelease() */ +int Apple80211Scan(Apple80211Ref handle, CFArrayRef *list, + CFDictionaryRef parameters); + +int Apple80211Associate(Apple80211Ref handle, CFDictionaryRef bss, + CFStringRef password); +int Apple80211AssociateAndCopyInfo(Apple80211Ref handle, CFDictionaryRef bss, + CFStringRef password, + CFDictionaryRef *info); + +enum { + APPLE80211_VALUE_SSID = 1, + APPLE80211_VALUE_BSSID = 9 +}; + +int Apple80211CopyValue(Apple80211Ref handle, int field, CFDictionaryRef arg2, + void *value); + +#endif /* MOBILEAPPLE80211_H */ diff --git a/src/drivers/android_drv.h b/src/drivers/android_drv.h deleted file mode 100644 index 5906527..0000000 --- a/src/drivers/android_drv.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Android driver interface - * - * 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. - */ - -#ifndef ANDROID_DRV_H -#define ANDROID_DRV_H - -#define WPA_EVENT_DRIVER_STATE "CTRL-EVENT-DRIVER-STATE " - -#define MAX_SSID_LEN 32 - -#define MAX_DRV_CMD_SIZE 248 -#define DRV_NUMBER_SEQUENTIAL_ERRORS 4 - -#define WEXT_PNOSETUP_HEADER "PNOSETUP " -#define WEXT_PNOSETUP_HEADER_SIZE 9 -#define WEXT_PNO_TLV_PREFIX 'S' -#define WEXT_PNO_TLV_VERSION '1' -#define WEXT_PNO_TLV_SUBVERSION '2' -#define WEXT_PNO_TLV_RESERVED '0' -#define WEXT_PNO_VERSION_SIZE 4 -#define WEXT_PNO_AMOUNT 16 -#define WEXT_PNO_SSID_SECTION 'S' -/* SSID header size is SSID section type above + SSID length */ -#define WEXT_PNO_SSID_HEADER_SIZE 2 -#define WEXT_PNO_SCAN_INTERVAL_SECTION 'T' -#define WEXT_PNO_SCAN_INTERVAL_LENGTH 2 -#define WEXT_PNO_SCAN_INTERVAL 30 -/* Scan interval size is scan interval section type + scan interval length - * above */ -#define WEXT_PNO_SCAN_INTERVAL_SIZE (1 + WEXT_PNO_SCAN_INTERVAL_LENGTH) -#define WEXT_PNO_REPEAT_SECTION 'R' -#define WEXT_PNO_REPEAT_LENGTH 1 -#define WEXT_PNO_REPEAT 4 -/* Repeat section size is Repeat section type + Repeat value length above */ -#define WEXT_PNO_REPEAT_SIZE (1 + WEXT_PNO_REPEAT_LENGTH) -#define WEXT_PNO_MAX_REPEAT_SECTION 'M' -#define WEXT_PNO_MAX_REPEAT_LENGTH 1 -#define WEXT_PNO_MAX_REPEAT 3 -/* Max Repeat section size is Max Repeat section type + Max Repeat value length - * above */ -#define WEXT_PNO_MAX_REPEAT_SIZE (1 + WEXT_PNO_MAX_REPEAT_LENGTH) -/* This corresponds to the size of all sections expect SSIDs */ -#define WEXT_PNO_NONSSID_SECTIONS_SIZE \ -(WEXT_PNO_SCAN_INTERVAL_SIZE + WEXT_PNO_REPEAT_SIZE + WEXT_PNO_MAX_REPEAT_SIZE) -/* PNO Max command size is total of header, version, ssid and other sections + - * Null termination */ -#define WEXT_PNO_MAX_COMMAND_SIZE \ - (WEXT_PNOSETUP_HEADER_SIZE + WEXT_PNO_VERSION_SIZE \ - + WEXT_PNO_AMOUNT * (WEXT_PNO_SSID_HEADER_SIZE + MAX_SSID_LEN) \ - + WEXT_PNO_NONSSID_SECTIONS_SIZE + 1) - -#endif /* ANDROID_DRV_H */ diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 53d1c25..c7b7363 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -556,27 +556,6 @@ struct wpa_driver_ap_params { int beacon_int; /** - * basic_rates: -1 terminated array of basic rates in 100 kbps - * - * This parameter can be used to set a specific basic rate set for the - * BSS. If %NULL, default basic rate set is used. - */ - int *basic_rates; - - /** - * proberesp - Probe Response template - * - * This is used by drivers that reply to Probe Requests internally in - * AP mode and require the full Probe Response template. - */ - const u8 *proberesp; - - /** - * proberesp_len - Length of the proberesp buffer in octets - */ - size_t proberesp_len; - - /** * ssid - The SSID to use in Beacon/Probe Response frames */ const u8 *ssid; @@ -649,7 +628,7 @@ struct wpa_driver_ap_params { * isolate - Whether to isolate frames between associated stations * * If this is non-zero, the AP is requested to disable forwarding of - * frames between associated stations. + * frames between association stations. */ int isolate; @@ -772,10 +751,6 @@ struct wpa_driver_capa { #define WPA_DRIVER_FLAGS_TDLS_SUPPORT 0x00080000 /* Driver requires external TDLS setup/teardown/discovery */ #define WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP 0x00100000 -/* Driver indicates support for Probe Response offloading in AP mode */ -#define WPA_DRIVER_FLAGS_PROBE_RESP_OFFLOAD 0x00200000 -/* Driver supports U-APSD in AP mode */ -#define WPA_DRIVER_FLAGS_AP_UAPSD 0x00400000 unsigned int flags; int max_scan_ssids; @@ -793,20 +768,6 @@ struct wpa_driver_capa { * supports in AP mode */ unsigned int max_stations; - - /** - * probe_resp_offloads - Bitmap of supported protocols by the driver - * for Probe Response offloading. - */ -/* Driver Probe Response offloading support for WPS ver. 1 */ -#define WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS 0x00000001 -/* Driver Probe Response offloading support for WPS ver. 2 */ -#define WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS2 0x00000002 -/* Driver Probe Response offloading support for P2P */ -#define WPA_DRIVER_PROBE_RESP_OFFLOAD_P2P 0x00000004 -/* Driver Probe Response offloading support for IEEE 802.11u (Interworking) */ -#define WPA_DRIVER_PROBE_RESP_OFFLOAD_INTERWORKING 0x00000008 - unsigned int probe_resp_offloads; }; @@ -834,7 +795,6 @@ struct hostapd_sta_add_params { const struct ieee80211_ht_capabilities *ht_capabilities; u32 flags; /* bitmask of WPA_STA_* flags */ int set; /* Set STA parameters instead of add */ - u8 qosinfo; }; struct hostapd_freq_params { @@ -1316,11 +1276,9 @@ struct wpa_driver_ops { * @priv: Private driver interface data * @data: IEEE 802.11 management frame with IEEE 802.11 header * @data_len: Size of the management frame - * @noack: Do not wait for this frame to be acked (disable retries) * Returns: 0 on success, -1 on failure */ - int (*send_mlme)(void *priv, const u8 *data, size_t data_len, - int noack); + int (*send_mlme)(void *priv, const u8 *data, size_t data_len); /** * update_ft_ies - Update FT (IEEE 802.11r) IEs @@ -1725,6 +1683,17 @@ struct wpa_driver_ops { int total_flags, int flags_or, int flags_and); /** + * set_rate_sets - Set supported and basic rate sets (AP only) + * @priv: Private driver interface data + * @supp_rates: -1 terminated array of supported rates in 100 kbps + * @basic_rates: -1 terminated array of basic rates in 100 kbps + * @mode: hardware mode (HOSTAPD_MODE_*) + * Returns: 0 on success, -1 on failure + */ + int (*set_rate_sets)(void *priv, int *supp_rates, int *basic_rates, + int mode); + + /** * set_tx_queue_params - Set TX queue parameters * @priv: Private driver interface data * @queue: Queue number (0 = VO, 1 = VI, 2 = BE, 3 = BK) @@ -1989,6 +1958,16 @@ struct wpa_driver_ops { int (*deinit_ap)(void *priv); /** + * deinit_p2p_cli - Deinitialize P2P client mode + * @priv: Private driver interface data + * Returns: 0 on success, -1 on failure (or if not supported) + * + * This optional function can be used to disable P2P client mode. It + * can be used to change the interface type back to station mode. + */ + int (*deinit_p2p_cli)(void *priv); + + /** * suspend - Notification on system suspend/hibernate event * @priv: Private driver interface data */ @@ -2908,12 +2887,7 @@ enum wpa_event_type { * This event indicates that the station responded to the poll * initiated with @poll_client. */ - EVENT_DRIVER_CLIENT_POLL_OK, - - /** - * EVENT_EAPOL_TX_STATUS - notify of EAPOL TX status - */ - EVENT_EAPOL_TX_STATUS + EVENT_DRIVER_CLIENT_POLL_OK }; @@ -3476,23 +3450,6 @@ union wpa_event_data { struct client_poll { u8 addr[ETH_ALEN]; } client_poll; - - /** - * struct eapol_tx_status - * @dst: Original destination - * @data: Data starting with IEEE 802.1X header (!) - * @data_len: Length of data - * @ack: Indicates ack or lost frame - * - * This corresponds to hapd_send_eapol if the frame sent - * there isn't just reported as EVENT_TX_STATUS. - */ - struct eapol_tx_status { - const u8 *dst; - const u8 *data; - int data_len; - int ack; - } eapol_tx_status; }; /** diff --git a/src/drivers/driver_atheros.c b/src/drivers/driver_atheros.c index b17d1a6..788171d 100644 --- a/src/drivers/driver_atheros.c +++ b/src/drivers/driver_atheros.c @@ -45,7 +45,7 @@ #endif #endif /* CONFIG_WPS */ -#include "linux_wext.h" +#include "wireless_copy.h" #include "driver.h" #include "eloop.h" diff --git a/src/drivers/driver_broadcom.c b/src/drivers/driver_broadcom.c new file mode 100644 index 0000000..cb88543 --- /dev/null +++ b/src/drivers/driver_broadcom.c @@ -0,0 +1,599 @@ +/* + * WPA Supplicant - driver interaction with old Broadcom wl.o driver + * Copyright (c) 2004, Nikki Chumkov + * Copyright (c) 2004, Jouni Malinen + * + * 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 the newer Broadcom driver ("hybrid Linux driver") supports + * Linux wireless extensions and does not need (or even work) with this old + * driver wrapper. Use driver_wext.c with that driver. + */ + +#include "includes.h" + +#include + +#include "common.h" + +#if 0 +#include +#include /* the L2 protocols */ +#else +#include +#include /* The L2 protocols */ +#endif +#include +#include + +/* wlioctl.h is a Broadcom header file and it is available, e.g., from Linksys + * WRT54G GPL tarball. */ +#include + +#include "driver.h" +#include "eloop.h" + +struct wpa_driver_broadcom_data { + void *ctx; + int ioctl_sock; + int event_sock; + char ifname[IFNAMSIZ + 1]; +}; + + +#ifndef WLC_DEAUTHENTICATE +#define WLC_DEAUTHENTICATE 143 +#endif +#ifndef WLC_DEAUTHENTICATE_WITH_REASON +#define WLC_DEAUTHENTICATE_WITH_REASON 201 +#endif +#ifndef WLC_SET_TKIP_COUNTERMEASURES +#define WLC_SET_TKIP_COUNTERMEASURES 202 +#endif + +#if !defined(PSK_ENABLED) /* NEW driver interface */ +#define WL_VERSION 360130 +/* wireless authentication bit vector */ +#define WPA_ENABLED 1 +#define PSK_ENABLED 2 + +#define WAUTH_WPA_ENABLED(wauth) ((wauth) & WPA_ENABLED) +#define WAUTH_PSK_ENABLED(wauth) ((wauth) & PSK_ENABLED) +#define WAUTH_ENABLED(wauth) ((wauth) & (WPA_ENABLED | PSK_ENABLED)) + +#define WSEC_PRIMARY_KEY WL_PRIMARY_KEY + +typedef wl_wsec_key_t wsec_key_t; +#endif + +typedef struct { + uint32 val; + struct ether_addr ea; + uint16 res; +} wlc_deauth_t; + + +static void wpa_driver_broadcom_scan_timeout(void *eloop_ctx, + void *timeout_ctx); + +static int broadcom_ioctl(struct wpa_driver_broadcom_data *drv, int cmd, + void *buf, int len) +{ + struct ifreq ifr; + wl_ioctl_t ioc; + int ret = 0; + + wpa_printf(MSG_MSGDUMP, "BROADCOM: wlioctl(%s,%d,len=%d,val=%p)", + drv->ifname, cmd, len, buf); + /* wpa_hexdump(MSG_MSGDUMP, "BROADCOM: wlioctl buf", buf, len); */ + + ioc.cmd = cmd; + ioc.buf = buf; + ioc.len = len; + os_strlcpy(ifr.ifr_name, drv->ifname, IFNAMSIZ); + ifr.ifr_data = (caddr_t) &ioc; + if ((ret = ioctl(drv->ioctl_sock, SIOCDEVPRIVATE, &ifr)) < 0) { + if (cmd != WLC_GET_MAGIC) + perror(ifr.ifr_name); + wpa_printf(MSG_MSGDUMP, "BROADCOM: wlioctl cmd=%d res=%d", + cmd, ret); + } + + return ret; +} + +static int wpa_driver_broadcom_get_bssid(void *priv, u8 *bssid) +{ + struct wpa_driver_broadcom_data *drv = priv; + if (broadcom_ioctl(drv, WLC_GET_BSSID, bssid, ETH_ALEN) == 0) + return 0; + + os_memset(bssid, 0, ETH_ALEN); + return -1; +} + +static int wpa_driver_broadcom_get_ssid(void *priv, u8 *ssid) +{ + struct wpa_driver_broadcom_data *drv = priv; + wlc_ssid_t s; + + if (broadcom_ioctl(drv, WLC_GET_SSID, &s, sizeof(s)) == -1) + return -1; + + os_memcpy(ssid, s.SSID, s.SSID_len); + return s.SSID_len; +} + +static int wpa_driver_broadcom_set_wpa(void *priv, int enable) +{ + struct wpa_driver_broadcom_data *drv = priv; + unsigned int wauth, wsec; + struct ether_addr ea; + + os_memset(&ea, enable ? 0xff : 0, sizeof(ea)); + if (broadcom_ioctl(drv, WLC_GET_WPA_AUTH, &wauth, sizeof(wauth)) == + -1 || + broadcom_ioctl(drv, WLC_GET_WSEC, &wsec, sizeof(wsec)) == -1) + return -1; + + if (enable) { + wauth = PSK_ENABLED; + wsec = TKIP_ENABLED; + } else { + wauth = 255; + wsec &= ~(TKIP_ENABLED | AES_ENABLED); + } + + if (broadcom_ioctl(drv, WLC_SET_WPA_AUTH, &wauth, sizeof(wauth)) == + -1 || + broadcom_ioctl(drv, WLC_SET_WSEC, &wsec, sizeof(wsec)) == -1) + return -1; + + /* FIX: magic number / error handling? */ + broadcom_ioctl(drv, 122, &ea, sizeof(ea)); + + return 0; +} + +static int wpa_driver_broadcom_set_key(const char *ifname, void *priv, + enum 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_broadcom_data *drv = priv; + int ret; + wsec_key_t wkt; + + os_memset(&wkt, 0, sizeof wkt); + wpa_printf(MSG_MSGDUMP, "BROADCOM: SET %sKEY[%d] alg=%d", + set_tx ? "PRIMARY " : "", key_idx, alg); + if (key && key_len > 0) + wpa_hexdump_key(MSG_MSGDUMP, "BROADCOM: key", key, key_len); + + switch (alg) { + case WPA_ALG_NONE: + wkt.algo = CRYPTO_ALGO_OFF; + break; + case WPA_ALG_WEP: + wkt.algo = CRYPTO_ALGO_WEP128; /* CRYPTO_ALGO_WEP1? */ + break; + case WPA_ALG_TKIP: + wkt.algo = 0; /* CRYPTO_ALGO_TKIP? */ + break; + case WPA_ALG_CCMP: + wkt.algo = 0; /* CRYPTO_ALGO_AES_CCM; + * AES_OCB_MSDU, AES_OCB_MPDU? */ + break; + default: + wkt.algo = CRYPTO_ALGO_NALG; + break; + } + + if (seq && seq_len > 0) + wpa_hexdump(MSG_MSGDUMP, "BROADCOM: SEQ", seq, seq_len); + + if (addr) + wpa_hexdump(MSG_MSGDUMP, "BROADCOM: addr", addr, ETH_ALEN); + + wkt.index = key_idx; + wkt.len = key_len; + if (key && key_len > 0) { + os_memcpy(wkt.data, key, key_len); + if (key_len == 32) { + /* hack hack hack XXX */ + os_memcpy(&wkt.data[16], &key[24], 8); + os_memcpy(&wkt.data[24], &key[16], 8); + } + } + /* wkt.algo = CRYPTO_ALGO_...; */ + wkt.flags = set_tx ? 0 : WSEC_PRIMARY_KEY; + if (addr && set_tx) + os_memcpy(&wkt.ea, addr, sizeof(wkt.ea)); + ret = broadcom_ioctl(drv, WLC_SET_KEY, &wkt, sizeof(wkt)); + if (addr && set_tx) { + /* FIX: magic number / error handling? */ + broadcom_ioctl(drv, 121, &wkt.ea, sizeof(wkt.ea)); + } + return ret; +} + + +static void wpa_driver_broadcom_event_receive(int sock, void *ctx, + void *sock_ctx) +{ + char buf[8192]; + int left; + wl_wpa_header_t *wwh; + union wpa_event_data data; + u8 *resp_ies = NULL; + + if ((left = recv(sock, buf, sizeof buf, 0)) < 0) + return; + + wpa_hexdump(MSG_DEBUG, "RECEIVE EVENT", (u8 *) buf, left); + + if ((size_t) left < sizeof(wl_wpa_header_t)) + return; + + wwh = (wl_wpa_header_t *) buf; + + if (wwh->snap.type != WL_WPA_ETHER_TYPE) + return; + if (os_memcmp(&wwh->snap, wl_wpa_snap_template, 6) != 0) + return; + + os_memset(&data, 0, sizeof(data)); + + switch (wwh->type) { + case WLC_ASSOC_MSG: + left -= WL_WPA_HEADER_LEN; + wpa_printf(MSG_DEBUG, "BROADCOM: ASSOC MESSAGE (left: %d)", + left); + if (left > 0) { + resp_ies = os_malloc(left); + if (resp_ies == NULL) + return; + os_memcpy(resp_ies, buf + WL_WPA_HEADER_LEN, left); + data.assoc_info.resp_ies = resp_ies; + data.assoc_info.resp_ies_len = left; + } + + wpa_supplicant_event(ctx, EVENT_ASSOC, &data); + os_free(resp_ies); + break; + case WLC_DISASSOC_MSG: + wpa_printf(MSG_DEBUG, "BROADCOM: DISASSOC MESSAGE"); + wpa_supplicant_event(ctx, EVENT_DISASSOC, NULL); + break; + case WLC_PTK_MIC_MSG: + wpa_printf(MSG_DEBUG, "BROADCOM: PTK MIC MSG MESSAGE"); + data.michael_mic_failure.unicast = 1; + wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data); + break; + case WLC_GTK_MIC_MSG: + wpa_printf(MSG_DEBUG, "BROADCOM: GTK MIC MSG MESSAGE"); + data.michael_mic_failure.unicast = 0; + wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data); + break; + default: + wpa_printf(MSG_DEBUG, "BROADCOM: UNKNOWN MESSAGE (%d)", + wwh->type); + break; + } +} + +static void * wpa_driver_broadcom_init(void *ctx, const char *ifname) +{ + int s; + struct sockaddr_ll ll; + struct wpa_driver_broadcom_data *drv; + struct ifreq ifr; + + /* open socket to kernel */ + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + perror("socket"); + return NULL; + } + /* do it */ + os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); + if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) { + perror(ifr.ifr_name); + return NULL; + } + + + drv = os_zalloc(sizeof(*drv)); + if (drv == NULL) + return NULL; + drv->ctx = ctx; + os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); + drv->ioctl_sock = s; + + s = socket(PF_PACKET, SOCK_RAW, ntohs(ETH_P_802_2)); + if (s < 0) { + perror("socket(PF_PACKET, SOCK_RAW, ntohs(ETH_P_802_2))"); + close(drv->ioctl_sock); + os_free(drv); + return NULL; + } + + os_memset(&ll, 0, sizeof(ll)); + ll.sll_family = AF_PACKET; + ll.sll_protocol = ntohs(ETH_P_802_2); + ll.sll_ifindex = ifr.ifr_ifindex; + ll.sll_hatype = 0; + ll.sll_pkttype = PACKET_HOST; + ll.sll_halen = 0; + + if (bind(s, (struct sockaddr *) &ll, sizeof(ll)) < 0) { + perror("bind(netlink)"); + close(s); + close(drv->ioctl_sock); + os_free(drv); + return NULL; + } + + eloop_register_read_sock(s, wpa_driver_broadcom_event_receive, ctx, + NULL); + drv->event_sock = s; + wpa_driver_broadcom_set_wpa(drv, 1); + + return drv; +} + +static void wpa_driver_broadcom_deinit(void *priv) +{ + struct wpa_driver_broadcom_data *drv = priv; + wpa_driver_broadcom_set_wpa(drv, 0); + eloop_cancel_timeout(wpa_driver_broadcom_scan_timeout, drv, drv->ctx); + eloop_unregister_read_sock(drv->event_sock); + close(drv->event_sock); + close(drv->ioctl_sock); + os_free(drv); +} + +static int wpa_driver_broadcom_set_countermeasures(void *priv, + int enabled) +{ +#if 0 + struct wpa_driver_broadcom_data *drv = priv; + /* FIX: ? */ + return broadcom_ioctl(drv, WLC_SET_TKIP_COUNTERMEASURES, &enabled, + sizeof(enabled)); +#else + return 0; +#endif +} + +static int wpa_driver_broadcom_set_drop_unencrypted(void *priv, int enabled) +{ + struct wpa_driver_broadcom_data *drv = priv; + /* SET_EAP_RESTRICT, SET_WEP_RESTRICT */ + int _restrict = (enabled ? 1 : 0); + + if (broadcom_ioctl(drv, WLC_SET_WEP_RESTRICT, + &_restrict, sizeof(_restrict)) < 0 || + broadcom_ioctl(drv, WLC_SET_EAP_RESTRICT, + &_restrict, sizeof(_restrict)) < 0) + return -1; + + return 0; +} + +static void wpa_driver_broadcom_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); +} + +static int wpa_driver_broadcom_scan(void *priv, + struct wpa_driver_scan_params *params) +{ + struct wpa_driver_broadcom_data *drv = priv; + wlc_ssid_t wst = { 0, "" }; + const u8 *ssid = params->ssids[0].ssid; + size_t ssid_len = params->ssids[0].ssid_len; + + if (ssid && ssid_len > 0 && ssid_len <= sizeof(wst.SSID)) { + wst.SSID_len = ssid_len; + os_memcpy(wst.SSID, ssid, ssid_len); + } + + if (broadcom_ioctl(drv, WLC_SCAN, &wst, sizeof(wst)) < 0) + return -1; + + eloop_cancel_timeout(wpa_driver_broadcom_scan_timeout, drv, drv->ctx); + eloop_register_timeout(3, 0, wpa_driver_broadcom_scan_timeout, drv, + drv->ctx); + return 0; +} + + +static const int frequency_list[] = { + 2412, 2417, 2422, 2427, 2432, 2437, 2442, + 2447, 2452, 2457, 2462, 2467, 2472, 2484 +}; + +struct bss_ie_hdr { + u8 elem_id; + u8 len; + u8 oui[3]; + /* u8 oui_type; */ + /* u16 version; */ +} __attribute__ ((packed)); + +static struct wpa_scan_results * +wpa_driver_broadcom_get_scan_results(void *priv) +{ + struct wpa_driver_broadcom_data *drv = priv; + char *buf; + wl_scan_results_t *wsr; + wl_bss_info_t *wbi; + size_t ap_num; + struct wpa_scan_results *res; + + buf = os_malloc(WLC_IOCTL_MAXLEN); + if (buf == NULL) + return NULL; + + wsr = (wl_scan_results_t *) buf; + + wsr->buflen = WLC_IOCTL_MAXLEN - sizeof(wsr); + wsr->version = 107; + wsr->count = 0; + + if (broadcom_ioctl(drv, WLC_SCAN_RESULTS, buf, WLC_IOCTL_MAXLEN) < 0) { + os_free(buf); + return NULL; + } + + res = os_zalloc(sizeof(*res)); + if (res == NULL) { + os_free(buf); + return NULL; + } + + res->res = os_zalloc(wsr->count * sizeof(struct wpa_scan_res *)); + if (res->res == NULL) { + os_free(res); + os_free(buf); + return NULL; + } + + for (ap_num = 0, wbi = wsr->bss_info; ap_num < wsr->count; ++ap_num) { + struct wpa_scan_res *r; + r = os_malloc(sizeof(*r) + wbi->ie_length); + if (r == NULL) + break; + res->res[res->num++] = r; + + os_memcpy(r->bssid, &wbi->BSSID, ETH_ALEN); + r->freq = frequency_list[wbi->channel - 1]; + /* get ie's */ + os_memcpy(r + 1, wbi + 1, wbi->ie_length); + r->ie_len = wbi->ie_length; + + wbi = (wl_bss_info_t *) ((u8 *) wbi + wbi->length); + } + + wpa_printf(MSG_MSGDUMP, "Received %d bytes of scan results (%lu " + "BSSes)", + wsr->buflen, (unsigned long) ap_num); + + os_free(buf); + return res; + } + +static int wpa_driver_broadcom_deauthenticate(void *priv, const u8 *addr, + int reason_code) +{ + struct wpa_driver_broadcom_data *drv = priv; + wlc_deauth_t wdt; + wdt.val = reason_code; + os_memcpy(&wdt.ea, addr, sizeof wdt.ea); + wdt.res = 0x7fff; + return broadcom_ioctl(drv, WLC_DEAUTHENTICATE_WITH_REASON, &wdt, + sizeof(wdt)); +} + +static int wpa_driver_broadcom_disassociate(void *priv, const u8 *addr, + int reason_code) +{ + struct wpa_driver_broadcom_data *drv = priv; + return broadcom_ioctl(drv, WLC_DISASSOC, NULL, 0); +} + +static int +wpa_driver_broadcom_associate(void *priv, + struct wpa_driver_associate_params *params) +{ + struct wpa_driver_broadcom_data *drv = priv; + wlc_ssid_t s; + int infra = 1; + int auth = 0; + int wsec = 4; + int dummy; + int wpa_auth; + int ret; + + ret = wpa_driver_broadcom_set_drop_unencrypted( + drv, params->drop_unencrypted); + + s.SSID_len = params->ssid_len; + os_memcpy(s.SSID, params->ssid, params->ssid_len); + + switch (params->pairwise_suite) { + case CIPHER_WEP40: + case CIPHER_WEP104: + wsec = 1; + break; + + case CIPHER_TKIP: + wsec = 2; + break; + + case CIPHER_CCMP: + wsec = 4; + break; + + default: + wsec = 0; + break; + } + + switch (params->key_mgmt_suite) { + case KEY_MGMT_802_1X: + wpa_auth = 1; + break; + + case KEY_MGMT_PSK: + wpa_auth = 2; + break; + + default: + wpa_auth = 255; + break; + } + + /* printf("broadcom_associate: %u %u %u\n", pairwise_suite, + * group_suite, key_mgmt_suite); + * broadcom_ioctl(ifname, WLC_GET_WSEC, &wsec, sizeof(wsec)); + * wl join uses wlc_sec_wep here, not wlc_set_wsec */ + + if (broadcom_ioctl(drv, WLC_SET_WSEC, &wsec, sizeof(wsec)) < 0 || + broadcom_ioctl(drv, WLC_SET_WPA_AUTH, &wpa_auth, + sizeof(wpa_auth)) < 0 || + broadcom_ioctl(drv, WLC_GET_WEP, &dummy, sizeof(dummy)) < 0 || + broadcom_ioctl(drv, WLC_SET_INFRA, &infra, sizeof(infra)) < 0 || + broadcom_ioctl(drv, WLC_SET_AUTH, &auth, sizeof(auth)) < 0 || + broadcom_ioctl(drv, WLC_SET_WEP, &wsec, sizeof(wsec)) < 0 || + broadcom_ioctl(drv, WLC_SET_SSID, &s, sizeof(s)) < 0) + return -1; + + return ret; +} + +const struct wpa_driver_ops wpa_driver_broadcom_ops = { + .name = "broadcom", + .desc = "Broadcom wl.o driver", + .get_bssid = wpa_driver_broadcom_get_bssid, + .get_ssid = wpa_driver_broadcom_get_ssid, + .set_key = wpa_driver_broadcom_set_key, + .init = wpa_driver_broadcom_init, + .deinit = wpa_driver_broadcom_deinit, + .set_countermeasures = wpa_driver_broadcom_set_countermeasures, + .scan2 = wpa_driver_broadcom_scan, + .get_scan_results2 = wpa_driver_broadcom_get_scan_results, + .deauthenticate = wpa_driver_broadcom_deauthenticate, + .disassociate = wpa_driver_broadcom_disassociate, + .associate = wpa_driver_broadcom_associate, +}; diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c index 26ca8d6..009a983 100644 --- a/src/drivers/driver_common.c +++ b/src/drivers/driver_common.c @@ -82,7 +82,6 @@ const char * event_to_string(enum wpa_event_type event) E2S(DRIVER_GTK_REKEY); E2S(SCHED_SCAN_STOPPED); E2S(DRIVER_CLIENT_POLL_OK); - E2S(EAPOL_TX_STATUS); } return "UNKNOWN"; diff --git a/src/drivers/driver_hostap.c b/src/drivers/driver_hostap.c index 8fc0efd..85e9251 100644 --- a/src/drivers/driver_hostap.c +++ b/src/drivers/driver_hostap.c @@ -15,7 +15,7 @@ #include "includes.h" #include -#include "linux_wext.h" +#include "wireless_copy.h" #include "common.h" #include "driver.h" #include "driver_wext.h" @@ -23,6 +23,8 @@ #include "driver_hostap.h" +#ifdef HOSTAPD + #include #include @@ -270,7 +272,7 @@ static int hostap_init_sockets(struct hostap_driver_data *drv, u8 *own_addr) } -static int hostap_send_mlme(void *priv, const u8 *msg, size_t len, int noack) +static int hostap_send_mlme(void *priv, const u8 *msg, size_t len) { struct hostap_driver_data *drv = priv; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) msg; @@ -319,7 +321,7 @@ static int hostap_send_eapol(void *priv, const u8 *addr, const u8 *data, pos += 2; memcpy(pos, data, data_len); - res = hostap_send_mlme(drv, (u8 *) hdr, len, 0); + res = hostap_send_mlme(drv, (u8 *) hdr, len); if (res < 0) { wpa_printf(MSG_ERROR, "hostap_send_eapol - packet len: %lu - " "failed: %d (%s)", @@ -1051,7 +1053,7 @@ static int hostap_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, memcpy(mgmt.bssid, own_addr, ETH_ALEN); mgmt.u.deauth.reason_code = host_to_le16(reason); return hostap_send_mlme(drv, (u8 *) &mgmt, IEEE80211_HDRLEN + - sizeof(mgmt.u.deauth), 0); + sizeof(mgmt.u.deauth)); } @@ -1088,7 +1090,7 @@ static int hostap_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr, memcpy(mgmt.bssid, own_addr, ETH_ALEN); mgmt.u.disassoc.reason_code = host_to_le16(reason); return hostap_send_mlme(drv, (u8 *) &mgmt, IEEE80211_HDRLEN + - sizeof(mgmt.u.disassoc), 0); + sizeof(mgmt.u.disassoc)); } @@ -1166,14 +1168,495 @@ static void wpa_driver_hostap_poll_client(void *priv, const u8 *own_addr, os_memcpy(hdr.IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN); os_memcpy(hdr.IEEE80211_SA_FROMDS, own_addr, ETH_ALEN); - hostap_send_mlme(priv, (u8 *)&hdr, sizeof(hdr), 0); + hostap_send_mlme(priv, (u8 *)&hdr, sizeof(hdr)); +} + +#else /* HOSTAPD */ + +struct wpa_driver_hostap_data { + void *wext; /* private data for driver_wext */ + void *ctx; + char ifname[IFNAMSIZ + 1]; + int sock; + int current_mode; /* infra/adhoc */ +}; + + +static int wpa_driver_hostap_set_auth_alg(void *priv, int auth_alg); + + +static int hostapd_ioctl(struct wpa_driver_hostap_data *drv, + struct prism2_hostapd_param *param, + int len, int show_err) +{ + struct iwreq iwr; + + os_memset(&iwr, 0, sizeof(iwr)); + os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); + iwr.u.data.pointer = (caddr_t) param; + iwr.u.data.length = len; + + if (ioctl(drv->sock, PRISM2_IOCTL_HOSTAPD, &iwr) < 0) { + int ret = errno; + if (show_err) + perror("ioctl[PRISM2_IOCTL_HOSTAPD]"); + return ret; + } + + return 0; +} + + +static int wpa_driver_hostap_set_wpa_ie(struct wpa_driver_hostap_data *drv, + const u8 *wpa_ie, size_t wpa_ie_len) +{ + struct prism2_hostapd_param *param; + int res; + size_t blen = PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN + wpa_ie_len; + if (blen < sizeof(*param)) + blen = sizeof(*param); + + param = os_zalloc(blen); + if (param == NULL) + return -1; + + param->cmd = PRISM2_HOSTAPD_SET_GENERIC_ELEMENT; + param->u.generic_elem.len = wpa_ie_len; + os_memcpy(param->u.generic_elem.data, wpa_ie, wpa_ie_len); + res = hostapd_ioctl(drv, param, blen, 1); + + os_free(param); + + return res; +} + + +static int prism2param(struct wpa_driver_hostap_data *drv, int param, + int value) +{ + struct iwreq iwr; + int *i, ret = 0; + + os_memset(&iwr, 0, sizeof(iwr)); + os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); + i = (int *) iwr.u.name; + *i++ = param; + *i++ = value; + + if (ioctl(drv->sock, PRISM2_IOCTL_PRISM2_PARAM, &iwr) < 0) { + perror("ioctl[PRISM2_IOCTL_PRISM2_PARAM]"); + ret = -1; + } + return ret; +} + + +static int wpa_driver_hostap_set_wpa(void *priv, int enabled) +{ + struct wpa_driver_hostap_data *drv = priv; + int ret = 0; + + wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled); + + if (!enabled && wpa_driver_hostap_set_wpa_ie(drv, NULL, 0) < 0) + ret = -1; + if (prism2param(drv, PRISM2_PARAM_HOST_ROAMING, enabled ? 2 : 0) < 0) + ret = -1; + if (prism2param(drv, PRISM2_PARAM_WPA, enabled) < 0) + ret = -1; + + return ret; +} + + +static void show_set_key_error(struct prism2_hostapd_param *param) +{ + switch (param->u.crypt.err) { + case HOSTAP_CRYPT_ERR_UNKNOWN_ALG: + wpa_printf(MSG_INFO, "Unknown algorithm '%s'.", + param->u.crypt.alg); + wpa_printf(MSG_INFO, "You may need to load kernel module to " + "register that algorithm."); + wpa_printf(MSG_INFO, "E.g., 'modprobe hostap_crypt_wep' for " + "WEP."); + break; + case HOSTAP_CRYPT_ERR_UNKNOWN_ADDR: + wpa_printf(MSG_INFO, "Unknown address " MACSTR ".", + MAC2STR(param->sta_addr)); + break; + case HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED: + wpa_printf(MSG_INFO, "Crypt algorithm initialization failed."); + break; + case HOSTAP_CRYPT_ERR_KEY_SET_FAILED: + wpa_printf(MSG_INFO, "Key setting failed."); + break; + case HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED: + wpa_printf(MSG_INFO, "TX key index setting failed."); + break; + case HOSTAP_CRYPT_ERR_CARD_CONF_FAILED: + wpa_printf(MSG_INFO, "Card configuration failed."); + break; + } +} + + +static int wpa_driver_hostap_set_key(const char *ifname, void *priv, + enum 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_hostap_data *drv = priv; + struct prism2_hostapd_param *param; + u8 *buf; + size_t blen; + int ret = 0; + char *alg_name; + + switch (alg) { + case WPA_ALG_NONE: + alg_name = "none"; + break; + case WPA_ALG_WEP: + alg_name = "WEP"; + break; + case WPA_ALG_TKIP: + alg_name = "TKIP"; + break; + case WPA_ALG_CCMP: + alg_name = "CCMP"; + break; + default: + 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 > 8) + return -2; + + blen = sizeof(*param) + key_len; + buf = os_zalloc(blen); + if (buf == NULL) + return -1; + + param = (struct prism2_hostapd_param *) buf; + param->cmd = PRISM2_SET_ENCRYPTION; + /* TODO: In theory, STA in client mode can use five keys; four default + * keys for receiving (with keyidx 0..3) and one individual key for + * both transmitting and receiving (keyidx 0) _unicast_ packets. Now, + * keyidx 0 is reserved for this unicast use and default keys can only + * use keyidx 1..3 (i.e., default key with keyidx 0 is not supported). + * This should be fine for more or less all cases, but for completeness + * sake, the driver could be enhanced to support the missing key. */ +#if 0 + if (addr == NULL) + os_memset(param->sta_addr, 0xff, ETH_ALEN); + else + os_memcpy(param->sta_addr, addr, ETH_ALEN); +#else + os_memset(param->sta_addr, 0xff, ETH_ALEN); +#endif + os_strlcpy((char *) param->u.crypt.alg, alg_name, + HOSTAP_CRYPT_ALG_NAME_LEN); + param->u.crypt.flags = set_tx ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0; + param->u.crypt.idx = key_idx; + if (seq) + os_memcpy(param->u.crypt.seq, seq, seq_len); + param->u.crypt.key_len = key_len; + os_memcpy((u8 *) (param + 1), key, key_len); + + if (hostapd_ioctl(drv, param, blen, 1)) { + wpa_printf(MSG_WARNING, "Failed to set encryption."); + show_set_key_error(param); + ret = -1; + } + os_free(buf); + + return ret; +} + + +static int wpa_driver_hostap_set_countermeasures(void *priv, int enabled) +{ + struct wpa_driver_hostap_data *drv = priv; + wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled); + return prism2param(drv, PRISM2_PARAM_TKIP_COUNTERMEASURES, enabled); +} + + +static int wpa_driver_hostap_reset(struct wpa_driver_hostap_data *drv, + int type) +{ + struct iwreq iwr; + int *i, ret = 0; + + wpa_printf(MSG_DEBUG, "%s: type=%d", __FUNCTION__, type); + + os_memset(&iwr, 0, sizeof(iwr)); + os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); + i = (int *) iwr.u.name; + *i++ = type; + + if (ioctl(drv->sock, PRISM2_IOCTL_RESET, &iwr) < 0) { + perror("ioctl[PRISM2_IOCTL_RESET]"); + ret = -1; + } + return ret; +} + + +static int wpa_driver_hostap_mlme(struct wpa_driver_hostap_data *drv, + const u8 *addr, int cmd, int reason_code) +{ + struct prism2_hostapd_param param; + int ret; + + /* There does not seem to be a better way of deauthenticating or + * disassociating with Prism2/2.5/3 than sending the management frame + * and then resetting the Port0 to make sure both the AP and the STA + * end up in disconnected state. */ + os_memset(¶m, 0, sizeof(param)); + param.cmd = PRISM2_HOSTAPD_MLME; + os_memcpy(param.sta_addr, addr, ETH_ALEN); + param.u.mlme.cmd = cmd; + param.u.mlme.reason_code = reason_code; + ret = hostapd_ioctl(drv, ¶m, sizeof(param), 1); + if (ret == 0) { + os_sleep(0, 100000); + ret = wpa_driver_hostap_reset(drv, 2); + } + return ret; +} + + +static int wpa_driver_hostap_deauthenticate(void *priv, const u8 *addr, + int reason_code) +{ + struct wpa_driver_hostap_data *drv = priv; + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); + return wpa_driver_hostap_mlme(drv, addr, MLME_STA_DEAUTH, + reason_code); +} + + +static int wpa_driver_hostap_disassociate(void *priv, const u8 *addr, + int reason_code) +{ + struct wpa_driver_hostap_data *drv = priv; + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); + return wpa_driver_hostap_mlme(drv, addr, MLME_STA_DISASSOC, + reason_code); } +static int +wpa_driver_hostap_associate(void *priv, + struct wpa_driver_associate_params *params) +{ + struct wpa_driver_hostap_data *drv = priv; + int ret = 0; + int allow_unencrypted_eapol; + + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); + + if (prism2param(drv, PRISM2_PARAM_DROP_UNENCRYPTED, + params->drop_unencrypted) < 0) + ret = -1; + if (wpa_driver_hostap_set_auth_alg(drv, params->auth_alg) < 0) + ret = -1; + if (params->mode != drv->current_mode) { + /* At the moment, Host AP driver requires host_roaming=2 for + * infrastructure mode and host_roaming=0 for adhoc. */ + if (prism2param(drv, PRISM2_PARAM_HOST_ROAMING, + params->mode == IEEE80211_MODE_IBSS ? 0 : 2) < + 0) { + wpa_printf(MSG_DEBUG, "%s: failed to set host_roaming", + __func__); + } + drv->current_mode = params->mode; + } + + if (prism2param(drv, PRISM2_PARAM_PRIVACY_INVOKED, + params->key_mgmt_suite != KEY_MGMT_NONE) < 0) + ret = -1; + if (wpa_driver_hostap_set_wpa_ie(drv, params->wpa_ie, + params->wpa_ie_len) < 0) + ret = -1; + if (wpa_driver_wext_set_mode(drv->wext, params->mode) < 0) + ret = -1; + if (params->freq && + wpa_driver_wext_set_freq(drv->wext, params->freq) < 0) + ret = -1; + if (wpa_driver_wext_set_ssid(drv->wext, params->ssid, params->ssid_len) + < 0) + ret = -1; + if (wpa_driver_wext_set_bssid(drv->wext, params->bssid) < 0) + ret = -1; + + /* Allow unencrypted EAPOL messages even if pairwise keys are set when + * not using WPA. IEEE 802.1X specifies that these frames are not + * encrypted, but WPA encrypts them when pairwise keys are in use. */ + if (params->key_mgmt_suite == KEY_MGMT_802_1X || + params->key_mgmt_suite == KEY_MGMT_PSK) + allow_unencrypted_eapol = 0; + else + allow_unencrypted_eapol = 1; + + if (prism2param(drv, PRISM2_PARAM_IEEE_802_1X, + allow_unencrypted_eapol) < 0) { + wpa_printf(MSG_DEBUG, "hostap: Failed to configure " + "ieee_802_1x param"); + /* Ignore this error.. driver_hostap.c can also be used with + * other drivers that do not support this prism2_param. */ + } + + return ret; +} + + +static int wpa_driver_hostap_scan(void *priv, + struct wpa_driver_scan_params *params) +{ + struct wpa_driver_hostap_data *drv = priv; + struct prism2_hostapd_param param; + int ret; + const u8 *ssid = params->ssids[0].ssid; + size_t ssid_len = params->ssids[0].ssid_len; + + if (ssid == NULL) { + /* Use standard Linux Wireless Extensions ioctl if possible + * because some drivers using hostap code in wpa_supplicant + * might not support Host AP specific scan request (with SSID + * info). */ + return wpa_driver_wext_scan(drv->wext, params); + } + + if (ssid_len > 32) + ssid_len = 32; + + os_memset(¶m, 0, sizeof(param)); + param.cmd = PRISM2_HOSTAPD_SCAN_REQ; + param.u.scan_req.ssid_len = ssid_len; + os_memcpy(param.u.scan_req.ssid, ssid, ssid_len); + ret = hostapd_ioctl(drv, ¶m, sizeof(param), 1); + + /* Not all drivers generate "scan completed" wireless event, so try to + * read results after a timeout. */ + eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv->wext, + drv->ctx); + eloop_register_timeout(3, 0, wpa_driver_wext_scan_timeout, drv->wext, + drv->ctx); + + return ret; +} + + +static int wpa_driver_hostap_set_auth_alg(void *priv, int auth_alg) +{ + struct wpa_driver_hostap_data *drv = priv; + int algs = 0; + + if (auth_alg & WPA_AUTH_ALG_OPEN) + algs |= 1; + if (auth_alg & WPA_AUTH_ALG_SHARED) + algs |= 2; + if (auth_alg & WPA_AUTH_ALG_LEAP) + algs |= 4; + if (algs == 0) + algs = 1; /* at least one algorithm should be set */ + + return prism2param(drv, PRISM2_PARAM_AP_AUTH_ALGS, algs); +} + + +static int wpa_driver_hostap_get_bssid(void *priv, u8 *bssid) +{ + struct wpa_driver_hostap_data *drv = priv; + return wpa_driver_wext_get_bssid(drv->wext, bssid); +} + + +static int wpa_driver_hostap_get_ssid(void *priv, u8 *ssid) +{ + struct wpa_driver_hostap_data *drv = priv; + return wpa_driver_wext_get_ssid(drv->wext, ssid); +} + + +static struct wpa_scan_results * wpa_driver_hostap_get_scan_results(void *priv) +{ + struct wpa_driver_hostap_data *drv = priv; + return wpa_driver_wext_get_scan_results(drv->wext); +} + + +static int wpa_driver_hostap_set_operstate(void *priv, int state) +{ + struct wpa_driver_hostap_data *drv = priv; + return wpa_driver_wext_set_operstate(drv->wext, state); +} + + +static void * wpa_driver_hostap_init(void *ctx, const char *ifname) +{ + struct wpa_driver_hostap_data *drv; + + drv = os_zalloc(sizeof(*drv)); + if (drv == NULL) + return NULL; + drv->wext = wpa_driver_wext_init(ctx, ifname); + if (drv->wext == NULL) { + os_free(drv); + 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) { + perror("socket"); + wpa_driver_wext_deinit(drv->wext); + os_free(drv); + return NULL; + } + + if (os_strncmp(ifname, "wlan", 4) == 0) { + /* + * Host AP driver may use both wlan# and wifi# interface in + * wireless events. + */ + char ifname2[IFNAMSIZ + 1]; + os_strlcpy(ifname2, ifname, sizeof(ifname2)); + os_memcpy(ifname2, "wifi", 4); + wpa_driver_wext_alternative_ifindex(drv->wext, ifname2); + } + + wpa_driver_hostap_set_wpa(drv, 1); + + return drv; +} + + +static void wpa_driver_hostap_deinit(void *priv) +{ + struct wpa_driver_hostap_data *drv = priv; + wpa_driver_hostap_set_wpa(drv, 0); + wpa_driver_wext_deinit(drv->wext); + close(drv->sock); + os_free(drv); +} + +#endif /* HOSTAPD */ + + const struct wpa_driver_ops wpa_driver_hostap_ops = { .name = "hostap", .desc = "Host AP driver (Intersil Prism2/2.5/3)", .set_key = wpa_driver_hostap_set_key, +#ifdef HOSTAPD .hapd_init = hostap_init, .hapd_deinit = hostap_driver_deinit, .set_ieee8021x = hostap_set_ieee8021x, @@ -1196,4 +1679,17 @@ const struct wpa_driver_ops wpa_driver_hostap_ops = { .set_ap_wps_ie = hostap_set_ap_wps_ie, .set_freq = hostap_set_freq, .poll_client = wpa_driver_hostap_poll_client, +#else /* HOSTAPD */ + .get_bssid = wpa_driver_hostap_get_bssid, + .get_ssid = wpa_driver_hostap_get_ssid, + .set_countermeasures = wpa_driver_hostap_set_countermeasures, + .scan2 = wpa_driver_hostap_scan, + .get_scan_results2 = wpa_driver_hostap_get_scan_results, + .deauthenticate = wpa_driver_hostap_deauthenticate, + .disassociate = wpa_driver_hostap_disassociate, + .associate = wpa_driver_hostap_associate, + .init = wpa_driver_hostap_init, + .deinit = wpa_driver_hostap_deinit, + .set_operstate = wpa_driver_hostap_set_operstate, +#endif /* HOSTAPD */ }; diff --git a/src/drivers/driver_iphone.m b/src/drivers/driver_iphone.m new file mode 100644 index 0000000..8213fda --- /dev/null +++ b/src/drivers/driver_iphone.m @@ -0,0 +1,466 @@ +/* + * WPA Supplicant - iPhone/iPod touch Apple80211 driver interface + * Copyright (c) 2007, Jouni Malinen + * + * 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" +#define Boolean __DummyBoolean +#include +#undef Boolean + +#include "common.h" +#include "driver.h" +#include "eloop.h" +#include "common/ieee802_11_defs.h" + +#include "MobileApple80211.h" + +struct wpa_driver_iphone_data { + void *ctx; + Apple80211Ref wireless_ctx; + CFArrayRef scan_results; + int ctrl_power; +}; + + +static const void * cfdict_get_key_str(CFDictionaryRef dict, const char *key) +{ + const void *res; + CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, key, + kCFStringEncodingMacRoman); + if (str == NULL) + return NULL; + + res = CFDictionaryGetValue(dict, str); + CFRelease(str); + return res; +} + + +static int wpa_driver_iphone_get_ssid(void *priv, u8 *ssid) +{ + struct wpa_driver_iphone_data *drv = priv; + CFDataRef data; + int err, len; + + err = Apple80211CopyValue(drv->wireless_ctx, APPLE80211_VALUE_SSID, 0, + &data); + if (err != 0) { + wpa_printf(MSG_DEBUG, "iPhone: Apple80211CopyValue(SSID) " + "failed: %d", err); + return -1; + } + + len = CFDataGetLength(data); + if (len > 32) { + CFRelease(data); + return -1; + } + os_memcpy(ssid, CFDataGetBytePtr(data), len); + CFRelease(data); + + return len; +} + + +static int wpa_driver_iphone_get_bssid(void *priv, u8 *bssid) +{ + struct wpa_driver_iphone_data *drv = priv; + CFStringRef data; + int err; + int a1, a2, a3, a4, a5, a6; + + err = Apple80211CopyValue(drv->wireless_ctx, APPLE80211_VALUE_BSSID, 0, + &data); + if (err != 0) { + wpa_printf(MSG_DEBUG, "iPhone: Apple80211CopyValue(BSSID) " + "failed: %d", err); + return -1; + } + + sscanf(CFStringGetCStringPtr(data, kCFStringEncodingMacRoman), + "%x:%x:%x:%x:%x:%x", &a1, &a2, &a3, &a4, &a5, &a6); + bssid[0] = a1; + bssid[1] = a2; + bssid[2] = a3; + bssid[3] = a4; + bssid[4] = a5; + bssid[5] = a6; + + CFRelease(data); + + return 0; +} + + +static void wpa_driver_iphone_scan_timeout(void *eloop_ctx, void *timeout_ctx) +{ + wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL); +} + + +static int wpa_driver_iphone_scan(void *priv, const u8 *ssid, size_t ssid_len) +{ + struct wpa_driver_iphone_data *drv = priv; + int err; + + if (drv->scan_results) { + CFRelease(drv->scan_results); + drv->scan_results = NULL; + } + + err = Apple80211Scan(drv->wireless_ctx, &drv->scan_results, NULL); + if (err) { + wpa_printf(MSG_DEBUG, "iPhone: Apple80211Scan failed: %d", + err); + return -1; + } + + eloop_register_timeout(0, 0, wpa_driver_iphone_scan_timeout, drv, + drv->ctx); + return 0; +} + + +static int wpa_driver_iphone_get_scan_results(void *priv, + struct wpa_scan_result *results, + size_t max_size) +{ + struct wpa_driver_iphone_data *drv = priv; + size_t i, num; + + if (drv->scan_results == NULL) + return 0; + + num = CFArrayGetCount(drv->scan_results); + if (num > max_size) + num = max_size; + os_memset(results, 0, num * sizeof(struct wpa_scan_result)); + + for (i = 0; i < num; i++) { + struct wpa_scan_result *res = &results[i]; + CFDictionaryRef dict = + CFArrayGetValueAtIndex(drv->scan_results, i); + CFDataRef data; + CFStringRef str; + CFNumberRef num; + int val; + + data = cfdict_get_key_str(dict, "SSID"); + if (data) { + res->ssid_len = CFDataGetLength(data); + if (res->ssid_len > 32) + res->ssid_len = 32; + os_memcpy(res->ssid, CFDataGetBytePtr(data), + res->ssid_len); + } + + str = cfdict_get_key_str(dict, "BSSID"); + if (str) { + int a1, a2, a3, a4, a5, a6; + sscanf(CFStringGetCStringPtr( + str, kCFStringEncodingMacRoman), + "%x:%x:%x:%x:%x:%x", + &a1, &a2, &a3, &a4, &a5, &a6); + res->bssid[0] = a1; + res->bssid[1] = a2; + res->bssid[2] = a3; + res->bssid[3] = a4; + res->bssid[4] = a5; + res->bssid[5] = a6; + } + + num = cfdict_get_key_str(dict, "CAPABILITIES"); + if (num) { + if (CFNumberGetValue(num, kCFNumberSInt32Type, &val)) + res->caps = val; + } + + num = cfdict_get_key_str(dict, "CHANNEL"); + if (num) { + if (CFNumberGetValue(num, kCFNumberSInt32Type, &val)) + res->freq = 2407 + val * 5; + } + + num = cfdict_get_key_str(dict, "RSSI"); + if (num) { + if (CFNumberGetValue(num, kCFNumberSInt32Type, &val)) + res->level = val; + } + + num = cfdict_get_key_str(dict, "NOISE"); + if (num) { + if (CFNumberGetValue(num, kCFNumberSInt32Type, &val)) + res->noise = val; + } + + data = cfdict_get_key_str(dict, "IE"); + if (data) { + u8 *ptr = (u8 *) CFDataGetBytePtr(data); + int len = CFDataGetLength(data); + u8 *pos = ptr, *end = ptr + len; + + while (pos + 2 < end) { + if (pos + 2 + pos[1] > end) + break; + if (pos[0] == WLAN_EID_RSN && + pos[1] <= SSID_MAX_WPA_IE_LEN) { + os_memcpy(res->rsn_ie, pos, + 2 + pos[1]); + res->rsn_ie_len = 2 + pos[1]; + } + if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && + pos[1] > 4 && pos[2] == 0x00 && + pos[3] == 0x50 && pos[4] == 0xf2 && + pos[5] == 0x01) { + os_memcpy(res->wpa_ie, pos, + 2 + pos[1]); + res->wpa_ie_len = 2 + pos[1]; + } + + pos = pos + 2 + pos[1]; + } + } + } + + return num; +} + + +static void wpa_driver_iphone_assoc_timeout(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_driver_iphone_data *drv = eloop_ctx; + u8 bssid[ETH_ALEN]; + + if (wpa_driver_iphone_get_bssid(drv, bssid) != 0) { + eloop_register_timeout(1, 0, wpa_driver_iphone_assoc_timeout, + drv, drv->ctx); + return; + } + + wpa_supplicant_event(timeout_ctx, EVENT_ASSOC, NULL); +} + + +static int wpa_driver_iphone_associate( + void *priv, struct wpa_driver_associate_params *params) +{ + struct wpa_driver_iphone_data *drv = priv; + int i, num, err; + size_t ssid_len; + CFDictionaryRef bss = NULL; + + /* + * TODO: Consider generating parameters instead of just using an entry + * from scan results in order to support ap_scan=2. + */ + + if (drv->scan_results == NULL) { + wpa_printf(MSG_DEBUG, "iPhone: No scan results - cannot " + "associate"); + return -1; + } + + num = CFArrayGetCount(drv->scan_results); + + for (i = 0; i < num; i++) { + CFDictionaryRef dict = + CFArrayGetValueAtIndex(drv->scan_results, i); + CFDataRef data; + + data = cfdict_get_key_str(dict, "SSID"); + if (data == NULL) + continue; + + ssid_len = CFDataGetLength(data); + if (ssid_len != params->ssid_len || + os_memcmp(CFDataGetBytePtr(data), params->ssid, ssid_len) + != 0) + continue; + + bss = dict; + break; + } + + if (bss == NULL) { + wpa_printf(MSG_DEBUG, "iPhone: Could not find SSID from scan " + "results - cannot associate"); + return -1; + } + + wpa_printf(MSG_DEBUG, "iPhone: Trying to associate with a BSS found " + "from scan results"); + + err = Apple80211Associate(drv->wireless_ctx, bss, NULL); + if (err) { + wpa_printf(MSG_DEBUG, "iPhone: Apple80211Associate() failed: " + "%d", err); + return -1; + } + + /* + * Driver is actually already associated; report association from an + * eloop callback. + */ + eloop_cancel_timeout(wpa_driver_iphone_assoc_timeout, drv, drv->ctx); + eloop_register_timeout(0, 0, wpa_driver_iphone_assoc_timeout, drv, + drv->ctx); + + return 0; +} + + +static int wpa_driver_iphone_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) +{ + /* + * TODO: Need to either support configuring PMK for 4-way handshake or + * PTK for TKIP/CCMP. + */ + return -1; +} + + +static int wpa_driver_iphone_get_capa(void *priv, struct wpa_driver_capa *capa) +{ + os_memset(capa, 0, sizeof(*capa)); + + capa->key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA | + WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | + WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | + WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK; + capa->enc = WPA_DRIVER_CAPA_ENC_WEP40 | WPA_DRIVER_CAPA_ENC_WEP104 | + WPA_DRIVER_CAPA_ENC_TKIP | WPA_DRIVER_CAPA_ENC_CCMP; + capa->auth = WPA_DRIVER_AUTH_OPEN | WPA_DRIVER_AUTH_SHARED | + WPA_DRIVER_AUTH_LEAP; + capa->flags = WPA_DRIVER_FLAGS_4WAY_HANDSHAKE; + + return 0; +} + + +static void * wpa_driver_iphone_init(void *ctx, const char *ifname) +{ + struct wpa_driver_iphone_data *drv; + int err; + char power; + CFStringRef name; + CFDictionaryRef dict; + + drv = os_zalloc(sizeof(*drv)); + if (drv == NULL) + return NULL; + drv->ctx = ctx; + err = Apple80211Open(&drv->wireless_ctx); + if (err) { + wpa_printf(MSG_ERROR, "iPhone: Apple80211Open failed: %d", + err); + os_free(drv); + return NULL; + } + + name = CFStringCreateWithCString(kCFAllocatorDefault, ifname, + kCFStringEncodingISOLatin1); + if (name == NULL) { + wpa_printf(MSG_ERROR, "iPhone: ifname -> CFString failed"); + Apple80211Close(drv->wireless_ctx); + os_free(drv); + return NULL; + } + + err = Apple80211BindToInterface(drv->wireless_ctx, name); + CFRelease(name); + + if (err) { + wpa_printf(MSG_ERROR, "iPhone: Apple80211BindToInterface " + "failed: %d", err); + Apple80211Close(drv->wireless_ctx); + os_free(drv); + return NULL; + } + + err = Apple80211GetPower(drv->wireless_ctx, &power); + if (err) + wpa_printf(MSG_DEBUG, "iPhone: Apple80211GetPower failed: %d", + err); + + wpa_printf(MSG_DEBUG, "iPhone: Power=%d", power); + + if (!power) { + drv->ctrl_power = 1; + err = Apple80211SetPower(drv->wireless_ctx, 1); + if (err) { + wpa_printf(MSG_DEBUG, "iPhone: Apple80211SetPower " + "failed: %d", err); + Apple80211Close(drv->wireless_ctx); + os_free(drv); + return NULL; + } + } + + err = Apple80211GetInfoCopy(drv->wireless_ctx, &dict); + if (err == 0) { + CFShow(dict); + CFRelease(dict); + } else { + printf("Apple80211GetInfoCopy: %d\n", err); + } + + return drv; +} + + +static void wpa_driver_iphone_deinit(void *priv) +{ + struct wpa_driver_iphone_data *drv = priv; + int err; + + eloop_cancel_timeout(wpa_driver_iphone_scan_timeout, drv, drv->ctx); + eloop_cancel_timeout(wpa_driver_iphone_assoc_timeout, drv, drv->ctx); + + if (drv->ctrl_power) { + wpa_printf(MSG_DEBUG, "iPhone: Power down the interface"); + err = Apple80211SetPower(drv->wireless_ctx, 0); + if (err) { + wpa_printf(MSG_DEBUG, "iPhone: Apple80211SetPower(0) " + "failed: %d", err); + } + } + + err = Apple80211Close(drv->wireless_ctx); + if (err) { + wpa_printf(MSG_DEBUG, "iPhone: Apple80211Close failed: %d", + err); + } + + if (drv->scan_results) + CFRelease(drv->scan_results); + + os_free(drv); +} + + +const struct wpa_driver_ops wpa_driver_iphone_ops = { + .name = "iphone", + .desc = "iPhone/iPod touch Apple80211 driver", + .get_ssid = wpa_driver_iphone_get_ssid, + .get_bssid = wpa_driver_iphone_get_bssid, + .init = wpa_driver_iphone_init, + .deinit = wpa_driver_iphone_deinit, + .scan = wpa_driver_iphone_scan, + .get_scan_results = wpa_driver_iphone_get_scan_results, + .associate = wpa_driver_iphone_associate, + .set_key = wpa_driver_iphone_set_key, + .get_capa = wpa_driver_iphone_get_capa, +}; diff --git a/src/drivers/driver_madwifi.c b/src/drivers/driver_madwifi.c index edb086f..0a855e7 100644 --- a/src/drivers/driver_madwifi.c +++ b/src/drivers/driver_madwifi.c @@ -27,7 +27,7 @@ #include "driver_wext.h" #include "eloop.h" #include "common/ieee802_11_defs.h" -#include "linux_wext.h" +#include "wireless_copy.h" /* * Avoid conflicts with wpa_supplicant definitions by undefining a definition. @@ -71,6 +71,8 @@ #define WPA_KEY_RSC_LEN 8 +#ifdef HOSTAPD + #include "priv_netlink.h" #include "netlink.h" #include "linux_ioctl.h" @@ -1292,11 +1294,554 @@ madwifi_commit(void *priv) return linux_set_iface_flags(drv->ioctl_sock, drv->iface, 1); } +#else /* HOSTAPD */ + +struct wpa_driver_madwifi_data { + void *wext; /* private data for driver_wext */ + void *ctx; + char ifname[IFNAMSIZ + 1]; + int sock; +}; + +static int wpa_driver_madwifi_set_auth_alg(void *priv, int auth_alg); +static int wpa_driver_madwifi_set_probe_req_ie(void *priv, const u8 *ies, + size_t ies_len); + + +static int +set80211priv(struct wpa_driver_madwifi_data *drv, int op, void *data, int len, + int show_err) +{ + struct iwreq iwr; + + 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; + } + + if (ioctl(drv->sock, op, &iwr) < 0) { + if (show_err) { +#ifdef MADWIFI_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 /* MADWIFI_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 /* MADWIFI_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_madwifi_data *drv, int op, int arg, + int show_err) +{ + struct iwreq iwr; + + 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)); + + if (ioctl(drv->sock, IEEE80211_IOCTL_SETPARAM, &iwr) < 0) { + if (show_err) + perror("ioctl[IEEE80211_IOCTL_SETPARAM]"); + return -1; + } + return 0; +} + +static int +wpa_driver_madwifi_set_wpa_ie(struct wpa_driver_madwifi_data *drv, + const u8 *wpa_ie, size_t wpa_ie_len) +{ + struct iwreq iwr; + + 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; + + if (ioctl(drv->sock, IEEE80211_IOCTL_SETOPTIE, &iwr) < 0) { + perror("ioctl[IEEE80211_IOCTL_SETOPTIE]"); + return -1; + } + return 0; +} + +static int +wpa_driver_madwifi_del_key(struct wpa_driver_madwifi_data *drv, int key_idx, + const u8 *addr) +{ + struct ieee80211req_del_key wk; + + 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_madwifi_set_key(const char *ifname, void *priv, enum 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_madwifi_data *drv = priv; + struct ieee80211req_key wk; + char *alg_name; + u_int8_t cipher; + + if (alg == WPA_ALG_NONE) + return wpa_driver_madwifi_del_key(drv, key_idx, addr); + + switch (alg) { + case WPA_ALG_WEP: + if (addr == NULL || os_memcmp(addr, "\xff\xff\xff\xff\xff\xff", + ETH_ALEN) == 0) { + /* + * madwifi did not seem to like static WEP key + * configuration with IEEE80211_IOCTL_SETKEY, so use + * Linux wireless extensions ioctl for this. + */ + return wpa_driver_wext_set_key(ifname, drv->wext, alg, + addr, key_idx, set_tx, + seq, seq_len, + key, key_len); + } + 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 + if (seq) { + 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 */ + if (seq) + os_memcpy(&wk.ik_keyrsc, seq, seq_len); +#endif /* WORDS_BIGENDIAN */ + os_memcpy(wk.ik_keydata, key, key_len); + + return set80211priv(drv, IEEE80211_IOCTL_SETKEY, &wk, sizeof(wk), 1); +} + +static int +wpa_driver_madwifi_set_countermeasures(void *priv, int enabled) +{ + struct wpa_driver_madwifi_data *drv = priv; + wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled); + return set80211param(drv, IEEE80211_PARAM_COUNTERMEASURES, enabled, 1); +} + +static int +wpa_driver_madwifi_deauthenticate(void *priv, const u8 *addr, int reason_code) +{ + struct wpa_driver_madwifi_data *drv = priv; + struct ieee80211req_mlme mlme; + + 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); + return set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme), 1); +} + +static int +wpa_driver_madwifi_disassociate(void *priv, const u8 *addr, int reason_code) +{ + struct wpa_driver_madwifi_data *drv = priv; + struct ieee80211req_mlme mlme; + + 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); + return set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme), 1); +} + +static int +wpa_driver_madwifi_associate(void *priv, + struct wpa_driver_associate_params *params) +{ + struct wpa_driver_madwifi_data *drv = priv; + struct ieee80211req_mlme mlme; + int ret = 0, privacy = 1; + + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); + + if (set80211param(drv, IEEE80211_PARAM_DROPUNENCRYPTED, + params->drop_unencrypted, 1) < 0) + ret = -1; + if (wpa_driver_madwifi_set_auth_alg(drv, params->auth_alg) < 0) + ret = -1; + + /* + * NB: Don't need to set the freq or cipher-related state as + * this is implied by the bssid which is used to locate + * the scanned node state which holds it. The ssid is + * needed to disambiguate an AP that broadcasts multiple + * ssid's but uses the same bssid. + */ + /* XXX error handling is wrong but unclear what to do... */ + if (wpa_driver_madwifi_set_wpa_ie(drv, params->wpa_ie, + params->wpa_ie_len) < 0) + ret = -1; + + if (params->pairwise_suite == CIPHER_NONE && + params->group_suite == CIPHER_NONE && + params->key_mgmt_suite == KEY_MGMT_NONE && + params->wpa_ie_len == 0) + privacy = 0; + + if (set80211param(drv, IEEE80211_PARAM_PRIVACY, privacy, 1) < 0) + ret = -1; + + if (params->wpa_ie_len && + set80211param(drv, IEEE80211_PARAM_WPA, + params->wpa_ie[0] == WLAN_EID_RSN ? 2 : 1, 1) < 0) + ret = -1; + + if (params->bssid == NULL) { + /* ap_scan=2 mode - driver takes care of AP selection and + * roaming */ + /* FIX: this does not seem to work; would probably need to + * change something in the driver */ + if (set80211param(drv, IEEE80211_PARAM_ROAMING, 0, 1) < 0) + ret = -1; + + if (wpa_driver_wext_set_ssid(drv->wext, params->ssid, + params->ssid_len) < 0) + ret = -1; + } else { + if (set80211param(drv, IEEE80211_PARAM_ROAMING, 2, 1) < 0) + ret = -1; + if (wpa_driver_wext_set_ssid(drv->wext, params->ssid, + params->ssid_len) < 0) + ret = -1; + os_memset(&mlme, 0, sizeof(mlme)); + mlme.im_op = IEEE80211_MLME_ASSOC; + os_memcpy(mlme.im_macaddr, params->bssid, IEEE80211_ADDR_LEN); + if (set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, + sizeof(mlme), 1) < 0) { + wpa_printf(MSG_DEBUG, "%s: SETMLME[ASSOC] failed", + __func__); + ret = -1; + } + } + + return ret; +} + +static int +wpa_driver_madwifi_set_auth_alg(void *priv, int auth_alg) +{ + struct wpa_driver_madwifi_data *drv = priv; + int authmode; + + if ((auth_alg & WPA_AUTH_ALG_OPEN) && + (auth_alg & WPA_AUTH_ALG_SHARED)) + authmode = IEEE80211_AUTH_AUTO; + else if (auth_alg & WPA_AUTH_ALG_SHARED) + authmode = IEEE80211_AUTH_SHARED; + else + authmode = IEEE80211_AUTH_OPEN; + + return set80211param(drv, IEEE80211_PARAM_AUTHMODE, authmode, 1); +} + +static int +wpa_driver_madwifi_scan(void *priv, struct wpa_driver_scan_params *params) +{ + struct wpa_driver_madwifi_data *drv = priv; + struct iwreq iwr; + int ret = 0; + const u8 *ssid = params->ssids[0].ssid; + size_t ssid_len = params->ssids[0].ssid_len; + + wpa_driver_madwifi_set_probe_req_ie(drv, params->extra_ies, + params->extra_ies_len); + + os_memset(&iwr, 0, sizeof(iwr)); + os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); + + /* set desired ssid before scan */ + /* FIX: scan should not break the current association, so using + * set_ssid may not be the best way of doing this.. */ + if (wpa_driver_wext_set_ssid(drv->wext, ssid, ssid_len) < 0) + ret = -1; + + if (ioctl(drv->sock, SIOCSIWSCAN, &iwr) < 0) { + perror("ioctl[SIOCSIWSCAN]"); + ret = -1; + } + + /* + * madwifi delivers a scan complete event so no need to poll, but + * register a backup timeout anyway to make sure that we recover even + * if the driver does not send this event for any reason. This timeout + * will only be used if the event is not delivered (event handler will + * cancel the timeout). + */ + 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_madwifi_get_bssid(void *priv, u8 *bssid) +{ + struct wpa_driver_madwifi_data *drv = priv; + return wpa_driver_wext_get_bssid(drv->wext, bssid); +} + + +static int wpa_driver_madwifi_get_ssid(void *priv, u8 *ssid) +{ + struct wpa_driver_madwifi_data *drv = priv; + return wpa_driver_wext_get_ssid(drv->wext, ssid); +} + + +static struct wpa_scan_results * +wpa_driver_madwifi_get_scan_results(void *priv) +{ + struct wpa_driver_madwifi_data *drv = priv; + return wpa_driver_wext_get_scan_results(drv->wext); +} + + +static int wpa_driver_madwifi_set_operstate(void *priv, int state) +{ + struct wpa_driver_madwifi_data *drv = priv; + return wpa_driver_wext_set_operstate(drv->wext, state); +} + + +static int wpa_driver_madwifi_set_probe_req_ie(void *priv, const u8 *ies, + size_t ies_len) +{ + struct ieee80211req_getset_appiebuf *probe_req_ie; + int ret; + + 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); + + 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_madwifi_init(void *ctx, const char *ifname) +{ + struct wpa_driver_madwifi_data *drv; + + drv = os_zalloc(sizeof(*drv)); + if (drv == NULL) + return NULL; + drv->wext = wpa_driver_wext_init(ctx, ifname); + if (drv->wext == NULL) + goto fail; + + drv->ctx = ctx; + os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); + drv->sock = socket(PF_INET, SOCK_DGRAM, 0); + if (drv->sock < 0) + goto fail2; + + if (set80211param(drv, IEEE80211_PARAM_ROAMING, 2, 1) < 0) { + wpa_printf(MSG_DEBUG, "%s: failed to set wpa_supplicant-based " + "roaming", __FUNCTION__); + goto fail3; + } + + if (set80211param(drv, IEEE80211_PARAM_WPA, 3, 1) < 0) { + wpa_printf(MSG_DEBUG, "%s: failed to enable WPA support", + __FUNCTION__); + goto fail3; + } + + return drv; + +fail3: + close(drv->sock); +fail2: + wpa_driver_wext_deinit(drv->wext); +fail: + os_free(drv); + return NULL; +} + + +static void wpa_driver_madwifi_deinit(void *priv) +{ + struct wpa_driver_madwifi_data *drv = priv; + + if (wpa_driver_madwifi_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); +} + +#endif /* HOSTAPD */ + const struct wpa_driver_ops wpa_driver_madwifi_ops = { .name = "madwifi", .desc = "MADWIFI 802.11 support (Atheros, etc.)", .set_key = wpa_driver_madwifi_set_key, +#ifdef HOSTAPD .hapd_init = madwifi_init, .hapd_deinit = madwifi_deinit, .set_ieee8021x = madwifi_set_ieee8021x, @@ -1316,4 +1861,17 @@ const struct wpa_driver_ops wpa_driver_madwifi_ops = { .commit = madwifi_commit, .set_ap_wps_ie = madwifi_set_ap_wps_ie, .set_freq = madwifi_set_freq, +#else /* HOSTAPD */ + .get_bssid = wpa_driver_madwifi_get_bssid, + .get_ssid = wpa_driver_madwifi_get_ssid, + .init = wpa_driver_madwifi_init, + .deinit = wpa_driver_madwifi_deinit, + .set_countermeasures = wpa_driver_madwifi_set_countermeasures, + .scan2 = wpa_driver_madwifi_scan, + .get_scan_results2 = wpa_driver_madwifi_get_scan_results, + .deauthenticate = wpa_driver_madwifi_deauthenticate, + .disassociate = wpa_driver_madwifi_disassociate, + .associate = wpa_driver_madwifi_associate, + .set_operstate = wpa_driver_madwifi_set_operstate, +#endif /* HOSTAPD */ }; diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c old mode 100644 new mode 100755 index bc8b1fc..e39e396 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -28,7 +28,6 @@ #include #include #include -#include #include "nl80211_copy.h" #include "common.h" @@ -44,29 +43,6 @@ #include "rfkill.h" #include "driver.h" -#ifndef SO_WIFI_STATUS -# if defined(__sparc__) -# define SO_WIFI_STATUS 0x0025 -# elif defined(__parisc__) -# define SO_WIFI_STATUS 0x4022 -# else -# define SO_WIFI_STATUS 41 -# endif - -# define SCM_WIFI_STATUS SO_WIFI_STATUS -#endif - -#ifndef SO_EE_ORIGIN_TXSTATUS -#define SO_EE_ORIGIN_TXSTATUS 4 -#endif - -#ifndef PACKET_TX_TIMESTAMP -#define PACKET_TX_TIMESTAMP 16 -#endif - -#ifdef ANDROID -#include "android_drv.h" -#endif /* ANDROID */ #ifdef CONFIG_LIBNL20 /* libnl 2.0 compatibility code */ #define nl_handle nl_sock @@ -112,37 +88,65 @@ static void nl80211_handle_destroy(struct nl_handle *handle) nl_handle_destroy(handle); } + +static inline int __genl_ctrl_alloc_cache(struct nl_handle *h, + struct nl_cache **cache) +{ + struct nl_cache *tmp = genl_ctrl_alloc_cache(h); + if (!tmp) + return -ENOMEM; + *cache = tmp; + return 0; +} +#define genl_ctrl_alloc_cache __genl_ctrl_alloc_cache #endif /* CONFIG_LIBNL20 */ -static struct nl_handle * nl_create_handle(struct nl_cb *cb, const char *dbg) -{ +struct nl80211_handles { struct nl_handle *handle; + struct nl_cache *cache; +}; + + +static int nl_create_handles(struct nl80211_handles *handles, struct nl_cb *cb, + const char *dbg) +{ + if (!handles) + return -1; - handle = nl80211_handle_alloc(cb); - if (handle == NULL) { + handles->handle = nl80211_handle_alloc(cb); + if (handles->handle == NULL) { wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink " "callbacks (%s)", dbg); - return NULL; + return -1; } - if (genl_connect(handle)) { + if (genl_connect(handles->handle)) { wpa_printf(MSG_ERROR, "nl80211: Failed to connect to generic " "netlink (%s)", dbg); - nl80211_handle_destroy(handle); - return NULL; + goto err; } - return handle; + if (genl_ctrl_alloc_cache(handles->handle, &handles->cache) < 0) { + wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic " + "netlink cache (%s)", dbg); + goto err; + } + + return 0; +err: + nl80211_handle_destroy(handles->handle); + return -1; } -static void nl_destroy_handles(struct nl_handle **handle) +static void nl_destroy_handles(struct nl80211_handles *handles) { - if (*handle == NULL) + if (handles->handle == NULL) return; - nl80211_handle_destroy(*handle); - *handle = NULL; + nl_cache_free(handles->cache); + nl80211_handle_destroy(handles->handle); + handles->handle = NULL; } @@ -165,22 +169,9 @@ struct nl80211_global { int if_add_ifindex; struct netlink_data *netlink; struct nl_cb *nl_cb; - struct nl_handle *nl; - int nl80211_id; + struct nl80211_handles nl; + struct genl_family *nl80211; int ioctl_sock; /* socket for ioctl() use */ - - struct nl_handle *nl_event; -}; - -struct nl80211_wiphy_data { - struct dl_list list; - struct dl_list bsss; - struct dl_list drvs; - - struct nl_handle *nl_beacons; - struct nl_cb *nl_cb; - - int wiphy_idx; }; static void nl80211_global_deinit(void *priv); @@ -195,22 +186,12 @@ struct i802_bss { unsigned int beacon_set:1; unsigned int added_if_into_bridge:1; unsigned int added_bridge:1; - - u8 addr[ETH_ALEN]; - - int freq; - - struct nl_handle *nl_preq, *nl_mgmt; - struct nl_cb *nl_cb; - - struct nl80211_wiphy_data *wiphy_data; - struct dl_list wiphy_list; }; struct wpa_driver_nl80211_data { struct nl80211_global *global; struct dl_list list; - struct dl_list wiphy_list; + u8 addr[ETH_ALEN]; char phyname[32]; void *ctx; int ifindex; @@ -225,7 +206,7 @@ struct wpa_driver_nl80211_data { int scan_complete_events; - struct nl_cb *nl_cb; + struct nl80211_handles nl_event, nl_preq; u8 auth_bssid[ETH_ALEN]; u8 bssid[ETH_ALEN]; @@ -238,29 +219,26 @@ struct wpa_driver_nl80211_data { int monitor_sock; int monitor_ifidx; - int monitor_refcount; + int no_monitor_iface_capab; unsigned int disabled_11b_rates:1; unsigned int pending_remain_on_chan:1; unsigned int in_interface_list:1; - unsigned int device_ap_sme:1; - unsigned int poll_command_supported:1; - unsigned int data_tx_status:1; - unsigned int scan_for_auth:1; - unsigned int retry_auth:1; - unsigned int use_monitor:1; u64 remain_on_chan_cookie; u64 send_action_cookie; unsigned int last_mgmt_freq; + unsigned int ap_oper_freq; struct wpa_driver_scan_filter *filter_ssids; size_t num_filter_ssids; struct i802_bss first_bss; - int eapol_tx_sock; +#ifdef CONFIG_AP + struct l2_packet_data *l2; +#endif /* CONFIG_AP */ #ifdef HOSTAPD int eapol_sock; /* socket for EAPOL frames */ @@ -272,20 +250,6 @@ struct wpa_driver_nl80211_data { int last_freq; int last_freq_ht; #endif /* HOSTAPD */ - - /* From failed authentication command */ - int auth_freq; - u8 auth_bssid_[ETH_ALEN]; - u8 auth_ssid[32]; - size_t auth_ssid_len; - int auth_alg; - u8 *auth_ie; - size_t auth_ie_len; - u8 auth_wep_key[4][16]; - size_t auth_wep_key_len[4]; - int auth_wep_tx_keyidx; - int auth_local_state_change; - int auth_p2p; }; @@ -300,16 +264,11 @@ static int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv, int local_state_change); static void nl80211_remove_monitor_interface( struct wpa_driver_nl80211_data *drv); -static int nl80211_send_frame_cmd(struct i802_bss *bss, +static int nl80211_send_frame_cmd(struct wpa_driver_nl80211_data *drv, unsigned int freq, unsigned int wait, const u8 *buf, size_t buf_len, u64 *cookie, - int no_cck, int no_ack, int offchanok); + int no_cck); static int wpa_driver_nl80211_probe_req_report(void *priv, int report); -#ifdef ANDROID -static int android_pno_start(struct i802_bss *bss, - struct wpa_driver_scan_params *params); -static int android_pno_stop(struct i802_bss *bss); -#endif /* ANDROID */ #ifdef HOSTAPD static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx); @@ -338,8 +297,6 @@ static int nl80211_disable_11b_rates(struct wpa_driver_nl80211_data *drv, int ifindex, int disabled); static int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv); -static int wpa_driver_nl80211_authenticate_retry( - struct wpa_driver_nl80211_data *drv); static int is_ap_interface(enum nl80211_iftype nlmode) @@ -403,7 +360,7 @@ static int no_seq_check(struct nl_msg *msg, void *arg) } -static int send_and_recv(struct nl80211_global *global, +static int send_and_recv(struct wpa_driver_nl80211_data *drv, struct nl_handle *nl_handle, struct nl_msg *msg, int (*valid_handler)(struct nl_msg *, void *), void *valid_data) @@ -411,7 +368,9 @@ static int send_and_recv(struct nl80211_global *global, struct nl_cb *cb; int err = -ENOMEM; - cb = nl_cb_clone(global->nl_cb); + u8 *temp = NULL; + + cb = nl_cb_clone(drv->global->nl_cb); if (!cb) goto out; @@ -428,6 +387,8 @@ static int send_and_recv(struct nl80211_global *global, if (valid_handler) nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, valid_handler, valid_data); + temp = (u8*) msg; + temp, 84); while (err > 0) nl_recvmsgs(nl_handle, cb); @@ -438,23 +399,13 @@ static int send_and_recv(struct nl80211_global *global, } -static int send_and_recv_msgs_global(struct nl80211_global *global, - struct nl_msg *msg, - int (*valid_handler)(struct nl_msg *, void *), - void *valid_data) -{ - return send_and_recv(global, global->nl, msg, valid_handler, - valid_data); -} - - static int send_and_recv_msgs(struct wpa_driver_nl80211_data *drv, struct nl_msg *msg, int (*valid_handler)(struct nl_msg *, void *), void *valid_data) { - return send_and_recv(drv->global, drv->global->nl, msg, - valid_handler, valid_data); + return send_and_recv(drv, drv->global->nl.handle, msg, valid_handler, + valid_data); } @@ -495,7 +446,7 @@ static int family_handler(struct nl_msg *msg, void *arg) } -static int nl_get_multicast_id(struct nl80211_global *global, +static int nl_get_multicast_id(struct wpa_driver_nl80211_data *drv, const char *family, const char *group) { struct nl_msg *msg; @@ -505,11 +456,12 @@ static int nl_get_multicast_id(struct nl80211_global *global, msg = nlmsg_alloc(); if (!msg) return -ENOMEM; - genlmsg_put(msg, 0, 0, genl_ctrl_resolve(global->nl, "nlctrl"), + genlmsg_put(msg, 0, 0, + genl_ctrl_resolve(drv->global->nl.handle, "nlctrl"), 0, 0, CTRL_CMD_GETFAMILY, 0); NLA_PUT_STRING(msg, CTRL_ATTR_FAMILY_NAME, family); - ret = send_and_recv_msgs_global(global, msg, family_handler, &res); + ret = send_and_recv_msgs(drv, msg, family_handler, &res); msg = NULL; if (ret == 0) ret = res.id; @@ -523,232 +475,11 @@ nla_put_failure: static void * nl80211_cmd(struct wpa_driver_nl80211_data *drv, struct nl_msg *msg, int flags, uint8_t cmd) { - return genlmsg_put(msg, 0, 0, drv->global->nl80211_id, + return genlmsg_put(msg, 0, 0, genl_family_get_id(drv->global->nl80211), 0, flags, cmd, 0); } -struct wiphy_idx_data { - int wiphy_idx; -}; - - -static int netdev_info_handler(struct nl_msg *msg, void *arg) -{ - struct nlattr *tb[NL80211_ATTR_MAX + 1]; - struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); - struct wiphy_idx_data *info = arg; - - nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), - genlmsg_attrlen(gnlh, 0), NULL); - - if (tb[NL80211_ATTR_WIPHY]) - info->wiphy_idx = nla_get_u32(tb[NL80211_ATTR_WIPHY]); - - return NL_SKIP; -} - - -static int nl80211_get_wiphy_index(struct i802_bss *bss) -{ - struct nl_msg *msg; - struct wiphy_idx_data data = { - .wiphy_idx = -1, - }; - - msg = nlmsg_alloc(); - if (!msg) - return -1; - - nl80211_cmd(bss->drv, msg, 0, NL80211_CMD_GET_INTERFACE); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex); - - if (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data) == 0) - return data.wiphy_idx; - msg = NULL; -nla_put_failure: - nlmsg_free(msg); - return -1; -} - - -static int nl80211_register_beacons(struct wpa_driver_nl80211_data *drv, - struct nl80211_wiphy_data *w) -{ - struct nl_msg *msg; - int ret = -1; - - msg = nlmsg_alloc(); - if (!msg) - return -1; - - nl80211_cmd(drv, msg, 0, NL80211_CMD_REGISTER_BEACONS); - - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, w->wiphy_idx); - - ret = send_and_recv(drv->global, w->nl_beacons, msg, NULL, NULL); - msg = NULL; - if (ret) { - wpa_printf(MSG_DEBUG, "nl80211: Register beacons command " - "failed: ret=%d (%s)", - ret, strerror(-ret)); - goto nla_put_failure; - } - ret = 0; -nla_put_failure: - nlmsg_free(msg); - return ret; -} - - -static void nl80211_recv_beacons(int sock, void *eloop_ctx, void *handle) -{ - struct nl80211_wiphy_data *w = eloop_ctx; - - wpa_printf(MSG_DEBUG, "nl80211: Beacon event message available"); - - nl_recvmsgs(handle, w->nl_cb); -} - - -static int process_beacon_event(struct nl_msg *msg, void *arg) -{ - struct nl80211_wiphy_data *w = arg; - struct wpa_driver_nl80211_data *drv; - struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); - struct nlattr *tb[NL80211_ATTR_MAX + 1]; - union wpa_event_data event; - - nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), - genlmsg_attrlen(gnlh, 0), NULL); - - if (gnlh->cmd != NL80211_CMD_FRAME) { - wpa_printf(MSG_DEBUG, "nl80211: Unexpected beacon event? (%d)", - gnlh->cmd); - return NL_SKIP; - } - - if (!tb[NL80211_ATTR_FRAME]) - return NL_SKIP; - - dl_list_for_each(drv, &w->drvs, struct wpa_driver_nl80211_data, - wiphy_list) { - os_memset(&event, 0, sizeof(event)); - event.rx_mgmt.frame = nla_data(tb[NL80211_ATTR_FRAME]); - event.rx_mgmt.frame_len = nla_len(tb[NL80211_ATTR_FRAME]); - wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event); - } - - return NL_SKIP; -} - - -static struct nl80211_wiphy_data * -nl80211_get_wiphy_data_ap(struct i802_bss *bss) -{ - static DEFINE_DL_LIST(nl80211_wiphys); - struct nl80211_wiphy_data *w; - int wiphy_idx, found = 0; - struct i802_bss *tmp_bss; - - if (bss->wiphy_data != NULL) - return bss->wiphy_data; - - wiphy_idx = nl80211_get_wiphy_index(bss); - - dl_list_for_each(w, &nl80211_wiphys, struct nl80211_wiphy_data, list) { - if (w->wiphy_idx == wiphy_idx) - goto add; - } - - /* alloc new one */ - w = os_zalloc(sizeof(*w)); - if (w == NULL) - return NULL; - w->wiphy_idx = wiphy_idx; - dl_list_init(&w->bsss); - dl_list_init(&w->drvs); - - w->nl_cb = nl_cb_alloc(NL_CB_DEFAULT); - if (!w->nl_cb) { - os_free(w); - return NULL; - } - nl_cb_set(w->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL); - nl_cb_set(w->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, process_beacon_event, - w); - - w->nl_beacons = nl_create_handle(bss->drv->global->nl_cb, - "wiphy beacons"); - if (w->nl_beacons == NULL) { - os_free(w); - return NULL; - } - - if (nl80211_register_beacons(bss->drv, w)) { - nl_destroy_handles(&w->nl_beacons); - os_free(w); - return NULL; - } - - eloop_register_read_sock(nl_socket_get_fd(w->nl_beacons), - nl80211_recv_beacons, w, w->nl_beacons); - - dl_list_add(&nl80211_wiphys, &w->list); - -add: - /* drv entry for this bss already there? */ - dl_list_for_each(tmp_bss, &w->bsss, struct i802_bss, wiphy_list) { - if (tmp_bss->drv == bss->drv) { - found = 1; - break; - } - } - /* if not add it */ - if (!found) - dl_list_add(&w->drvs, &bss->drv->wiphy_list); - - dl_list_add(&w->bsss, &bss->wiphy_list); - bss->wiphy_data = w; - return w; -} - - -static void nl80211_put_wiphy_data_ap(struct i802_bss *bss) -{ - struct nl80211_wiphy_data *w = bss->wiphy_data; - struct i802_bss *tmp_bss; - int found = 0; - - if (w == NULL) - return; - bss->wiphy_data = NULL; - dl_list_del(&bss->wiphy_list); - - /* still any for this drv present? */ - dl_list_for_each(tmp_bss, &w->bsss, struct i802_bss, wiphy_list) { - if (tmp_bss->drv == bss->drv) { - found = 1; - break; - } - } - /* if not remove it */ - if (!found) - dl_list_del(&bss->drv->wiphy_list); - - if (!dl_list_empty(&w->bsss)) - return; - - eloop_unregister_read_sock(nl_socket_get_fd(w->nl_beacons)); - - nl_cb_put(w->nl_cb); - nl_destroy_handles(&w->nl_beacons); - dl_list_del(&w->list); - os_free(w); -} - - static int wpa_driver_nl80211_get_bssid(void *priv, u8 *bssid) { struct i802_bss *bss = priv; @@ -789,10 +520,28 @@ static void wpa_driver_nl80211_event_link(struct wpa_driver_nl80211_data *drv, del ? "removed" : "added"); if (os_strcmp(drv->first_bss.ifname, event.interface_status.ifname) == 0) { - if (del) + if (del) { + if (drv->if_removed) { + wpa_printf(MSG_DEBUG, "nl80211: if_removed " + "already set - ignore event"); + return; + } drv->if_removed = 1; - else + } else { + if (if_nametoindex(drv->first_bss.ifname) == 0) { + wpa_printf(MSG_DEBUG, "nl80211: Interface %s " + "does not exist - ignore " + "RTM_NEWLINK", + drv->first_bss.ifname); + return; + } + if (!drv->if_removed) { + wpa_printf(MSG_DEBUG, "nl80211: if_removed " + "already cleared - ignore event"); + return; + } drv->if_removed = 0; + } } wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event); @@ -909,6 +658,14 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx, wpa_printf(MSG_DEBUG, "nl80211: Ignore interface up " "event since interface %s is down", namebuf); + } else if (if_nametoindex(drv->first_bss.ifname) == 0) { + wpa_printf(MSG_DEBUG, "nl80211: Ignore interface up " + "event since interface %s does not exist", + drv->first_bss.ifname); + } else if (drv->if_removed) { + wpa_printf(MSG_DEBUG, "nl80211: Ignore interface up " + "event since interface %s is marked " + "removed", drv->first_bss.ifname); } else { wpa_printf(MSG_DEBUG, "nl80211: Interface up"); drv->if_disabled = 0; @@ -1235,29 +992,26 @@ static void mlme_event_mgmt(struct wpa_driver_nl80211_data *drv, } -static void mlme_event_mgmt_tx_status(struct wpa_driver_nl80211_data *drv, - struct nlattr *cookie, const u8 *frame, - size_t len, struct nlattr *ack) +static void mlme_event_action_tx_status(struct wpa_driver_nl80211_data *drv, + struct nlattr *cookie, const u8 *frame, + size_t len, struct nlattr *ack) { union wpa_event_data event; const struct ieee80211_hdr *hdr; u16 fc; + u64 cookie_val; - if (!is_ap_interface(drv->nlmode)) { - u64 cookie_val; - - if (!cookie) - return; + if (!cookie) + return; - cookie_val = nla_get_u64(cookie); - wpa_printf(MSG_DEBUG, "nl80211: Action TX status:" - " cookie=0%llx%s (ack=%d)", - (long long unsigned int) cookie_val, - cookie_val == drv->send_action_cookie ? - " (match)" : " (unknown)", ack != NULL); - if (cookie_val != drv->send_action_cookie) - return; - } + cookie_val = nla_get_u64(cookie); + wpa_printf(MSG_DEBUG, "nl80211: Action TX status: cookie=0%llx%s " + "(ack=%d)", + (long long unsigned int) cookie_val, + cookie_val == drv->send_action_cookie ? + " (match)" : " (unknown)", ack != NULL); + if (cookie_val != drv->send_action_cookie) + return; hdr = (const struct ieee80211_hdr *) frame; fc = le_to_host16(hdr->frame_control); @@ -1402,8 +1156,8 @@ static void mlme_event(struct wpa_driver_nl80211_data *drv, mlme_event_mgmt(drv, freq, nla_data(frame), nla_len(frame)); break; case NL80211_CMD_FRAME_TX_STATUS: - mlme_event_mgmt_tx_status(drv, cookie, nla_data(frame), - nla_len(frame), ack); + mlme_event_action_tx_status(drv, cookie, nla_data(frame), + nla_len(frame), ack); break; case NL80211_CMD_UNPROT_DEAUTHENTICATE: mlme_event_unprot_disconnect(drv, EVENT_UNPROT_DEAUTH, @@ -1531,14 +1285,6 @@ static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted, int freqs[MAX_REPORT_FREQS]; int num_freqs = 0; - if (drv->scan_for_auth) { - drv->scan_for_auth = 0; - wpa_printf(MSG_DEBUG, "nl80211: Scan results for missing " - "cfg80211 BSS entry"); - wpa_driver_nl80211_authenticate_retry(drv); - return; - } - os_memset(&event, 0, sizeof(event)); info = &event.scan_info; info->aborted = aborted; @@ -1860,7 +1606,7 @@ static void nl80211_new_station_event(struct wpa_driver_nl80211_data *drv, addr = nla_data(tb[NL80211_ATTR_MAC]); wpa_printf(MSG_DEBUG, "nl80211: New station " MACSTR, MAC2STR(addr)); - if (is_ap_interface(drv->nlmode) && drv->device_ap_sme) { + if (is_ap_interface(drv->nlmode) && drv->no_monitor_iface_capab) { u8 *ies = NULL; size_t ies_len = 0; if (tb[NL80211_ATTR_IE]) { @@ -1893,7 +1639,7 @@ static void nl80211_del_station_event(struct wpa_driver_nl80211_data *drv, wpa_printf(MSG_DEBUG, "nl80211: Delete station " MACSTR, MAC2STR(addr)); - if (is_ap_interface(drv->nlmode) && drv->device_ap_sme) { + if (is_ap_interface(drv->nlmode) && drv->no_monitor_iface_capab) { drv_event_disassoc(drv->ctx, addr); return; } @@ -1983,52 +1729,34 @@ static void nl80211_pmksa_candidate_event(struct wpa_driver_nl80211_data *drv, } -static void nl80211_client_probe_event(struct wpa_driver_nl80211_data *drv, - struct nlattr **tb) +static int process_event(struct nl_msg *msg, void *arg) { - union wpa_event_data data; - - if (!tb[NL80211_ATTR_MAC] || !tb[NL80211_ATTR_ACK]) - return; - - os_memset(&data, 0, sizeof(data)); - os_memcpy(data.client_poll.addr, - nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN); - - wpa_supplicant_event(drv->ctx, EVENT_DRIVER_CLIENT_POLL_OK, &data); -} - - -static void nl80211_spurious_frame(struct i802_bss *bss, struct nlattr **tb, - int wds) -{ - struct wpa_driver_nl80211_data *drv = bss->drv; - union wpa_event_data event; - - if (!tb[NL80211_ATTR_MAC]) - return; - - os_memset(&event, 0, sizeof(event)); - event.rx_from_unknown.bssid = bss->addr; - event.rx_from_unknown.addr = nla_data(tb[NL80211_ATTR_MAC]); - event.rx_from_unknown.wds = wds; + struct wpa_driver_nl80211_data *drv = arg; + struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); + struct nlattr *tb[NL80211_ATTR_MAX + 1]; - wpa_supplicant_event(drv->ctx, EVENT_RX_FROM_UNKNOWN, &event); -} + nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), + genlmsg_attrlen(gnlh, 0), NULL); + if (tb[NL80211_ATTR_IFINDEX]) { + int ifindex = nla_get_u32(tb[NL80211_ATTR_IFINDEX]); + if (ifindex != drv->ifindex && !have_ifidx(drv, ifindex)) { + wpa_printf(MSG_DEBUG, "nl80211: Ignored event (cmd=%d)" + " for foreign interface (ifindex %d)", + gnlh->cmd, ifindex); + return NL_SKIP; + } + } -static void do_process_drv_event(struct wpa_driver_nl80211_data *drv, - int cmd, struct nlattr **tb) -{ if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED && - (cmd == NL80211_CMD_NEW_SCAN_RESULTS || - cmd == NL80211_CMD_SCAN_ABORTED)) { + (gnlh->cmd == NL80211_CMD_NEW_SCAN_RESULTS || + gnlh->cmd == NL80211_CMD_SCAN_ABORTED)) { wpa_driver_nl80211_set_mode(&drv->first_bss, drv->ap_scan_as_station); drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED; } - switch (cmd) { + switch (gnlh->cmd) { case NL80211_CMD_TRIGGER_SCAN: wpa_printf(MSG_DEBUG, "nl80211: Scan trigger"); break; @@ -2065,17 +1793,18 @@ static void do_process_drv_event(struct wpa_driver_nl80211_data *drv, case NL80211_CMD_ASSOCIATE: case NL80211_CMD_DEAUTHENTICATE: case NL80211_CMD_DISASSOCIATE: + case NL80211_CMD_FRAME: case NL80211_CMD_FRAME_TX_STATUS: case NL80211_CMD_UNPROT_DEAUTHENTICATE: case NL80211_CMD_UNPROT_DISASSOCIATE: - mlme_event(drv, cmd, tb[NL80211_ATTR_FRAME], + mlme_event(drv, gnlh->cmd, tb[NL80211_ATTR_FRAME], tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT], tb[NL80211_ATTR_WIPHY_FREQ], tb[NL80211_ATTR_ACK], tb[NL80211_ATTR_COOKIE]); break; case NL80211_CMD_CONNECT: case NL80211_CMD_ROAM: - mlme_event_connect(drv, cmd, + mlme_event_connect(drv, gnlh->cmd, tb[NL80211_ATTR_STATUS_CODE], tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_REQ_IE], @@ -2122,89 +1851,6 @@ static void do_process_drv_event(struct wpa_driver_nl80211_data *drv, case NL80211_CMD_PMKSA_CANDIDATE: nl80211_pmksa_candidate_event(drv, tb); break; - case NL80211_CMD_PROBE_CLIENT: - nl80211_client_probe_event(drv, tb); - break; - default: - wpa_printf(MSG_DEBUG, "nl80211: Ignored unknown event " - "(cmd=%d)", cmd); - break; - } -} - - -static int process_drv_event(struct nl_msg *msg, void *arg) -{ - struct wpa_driver_nl80211_data *drv = arg; - struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); - struct nlattr *tb[NL80211_ATTR_MAX + 1]; - - nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), - genlmsg_attrlen(gnlh, 0), NULL); - - if (tb[NL80211_ATTR_IFINDEX]) { - int ifindex = nla_get_u32(tb[NL80211_ATTR_IFINDEX]); - if (ifindex != drv->ifindex && !have_ifidx(drv, ifindex)) { - wpa_printf(MSG_DEBUG, "nl80211: Ignored event (cmd=%d)" - " for foreign interface (ifindex %d)", - gnlh->cmd, ifindex); - return NL_SKIP; - } - } - - do_process_drv_event(drv, gnlh->cmd, tb); - return NL_SKIP; -} - - -static int process_global_event(struct nl_msg *msg, void *arg) -{ - struct nl80211_global *global = arg; - struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); - struct nlattr *tb[NL80211_ATTR_MAX + 1]; - struct wpa_driver_nl80211_data *drv; - int ifidx = -1; - - nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), - genlmsg_attrlen(gnlh, 0), NULL); - - if (tb[NL80211_ATTR_IFINDEX]) - ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]); - - dl_list_for_each(drv, &global->interfaces, - struct wpa_driver_nl80211_data, list) { - if (ifidx == -1 || ifidx == drv->ifindex || - have_ifidx(drv, ifidx)) - do_process_drv_event(drv, gnlh->cmd, tb); - } - - return NL_SKIP; -} - - -static int process_bss_event(struct nl_msg *msg, void *arg) -{ - struct i802_bss *bss = arg; - struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); - struct nlattr *tb[NL80211_ATTR_MAX + 1]; - - nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), - genlmsg_attrlen(gnlh, 0), NULL); - - switch (gnlh->cmd) { - case NL80211_CMD_FRAME: - case NL80211_CMD_FRAME_TX_STATUS: - mlme_event(bss->drv, gnlh->cmd, tb[NL80211_ATTR_FRAME], - tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT], - tb[NL80211_ATTR_WIPHY_FREQ], tb[NL80211_ATTR_ACK], - tb[NL80211_ATTR_COOKIE]); - break; - case NL80211_CMD_UNEXPECTED_FRAME: - nl80211_spurious_frame(bss, tb, 0); - break; - case NL80211_CMD_UNEXPECTED_4ADDR_FRAME: - nl80211_spurious_frame(bss, tb, 1); - break; default: wpa_printf(MSG_DEBUG, "nl80211: Ignored unknown event " "(cmd=%d)", gnlh->cmd); @@ -2218,11 +1864,18 @@ static int process_bss_event(struct nl_msg *msg, void *arg) static void wpa_driver_nl80211_event_receive(int sock, void *eloop_ctx, void *handle) { - struct nl_cb *cb = eloop_ctx; + struct nl_cb *cb; + struct wpa_driver_nl80211_data *drv = eloop_ctx; wpa_printf(MSG_DEBUG, "nl80211: Event message available"); + cb = nl_cb_clone(drv->global->nl_cb); + if (!cb) + return; + nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL); + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, process_event, drv); nl_recvmsgs(handle, cb); + nl_cb_put(cb); } @@ -2266,29 +1919,9 @@ struct wiphy_info_data { struct wpa_driver_capa *capa; unsigned int error:1; - unsigned int device_ap_sme:1; - unsigned int poll_command_supported:1; - unsigned int data_tx_status:1; }; -static unsigned int probe_resp_offload_support(int supp_protocols) -{ - unsigned int prot = 0; - - if (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS) - prot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS; - if (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2) - prot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS2; - if (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P) - prot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_P2P; - if (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U) - prot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_INTERWORKING; - - return prot; -} - - static int wiphy_info_handler(struct nl_msg *msg, void *arg) { struct nlattr *tb[NL80211_ATTR_MAX + 1]; @@ -2415,10 +2048,12 @@ broken_combination: connect_supported = 1; break; case NL80211_CMD_START_SCHED_SCAN: + /* + * Disabled for 1.x for now as it is + * broken there due to the way it ends + * up getting used. capa->sched_scan_supported = 1; - break; - case NL80211_CMD_PROBE_CLIENT: - info->poll_command_supported = 1; + */ break; } } @@ -2438,9 +2073,6 @@ broken_combination: /* default to 5000 since early versions of mac80211 don't set it */ capa->max_remain_on_chan = 5000; - if (tb[NL80211_ATTR_SUPPORT_AP_UAPSD]) - capa->flags |= WPA_DRIVER_FLAGS_AP_UAPSD; - if (tb[NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION]) capa->max_remain_on_chan = nla_get_u32(tb[NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION]); @@ -2473,26 +2105,6 @@ broken_combination: } } - if (tb[NL80211_ATTR_DEVICE_AP_SME]) - info->device_ap_sme = 1; - - if (tb[NL80211_ATTR_FEATURE_FLAGS]) { - u32 flags = nla_get_u32(tb[NL80211_ATTR_FEATURE_FLAGS]); - - if (flags & NL80211_FEATURE_SK_TX_STATUS) - info->data_tx_status = 1; - } - - if (tb[NL80211_ATTR_PROBE_RESP_OFFLOAD]) { - int protocols = - nla_get_u32(tb[NL80211_ATTR_PROBE_RESP_OFFLOAD]); - wpa_printf(MSG_DEBUG, "nl80211: Supports Probe Response " - "offload in AP mode"); - capa->flags |= WPA_DRIVER_FLAGS_PROBE_RESP_OFFLOAD; - capa->probe_resp_offloads = - probe_resp_offload_support(protocols); - } - return NL_SKIP; } @@ -2550,32 +2162,48 @@ static int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv) drv->capa.flags |= WPA_DRIVER_FLAGS_EAPOL_TX_STATUS; drv->capa.flags |= WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS; - drv->device_ap_sme = info.device_ap_sme; - drv->poll_command_supported = info.poll_command_supported; - drv->data_tx_status = info.data_tx_status; + return 0; +} + +#ifdef ANDROID +static int android_genl_ctrl_resolve(struct nl_handle *handle, + const char *name) +{ /* - * If poll command is supported mac80211 is new enough to - * have everything we need to not need monitor interfaces. + * Android ICS has very minimal genl_ctrl_resolve() implementation, so + * need to work around that. */ - drv->use_monitor = !info.poll_command_supported; + struct nl_cache *cache = NULL; + struct genl_family *nl80211 = NULL; + int id = -1; - /* - * If we aren't going to use monitor interfaces, but the - * driver doesn't support data TX status, we won't get TX - * status for EAPOL frames. - */ - if (!drv->use_monitor && !info.data_tx_status) - drv->capa.flags &= ~WPA_DRIVER_FLAGS_EAPOL_TX_STATUS; + if (genl_ctrl_alloc_cache(handle, &cache) < 0) { + wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic " + "netlink cache"); + goto fail; + } - return 0; + nl80211 = genl_ctrl_search_by_name(cache, name); + if (nl80211 == NULL) + goto fail; + + id = genl_family_get_id(nl80211); + +fail: + if (nl80211) + genl_family_put(nl80211); + if (cache) + nl_cache_free(cache); + + return id; } +#define genl_ctrl_resolve android_genl_ctrl_resolve +#endif /* ANDROID */ static int wpa_driver_nl80211_init_nl_global(struct nl80211_global *global) { - int ret; - global->nl_cb = nl_cb_alloc(NL_CB_DEFAULT); if (global->nl_cb == NULL) { wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink " @@ -2583,44 +2211,54 @@ static int wpa_driver_nl80211_init_nl_global(struct nl80211_global *global) return -1; } - global->nl = nl_create_handle(global->nl_cb, "nl"); - if (global->nl == NULL) - goto err; + if (nl_create_handles(&global->nl, global->nl_cb, "nl")) + return -1; - global->nl80211_id = genl_ctrl_resolve(global->nl, "nl80211"); - if (global->nl80211_id < 0) { + global->nl80211 = genl_ctrl_search_by_name(global->nl.cache, + "nl80211"); + if (global->nl80211 == NULL) { wpa_printf(MSG_ERROR, "nl80211: 'nl80211' generic netlink not " "found"); - goto err; + return -1; } - global->nl_event = nl_create_handle(global->nl_cb, "event"); - if (global->nl_event == NULL) - goto err; + return 0; +} + + +static int wpa_driver_nl80211_init_nl(struct wpa_driver_nl80211_data *drv) +{ + struct nl80211_global *global = drv->global; + int ret; + + /* Initialize generic netlink and nl80211 */ - ret = nl_get_multicast_id(global, "nl80211", "scan"); + if (nl_create_handles(&drv->nl_event, global->nl_cb, "event")) + goto err3; + + ret = nl_get_multicast_id(drv, "nl80211", "scan"); if (ret >= 0) - ret = nl_socket_add_membership(global->nl_event, ret); + ret = nl_socket_add_membership(drv->nl_event.handle, ret); if (ret < 0) { wpa_printf(MSG_ERROR, "nl80211: Could not add multicast " "membership for scan events: %d (%s)", ret, strerror(-ret)); - goto err; + goto err4; } - ret = nl_get_multicast_id(global, "nl80211", "mlme"); + ret = nl_get_multicast_id(drv, "nl80211", "mlme"); if (ret >= 0) - ret = nl_socket_add_membership(global->nl_event, ret); + ret = nl_socket_add_membership(drv->nl_event.handle, ret); if (ret < 0) { wpa_printf(MSG_ERROR, "nl80211: Could not add multicast " "membership for mlme events: %d (%s)", ret, strerror(-ret)); - goto err; + goto err4; } - ret = nl_get_multicast_id(global, "nl80211", "regulatory"); + ret = nl_get_multicast_id(drv, "nl80211", "regulatory"); if (ret >= 0) - ret = nl_socket_add_membership(global->nl_event, ret); + ret = nl_socket_add_membership(drv->nl_event.handle, ret); if (ret < 0) { wpa_printf(MSG_DEBUG, "nl80211: Could not add multicast " "membership for regulatory events: %d (%s)", @@ -2628,43 +2266,19 @@ static int wpa_driver_nl80211_init_nl_global(struct nl80211_global *global) /* Continue without regulatory events */ } - nl_cb_set(global->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, - no_seq_check, NULL); - nl_cb_set(global->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, - process_global_event, global); - - eloop_register_read_sock(nl_socket_get_fd(global->nl_event), - wpa_driver_nl80211_event_receive, - global->nl_cb, global->nl_event); + eloop_register_read_sock(nl_socket_get_fd(drv->nl_event.handle), + wpa_driver_nl80211_event_receive, drv, + drv->nl_event.handle); return 0; -err: - nl_destroy_handles(&global->nl_event); - nl_destroy_handles(&global->nl); - nl_cb_put(global->nl_cb); - global->nl_cb = NULL; +err4: + nl_destroy_handles(&drv->nl_event); +err3: return -1; } -static int wpa_driver_nl80211_init_nl(struct wpa_driver_nl80211_data *drv) -{ - drv->nl_cb = nl_cb_alloc(NL_CB_DEFAULT); - if (!drv->nl_cb) { - wpa_printf(MSG_ERROR, "nl80211: Failed to alloc cb struct"); - return -1; - } - - nl_cb_set(drv->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, - no_seq_check, NULL); - nl_cb_set(drv->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, - process_drv_event, drv); - - return 0; -} - - static void wpa_driver_nl80211_rfkill_blocked(void *ctx) { wpa_printf(MSG_DEBUG, "nl80211: RFKILL blocked"); @@ -2722,88 +2336,14 @@ static void nl80211_get_phy_name(struct wpa_driver_nl80211_data *drv) } -static void wpa_driver_nl80211_handle_eapol_tx_status(int sock, - void *eloop_ctx, - void *handle) -{ - struct wpa_driver_nl80211_data *drv = eloop_ctx; - u8 data[2048]; - struct msghdr msg; - struct iovec entry; - struct { - struct cmsghdr cm; - char control[512]; - } control; - struct cmsghdr *cmsg; - int res, found_ee = 0, found_wifi = 0, acked = 0; - union wpa_event_data event; - - memset(&msg, 0, sizeof(msg)); - msg.msg_iov = &entry; - msg.msg_iovlen = 1; - entry.iov_base = data; - entry.iov_len = sizeof(data); - msg.msg_control = &control; - msg.msg_controllen = sizeof(control); - - res = recvmsg(sock, &msg, MSG_ERRQUEUE); - /* if error or not fitting 802.3 header, return */ - if (res < 14) - return; - - for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) - { - if (cmsg->cmsg_level == SOL_SOCKET && - cmsg->cmsg_type == SCM_WIFI_STATUS) { - int *ack; - - found_wifi = 1; - ack = (void *)CMSG_DATA(cmsg); - acked = *ack; - } - - if (cmsg->cmsg_level == SOL_PACKET && - cmsg->cmsg_type == PACKET_TX_TIMESTAMP) { - struct sock_extended_err *err = - (struct sock_extended_err *)CMSG_DATA(cmsg); - - if (err->ee_origin == SO_EE_ORIGIN_TXSTATUS) - found_ee = 1; - } - } - - if (!found_ee || !found_wifi) - return; - - memset(&event, 0, sizeof(event)); - event.eapol_tx_status.dst = data; - event.eapol_tx_status.data = data + 14; - event.eapol_tx_status.data_len = res - 14; - event.eapol_tx_status.ack = acked; - wpa_supplicant_event(drv->ctx, EVENT_EAPOL_TX_STATUS, &event); -} - - -static int nl80211_init_bss(struct i802_bss *bss) -{ - bss->nl_cb = nl_cb_alloc(NL_CB_DEFAULT); - if (!bss->nl_cb) - return -1; - - nl_cb_set(bss->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, - no_seq_check, NULL); - nl_cb_set(bss->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, - process_bss_event, bss); - - return 0; -} - - -static void nl80211_destroy_bss(struct i802_bss *bss) +#ifdef CONFIG_AP +static void nl80211_l2_read(void *ctx, const u8 *src_addr, const u8 *buf, + size_t len) { - nl_cb_put(bss->nl_cb); - bss->nl_cb = NULL; + wpa_printf(MSG_DEBUG, "nl80211: l2_packet read %u", + (unsigned int) len); } +#endif /* CONFIG_AP */ /** @@ -2833,7 +2373,6 @@ static void * wpa_driver_nl80211_init(void *ctx, const char *ifname, os_strlcpy(bss->ifname, ifname, sizeof(bss->ifname)); drv->monitor_ifidx = -1; drv->monitor_sock = -1; - drv->eapol_tx_sock = -1; drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED; if (wpa_driver_nl80211_init_nl(drv)) { @@ -2841,9 +2380,6 @@ static void * wpa_driver_nl80211_init(void *ctx, const char *ifname, return NULL; } - if (nl80211_init_bss(bss)) - goto failed; - nl80211_get_phy_name(drv); rcfg = os_zalloc(sizeof(*rcfg)); @@ -2862,27 +2398,10 @@ static void * wpa_driver_nl80211_init(void *ctx, const char *ifname, if (wpa_driver_nl80211_finish_drv_init(drv)) goto failed; - drv->eapol_tx_sock = socket(PF_PACKET, SOCK_DGRAM, 0); - if (drv->eapol_tx_sock < 0) - goto failed; - - if (drv->data_tx_status) { - int enabled = 1; - - if (setsockopt(drv->eapol_tx_sock, SOL_SOCKET, SO_WIFI_STATUS, - &enabled, sizeof(enabled)) < 0) { - wpa_printf(MSG_DEBUG, - "nl80211: wifi status sockopt failed\n"); - drv->data_tx_status = 0; - if (!drv->use_monitor) - drv->capa.flags &= - ~WPA_DRIVER_FLAGS_EAPOL_TX_STATUS; - } else { - eloop_register_read_sock(drv->eapol_tx_sock, - wpa_driver_nl80211_handle_eapol_tx_status, - drv, NULL); - } - } +#ifdef CONFIG_AP + drv->l2 = l2_packet_init(ifname, NULL, ETH_P_EAPOL, + nl80211_l2_read, drv, 0); +#endif /* CONFIG_AP */ if (drv->global) { dl_list_add(&drv->global->interfaces, &drv->list); @@ -2897,11 +2416,10 @@ failed: } -static int nl80211_register_frame(struct i802_bss *bss, +static int nl80211_register_frame(struct wpa_driver_nl80211_data *drv, struct nl_handle *nl_handle, u16 type, const u8 *match, size_t match_len) { - struct wpa_driver_nl80211_data *drv = bss->drv; struct nl_msg *msg; int ret = -1; @@ -2911,11 +2429,11 @@ static int nl80211_register_frame(struct i802_bss *bss, nl80211_cmd(drv, msg, 0, NL80211_CMD_REGISTER_ACTION); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex); + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); NLA_PUT_U16(msg, NL80211_ATTR_FRAME_TYPE, type); NLA_PUT(msg, NL80211_ATTR_FRAME_MATCH, match_len, match); - ret = send_and_recv(drv->global, nl_handle, msg, NULL, NULL); + ret = send_and_recv(drv, nl_handle, msg, NULL, NULL); msg = NULL; if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Register frame command " @@ -2932,182 +2450,69 @@ nla_put_failure: } -static int nl80211_alloc_mgmt_handle(struct i802_bss *bss) -{ - struct wpa_driver_nl80211_data *drv = bss->drv; - - if (bss->nl_mgmt) { - wpa_printf(MSG_DEBUG, "nl80211: Mgmt reporting " - "already on!"); - return -1; - } - - bss->nl_mgmt = nl_create_handle(drv->nl_cb, "mgmt"); - if (bss->nl_mgmt == NULL) - return -1; - - eloop_register_read_sock(nl_socket_get_fd(bss->nl_mgmt), - wpa_driver_nl80211_event_receive, bss->nl_cb, - bss->nl_mgmt); - - return 0; -} - - -static int nl80211_register_action_frame(struct i802_bss *bss, +static int nl80211_register_action_frame(struct wpa_driver_nl80211_data *drv, const u8 *match, size_t match_len) { u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_ACTION << 4); - return nl80211_register_frame(bss, bss->nl_mgmt, + return nl80211_register_frame(drv, drv->nl_event.handle, type, match, match_len); } -static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss) +static int nl80211_register_action_frames(struct wpa_driver_nl80211_data *drv) { - struct wpa_driver_nl80211_data *drv = bss->drv; - - if (nl80211_alloc_mgmt_handle(bss)) - return -1; - #if defined(CONFIG_P2P) || defined(CONFIG_INTERWORKING) /* GAS Initial Request */ - if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0a", 2) < 0) + if (nl80211_register_action_frame(drv, (u8 *) "\x04\x0a", 2) < 0) return -1; /* GAS Initial Response */ - if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0b", 2) < 0) + if (nl80211_register_action_frame(drv, (u8 *) "\x04\x0b", 2) < 0) return -1; /* GAS Comeback Request */ - if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0c", 2) < 0) + if (nl80211_register_action_frame(drv, (u8 *) "\x04\x0c", 2) < 0) return -1; /* GAS Comeback Response */ - if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0d", 2) < 0) + if (nl80211_register_action_frame(drv, (u8 *) "\x04\x0d", 2) < 0) return -1; #endif /* CONFIG_P2P || CONFIG_INTERWORKING */ #ifdef CONFIG_P2P /* P2P Public Action */ - if (nl80211_register_action_frame(bss, + if (nl80211_register_action_frame(drv, (u8 *) "\x04\x09\x50\x6f\x9a\x09", 6) < 0) return -1; /* P2P Action */ - if (nl80211_register_action_frame(bss, + if (nl80211_register_action_frame(drv, (u8 *) "\x7f\x50\x6f\x9a\x09", 5) < 0) return -1; #endif /* CONFIG_P2P */ #ifdef CONFIG_IEEE80211W /* SA Query Response */ - if (nl80211_register_action_frame(bss, (u8 *) "\x08\x01", 2) < 0) + if (nl80211_register_action_frame(drv, (u8 *) "\x08\x01", 2) < 0) return -1; #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_TDLS if ((drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT)) { /* TDLS Discovery Response */ - if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0e", 2) < + if (nl80211_register_action_frame(drv, (u8 *) "\x04\x0e", 2) < 0) return -1; } #endif /* CONFIG_TDLS */ /* FT Action frames */ - if (nl80211_register_action_frame(bss, (u8 *) "\x06", 1) < 0) + if (nl80211_register_action_frame(drv, (u8 *) "\x06", 1) < 0) return -1; else drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT | WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK; /* WNM - BSS Transition Management Request */ - if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x07", 2) < 0) - return -1; - - return 0; -} - - -static int nl80211_register_spurious_class3(struct i802_bss *bss) -{ - struct wpa_driver_nl80211_data *drv = bss->drv; - struct nl_msg *msg; - int ret = -1; - - msg = nlmsg_alloc(); - if (!msg) - return -1; - - nl80211_cmd(drv, msg, 0, NL80211_CMD_UNEXPECTED_FRAME); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex); - - ret = send_and_recv(drv->global, bss->nl_mgmt, msg, NULL, NULL); - msg = NULL; - if (ret) { - wpa_printf(MSG_DEBUG, "nl80211: Register spurious class3 " - "failed: ret=%d (%s)", - ret, strerror(-ret)); - goto nla_put_failure; - } - ret = 0; -nla_put_failure: - nlmsg_free(msg); - return ret; -} - - -static int nl80211_mgmt_subscribe_ap(struct i802_bss *bss) -{ - static const int stypes[] = { - WLAN_FC_STYPE_AUTH, - WLAN_FC_STYPE_ASSOC_REQ, - WLAN_FC_STYPE_REASSOC_REQ, - WLAN_FC_STYPE_DISASSOC, - WLAN_FC_STYPE_DEAUTH, - WLAN_FC_STYPE_ACTION, - WLAN_FC_STYPE_PROBE_REQ, -/* Beacon doesn't work as mac80211 doesn't currently allow - * it, but it wouldn't really be the right thing anyway as - * it isn't per interface ... maybe just dump the scan - * results periodically for OLBC? - */ -// WLAN_FC_STYPE_BEACON, - }; - unsigned int i; - - if (nl80211_alloc_mgmt_handle(bss)) + if (nl80211_register_action_frame(drv, (u8 *) "\x0a\x07", 2) < 0) return -1; - for (i = 0; i < sizeof(stypes) / sizeof(stypes[0]); i++) { - if (nl80211_register_frame(bss, bss->nl_mgmt, - (WLAN_FC_TYPE_MGMT << 2) | - (stypes[i] << 4), - NULL, 0) < 0) { - goto out_err; - } - } - - if (nl80211_register_spurious_class3(bss)) - goto out_err; - - if (nl80211_get_wiphy_data_ap(bss) == NULL) - goto out_err; - return 0; - -out_err: - eloop_unregister_read_sock(nl_socket_get_fd(bss->nl_mgmt)); - nl_destroy_handles(&bss->nl_mgmt); - return -1; -} - - -static void nl80211_mgmt_unsubscribe(struct i802_bss *bss) -{ - if (bss->nl_mgmt == NULL) - return; - eloop_unregister_read_sock(nl_socket_get_fd(bss->nl_mgmt)); - nl_destroy_handles(&bss->nl_mgmt); - - nl80211_put_wiphy_data_ap(bss); } @@ -3161,9 +2566,19 @@ wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv) return -1; if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname, - bss->addr)) + drv->addr)) return -1; + if (nl80211_register_action_frames(drv) < 0) { + wpa_printf(MSG_DEBUG, "nl80211: Failed to register Action " + "frame processing - ignore for now"); + /* + * Older kernel versions did not support this, so ignore the + * error for now. Some functionality may not be available + * because of this. + */ + } + if (send_rfkill_event) { eloop_register_timeout(0, 0, wpa_driver_nl80211_send_rfkill, drv, drv->ctx); @@ -3203,12 +2618,12 @@ static void wpa_driver_nl80211_deinit(void *priv) struct i802_bss *bss = priv; struct wpa_driver_nl80211_data *drv = bss->drv; - if (drv->data_tx_status) - eloop_unregister_read_sock(drv->eapol_tx_sock); - if (drv->eapol_tx_sock >= 0) - close(drv->eapol_tx_sock); +#ifdef CONFIG_AP + if (drv->l2) + l2_packet_deinit(drv->l2); +#endif /* CONFIG_AP */ - if (bss->nl_preq) + if (drv->nl_preq.handle) wpa_driver_nl80211_probe_req_report(bss, 0); if (bss->added_if_into_bridge) { if (linux_br_del_if(drv->global->ioctl_sock, bss->brname, @@ -3258,16 +2673,12 @@ static void wpa_driver_nl80211_deinit(void *priv) (void) linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0); wpa_driver_nl80211_set_mode(bss, NL80211_IFTYPE_STATION); - nl80211_mgmt_unsubscribe(bss); - - nl_cb_put(drv->nl_cb); - nl80211_destroy_bss(&drv->first_bss); + eloop_unregister_read_sock(nl_socket_get_fd(drv->nl_event.handle)); + nl_destroy_handles(&drv->nl_event); os_free(drv->filter_ssids); - os_free(drv->auth_ie); - if (drv->in_interface_list) dl_list_del(&drv->list); @@ -3311,8 +2722,6 @@ static int wpa_driver_nl80211_scan(void *priv, struct nl_msg *msg, *ssids, *freqs, *rates; size_t i; - drv->scan_for_auth = 0; - msg = nlmsg_alloc(); ssids = nlmsg_alloc(); freqs = nlmsg_alloc(); @@ -3345,8 +2754,8 @@ static int wpa_driver_nl80211_scan(void *priv, nla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS, ssids); if (params->extra_ies) { - wpa_hexdump(MSG_MSGDUMP, "nl80211: Scan extra IEs", - params->extra_ies, params->extra_ies_len); + wpa_hexdump_ascii(MSG_MSGDUMP, "nl80211: Scan extra IEs", + params->extra_ies, params->extra_ies_len); NLA_PUT(msg, NL80211_ATTR_IE, params->extra_ies_len, params->extra_ies); } @@ -3369,6 +2778,7 @@ static int wpa_driver_nl80211_scan(void *priv, */ NLA_PUT(rates, NL80211_BAND_2GHZ, 8, "\x0c\x12\x18\x24\x30\x48\x60\x6c"); + nla_put_nested(msg, NL80211_ATTR_SCAN_SUPP_RATES, rates); NLA_PUT_FLAG(msg, NL80211_ATTR_TX_NO_CCK_RATE); @@ -3423,7 +2833,8 @@ static int wpa_driver_nl80211_scan(void *priv, nla_put_failure: nlmsg_free(ssids); - nlmsg_free(msg); + if(msg) + nlmsg_free(msg); nlmsg_free(freqs); nlmsg_free(rates); return ret; @@ -3447,11 +2858,6 @@ static int wpa_driver_nl80211_sched_scan(void *priv, struct nl_msg *msg, *ssids, *freqs, *match_set_ssid, *match_sets; size_t i; -#ifdef ANDROID - if (!drv->capa.sched_scan_supported) - return android_pno_start(bss, params); -#endif /* ANDROID */ - msg = nlmsg_alloc(); ssids = nlmsg_alloc(); freqs = nlmsg_alloc(); @@ -3473,8 +2879,7 @@ static int wpa_driver_nl80211_sched_scan(void *priv, NLA_PUT_U32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL, interval); - if (drv->num_filter_ssids && - (int) drv->num_filter_ssids <= drv->capa.max_match_sets) { + if (drv->num_filter_ssids) { match_sets = nlmsg_alloc(); for (i = 0; i < drv->num_filter_ssids; i++) { @@ -3559,11 +2964,6 @@ static int wpa_driver_nl80211_stop_sched_scan(void *priv) int ret = 0; struct nl_msg *msg; -#ifdef ANDROID - if (!drv->capa.sched_scan_supported) - return android_pno_stop(bss); -#endif /* ANDROID */ - msg = nlmsg_alloc(); if (!msg) return -1; @@ -4239,9 +3639,8 @@ static int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv, ret = send_and_recv_msgs(drv, msg, NULL, NULL); msg = NULL; if (ret) { - wpa_dbg(drv->ctx, MSG_DEBUG, - "nl80211: MLME command failed: reason=%u ret=%d (%s)", - reason_code, ret, strerror(-ret)); + wpa_printf(MSG_DEBUG, "nl80211: MLME command failed: ret=%d " + "(%s)", ret, strerror(-ret)); goto nla_put_failure; } ret = 0; @@ -4294,52 +3693,6 @@ static int wpa_driver_nl80211_disassociate(void *priv, const u8 *addr, } -static void nl80211_copy_auth_params(struct wpa_driver_nl80211_data *drv, - struct wpa_driver_auth_params *params) -{ - int i; - - drv->auth_freq = params->freq; - drv->auth_alg = params->auth_alg; - drv->auth_wep_tx_keyidx = params->wep_tx_keyidx; - drv->auth_local_state_change = params->local_state_change; - drv->auth_p2p = params->p2p; - - if (params->bssid) - os_memcpy(drv->auth_bssid_, params->bssid, ETH_ALEN); - else - os_memset(drv->auth_bssid_, 0, ETH_ALEN); - - if (params->ssid) { - os_memcpy(drv->auth_ssid, params->ssid, params->ssid_len); - drv->auth_ssid_len = params->ssid_len; - } else - drv->auth_ssid_len = 0; - - - os_free(drv->auth_ie); - drv->auth_ie = NULL; - drv->auth_ie_len = 0; - if (params->ie) { - drv->auth_ie = os_malloc(params->ie_len); - if (drv->auth_ie) { - os_memcpy(drv->auth_ie, params->ie, params->ie_len); - drv->auth_ie_len = params->ie_len; - } - } - - for (i = 0; i < 4; i++) { - if (params->wep_key[i] && params->wep_key_len[i] && - params->wep_key_len[i] <= 16) { - os_memcpy(drv->auth_wep_key[i], params->wep_key[i], - params->wep_key_len[i]); - drv->auth_wep_key_len[i] = params->wep_key_len[i]; - } else - drv->auth_wep_key_len[i] = 0; - } -} - - static int wpa_driver_nl80211_authenticate( void *priv, struct wpa_driver_auth_params *params) { @@ -4350,10 +3703,6 @@ static int wpa_driver_nl80211_authenticate( enum nl80211_auth_type type; enum nl80211_iftype nlmode; int count = 0; - int is_retry; - - is_retry = drv->retry_auth; - drv->retry_auth = 0; drv->associated = 0; os_memset(drv->auth_bssid, 0, ETH_ALEN); @@ -4430,9 +3779,8 @@ retry: ret = send_and_recv_msgs(drv, msg, NULL, NULL); msg = NULL; if (ret) { - wpa_dbg(drv->ctx, MSG_DEBUG, - "nl80211: MLME command failed (auth): ret=%d (%s)", - ret, strerror(-ret)); + wpa_printf(MSG_DEBUG, "nl80211: MLME command failed: ret=%d " + "(%s)", ret, strerror(-ret)); count++; if (ret == -EALREADY && count == 1 && params->bssid && !params->local_state_change) { @@ -4449,49 +3797,6 @@ retry: nlmsg_free(msg); goto retry; } - - if (ret == -ENOENT && params->freq && !is_retry) { - /* - * cfg80211 has likely expired the BSS entry even - * though it was previously available in our internal - * BSS table. To recover quickly, start a single - * channel scan on the specified channel. - */ - struct wpa_driver_scan_params scan; - int freqs[2]; - - os_memset(&scan, 0, sizeof(scan)); - scan.num_ssids = 1; - if (params->ssid) { - scan.ssids[0].ssid = params->ssid; - scan.ssids[0].ssid_len = params->ssid_len; - } - freqs[0] = params->freq; - freqs[1] = 0; - scan.freqs = freqs; - wpa_printf(MSG_DEBUG, "nl80211: Trigger single " - "channel scan to refresh cfg80211 BSS " - "entry"); - ret = wpa_driver_nl80211_scan(bss, &scan); - if (ret == 0) { - nl80211_copy_auth_params(drv, params); - drv->scan_for_auth = 1; - } - } else if (is_retry) { - /* - * Need to indicate this with an event since the return - * value from the retry is not delivered to core code. - */ - union wpa_event_data event; - wpa_printf(MSG_DEBUG, "nl80211: Authentication retry " - "failed"); - os_memset(&event, 0, sizeof(event)); - os_memcpy(event.timeout_event.addr, drv->auth_bssid_, - ETH_ALEN); - wpa_supplicant_event(drv->ctx, EVENT_AUTH_TIMED_OUT, - &event); - } - goto nla_put_failure; } ret = 0; @@ -4504,45 +3809,6 @@ nla_put_failure: } -static int wpa_driver_nl80211_authenticate_retry( - struct wpa_driver_nl80211_data *drv) -{ - struct wpa_driver_auth_params params; - struct i802_bss *bss = &drv->first_bss; - int i; - - wpa_printf(MSG_DEBUG, "nl80211: Try to authenticate again"); - - os_memset(¶ms, 0, sizeof(params)); - params.freq = drv->auth_freq; - params.auth_alg = drv->auth_alg; - params.wep_tx_keyidx = drv->auth_wep_tx_keyidx; - params.local_state_change = drv->auth_local_state_change; - params.p2p = drv->auth_p2p; - - if (!is_zero_ether_addr(drv->auth_bssid_)) - params.bssid = drv->auth_bssid_; - - if (drv->auth_ssid_len) { - params.ssid = drv->auth_ssid; - params.ssid_len = drv->auth_ssid_len; - } - - params.ie = drv->auth_ie; - params.ie_len = drv->auth_ie_len; - - for (i = 0; i < 4; i++) { - if (drv->auth_wep_key_len[i]) { - params.wep_key[i] = drv->auth_wep_key[i]; - params.wep_key_len[i] = drv->auth_wep_key_len[i]; - } - } - - drv->retry_auth = 1; - return wpa_driver_nl80211_authenticate(bss, ¶ms); -} - - struct phy_info_arg { u16 *num_modes; struct hostapd_hw_modes *modes; @@ -4974,9 +4240,9 @@ wpa_driver_nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags) } -static int wpa_driver_nl80211_send_mntr(struct wpa_driver_nl80211_data *drv, - const void *data, size_t len, - int encrypt, int noack) +static int wpa_driver_nl80211_send_frame(struct wpa_driver_nl80211_data *drv, + const void *data, size_t len, + int encrypt) { __u8 rtap_hdr[] = { 0x00, 0x00, /* radiotap version */ @@ -5007,7 +4273,6 @@ static int wpa_driver_nl80211_send_mntr(struct wpa_driver_nl80211_data *drv, .msg_flags = 0, }; int res; - u16 txflags = 0; if (encrypt) rtap_hdr[8] |= IEEE80211_RADIOTAP_F_WEP; @@ -5018,10 +4283,6 @@ static int wpa_driver_nl80211_send_mntr(struct wpa_driver_nl80211_data *drv, return -1; } - if (noack) - txflags |= IEEE80211_RADIOTAP_F_TX_NOACK; - *(le16 *) &rtap_hdr[12] = host_to_le16(txflags); - res = sendmsg(drv->monitor_sock, &msg, 0); if (res < 0) { wpa_printf(MSG_INFO, "nl80211: sendmsg: %s", strerror(errno)); @@ -5031,24 +4292,8 @@ static int wpa_driver_nl80211_send_mntr(struct wpa_driver_nl80211_data *drv, } -static int wpa_driver_nl80211_send_frame(struct i802_bss *bss, - const void *data, size_t len, - int encrypt, int noack) -{ - struct wpa_driver_nl80211_data *drv = bss->drv; - u64 cookie; - - if (drv->use_monitor) - return wpa_driver_nl80211_send_mntr(drv, data, len, - encrypt, noack); - - return nl80211_send_frame_cmd(bss, bss->freq, 0, data, len, - &cookie, 0, noack, 0); -} - - static int wpa_driver_nl80211_send_mlme(void *priv, const u8 *data, - size_t data_len, int noack) + size_t data_len) { struct i802_bss *bss = priv; struct wpa_driver_nl80211_data *drv = bss->drv; @@ -5067,15 +4312,14 @@ static int wpa_driver_nl80211_send_mlme(void *priv, const u8 *data, * but it works due to the single-threaded nature * of wpa_supplicant. */ - return nl80211_send_frame_cmd(bss, drv->last_mgmt_freq, 0, - data, data_len, NULL, 1, noack, - 1); + return nl80211_send_frame_cmd(drv, drv->last_mgmt_freq, 0, + data, data_len, NULL, 1); } - if (drv->device_ap_sme && is_ap_interface(drv->nlmode)) { - return nl80211_send_frame_cmd(bss, bss->freq, 0, - data, data_len, NULL, - 0, noack, 0); + if (drv->no_monitor_iface_capab && is_ap_interface(drv->nlmode)) { + return nl80211_send_frame_cmd(drv, drv->ap_oper_freq, 0, + data, data_len, + &drv->send_action_cookie, 0); } if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && @@ -5092,14 +4336,32 @@ static int wpa_driver_nl80211_send_mlme(void *priv, const u8 *data, encrypt = 0; } - return wpa_driver_nl80211_send_frame(bss, data, data_len, encrypt, - noack); + return wpa_driver_nl80211_send_frame(drv, data, data_len, encrypt); +} + + +static int nl80211_set_ap_isolate(struct i802_bss *bss, int enabled) +{ + struct wpa_driver_nl80211_data *drv = bss->drv; + struct nl_msg *msg; + + msg = nlmsg_alloc(); + if (!msg) + return -ENOMEM; + + nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_BSS); + + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname)); + NLA_PUT_U8(msg, NL80211_ATTR_AP_ISOLATE, enabled); + + return send_and_recv_msgs(drv, msg, NULL, NULL); + nla_put_failure: + return -ENOBUFS; } static int nl80211_set_bss(struct i802_bss *bss, int cts, int preamble, - int slot, int ht_opmode, int ap_isolate, - int *basic_rates) + int slot, int ht_opmode) { struct wpa_driver_nl80211_data *drv = bss->drv; struct nl_msg *msg; @@ -5118,21 +4380,6 @@ static int nl80211_set_bss(struct i802_bss *bss, int cts, int preamble, NLA_PUT_U8(msg, NL80211_ATTR_BSS_SHORT_SLOT_TIME, slot); if (ht_opmode >= 0) NLA_PUT_U16(msg, NL80211_ATTR_BSS_HT_OPMODE, ht_opmode); - if (ap_isolate >= 0) - NLA_PUT_U8(msg, NL80211_ATTR_AP_ISOLATE, ap_isolate); - - if (basic_rates) { - u8 rates[NL80211_MAX_SUPP_RATES]; - u8 rates_len = 0; - int i; - - for (i = 0; i < NL80211_MAX_SUPP_RATES && basic_rates[i] >= 0; - i++) - rates[rates_len++] = basic_rates[i] / 5; - - NLA_PUT(msg, NL80211_ATTR_BSS_BASIC_RATES, rates_len, rates); - } - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname)); return send_and_recv_msgs(drv, msg, NULL, NULL); @@ -5175,9 +4422,6 @@ static int wpa_driver_nl80211_set_ap(void *priv, NLA_PUT_U32(msg, NL80211_ATTR_DTIM_PERIOD, params->dtim_period); NLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len, params->ssid); - if (params->proberesp && params->proberesp_len) - NLA_PUT(msg, NL80211_ATTR_PROBE_RESP, params->proberesp_len, - params->proberesp); switch (params->hide_ssid) { case NO_SSID_HIDING: NLA_PUT_U32(msg, NL80211_ATTR_HIDDEN_SSID, @@ -5222,10 +4466,6 @@ static int wpa_driver_nl80211_set_ap(void *priv, num_suites * sizeof(u32), suites); } - if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X && - params->pairwise_ciphers & (WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40)) - NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT); - num_suites = 0; if (params->pairwise_ciphers & WPA_CIPHER_CCMP) suites[num_suites++] = WLAN_CIPHER_SUITE_CCMP; @@ -5280,9 +4520,16 @@ static int wpa_driver_nl80211_set_ap(void *priv, ret, strerror(-ret)); } else { bss->beacon_set = 1; + ret = nl80211_set_ap_isolate(bss, params->isolate); + if (!params->isolate && ret) { + wpa_printf(MSG_DEBUG, "nl80211: Ignore AP isolation " + "configuration error since isolation is " + "not used"); + ret = 0; + } + nl80211_set_bss(bss, params->cts_protect, params->preamble, - params->short_slot_time, params->ht_opmode, - params->isolate, params->basic_rates); + params->short_slot_time, params->ht_opmode); } return ret; nla_put_failure: @@ -5291,11 +4538,10 @@ static int wpa_driver_nl80211_set_ap(void *priv, } -static int wpa_driver_nl80211_set_freq(struct i802_bss *bss, +static int wpa_driver_nl80211_set_freq(struct wpa_driver_nl80211_data *drv, int freq, int ht_enabled, int sec_channel_offset) { - struct wpa_driver_nl80211_data *drv = bss->drv; struct nl_msg *msg; int ret; @@ -5329,10 +4575,8 @@ static int wpa_driver_nl80211_set_freq(struct i802_bss *bss, ret = send_and_recv_msgs(drv, msg, NULL, NULL); msg = NULL; - if (ret == 0) { - bss->freq = freq; + if (ret == 0) return 0; - } wpa_printf(MSG_DEBUG, "nl80211: Failed to set channel (freq=%d): " "%d (%s)", freq, ret, strerror(-ret)); nla_put_failure: @@ -5365,7 +4609,7 @@ static int wpa_driver_nl80211_sta_add(void *priv, { struct i802_bss *bss = priv; struct wpa_driver_nl80211_data *drv = bss->drv; - struct nl_msg *msg, *wme = NULL; + struct nl_msg *msg; struct nl80211_sta_flag_update upd; int ret = -ENOBUFS; @@ -5400,19 +4644,6 @@ static int wpa_driver_nl80211_sta_add(void *priv, upd.set = upd.mask; NLA_PUT(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd); - if (params->flags & WPA_STA_WMM) { - wme = nlmsg_alloc(); - if (!wme) - goto nla_put_failure; - - NLA_PUT_U8(wme, NL80211_STA_WME_UAPSD_QUEUES, - params->qosinfo & WMM_QOSINFO_STA_AC_MASK); - NLA_PUT_U8(wme, NL80211_STA_WME_MAX_SP, - (params->qosinfo > WMM_QOSINFO_STA_SP_SHIFT) & - WMM_QOSINFO_STA_SP_MASK); - nla_put_nested(msg, NL80211_ATTR_STA_WME, wme); - } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); msg = NULL; if (ret) @@ -5422,7 +4653,6 @@ static int wpa_driver_nl80211_sta_add(void *priv, if (ret == -EEXIST) ret = 0; nla_put_failure: - nlmsg_free(wme); nlmsg_free(msg); return ret; } @@ -5893,10 +5123,6 @@ static int add_monitor_filter(int s) static void nl80211_remove_monitor_interface( struct wpa_driver_nl80211_data *drv) { - drv->monitor_refcount--; - if (drv->monitor_refcount > 0) - return; - if (drv->monitor_ifidx >= 0) { nl80211_remove_iface(drv, drv->monitor_ifidx); drv->monitor_ifidx = -1; @@ -5917,11 +5143,6 @@ nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv) int optval; socklen_t optlen; - if (drv->monitor_ifidx >= 0) { - drv->monitor_refcount++; - return 0; - } - if (os_strncmp(drv->first_bss.ifname, "p2p-", 4) == 0) { /* * P2P interface name is of the format p2p-%s-%d. For monitor @@ -5942,15 +5163,9 @@ nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv) 0); if (drv->monitor_ifidx == -EOPNOTSUPP) { - /* - * This is backward compatibility for a few versions of - * the kernel only that didn't advertise the right - * attributes for the only driver that then supported - * AP mode w/o monitor -- ath6kl. - */ wpa_printf(MSG_DEBUG, "nl80211: Driver does not support " "monitor interface type - try to run without it"); - drv->device_ap_sme = 1; + drv->no_monitor_iface_capab = 1; } if (drv->monitor_ifidx < 0) @@ -6000,79 +5215,22 @@ nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv) } -static int nl80211_setup_ap(struct i802_bss *bss) -{ - struct wpa_driver_nl80211_data *drv = bss->drv; - - /* - * Disable Probe Request reporting unless we need it in this way for - * devices that include the AP SME, in the other case (unless using - * monitor iface) we'll get it through the nl_mgmt socket instead. - */ - if (!drv->device_ap_sme) - wpa_driver_nl80211_probe_req_report(bss, 0); - - if (!drv->device_ap_sme && !drv->use_monitor) - if (nl80211_mgmt_subscribe_ap(bss)) - return -1; - - if (!drv->device_ap_sme && drv->use_monitor && - nl80211_create_monitor_interface(drv) && - !drv->device_ap_sme) - return -1; - - if (drv->device_ap_sme && - wpa_driver_nl80211_probe_req_report(bss, 1) < 0) { - wpa_printf(MSG_DEBUG, "nl80211: Failed to enable " - "Probe Request frame reporting in AP mode"); - /* Try to survive without this */ - } - - return 0; -} - - -static void nl80211_teardown_ap(struct i802_bss *bss) -{ - struct wpa_driver_nl80211_data *drv = bss->drv; - - if (drv->device_ap_sme) - wpa_driver_nl80211_probe_req_report(bss, 0); - else if (drv->use_monitor) - nl80211_remove_monitor_interface(drv); - else - nl80211_mgmt_unsubscribe(bss); - - bss->beacon_set = 0; -} - - +#ifdef CONFIG_AP static int nl80211_send_eapol_data(struct i802_bss *bss, const u8 *addr, const u8 *data, - size_t data_len) + size_t data_len, const u8 *own_addr) { - struct sockaddr_ll ll; - int ret; - - if (bss->drv->eapol_tx_sock < 0) { - wpa_printf(MSG_DEBUG, "nl80211: No socket to send EAPOL"); + if (bss->drv->l2 == NULL) { + wpa_printf(MSG_DEBUG, "nl80211: No l2_packet to send EAPOL"); return -1; } - os_memset(&ll, 0, sizeof(ll)); - ll.sll_family = AF_PACKET; - ll.sll_ifindex = bss->ifindex; - ll.sll_protocol = htons(ETH_P_PAE); - ll.sll_halen = ETH_ALEN; - os_memcpy(ll.sll_addr, addr, ETH_ALEN); - ret = sendto(bss->drv->eapol_tx_sock, data, data_len, 0, - (struct sockaddr *) &ll, sizeof(ll)); - if (ret < 0) - wpa_printf(MSG_ERROR, "nl80211: EAPOL TX: %s", - strerror(errno)); - - return ret; + if (l2_packet_send(bss->drv->l2, addr, ETH_P_EAPOL, data, data_len) < + 0) + return -1; + return 0; } +#endif /* CONFIG_AP */ static const u8 rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; @@ -6089,8 +5247,11 @@ static int wpa_driver_nl80211_hapd_send_eapol( int res; int qos = flags & WPA_STA_WMM; - if (drv->device_ap_sme || !drv->use_monitor) - return nl80211_send_eapol_data(bss, addr, data, data_len); +#ifdef CONFIG_AP + if (drv->no_monitor_iface_capab) + return nl80211_send_eapol_data(bss, addr, data, data_len, + own_addr); +#endif /* CONFIG_AP */ len = sizeof(*hdr) + (qos ? 2 : 0) + sizeof(rfc1042_header) + 2 + data_len; @@ -6129,7 +5290,7 @@ static int wpa_driver_nl80211_hapd_send_eapol( pos += 2; memcpy(pos, data, data_len); - res = wpa_driver_nl80211_send_frame(bss, (u8 *) hdr, len, encrypt, 0); + res = wpa_driver_nl80211_send_frame(drv, (u8 *) hdr, len, encrypt); if (res < 0) { wpa_printf(MSG_ERROR, "i802_send_eapol - packet len: %lu - " "failed: %d (%s)", @@ -6216,11 +5377,22 @@ static int wpa_driver_nl80211_ap(struct wpa_driver_nl80211_data *drv, nlmode = NL80211_IFTYPE_AP; if (wpa_driver_nl80211_set_mode(&drv->first_bss, nlmode) || - wpa_driver_nl80211_set_freq(&drv->first_bss, params->freq, 0, 0)) { + wpa_driver_nl80211_set_freq(drv, params->freq, 0, 0)) { nl80211_remove_monitor_interface(drv); return -1; } + if (drv->no_monitor_iface_capab) { + if (wpa_driver_nl80211_probe_req_report(&drv->first_bss, 1) < 0) + { + wpa_printf(MSG_DEBUG, "nl80211: Failed to enable " + "Probe Request frame reporting in AP mode"); + /* Try to survive without this */ + } + } + + drv->ap_oper_freq = params->freq; + return 0; } @@ -6668,9 +5840,8 @@ static int wpa_driver_nl80211_associate( ret = send_and_recv_msgs(drv, msg, NULL, NULL); msg = NULL; if (ret) { - wpa_dbg(drv->ctx, MSG_DEBUG, - "nl80211: MLME command failed (assoc): ret=%d (%s)", - ret, strerror(-ret)); + wpa_printf(MSG_DEBUG, "nl80211: MLME command failed: ret=%d " + "(%s)", ret, strerror(-ret)); nl80211_dump_scan(drv); goto nla_put_failure; } @@ -6720,18 +5891,13 @@ static int wpa_driver_nl80211_set_mode(struct i802_bss *bss, int ret = -1; int i; int was_ap = is_ap_interface(drv->nlmode); - int res; - res = nl80211_set_mode(drv, drv->ifindex, nlmode); - if (res == 0) { + if (nl80211_set_mode(drv, drv->ifindex, nlmode) == 0) { drv->nlmode = nlmode; ret = 0; goto done; } - if (res == -ENODEV) - return -1; - if (nlmode == drv->nlmode) { wpa_printf(MSG_DEBUG, "nl80211: Interface already in " "requested mode - ignore error"); @@ -6746,6 +5912,7 @@ static int wpa_driver_nl80211_set_mode(struct i802_bss *bss, wpa_printf(MSG_DEBUG, "nl80211: Try mode change after setting " "interface down"); for (i = 0; i < 10; i++) { + int res; res = linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0); if (res == -EACCES || res == -ENODEV) @@ -6776,30 +5943,33 @@ static int wpa_driver_nl80211_set_mode(struct i802_bss *bss, } done: - if (ret) { - wpa_printf(MSG_DEBUG, "nl80211: Interface mode change to %d " - "from %d failed", nlmode, drv->nlmode); - return ret; - } - - if (is_ap_interface(nlmode)) { - nl80211_mgmt_unsubscribe(bss); + if (!ret && is_ap_interface(nlmode)) { /* Setup additional AP mode functionality if needed */ - if (nl80211_setup_ap(bss)) + if (!drv->no_monitor_iface_capab && drv->monitor_ifidx < 0 && + nl80211_create_monitor_interface(drv) && + !drv->no_monitor_iface_capab) return -1; - } else if (was_ap) { + } else if (!ret && !is_ap_interface(nlmode)) { /* Remove additional AP mode functionality */ - nl80211_teardown_ap(bss); - } else { - nl80211_mgmt_unsubscribe(bss); + if (was_ap && drv->no_monitor_iface_capab) + wpa_driver_nl80211_probe_req_report(bss, 0); + nl80211_remove_monitor_interface(drv); + bss->beacon_set = 0; } - if (!is_ap_interface(nlmode) && - nl80211_mgmt_subscribe_non_ap(bss) < 0) - wpa_printf(MSG_DEBUG, "nl80211: Failed to register Action " - "frame processing - ignore for now"); + if (!ret && is_p2p_interface(drv->nlmode)) { + nl80211_disable_11b_rates(drv, drv->ifindex, 1); + drv->disabled_11b_rates = 1; + } else if (!ret && drv->disabled_11b_rates) { + nl80211_disable_11b_rates(drv, drv->ifindex, 0); + drv->disabled_11b_rates = 0; + } - return 0; + if (ret) + wpa_printf(MSG_DEBUG, "nl80211: Interface mode change to %d " + "from %d failed", nlmode, drv->nlmode); + + return ret; } @@ -6862,7 +6032,8 @@ static int wpa_driver_nl80211_set_supp_port(void *priv, int authorized) static int i802_set_freq(void *priv, struct hostapd_freq_params *freq) { struct i802_bss *bss = priv; - return wpa_driver_nl80211_set_freq(bss, freq->freq, freq->ht_enabled, + struct wpa_driver_nl80211_data *drv = bss->drv; + return wpa_driver_nl80211_set_freq(drv, freq->freq, freq->ht_enabled, freq->sec_channel_offset); } @@ -6925,6 +6096,35 @@ static int i802_get_seqnum(const char *iface, void *priv, const u8 *addr, } +static int i802_set_rate_sets(void *priv, int *supp_rates, int *basic_rates, + int mode) +{ + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; + struct nl_msg *msg; + u8 rates[NL80211_MAX_SUPP_RATES]; + u8 rates_len = 0; + int i; + + msg = nlmsg_alloc(); + if (!msg) + return -ENOMEM; + + nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_BSS); + + for (i = 0; i < NL80211_MAX_SUPP_RATES && basic_rates[i] >= 0; i++) + rates[rates_len++] = basic_rates[i] / 5; + + NLA_PUT(msg, NL80211_ATTR_BSS_BASIC_RATES, rates_len, rates); + + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname)); + + return send_and_recv_msgs(drv, msg, NULL, NULL); + nla_put_failure: + return -ENOBUFS; +} + + static int i802_set_rts(void *priv, int rts) { struct i802_bss *bss = priv; @@ -7221,7 +6421,7 @@ static int i802_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, mgmt.u.deauth.reason_code = host_to_le16(reason); return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt, IEEE80211_HDRLEN + - sizeof(mgmt.u.deauth), 0); + sizeof(mgmt.u.deauth)); } @@ -7240,7 +6440,7 @@ static int i802_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr, mgmt.u.disassoc.reason_code = host_to_le16(reason); return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt, IEEE80211_HDRLEN + - sizeof(mgmt.u.disassoc), 0); + sizeof(mgmt.u.disassoc)); } #endif /* HOSTAPD || CONFIG_AP */ @@ -7499,8 +6699,6 @@ static void *i802_init(struct hostapd_data *hapd, params->own_addr)) goto failed; - memcpy(bss->addr, params->own_addr, ETH_ALEN); - return bss; failed: @@ -7544,7 +6742,7 @@ static int nl80211_addr_in_use(struct nl80211_global *global, const u8 *addr) struct wpa_driver_nl80211_data *drv; dl_list_for_each(drv, &global->interfaces, struct wpa_driver_nl80211_data, list) { - if (os_memcmp(addr, drv->first_bss.addr, ETH_ALEN) == 0) + if (os_memcmp(addr, drv->addr, ETH_ALEN) == 0) return 1; } return 0; @@ -7559,9 +6757,9 @@ static int nl80211_p2p_interface_addr(struct wpa_driver_nl80211_data *drv, if (!drv->global) return -1; - os_memcpy(new_addr, drv->first_bss.addr, ETH_ALEN); + os_memcpy(new_addr, drv->addr, ETH_ALEN); for (idx = 0; idx < 64; idx++) { - new_addr[0] = drv->first_bss.addr[0] | 0x02; + new_addr[0] = drv->addr[0] | 0x02; new_addr[0] ^= idx << 2; if (!nl80211_addr_in_use(drv->global, new_addr)) break; @@ -7665,14 +6863,12 @@ static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type, return -1; } os_strlcpy(new_bss->ifname, ifname, IFNAMSIZ); - os_memcpy(new_bss->addr, if_addr, ETH_ALEN); new_bss->ifindex = ifidx; new_bss->drv = drv; new_bss->next = drv->first_bss.next; drv->first_bss.next = new_bss; if (drv_priv) *drv_priv = new_bss; - nl80211_init_bss(new_bss); } #endif /* HOSTAPD */ @@ -7724,7 +6920,6 @@ static int wpa_driver_nl80211_if_remove(void *priv, for (tbss = &drv->first_bss; tbss; tbss = tbss->next) { if (tbss->next == bss) { tbss->next = bss->next; - nl80211_destroy_bss(bss); os_free(bss); bss = NULL; break; @@ -7753,13 +6948,11 @@ static int cookie_handler(struct nl_msg *msg, void *arg) } -static int nl80211_send_frame_cmd(struct i802_bss *bss, +static int nl80211_send_frame_cmd(struct wpa_driver_nl80211_data *drv, unsigned int freq, unsigned int wait, const u8 *buf, size_t buf_len, - u64 *cookie_out, int no_cck, int no_ack, - int offchanok) + u64 *cookie_out, int no_cck) { - struct wpa_driver_nl80211_data *drv = bss->drv; struct nl_msg *msg; u64 cookie; int ret = -1; @@ -7770,16 +6963,13 @@ static int nl80211_send_frame_cmd(struct i802_bss *bss, nl80211_cmd(drv, msg, 0, NL80211_CMD_FRAME); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex); + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq); if (wait) NLA_PUT_U32(msg, NL80211_ATTR_DURATION, wait); - if (offchanok) - NLA_PUT_FLAG(msg, NL80211_ATTR_OFFCHANNEL_TX_OK); + NLA_PUT_FLAG(msg, NL80211_ATTR_OFFCHANNEL_TX_OK); if (no_cck) NLA_PUT_FLAG(msg, NL80211_ATTR_TX_NO_CCK_RATE); - if (no_ack) - NLA_PUT_FLAG(msg, NL80211_ATTR_DONT_WAIT_FOR_ACK); NLA_PUT(msg, NL80211_ATTR_FRAME, buf_len, buf); @@ -7792,12 +6982,11 @@ static int nl80211_send_frame_cmd(struct i802_bss *bss, freq, wait); goto nla_put_failure; } - wpa_printf(MSG_DEBUG, "nl80211: Frame TX command accepted%s; " - "cookie 0x%llx", no_ack ? " (no ACK)" : "", - (long long unsigned int) cookie); + wpa_printf(MSG_DEBUG, "nl80211: Frame TX command accepted; " + "cookie 0x%llx", (long long unsigned int) cookie); if (cookie_out) - *cookie_out = no_ack ? (u64) -1 : cookie; + *cookie_out = cookie; nla_put_failure: nlmsg_free(msg); @@ -7833,13 +7022,12 @@ static int wpa_driver_nl80211_send_action(void *priv, unsigned int freq, os_memcpy(hdr->addr3, bssid, ETH_ALEN); if (is_ap_interface(drv->nlmode)) - ret = wpa_driver_nl80211_send_mlme(priv, buf, 24 + data_len, - 0); + ret = wpa_driver_nl80211_send_mlme(priv, buf, 24 + data_len); else - ret = nl80211_send_frame_cmd(bss, freq, wait_time, buf, + ret = nl80211_send_frame_cmd(drv, freq, wait_time, buf, 24 + data_len, &drv->send_action_cookie, - no_cck, 0, 1); + no_cck); os_free(buf); return ret; @@ -7956,38 +7144,48 @@ static int wpa_driver_nl80211_probe_req_report(void *priv, int report) struct wpa_driver_nl80211_data *drv = bss->drv; if (!report) { - if (bss->nl_preq) { + if (drv->nl_preq.handle && drv->no_monitor_iface_capab && + is_ap_interface(drv->nlmode)) { + /* + * Do not disable Probe Request reporting that was + * enabled in nl80211_setup_ap(). + */ + wpa_printf(MSG_DEBUG, "nl80211: Skip disabling of " + "Probe Request reporting nl_preq=%p while " + "in AP mode", drv->nl_preq.handle); + } else if (drv->nl_preq.handle) { + wpa_printf(MSG_DEBUG, "nl80211: Disable Probe Request " + "reporting nl_preq=%p", drv->nl_preq.handle); eloop_unregister_read_sock( - nl_socket_get_fd(bss->nl_preq)); - nl_destroy_handles(&bss->nl_preq); + nl_socket_get_fd(drv->nl_preq.handle)); + nl_destroy_handles(&drv->nl_preq); } return 0; } - if (bss->nl_preq) { + if (drv->nl_preq.handle) { wpa_printf(MSG_DEBUG, "nl80211: Probe Request reporting " "already on!"); return 0; } - bss->nl_preq = nl_create_handle(drv->global->nl_cb, "preq"); - if (bss->nl_preq == NULL) + if (nl_create_handles(&drv->nl_preq, drv->global->nl_cb, "preq")) return -1; - if (nl80211_register_frame(bss, bss->nl_preq, + if (nl80211_register_frame(drv, drv->nl_preq.handle, (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_PROBE_REQ << 4), NULL, 0) < 0) goto out_err; - eloop_register_read_sock(nl_socket_get_fd(bss->nl_preq), - wpa_driver_nl80211_event_receive, bss->nl_cb, - bss->nl_preq); + eloop_register_read_sock(nl_socket_get_fd(drv->nl_preq.handle), + wpa_driver_nl80211_event_receive, drv, + drv->nl_preq.handle); return 0; out_err: - nl_destroy_handles(&bss->nl_preq); + nl_destroy_handles(&drv->nl_preq); return -1; } @@ -8052,6 +7250,16 @@ static int wpa_driver_nl80211_deinit_ap(void *priv) } +static int wpa_driver_nl80211_deinit_p2p_cli(void *priv) +{ + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; + if (drv->nlmode != NL80211_IFTYPE_P2P_CLIENT) + return -1; + return wpa_driver_nl80211_set_mode(priv, NL80211_IFTYPE_STATION); +} + + static void wpa_driver_nl80211_resume(void *priv) { struct i802_bss *bss = priv; @@ -8071,7 +7279,11 @@ static int nl80211_send_ft_action(void *priv, u8 action, const u8 *target_ap, int ret; u8 *data, *pos; size_t data_len; - const u8 *own_addr = bss->addr; + u8 own_addr[ETH_ALEN]; + + if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname, + own_addr) < 0) + return -1; if (action != 1) { wpa_printf(MSG_ERROR, "nl80211: Unsupported send_ft_action " @@ -8161,49 +7373,12 @@ static int nl80211_signal_poll(void *priv, struct wpa_signal_info *si) } -static int wpa_driver_nl80211_shared_freq(void *priv) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - struct wpa_driver_nl80211_data *driver; - int freq = 0; - - /* - * If the same PHY is in connected state with some other interface, - * then retrieve the assoc freq. - */ - wpa_printf(MSG_DEBUG, "nl80211: Get shared freq for PHY %s", - drv->phyname); - - dl_list_for_each(driver, &drv->global->interfaces, - struct wpa_driver_nl80211_data, list) { - if (drv == driver || - os_strcmp(drv->phyname, driver->phyname) != 0 || - !driver->associated) - continue; - - wpa_printf(MSG_DEBUG, "nl80211: Found a match for PHY %s - %s " - MACSTR, - driver->phyname, driver->first_bss.ifname, - MAC2STR(driver->first_bss.addr)); - freq = nl80211_get_assoc_freq(driver); - wpa_printf(MSG_DEBUG, "nl80211: Shared freq for PHY %s: %d", - drv->phyname, freq); - } - - if (!freq) - wpa_printf(MSG_DEBUG, "nl80211: No shared interface for " - "PHY (%s) in associated state", drv->phyname); - - return freq; -} - - static int nl80211_send_frame(void *priv, const u8 *data, size_t data_len, int encrypt) { struct i802_bss *bss = priv; - return wpa_driver_nl80211_send_frame(bss, data, data_len, encrypt, 0); + struct wpa_driver_nl80211_data *drv = bss->drv; + return wpa_driver_nl80211_send_frame(drv, data, data_len, encrypt); } @@ -8285,15 +7460,12 @@ static void nl80211_global_deinit(void *priv) if (global->netlink) netlink_deinit(global->netlink); + if (global->nl80211) + genl_family_put(global->nl80211); nl_destroy_handles(&global->nl); - if (global->nl_event) { - eloop_unregister_read_sock( - nl_socket_get_fd(global->nl_event)); - nl_destroy_handles(&global->nl_event); - } - - nl_cb_put(global->nl_cb); + if (global->nl_cb) + nl_cb_put(global->nl_cb); if (global->ioctl_sock >= 0) close(global->ioctl_sock); @@ -8393,11 +7565,10 @@ static void nl80211_set_rekey_info(void *priv, const u8 *kek, const u8 *kck, } -static void nl80211_send_null_frame(struct i802_bss *bss, const u8 *own_addr, - const u8 *addr, int qos) +static void nl80211_poll_client(void *priv, const u8 *own_addr, const u8 *addr, + int qos) { - /* send data frame to poll STA and check whether - * this frame is ACKed */ + struct i802_bss *bss = priv; struct { struct ieee80211_hdr hdr; u16 qos_ctl; @@ -8425,77 +7596,11 @@ static void nl80211_send_null_frame(struct i802_bss *bss, const u8 *own_addr, os_memcpy(nulldata.hdr.IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN); os_memcpy(nulldata.hdr.IEEE80211_SA_FROMDS, own_addr, ETH_ALEN); - if (wpa_driver_nl80211_send_mlme(bss, (u8 *) &nulldata, size, 0) < 0) + if (wpa_driver_nl80211_send_mlme(bss, (u8 *) &nulldata, size) < 0) wpa_printf(MSG_DEBUG, "nl80211_send_null_frame: Failed to " "send poll frame"); } -static void nl80211_poll_client(void *priv, const u8 *own_addr, const u8 *addr, - int qos) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - struct nl_msg *msg; - - if (!drv->poll_command_supported) { - nl80211_send_null_frame(bss, own_addr, addr, qos); - return; - } - - msg = nlmsg_alloc(); - if (!msg) - return; - - nl80211_cmd(drv, msg, 0, NL80211_CMD_PROBE_CLIENT); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); - - send_and_recv_msgs(drv, msg, NULL, NULL); - return; - nla_put_failure: - nlmsg_free(msg); -} - - -static int nl80211_set_power_save(struct i802_bss *bss, int enabled) -{ - struct nl_msg *msg; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - nl80211_cmd(bss->drv, msg, 0, NL80211_CMD_SET_POWER_SAVE); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex); - NLA_PUT_U32(msg, NL80211_ATTR_PS_STATE, - enabled ? NL80211_PS_ENABLED : NL80211_PS_DISABLED); - return send_and_recv_msgs(bss->drv, msg, NULL, NULL); -nla_put_failure: - nlmsg_free(msg); - return -ENOBUFS; -} - - -static int nl80211_set_p2p_powersave(void *priv, int legacy_ps, int opp_ps, - int ctwindow) -{ - struct i802_bss *bss = priv; - - wpa_printf(MSG_DEBUG, "nl80211: set_p2p_powersave (legacy_ps=%d " - "opp_ps=%d ctwindow=%d)", legacy_ps, opp_ps, ctwindow); - - if (opp_ps != -1 || ctwindow != -1) - return -1; /* Not yet supported */ - - if (legacy_ps == -1) - return 0; - if (legacy_ps != 0 && legacy_ps != 1) - return -1; /* Not yet supported */ - - return nl80211_set_power_save(bss, legacy_ps); -} - #ifdef CONFIG_TDLS @@ -8586,139 +7691,6 @@ nla_put_failure: #endif /* CONFIG TDLS */ -#ifdef ANDROID - -typedef struct android_wifi_priv_cmd { - char *buf; - int used_len; - int total_len; -} android_wifi_priv_cmd; - -static int drv_errors = 0; - -static void wpa_driver_send_hang_msg(struct wpa_driver_nl80211_data *drv) -{ - drv_errors++; - if (drv_errors > DRV_NUMBER_SEQUENTIAL_ERRORS) { - drv_errors = 0; - wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED"); - } -} - - -static int android_priv_cmd(struct i802_bss *bss, const char *cmd) -{ - struct wpa_driver_nl80211_data *drv = bss->drv; - struct ifreq ifr; - android_wifi_priv_cmd priv_cmd; - char buf[MAX_DRV_CMD_SIZE]; - int ret; - - os_memset(&ifr, 0, sizeof(ifr)); - os_memset(&priv_cmd, 0, sizeof(priv_cmd)); - os_strlcpy(ifr.ifr_name, bss->ifname, IFNAMSIZ); - - os_memset(buf, 0, sizeof(buf)); - os_strlcpy(buf, cmd, sizeof(buf)); - - priv_cmd.buf = buf; - priv_cmd.used_len = sizeof(buf); - priv_cmd.total_len = sizeof(buf); - ifr.ifr_data = &priv_cmd; - - ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr); - if (ret < 0) { - wpa_printf(MSG_ERROR, "%s: failed to issue private commands", - __func__); - wpa_driver_send_hang_msg(drv); - return ret; - } - - drv_errors = 0; - return 0; -} - - -static int android_pno_start(struct i802_bss *bss, - struct wpa_driver_scan_params *params) -{ - struct wpa_driver_nl80211_data *drv = bss->drv; - struct ifreq ifr; - android_wifi_priv_cmd priv_cmd; - int ret = 0, i = 0, bp; - char buf[WEXT_PNO_MAX_COMMAND_SIZE]; - - bp = WEXT_PNOSETUP_HEADER_SIZE; - os_memcpy(buf, WEXT_PNOSETUP_HEADER, bp); - buf[bp++] = WEXT_PNO_TLV_PREFIX; - buf[bp++] = WEXT_PNO_TLV_VERSION; - buf[bp++] = WEXT_PNO_TLV_SUBVERSION; - buf[bp++] = WEXT_PNO_TLV_RESERVED; - - while (i < WEXT_PNO_AMOUNT && (size_t) i < params->num_ssids) { - /* Check that there is enough space needed for 1 more SSID, the - * other sections and null termination */ - if ((bp + WEXT_PNO_SSID_HEADER_SIZE + MAX_SSID_LEN + - WEXT_PNO_NONSSID_SECTIONS_SIZE + 1) >= (int) sizeof(buf)) - break; - wpa_hexdump_ascii(MSG_DEBUG, "For PNO Scan", - params->ssids[i].ssid, - params->ssids[i].ssid_len); - buf[bp++] = WEXT_PNO_SSID_SECTION; - buf[bp++] = params->ssids[i].ssid_len; - os_memcpy(&buf[bp], params->ssids[i].ssid, - params->ssids[i].ssid_len); - bp += params->ssids[i].ssid_len; - i++; - } - - buf[bp++] = WEXT_PNO_SCAN_INTERVAL_SECTION; - os_snprintf(&buf[bp], WEXT_PNO_SCAN_INTERVAL_LENGTH + 1, "%x", - WEXT_PNO_SCAN_INTERVAL); - bp += WEXT_PNO_SCAN_INTERVAL_LENGTH; - - buf[bp++] = WEXT_PNO_REPEAT_SECTION; - os_snprintf(&buf[bp], WEXT_PNO_REPEAT_LENGTH + 1, "%x", - WEXT_PNO_REPEAT); - bp += WEXT_PNO_REPEAT_LENGTH; - - buf[bp++] = WEXT_PNO_MAX_REPEAT_SECTION; - os_snprintf(&buf[bp], WEXT_PNO_MAX_REPEAT_LENGTH + 1, "%x", - WEXT_PNO_MAX_REPEAT); - bp += WEXT_PNO_MAX_REPEAT_LENGTH + 1; - - memset(&ifr, 0, sizeof(ifr)); - memset(&priv_cmd, 0, sizeof(priv_cmd)); - os_strncpy(ifr.ifr_name, bss->ifname, IFNAMSIZ); - - priv_cmd.buf = buf; - priv_cmd.used_len = bp; - priv_cmd.total_len = bp; - ifr.ifr_data = &priv_cmd; - - ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr); - - if (ret < 0) { - wpa_printf(MSG_ERROR, "ioctl[SIOCSIWPRIV] (pnosetup): %d", - ret); - wpa_driver_send_hang_msg(drv); - return ret; - } - - drv_errors = 0; - - return android_priv_cmd(bss, "PNOFORCE 1"); -} - - -static int android_pno_stop(struct i802_bss *bss) -{ - return android_priv_cmd(bss, "PNOFORCE 0"); -} - -#endif /* ANDROID */ - - const struct wpa_driver_ops wpa_driver_nl80211_ops = { .name = "nl80211", .desc = "Linux nl80211/cfg80211", @@ -8765,6 +7737,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = { .set_frag = i802_set_frag, .set_tx_queue_params = i802_set_tx_queue_params, .set_sta_vlan = i802_set_sta_vlan, + .set_rate_sets = i802_set_rate_sets, .sta_deauth = i802_sta_deauth, .sta_disassoc = i802_sta_disassoc, #endif /* HOSTAPD || CONFIG_AP */ @@ -8776,12 +7749,12 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = { wpa_driver_nl80211_cancel_remain_on_channel, .probe_req_report = wpa_driver_nl80211_probe_req_report, .deinit_ap = wpa_driver_nl80211_deinit_ap, + .deinit_p2p_cli = wpa_driver_nl80211_deinit_p2p_cli, .resume = wpa_driver_nl80211_resume, .send_ft_action = nl80211_send_ft_action, .signal_monitor = nl80211_signal_monitor, .signal_poll = nl80211_signal_poll, .send_frame = nl80211_send_frame, - .shared_freq = wpa_driver_nl80211_shared_freq, .set_param = nl80211_set_param, .get_radio_name = nl80211_get_radio_name, .add_pmkid = nl80211_add_pmkid, @@ -8789,7 +7762,6 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = { .flush_pmkid = nl80211_flush_pmkid, .set_rekey_info = nl80211_set_rekey_info, .poll_client = nl80211_poll_client, - .set_p2p_powersave = nl80211_set_p2p_powersave, #ifdef CONFIG_TDLS .send_tdls_mgmt = nl80211_send_tdls_mgmt, .tdls_oper = nl80211_tdls_oper, diff --git a/src/drivers/driver_osx.m b/src/drivers/driver_osx.m new file mode 100644 index 0000000..69ca4b5 --- /dev/null +++ b/src/drivers/driver_osx.m @@ -0,0 +1,459 @@ +/* + * WPA Supplicant - Mac OS X Apple80211 driver interface + * Copyright (c) 2007, Jouni Malinen + * + * 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" +#define Boolean __DummyBoolean +#include +#undef Boolean + +#include "common.h" +#include "driver.h" +#include "eloop.h" +#include "common/ieee802_11_defs.h" + +#include "Apple80211.h" + +struct wpa_driver_osx_data { + void *ctx; + WirelessRef wireless_ctx; + CFArrayRef scan_results; +}; + + +#ifndef CONFIG_NO_STDOUT_DEBUG +extern int wpa_debug_level; + +static void dump_dict_cb(const void *key, const void *value, void *context) +{ + if (MSG_DEBUG < wpa_debug_level) + return; + + wpa_printf(MSG_DEBUG, "Key:"); + CFShow(key); + wpa_printf(MSG_DEBUG, "Value:"); + CFShow(value); +} +#endif /* CONFIG_NO_STDOUT_DEBUG */ + + +static void wpa_driver_osx_dump_dict(CFDictionaryRef dict, const char *title) +{ +#ifndef CONFIG_NO_STDOUT_DEBUG + wpa_printf(MSG_DEBUG, "OSX: Dump dictionary %s - %u entries", + title, (unsigned int) CFDictionaryGetCount(dict)); + CFDictionaryApplyFunction(dict, dump_dict_cb, NULL); +#endif /* CONFIG_NO_STDOUT_DEBUG */ +} + + +static int wpa_driver_osx_get_ssid(void *priv, u8 *ssid) +{ + struct wpa_driver_osx_data *drv = priv; + WirelessError err; + WirelessInfo info; + int len; + + err = WirelessGetInfo(drv->wireless_ctx, &info); + if (err) { + wpa_printf(MSG_DEBUG, "OSX: WirelessGetInfo failed: %d", + (int) err); + return -1; + } + if (!info.power) { + wpa_printf(MSG_DEBUG, "OSX: Wireless device power off"); + return -1; + } + + for (len = 0; len < 32; len++) + if (info.ssid[len] == 0) + break; + + os_memcpy(ssid, info.ssid, len); + return len; +} + + +static int wpa_driver_osx_get_bssid(void *priv, u8 *bssid) +{ + struct wpa_driver_osx_data *drv = priv; + WirelessError err; + WirelessInfo info; + + err = WirelessGetInfo(drv->wireless_ctx, &info); + if (err) { + wpa_printf(MSG_DEBUG, "OSX: WirelessGetInfo failed: %d", + (int) err); + return -1; + } + if (!info.power) { + wpa_printf(MSG_DEBUG, "OSX: Wireless device power off"); + return -1; + } + + os_memcpy(bssid, info.bssID, ETH_ALEN); + return 0; +} + + +static void wpa_driver_osx_scan_timeout(void *eloop_ctx, void *timeout_ctx) +{ + wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL); +} + + +static int wpa_driver_osx_scan(void *priv, struct wpa_driver_scan_params *params) +{ + struct wpa_driver_osx_data *drv = priv; + WirelessError err; + const u8 *ssid = params->ssids[0].ssid; + size_t ssid_len = params->ssids[0].ssid_len; + + if (drv->scan_results) { + CFRelease(drv->scan_results); + drv->scan_results = NULL; + } + + if (ssid) { + CFStringRef data; + data = CFStringCreateWithBytes(kCFAllocatorDefault, + ssid, ssid_len, + kCFStringEncodingISOLatin1, + FALSE); + if (data == NULL) { + wpa_printf(MSG_DEBUG, "CFStringCreateWithBytes " + "failed"); + return -1; + } + + err = WirelessDirectedScan(drv->wireless_ctx, + &drv->scan_results, 0, data); + CFRelease(data); + if (err) { + wpa_printf(MSG_DEBUG, "OSX: WirelessDirectedScan " + "failed: 0x%08x", (unsigned int) err); + return -1; + } + } else { + err = WirelessScan(drv->wireless_ctx, &drv->scan_results, 0); + if (err) { + wpa_printf(MSG_DEBUG, "OSX: WirelessScan failed: " + "0x%08x", (unsigned int) err); + return -1; + } + } + + eloop_register_timeout(0, 0, wpa_driver_osx_scan_timeout, drv, + drv->ctx); + return 0; +} + + +static void wpa_driver_osx_add_scan_entry(struct wpa_scan_results *res, + WirelessNetworkInfo *info) +{ + struct wpa_scan_res *result, **tmp; + size_t extra_len; + u8 *pos; + + extra_len = 2 + info->ssid_len; + + result = os_zalloc(sizeof(*result) + extra_len); + if (result == NULL) + return; + os_memcpy(result->bssid, info->bssid, ETH_ALEN); + result->freq = 2407 + info->channel * 5; + //result->beacon_int =; + result->caps = info->capability; + //result->qual = info->signal; + result->noise = info->noise; + + pos = (u8 *)(result + 1); + + *pos++ = WLAN_EID_SSID; + *pos++ = info->ssid_len; + os_memcpy(pos, info->ssid, info->ssid_len); + pos += info->ssid_len; + + result->ie_len = pos - (u8 *)(result + 1); + + tmp = os_realloc(res->res, + (res->num + 1) * sizeof(struct wpa_scan_res *)); + if (tmp == NULL) { + os_free(result); + return; + } + tmp[res->num++] = result; + res->res = tmp; +} + + +static struct wpa_scan_results * wpa_driver_osx_get_scan_results(void *priv) +{ + struct wpa_driver_osx_data *drv = priv; + struct wpa_scan_results *res; + size_t i, num; + + if (drv->scan_results == NULL) + return 0; + + num = CFArrayGetCount(drv->scan_results); + + res = os_zalloc(sizeof(*res)); + if (res == NULL) + return NULL; + + for (i = 0; i < num; i++) + wpa_driver_osx_add_scan_entry(res, (WirelessNetworkInfo *) + CFDataGetBytePtr(CFArrayGetValueAtIndex( + drv->scan_results, i))); + + return res; +} + + +static void wpa_driver_osx_assoc_timeout(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_driver_osx_data *drv = eloop_ctx; + u8 bssid[ETH_ALEN]; + CFDictionaryRef ai; + + if (wpa_driver_osx_get_bssid(drv, bssid) != 0) { + eloop_register_timeout(1, 0, wpa_driver_osx_assoc_timeout, + drv, drv->ctx); + return; + } + + ai = WirelessGetAssociationInfo(drv->wireless_ctx); + if (ai) { + wpa_driver_osx_dump_dict(ai, "WirelessGetAssociationInfo"); + CFRelease(ai); + } else { + wpa_printf(MSG_DEBUG, "OSX: Failed to get association info"); + } + + wpa_supplicant_event(timeout_ctx, EVENT_ASSOC, NULL); +} + + +static int wpa_driver_osx_associate(void *priv, + struct wpa_driver_associate_params *params) +{ + struct wpa_driver_osx_data *drv = priv; + WirelessError err; + CFDataRef ssid; + CFStringRef key; + int assoc_type; + + ssid = CFDataCreate(kCFAllocatorDefault, params->ssid, + params->ssid_len); + if (ssid == NULL) + return -1; + + /* TODO: support for WEP */ + if (params->key_mgmt_suite == KEY_MGMT_PSK) { + if (params->passphrase == NULL) + return -1; + key = CFStringCreateWithCString(kCFAllocatorDefault, + params->passphrase, + kCFStringEncodingISOLatin1); + if (key == NULL) { + CFRelease(ssid); + return -1; + } + } else + key = NULL; + + if (params->key_mgmt_suite == KEY_MGMT_NONE) + assoc_type = 0; + else + assoc_type = 4; + + wpa_printf(MSG_DEBUG, "OSX: WirelessAssociate(type=%d key=%p)", + assoc_type, key); + err = WirelessAssociate(drv->wireless_ctx, assoc_type, ssid, key); + CFRelease(ssid); + if (key) + CFRelease(key); + if (err) { + wpa_printf(MSG_DEBUG, "OSX: WirelessAssociate failed: 0x%08x", + (unsigned int) err); + return -1; + } + + /* + * Driver is actually already associated; report association from an + * eloop callback. + */ + eloop_cancel_timeout(wpa_driver_osx_assoc_timeout, drv, drv->ctx); + eloop_register_timeout(0, 0, wpa_driver_osx_assoc_timeout, drv, + drv->ctx); + + return 0; +} + + +static int wpa_driver_osx_set_key(const char *ifname, void *priv, + enum 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_osx_data *drv = priv; + WirelessError err; + + if (alg == WPA_ALG_WEP) { + err = WirelessSetKey(drv->wireless_ctx, 1, key_idx, key_len, + key); + if (err != 0) { + wpa_printf(MSG_DEBUG, "OSX: WirelessSetKey failed: " + "0x%08x", (unsigned int) err); + return -1; + } + + return 0; + } + + if (alg == WPA_ALG_PMK) { + err = WirelessSetWPAKey(drv->wireless_ctx, 1, key_len, key); + if (err != 0) { + wpa_printf(MSG_DEBUG, "OSX: WirelessSetWPAKey failed: " + "0x%08x", (unsigned int) err); + return -1; + } + return 0; + } + + wpa_printf(MSG_DEBUG, "OSX: Unsupported set_key alg %d", alg); + return -1; +} + + +static int wpa_driver_osx_get_capa(void *priv, struct wpa_driver_capa *capa) +{ + os_memset(capa, 0, sizeof(*capa)); + + capa->key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA | + WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | + WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | + WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK; + capa->enc = WPA_DRIVER_CAPA_ENC_WEP40 | WPA_DRIVER_CAPA_ENC_WEP104 | + WPA_DRIVER_CAPA_ENC_TKIP | WPA_DRIVER_CAPA_ENC_CCMP; + capa->auth = WPA_DRIVER_AUTH_OPEN | WPA_DRIVER_AUTH_SHARED | + WPA_DRIVER_AUTH_LEAP; + capa->flags = WPA_DRIVER_FLAGS_4WAY_HANDSHAKE; + + return 0; +} + + +static void * wpa_driver_osx_init(void *ctx, const char *ifname) +{ + struct wpa_driver_osx_data *drv; + WirelessError err; + u8 enabled, power; + + if (!WirelessIsAvailable()) { + wpa_printf(MSG_ERROR, "OSX: No wireless interface available"); + return NULL; + } + + drv = os_zalloc(sizeof(*drv)); + if (drv == NULL) + return NULL; + drv->ctx = ctx; + err = WirelessAttach(&drv->wireless_ctx, 0); + if (err) { + wpa_printf(MSG_ERROR, "OSX: WirelessAttach failed: %d", + (int) err); + os_free(drv); + return NULL; + } + + err = WirelessGetEnabled(drv->wireless_ctx, &enabled); + if (err) + wpa_printf(MSG_DEBUG, "OSX: WirelessGetEnabled failed: 0x%08x", + (unsigned int) err); + err = WirelessGetPower(drv->wireless_ctx, &power); + if (err) + wpa_printf(MSG_DEBUG, "OSX: WirelessGetPower failed: 0x%08x", + (unsigned int) err); + + wpa_printf(MSG_DEBUG, "OSX: Enabled=%d Power=%d", enabled, power); + + if (!enabled) { + err = WirelessSetEnabled(drv->wireless_ctx, 1); + if (err) { + wpa_printf(MSG_DEBUG, "OSX: WirelessSetEnabled failed:" + " 0x%08x", (unsigned int) err); + WirelessDetach(drv->wireless_ctx); + os_free(drv); + return NULL; + } + } + + if (!power) { + err = WirelessSetPower(drv->wireless_ctx, 1); + if (err) { + wpa_printf(MSG_DEBUG, "OSX: WirelessSetPower failed: " + "0x%08x", (unsigned int) err); + WirelessDetach(drv->wireless_ctx); + os_free(drv); + return NULL; + } + } + + return drv; +} + + +static void wpa_driver_osx_deinit(void *priv) +{ + struct wpa_driver_osx_data *drv = priv; + WirelessError err; + + eloop_cancel_timeout(wpa_driver_osx_scan_timeout, drv, drv->ctx); + eloop_cancel_timeout(wpa_driver_osx_assoc_timeout, drv, drv->ctx); + + err = WirelessSetPower(drv->wireless_ctx, 0); + if (err) { + wpa_printf(MSG_DEBUG, "OSX: WirelessSetPower(0) failed: " + "0x%08x", (unsigned int) err); + } + + err = WirelessDetach(drv->wireless_ctx); + if (err) { + wpa_printf(MSG_DEBUG, "OSX: WirelessDetach failed: 0x%08x", + (unsigned int) err); + } + + if (drv->scan_results) + CFRelease(drv->scan_results); + + os_free(drv); +} + + +const struct wpa_driver_ops wpa_driver_osx_ops = { + .name = "osx", + .desc = "Mac OS X Apple80211 driver", + .get_ssid = wpa_driver_osx_get_ssid, + .get_bssid = wpa_driver_osx_get_bssid, + .init = wpa_driver_osx_init, + .deinit = wpa_driver_osx_deinit, + .scan2 = wpa_driver_osx_scan, + .get_scan_results2 = wpa_driver_osx_get_scan_results, + .associate = wpa_driver_osx_associate, + .set_key = wpa_driver_osx_set_key, + .get_capa = wpa_driver_osx_get_capa, +}; diff --git a/src/drivers/driver_ralink.c b/src/drivers/driver_ralink.c new file mode 100644 index 0000000..a1e27be --- /dev/null +++ b/src/drivers/driver_ralink.c @@ -0,0 +1,1498 @@ +/* + * WPA Supplicant - driver interaction with Ralink Wireless Client + * Copyright (c) 2003-2006, Jouni Malinen + * Copyright (c) 2007, Snowpin Lee + * + * 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 + +#include "wireless_copy.h" +#include "common.h" +#include "driver.h" +#include "l2_packet/l2_packet.h" +#include "eloop.h" +#include "common/ieee802_11_defs.h" +#include "priv_netlink.h" +#include "netlink.h" +#include "linux_ioctl.h" +#include "driver_ralink.h" + +static void wpa_driver_ralink_scan_timeout(void *eloop_ctx, void *timeout_ctx); + +#define MAX_SSID_LEN 32 + +struct wpa_driver_ralink_data { + void *ctx; + int ioctl_sock; + struct netlink_data *netlink; + char ifname[IFNAMSIZ + 1]; + u8 *assoc_req_ies; + size_t assoc_req_ies_len; + u8 *assoc_resp_ies; + size_t assoc_resp_ies_len; + int no_of_pmkid; + struct ndis_pmkid_entry *pmkid; + int we_version_compiled; + int ap_scan; + int scanning_done; + u8 g_driver_down; + BOOLEAN bAddWepKey; +}; + +static int ralink_set_oid(struct wpa_driver_ralink_data *drv, + unsigned short oid, char *data, int len) +{ + char *buf; + struct iwreq iwr; + + buf = os_zalloc(len); + if (buf == NULL) + return -1; + os_memset(&iwr, 0, sizeof(iwr)); + os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); + iwr.u.data.flags = oid; + iwr.u.data.flags |= OID_GET_SET_TOGGLE; + + if (data) + os_memcpy(buf, data, len); + + iwr.u.data.pointer = (caddr_t) buf; + iwr.u.data.length = len; + + if (ioctl(drv->ioctl_sock, RT_PRIV_IOCTL, &iwr) < 0) { + wpa_printf(MSG_DEBUG, "%s: oid=0x%x len (%d) failed", + __func__, oid, len); + os_free(buf); + return -1; + } + os_free(buf); + return 0; +} + +static int +ralink_get_new_driver_flag(struct wpa_driver_ralink_data *drv) +{ + struct iwreq iwr; + UCHAR enabled = 0; + + os_memset(&iwr, 0, sizeof(iwr)); + os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); + iwr.u.data.pointer = (UCHAR*) &enabled; + iwr.u.data.flags = RT_OID_NEW_DRIVER; + + if (ioctl(drv->ioctl_sock, RT_PRIV_IOCTL, &iwr) < 0) { + wpa_printf(MSG_DEBUG, "%s: failed", __func__); + return 0; + } + + return (enabled == 1) ? 1 : 0; +} + +static int wpa_driver_ralink_get_bssid(void *priv, u8 *bssid) +{ + struct wpa_driver_ralink_data *drv = priv; + struct iwreq iwr; + int ret = 0; + + if (drv->g_driver_down == 1) + return -1; + + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); + + os_memset(&iwr, 0, sizeof(iwr)); + os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); + + if (ioctl(drv->ioctl_sock, SIOCGIWAP, &iwr) < 0) { + perror("ioctl[SIOCGIWAP]"); + ret = -1; + } + os_memcpy(bssid, iwr.u.ap_addr.sa_data, ETH_ALEN); + + return ret; +} + +static int wpa_driver_ralink_get_ssid(void *priv, u8 *ssid) +{ + struct wpa_driver_ralink_data *drv = priv; +#if 0 + struct wpa_supplicant *wpa_s = drv->ctx; + struct wpa_ssid *entry; +#endif + int ssid_len; + u8 bssid[ETH_ALEN]; + u8 ssid_str[MAX_SSID_LEN]; + struct iwreq iwr; +#if 0 + int result = 0; +#endif + int ret = 0; +#if 0 + BOOLEAN ieee8021x_mode = FALSE; + BOOLEAN ieee8021x_required_key = FALSE; +#endif + + if (drv->g_driver_down == 1) + return -1; + + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); + + 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; + + if (ioctl(drv->ioctl_sock, SIOCGIWESSID, &iwr) < 0) { + perror("ioctl[SIOCGIWESSID]"); + ret = -1; + } else + ret = iwr.u.essid.length; + + if (ret <= 0) + return ret; + + ssid_len = ret; + os_memset(ssid_str, 0, MAX_SSID_LEN); + os_memcpy(ssid_str, ssid, ssid_len); + + if (drv->ap_scan == 0) { + /* Read BSSID form driver */ + if (wpa_driver_ralink_get_bssid(priv, bssid) < 0) { + wpa_printf(MSG_WARNING, "Could not read BSSID from " + "driver."); + return ret; + } + +#if 0 + entry = wpa_s->conf->ssid; + while (entry) { + if (!entry->disabled && ssid_len == entry->ssid_len && + os_memcmp(ssid_str, entry->ssid, ssid_len) == 0 && + (!entry->bssid_set || + os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)) { + /* match the config of driver */ + result = 1; + break; + } + entry = entry->next; + } + + if (result) { + wpa_printf(MSG_DEBUG, "Ready to set 802.1x mode and " + "ieee_required_keys parameters to driver"); + + /* set 802.1x mode and ieee_required_keys parameter */ + if (entry->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { + if ((entry->eapol_flags & (EAPOL_FLAG_REQUIRE_KEY_UNICAST | EAPOL_FLAG_REQUIRE_KEY_BROADCAST))) + ieee8021x_required_key = TRUE; + ieee8021x_mode = TRUE; + } + + if (ralink_set_oid(drv, OID_802_11_SET_IEEE8021X, (char *) &ieee8021x_mode, sizeof(BOOLEAN)) < 0) + { + wpa_printf(MSG_DEBUG, "RALINK: Failed to set OID_802_11_SET_IEEE8021X(%d)", (int) ieee8021x_mode); + } + else + { + wpa_printf(MSG_DEBUG, "ieee8021x_mode is %s", ieee8021x_mode ? "TRUE" : "FALSE"); + } + + if (ralink_set_oid(drv, OID_802_11_SET_IEEE8021X_REQUIRE_KEY, (char *) &ieee8021x_required_key, sizeof(BOOLEAN)) < 0) + { + wpa_printf(MSG_DEBUG, "ERROR: Failed to set OID_802_11_SET_IEEE8021X_REQUIRE_KEY(%d)", (int) ieee8021x_required_key); + } + else + { + wpa_printf(MSG_DEBUG, "ieee8021x_required_key is %s and eapol_flag(%d)", ieee8021x_required_key ? "TRUE" : "FALSE", + entry->eapol_flags); + } + } +#endif + } + + return ret; +} + +static int wpa_driver_ralink_set_ssid(struct wpa_driver_ralink_data *drv, + const u8 *ssid, size_t ssid_len) +{ + NDIS_802_11_SSID *buf; + int ret = 0; + struct iwreq iwr; + + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); + + buf = os_zalloc(sizeof(NDIS_802_11_SSID)); + if (buf == NULL) + return -1; + os_memset(buf, 0, sizeof(buf)); + buf->SsidLength = ssid_len; + os_memcpy(buf->Ssid, ssid, ssid_len); + os_memset(&iwr, 0, sizeof(iwr)); + os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); + + iwr.u.data.flags = OID_802_11_SSID; + iwr.u.data.flags |= OID_GET_SET_TOGGLE; + iwr.u.data.pointer = (caddr_t) buf; + iwr.u.data.length = sizeof(NDIS_802_11_SSID); + + if (ioctl(drv->ioctl_sock, RT_PRIV_IOCTL, &iwr) < 0) { + perror("ioctl[RT_PRIV_IOCTL] -- OID_802_11_SSID"); + ret = -1; + } + os_free(buf); + return ret; +} + +static void wpa_driver_ralink_event_pmkid(struct wpa_driver_ralink_data *drv, + const u8 *data, size_t data_len) +{ + NDIS_802_11_PMKID_CANDIDATE_LIST *pmkid; + size_t i; + union wpa_event_data event; + + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); + + if (data_len < 8) { + wpa_printf(MSG_DEBUG, "RALINK: Too short PMKID Candidate List " + "Event (len=%lu)", (unsigned long) data_len); + return; + } + pmkid = (NDIS_802_11_PMKID_CANDIDATE_LIST *) data; + wpa_printf(MSG_DEBUG, "RALINK: PMKID Candidate List Event - Version %d" + " NumCandidates %d", + (int) pmkid->Version, (int) pmkid->NumCandidates); + + if (pmkid->Version != 1) { + wpa_printf(MSG_DEBUG, "RALINK: Unsupported PMKID Candidate " + "List Version %d", (int) pmkid->Version); + return; + } + + if (data_len < 8 + pmkid->NumCandidates * sizeof(PMKID_CANDIDATE)) { + wpa_printf(MSG_DEBUG, "RALINK: PMKID Candidate List " + "underflow"); + + return; + } + + + + os_memset(&event, 0, sizeof(event)); + for (i = 0; i < pmkid->NumCandidates; i++) { + PMKID_CANDIDATE *p = &pmkid->CandidateList[i]; + wpa_printf(MSG_DEBUG, "RALINK: %lu: " MACSTR " Flags 0x%x", + (unsigned long) i, MAC2STR(p->BSSID), + (int) p->Flags); + os_memcpy(event.pmkid_candidate.bssid, p->BSSID, ETH_ALEN); + event.pmkid_candidate.index = i; + event.pmkid_candidate.preauth = + p->Flags & NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED; + wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE, + &event); + } +} + +static int wpa_driver_ralink_set_pmkid(struct wpa_driver_ralink_data *drv) +{ + int len, count, i, ret; + struct ndis_pmkid_entry *entry; + NDIS_802_11_PMKID *p; + + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); + + count = 0; + entry = drv->pmkid; + while (entry) { + count++; + if (count >= drv->no_of_pmkid) + break; + entry = entry->next; + } + len = 8 + count * sizeof(BSSID_INFO); + p = os_zalloc(len); + if (p == NULL) + return -1; + p->Length = len; + p->BSSIDInfoCount = count; + entry = drv->pmkid; + for (i = 0; i < count; i++) { + os_memcpy(&p->BSSIDInfo[i].BSSID, entry->bssid, ETH_ALEN); + os_memcpy(&p->BSSIDInfo[i].PMKID, entry->pmkid, 16); + entry = entry->next; + } + wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID", + (const u8 *) p, len); + ret = ralink_set_oid(drv, OID_802_11_PMKID, (char *) p, len); + os_free(p); + return ret; +} + +static int wpa_driver_ralink_add_pmkid(void *priv, const u8 *bssid, + const u8 *pmkid) +{ + struct wpa_driver_ralink_data *drv = priv; + struct ndis_pmkid_entry *entry, *prev; + + if (drv->g_driver_down == 1) + return -1; + + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); + + if (drv->no_of_pmkid == 0) + return 0; + + prev = NULL; + entry = drv->pmkid; + while (entry) { + if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0) + break; + prev = entry; + entry = entry->next; + } + + if (entry) { + /* Replace existing entry for this BSSID and move it into the + * beginning of the list. */ + os_memcpy(entry->pmkid, pmkid, 16); + if (prev) { + prev->next = entry->next; + entry->next = drv->pmkid; + drv->pmkid = entry; + } + } else { + entry = os_malloc(sizeof(*entry)); + if (entry) { + os_memcpy(entry->bssid, bssid, ETH_ALEN); + os_memcpy(entry->pmkid, pmkid, 16); + entry->next = drv->pmkid; + drv->pmkid = entry; + } + } + + return wpa_driver_ralink_set_pmkid(drv); +} + + +static int wpa_driver_ralink_remove_pmkid(void *priv, const u8 *bssid, + const u8 *pmkid) +{ + struct wpa_driver_ralink_data *drv = priv; + struct ndis_pmkid_entry *entry, *prev; + + if (drv->g_driver_down == 1) + return -1; + + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); + + if (drv->no_of_pmkid == 0) + return 0; + + entry = drv->pmkid; + prev = NULL; + drv->pmkid = NULL; + while (entry) { + if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0 && + os_memcmp(entry->pmkid, pmkid, 16) == 0) { + if (prev) + prev->next = entry->next; + else + drv->pmkid = entry->next; + os_free(entry); + break; + } + prev = entry; + entry = entry->next; + } + return wpa_driver_ralink_set_pmkid(drv); +} + + +static int wpa_driver_ralink_flush_pmkid(void *priv) +{ + struct wpa_driver_ralink_data *drv = priv; + NDIS_802_11_PMKID p; + struct ndis_pmkid_entry *pmkid, *prev; + + if (drv->g_driver_down == 1) + return -1; + + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); + + if (drv->no_of_pmkid == 0) + return 0; + + pmkid = drv->pmkid; + drv->pmkid = NULL; + while (pmkid) { + prev = pmkid; + pmkid = pmkid->next; + os_free(prev); + } + + os_memset(&p, 0, sizeof(p)); + p.Length = 8; + p.BSSIDInfoCount = 0; + wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID (flush)", + (const u8 *) &p, 8); + return ralink_set_oid(drv, OID_802_11_PMKID, (char *) &p, 8); +} + +static void +wpa_driver_ralink_event_wireless_custom(struct wpa_driver_ralink_data *drv, + void *ctx, char *custom) +{ + union wpa_event_data data; + u8 *req_ies = NULL, *resp_ies = NULL; + + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); + + wpa_printf(MSG_DEBUG, "Custom wireless event: '%s'", custom); + + os_memset(&data, 0, sizeof(data)); + /* Host AP driver */ + if (os_strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) { + /* receive a MICFAILURE report */ + data.michael_mic_failure.unicast = + os_strstr(custom, " unicast") != NULL; + /* TODO: parse parameters(?) */ + wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data); + } else if (os_strncmp(custom, "ASSOCINFO_ReqIEs=", 17) == 0) { + /* receive assoc. req. IEs */ + char *spos; + int bytes; + + spos = custom + 17; + /*get IE's length */ + /* + * bytes = strlen(spos); ==> bug, bytes may less than original + * size by using this way to get size. snowpin 20070312 + * if (!bytes) + * return; + */ + bytes = drv->assoc_req_ies_len; + + req_ies = os_malloc(bytes); + if (req_ies == NULL) + return; + os_memcpy(req_ies, spos, bytes); + data.assoc_info.req_ies = req_ies; + data.assoc_info.req_ies_len = bytes; + + /* skip the '\0' byte */ + spos += bytes + 1; + + data.assoc_info.resp_ies = NULL; + data.assoc_info.resp_ies_len = 0; + + if (os_strncmp(spos, " RespIEs=", 9) == 0) { + /* receive assoc. resp. IEs */ + spos += 9; + /* get IE's length */ + bytes = os_strlen(spos); + if (!bytes) + goto done; + + resp_ies = os_malloc(bytes); + if (resp_ies == NULL) + goto done; + os_memcpy(resp_ies, spos, bytes); + data.assoc_info.resp_ies = resp_ies; + data.assoc_info.resp_ies_len = bytes; + } + + wpa_supplicant_event(ctx, EVENT_ASSOCINFO, &data); + + done: + /* free allocated memory */ + os_free(resp_ies); + os_free(req_ies); + } +} + +static void ralink_interface_up(struct wpa_driver_ralink_data *drv) +{ + union wpa_event_data event; + int enable_wpa_supplicant = 0; + drv->g_driver_down = 0; + os_memset(&event, 0, sizeof(event)); + os_snprintf(event.interface_status.ifname, + sizeof(event.interface_status.ifname), "%s", drv->ifname); + + event.interface_status.ievent = EVENT_INTERFACE_ADDED; + wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event); + + if (drv->ap_scan == 1) + enable_wpa_supplicant = 1; + else + enable_wpa_supplicant = 2; + /* trigger driver support wpa_supplicant */ + if (ralink_set_oid(drv, RT_OID_WPA_SUPPLICANT_SUPPORT, + (PCHAR) &enable_wpa_supplicant, sizeof(UCHAR)) < 0) + { + wpa_printf(MSG_INFO, "RALINK: Failed to set " + "RT_OID_WPA_SUPPLICANT_SUPPORT(%d)", + (int) enable_wpa_supplicant); + wpa_printf(MSG_ERROR, "ralink. Driver does not support " + "wpa_supplicant"); + } +} + +static void +wpa_driver_ralink_event_wireless(struct wpa_driver_ralink_data *drv, + void *ctx, char *data, int len) +{ + struct iw_event iwe_buf, *iwe = &iwe_buf; + char *pos, *end, *custom, *buf, *assoc_info_buf, *info_pos; +#if 0 + BOOLEAN ieee8021x_required_key = FALSE; +#endif + + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); + + assoc_info_buf = info_pos = NULL; + 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); + 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 == IWEVCUSTOM) { + /* 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; + } + + switch (iwe->cmd) { + case IWEVCUSTOM: + if (custom + iwe->u.data.length > end) + 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'; + + if (drv->ap_scan == 1) { + if ((iwe->u.data.flags == RT_ASSOC_EVENT_FLAG) + || (iwe->u.data.flags == + RT_REQIE_EVENT_FLAG) || + (iwe->u.data.flags == RT_RESPIE_EVENT_FLAG) + || (iwe->u.data.flags == + RT_ASSOCINFO_EVENT_FLAG)) { + if (drv->scanning_done == 0) { + os_free(buf); + return; + } + } + } + + if (iwe->u.data.flags == RT_ASSOC_EVENT_FLAG) { + wpa_supplicant_event(ctx, EVENT_ASSOC, NULL); + wpa_printf(MSG_DEBUG, "Custom wireless event: " + "receive ASSOCIATED_EVENT !!!"); + } else if (iwe->u.data.flags == RT_REQIE_EVENT_FLAG) { + wpa_printf(MSG_DEBUG, "Custom wireless event: " + "receive ReqIEs !!!"); + drv->assoc_req_ies = + os_malloc(iwe->u.data.length); + if (drv->assoc_req_ies == NULL) { + os_free(buf); + return; + } + + drv->assoc_req_ies_len = iwe->u.data.length; + os_memcpy(drv->assoc_req_ies, custom, + iwe->u.data.length); + } else if (iwe->u.data.flags == RT_RESPIE_EVENT_FLAG) { + wpa_printf(MSG_DEBUG, "Custom wireless event: " + "receive RespIEs !!!"); + drv->assoc_resp_ies = + os_malloc(iwe->u.data.length); + if (drv->assoc_resp_ies == NULL) { + os_free(drv->assoc_req_ies); + drv->assoc_req_ies = NULL; + os_free(buf); + return; + } + + drv->assoc_resp_ies_len = iwe->u.data.length; + os_memcpy(drv->assoc_resp_ies, custom, + iwe->u.data.length); + } else if (iwe->u.data.flags == + RT_ASSOCINFO_EVENT_FLAG) { + wpa_printf(MSG_DEBUG, "Custom wireless event: " + "receive ASSOCINFO_EVENT !!!"); + + assoc_info_buf = + os_zalloc(drv->assoc_req_ies_len + + drv->assoc_resp_ies_len + 1); + + if (assoc_info_buf == NULL) { + os_free(drv->assoc_req_ies); + drv->assoc_req_ies = NULL; + os_free(drv->assoc_resp_ies); + drv->assoc_resp_ies = NULL; + os_free(buf); + return; + } + + if (drv->assoc_req_ies) { + os_memcpy(assoc_info_buf, + drv->assoc_req_ies, + drv->assoc_req_ies_len); + } + info_pos = assoc_info_buf + + drv->assoc_req_ies_len; + if (drv->assoc_resp_ies) { + os_memcpy(info_pos, + drv->assoc_resp_ies, + drv->assoc_resp_ies_len); + } + assoc_info_buf[drv->assoc_req_ies_len + + drv->assoc_resp_ies_len] = '\0'; + wpa_driver_ralink_event_wireless_custom( + drv, ctx, assoc_info_buf); + os_free(drv->assoc_req_ies); + drv->assoc_req_ies = NULL; + os_free(drv->assoc_resp_ies); + drv->assoc_resp_ies = NULL; + os_free(assoc_info_buf); + } else if (iwe->u.data.flags == RT_DISASSOC_EVENT_FLAG) + { + wpa_printf(MSG_DEBUG, "Custom wireless event: " + "receive DISASSOCIATED_EVENT !!!"); + wpa_supplicant_event(ctx, EVENT_DISASSOC, + NULL); + } else if (iwe->u.data.flags == RT_PMKIDCAND_FLAG) { + wpa_printf(MSG_DEBUG, "Custom wireless event: " + "receive PMKIDCAND_EVENT !!!"); + wpa_driver_ralink_event_pmkid( + drv, (const u8 *) custom, + iwe->u.data.length); + } else if (iwe->u.data.flags == RT_INTERFACE_DOWN) { + drv->g_driver_down = 1; + eloop_terminate(); + } else if (iwe->u.data.flags == RT_INTERFACE_UP) { + ralink_interface_up(drv); + } else { + wpa_driver_ralink_event_wireless_custom( + drv, ctx, buf); + } + os_free(buf); + break; + } + + pos += iwe->len; + } +} + +static void +wpa_driver_ralink_event_rtm_newlink(void *ctx, struct ifinfomsg *ifi, + u8 *buf, size_t len) +{ + struct wpa_driver_ralink_data *drv = ctx; + int attrlen, rta_len; + struct rtattr *attr; + + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); + + wpa_hexdump(MSG_DEBUG, "ifi: ", (u8 *) ifi, sizeof(struct ifinfomsg)); + + attrlen = len; + wpa_printf(MSG_DEBUG, "attrlen=%d", attrlen); + attr = (struct rtattr *) buf; + wpa_hexdump(MSG_DEBUG, "attr1: ", (u8 *) attr, sizeof(struct rtattr)); + rta_len = RTA_ALIGN(sizeof(struct rtattr)); + wpa_hexdump(MSG_DEBUG, "attr2: ", (u8 *)attr,rta_len); + while (RTA_OK(attr, attrlen)) { + wpa_printf(MSG_DEBUG, "rta_type=%02x\n", attr->rta_type); + if (attr->rta_type == IFLA_WIRELESS) { + wpa_driver_ralink_event_wireless( + drv, ctx, + ((char *) attr) + rta_len, + attr->rta_len - rta_len); + } + attr = RTA_NEXT(attr, attrlen); + wpa_hexdump(MSG_DEBUG, "attr3: ", + (u8 *) attr, sizeof(struct rtattr)); + } +} + +static int +ralink_get_we_version_compiled(struct wpa_driver_ralink_data *drv) +{ + struct iwreq iwr; + UINT we_version_compiled = 0; + + os_memset(&iwr, 0, sizeof(iwr)); + os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); + iwr.u.data.pointer = (caddr_t) &we_version_compiled; + iwr.u.data.flags = RT_OID_WE_VERSION_COMPILED; + + if (ioctl(drv->ioctl_sock, RT_PRIV_IOCTL, &iwr) < 0) { + wpa_printf(MSG_DEBUG, "%s: failed", __func__); + return -1; + } + + drv->we_version_compiled = we_version_compiled; + + return 0; +} + +static void * wpa_driver_ralink_init(void *ctx, const char *ifname) +{ + int s; + struct wpa_driver_ralink_data *drv; + struct ifreq ifr; + UCHAR enable_wpa_supplicant = 0; + struct netlink_config *cfg; + + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); + + /* open socket to kernel */ + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + perror("socket"); + return NULL; + } + /* do it */ + os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); + + if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) { + perror(ifr.ifr_name); + return NULL; + } + + drv = os_zalloc(sizeof(*drv)); + if (drv == NULL) + return NULL; + + drv->scanning_done = 1; + drv->ap_scan = 1; /* for now - let's assume ap_scan=1 is used */ + drv->ctx = ctx; + os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); + drv->ioctl_sock = s; + drv->g_driver_down = 0; + + cfg = os_zalloc(sizeof(*cfg)); + if (cfg == NULL) { + close(drv->ioctl_sock); + os_free(drv); + return NULL; + } + cfg->ctx = drv; + cfg->newlink_cb = wpa_driver_ralink_event_rtm_newlink; + drv->netlink = netlink_init(cfg); + if (drv->netlink == NULL) { + os_free(cfg); + close(drv->ioctl_sock); + os_free(drv); + return NULL; + } + + drv->no_of_pmkid = 4; /* Number of PMKID saved supported */ + + linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1); + ralink_get_we_version_compiled(drv); + wpa_driver_ralink_flush_pmkid(drv); + + if (drv->ap_scan == 1) + enable_wpa_supplicant = 1; + else + enable_wpa_supplicant = 2; + /* trigger driver support wpa_supplicant */ + if (ralink_set_oid(drv, RT_OID_WPA_SUPPLICANT_SUPPORT, + (PCHAR) &enable_wpa_supplicant, sizeof(UCHAR)) < 0) + { + wpa_printf(MSG_DEBUG, "RALINK: Failed to set " + "RT_OID_WPA_SUPPLICANT_SUPPORT(%d)", + (int) enable_wpa_supplicant); + wpa_printf(MSG_ERROR, "RALINK: Driver does not support " + "wpa_supplicant"); + close(s); + close(drv->ioctl_sock); + os_free(drv); + return NULL; + } + + if (drv->ap_scan == 1) + drv->scanning_done = 0; + + return drv; +} + +static void wpa_driver_ralink_deinit(void *priv) +{ + struct wpa_driver_ralink_data *drv = priv; + UCHAR enable_wpa_supplicant; + + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); + + enable_wpa_supplicant = 0; + + if (drv->g_driver_down == 0) { + /* trigger driver disable wpa_supplicant support */ + if (ralink_set_oid(drv, RT_OID_WPA_SUPPLICANT_SUPPORT, + (char *) &enable_wpa_supplicant, + sizeof(BOOLEAN)) < 0) { + wpa_printf(MSG_DEBUG, "RALINK: Failed to set " + "RT_OID_WPA_SUPPLICANT_SUPPORT(%d)", + (int) enable_wpa_supplicant); + } + + wpa_driver_ralink_flush_pmkid(drv); + + sleep(1); + /* linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 0); */ + } + + eloop_cancel_timeout(wpa_driver_ralink_scan_timeout, drv, drv->ctx); + netlink_deinit(drv->netlink); + close(drv->ioctl_sock); + os_free(drv); +} + +static void wpa_driver_ralink_scan_timeout(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_driver_ralink_data *drv = eloop_ctx; + + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); + + wpa_printf(MSG_DEBUG, "Scan timeout - try to get results"); + wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL); + + drv->scanning_done = 1; + +} + +static int wpa_driver_ralink_scan(void *priv, + struct wpa_driver_scan_params *params) +{ + struct wpa_driver_ralink_data *drv = priv; + struct iwreq iwr; + int ret = 0; + + if (drv->g_driver_down == 1) + return -1; + + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); + +#if 0 + if (ssid_len > IW_ESSID_MAX_SIZE) { + wpa_printf(MSG_DEBUG, "%s: too long SSID (%lu)", + __FUNCTION__, (unsigned long) ssid_len); + return -1; + } + + /* wpa_driver_ralink_set_ssid(drv, ssid, ssid_len); */ +#endif + + if (ralink_set_oid(drv, RT_OID_WPS_PROBE_REQ_IE, + (char *) params->extra_ies, params->extra_ies_len) < + 0) { + wpa_printf(MSG_DEBUG, "RALINK: Failed to set " + "RT_OID_WPS_PROBE_REQ_IE"); + } + + os_memset(&iwr, 0, sizeof(iwr)); + os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); + + if (ioctl(drv->ioctl_sock, SIOCSIWSCAN, &iwr) < 0) { + perror("ioctl[SIOCSIWSCAN]"); + ret = -1; + } + + /* Not all drivers generate "scan completed" wireless event, so try to + * read results after a timeout. */ + eloop_cancel_timeout(wpa_driver_ralink_scan_timeout, drv, drv->ctx); + eloop_register_timeout(4, 0, wpa_driver_ralink_scan_timeout, drv, + drv->ctx); + + drv->scanning_done = 0; + + return ret; +} + +static struct wpa_scan_results * +wpa_driver_ralink_get_scan_results(void *priv) +{ + struct wpa_driver_ralink_data *drv = priv; + UCHAR *buf = NULL; + size_t buf_len; + NDIS_802_11_BSSID_LIST_EX *wsr; + NDIS_WLAN_BSSID_EX *wbi; + struct iwreq iwr; + size_t ap_num; + u8 *pos; + struct wpa_scan_results *res; + + if (drv->g_driver_down == 1) + return NULL; + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); + + if (drv->we_version_compiled >= 17) + buf_len = 8192; + else + buf_len = 4096; + + for (;;) { + buf = os_zalloc(buf_len); + iwr.u.data.length = buf_len; + if (buf == NULL) + return NULL; + + wsr = (NDIS_802_11_BSSID_LIST_EX *) buf; + + wsr->NumberOfItems = 0; + os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); + iwr.u.data.pointer = (void *) buf; + iwr.u.data.flags = OID_802_11_BSSID_LIST; + + if (ioctl(drv->ioctl_sock, RT_PRIV_IOCTL, &iwr) == 0) + break; + + if (errno == E2BIG && buf_len < 65535) { + os_free(buf); + buf = NULL; + buf_len *= 2; + if (buf_len > 65535) + buf_len = 65535; /* 16-bit length field */ + wpa_printf(MSG_DEBUG, "Scan results did not fit - " + "trying larger buffer (%lu bytes)", + (unsigned long) buf_len); + } else { + perror("ioctl[RT_PRIV_IOCTL]"); + os_free(buf); + return NULL; + } + } + + res = os_zalloc(sizeof(*res)); + if (res == NULL) { + os_free(buf); + return NULL; + } + + res->res = os_zalloc(wsr->NumberOfItems * + sizeof(struct wpa_scan_res *)); + if (res->res == NULL) { + os_free(res); + os_free(buf); + return NULL; + } + + for (ap_num = 0, wbi = wsr->Bssid; ap_num < wsr->NumberOfItems; + ++ap_num) { + struct wpa_scan_res *r = NULL; + size_t extra_len = 0, var_ie_len = 0; + u8 *pos2; + + /* SSID data element */ + extra_len += 2 + wbi->Ssid.SsidLength; + var_ie_len = wbi->IELength - sizeof(NDIS_802_11_FIXED_IEs); + r = os_zalloc(sizeof(*r) + extra_len + var_ie_len); + if (r == NULL) + break; + res->res[res->num++] = r; + + wpa_printf(MSG_DEBUG, "SSID - %s", wbi->Ssid.Ssid); + /* get ie's */ + wpa_hexdump(MSG_DEBUG, "RALINK: AP IEs", + (u8 *) &wbi->IEs[0], wbi->IELength); + + os_memcpy(r->bssid, wbi->MacAddress, ETH_ALEN); + + extra_len += (2 + wbi->Ssid.SsidLength); + r->ie_len = extra_len + var_ie_len; + pos2 = (u8 *) (r + 1); + + /* + * Generate a fake SSID IE since the driver did not report + * a full IE list. + */ + *pos2++ = WLAN_EID_SSID; + *pos2++ = wbi->Ssid.SsidLength; + os_memcpy(pos2, wbi->Ssid.Ssid, wbi->Ssid.SsidLength); + pos2 += wbi->Ssid.SsidLength; + + r->freq = (wbi->Configuration.DSConfig / 1000); + + pos = (u8 *) wbi + sizeof(*wbi) - 1; + + pos += sizeof(NDIS_802_11_FIXED_IEs) - 2; + os_memcpy(&(r->caps), pos, 2); + pos += 2; + + if (wbi->IELength > sizeof(NDIS_802_11_FIXED_IEs)) + os_memcpy(pos2, pos, var_ie_len); + + wbi = (NDIS_WLAN_BSSID_EX *) ((u8 *) wbi + wbi->Length); + } + + os_free(buf); + return res; +} + +static int ralink_set_auth_mode(struct wpa_driver_ralink_data *drv, + NDIS_802_11_AUTHENTICATION_MODE mode) +{ + NDIS_802_11_AUTHENTICATION_MODE auth_mode = mode; + + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); + + if (ralink_set_oid(drv, OID_802_11_AUTHENTICATION_MODE, + (char *) &auth_mode, sizeof(auth_mode)) < 0) { + wpa_printf(MSG_DEBUG, "RALINK: Failed to set " + "OID_802_11_AUTHENTICATION_MODE (%d)", + (int) auth_mode); + return -1; + } + return 0; +} + +static int ralink_set_encr_type(struct wpa_driver_ralink_data *drv, + NDIS_802_11_WEP_STATUS encr_type) +{ + NDIS_802_11_WEP_STATUS wep_status = encr_type; + + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); + + if (ralink_set_oid(drv, OID_802_11_WEP_STATUS, + (char *) &wep_status, sizeof(wep_status)) < 0) { + wpa_printf(MSG_DEBUG, "RALINK: Failed to set " + "OID_802_11_WEP_STATUS (%d)", + (int) wep_status); + return -1; + } + return 0; +} + + +static int wpa_driver_ralink_remove_key(struct wpa_driver_ralink_data *drv, + int key_idx, const u8 *addr, + const u8 *bssid, int pairwise) +{ + NDIS_802_11_REMOVE_KEY rkey; + NDIS_802_11_KEY_INDEX _index; + int res, res2; + + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); + + os_memset(&rkey, 0, sizeof(rkey)); + + rkey.Length = sizeof(rkey); + rkey.KeyIndex = key_idx; + + if (pairwise) + rkey.KeyIndex |= 1 << 30; + + os_memcpy(rkey.BSSID, bssid, ETH_ALEN); + + res = ralink_set_oid(drv, OID_802_11_REMOVE_KEY, (char *) &rkey, + sizeof(rkey)); + + /* AlbertY@20060210 removed it */ + if (0 /* !pairwise */) { + res2 = ralink_set_oid(drv, OID_802_11_REMOVE_WEP, + (char *) &_index, sizeof(_index)); + } else + res2 = 0; + + if (res < 0 && res2 < 0) + return res; + return 0; +} + +static int wpa_driver_ralink_add_wep(struct wpa_driver_ralink_data *drv, + int pairwise, int key_idx, int set_tx, + const u8 *key, size_t key_len) +{ + NDIS_802_11_WEP *wep; + size_t len; + int res; + + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); + + len = 12 + key_len; + wep = os_zalloc(len); + if (wep == NULL) + return -1; + + wep->Length = len; + wep->KeyIndex = key_idx; + + if (set_tx) + wep->KeyIndex |= 0x80000000; + + wep->KeyLength = key_len; + os_memcpy(wep->KeyMaterial, key, key_len); + + wpa_hexdump_key(MSG_MSGDUMP, "RALINK: OID_802_11_ADD_WEP", + (const u8 *) wep, len); + res = ralink_set_oid(drv, OID_802_11_ADD_WEP, (char *) wep, len); + + os_free(wep); + + return res; +} + +static int wpa_driver_ralink_set_key(const char *ifname, void *priv, + enum 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_ralink_data *drv = priv; + size_t len, i; + NDIS_802_11_KEY *nkey; + int res, pairwise; + u8 bssid[ETH_ALEN]; + + if (drv->g_driver_down == 1) + return -1; + + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); + + drv->bAddWepKey = FALSE; + + if (addr == NULL || is_broadcast_ether_addr(addr)) { + /* Group Key */ + pairwise = 0; + wpa_driver_ralink_get_bssid(drv, bssid); + } else { + /* Pairwise Key */ + pairwise = 1; + os_memcpy(bssid, addr, ETH_ALEN); + } + + if (alg == WPA_ALG_NONE || key_len == 0) { + return wpa_driver_ralink_remove_key(drv, key_idx, addr, bssid, + pairwise); + } + + if (alg == WPA_ALG_WEP) { + drv->bAddWepKey = TRUE; + return wpa_driver_ralink_add_wep(drv, pairwise, key_idx, + set_tx, key, key_len); + } + + len = 12 + 6 + 6 + 8 + key_len; + + nkey = os_zalloc(len); + if (nkey == NULL) + return -1; + + nkey->Length = len; + nkey->KeyIndex = key_idx; + + if (set_tx) + nkey->KeyIndex |= 1 << 31; + + if (pairwise) + nkey->KeyIndex |= 1 << 30; + + if (seq && seq_len) + nkey->KeyIndex |= 1 << 29; + + nkey->KeyLength = key_len; + os_memcpy(nkey->BSSID, bssid, ETH_ALEN); + + if (seq && seq_len) { + for (i = 0; i < seq_len; i++) + nkey->KeyRSC |= seq[i] << (i * 8); + } + if (alg == WPA_ALG_TKIP && key_len == 32) { + os_memcpy(nkey->KeyMaterial, key, 16); + os_memcpy(nkey->KeyMaterial + 16, key + 24, 8); + os_memcpy(nkey->KeyMaterial + 24, key + 16, 8); + } else { + os_memcpy(nkey->KeyMaterial, key, key_len); + } + + 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); + + wpa_hexdump_key(MSG_MSGDUMP, "RALINK: OID_802_11_ADD_KEY", + (const u8 *) nkey, len); + res = ralink_set_oid(drv, OID_802_11_ADD_KEY, (char *) nkey, len); + os_free(nkey); + + return res; +} + +static int wpa_driver_ralink_disassociate(void *priv, const u8 *addr, + int reason_code) +{ + struct wpa_driver_ralink_data *drv = priv; + + if (drv->g_driver_down == 1) + return -1; + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); + if (ralink_set_oid(drv, OID_802_11_DISASSOCIATE, " ", 4) < 0) { + wpa_printf(MSG_DEBUG, "RALINK: Failed to set " + "OID_802_11_DISASSOCIATE"); + } + + return 0; +} + +static int wpa_driver_ralink_deauthenticate(void *priv, const u8 *addr, + int reason_code) +{ + struct wpa_driver_ralink_data *drv = priv; + + wpa_printf(MSG_DEBUG, "g_driver_down = %d", drv->g_driver_down); + + if (drv->g_driver_down == 1) + return -1; + + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); + if (ralink_get_new_driver_flag(drv) == 0) { + return wpa_driver_ralink_disassociate(priv, addr, reason_code); + } else { + MLME_DEAUTH_REQ_STRUCT mlme; + os_memset(&mlme, 0, sizeof(MLME_DEAUTH_REQ_STRUCT)); + mlme.Reason = reason_code; + os_memcpy(mlme.Addr, addr, MAC_ADDR_LEN); + return ralink_set_oid(drv, OID_802_11_DEAUTHENTICATION, + (char *) &mlme, + sizeof(MLME_DEAUTH_REQ_STRUCT)); + } +} + +static int wpa_driver_ralink_set_gen_ie(void *priv, const u8 *ie, + size_t ie_len) +{ + struct wpa_driver_ralink_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.data.pointer = (caddr_t) ie; + iwr.u.data.length = ie_len; + + wpa_hexdump(MSG_DEBUG, "wpa_driver_ralink_set_gen_ie: ", + (u8 *) ie, ie_len); + + if (ioctl(drv->ioctl_sock, SIOCSIWGENIE, &iwr) < 0) { + perror("ioctl[SIOCSIWGENIE]"); + ret = -1; + } + + return ret; +} + +static int +wpa_driver_ralink_associate(void *priv, + struct wpa_driver_associate_params *params) +{ + struct wpa_driver_ralink_data *drv = priv; + + NDIS_802_11_NETWORK_INFRASTRUCTURE mode; + NDIS_802_11_AUTHENTICATION_MODE auth_mode; + NDIS_802_11_WEP_STATUS encr; + BOOLEAN ieee8021xMode; + BOOLEAN ieee8021x_required_key = TRUE; + + if (drv->g_driver_down == 1) + return -1; + wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); + + if (params->mode == IEEE80211_MODE_IBSS) + mode = Ndis802_11IBSS; + else + mode = Ndis802_11Infrastructure; + + if (ralink_set_oid(drv, OID_802_11_INFRASTRUCTURE_MODE, + (char *) &mode, sizeof(mode)) < 0) { + wpa_printf(MSG_DEBUG, "RALINK: Failed to set " + "OID_802_11_INFRASTRUCTURE_MODE (%d)", + (int) mode); + /* Try to continue anyway */ + } + + if (params->key_mgmt_suite == KEY_MGMT_WPS) { + UCHAR enable_wps = 0x80; + /* trigger driver support wpa_supplicant */ + if (ralink_set_oid(drv, RT_OID_WPA_SUPPLICANT_SUPPORT, + (PCHAR) &enable_wps, sizeof(UCHAR)) < 0) { + wpa_printf(MSG_INFO, "RALINK: Failed to set " + "RT_OID_WPA_SUPPLICANT_SUPPORT (%d)", + (int) enable_wps); + } + + wpa_driver_ralink_set_gen_ie(priv, params->wpa_ie, + params->wpa_ie_len); + + ralink_set_auth_mode(drv, Ndis802_11AuthModeOpen); + + ralink_set_encr_type(drv, Ndis802_11EncryptionDisabled); + } else { +#ifdef CONFIG_WPS + UCHAR enable_wpa_supplicant; + + if (drv->ap_scan == 1) + enable_wpa_supplicant = 0x01; + else + enable_wpa_supplicant = 0x02; + + /* trigger driver support wpa_supplicant */ + if (ralink_set_oid(drv, RT_OID_WPA_SUPPLICANT_SUPPORT, + (PCHAR) &enable_wpa_supplicant, + sizeof(UCHAR)) < 0) { + wpa_printf(MSG_DEBUG, "RALINK: Failed to set " + "RT_OID_WPA_SUPPLICANT_SUPPORT (%d)", + (int) enable_wpa_supplicant); + } + + wpa_driver_ralink_set_gen_ie(priv, (u8 *) "", 0); +#endif /* CONFIG_WPS */ + + if (params->wpa_ie == NULL || params->wpa_ie_len == 0) { + if (params->auth_alg & WPA_AUTH_ALG_SHARED) { + if (params->auth_alg & WPA_AUTH_ALG_OPEN) + auth_mode = Ndis802_11AuthModeAutoSwitch; + else + auth_mode = Ndis802_11AuthModeShared; + } else + auth_mode = Ndis802_11AuthModeOpen; + } else if (params->wpa_ie[0] == WLAN_EID_RSN) { + if (params->key_mgmt_suite == KEY_MGMT_PSK) + auth_mode = Ndis802_11AuthModeWPA2PSK; + else + auth_mode = Ndis802_11AuthModeWPA2; + } else { + if (params->key_mgmt_suite == KEY_MGMT_WPA_NONE) + auth_mode = Ndis802_11AuthModeWPANone; + else if (params->key_mgmt_suite == KEY_MGMT_PSK) + auth_mode = Ndis802_11AuthModeWPAPSK; + else + auth_mode = Ndis802_11AuthModeWPA; + } + + switch (params->pairwise_suite) { + case CIPHER_CCMP: + encr = Ndis802_11Encryption3Enabled; + break; + case CIPHER_TKIP: + encr = Ndis802_11Encryption2Enabled; + break; + case CIPHER_WEP40: + case CIPHER_WEP104: + encr = Ndis802_11Encryption1Enabled; + break; + case CIPHER_NONE: + if (params->group_suite == CIPHER_CCMP) + encr = Ndis802_11Encryption3Enabled; + else if (params->group_suite == CIPHER_TKIP) + encr = Ndis802_11Encryption2Enabled; + else + encr = Ndis802_11EncryptionDisabled; + break; + default: + encr = Ndis802_11EncryptionDisabled; + break; + } + + ralink_set_auth_mode(drv, auth_mode); + + /* notify driver that IEEE8021x mode is enabled */ + if (params->key_mgmt_suite == KEY_MGMT_802_1X_NO_WPA) { + ieee8021xMode = TRUE; + if (drv->bAddWepKey) + ieee8021x_required_key = FALSE; + } else + ieee8021xMode = FALSE; + + if (ralink_set_oid(drv, OID_802_11_SET_IEEE8021X_REQUIRE_KEY, + (char *) &ieee8021x_required_key, + sizeof(BOOLEAN)) < 0) { + wpa_printf(MSG_DEBUG, "ERROR: Failed to set " + "OID_802_11_SET_IEEE8021X_REQUIRE_KEY(%d)", + (int) ieee8021x_required_key); + } else { + wpa_printf(MSG_DEBUG, "ieee8021x_required_key is %s", + ieee8021x_required_key ? "TRUE" : "FALSE"); + } + + if (ralink_set_oid(drv, OID_802_11_SET_IEEE8021X, + (char *) &ieee8021xMode, sizeof(BOOLEAN)) < + 0) { + wpa_printf(MSG_DEBUG, "RALINK: Failed to set " + "OID_802_11_SET_IEEE8021X(%d)", + (int) ieee8021xMode); + } + + ralink_set_encr_type(drv, encr); + + if ((ieee8021xMode == FALSE) && + (encr == Ndis802_11Encryption1Enabled)) { + /* static WEP */ + int enabled = 0; + if (ralink_set_oid(drv, OID_802_11_DROP_UNENCRYPTED, + (char *) &enabled, sizeof(enabled)) + < 0) { + wpa_printf(MSG_DEBUG, "RALINK: Failed to set " + "OID_802_11_DROP_UNENCRYPTED(%d)", + (int) encr); + } + } + } + + return wpa_driver_ralink_set_ssid(drv, params->ssid, params->ssid_len); +} + +static int +wpa_driver_ralink_set_countermeasures(void *priv, int enabled) +{ + struct wpa_driver_ralink_data *drv = priv; + if (drv->g_driver_down == 1) + return -1; + wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled); + return ralink_set_oid(drv, OID_SET_COUNTERMEASURES, (char *) &enabled, + sizeof(int)); +} + +const struct wpa_driver_ops wpa_driver_ralink_ops = { + .name = "ralink", + .desc = "Ralink Wireless Client driver", + .get_bssid = wpa_driver_ralink_get_bssid, + .get_ssid = wpa_driver_ralink_get_ssid, + .set_key = wpa_driver_ralink_set_key, + .init = wpa_driver_ralink_init, + .deinit = wpa_driver_ralink_deinit, + .set_countermeasures = wpa_driver_ralink_set_countermeasures, + .scan2 = wpa_driver_ralink_scan, + .get_scan_results2 = wpa_driver_ralink_get_scan_results, + .deauthenticate = wpa_driver_ralink_deauthenticate, + .disassociate = wpa_driver_ralink_disassociate, + .associate = wpa_driver_ralink_associate, + .add_pmkid = wpa_driver_ralink_add_pmkid, + .remove_pmkid = wpa_driver_ralink_remove_pmkid, + .flush_pmkid = wpa_driver_ralink_flush_pmkid, +}; diff --git a/src/drivers/driver_ralink.h b/src/drivers/driver_ralink.h new file mode 100644 index 0000000..d13df28 --- /dev/null +++ b/src/drivers/driver_ralink.h @@ -0,0 +1,383 @@ +/* + * WPA Supplicant - driver_ralink exported functions + * Copyright (c) 2003-2005, Jouni Malinen + * Copyright (c) 2007, Snowpin Lee + * + * 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. + */ + +// Ralink defined OIDs +#if WIRELESS_EXT <= 11 +#ifndef SIOCDEVPRIVATE +#define SIOCDEVPRIVATE 0x8BE0 +#endif +#define SIOCIWFIRSTPRIV SIOCDEVPRIVATE +#endif + +#define RT_PRIV_IOCTL (SIOCIWFIRSTPRIV + 0x0E) +#define RTPRIV_IOCTL_SET (SIOCIWFIRSTPRIV + 0x02) + +// IEEE 802.11 OIDs & Ralink defined OIDs ****** + +// (RaConfig Set/QueryInform) ==> +#define OID_GET_SET_TOGGLE 0x8000 + +#define OID_802_11_ADD_WEP 0x0112 +#define OID_802_11_REMOVE_WEP 0x0113 +#define OID_802_11_DISASSOCIATE 0x0114 +#define OID_802_11_PRIVACY_FILTER 0x0118 +#define OID_802_11_ASSOCIATION_INFORMATION 0x011E +#define OID_802_11_BSSID_LIST_SCAN 0x0508 +#define OID_802_11_SSID 0x0509 +#define OID_802_11_BSSID 0x050A +#define OID_802_11_WEP_STATUS 0x0510 +#define OID_802_11_AUTHENTICATION_MODE 0x0511 +#define OID_802_11_INFRASTRUCTURE_MODE 0x0512 +#define OID_802_11_TX_POWER_LEVEL 0x0517 +#define OID_802_11_REMOVE_KEY 0x0519 +#define OID_802_11_ADD_KEY 0x0520 +#define OID_802_11_DEAUTHENTICATION 0x0526 +#define OID_802_11_DROP_UNENCRYPTED 0x0527 +#define OID_802_11_BSSID_LIST 0x0609 +#define OID_802_3_CURRENT_ADDRESS 0x060A +#define OID_SET_COUNTERMEASURES 0x0616 +#define OID_802_11_SET_IEEE8021X 0x0617 // For IEEE8021x mode +#define OID_802_11_SET_IEEE8021X_REQUIRE_KEY 0x0618 // For DynamicWEP in IEEE802.1x mode +#define OID_802_11_PMKID 0x0620 +#define RT_OID_WPA_SUPPLICANT_SUPPORT 0x0621 // for trigger driver enable/disable wpa_supplicant support +#define RT_OID_WE_VERSION_COMPILED 0x0622 +#define RT_OID_NEW_DRIVER 0x0623 +#define RT_OID_WPS_PROBE_REQ_IE 0x0625 + +#define PACKED __attribute__ ((packed)) + +//wpa_supplicant event flags +#define RT_ASSOC_EVENT_FLAG 0x0101 +#define RT_DISASSOC_EVENT_FLAG 0x0102 +#define RT_REQIE_EVENT_FLAG 0x0103 +#define RT_RESPIE_EVENT_FLAG 0x0104 +#define RT_ASSOCINFO_EVENT_FLAG 0x0105 +#define RT_PMKIDCAND_FLAG 0x0106 +#define RT_INTERFACE_DOWN 0x0107 +#define RT_INTERFACE_UP 0x0108 + +// +// IEEE 802.11 Structures and definitions +// +// new types for Media Specific Indications + +#ifndef ULONG +#define CHAR char +#define INT int +#define SHORT int +#define UINT u32 +#undef ULONG +//#define ULONG u32 +#define ULONG unsigned long /* 32-bit in 32-bit CPU or 64-bit in 64-bit CPU */ +#define USHORT unsigned short +#define UCHAR unsigned char + +#define uint32 u32 +#define uint8 u8 + + +#define BOOLEAN u8 +//#define LARGE_INTEGER s64 +#define VOID void +#define LONG long +#define LONGLONG s64 +#define ULONGLONG u64 +typedef VOID *PVOID; +typedef CHAR *PCHAR; +typedef UCHAR *PUCHAR; +typedef USHORT *PUSHORT; +typedef LONG *PLONG; +typedef ULONG *PULONG; + +typedef union _LARGE_INTEGER { + struct { + ULONG LowPart; + LONG HighPart; + }vv; + struct { + ULONG LowPart; + LONG HighPart; + } u; + s64 QuadPart; +} LARGE_INTEGER; + +#endif + +#define NDIS_802_11_LENGTH_SSID 32 +#define NDIS_802_11_LENGTH_RATES 8 +#define NDIS_802_11_LENGTH_RATES_EX 16 +#define MAX_LEN_OF_SSID 32 +#define MAC_ADDR_LEN 6 + +typedef UCHAR NDIS_802_11_MAC_ADDRESS[6]; + +// mask for authentication/integrity fields +#define NDIS_802_11_AUTH_REQUEST_AUTH_FIELDS 0x0f + +#define NDIS_802_11_AUTH_REQUEST_REAUTH 0x01 +#define NDIS_802_11_AUTH_REQUEST_KEYUPDATE 0x02 +#define NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR 0x06 +#define NDIS_802_11_AUTH_REQUEST_GROUP_ERROR 0x0E + +// Added new types for OFDM 5G and 2.4G +typedef enum _NDIS_802_11_NETWORK_TYPE +{ + Ndis802_11FH, + Ndis802_11DS, + Ndis802_11OFDM5, + Ndis802_11OFDM24, + Ndis802_11Automode, + Ndis802_11NetworkTypeMax // not a real type, defined as an upper bound +} NDIS_802_11_NETWORK_TYPE, *PNDIS_802_11_NETWORK_TYPE; + +// +// Received Signal Strength Indication +// +typedef LONG NDIS_802_11_RSSI; // in dBm + +typedef struct _NDIS_802_11_CONFIGURATION_FH +{ + ULONG Length; // Length of structure + ULONG HopPattern; // As defined by 802.11, MSB set + ULONG HopSet; // to one if non-802.11 + ULONG DwellTime; // units are Kusec +} NDIS_802_11_CONFIGURATION_FH, *PNDIS_802_11_CONFIGURATION_FH; + +typedef struct _NDIS_802_11_CONFIGURATION +{ + ULONG Length; // Length of structure + ULONG BeaconPeriod; // units are Kusec + ULONG ATIMWindow; // units are Kusec + ULONG DSConfig; // Frequency, units are kHz + NDIS_802_11_CONFIGURATION_FH FHConfig; +} NDIS_802_11_CONFIGURATION, *PNDIS_802_11_CONFIGURATION; + +typedef ULONG NDIS_802_11_KEY_INDEX; +typedef ULONGLONG NDIS_802_11_KEY_RSC; + +// Key mapping keys require a BSSID +typedef struct _NDIS_802_11_KEY +{ + UINT Length; // Length of this structure + UINT KeyIndex; + UINT KeyLength; // length of key in bytes + NDIS_802_11_MAC_ADDRESS BSSID; + NDIS_802_11_KEY_RSC KeyRSC; + UCHAR KeyMaterial[1]; // variable length depending on above field +} NDIS_802_11_KEY, *PNDIS_802_11_KEY; + +typedef struct _NDIS_802_11_REMOVE_KEY +{ + UINT Length; // Length of this structure + UINT KeyIndex; + NDIS_802_11_MAC_ADDRESS BSSID; +} NDIS_802_11_REMOVE_KEY, *PNDIS_802_11_REMOVE_KEY; + +typedef struct PACKED _NDIS_802_11_WEP +{ + UINT Length; // Length of this structure + UINT KeyIndex; // 0 is the per-client key, 1-N are the + // global keys + UINT KeyLength; // length of key in bytes + UCHAR KeyMaterial[1];// variable length depending on above field +} NDIS_802_11_WEP, *PNDIS_802_11_WEP; + + +typedef enum _NDIS_802_11_NETWORK_INFRASTRUCTURE +{ + Ndis802_11IBSS, + Ndis802_11Infrastructure, + Ndis802_11AutoUnknown, + Ndis802_11InfrastructureMax // Not a real value, defined as upper bound +} NDIS_802_11_NETWORK_INFRASTRUCTURE, *PNDIS_802_11_NETWORK_INFRASTRUCTURE; + +// PMKID Structures +typedef UCHAR NDIS_802_11_PMKID_VALUE[16]; + +typedef struct _BSSID_INFO +{ + NDIS_802_11_MAC_ADDRESS BSSID; + NDIS_802_11_PMKID_VALUE PMKID; +} BSSID_INFO, *PBSSID_INFO; + +typedef struct _NDIS_802_11_PMKID +{ + ULONG Length; + ULONG BSSIDInfoCount; + BSSID_INFO BSSIDInfo[1]; +} NDIS_802_11_PMKID, *PNDIS_802_11_PMKID; + +//Added new types for PMKID Candidate lists. +typedef struct _PMKID_CANDIDATE { + NDIS_802_11_MAC_ADDRESS BSSID; + ULONG Flags; +} PMKID_CANDIDATE, *PPMKID_CANDIDATE; + +typedef struct _NDIS_802_11_PMKID_CANDIDATE_LIST +{ + ULONG Version; // Version of the structure + ULONG NumCandidates; // No. of pmkid candidates + PMKID_CANDIDATE CandidateList[1]; +} NDIS_802_11_PMKID_CANDIDATE_LIST, *PNDIS_802_11_PMKID_CANDIDATE_LIST; + +//Flags for PMKID Candidate list structure +#define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01 + +// Add new authentication modes +typedef enum _NDIS_802_11_AUTHENTICATION_MODE +{ + Ndis802_11AuthModeOpen, + Ndis802_11AuthModeShared, + Ndis802_11AuthModeAutoSwitch, + Ndis802_11AuthModeWPA, + Ndis802_11AuthModeWPAPSK, + Ndis802_11AuthModeWPANone, + Ndis802_11AuthModeWPA2, + Ndis802_11AuthModeWPA2PSK, + Ndis802_11AuthModeMax // Not a real mode, defined as upper bound +} NDIS_802_11_AUTHENTICATION_MODE, *PNDIS_802_11_AUTHENTICATION_MODE; + +typedef UCHAR NDIS_802_11_RATES[NDIS_802_11_LENGTH_RATES]; // Set of 8 data rates +typedef UCHAR NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX]; // Set of 16 data rates + +typedef struct PACKED _NDIS_802_11_SSID +{ + INT SsidLength; // length of SSID field below, in bytes; + // this can be zero. + UCHAR Ssid[NDIS_802_11_LENGTH_SSID]; // SSID information field +} NDIS_802_11_SSID, *PNDIS_802_11_SSID; + + +typedef struct PACKED _NDIS_WLAN_BSSID +{ + ULONG Length; // Length of this structure + NDIS_802_11_MAC_ADDRESS MacAddress; // BSSID + UCHAR Reserved[2]; + NDIS_802_11_SSID Ssid; // SSID + ULONG Privacy; // WEP encryption requirement + NDIS_802_11_RSSI Rssi; // receive signal + // strength in dBm + NDIS_802_11_NETWORK_TYPE NetworkTypeInUse; + NDIS_802_11_CONFIGURATION Configuration; + NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode; + NDIS_802_11_RATES SupportedRates; +} NDIS_WLAN_BSSID, *PNDIS_WLAN_BSSID; + +typedef struct PACKED _NDIS_802_11_BSSID_LIST +{ + UINT NumberOfItems; // in list below, at least 1 + NDIS_WLAN_BSSID Bssid[1]; +} NDIS_802_11_BSSID_LIST, *PNDIS_802_11_BSSID_LIST; + +// Added Capabilities, IELength and IEs for each BSSID +typedef struct PACKED _NDIS_WLAN_BSSID_EX +{ + ULONG Length; // Length of this structure + NDIS_802_11_MAC_ADDRESS MacAddress; // BSSID + UCHAR Reserved[2]; + NDIS_802_11_SSID Ssid; // SSID + UINT Privacy; // WEP encryption requirement + NDIS_802_11_RSSI Rssi; // receive signal + // strength in dBm + NDIS_802_11_NETWORK_TYPE NetworkTypeInUse; + NDIS_802_11_CONFIGURATION Configuration; + NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode; + NDIS_802_11_RATES_EX SupportedRates; + ULONG IELength; + UCHAR IEs[1]; +} NDIS_WLAN_BSSID_EX, *PNDIS_WLAN_BSSID_EX; + +typedef struct PACKED _NDIS_802_11_BSSID_LIST_EX +{ + UINT NumberOfItems; // in list below, at least 1 + NDIS_WLAN_BSSID_EX Bssid[1]; +} NDIS_802_11_BSSID_LIST_EX, *PNDIS_802_11_BSSID_LIST_EX; + +typedef struct PACKED _NDIS_802_11_FIXED_IEs +{ + UCHAR Timestamp[8]; + USHORT BeaconInterval; + USHORT Capabilities; +} NDIS_802_11_FIXED_IEs, *PNDIS_802_11_FIXED_IEs; + +// Added new encryption types +// Also aliased typedef to new name +typedef enum _NDIS_802_11_WEP_STATUS +{ + Ndis802_11WEPEnabled, + Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled, + Ndis802_11WEPDisabled, + Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled, + Ndis802_11WEPKeyAbsent, + Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent, + Ndis802_11WEPNotSupported, + Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported, + Ndis802_11Encryption2Enabled, + Ndis802_11Encryption2KeyAbsent, + Ndis802_11Encryption3Enabled, + Ndis802_11Encryption3KeyAbsent +} NDIS_802_11_WEP_STATUS, *PNDIS_802_11_WEP_STATUS, + NDIS_802_11_ENCRYPTION_STATUS, *PNDIS_802_11_ENCRYPTION_STATUS; + +typedef enum _NDIS_802_11_RELOAD_DEFAULTS +{ + Ndis802_11ReloadWEPKeys +} NDIS_802_11_RELOAD_DEFAULTS, *PNDIS_802_11_RELOAD_DEFAULTS; + +#define NDIS_802_11_AI_REQFI_CAPABILITIES 1 +#define NDIS_802_11_AI_REQFI_LISTENINTERVAL 2 +#define NDIS_802_11_AI_REQFI_CURRENTAPADDRESS 4 + +#define NDIS_802_11_AI_RESFI_CAPABILITIES 1 +#define NDIS_802_11_AI_RESFI_STATUSCODE 2 +#define NDIS_802_11_AI_RESFI_ASSOCIATIONID 4 + +typedef struct _NDIS_802_11_AI_REQFI +{ + USHORT Capabilities; + USHORT ListenInterval; + NDIS_802_11_MAC_ADDRESS CurrentAPAddress; +} NDIS_802_11_AI_REQFI, *PNDIS_802_11_AI_REQFI; + +typedef struct _NDIS_802_11_AI_RESFI +{ + USHORT Capabilities; + USHORT StatusCode; + USHORT AssociationId; +} NDIS_802_11_AI_RESFI, *PNDIS_802_11_AI_RESFI; + +typedef struct _NDIS_802_11_ASSOCIATION_INFORMATION +{ + ULONG Length; + USHORT AvailableRequestFixedIEs; + NDIS_802_11_AI_REQFI RequestFixedIEs; + ULONG RequestIELength; + ULONG OffsetRequestIEs; + USHORT AvailableResponseFixedIEs; + NDIS_802_11_AI_RESFI ResponseFixedIEs; + ULONG ResponseIELength; + ULONG OffsetResponseIEs; +} NDIS_802_11_ASSOCIATION_INFORMATION, *PNDIS_802_11_ASSOCIATION_INFORMATION; + +struct ndis_pmkid_entry { + struct ndis_pmkid_entry *next; + u8 bssid[ETH_ALEN]; + u8 pmkid[16]; +}; + +typedef struct _MLME_DEAUTH_REQ_STRUCT { + UCHAR Addr[MAC_ADDR_LEN]; + USHORT Reason; +} MLME_DEAUTH_REQ_STRUCT, *PMLME_DEAUTH_REQ_STRUCT; diff --git a/src/drivers/driver_test.c b/src/drivers/driver_test.c index f8e314b..74dedb2 100644 --- a/src/drivers/driver_test.c +++ b/src/drivers/driver_test.c @@ -309,7 +309,7 @@ static int test_driver_send_ether(void *priv, const u8 *dst, const u8 *src, static int wpa_driver_test_send_mlme(void *priv, const u8 *data, - size_t data_len, int noack) + size_t data_len) { struct test_driver_bss *dbss = priv; struct wpa_driver_test_data *drv = dbss->drv; @@ -2705,7 +2705,7 @@ static int wpa_driver_test_send_action(void *priv, unsigned int freq, os_memcpy(hdr->addr2, src, ETH_ALEN); os_memcpy(hdr->addr3, bssid, ETH_ALEN); - ret = wpa_driver_test_send_mlme(priv, buf, 24 + data_len, 0); + ret = wpa_driver_test_send_mlme(priv, buf, 24 + data_len); os_free(buf); return ret; } @@ -2832,7 +2832,7 @@ static int wpa_driver_test_p2p_find(void *priv, unsigned int timeout, int type) wpa_printf(MSG_DEBUG, "%s(timeout=%u)", __func__, timeout); if (!drv->p2p) return -1; - return p2p_find(drv->p2p, timeout, type, 0, NULL); + return p2p_find(drv->p2p, timeout, type, 0, NULL, NULL); } @@ -2918,7 +2918,7 @@ static int wpa_driver_test_p2p_set_params(void *priv, static int test_p2p_scan(void *ctx, enum p2p_scan_type type, int freq, unsigned int num_req_dev_types, - const u8 *req_dev_types) + const u8 *req_dev_types, const u8 *dev_id) { struct wpa_driver_test_data *drv = ctx; struct wpa_driver_scan_params params; @@ -2956,7 +2956,7 @@ static int test_p2p_scan(void *ctx, enum p2p_scan_type type, int freq, wpabuf_put_buf(ies, wps_ie); wpabuf_free(wps_ie); - p2p_scan_ie(drv->p2p, ies); + p2p_scan_ie(drv->p2p, ies, dev_id); params.extra_ies = wpabuf_head(ies); params.extra_ies_len = wpabuf_len(ies); diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c index c11ee75..53bd7ce 100644 --- a/src/drivers/driver_wext.c +++ b/src/drivers/driver_wext.c @@ -25,7 +25,7 @@ #include #include -#include "linux_wext.h" +#include "wireless_copy.h" #include "common.h" #include "eloop.h" #include "common/ieee802_11_defs.h" @@ -37,9 +37,6 @@ #include "driver.h" #include "driver_wext.h" -#ifdef ANDROID -#include "android_drv.h" -#endif /* ANDROID */ static int wpa_driver_wext_flush_pmkid(void *priv); static int wpa_driver_wext_get_range(void *priv); @@ -305,14 +302,6 @@ wpa_driver_wext_event_wireless_custom(void *ctx, char *custom) } wpa_supplicant_event(ctx, EVENT_STKSTART, &data); #endif /* CONFIG_PEERKEY */ -#ifdef ANDROID - } else if (os_strncmp(custom, "STOP", 4) == 0) { - wpa_msg(ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STOPPED"); - } else if (os_strncmp(custom, "START", 5) == 0) { - wpa_msg(ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STARTED"); - } else if (os_strncmp(custom, "HANG", 4) == 0) { - wpa_msg(ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED"); -#endif /* ANDROID */ } } @@ -575,10 +564,28 @@ static void wpa_driver_wext_event_link(struct wpa_driver_wext_data *drv, del ? "removed" : "added"); if (os_strcmp(drv->ifname, event.interface_status.ifname) == 0) { - if (del) + if (del) { + if (drv->if_removed) { + wpa_printf(MSG_DEBUG, "WEXT: if_removed " + "already set - ignore event"); + return; + } drv->if_removed = 1; - else + } else { + if (if_nametoindex(drv->ifname) == 0) { + wpa_printf(MSG_DEBUG, "WEXT: Interface %s " + "does not exist - ignore " + "RTM_NEWLINK", + drv->ifname); + return; + } + if (!drv->if_removed) { + wpa_printf(MSG_DEBUG, "WEXT: if_removed " + "already cleared - ignore event"); + return; + } drv->if_removed = 0; + } } wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event); @@ -634,6 +641,7 @@ static void wpa_driver_wext_event_rtm_newlink(void *ctx, struct ifinfomsg *ifi, struct wpa_driver_wext_data *drv = ctx; int attrlen, rta_len; struct rtattr *attr; + char namebuf[IFNAMSIZ]; if (!wpa_driver_wext_own_ifindex(drv, ifi->ifi_index, buf, len)) { wpa_printf(MSG_DEBUG, "Ignore event for foreign ifindex %d", @@ -656,9 +664,25 @@ static void wpa_driver_wext_event_rtm_newlink(void *ctx, struct ifinfomsg *ifi, } if (drv->if_disabled && (ifi->ifi_flags & IFF_UP)) { - wpa_printf(MSG_DEBUG, "WEXT: Interface up"); - drv->if_disabled = 0; - wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED, NULL); + if (if_indextoname(ifi->ifi_index, namebuf) && + linux_iface_up(drv->ioctl_sock, drv->ifname) == 0) { + wpa_printf(MSG_DEBUG, "WEXT: Ignore interface up " + "event since interface %s is down", + namebuf); + } else if (if_nametoindex(drv->ifname) == 0) { + wpa_printf(MSG_DEBUG, "WEXT: Ignore interface up " + "event since interface %s does not exist", + drv->ifname); + } else if (drv->if_removed) { + wpa_printf(MSG_DEBUG, "WEXT: Ignore interface up " + "event since interface %s is marked " + "removed", drv->ifname); + } else { + wpa_printf(MSG_DEBUG, "WEXT: Interface up"); + drv->if_disabled = 0; + wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED, + NULL); + } } /* @@ -831,12 +855,6 @@ void * wpa_driver_wext_init(void *ctx, const char *ifname) drv->mlme_sock = -1; -#ifdef ANDROID - drv->errors = 0; - drv->driver_is_started = TRUE; - drv->bgscan_enabled = 0; -#endif /* ANDROID */ - if (wpa_driver_wext_finish_drv_init(drv) < 0) goto err3; @@ -2330,129 +2348,6 @@ static const char * wext_get_radio_name(void *priv) } -#ifdef ANDROID - -static int android_wext_cmd(struct wpa_driver_wext_data *drv, const char *cmd) -{ - struct iwreq iwr; - char buf[MAX_DRV_CMD_SIZE]; - int ret; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - - os_memset(buf, 0, sizeof(buf)); - os_strlcpy(buf, cmd, sizeof(buf)); - - iwr.u.data.pointer = buf; - iwr.u.data.length = sizeof(buf); - - ret = ioctl(drv->ioctl_sock, SIOCSIWPRIV, &iwr); - - if (ret < 0) { - wpa_printf(MSG_ERROR, "%s failed (%d): %s", __func__, ret, - cmd); - drv->errors++; - if (drv->errors > DRV_NUMBER_SEQUENTIAL_ERRORS) { - drv->errors = 0; - wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE - "HANGED"); - } - return ret; - } - - drv->errors = 0; - return 0; -} - - -static int wext_sched_scan(void *priv, struct wpa_driver_scan_params *params, - u32 interval) -{ - struct wpa_driver_wext_data *drv = priv; - struct iwreq iwr; - int ret = 0, i = 0, bp; - char buf[WEXT_PNO_MAX_COMMAND_SIZE]; - - bp = WEXT_PNOSETUP_HEADER_SIZE; - os_memcpy(buf, WEXT_PNOSETUP_HEADER, bp); - buf[bp++] = WEXT_PNO_TLV_PREFIX; - buf[bp++] = WEXT_PNO_TLV_VERSION; - buf[bp++] = WEXT_PNO_TLV_SUBVERSION; - buf[bp++] = WEXT_PNO_TLV_RESERVED; - - while (i < WEXT_PNO_AMOUNT && (size_t) i < params->num_ssids) { - /* - * Check that there is enough space needed for 1 more SSID, the - * other sections and null termination. - */ - if ((bp + WEXT_PNO_SSID_HEADER_SIZE + IW_ESSID_MAX_SIZE + - WEXT_PNO_NONSSID_SECTIONS_SIZE + 1) >= (int) sizeof(buf)) - break; - - wpa_hexdump_ascii(MSG_DEBUG, "For PNO Scan", - params->ssids[i].ssid, - params->ssids[i].ssid_len); - buf[bp++] = WEXT_PNO_SSID_SECTION; - buf[bp++] = params->ssids[i].ssid_len; - os_memcpy(&buf[bp], params->ssids[i].ssid, - params->ssids[i].ssid_len); - bp += params->ssids[i].ssid_len; - i++; - } - - buf[bp++] = WEXT_PNO_SCAN_INTERVAL_SECTION; - /* TODO: consider using interval parameter (interval in msec) instead - * of hardcoded value here */ - os_snprintf(&buf[bp], WEXT_PNO_SCAN_INTERVAL_LENGTH + 1, "%x", - WEXT_PNO_SCAN_INTERVAL); - bp += WEXT_PNO_SCAN_INTERVAL_LENGTH; - - buf[bp++] = WEXT_PNO_REPEAT_SECTION; - os_snprintf(&buf[bp], WEXT_PNO_REPEAT_LENGTH + 1, "%x", - WEXT_PNO_REPEAT); - bp += WEXT_PNO_REPEAT_LENGTH; - - buf[bp++] = WEXT_PNO_MAX_REPEAT_SECTION; - os_snprintf(&buf[bp], WEXT_PNO_MAX_REPEAT_LENGTH + 1, "%x", - WEXT_PNO_MAX_REPEAT); - bp += WEXT_PNO_MAX_REPEAT_LENGTH + 1; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.data.pointer = buf; - iwr.u.data.length = bp; - - ret = ioctl(drv->ioctl_sock, SIOCSIWPRIV, &iwr); - if (ret < 0) { - wpa_printf(MSG_ERROR, "ioctl[SIOCSIWPRIV] (pnosetup): %d", - ret); - drv->errors++; - if (drv->errors > DRV_NUMBER_SEQUENTIAL_ERRORS) { - drv->errors = 0; - wpa_msg(drv->ctx, MSG_INFO, - WPA_EVENT_DRIVER_STATE "HANGED"); - } - return ret; - } - - drv->errors = 0; - drv->bgscan_enabled = 1; - - return android_wext_cmd(drv, "PNOFORCE 1"); -} - - -static int wext_stop_sched_scan(void *priv) -{ - struct wpa_driver_wext_data *drv = priv; - drv->bgscan_enabled = 0; - return android_wext_cmd(drv, "PNOFORCE 0"); -} - -#endif /* ANDROID */ - - const struct wpa_driver_ops wpa_driver_wext_ops = { .name = "wext", .desc = "Linux wireless extensions (generic)", @@ -2473,8 +2368,4 @@ const struct wpa_driver_ops wpa_driver_wext_ops = { .get_capa = wpa_driver_wext_get_capa, .set_operstate = wpa_driver_wext_set_operstate, .get_radio_name = wext_get_radio_name, -#ifdef ANDROID - .sched_scan = wext_sched_scan, - .stop_sched_scan = wext_stop_sched_scan, -#endif /* ANDROID */ }; diff --git a/src/drivers/driver_wext.h b/src/drivers/driver_wext.h index 8bcbee6..89c13eb 100644 --- a/src/drivers/driver_wext.h +++ b/src/drivers/driver_wext.h @@ -50,12 +50,6 @@ struct wpa_driver_wext_data { int cfg80211; /* whether driver is using cfg80211 */ u8 max_level; - -#ifdef ANDROID - int errors; - int driver_is_started; - int bgscan_enabled; -#endif /* ANDROID */ }; int wpa_driver_wext_get_bssid(void *priv, u8 *bssid); diff --git a/src/drivers/drivers.c b/src/drivers/drivers.c index 667ea22..b710778 100644 --- a/src/drivers/drivers.c +++ b/src/drivers/drivers.c @@ -27,6 +27,9 @@ extern struct wpa_driver_ops wpa_driver_hostap_ops; /* driver_hostap.c */ #ifdef CONFIG_DRIVER_MADWIFI extern struct wpa_driver_ops wpa_driver_madwifi_ops; /* driver_madwifi.c */ #endif /* CONFIG_DRIVER_MADWIFI */ +#ifdef CONFIG_DRIVER_BROADCOM +extern struct wpa_driver_ops wpa_driver_broadcom_ops; /* driver_broadcom.c */ +#endif /* CONFIG_DRIVER_BROADCOM */ #ifdef CONFIG_DRIVER_BSD extern struct wpa_driver_ops wpa_driver_bsd_ops; /* driver_bsd.c */ #endif /* CONFIG_DRIVER_BSD */ @@ -39,6 +42,15 @@ extern struct wpa_driver_ops wpa_driver_wired_ops; /* driver_wired.c */ #ifdef CONFIG_DRIVER_TEST extern struct wpa_driver_ops wpa_driver_test_ops; /* driver_test.c */ #endif /* CONFIG_DRIVER_TEST */ +#ifdef CONFIG_DRIVER_RALINK +extern struct wpa_driver_ops wpa_driver_ralink_ops; /* driver_ralink.c */ +#endif /* CONFIG_DRIVER_RALINK */ +#ifdef CONFIG_DRIVER_OSX +extern struct wpa_driver_ops wpa_driver_osx_ops; /* driver_osx.m */ +#endif /* CONFIG_DRIVER_OSX */ +#ifdef CONFIG_DRIVER_IPHONE +extern struct wpa_driver_ops wpa_driver_iphone_ops; /* driver_iphone.m */ +#endif /* CONFIG_DRIVER_IPHONE */ #ifdef CONFIG_DRIVER_ROBOSWITCH /* driver_roboswitch.c */ extern struct wpa_driver_ops wpa_driver_roboswitch_ops; @@ -65,6 +77,9 @@ struct wpa_driver_ops *wpa_drivers[] = #ifdef CONFIG_DRIVER_MADWIFI &wpa_driver_madwifi_ops, #endif /* CONFIG_DRIVER_MADWIFI */ +#ifdef CONFIG_DRIVER_BROADCOM + &wpa_driver_broadcom_ops, +#endif /* CONFIG_DRIVER_BROADCOM */ #ifdef CONFIG_DRIVER_BSD &wpa_driver_bsd_ops, #endif /* CONFIG_DRIVER_BSD */ @@ -77,6 +92,15 @@ struct wpa_driver_ops *wpa_drivers[] = #ifdef CONFIG_DRIVER_TEST &wpa_driver_test_ops, #endif /* CONFIG_DRIVER_TEST */ +#ifdef CONFIG_DRIVER_RALINK + &wpa_driver_ralink_ops, +#endif /* CONFIG_DRIVER_RALINK */ +#ifdef CONFIG_DRIVER_OSX + &wpa_driver_osx_ops, +#endif /* CONFIG_DRIVER_OSX */ +#ifdef CONFIG_DRIVER_IPHONE + &wpa_driver_iphone_ops, +#endif /* CONFIG_DRIVER_IPHONE */ #ifdef CONFIG_DRIVER_ROBOSWITCH &wpa_driver_roboswitch_ops, #endif /* CONFIG_DRIVER_ROBOSWITCH */ diff --git a/src/drivers/drivers.mak b/src/drivers/drivers.mak index 0cc81f9..b1f70e0 100644 --- a/src/drivers/drivers.mak +++ b/src/drivers/drivers.mak @@ -12,11 +12,29 @@ DRV_AP_LIBS = ##### COMMON DRIVERS +ifdef CONFIG_DRIVER_HOSTAP +DRV_CFLAGS += -DCONFIG_DRIVER_HOSTAP +DRV_OBJS += ../src/drivers/driver_hostap.o +CONFIG_WIRELESS_EXTENSION=y +NEED_AP_MLME=y +NEED_NETLINK=y +NEED_LINUX_IOCTL=y +endif + ifdef CONFIG_DRIVER_WIRED DRV_CFLAGS += -DCONFIG_DRIVER_WIRED DRV_OBJS += ../src/drivers/driver_wired.o endif +ifdef CONFIG_DRIVER_MADWIFI +DRV_CFLAGS += -DCONFIG_DRIVER_MADWIFI +DRV_OBJS += ../src/drivers/driver_madwifi.o +CONFIG_WIRELESS_EXTENSION=y +CONFIG_L2_PACKET=linux +NEED_NETLINK=y +NEED_LINUX_IOCTL=y +endif + ifdef CONFIG_DRIVER_NL80211 DRV_CFLAGS += -DCONFIG_DRIVER_NL80211 DRV_OBJS += ../src/drivers/driver_nl80211.o @@ -68,24 +86,6 @@ endif ##### PURE AP DRIVERS -ifdef CONFIG_DRIVER_HOSTAP -DRV_AP_CFLAGS += -DCONFIG_DRIVER_HOSTAP -DRV_AP_OBJS += ../src/drivers/driver_hostap.o -CONFIG_WIRELESS_EXTENSION=y -NEED_AP_MLME=y -NEED_NETLINK=y -NEED_LINUX_IOCTL=y -endif - -ifdef CONFIG_DRIVER_MADWIFI -DRV_AP_CFLAGS += -DCONFIG_DRIVER_MADWIFI -DRV_AP_OBJS += ../src/drivers/driver_madwifi.o -CONFIG_WIRELESS_EXTENSION=y -CONFIG_L2_PACKET=linux -NEED_NETLINK=y -NEED_LINUX_IOCTL=y -endif - ifdef CONFIG_DRIVER_ATHEROS DRV_AP_CFLAGS += -DCONFIG_DRIVER_ATHEROS DRV_AP_OBJS += ../src/drivers/driver_atheros.o @@ -104,6 +104,18 @@ NEED_LINUX_IOCTL=y NEED_RFKILL=y endif +ifdef CONFIG_DRIVER_RALINK +DRV_WPA_CFLAGS += -DCONFIG_DRIVER_RALINK +DRV_WPA_OBJS += ../src/drivers/driver_ralink.o +NEED_NETLINK=y +NEED_LINUX_IOCTL=y +endif + +ifdef CONFIG_DRIVER_BROADCOM +DRV_WPA_CFLAGS += -DCONFIG_DRIVER_BROADCOM +DRV_WPA_OBJS += ../src/drivers/driver_broadcom.o +endif + ifdef CONFIG_DRIVER_NDIS DRV_WPA_CFLAGS += -DCONFIG_DRIVER_NDIS DRV_WPA_OBJS += ../src/drivers/driver_ndis.o @@ -119,6 +131,20 @@ DRV_WPA_CFLAGS += -DCONFIG_USE_NDISUIO endif endif +ifdef CONFIG_DRIVER_OSX +DRV_WPA_CFLAGS += -DCONFIG_DRIVER_OSX +DRV_WPA_OBJS += ../src/drivers/driver_osx.o +DRV_WPA_LDFLAGS += -framework CoreFoundation +DRV_WPA_LDFLAGS += -F/System/Library/PrivateFrameworks -framework Apple80211 +endif + +ifdef CONFIG_DRIVER_IPHONE +DRV_WPA_CFLAGS += -DCONFIG_DRIVER_IPHONE +DRV_WPA_OBJS += ../src/drivers/driver_iphone.o +DRV_WPA_OBJS += ../src/drivers/MobileApple80211.o +DRV_WPA_LDFLAGS += -framework CoreFoundation +endif + ifdef CONFIG_DRIVER_ROBOSWITCH DRV_WPA_CFLAGS += -DCONFIG_DRIVER_ROBOSWITCH DRV_WPA_OBJS += ../src/drivers/driver_roboswitch.o diff --git a/src/drivers/drivers.mk b/src/drivers/drivers.mk index 1d7129c..2d1ad9d 100644 --- a/src/drivers/drivers.mk +++ b/src/drivers/drivers.mk @@ -12,11 +12,29 @@ DRV_AP_LIBS = ##### COMMON DRIVERS +ifdef CONFIG_DRIVER_HOSTAP +DRV_CFLAGS += -DCONFIG_DRIVER_HOSTAP +DRV_OBJS += src/drivers/driver_hostap.c +CONFIG_WIRELESS_EXTENSION=y +NEED_AP_MLME=y +NEED_NETLINK=y +NEED_LINUX_IOCTL=y +endif + ifdef CONFIG_DRIVER_WIRED DRV_CFLAGS += -DCONFIG_DRIVER_WIRED DRV_OBJS += src/drivers/driver_wired.c endif +ifdef CONFIG_DRIVER_MADWIFI +DRV_CFLAGS += -DCONFIG_DRIVER_MADWIFI +DRV_OBJS += src/drivers/driver_madwifi.c +CONFIG_WIRELESS_EXTENSION=y +CONFIG_L2_PACKET=linux +NEED_NETLINK=y +NEED_LINUX_IOCTL=y +endif + ifdef CONFIG_DRIVER_NL80211 DRV_CFLAGS += -DCONFIG_DRIVER_NL80211 DRV_OBJS += src/drivers/driver_nl80211.c @@ -68,24 +86,6 @@ endif ##### PURE AP DRIVERS -ifdef CONFIG_DRIVER_HOSTAP -DRV_AP_CFLAGS += -DCONFIG_DRIVER_HOSTAP -DRV_AP_OBJS += src/drivers/driver_hostap.c -CONFIG_WIRELESS_EXTENSION=y -NEED_AP_MLME=y -NEED_NETLINK=y -NEED_LINUX_IOCTL=y -endif - -ifdef CONFIG_DRIVER_MADWIFI -DRV_AP_CFLAGS += -DCONFIG_DRIVER_MADWIFI -DRV_AP_OBJS += src/drivers/driver_madwifi.c -CONFIG_WIRELESS_EXTENSION=y -CONFIG_L2_PACKET=linux -NEED_NETLINK=y -NEED_LINUX_IOCTL=y -endif - ifdef CONFIG_DRIVER_ATHEROS DRV_AP_CFLAGS += -DCONFIG_DRIVER_ATHEROS DRV_AP_OBJS += src/drivers/driver_atheros.c @@ -104,6 +104,18 @@ NEED_LINUX_IOCTL=y NEED_RFKILL=y endif +ifdef CONFIG_DRIVER_RALINK +DRV_WPA_CFLAGS += -DCONFIG_DRIVER_RALINK +DRV_WPA_OBJS += src/drivers/driver_ralink.c +NEED_NETLINK=y +NEED_LINUX_IOCTL=y +endif + +ifdef CONFIG_DRIVER_BROADCOM +DRV_WPA_CFLAGS += -DCONFIG_DRIVER_BROADCOM +DRV_WPA_OBJS += src/drivers/driver_broadcom.c +endif + ifdef CONFIG_DRIVER_NDIS DRV_WPA_CFLAGS += -DCONFIG_DRIVER_NDIS DRV_WPA_OBJS += src/drivers/driver_ndis.c @@ -119,6 +131,20 @@ DRV_WPA_CFLAGS += -DCONFIG_USE_NDISUIO endif endif +ifdef CONFIG_DRIVER_OSX +DRV_WPA_CFLAGS += -DCONFIG_DRIVER_OSX +DRV_WPA_OBJS += src/drivers/driver_osx.c +DRV_WPA_LDFLAGS += -framework CoreFoundation +DRV_WPA_LDFLAGS += -F/System/Library/PrivateFrameworks -framework Apple80211 +endif + +ifdef CONFIG_DRIVER_IPHONE +DRV_WPA_CFLAGS += -DCONFIG_DRIVER_IPHONE +DRV_WPA_OBJS += src/drivers/driver_iphone.c +DRV_WPA_OBJS += src/drivers/MobileApple80211.c +DRV_WPA_LDFLAGS += -framework CoreFoundation +endif + ifdef CONFIG_DRIVER_ROBOSWITCH DRV_WPA_CFLAGS += -DCONFIG_DRIVER_ROBOSWITCH DRV_WPA_OBJS += src/drivers/driver_roboswitch.c diff --git a/src/drivers/linux_wext.h b/src/drivers/linux_wext.h deleted file mode 100644 index b6eea68..0000000 --- a/src/drivers/linux_wext.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Driver interaction with generic Linux Wireless Extensions - * Copyright (c) 2003-2011, Jouni Malinen - * - * 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 LINUX_WEXT_H -#define LINUX_WEXT_H - -#ifndef ANDROID - -/* - * Avoid including other kernel header to avoid conflicts with C library - * headers. - */ -#define _LINUX_TYPES_H -#define _LINUX_SOCKET_H -#define _LINUX_IF_H - -#include -#include -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 /* ANDROID */ - -#include - -#ifndef IW_ENCODE_ALG_PMK -#define IW_ENCODE_ALG_PMK 4 -#endif - -#ifndef IW_ENC_CAPA_4WAY_HANDSHAKE -#define IW_ENC_CAPA_4WAY_HANDSHAKE 0x00000010 -#endif - -#endif /* LINUX_WEXT_H */ diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h index f9261c2..acd6cfa 100644 --- a/src/drivers/nl80211_copy.h +++ b/src/drivers/nl80211_copy.h @@ -156,21 +156,23 @@ * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX * or %NL80211_ATTR_MAC. * - * @NL80211_CMD_GET_BEACON: retrieve beacon information (returned in a - * %NL80222_CMD_NEW_BEACON message) - * @NL80211_CMD_SET_BEACON: set the beacon on an access point interface - * using the %NL80211_ATTR_BEACON_INTERVAL, %NL80211_ATTR_DTIM_PERIOD, - * %NL80211_ATTR_BEACON_HEAD and %NL80211_ATTR_BEACON_TAIL attributes. - * Following attributes are provided for drivers that generate full Beacon - * and Probe Response frames internally: %NL80211_ATTR_SSID, + * @NL80211_CMD_GET_BEACON: (not used) + * @NL80211_CMD_SET_BEACON: change the beacon on an access point interface + * using the %NL80211_ATTR_BEACON_HEAD and %NL80211_ATTR_BEACON_TAIL + * attributes. For drivers that generate the beacon and probe responses + * internally, the following attributes must be provided: %NL80211_ATTR_IE, + * %NL80211_ATTR_IE_PROBE_RESP and %NL80211_ATTR_IE_ASSOC_RESP. + * @NL80211_CMD_START_AP: Start AP operation on an AP interface, parameters + * are like for %NL80211_CMD_SET_BEACON, and additionally parameters that + * do not change are used, these include %NL80211_ATTR_BEACON_INTERVAL, + * %NL80211_ATTR_DTIM_PERIOD, %NL80211_ATTR_SSID, * %NL80211_ATTR_HIDDEN_SSID, %NL80211_ATTR_CIPHERS_PAIRWISE, * %NL80211_ATTR_CIPHER_GROUP, %NL80211_ATTR_WPA_VERSIONS, * %NL80211_ATTR_AKM_SUITES, %NL80211_ATTR_PRIVACY, - * %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_IE, %NL80211_ATTR_IE_PROBE_RESP, - * %NL80211_ATTR_IE_ASSOC_RESP. - * @NL80211_CMD_NEW_BEACON: add a new beacon to an access point interface, - * parameters are like for %NL80211_CMD_SET_BEACON. - * @NL80211_CMD_DEL_BEACON: remove the beacon, stop sending it + * %NL80211_ATTR_AUTH_TYPE and %NL80211_ATTR_INACTIVITY_TIMEOUT. + * @NL80211_CMD_NEW_BEACON: old alias for %NL80211_CMD_START_AP + * @NL80211_CMD_STOP_AP: Stop AP operation on the given interface + * @NL80211_CMD_DEL_BEACON: old alias for %NL80211_CMD_STOP_AP * * @NL80211_CMD_GET_STATION: Get station attributes for station identified by * %NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX. @@ -367,6 +369,11 @@ * %NL80211_ATTR_WIPHY_FREQ, %NL80211_ATTR_CONTROL_PORT, * %NL80211_ATTR_CONTROL_PORT_ETHERTYPE and * %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT. + * Background scan period can optionally be + * specified in %NL80211_ATTR_BG_SCAN_PERIOD, + * if not specified default background scan configuration + * in driver is used and if period value is 0, bg scan will be disabled. + * This attribute is ignored if driver does not support roam scan. * It is also sent as an event, with the BSSID and response IEs when the * connection is established or failed to be established. This can be * determined by the STATUS_CODE attribute. @@ -509,35 +516,6 @@ * @NL80211_CMD_TDLS_OPER: Perform a high-level TDLS command (e.g. link setup). * @NL80211_CMD_TDLS_MGMT: Send a TDLS management frame. * - * @NL80211_CMD_UNEXPECTED_FRAME: Used by an application controlling an AP - * (or GO) interface (i.e. hostapd) to ask for unexpected frames to - * implement sending deauth to stations that send unexpected class 3 - * frames. Also used as the event sent by the kernel when such a frame - * is received. - * For the event, the %NL80211_ATTR_MAC attribute carries the TA and - * other attributes like the interface index are present. - * If used as the command it must have an interface index and you can - * only unsubscribe from the event by closing the socket. Subscription - * is also for %NL80211_CMD_UNEXPECTED_4ADDR_FRAME events. - * - * @NL80211_CMD_UNEXPECTED_4ADDR_FRAME: Sent as an event indicating that the - * associated station identified by %NL80211_ATTR_MAC sent a 4addr frame - * and wasn't already in a 4-addr VLAN. The event will be sent similarly - * to the %NL80211_CMD_UNEXPECTED_FRAME event, to the same listener. - * - * @NL80211_CMD_PROBE_CLIENT: Probe an associated station on an AP interface - * by sending a null data frame to it and reporting when the frame is - * acknowleged. This is used to allow timing out inactive clients. Uses - * %NL80211_ATTR_IFINDEX and %NL80211_ATTR_MAC. The command returns a - * direct reply with an %NL80211_ATTR_COOKIE that is later used to match - * up the event with the request. The event includes the same data and - * has %NL80211_ATTR_ACK set if the frame was ACKed. - * - * @NL80211_CMD_REGISTER_BEACONS: Register this socket to receive beacons from - * other BSSes when any interfaces are in AP mode. This helps implement - * OLBC handling in hostapd. Beacons are reported in %NL80211_CMD_FRAME - * messages. Note that per PHY only one application may register. - * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -562,8 +540,10 @@ enum nl80211_commands { NL80211_CMD_GET_BEACON, NL80211_CMD_SET_BEACON, - NL80211_CMD_NEW_BEACON, - NL80211_CMD_DEL_BEACON, + NL80211_CMD_START_AP, + NL80211_CMD_NEW_BEACON = NL80211_CMD_START_AP, + NL80211_CMD_STOP_AP, + NL80211_CMD_DEL_BEACON = NL80211_CMD_STOP_AP, NL80211_CMD_GET_STATION, NL80211_CMD_SET_STATION, @@ -667,14 +647,6 @@ enum nl80211_commands { NL80211_CMD_TDLS_OPER, NL80211_CMD_TDLS_MGMT, - NL80211_CMD_UNEXPECTED_FRAME, - - NL80211_CMD_PROBE_CLIENT, - - NL80211_CMD_REGISTER_BEACONS, - - NL80211_CMD_UNEXPECTED_4ADDR_FRAME, - /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -695,8 +667,6 @@ enum nl80211_commands { #define NL80211_CMD_DISASSOCIATE NL80211_CMD_DISASSOCIATE #define NL80211_CMD_REG_BEACON_HINT NL80211_CMD_REG_BEACON_HINT -#define NL80211_ATTR_FEATURE_FLAGS NL80211_ATTR_FEATURE_FLAGS - /* source-level API compatibility */ #define NL80211_CMD_GET_MESH_PARAMS NL80211_CMD_GET_MESH_CONFIG #define NL80211_CMD_SET_MESH_PARAMS NL80211_CMD_SET_MESH_CONFIG @@ -1169,6 +1139,37 @@ enum nl80211_commands { * @NL80211_ATTR_PROBE_RESP: Probe Response template data. Contains the entire * probe-response frame. The DA field in the 802.11 header is zero-ed out, * to be filled by the FW. + * @NL80211_ATTR_DISABLE_HT: Force HT capable interfaces to disable + * this feature. Currently, only supported in mac80211 drivers. + * @NL80211_ATTR_HT_CAPABILITY_MASK: Specify which bits of the + * ATTR_HT_CAPABILITY to which attention should be paid. + * Currently, only mac80211 NICs support this feature. + * The values that may be configured are: + * MCS rates, MAX-AMSDU, HT-20-40 and HT_CAP_SGI_40 + * AMPDU density and AMPDU factor. + * All values are treated as suggestions and may be ignored + * by the driver as required. The actual values may be seen in + * the station debugfs ht_caps file. + * + * @NL80211_ATTR_DFS_REGION: region for regulatory rules which this country + * abides to when initiating radiation on DFS channels. A country maps + * to one DFS region. + * + * @NL80211_ATTR_NOACK_MAP: This u16 bitmap contains the No Ack Policy of + * up to 16 TIDs. + * + * @NL80211_ATTR_INACTIVITY_TIMEOUT: timeout value in seconds, this can be + * used by the drivers which has MLME in firmware and does not have support + * to report per station tx/rx activity to free up the staion entry from + * the list. This needs to be used when the driver advertises the + * capability to timeout the stations. + * + * @NL80211_ATTR_RX_SIGNAL_DBM: signal strength in dBm (as a 32-bit int); + * this attribute is (depending on the driver capabilities) added to + * received frames indicated with %NL80211_CMD_FRAME. + * + * @NL80211_ATTR_BG_SCAN_PERIOD: Background scan period in seconds + * or 0 to disable background scan. * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -1408,6 +1409,19 @@ enum nl80211_attrs { NL80211_ATTR_PROBE_RESP, + NL80211_ATTR_DFS_REGION, + + NL80211_ATTR_DISABLE_HT, + NL80211_ATTR_HT_CAPABILITY_MASK, + + NL80211_ATTR_NOACK_MAP, + + NL80211_ATTR_INACTIVITY_TIMEOUT, + + NL80211_ATTR_RX_SIGNAL_DBM, + + NL80211_ATTR_BG_SCAN_PERIOD, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -1442,9 +1456,9 @@ enum nl80211_attrs { #define NL80211_ATTR_AKM_SUITES NL80211_ATTR_AKM_SUITES #define NL80211_ATTR_KEY NL80211_ATTR_KEY #define NL80211_ATTR_KEYS NL80211_ATTR_KEYS -#define NL80211_ATTR_FEATURE_FLAGS NL80211_ATTR_FEATURE_FLAGS #define NL80211_MAX_SUPP_RATES 32 +#define NL80211_MAX_SUPP_HT_RATES 77 #define NL80211_MAX_SUPP_REG_RULES 32 #define NL80211_TKIP_DATA_OFFSET_ENCR_KEY 0 #define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16 @@ -1620,7 +1634,6 @@ enum nl80211_sta_bss_param { * @NL80211_STA_INFO_BSS_PARAM: current station's view of BSS, nested attribute * containing info as possible, see &enum nl80211_sta_bss_param * @NL80211_STA_INFO_CONNECTED_TIME: time since the station is last connected - * @NL80211_STA_INFO_STA_FLAGS: Contains a struct nl80211_sta_flag_update. * @__NL80211_STA_INFO_AFTER_LAST: internal * @NL80211_STA_INFO_MAX: highest possible station info attribute */ @@ -1642,7 +1655,6 @@ enum nl80211_sta_info { NL80211_STA_INFO_RX_BITRATE, NL80211_STA_INFO_BSS_PARAM, NL80211_STA_INFO_CONNECTED_TIME, - NL80211_STA_INFO_STA_FLAGS, /* keep last */ __NL80211_STA_INFO_AFTER_LAST, @@ -2049,6 +2061,17 @@ enum nl80211_mntr_flags { * access to a broader network beyond the MBSS. This is done via Root * Announcement frames. * + * @NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL: The minimum interval of time (in + * TUs) during which a mesh STA can send only one Action frame containing a + * PERR element. + * + * @NL80211_MESHCONF_FORWARDING: set Mesh STA as forwarding or non-forwarding + * or forwarding entity (default is TRUE - forwarding entity) + * + * @NL80211_MESHCONF_RSSI_THRESHOLD: RSSI threshold in dBm. This specifies the + * threshold for average signal strength of candidate station to establish + * a peer link. + * * @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute * * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use @@ -2072,6 +2095,9 @@ enum nl80211_meshconf_params { NL80211_MESHCONF_ELEMENT_TTL, NL80211_MESHCONF_HWMP_RANN_INTERVAL, NL80211_MESHCONF_GATE_ANNOUNCEMENTS, + NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL, + NL80211_MESHCONF_FORWARDING, + NL80211_MESHCONF_RSSI_THRESHOLD, /* keep last */ __NL80211_MESHCONF_ATTR_AFTER_LAST, @@ -2345,12 +2371,15 @@ enum nl80211_key_attributes { * in an array of rates as defined in IEEE 802.11 7.3.2.2 (u8 values with * 1 = 500 kbps) but without the IE length restriction (at most * %NL80211_MAX_SUPP_RATES in a single array). + * @NL80211_TXRATE_MCS: HT (MCS) rates allowed for TX rate selection + * in an array of MCS numbers. * @__NL80211_TXRATE_AFTER_LAST: internal * @NL80211_TXRATE_MAX: highest TX rate attribute */ enum nl80211_tx_rate_attributes { __NL80211_TXRATE_INVALID, NL80211_TXRATE_LEGACY, + NL80211_TXRATE_MCS, /* keep last */ __NL80211_TXRATE_AFTER_LAST, @@ -2735,9 +2764,14 @@ enum nl80211_ap_sme_features { * @NL80211_FEATURE_SK_TX_STATUS: This driver supports reflecting back * TX status to the socket error queue when requested with the * socket option. + * @NL80211_FEATURE_HT_IBSS: This driver supports IBSS with HT datarates. + * @NL80211_FEATURE_INACTIVITY_TIMER: This driver takes care of freeing up + * the connected inactive stations in AP mode. */ enum nl80211_feature_flags { NL80211_FEATURE_SK_TX_STATUS = 1 << 0, + NL80211_FEATURE_HT_IBSS = 1 << 1, + NL80211_FEATURE_INACTIVITY_TIMER = 1 << 2, }; /** diff --git a/src/drivers/wireless_copy.h b/src/drivers/wireless_copy.h new file mode 100644 index 0000000..d01f4cb --- /dev/null +++ b/src/drivers/wireless_copy.h @@ -0,0 +1,1183 @@ +/* This is based on Linux Wireless Extensions header file from WIRELESS_EXT 22. + * 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 : 22 16.3.07 + * + * Authors : Jean Tourrilhes - HPL - + * Copyright (c) 1997-2007 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 */ +#ifdef ANDROID +#include /* for __u* and __s* typedefs */ +#include /* for "struct sockaddr" et al */ +#include /* for IFNAMSIZ and co... */ +#else /* ANDROID */ +#include +#include +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 /* ANDROID */ + +/***************************** 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 22 + +/* + * 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 ) + * ---------- + * - 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 + * + * V19 to V20 + * ---------- + * - RtNetlink requests support (SET/GET) + * + * V20 to V21 + * ---------- + * - Remove (struct net_device *)->get_wireless_stats() + * - Change length in ESSID and NICK to strlen() instead of strlen()+1 + * - Add IW_RETRY_SHORT/IW_RETRY_LONG retry modifiers + * - Power/Retry relative values no longer * 100000 + * - Add explicit flag to tell stats are in 802.11k RCPI : IW_QUAL_RCPI + * + * V21 to V22 + * ---------- + * - Prevent leaking of kernel space in stream on 64 bits. + */ + +/**************************** 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 'even' 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) +#define IW_HANDLER(id, func) \ + [IW_IOCTL_IDX(id)] = func + +/* Odd : get (world access), even : 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) */ +#define IW_MODE_MESH 7 /* Mesh (IEEE 802.11s) network */ + +/* 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_RCPI 0x80 /* Level + Noise are 802.11k RCPI */ +#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 0x00FF /* 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 */ +#define IW_RETRY_SHORT 0x0010 /* Value is for short packets */ +#define IW_RETRY_LONG 0x0020 /* Value is for long packets */ + +/* 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 */ + +/* Scan capability flags - in (struct iw_range *)->scan_capa */ +#define IW_SCAN_CAPA_NONE 0x00 +#define IW_SCAN_CAPA_ESSID 0x01 +#define IW_SCAN_CAPA_BSSID 0x02 +#define IW_SCAN_CAPA_CHANNEL 0x04 +#define IW_SCAN_CAPA_MODE 0x08 +#define IW_SCAN_CAPA_RATE 0x10 +#define IW_SCAN_CAPA_TYPE 0x20 +#define IW_SCAN_CAPA_TIME 0x40 + +/* 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 +#define IW_MLME_AUTH 2 +#define IW_MLME_ASSOC 3 + +/* 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, IW_AUTH_GROUP_CIPHER, and IW_AUTH_CIPHER_GROUP_MGMT + * 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 +#define IW_AUTH_CIPHER_AES_CMAC 0x00000020 + +/* 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 - SIOCIWFIRST)) +#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 */ +}; + +#ifdef __KERNEL__ +#ifdef CONFIG_COMPAT + +#include + +struct compat_iw_point { + compat_caddr_t pointer; + __u16 length; + __u16 flags; +}; +#endif +#endif + +/* + * 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; + + /* Scan capabilities */ + __u8 scan_capa; /* IW_SCAN_CAPA_* bit field */ + + /* 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 length 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) + +#ifdef __KERNEL__ +#ifdef CONFIG_COMPAT +struct __compat_iw_event { + __u16 len; /* Real length of this stuff */ + __u16 cmd; /* Wireless IOCTL */ + compat_caddr_t pointer; +}; +#define IW_EV_COMPAT_LCP_LEN offsetof(struct __compat_iw_event, pointer) +#define IW_EV_COMPAT_POINT_OFF offsetof(struct compat_iw_point, length) + +/* Size of the various events for compat */ +#define IW_EV_COMPAT_CHAR_LEN (IW_EV_COMPAT_LCP_LEN + IFNAMSIZ) +#define IW_EV_COMPAT_UINT_LEN (IW_EV_COMPAT_LCP_LEN + sizeof(__u32)) +#define IW_EV_COMPAT_FREQ_LEN (IW_EV_COMPAT_LCP_LEN + sizeof(struct iw_freq)) +#define IW_EV_COMPAT_PARAM_LEN (IW_EV_COMPAT_LCP_LEN + sizeof(struct iw_param)) +#define IW_EV_COMPAT_ADDR_LEN (IW_EV_COMPAT_LCP_LEN + sizeof(struct sockaddr)) +#define IW_EV_COMPAT_QUAL_LEN (IW_EV_COMPAT_LCP_LEN + sizeof(struct iw_quality)) +#define IW_EV_COMPAT_POINT_LEN \ + (IW_EV_COMPAT_LCP_LEN + sizeof(struct compat_iw_point) - \ + IW_EV_COMPAT_POINT_OFF) +#endif +#endif + +/* Size of the Event prefix when packed in stream */ +#define IW_EV_LCP_PK_LEN (4) +/* Size of the various events when packed in stream */ +#define IW_EV_CHAR_PK_LEN (IW_EV_LCP_PK_LEN + IFNAMSIZ) +#define IW_EV_UINT_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(__u32)) +#define IW_EV_FREQ_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_freq)) +#define IW_EV_PARAM_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_param)) +#define IW_EV_ADDR_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct sockaddr)) +#define IW_EV_QUAL_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_quality)) +#define IW_EV_POINT_PK_LEN (IW_EV_LCP_PK_LEN + 4) + +#endif /* _LINUX_WIRELESS_H */ diff --git a/src/eap_common/eap_fast_common.c b/src/eap_common/eap_fast_common.c index d3406f3..4de34a8 100644 --- a/src/eap_common/eap_fast_common.c +++ b/src/eap_common/eap_fast_common.c @@ -133,9 +133,9 @@ u8 * eap_fast_derive_key(void *ssl_ctx, struct tls_connection *conn, wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: master_secret for key " "expansion", keys.master_key, keys.master_key_len); - if (tls_prf_sha1_md5(keys.master_key, keys.master_key_len, - label, rnd, keys.client_random_len + - keys.server_random_len, out, block_size + len)) + if (tls_prf(keys.master_key, keys.master_key_len, + label, rnd, keys.client_random_len + + keys.server_random_len, out, block_size + len)) goto fail; os_free(rnd); os_memmove(out, out + block_size, len); diff --git a/src/eap_common/eap_pwd_common.h b/src/eap_common/eap_pwd_common.h index 4b841b7..971386d 100644 --- a/src/eap_common/eap_pwd_common.h +++ b/src/eap_common/eap_pwd_common.h @@ -35,8 +35,13 @@ typedef struct group_definition_ { /* * EAP-pwd header, included on all payloads - * L(1 bit) | M(1 bit) | exch(6 bits) | total_length(if L is set) */ +struct eap_pwd_hdr { + u8 l_bit:1; + u8 m_bit:1; + u8 exch:6; + u8 total_length[0]; /* included when l_bit is set */ +} STRUCT_PACKED; #define EAP_PWD_OPCODE_ID_EXCH 1 #define EAP_PWD_OPCODE_COMMIT_EXCH 2 diff --git a/src/eap_peer/eap.c b/src/eap_peer/eap.c index 91fa4a9..cac85db 100644 --- a/src/eap_peer/eap.c +++ b/src/eap_peer/eap.c @@ -895,6 +895,11 @@ static int eap_sm_imsi_identity(struct eap_sm *sm, wpa_hexdump_ascii(MSG_DEBUG, "IMSI", (u8 *) imsi, imsi_len); + if (imsi_len < 7) { + wpa_printf(MSG_WARNING, "Too short IMSI for SIM identity"); + return -1; + } + for (i = 0; m && (m[i].vendor != EAP_VENDOR_IETF || m[i].method != EAP_TYPE_NONE); i++) { if (m[i].vendor == EAP_VENDOR_IETF && diff --git a/src/eap_peer/eap_aka.c b/src/eap_peer/eap_aka.c index 766764b..6ac6b64 100644 --- a/src/eap_peer/eap_aka.c +++ b/src/eap_peer/eap_aka.c @@ -235,19 +235,19 @@ static int eap_aka_umts_auth(struct eap_sm *sm, struct eap_aka_data *data) static void eap_aka_clear_identities(struct eap_aka_data *data, int id) { - if (id & CLEAR_PSEUDONYM) { + if ((id & CLEAR_PSEUDONYM) && data->pseudonym) { wpa_printf(MSG_DEBUG, "EAP-AKA: forgetting old pseudonym"); os_free(data->pseudonym); data->pseudonym = NULL; data->pseudonym_len = 0; } - if (id & CLEAR_REAUTH_ID) { + if ((id & CLEAR_REAUTH_ID) && data->reauth_id) { wpa_printf(MSG_DEBUG, "EAP-AKA: forgetting old reauth_id"); os_free(data->reauth_id); data->reauth_id = NULL; data->reauth_id_len = 0; } - if (id & CLEAR_EAP_ID) { + if ((id & CLEAR_EAP_ID) && data->last_eap_identity) { wpa_printf(MSG_DEBUG, "EAP-AKA: forgetting old eap_id"); os_free(data->last_eap_identity); data->last_eap_identity = NULL; @@ -256,24 +256,44 @@ static void eap_aka_clear_identities(struct eap_aka_data *data, int id) } -static int eap_aka_learn_ids(struct eap_aka_data *data, +static int eap_aka_learn_ids(struct eap_sm *sm, struct eap_aka_data *data, struct eap_sim_attrs *attr) { if (attr->next_pseudonym) { + const u8 *identity = NULL; + size_t identity_len = 0; + const u8 *realm = NULL; + size_t realm_len = 0; + + wpa_hexdump_ascii(MSG_DEBUG, + "EAP-AKA: (encr) AT_NEXT_PSEUDONYM", + attr->next_pseudonym, + attr->next_pseudonym_len); os_free(data->pseudonym); - data->pseudonym = os_malloc(attr->next_pseudonym_len); + /* Look for the realm of the permanent identity */ + identity = eap_get_config_identity(sm, &identity_len); + if (identity) { + for (realm = identity, realm_len = identity_len; + realm_len > 0; realm_len--, realm++) { + if (*realm == '@') + break; + } + } + data->pseudonym = os_malloc(attr->next_pseudonym_len + + realm_len); if (data->pseudonym == NULL) { wpa_printf(MSG_INFO, "EAP-AKA: (encr) No memory for " "next pseudonym"); + data->pseudonym_len = 0; return -1; } os_memcpy(data->pseudonym, attr->next_pseudonym, attr->next_pseudonym_len); - data->pseudonym_len = attr->next_pseudonym_len; - wpa_hexdump_ascii(MSG_DEBUG, - "EAP-AKA: (encr) AT_NEXT_PSEUDONYM", - data->pseudonym, - data->pseudonym_len); + if (realm_len) { + os_memcpy(data->pseudonym + attr->next_pseudonym_len, + realm, realm_len); + } + data->pseudonym_len = attr->next_pseudonym_len + realm_len; } if (attr->next_reauth_id) { @@ -282,6 +302,7 @@ static int eap_aka_learn_ids(struct eap_aka_data *data, if (data->reauth_id == NULL) { wpa_printf(MSG_INFO, "EAP-AKA: (encr) No memory for " "next reauth_id"); + data->reauth_id_len = 0; return -1; } os_memcpy(data->reauth_id, attr->next_reauth_id, @@ -894,7 +915,7 @@ static struct wpabuf * eap_aka_process_challenge(struct eap_sm *sm, return eap_aka_client_error( data, id, EAP_AKA_UNABLE_TO_PROCESS_PACKET); } - eap_aka_learn_ids(data, &eattr); + eap_aka_learn_ids(sm, data, &eattr); os_free(decrypted); } @@ -1112,7 +1133,7 @@ static struct wpabuf * eap_aka_process_reauthentication( data->msk, data->emsk); } eap_aka_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID); - eap_aka_learn_ids(data, &eattr); + eap_aka_learn_ids(sm, data, &eattr); if (data->result_ind && attr->result_ind) data->use_result_ind = 1; diff --git a/src/eap_peer/eap_pwd.c b/src/eap_peer/eap_pwd.c index 1957c82..6511a66 100644 --- a/src/eap_peer/eap_pwd.c +++ b/src/eap_peer/eap_pwd.c @@ -423,7 +423,8 @@ eap_pwd_perform_commit_exchange(struct eap_sm *sm, struct eap_pwd_data *data, BN_bn2bin(y, element + BN_num_bytes(data->grp->prime) + offset); resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD, - 1 + BN_num_bytes(data->grp->order) + + sizeof(struct eap_pwd_hdr) + + BN_num_bytes(data->grp->order) + (2 * BN_num_bytes(data->grp->prime)), EAP_CODE_RESPONSE, eap_get_id(reqData)); if (resp == NULL) @@ -632,7 +633,7 @@ eap_pwd_perform_confirm_exchange(struct eap_sm *sm, struct eap_pwd_data *data, H_Final(&ctx, conf); resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD, - 1 + SHA256_DIGEST_LENGTH, + sizeof(struct eap_pwd_hdr) + SHA256_DIGEST_LENGTH, EAP_CODE_RESPONSE, eap_get_id(reqData)); if (resp == NULL) goto fin; diff --git a/src/eap_peer/eap_sim.c b/src/eap_peer/eap_sim.c index 06fbc5b..2e81850 100644 --- a/src/eap_peer/eap_sim.c +++ b/src/eap_peer/eap_sim.c @@ -287,24 +287,44 @@ static void eap_sim_clear_identities(struct eap_sim_data *data, int id) } -static int eap_sim_learn_ids(struct eap_sim_data *data, +static int eap_sim_learn_ids(struct eap_sm *sm, struct eap_sim_data *data, struct eap_sim_attrs *attr) { if (attr->next_pseudonym) { + const u8 *identity = NULL; + size_t identity_len = 0; + const u8 *realm = NULL; + size_t realm_len = 0; + + wpa_hexdump_ascii(MSG_DEBUG, + "EAP-SIM: (encr) AT_NEXT_PSEUDONYM", + attr->next_pseudonym, + attr->next_pseudonym_len); os_free(data->pseudonym); - data->pseudonym = os_malloc(attr->next_pseudonym_len); + /* Look for the realm of the permanent identity */ + identity = eap_get_config_identity(sm, &identity_len); + if (identity) { + for (realm = identity, realm_len = identity_len; + realm_len > 0; realm_len--, realm++) { + if (*realm == '@') + break; + } + } + data->pseudonym = os_malloc(attr->next_pseudonym_len + + realm_len); if (data->pseudonym == NULL) { wpa_printf(MSG_INFO, "EAP-SIM: (encr) No memory for " "next pseudonym"); + data->pseudonym_len = 0; return -1; } os_memcpy(data->pseudonym, attr->next_pseudonym, attr->next_pseudonym_len); - data->pseudonym_len = attr->next_pseudonym_len; - wpa_hexdump_ascii(MSG_DEBUG, - "EAP-SIM: (encr) AT_NEXT_PSEUDONYM", - data->pseudonym, - data->pseudonym_len); + if (realm_len) { + os_memcpy(data->pseudonym + attr->next_pseudonym_len, + realm, realm_len); + } + data->pseudonym_len = attr->next_pseudonym_len + realm_len; } if (attr->next_reauth_id) { @@ -313,6 +333,7 @@ static int eap_sim_learn_ids(struct eap_sim_data *data, if (data->reauth_id == NULL) { wpa_printf(MSG_INFO, "EAP-SIM: (encr) No memory for " "next reauth_id"); + data->reauth_id_len = 0; return -1; } os_memcpy(data->reauth_id, attr->next_reauth_id, @@ -663,7 +684,7 @@ static struct wpabuf * eap_sim_process_challenge(struct eap_sm *sm, return eap_sim_client_error( data, id, EAP_SIM_UNABLE_TO_PROCESS_PACKET); } - eap_sim_learn_ids(data, &eattr); + eap_sim_learn_ids(sm, data, &eattr); os_free(decrypted); } @@ -861,7 +882,7 @@ static struct wpabuf * eap_sim_process_reauthentication( data->nonce_s, data->mk, data->msk, data->emsk); eap_sim_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID); - eap_sim_learn_ids(data, &eattr); + eap_sim_learn_ids(sm, data, &eattr); if (data->result_ind && attr->result_ind) data->use_result_ind = 1; diff --git a/src/eap_peer/eap_tls_common.c b/src/eap_peer/eap_tls_common.c index 2934ba4..93df756 100644 --- a/src/eap_peer/eap_tls_common.c +++ b/src/eap_peer/eap_tls_common.c @@ -294,9 +294,9 @@ u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, os_memcpy(rnd + keys.client_random_len, keys.server_random, keys.server_random_len); - if (tls_prf_sha1_md5(keys.master_key, keys.master_key_len, - label, rnd, keys.client_random_len + - keys.server_random_len, out, len)) + if (tls_prf(keys.master_key, keys.master_key_len, + label, rnd, keys.client_random_len + + keys.server_random_len, out, len)) goto fail; os_free(rnd); diff --git a/src/eap_peer/eap_tnc.c b/src/eap_peer/eap_tnc.c index da288eb..6c95f72 100644 --- a/src/eap_peer/eap_tnc.c +++ b/src/eap_peer/eap_tnc.c @@ -15,6 +15,7 @@ #include "includes.h" #include "common.h" +#include "base64.h" #include "eap_i.h" #include "tncc.h" diff --git a/src/eap_peer/eap_ttls.c b/src/eap_peer/eap_ttls.c index 612dfa7..2c939f9 100644 --- a/src/eap_peer/eap_ttls.c +++ b/src/eap_peer/eap_ttls.c @@ -441,7 +441,6 @@ static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm, "implicit challenge"); return -1; } - peer_challenge = challenge + 1 + EAP_TTLS_MSCHAPV2_CHALLENGE_LEN; pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_MS_CHAP_CHALLENGE, RADIUS_VENDOR_ID_MICROSOFT, 1, @@ -454,7 +453,14 @@ static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm, data->ident = challenge[EAP_TTLS_MSCHAPV2_CHALLENGE_LEN]; *pos++ = data->ident; *pos++ = 0; /* Flags */ - os_memcpy(pos, peer_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN); + if (os_get_random(pos, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN) < 0) { + os_free(challenge); + wpabuf_free(msg); + wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to get " + "random data for peer challenge"); + return -1; + } + peer_challenge = pos; pos += EAP_TTLS_MSCHAPV2_CHALLENGE_LEN; os_memset(pos, 0, 8); /* Reserved, must be zero */ pos += 8; @@ -462,6 +468,7 @@ static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm, password_len, pwhash, challenge, peer_challenge, pos, data->auth_response, data->master_key)) { + os_free(challenge); wpabuf_free(msg); wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive " "response"); diff --git a/src/eap_server/eap.h b/src/eap_server/eap.h index d5f8f1d..e1f500a 100644 --- a/src/eap_server/eap.h +++ b/src/eap_server/eap.h @@ -22,6 +22,8 @@ struct eap_sm; +#define EAP_MAX_METHODS 8 + #define EAP_TTLS_AUTH_PAP 1 #define EAP_TTLS_AUTH_CHAP 2 #define EAP_TTLS_AUTH_MSCHAP 4 diff --git a/src/eap_server/eap_server_aka.c b/src/eap_server/eap_server_aka.c index 0f25ffd..6ae7a6f 100644 --- a/src/eap_server/eap_server_aka.c +++ b/src/eap_server/eap_server_aka.c @@ -298,8 +298,13 @@ static int eap_aka_build_encr(struct eap_sm *sm, struct eap_aka_data *data, const u8 *nonce_s) { os_free(data->next_pseudonym); - data->next_pseudonym = - eap_sim_db_get_next_pseudonym(sm->eap_sim_db_priv, 1); + if (nonce_s == NULL) { + data->next_pseudonym = + eap_sim_db_get_next_pseudonym(sm->eap_sim_db_priv, 1); + } else { + /* Do not update pseudonym during re-authentication */ + data->next_pseudonym = NULL; + } os_free(data->next_reauth_id); if (data->counter <= EAP_AKA_MAX_FAST_REAUTHS) { data->next_reauth_id = @@ -1023,11 +1028,6 @@ static void eap_aka_process_reauth(struct eap_sm *sm, identity_len = id2_len; } - if (data->next_pseudonym) { - eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity, - identity_len, data->next_pseudonym); - data->next_pseudonym = NULL; - } if (data->next_reauth_id) { if (data->eap_method == EAP_TYPE_AKA_PRIME) { #ifdef EAP_SERVER_AKA_PRIME diff --git a/src/eap_server/eap_server_mschapv2.c b/src/eap_server/eap_server_mschapv2.c index f5ee7f4..64120a4 100644 --- a/src/eap_server/eap_server_mschapv2.c +++ b/src/eap_server/eap_server_mschapv2.c @@ -405,12 +405,9 @@ static void eap_mschapv2_process_response(struct eap_sm *sm, if (sm->user->password_hash) { pw_hash = sm->user->password; } else { - if (nt_password_hash(sm->user->password, - sm->user->password_len, - pw_hash_buf) < 0) { - data->state = FAILURE; - return; - } + nt_password_hash(sm->user->password, + sm->user->password_len, + pw_hash_buf); pw_hash = pw_hash_buf; } generate_authenticator_response_pwhash( diff --git a/src/eap_server/eap_server_peap.c b/src/eap_server/eap_server_peap.c index 50e79c0..381c44a 100644 --- a/src/eap_server/eap_server_peap.c +++ b/src/eap_server/eap_server_peap.c @@ -1064,6 +1064,8 @@ static void eap_peap_process_phase2(struct eap_sm *sm, wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP", in_decrypted); + hdr = wpabuf_head(in_decrypted); + if (data->peap_version == 0 && data->state != PHASE2_TLV) { const struct eap_hdr *resp; struct eap_hdr *nhdr; diff --git a/src/eap_server/eap_server_pwd.c b/src/eap_server/eap_server_pwd.c index 4c6f4d1..cf714c5 100644 --- a/src/eap_server/eap_server_pwd.c +++ b/src/eap_server/eap_server_pwd.c @@ -156,8 +156,8 @@ eap_pwd_build_id_req(struct eap_sm *sm, struct eap_pwd_data *data, u8 id) wpa_printf(MSG_DEBUG, "EAP-pwd: ID/Request"); req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD, - 1 + sizeof(struct eap_pwd_id) + - data->id_server_len, + sizeof(struct eap_pwd_hdr) + + sizeof(struct eap_pwd_id) + data->id_server_len, EAP_CODE_REQUEST, id); if (req == NULL) { eap_pwd_state(data, FAILURE); @@ -257,7 +257,8 @@ eap_pwd_build_commit_req(struct eap_sm *sm, struct eap_pwd_data *data, u8 id) BN_bn2bin(y, element + BN_num_bytes(data->grp->prime) + offset); req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD, - 1 + (2 * BN_num_bytes(data->grp->prime)) + + sizeof(struct eap_pwd_hdr) + + (2 * BN_num_bytes(data->grp->prime)) + BN_num_bytes(data->grp->order), EAP_CODE_REQUEST, id); if (req == NULL) @@ -384,7 +385,7 @@ eap_pwd_build_confirm_req(struct eap_sm *sm, struct eap_pwd_data *data, u8 id) os_memcpy(data->my_confirm, conf, SHA256_DIGEST_LENGTH); req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD, - 1 + SHA256_DIGEST_LENGTH, + sizeof(struct eap_pwd_hdr) + SHA256_DIGEST_LENGTH, EAP_CODE_REQUEST, id); if (req == NULL) goto fin; diff --git a/src/eap_server/eap_server_sim.c b/src/eap_server/eap_server_sim.c index 29df2ff..6de2e70 100644 --- a/src/eap_server/eap_server_sim.c +++ b/src/eap_server/eap_server_sim.c @@ -137,8 +137,13 @@ static int eap_sim_build_encr(struct eap_sm *sm, struct eap_sim_data *data, const u8 *nonce_s) { os_free(data->next_pseudonym); - data->next_pseudonym = - eap_sim_db_get_next_pseudonym(sm->eap_sim_db_priv, 0); + if (nonce_s == NULL) { + data->next_pseudonym = + eap_sim_db_get_next_pseudonym(sm->eap_sim_db_priv, 0); + } else { + /* Do not update pseudonym during re-authentication */ + data->next_pseudonym = NULL; + } os_free(data->next_reauth_id); if (data->counter <= EAP_SIM_MAX_FAST_REAUTHS) { data->next_reauth_id = @@ -622,11 +627,6 @@ static void eap_sim_process_reauth(struct eap_sm *sm, identity_len = id2_len; } - if (data->next_pseudonym) { - eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity, - identity_len, data->next_pseudonym); - data->next_pseudonym = NULL; - } if (data->next_reauth_id) { eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity, identity_len, data->next_reauth_id, diff --git a/src/eap_server/eap_server_tls_common.c b/src/eap_server/eap_server_tls_common.c index 0bb9d14..e149ee3 100644 --- a/src/eap_server/eap_server_tls_common.c +++ b/src/eap_server/eap_server_tls_common.c @@ -94,9 +94,9 @@ u8 * eap_server_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, os_memcpy(rnd + keys.client_random_len, keys.server_random, keys.server_random_len); - if (tls_prf_sha1_md5(keys.master_key, keys.master_key_len, - label, rnd, keys.client_random_len + - keys.server_random_len, out, len)) + if (tls_prf(keys.master_key, keys.master_key_len, + label, rnd, keys.client_random_len + + keys.server_random_len, out, len)) goto fail; os_free(rnd); diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index c0009ce..3bcbea6 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -18,6 +18,7 @@ #include "eloop.h" #include "common/ieee802_11_defs.h" #include "common/ieee802_11_common.h" +#include "common/wpa_ctrl.h" #include "wps/wps_i.h" #include "p2p_i.h" #include "p2p.h" @@ -55,11 +56,38 @@ static void p2p_expire_peers(struct p2p_data *p2p) { struct p2p_device *dev, *n; struct os_time now; + size_t i; os_get_time(&now); dl_list_for_each_safe(dev, n, &p2p->devices, struct p2p_device, list) { if (dev->last_seen.sec + P2P_PEER_EXPIRATION_AGE >= now.sec) continue; + + if (p2p->cfg->go_connected && + p2p->cfg->go_connected(p2p->cfg->cb_ctx, + dev->info.p2p_device_addr)) { + /* + * We are connected as a client to a group in which the + * peer is the GO, so do not expire the peer entry. + */ + os_get_time(&dev->last_seen); + continue; + } + + for (i = 0; i < p2p->num_groups; i++) { + if (p2p_group_is_client_connected( + p2p->groups[i], dev->info.p2p_device_addr)) + break; + } + if (i < p2p->num_groups) { + /* + * The peer is connected as a client in a group where + * we are the GO, so do not expire the peer entry. + */ + os_get_time(&dev->last_seen); + continue; + } + wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Expiring old peer " "entry " MACSTR, MAC2STR(dev->info.p2p_device_addr)); dl_list_del(&dev->list); @@ -129,14 +157,14 @@ u16 p2p_get_provisioning_info(struct p2p_data *p2p, const u8 *addr) } -void p2p_clear_provisioning_info(struct p2p_data *p2p, const u8 *iface_addr) +void p2p_clear_provisioning_info(struct p2p_data *p2p, const u8 *addr) { struct p2p_device *dev = NULL; - if (!iface_addr || !p2p) + if (!addr || !p2p) return; - dev = p2p_get_device_interface(p2p, iface_addr); + dev = p2p_get_device(p2p, addr); if (dev) dev->wps_prov_info = 0; } @@ -251,6 +279,12 @@ int p2p_listen(struct p2p_data *p2p, unsigned int timeout) p2p->pending_listen_usec = (timeout % 1000) * 1000; if (p2p->p2p_scan_running) { + if (p2p->start_after_scan == P2P_AFTER_SCAN_NOTHING) { + wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, + "P2P: p2p_scan running - connect is already " + "pending - skip listen"); + return 0; + } wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: p2p_scan running - delay start of listen state"); p2p->start_after_scan = P2P_AFTER_SCAN_LISTEN; @@ -789,8 +823,8 @@ static void p2p_search(struct p2p_data *p2p) } if (p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, type, freq, - p2p->num_req_dev_types, p2p->req_dev_types) < 0) - { + p2p->num_req_dev_types, p2p->req_dev_types, + p2p->find_dev_id)) { wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Scan request failed"); p2p_continue_find(p2p); @@ -889,7 +923,8 @@ static void p2p_free_req_dev_types(struct p2p_data *p2p) int p2p_find(struct p2p_data *p2p, unsigned int timeout, enum p2p_discovery_type type, - unsigned int num_req_dev_types, const u8 *req_dev_types) + unsigned int num_req_dev_types, const u8 *req_dev_types, + const u8 *dev_id) { int res; @@ -911,6 +946,12 @@ int p2p_find(struct p2p_data *p2p, unsigned int timeout, p2p->num_req_dev_types = num_req_dev_types; } + if (dev_id) { + os_memcpy(p2p->find_dev_id_buf, dev_id, ETH_ALEN); + p2p->find_dev_id = p2p->find_dev_id_buf; + } else + p2p->find_dev_id = NULL; + p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING; p2p_clear_timeout(p2p); p2p->cfg->stop_listen(p2p->cfg->cb_ctx); @@ -927,12 +968,12 @@ int p2p_find(struct p2p_data *p2p, unsigned int timeout, case P2P_FIND_PROGRESSIVE: res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_FULL, 0, p2p->num_req_dev_types, - p2p->req_dev_types); + p2p->req_dev_types, dev_id); break; case P2P_FIND_ONLY_SOCIAL: res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_SOCIAL, 0, p2p->num_req_dev_types, - p2p->req_dev_types); + p2p->req_dev_types, dev_id); break; default: return -1; @@ -969,7 +1010,8 @@ int p2p_other_scan_completed(struct p2p_data *p2p) wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting pending P2P find " "now that previous scan was completed"); if (p2p_find(p2p, p2p->last_p2p_find_timeout, p2p->find_type, - p2p->num_req_dev_types, p2p->req_dev_types) < 0) + p2p->num_req_dev_types, p2p->req_dev_types, + p2p->find_dev_id) < 0) return 0; return 1; } @@ -980,17 +1022,29 @@ void p2p_stop_find_for_freq(struct p2p_data *p2p, int freq) wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Stopping find"); eloop_cancel_timeout(p2p_find_timeout, p2p, NULL); p2p_clear_timeout(p2p); + if (p2p->state == P2P_SEARCH) + wpa_msg(p2p->cfg->msg_ctx, MSG_INFO, P2P_EVENT_FIND_STOPPED); p2p_set_state(p2p, P2P_IDLE); p2p_free_req_dev_types(p2p); p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING; p2p->go_neg_peer = NULL; p2p->sd_peer = NULL; p2p->invite_peer = NULL; + p2p_stop_listen_for_freq(p2p, freq); +} + + +void p2p_stop_listen_for_freq(struct p2p_data *p2p, int freq) +{ if (freq > 0 && p2p->drv_in_listen == freq && p2p->in_listen) { wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Skip stop_listen " "since we are on correct channel for response"); return; } + if (p2p->in_listen) { + p2p->in_listen = 0; + p2p_clear_timeout(p2p); + } if (p2p->drv_in_listen) { /* * The driver may not deliver callback to p2p_listen_end() @@ -1450,9 +1504,9 @@ static void p2p_rx_p2p_action(struct p2p_data *p2p, const u8 *sa, } -static void p2p_rx_action_public(struct p2p_data *p2p, const u8 *da, - const u8 *sa, const u8 *bssid, const u8 *data, - size_t len, int freq) +void p2p_rx_action_public(struct p2p_data *p2p, const u8 *da, const u8 *sa, + const u8 *bssid, const u8 *data, size_t len, + int freq) { if (len < 1) return; @@ -2052,6 +2106,35 @@ int p2p_scan_result_text(const u8 *ies, size_t ies_len, char *buf, char *end) } +int p2p_parse_dev_addr(const u8 *ies, size_t ies_len, u8 *dev_addr) +{ + struct wpabuf *p2p_ie; + struct p2p_message msg; + int ret = -1; + + p2p_ie = ieee802_11_vendor_ie_concat(ies, ies_len, + P2P_IE_VENDOR_TYPE); + if (p2p_ie == NULL) + return -1; + os_memset(&msg, 0, sizeof(msg)); + if (p2p_parse_p2p_ie(p2p_ie, &msg)) { + wpabuf_free(p2p_ie); + return -1; + } + + if (msg.p2p_device_addr) { + os_memcpy(dev_addr, msg.p2p_device_addr, ETH_ALEN); + ret = 0; + } else if (msg.device_id) { + os_memcpy(dev_addr, msg.device_id, ETH_ALEN); + ret = 0; + } + + wpabuf_free(p2p_ie); + return ret; +} + + static void p2p_clear_go_neg(struct p2p_data *p2p) { p2p->go_neg_peer = NULL; @@ -2126,6 +2209,16 @@ struct p2p_data * p2p_init(const struct p2p_config *cfg) p2p->cfg->model_number = os_strdup(cfg->model_number); if (cfg->serial_number) p2p->cfg->serial_number = os_strdup(cfg->serial_number); + if (cfg->pref_chan) { + p2p->cfg->pref_chan = os_malloc(cfg->num_pref_chan * + sizeof(struct p2p_channel)); + if (p2p->cfg->pref_chan) { + os_memcpy(p2p->cfg->pref_chan, cfg->pref_chan, + cfg->num_pref_chan * + sizeof(struct p2p_channel)); + } else + p2p->cfg->num_pref_chan = 0; + } p2p->min_disc_int = 1; p2p->max_disc_int = 3; @@ -2160,6 +2253,7 @@ void p2p_deinit(struct p2p_data *p2p) os_free(p2p->cfg->model_name); os_free(p2p->cfg->model_number); os_free(p2p->cfg->serial_number); + os_free(p2p->cfg->pref_chan); os_free(p2p->groups); wpabuf_free(p2p->sd_resp); os_free(p2p->after_scan_tx); @@ -2171,11 +2265,7 @@ void p2p_deinit(struct p2p_data *p2p) void p2p_flush(struct p2p_data *p2p) { struct p2p_device *dev, *prev; - p2p_clear_timeout(p2p); - p2p_set_state(p2p, P2P_IDLE); - p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING; - p2p->go_neg_peer = NULL; - eloop_cancel_timeout(p2p_find_timeout, p2p, NULL); + p2p_stop_find(p2p); dl_list_for_each_safe(dev, prev, &p2p->devices, struct p2p_device, list) { dl_list_del(&dev->list); @@ -2369,7 +2459,7 @@ void p2p_continue_find(struct p2p_data *p2p) } else if (dev->req_config_methods && !(dev->flags & P2P_DEV_PD_FOR_JOIN)) { wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send " - "pending Provision Discovery Request to " + "pending Provisioning Discovery Request to " MACSTR " (config methods 0x%x)", MAC2STR(dev->info.p2p_device_addr), dev->req_config_methods); @@ -2415,7 +2505,7 @@ static void p2p_sd_cb(struct p2p_data *p2p, int success) * p2p_retry_pd - Retry any pending provision disc requests in IDLE state * @p2p: P2P module context from p2p_init() */ -static void p2p_retry_pd(struct p2p_data *p2p) +void p2p_retry_pd(struct p2p_data *p2p) { struct p2p_device *dev; @@ -2438,7 +2528,7 @@ static void p2p_retry_pd(struct p2p_data *p2p) continue; wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send " - "pending Provision Discovery Request to " + "pending Provisioning Discovery Request to " MACSTR " (config methods 0x%x)", MAC2STR(dev->info.p2p_device_addr), dev->req_config_methods); @@ -2527,10 +2617,12 @@ void p2p_scan_res_handled(struct p2p_data *p2p) } -void p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies) +void p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies, const u8 *dev_id) { u8 *len = p2p_buf_add_ie_hdr(ies); p2p_buf_add_capability(ies, p2p->dev_capab, 0); + if (dev_id) + p2p_buf_add_device_id(ies, dev_id); if (p2p->cfg->reg_class && p2p->cfg->channel) p2p_buf_add_listen_channel(ies, p2p->cfg->country, p2p->cfg->reg_class, @@ -2779,6 +2871,20 @@ int p2p_listen_end(struct p2p_data *p2p, unsigned int freq) p2p_connect_send(p2p, p2p->go_neg_peer); return 1; } else if (p2p->state == P2P_SEARCH) { + if (p2p->p2p_scan_running) { + /* + * Search is already in progress. This can happen if + * an Action frame RX is reported immediately after + * the end of a remain-on-channel operation and the + * response frame to that is sent using an offchannel + * operation while in p2p_find. Avoid an attempt to + * restart a scan here. + */ + wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: p2p_scan " + "already in progress - do not try to start a " + "new one"); + return 1; + } p2p_search(p2p); return 1; } @@ -3064,14 +3170,10 @@ static const char * p2p_go_state_text(enum p2p_go_state go_state) } -int p2p_get_peer_info(struct p2p_data *p2p, const u8 *addr, int next, - char *buf, size_t buflen) +const struct p2p_peer_info * p2p_get_peer_info(struct p2p_data *p2p, + const u8 *addr, int next) { struct p2p_device *dev; - int res; - char *pos, *end; - struct os_time now; - char devtype[WPS_DEV_TYPE_BUFSIZE]; if (addr) dev = p2p_get_device(p2p, addr); @@ -3085,35 +3187,37 @@ int p2p_get_peer_info(struct p2p_data *p2p, const u8 *addr, int next, } if (dev == NULL) + return NULL; + + return &dev->info; +} + + +int p2p_get_peer_info_txt(const struct p2p_peer_info *info, + char *buf, size_t buflen) +{ + struct p2p_device *dev; + int res; + char *pos, *end; + struct os_time now; + + if (info == NULL) return -1; + dev = (struct p2p_device *) (((u8 *) info) - + offsetof(struct p2p_device, info)); + pos = buf; end = buf + buflen; - res = os_snprintf(pos, end - pos, MACSTR "\n", - MAC2STR(dev->info.p2p_device_addr)); - if (res < 0 || res >= end - pos) - return pos - buf; - pos += res; - os_get_time(&now); res = os_snprintf(pos, end - pos, "age=%d\n" "listen_freq=%d\n" - "level=%d\n" "wps_method=%s\n" "interface_addr=" MACSTR "\n" "member_in_go_dev=" MACSTR "\n" "member_in_go_iface=" MACSTR "\n" - "pri_dev_type=%s\n" - "device_name=%s\n" - "manufacturer=%s\n" - "model_name=%s\n" - "model_number=%s\n" - "serial_number=%s\n" - "config_methods=0x%x\n" - "dev_capab=0x%x\n" - "group_capab=0x%x\n" "go_neg_req_sent=%d\n" "go_state=%s\n" "dialog_token=%u\n" @@ -3127,21 +3231,10 @@ int p2p_get_peer_info(struct p2p_data *p2p, const u8 *addr, int next, "invitation_reqs=%u\n", (int) (now.sec - dev->last_seen.sec), dev->listen_freq, - dev->info.level, p2p_wps_method_text(dev->wps_method), MAC2STR(dev->interface_addr), MAC2STR(dev->member_in_go_dev), MAC2STR(dev->member_in_go_iface), - wps_dev_type_bin2str(dev->info.pri_dev_type, - devtype, sizeof(devtype)), - dev->info.device_name, - dev->info.manufacturer, - dev->info.model_name, - dev->info.model_number, - dev->info.serial_number, - dev->info.config_methods, - dev->info.dev_capab, - dev->info.group_capab, dev->go_neg_req_sent, p2p_go_state_text(dev->go_state), dev->dialog_token, @@ -3210,6 +3303,12 @@ int p2p_get_peer_info(struct p2p_data *p2p, const u8 *addr, int next, } +int p2p_peer_known(struct p2p_data *p2p, const u8 *addr) +{ + return p2p_get_device(p2p, addr) != NULL; +} + + void p2p_set_client_discoverability(struct p2p_data *p2p, int enabled) { if (enabled) { @@ -3610,6 +3709,28 @@ int p2p_set_oper_channel(struct p2p_data *p2p, u8 op_reg_class, u8 op_channel, } +int p2p_set_pref_chan(struct p2p_data *p2p, unsigned int num_pref_chan, + const struct p2p_channel *pref_chan) +{ + struct p2p_channel *n; + + if (pref_chan) { + n = os_malloc(num_pref_chan * sizeof(struct p2p_channel)); + if (n == NULL) + return -1; + os_memcpy(n, pref_chan, + num_pref_chan * sizeof(struct p2p_channel)); + } else + n = NULL; + + os_free(p2p->cfg->pref_chan); + p2p->cfg->pref_chan = n; + p2p->cfg->num_pref_chan = num_pref_chan; + + return 0; +} + + int p2p_get_interface_addr(struct p2p_data *p2p, const u8 *dev_addr, u8 *iface_addr) { diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index 6a640ab..75d4739 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -224,6 +224,11 @@ enum p2p_prov_disc_status { P2P_PROV_DISC_REJECTED, }; +struct p2p_channel { + u8 op_class; + u8 chan; +}; + /** * struct p2p_config - P2P configuration * @@ -271,6 +276,16 @@ struct p2p_config { struct p2p_channels channels; /** + * num_pref_chan - Number of pref_chan entries + */ + unsigned int num_pref_chan; + + /** + * pref_chan - Preferred channels for GO Negotiation + */ + struct p2p_channel *pref_chan; + + /** * pri_dev_type - Primary Device Type (see WPS) */ u8 pri_dev_type[8]; @@ -359,6 +374,7 @@ struct p2p_config { * @freq: Specific frequency (MHz) to scan or 0 for no restriction * @num_req_dev_types: Number of requested device types * @req_dev_types: Array containing requested device types + * @dev_id: Device ID to search for or %NULL to find all devices * Returns: 0 on success, -1 on failure * * This callback function is used to request a P2P scan or search @@ -382,7 +398,7 @@ struct p2p_config { */ int (*p2p_scan)(void *ctx, enum p2p_scan_type type, int freq, unsigned int num_req_dev_types, - const u8 *req_dev_types); + const u8 *req_dev_types, const u8 *dev_id); /** * send_probe_resp - Transmit a Probe Response frame @@ -705,6 +721,15 @@ struct p2p_config { * local failure in transmitting the Invitation Request. */ void (*invitation_result)(void *ctx, int status, const u8 *bssid); + + /** + * go_connected - Check whether we are connected to a GO + * @ctx: Callback context from cb_ctx + * @dev_addr: P2P Device Address of a GO + * Returns: 1 if we are connected as a P2P client to the specified GO + * or 0 if not. + */ + int (*go_connected)(void *ctx, const u8 *dev_addr); }; @@ -809,11 +834,13 @@ enum p2p_discovery_type { * @req_dev_types: Requested device types array, must be an array * containing num_req_dev_types * WPS_DEV_TYPE_LEN bytes; %NULL if no * requested device types. + * @dev_id: Device ID to search for or %NULL to find all devices * Returns: 0 on success, -1 on failure */ int p2p_find(struct p2p_data *p2p, unsigned int timeout, enum p2p_discovery_type type, - unsigned int num_req_dev_types, const u8 *req_dev_types); + unsigned int num_req_dev_types, const u8 *req_dev_types, + const u8 *dev_id); /** * p2p_stop_find - Stop P2P Find (Device Discovery) @@ -1054,12 +1081,12 @@ u16 p2p_get_provisioning_info(struct p2p_data *p2p, const u8 *addr); /** * p2p_clear_provisioning_info - Clear any stored provisioning info * @p2p: P2P module context from p2p_init() - * @iface_addr: Peer P2P Interface Address + * @iface_addr: Peer P2P Device Address * * This function is used to clear stored WPS provisioning info for the given * peer. */ -void p2p_clear_provisioning_info(struct p2p_data *p2p, const u8 *iface_addr); +void p2p_clear_provisioning_info(struct p2p_data *p2p, const u8 *addr); /* Event notifications from lower layer driver operations */ @@ -1324,6 +1351,11 @@ int p2p_group_notif_noa(struct p2p_group *group, const u8 *noa, int p2p_group_match_dev_type(struct p2p_group *group, struct wpabuf *wps); /** + * p2p_group_match_dev_id - Match P2P Device Address in group with requested device id + */ +int p2p_group_match_dev_id(struct p2p_group *group, struct wpabuf *p2p); + +/** * p2p_group_go_discover - Send GO Discoverability Request to a group client * @group: P2P group context from p2p_group_init() * Returns: 0 on success (frame scheduled); -1 if client was not found @@ -1360,6 +1392,15 @@ int p2p_ie_text(struct wpabuf *p2p_ie, char *buf, char *end); int p2p_scan_result_text(const u8 *ies, size_t ies_len, char *buf, char *end); /** + * p2p_parse_dev_addr - Parse P2P Device Address from P2P IE(s) + * @ies: Information elements from scan results + * @ies_len: ies buffer length in octets + * @dev_addr: Buffer for returning P2P Device Address + * Returns: 0 on success or -1 if P2P Device Address could not be parsed + */ +int p2p_parse_dev_addr(const u8 *ies, size_t ies_len, u8 *dev_addr); + +/** * p2p_assoc_req_ie - Build P2P IE for (Re)Association Request frame * @p2p: P2P module context from p2p_init() * @bssid: BSSID @@ -1376,8 +1417,9 @@ int p2p_assoc_req_ie(struct p2p_data *p2p, const u8 *bssid, u8 *buf, * p2p_scan_ie - Build P2P IE for Probe Request * @p2p: P2P module context from p2p_init() * @ies: Buffer for writing P2P IE + * @dev_id: Device ID to search for or %NULL for any */ -void p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies); +void p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies, const u8 *dev_id); /** * p2p_scan_ie_buf_len - Get maximum buffer length needed for p2p_scan_ie @@ -1416,16 +1458,36 @@ int p2p_get_cross_connect_disallowed(const struct wpabuf *p2p_ie); const u8 * p2p_get_go_dev_addr(const struct wpabuf *p2p_ie); /** - * p2p_get_peer_info - Get P2P peer information in text format + * p2p_get_peer_info - Get P2P peer information * @p2p: P2P module context from p2p_init() * @addr: P2P Device Address of the peer or %NULL to indicate the first peer * @next: Whether to select the peer entry following the one indicated by addr + * Returns: Pointer to peer info or %NULL if not found + */ +const struct p2p_peer_info * p2p_get_peer_info(struct p2p_data *p2p, + const u8 *addr, int next); + +/** + * p2p_get_peer_info_txt - Get internal P2P peer information in text format + * @info: Pointer to P2P peer info from p2p_get_peer_info() * @buf: Buffer for returning text * @buflen: Maximum buffer length * Returns: Number of octets written to the buffer or -1 on failure + * + * Note: This information is internal to the P2P module and subject to change. + * As such, this should not really be used by external programs for purposes + * other than debugging. */ -int p2p_get_peer_info(struct p2p_data *p2p, const u8 *addr, int next, - char *buf, size_t buflen); +int p2p_get_peer_info_txt(const struct p2p_peer_info *info, + char *buf, size_t buflen); + +/** + * p2p_peer_known - Check whether P2P peer is known + * @p2p: P2P module context from p2p_init() + * @addr: P2P Device Address of the peer + * Returns: 1 if the specified device is in the P2P peer table or 0 if not + */ +int p2p_peer_known(struct p2p_data *p2p, const u8 *addr); /** * p2p_set_client_discoverability - Set client discoverability capability @@ -1439,7 +1501,7 @@ int p2p_get_peer_info(struct p2p_data *p2p, const u8 *addr, int next, void p2p_set_client_discoverability(struct p2p_data *p2p, int enabled); /** - * p2p_set_manageD_oper - Set managed P2P Device operations capability + * p2p_set_managed_oper - Set managed P2P Device operations capability * @p2p: P2P module context from p2p_init() * @enabled: Whether managed P2P Device operations will be enabled */ @@ -1465,9 +1527,6 @@ void p2p_set_cross_connect(struct p2p_data *p2p, int enabled); int p2p_get_oper_freq(struct p2p_data *p2p, const u8 *iface_addr); -int p2p_add_device(struct p2p_data *p2p, const u8 *addr, int freq, int level, - const u8 *ies, size_t ies_len); - /** * p2p_set_intra_bss_dist - Set intra BSS distribution * @p2p: P2P module context from p2p_init() @@ -1523,6 +1582,14 @@ const u8 * p2p_iterate_group_members(struct p2p_group *group, void **next); const u8 * p2p_group_get_dev_addr(struct p2p_group *group, const u8 *addr); /** + * p2p_group_is_client_connected - Check whether a specific client is connected + * @group: P2P group context from p2p_group_init() + * @addr: P2P Device Address of the client + * Returns: 1 if client is connected or 0 if not + */ +int p2p_group_is_client_connected(struct p2p_group *group, const u8 *dev_addr); + +/** * p2p_get_peer_found - Get P2P peer info structure of a found peer * @p2p: P2P module context from p2p_init() * @addr: P2P Device Address of the peer or %NULL to indicate the first peer @@ -1562,6 +1629,16 @@ int p2p_set_oper_channel(struct p2p_data *p2p, u8 op_reg_class, u8 op_channel, int cfg_op_channel); /** + * p2p_set_pref_chan - Set P2P preferred channel list + * @p2p: P2P module context from p2p_init() + * @num_pref_chan: Number of entries in pref_chan list + * @pref_chan: Preferred channels or %NULL to remove preferences + * Returns: 0 on success, -1 on failure + */ +int p2p_set_pref_chan(struct p2p_data *p2p, unsigned int num_pref_chan, + const struct p2p_channel *pref_chan); + +/** * p2p_in_progress - Check whether a P2P operation is progress * @p2p: P2P module context from p2p_init() * Returns: 0 if P2P module is idle or 1 if an operation is in progress diff --git a/src/p2p/p2p_go_neg.c b/src/p2p/p2p_go_neg.c index eb85f51..f83d3de 100644 --- a/src/p2p/p2p_go_neg.c +++ b/src/p2p/p2p_go_neg.c @@ -302,6 +302,7 @@ static void p2p_reselect_channel(struct p2p_data *p2p, struct p2p_reg_class *cl; int freq; u8 op_reg_class, op_channel; + unsigned int i; wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Selected operating " "channel (reg_class %u channel %u) not acceptable to the " @@ -334,6 +335,21 @@ static void p2p_reselect_channel(struct p2p_data *p2p, return; } + /* Select channel with highest preference if the peer supports it */ + for (i = 0; p2p->cfg->pref_chan && i < p2p->cfg->num_pref_chan; i++) { + if (p2p_channels_includes(intersection, + p2p->cfg->pref_chan[i].op_class, + p2p->cfg->pref_chan[i].chan)) { + p2p->op_reg_class = p2p->cfg->pref_chan[i].op_class; + p2p->op_channel = p2p->cfg->pref_chan[i].chan; + wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Pick " + "highest preferred chnnel (op_class %u " + "channel %u) from intersection", + p2p->op_reg_class, p2p->op_channel); + return; + } + } + /* * Fall back to whatever is included in the channel intersection since * no better options seems to be available. diff --git a/src/p2p/p2p_group.c b/src/p2p/p2p_group.c index 59d1507..e25baaa 100644 --- a/src/p2p/p2p_group.c +++ b/src/p2p/p2p_group.c @@ -490,6 +490,31 @@ int p2p_group_match_dev_type(struct p2p_group *group, struct wpabuf *wps) } +int p2p_group_match_dev_id(struct p2p_group *group, struct wpabuf *p2p) +{ + struct p2p_group_member *m; + struct p2p_message msg; + + os_memset(&msg, 0, sizeof(msg)); + if (p2p_parse_p2p_ie(p2p, &msg)) + return 1; /* Failed to parse - assume no filter on Device ID */ + + if (!msg.device_id) + return 1; /* No filter on Device ID */ + + if (os_memcmp(msg.device_id, group->p2p->cfg->dev_addr, ETH_ALEN) == 0) + return 1; /* Match with our P2P Device Address */ + + for (m = group->members; m; m = m->next) { + if (os_memcmp(msg.device_id, m->dev_addr, ETH_ALEN) == 0) + return 1; /* Match with group client P2P Device Address */ + } + + /* No match with Device ID */ + return 0; +} + + void p2p_group_notif_formation_done(struct p2p_group *group) { if (group == NULL) @@ -699,3 +724,16 @@ const u8 * p2p_iterate_group_members(struct p2p_group *group, void **next) return iter->addr; } + + +int p2p_group_is_client_connected(struct p2p_group *group, const u8 *dev_addr) +{ + struct p2p_group_member *m; + + for (m = group->members; m; m = m->next) { + if (os_memcmp(m->dev_addr, dev_addr, ETH_ALEN) == 0) + return 1; + } + + return 0; +} diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h index 0dc33e7..d052a03 100644 --- a/src/p2p/p2p_i.h +++ b/src/p2p/p2p_i.h @@ -67,7 +67,7 @@ struct p2p_device { size_t oper_ssid_len; /** - * req_config_methods - Pending provision discovery methods + * req_config_methods - Pending provisioning discovery methods */ u16 req_config_methods; @@ -381,6 +381,8 @@ struct p2p_data { /* Requested device types for find/search */ unsigned int num_req_dev_types; u8 *req_dev_types; + u8 *find_dev_id; + u8 find_dev_id_buf[ETH_ALEN]; struct p2p_group **groups; size_t num_groups; @@ -655,6 +657,8 @@ struct p2p_device * p2p_add_dev_from_go_neg_req(struct p2p_data *p2p, struct p2p_message *msg); void p2p_add_dev_info(struct p2p_data *p2p, const u8 *addr, struct p2p_device *dev, struct p2p_message *msg); +int p2p_add_device(struct p2p_data *p2p, const u8 *addr, int freq, int level, + const u8 *ies, size_t ies_len); struct p2p_device * p2p_get_device(struct p2p_data *p2p, const u8 *addr); struct p2p_device * p2p_get_device_interface(struct p2p_data *p2p, const u8 *addr); @@ -669,5 +673,6 @@ void p2p_build_ssid(struct p2p_data *p2p, u8 *ssid, size_t *ssid_len); int p2p_send_action(struct p2p_data *p2p, unsigned int freq, const u8 *dst, const u8 *src, const u8 *bssid, const u8 *buf, size_t len, unsigned int wait_time); +void p2p_stop_listen_for_freq(struct p2p_data *p2p, int freq); #endif /* P2P_I_H */ diff --git a/src/p2p/p2p_invitation.c b/src/p2p/p2p_invitation.c index bb2767d..016c572 100644 --- a/src/p2p/p2p_invitation.c +++ b/src/p2p/p2p_invitation.c @@ -350,6 +350,8 @@ int p2p_invite_send(struct p2p_data *p2p, struct p2p_device *dev, req = p2p_build_invitation_req(p2p, dev, go_dev_addr); if (req == NULL) return -1; + if (p2p->state != P2P_IDLE) + p2p_stop_listen_for_freq(p2p, freq); wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Sending Invitation Request"); p2p_set_state(p2p, P2P_INVITE); diff --git a/src/p2p/p2p_pd.c b/src/p2p/p2p_pd.c index 1ee59c5..8eced26 100644 --- a/src/p2p/p2p_pd.c +++ b/src/p2p/p2p_pd.c @@ -209,14 +209,14 @@ void p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa, return; wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Received Provision Discovery Response from " MACSTR + "P2P: Received Provisioning Discovery Response from " MACSTR " with config methods 0x%x", MAC2STR(sa), msg.wps_config_methods); dev = p2p_get_device(p2p, sa); if (dev == NULL || !dev->req_config_methods) { wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Ignore Provision Discovery Response from " + "P2P: Ignore Provisioning Discovery Response from " MACSTR " with no pending request", MAC2STR(sa)); p2p_parse_free(&msg); return; @@ -229,7 +229,7 @@ void p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa, if (dev->dialog_token != msg.dialog_token) { wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Ignore Provision Discovery Response with " + "P2P: Ignore Provisioning Discovery Response with " "unexpected Dialog Token %u (expected %u)", msg.dialog_token, dev->dialog_token); p2p_parse_free(&msg); @@ -246,7 +246,7 @@ void p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa, if (msg.wps_config_methods != dev->req_config_methods) { wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer rejected " - "our Provision Discovery Request"); + "our Provisioning Discovery Request"); if (p2p->cfg->prov_disc_fail) p2p->cfg->prov_disc_fail(p2p->cfg->cb_ctx, sa, P2P_PROV_DISC_REJECTED); @@ -322,6 +322,8 @@ int p2p_send_prov_disc_req(struct p2p_data *p2p, struct p2p_device *dev, if (req == NULL) return -1; + if (p2p->state != P2P_IDLE) + p2p_stop_listen_for_freq(p2p, freq); p2p->pending_action_state = P2P_PENDING_PD; if (p2p_send_action(p2p, freq, dev->info.p2p_device_addr, p2p->cfg->dev_addr, dev->info.p2p_device_addr, @@ -369,9 +371,8 @@ int p2p_prov_disc_req(struct p2p_data *p2p, const u8 *peer_addr, else dev->flags &= ~P2P_DEV_PD_FOR_JOIN; - if (p2p->go_neg_peer || - (p2p->state != P2P_IDLE && p2p->state != P2P_SEARCH && - p2p->state != P2P_LISTEN_ONLY)) { + if (p2p->state != P2P_IDLE && p2p->state != P2P_SEARCH && + p2p->state != P2P_LISTEN_ONLY) { wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Busy with other " "operations; postpone Provision Discovery Request " "with " MACSTR " (config methods 0x%x)", diff --git a/src/p2p/p2p_sd.c b/src/p2p/p2p_sd.c index f53d4b5..43b3a61 100644 --- a/src/p2p/p2p_sd.c +++ b/src/p2p/p2p_sd.c @@ -27,7 +27,7 @@ struct p2p_sd_query * p2p_pending_sd_req(struct p2p_data *p2p, struct p2p_sd_query *q; if (!(dev->info.dev_capab & P2P_DEV_CAPAB_SERVICE_DISCOVERY)) - return NULL; /* peer does not support SD */ + return 0; /* peer does not support SD */ for (q = p2p->sd_queries; q; q = q->next) { if (q->for_all_peers && !(dev->flags & P2P_DEV_SD_INFO)) diff --git a/src/radius/radius.c b/src/radius/radius.c index 3ead847..fb03a25 100644 --- a/src/radius/radius.c +++ b/src/radius/radius.c @@ -218,8 +218,6 @@ static struct radius_attr_type radius_attrs[] = { RADIUS_ATTR_TUNNEL_TYPE, "Tunnel-Type", RADIUS_ATTR_HEXDUMP }, { RADIUS_ATTR_TUNNEL_MEDIUM_TYPE, "Tunnel-Medium-Type", RADIUS_ATTR_HEXDUMP }, - { RADIUS_ATTR_TUNNEL_PASSWORD, "Tunnel-Password", - RADIUS_ATTR_UNDIST }, { RADIUS_ATTR_CONNECT_INFO, "Connect-Info", RADIUS_ATTR_TEXT }, { RADIUS_ATTR_EAP_MESSAGE, "EAP-Message", RADIUS_ATTR_UNDIST }, { RADIUS_ATTR_MESSAGE_AUTHENTICATOR, "Message-Authenticator", @@ -1277,120 +1275,6 @@ int radius_msg_get_vlanid(struct radius_msg *msg) } -/** - * radius_msg_get_tunnel_password - Parse RADIUS attribute Tunnel-Password - * @msg: Received RADIUS message - * @keylen: Length of returned password - * @secret: RADIUS shared secret - * @secret_len: Length of secret - * @sent_msg: Sent RADIUS message - * Returns: pointer to password (free with os_free) or %NULL - */ -char * radius_msg_get_tunnel_password(struct radius_msg *msg, int *keylen, - const u8 *secret, size_t secret_len, - struct radius_msg *sent_msg) -{ - u8 *buf = NULL; - size_t buflen; - const u8 *salt; - u8 *str; - const u8 *addr[3]; - size_t len[3]; - u8 hash[16]; - u8 *pos; - size_t i; - struct radius_attr_hdr *attr; - const u8 *data; - size_t dlen; - const u8 *fdata = NULL; /* points to found item */ - size_t fdlen = -1; - char *ret = NULL; - - /* find attribute with lowest tag and check it */ - for (i = 0; i < msg->attr_used; i++) { - attr = radius_get_attr_hdr(msg, i); - if (attr == NULL || - attr->type != RADIUS_ATTR_TUNNEL_PASSWORD) { - continue; - } - if (attr->length <= 5) - continue; - data = (const u8 *) (attr + 1); - dlen = attr->length - sizeof(*attr); - if (dlen <= 3 || dlen % 16 != 3) - continue; - if (fdata != NULL && fdata[0] <= data[0]) - continue; - - fdata = data; - fdlen = dlen; - } - if (fdata == NULL) - goto out; - - /* alloc writable memory for decryption */ - buf = os_malloc(fdlen); - if (buf == NULL) - goto out; - os_memcpy(buf, fdata, fdlen); - buflen = fdlen; - - /* init pointers */ - salt = buf + 1; - str = buf + 3; - - /* decrypt blocks */ - pos = buf + buflen - 16; /* last block */ - while (pos >= str + 16) { /* all but the first block */ - addr[0] = secret; - len[0] = secret_len; - addr[1] = pos - 16; - len[1] = 16; - md5_vector(2, addr, len, hash); - - for (i = 0; i < 16; i++) - pos[i] ^= hash[i]; - - pos -= 16; - } - - /* decrypt first block */ - if (str != pos) - goto out; - addr[0] = secret; - len[0] = secret_len; - addr[1] = sent_msg->hdr->authenticator; - len[1] = 16; - addr[2] = salt; - len[2] = 2; - md5_vector(3, addr, len, hash); - - for (i = 0; i < 16; i++) - pos[i] ^= hash[i]; - - /* derive plaintext length from first subfield */ - *keylen = (unsigned char) str[0]; - if ((u8 *) (str + *keylen) >= (u8 *) (buf + buflen)) { - /* decryption error - invalid key length */ - goto out; - } - if (*keylen == 0) { - /* empty password */ - goto out; - } - - /* copy passphrase into new buffer */ - ret = os_malloc(*keylen); - if (ret) - os_memcpy(ret, str + 1, *keylen); - -out: - /* return new buffer */ - os_free(buf); - return ret; -} - - void radius_free_class(struct radius_class_data *c) { size_t i; diff --git a/src/radius/radius.h b/src/radius/radius.h index e69a047..a3cdac0 100644 --- a/src/radius/radius.h +++ b/src/radius/radius.h @@ -82,7 +82,6 @@ enum { RADIUS_ATTR_USER_NAME = 1, RADIUS_ATTR_NAS_PORT_TYPE = 61, RADIUS_ATTR_TUNNEL_TYPE = 64, RADIUS_ATTR_TUNNEL_MEDIUM_TYPE = 65, - RADIUS_ATTR_TUNNEL_PASSWORD = 69, RADIUS_ATTR_CONNECT_INFO = 77, RADIUS_ATTR_EAP_MESSAGE = 79, RADIUS_ATTR_MESSAGE_AUTHENTICATOR = 80, @@ -232,9 +231,6 @@ radius_msg_add_attr_user_password(struct radius_msg *msg, const u8 *secret, size_t secret_len); int radius_msg_get_attr(struct radius_msg *msg, u8 type, u8 *buf, size_t len); int radius_msg_get_vlanid(struct radius_msg *msg); -char * radius_msg_get_tunnel_password(struct radius_msg *msg, int *keylen, - const u8 *secret, size_t secret_len, - struct radius_msg *sent_msg); static inline int radius_msg_add_attr_int32(struct radius_msg *msg, u8 type, u32 value) diff --git a/src/radius/radius_client.c b/src/radius/radius_client.c index 691f77a..9ec95a2 100644 --- a/src/radius/radius_client.c +++ b/src/radius/radius_client.c @@ -684,7 +684,7 @@ int radius_client_send(struct radius_client_data *radius, radius_client_list_add(radius, msg, msg_type, shared_secret, shared_secret_len, addr); - return res; + return 0; } diff --git a/src/radius/radius_server.c b/src/radius/radius_server.c index 47948bc..6f1c3a5 100644 --- a/src/radius/radius_server.c +++ b/src/radius/radius_server.c @@ -1,6 +1,6 @@ /* * RADIUS authentication server - * Copyright (c) 2005-2009, 2011, Jouni Malinen + * Copyright (c) 2005-2009, Jouni Malinen * * 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 @@ -292,10 +292,6 @@ struct radius_server_data { * msg_ctx - Context data for wpa_msg() calls */ void *msg_ctx; - -#ifdef CONFIG_RADIUS_TEST - char *dump_msk_file; -#endif /* CONFIG_RADIUS_TEST */ }; @@ -578,24 +574,6 @@ radius_server_encapsulate_eap(struct radius_server_data *data, if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->eap_if->eapKeyData) { int len; -#ifdef CONFIG_RADIUS_TEST - if (data->dump_msk_file) { - FILE *f; - char buf[2 * 64 + 1]; - f = fopen(data->dump_msk_file, "a"); - if (f) { - len = sess->eap_if->eapKeyDataLen; - if (len > 64) - len = 64; - len = wpa_snprintf_hex( - buf, sizeof(buf), - sess->eap_if->eapKeyData, len); - buf[len] = '\0'; - fprintf(f, "%s\n", buf); - fclose(f); - } - } -#endif /* CONFIG_RADIUS_TEST */ if (sess->eap_if->eapKeyDataLen > 64) { len = 32; } else { @@ -1299,11 +1277,6 @@ radius_server_init(struct radius_server_conf *conf) } } -#ifdef CONFIG_RADIUS_TEST - if (conf->dump_msk_file) - data->dump_msk_file = os_strdup(conf->dump_msk_file); -#endif /* CONFIG_RADIUS_TEST */ - data->clients = radius_server_read_clients(conf->client_file, conf->ipv6); if (data->clients == NULL) { @@ -1355,9 +1328,6 @@ void radius_server_deinit(struct radius_server_data *data) os_free(data->eap_fast_a_id); os_free(data->eap_fast_a_id_info); os_free(data->eap_req_id_text); -#ifdef CONFIG_RADIUS_TEST - os_free(data->dump_msk_file); -#endif /* CONFIG_RADIUS_TEST */ os_free(data); } diff --git a/src/radius/radius_server.h b/src/radius/radius_server.h index 8d6e2ab..126e314 100644 --- a/src/radius/radius_server.h +++ b/src/radius/radius_server.h @@ -1,6 +1,6 @@ /* * RADIUS authentication server - * Copyright (c) 2005-2009, 2011, Jouni Malinen + * Copyright (c) 2005-2009, Jouni Malinen * * 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 @@ -201,10 +201,6 @@ struct radius_server_conf { * msg_ctx - Context data for wpa_msg() calls */ void *msg_ctx; - -#ifdef CONFIG_RADIUS_TEST - const char *dump_msk_file; -#endif /* CONFIG_RADIUS_TEST */ }; diff --git a/src/rsn_supp/preauth.c b/src/rsn_supp/preauth.c index fefca83..6109f5e 100644 --- a/src/rsn_supp/preauth.c +++ b/src/rsn_supp/preauth.c @@ -22,6 +22,7 @@ #include "preauth.h" #include "pmksa_cache.h" #include "wpa_i.h" +#include "common/ieee802_11_defs.h" #if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA2) diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c index dbf5996..f6fd7da 100644 --- a/src/rsn_supp/wpa_ft.c +++ b/src/rsn_supp/wpa_ft.c @@ -21,6 +21,7 @@ #include "common/ieee802_11_common.h" #include "wpa.h" #include "wpa_i.h" +#include "wpa_ie.h" #ifdef CONFIG_IEEE80211R diff --git a/src/tls/Makefile b/src/tls/Makefile index 27cdfca..a2da096 100644 --- a/src/tls/Makefile +++ b/src/tls/Makefile @@ -11,8 +11,6 @@ include ../lib.rules CFLAGS += -DCONFIG_INTERNAL_LIBTOMMATH CFLAGS += -DCONFIG_CRYPTO_INTERNAL -CFLAGS += -DCONFIG_TLSV11 -CFLAGS += -DCONFIG_TLSV12 LIB_OBJS= \ asn1.o \ diff --git a/src/tls/libtommath.c b/src/tls/libtommath.c index 7c9857f..1c02167 100644 --- a/src/tls/libtommath.c +++ b/src/tls/libtommath.c @@ -2678,7 +2678,7 @@ mp_montgomery_setup (mp_int * n, mp_digit * rho) * * Based on Algorithm 14.32 on pp.601 of HAC. */ -static int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) +int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) { int ix, res, olduse; mp_word W[MP_WARRAY]; diff --git a/src/tls/pkcs5.c b/src/tls/pkcs5.c index fd9e346..4291b84 100644 --- a/src/tls/pkcs5.c +++ b/src/tls/pkcs5.c @@ -32,7 +32,7 @@ struct pkcs5_params { }; -static enum pkcs5_alg pkcs5_get_alg(struct asn1_oid *oid) +enum pkcs5_alg pkcs5_get_alg(struct asn1_oid *oid) { if (oid->len == 7 && oid->oid[0] == 1 /* iso */ && diff --git a/src/tls/tlsv1_client.c b/src/tls/tlsv1_client.c index d0da588..75b8612 100644 --- a/src/tls/tlsv1_client.c +++ b/src/tls/tlsv1_client.c @@ -1,5 +1,5 @@ /* - * TLS v1.0/v1.1/v1.2 client (RFC 2246, RFC 4346, RFC 5246) + * TLS v1.0 (RFC 2246) and v1.1 (RFC 4346) client * Copyright (c) 2006-2011, Jouni Malinen * * This program is free software; you can redistribute it and/or modify @@ -67,8 +67,7 @@ int tls_derive_keys(struct tlsv1_client *conn, os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN); os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random, TLS_RANDOM_LEN); - if (tls_prf(conn->rl.tls_version, - pre_master_secret, pre_master_secret_len, + if (tls_prf(pre_master_secret, pre_master_secret_len, "master secret", seed, 2 * TLS_RANDOM_LEN, conn->master_secret, TLS_MASTER_SECRET_LEN)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive " @@ -84,8 +83,7 @@ int tls_derive_keys(struct tlsv1_client *conn, key_block_len = 2 * (conn->rl.hash_size + conn->rl.key_material_len); if (conn->rl.tls_version == TLS_VERSION_1) key_block_len += 2 * conn->rl.iv_size; - if (tls_prf(conn->rl.tls_version, - conn->master_secret, TLS_MASTER_SECRET_LEN, + if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, "key expansion", seed, 2 * TLS_RANDOM_LEN, key_block, key_block_len)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive key_block"); @@ -138,23 +136,17 @@ int tls_derive_keys(struct tlsv1_client *conn, * @out_len: Length of the output buffer. * @appl_data: Pointer to application data pointer, or %NULL if dropped * @appl_data_len: Pointer to variable that is set to appl_data length - * @need_more_data: Set to 1 if more data would be needed to complete - * processing * Returns: Pointer to output data, %NULL on failure */ u8 * tlsv1_client_handshake(struct tlsv1_client *conn, const u8 *in_data, size_t in_len, size_t *out_len, u8 **appl_data, - size_t *appl_data_len, int *need_more_data) + size_t *appl_data_len) { const u8 *pos, *end; - u8 *msg = NULL, *in_msg = NULL, *in_pos, *in_end, alert, ct; + u8 *msg = NULL, *in_msg, *in_pos, *in_end, alert, ct; size_t in_msg_len; int no_appl_data; - int used; - - if (need_more_data) - *need_more_data = 0; if (conn->state == CLIENT_HELLO) { if (in_len) @@ -162,19 +154,6 @@ u8 * tlsv1_client_handshake(struct tlsv1_client *conn, return tls_send_client_hello(conn, out_len); } - if (conn->partial_input) { - if (wpabuf_resize(&conn->partial_input, in_len) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " - "memory for pending record"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - goto failed; - } - wpabuf_put_data(conn->partial_input, in_data, in_len); - in_data = wpabuf_head(conn->partial_input); - in_len = wpabuf_len(conn->partial_input); - } - if (in_data == NULL || in_len == 0) return NULL; @@ -187,33 +166,13 @@ u8 * tlsv1_client_handshake(struct tlsv1_client *conn, /* Each received packet may include multiple records */ while (pos < end) { in_msg_len = in_len; - used = tlsv1_record_receive(&conn->rl, pos, end - pos, - in_msg, &in_msg_len, &alert); - if (used < 0) { + if (tlsv1_record_receive(&conn->rl, pos, end - pos, + in_msg, &in_msg_len, &alert)) { wpa_printf(MSG_DEBUG, "TLSv1: Processing received " "record failed"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); goto failed; } - if (used == 0) { - struct wpabuf *partial; - wpa_printf(MSG_DEBUG, "TLSv1: Need more data"); - partial = wpabuf_alloc_copy(pos, end - pos); - wpabuf_free(conn->partial_input); - conn->partial_input = partial; - if (conn->partial_input == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to " - "allocate memory for pending " - "record"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - goto failed; - } - os_free(in_msg); - if (need_more_data) - *need_more_data = 1; - return NULL; - } ct = pos[0]; in_pos = in_msg; @@ -231,7 +190,7 @@ u8 * tlsv1_client_handshake(struct tlsv1_client *conn, in_pos += in_msg_len; } - pos += used; + pos += TLS_RECORD_HEADER_LEN + WPA_GET_BE16(pos + 3); } os_free(in_msg); @@ -243,8 +202,6 @@ u8 * tlsv1_client_handshake(struct tlsv1_client *conn, failed: os_free(in_msg); if (conn->alert_level) { - wpabuf_free(conn->partial_input); - conn->partial_input = NULL; conn->state = FAILED; os_free(msg); msg = tlsv1_client_send_alert(conn, conn->alert_level, @@ -255,11 +212,6 @@ failed: *out_len = 0; } - if (need_more_data == NULL || !(*need_more_data)) { - wpabuf_free(conn->partial_input); - conn->partial_input = NULL; - } - return msg; } @@ -302,116 +254,58 @@ int tlsv1_client_encrypt(struct tlsv1_client *conn, * @conn: TLSv1 client connection data from tlsv1_client_init() * @in_data: Pointer to input buffer (encrypted TLS data) * @in_len: Input buffer length - * @need_more_data: Set to 1 if more data would be needed to complete - * processing - * Returns: Decrypted data or %NULL on failure + * @out_data: Pointer to output buffer (decrypted data from TLS tunnel) + * @out_len: Maximum out_data length + * Returns: Number of bytes written to out_data, -1 on failure * * This function is used after TLS handshake has been completed successfully to * receive data from the encrypted tunnel. */ -struct wpabuf * tlsv1_client_decrypt(struct tlsv1_client *conn, - const u8 *in_data, size_t in_len, - int *need_more_data) +int tlsv1_client_decrypt(struct tlsv1_client *conn, + const u8 *in_data, size_t in_len, + u8 *out_data, size_t out_len) { const u8 *in_end, *pos; - int used; - u8 alert, *out_pos, ct; + int res; + u8 alert, *out_end, *out_pos; size_t olen; - struct wpabuf *buf = NULL; - - if (need_more_data) - *need_more_data = 0; - - if (conn->partial_input) { - if (wpabuf_resize(&conn->partial_input, in_len) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " - "memory for pending record"); - alert = TLS_ALERT_INTERNAL_ERROR; - goto fail; - } - wpabuf_put_data(conn->partial_input, in_data, in_len); - in_data = wpabuf_head(conn->partial_input); - in_len = wpabuf_len(conn->partial_input); - } pos = in_data; in_end = in_data + in_len; + out_pos = out_data; + out_end = out_data + out_len; while (pos < in_end) { - ct = pos[0]; - if (wpabuf_resize(&buf, in_end - pos) < 0) { - alert = TLS_ALERT_INTERNAL_ERROR; - goto fail; + if (pos[0] != TLS_CONTENT_TYPE_APPLICATION_DATA) { + wpa_printf(MSG_DEBUG, "TLSv1: Unexpected content type " + "0x%x", pos[0]); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_UNEXPECTED_MESSAGE); + return -1; } - out_pos = wpabuf_put(buf, 0); - olen = wpabuf_tailroom(buf); - used = tlsv1_record_receive(&conn->rl, pos, in_end - pos, - out_pos, &olen, &alert); - if (used < 0) { + + olen = out_end - out_pos; + res = tlsv1_record_receive(&conn->rl, pos, in_end - pos, + out_pos, &olen, &alert); + if (res < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Record layer processing " "failed"); - goto fail; - } - if (used == 0) { - struct wpabuf *partial; - wpa_printf(MSG_DEBUG, "TLSv1: Need more data"); - partial = wpabuf_alloc_copy(pos, in_end - pos); - wpabuf_free(conn->partial_input); - conn->partial_input = partial; - if (conn->partial_input == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to " - "allocate memory for pending " - "record"); - alert = TLS_ALERT_INTERNAL_ERROR; - goto fail; - } - if (need_more_data) - *need_more_data = 1; - return buf; - } - - if (ct == TLS_CONTENT_TYPE_ALERT) { - if (olen < 2) { - wpa_printf(MSG_DEBUG, "TLSv1: Alert " - "underflow"); - alert = TLS_ALERT_DECODE_ERROR; - goto fail; - } - wpa_printf(MSG_DEBUG, "TLSv1: Received alert %d:%d", - out_pos[0], out_pos[1]); - if (out_pos[0] == TLS_ALERT_LEVEL_WARNING) { - /* Continue processing */ - pos += used; - continue; - } - - alert = out_pos[1]; - goto fail; + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); + return -1; } - - if (ct != TLS_CONTENT_TYPE_APPLICATION_DATA) { - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected content type " - "0x%x when decrypting application data", - pos[0]); - alert = TLS_ALERT_UNEXPECTED_MESSAGE; - goto fail; + out_pos += olen; + if (out_pos > out_end) { + wpa_printf(MSG_DEBUG, "TLSv1: Buffer not large enough " + "for processing the received record"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; } - wpabuf_put(buf, olen); - - pos += used; + pos += TLS_RECORD_HEADER_LEN + WPA_GET_BE16(pos + 3); } - wpabuf_free(conn->partial_input); - conn->partial_input = NULL; - return buf; - -fail: - wpabuf_free(buf); - wpabuf_free(conn->partial_input); - conn->partial_input = NULL; - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); - return NULL; + return out_pos - out_data; } @@ -466,10 +360,8 @@ struct tlsv1_client * tlsv1_client_init(void) count = 0; suites = conn->cipher_suites; #ifndef CONFIG_CRYPTO_INTERNAL - suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA256; suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA; #endif /* CONFIG_CRYPTO_INTERNAL */ - suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA256; suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA; suites[count++] = TLS_RSA_WITH_3DES_EDE_CBC_SHA; suites[count++] = TLS_RSA_WITH_RC4_128_SHA; @@ -496,7 +388,6 @@ void tlsv1_client_deinit(struct tlsv1_client *conn) os_free(conn->client_hello_ext); tlsv1_client_free_dh(conn); tlsv1_cred_free(conn->cred); - wpabuf_free(conn->partial_input); os_free(conn); } @@ -540,8 +431,7 @@ int tlsv1_client_prf(struct tlsv1_client *conn, const char *label, TLS_RANDOM_LEN); } - return tls_prf(conn->rl.tls_version, - conn->master_secret, TLS_MASTER_SECRET_LEN, + return tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, label, seed, 2 * TLS_RANDOM_LEN, out, out_len); } @@ -573,24 +463,15 @@ int tlsv1_client_get_cipher(struct tlsv1_client *conn, char *buf, case TLS_RSA_WITH_3DES_EDE_CBC_SHA: cipher = "DES-CBC3-SHA"; break; - case TLS_DH_anon_WITH_AES_128_CBC_SHA256: - cipher = "ADH-AES-128-SHA256"; - break; case TLS_DH_anon_WITH_AES_128_CBC_SHA: cipher = "ADH-AES-128-SHA"; break; case TLS_RSA_WITH_AES_256_CBC_SHA: cipher = "AES-256-SHA"; break; - case TLS_RSA_WITH_AES_256_CBC_SHA256: - cipher = "AES-256-SHA256"; - break; case TLS_RSA_WITH_AES_128_CBC_SHA: cipher = "AES-128-SHA"; break; - case TLS_RSA_WITH_AES_128_CBC_SHA256: - cipher = "AES-128-SHA256"; - break; default: return -1; } @@ -742,10 +623,8 @@ int tlsv1_client_set_cipher_list(struct tlsv1_client *conn, u8 *ciphers) count = 0; suites = conn->cipher_suites; #ifndef CONFIG_CRYPTO_INTERNAL - suites[count++] = TLS_DH_anon_WITH_AES_256_CBC_SHA256; suites[count++] = TLS_DH_anon_WITH_AES_256_CBC_SHA; #endif /* CONFIG_CRYPTO_INTERNAL */ - suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA256; suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA; suites[count++] = TLS_DH_anon_WITH_3DES_EDE_CBC_SHA; suites[count++] = TLS_DH_anon_WITH_RC4_128_MD5; diff --git a/src/tls/tlsv1_client.h b/src/tls/tlsv1_client.h index ef5e694..a620d62 100644 --- a/src/tls/tlsv1_client.h +++ b/src/tls/tlsv1_client.h @@ -1,5 +1,5 @@ /* - * TLS v1.0/v1.1/v1.2 client (RFC 2246, RFC 4346, RFC 5246) + * TLSv1 client (RFC 2246) * Copyright (c) 2006-2011, Jouni Malinen * * This program is free software; you can redistribute it and/or modify @@ -29,13 +29,13 @@ int tlsv1_client_prf(struct tlsv1_client *conn, const char *label, u8 * tlsv1_client_handshake(struct tlsv1_client *conn, const u8 *in_data, size_t in_len, size_t *out_len, u8 **appl_data, - size_t *appl_data_len, int *need_more_data); + size_t *appl_data_len); int tlsv1_client_encrypt(struct tlsv1_client *conn, const u8 *in_data, size_t in_len, u8 *out_data, size_t out_len); -struct wpabuf * tlsv1_client_decrypt(struct tlsv1_client *conn, - const u8 *in_data, size_t in_len, - int *need_more_data); +int tlsv1_client_decrypt(struct tlsv1_client *conn, + const u8 *in_data, size_t in_len, + u8 *out_data, size_t out_len); int tlsv1_client_get_cipher(struct tlsv1_client *conn, char *buf, size_t buflen); int tlsv1_client_shutdown(struct tlsv1_client *conn); diff --git a/src/tls/tlsv1_client_i.h b/src/tls/tlsv1_client_i.h index 92912ca..f091bcf 100644 --- a/src/tls/tlsv1_client_i.h +++ b/src/tls/tlsv1_client_i.h @@ -68,8 +68,6 @@ struct tlsv1_client { tlsv1_client_session_ticket_cb session_ticket_cb; void *session_ticket_cb_ctx; - - struct wpabuf *partial_input; }; diff --git a/src/tls/tlsv1_client_read.c b/src/tls/tlsv1_client_read.c index eb0cbef..457c3b0 100644 --- a/src/tls/tlsv1_client_read.c +++ b/src/tls/tlsv1_client_read.c @@ -1,5 +1,5 @@ /* - * TLSv1 client - read handshake message + * TLS v1.0 (RFC 2246) and v1.1 (RFC 4346) client - read handshake message * Copyright (c) 2006-2011, Jouni Malinen * * This program is free software; you can redistribute it and/or modify @@ -17,7 +17,6 @@ #include "common.h" #include "crypto/md5.h" #include "crypto/sha1.h" -#include "crypto/sha256.h" #include "crypto/tls.h" #include "x509v3.h" #include "tlsv1_common.h" @@ -82,7 +81,9 @@ static int tls_process_server_hello(struct tlsv1_client *conn, u8 ct, if (end - pos < 2) goto decode_error; tls_version = WPA_GET_BE16(pos); - if (!tls_version_ok(tls_version)) { + if (tls_version != TLS_VERSION_1 && + (tls_version != TLS_VERSION_1_1 || + TLS_VERSION == TLS_VERSION_1)) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected protocol version in " "ServerHello %u.%u", pos[0], pos[1]); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, @@ -92,7 +93,7 @@ static int tls_process_server_hello(struct tlsv1_client *conn, u8 ct, pos += 2; wpa_printf(MSG_DEBUG, "TLSv1: Using TLS v%s", - tls_version_str(tls_version)); + tls_version == TLS_VERSION_1_1 ? "1.1" : "1.0"); conn->rl.tls_version = tls_version; /* Random random */ @@ -823,21 +824,6 @@ static int tls_process_server_finished(struct tlsv1_client *conn, u8 ct, wpa_hexdump(MSG_MSGDUMP, "TLSv1: verify_data in Finished", pos, TLS_VERIFY_DATA_LEN); -#ifdef CONFIG_TLSV12 - if (conn->rl.tls_version >= TLS_VERSION_1_2) { - hlen = SHA256_MAC_LEN; - if (conn->verify.sha256_server == NULL || - crypto_hash_finish(conn->verify.sha256_server, hash, &hlen) - < 0) { - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - conn->verify.sha256_server = NULL; - return -1; - } - conn->verify.sha256_server = NULL; - } else { -#endif /* CONFIG_TLSV12 */ - hlen = MD5_MAC_LEN; if (conn->verify.md5_server == NULL || crypto_hash_finish(conn->verify.md5_server, hash, &hlen) < 0) { @@ -859,15 +845,9 @@ static int tls_process_server_finished(struct tlsv1_client *conn, u8 ct, return -1; } conn->verify.sha1_server = NULL; - hlen = MD5_MAC_LEN + SHA1_MAC_LEN; - -#ifdef CONFIG_TLSV12 - } -#endif /* CONFIG_TLSV12 */ - if (tls_prf(conn->rl.tls_version, - conn->master_secret, TLS_MASTER_SECRET_LEN, - "server finished", hash, hlen, + if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, + "server finished", hash, MD5_MAC_LEN + SHA1_MAC_LEN, verify_data, TLS_VERIFY_DATA_LEN)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive verify_data"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, diff --git a/src/tls/tlsv1_client_write.c b/src/tls/tlsv1_client_write.c index 35a238b..9d53dd1 100644 --- a/src/tls/tlsv1_client_write.c +++ b/src/tls/tlsv1_client_write.c @@ -1,5 +1,5 @@ /* - * TLSv1 client - write handshake message + * TLS v1.0 (RFC 2246) and v1.1 (RFC 4346) client - write handshake message * Copyright (c) 2006-2011, Jouni Malinen * * This program is free software; you can redistribute it and/or modify @@ -17,7 +17,6 @@ #include "common.h" #include "crypto/md5.h" #include "crypto/sha1.h" -#include "crypto/sha256.h" #include "crypto/tls.h" #include "crypto/random.h" #include "x509v3.h" @@ -437,7 +436,7 @@ static int tls_write_client_certificate_verify(struct tlsv1_client *conn, { u8 *pos, *rhdr, *hs_start, *hs_length, *signed_start; size_t rlen, hlen, clen; - u8 hash[100], *hpos; + u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN], *hpos; enum { SIGN_ALG_RSA, SIGN_ALG_DSA } alg = SIGN_ALG_RSA; pos = *msgpos; @@ -477,40 +476,6 @@ static int tls_write_client_certificate_verify(struct tlsv1_client *conn, hpos = hash; -#ifdef CONFIG_TLSV12 - if (conn->rl.tls_version == TLS_VERSION_1_2) { - hlen = SHA256_MAC_LEN; - if (conn->verify.sha256_cert == NULL || - crypto_hash_finish(conn->verify.sha256_cert, hpos, &hlen) < - 0) { - conn->verify.sha256_cert = NULL; - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - conn->verify.sha256_cert = NULL; - - /* - * RFC 3447, A.2.4 RSASSA-PKCS1-v1_5 - * - * DigestInfo ::= SEQUENCE { - * digestAlgorithm DigestAlgorithm, - * digest OCTET STRING - * } - * - * SHA-256 OID: sha256WithRSAEncryption ::= {pkcs-1 11} - * - * DER encoded DigestInfo for SHA256 per RFC 3447: - * 30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 || - * H - */ - os_memmove(hash + 19, hash, hlen); - hlen += 19; - os_memcpy(hash, "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65" - "\x03\x04\x02\x01\x05\x00\x04\x20", 19); - } else { -#endif /* CONFIG_TLSV12 */ - if (alg == SIGN_ALG_RSA) { hlen = MD5_MAC_LEN; if (conn->verify.md5_cert == NULL || @@ -541,29 +506,8 @@ static int tls_write_client_certificate_verify(struct tlsv1_client *conn, if (alg == SIGN_ALG_RSA) hlen += MD5_MAC_LEN; -#ifdef CONFIG_TLSV12 - } -#endif /* CONFIG_TLSV12 */ - wpa_hexdump(MSG_MSGDUMP, "TLSv1: CertificateVerify hash", hash, hlen); -#ifdef CONFIG_TLSV12 - if (conn->rl.tls_version >= TLS_VERSION_1_2) { - /* - * RFC 5246, 4.7: - * TLS v1.2 adds explicit indication of the used signature and - * hash algorithms. - * - * struct { - * HashAlgorithm hash; - * SignatureAlgorithm signature; - * } SignatureAndHashAlgorithm; - */ - *pos++ = TLS_HASH_ALG_SHA256; - *pos++ = TLS_SIGN_ALG_RSA; - } -#endif /* CONFIG_TLSV12 */ - /* * RFC 2246, 4.7: * In digital signing, one-way hash functions are used as input for a @@ -655,21 +599,6 @@ static int tls_write_client_finished(struct tlsv1_client *conn, /* Encrypted Handshake Message: Finished */ -#ifdef CONFIG_TLSV12 - if (conn->rl.tls_version >= TLS_VERSION_1_2) { - hlen = SHA256_MAC_LEN; - if (conn->verify.sha256_client == NULL || - crypto_hash_finish(conn->verify.sha256_client, hash, &hlen) - < 0) { - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - conn->verify.sha256_client = NULL; - return -1; - } - conn->verify.sha256_client = NULL; - } else { -#endif /* CONFIG_TLSV12 */ - hlen = MD5_MAC_LEN; if (conn->verify.md5_client == NULL || crypto_hash_finish(conn->verify.md5_client, hash, &hlen) < 0) { @@ -691,15 +620,9 @@ static int tls_write_client_finished(struct tlsv1_client *conn, return -1; } conn->verify.sha1_client = NULL; - hlen = MD5_MAC_LEN + SHA1_MAC_LEN; - -#ifdef CONFIG_TLSV12 - } -#endif /* CONFIG_TLSV12 */ - if (tls_prf(conn->rl.tls_version, - conn->master_secret, TLS_MASTER_SECRET_LEN, - "client finished", hash, hlen, + if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, + "client finished", hash, MD5_MAC_LEN + SHA1_MAC_LEN, verify_data + 1 + 3, TLS_VERIFY_DATA_LEN)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate verify_data"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, diff --git a/src/tls/tlsv1_common.c b/src/tls/tlsv1_common.c index 871359a..2f9dd0f 100644 --- a/src/tls/tlsv1_common.c +++ b/src/tls/tlsv1_common.c @@ -1,6 +1,6 @@ /* * TLSv1 common routines - * Copyright (c) 2006-2011, Jouni Malinen + * Copyright (c) 2006-2007, Jouni Malinen * * 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 @@ -15,8 +15,6 @@ #include "includes.h" #include "common.h" -#include "crypto/sha1.h" -#include "crypto/sha256.h" #include "x509v3.h" #include "tlsv1_common.h" @@ -52,15 +50,7 @@ static const struct tls_cipher_suite tls_cipher_suites[] = { { TLS_RSA_WITH_AES_256_CBC_SHA, TLS_KEY_X_RSA, TLS_CIPHER_AES_256_CBC, TLS_HASH_SHA }, { TLS_DH_anon_WITH_AES_256_CBC_SHA, TLS_KEY_X_DH_anon, - TLS_CIPHER_AES_256_CBC, TLS_HASH_SHA }, - { TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_KEY_X_RSA, - TLS_CIPHER_AES_128_CBC, TLS_HASH_SHA256 }, - { TLS_RSA_WITH_AES_256_CBC_SHA256, TLS_KEY_X_RSA, - TLS_CIPHER_AES_256_CBC, TLS_HASH_SHA256 }, - { TLS_DH_anon_WITH_AES_128_CBC_SHA256, TLS_KEY_X_DH_anon, - TLS_CIPHER_AES_128_CBC, TLS_HASH_SHA256 }, - { TLS_DH_anon_WITH_AES_256_CBC_SHA256, TLS_KEY_X_DH_anon, - TLS_CIPHER_AES_256_CBC, TLS_HASH_SHA256 } + TLS_CIPHER_AES_256_CBC, TLS_HASH_SHA } }; #define NUM_ELEMS(a) (sizeof(a) / sizeof((a)[0])) @@ -212,19 +202,6 @@ int tls_verify_hash_init(struct tls_verify_hash *verify) tls_verify_hash_free(verify); return -1; } -#ifdef CONFIG_TLSV12 - verify->sha256_client = crypto_hash_init(CRYPTO_HASH_ALG_SHA256, NULL, - 0); - verify->sha256_server = crypto_hash_init(CRYPTO_HASH_ALG_SHA256, NULL, - 0); - verify->sha256_cert = crypto_hash_init(CRYPTO_HASH_ALG_SHA256, NULL, - 0); - if (verify->sha256_client == NULL || verify->sha256_server == NULL || - verify->sha256_cert == NULL) { - tls_verify_hash_free(verify); - return -1; - } -#endif /* CONFIG_TLSV12 */ return 0; } @@ -244,14 +221,6 @@ void tls_verify_hash_add(struct tls_verify_hash *verify, const u8 *buf, crypto_hash_update(verify->md5_cert, buf, len); crypto_hash_update(verify->sha1_cert, buf, len); } -#ifdef CONFIG_TLSV12 - if (verify->sha256_client) - crypto_hash_update(verify->sha256_client, buf, len); - if (verify->sha256_server) - crypto_hash_update(verify->sha256_server, buf, len); - if (verify->sha256_cert) - crypto_hash_update(verify->sha256_cert, buf, len); -#endif /* CONFIG_TLSV12 */ } @@ -269,60 +238,4 @@ void tls_verify_hash_free(struct tls_verify_hash *verify) verify->sha1_client = NULL; verify->sha1_server = NULL; verify->sha1_cert = NULL; -#ifdef CONFIG_TLSV12 - crypto_hash_finish(verify->sha256_client, NULL, NULL); - crypto_hash_finish(verify->sha256_server, NULL, NULL); - crypto_hash_finish(verify->sha256_cert, NULL, NULL); - verify->sha256_client = NULL; - verify->sha256_server = NULL; - verify->sha256_cert = NULL; -#endif /* CONFIG_TLSV12 */ -} - - -int tls_version_ok(u16 ver) -{ - if (ver == TLS_VERSION_1) - return 1; -#ifdef CONFIG_TLSV11 - if (ver == TLS_VERSION_1_1) - return 1; -#endif /* CONFIG_TLSV11 */ -#ifdef CONFIG_TLSV12 - if (ver == TLS_VERSION_1_2) - return 1; -#endif /* CONFIG_TLSV12 */ - - return 0; -} - - -const char * tls_version_str(u16 ver) -{ - switch (ver) { - case TLS_VERSION_1: - return "1.0"; - case TLS_VERSION_1_1: - return "1.1"; - case TLS_VERSION_1_2: - return "1.2"; - } - - return "?"; -} - - -int tls_prf(u16 ver, const u8 *secret, size_t secret_len, const char *label, - const u8 *seed, size_t seed_len, u8 *out, size_t outlen) -{ -#ifdef CONFIG_TLSV12 - if (ver >= TLS_VERSION_1_2) { - tls_prf_sha256(secret, secret_len, label, seed, seed_len, - out, outlen); - return 0; - } -#endif /* CONFIG_TLSV12 */ - - return tls_prf_sha1_md5(secret, secret_len, label, seed, seed_len, out, - outlen); } diff --git a/src/tls/tlsv1_common.h b/src/tls/tlsv1_common.h index 027daa4..712d276 100644 --- a/src/tls/tlsv1_common.h +++ b/src/tls/tlsv1_common.h @@ -1,5 +1,5 @@ /* - * TLSv1 common definitions + * TLS v1.0 (RFC 2246) and v1.1 (RFC 4346) common definitions * Copyright (c) 2006-2011, Jouni Malinen * * This program is free software; you can redistribute it and/or modify @@ -19,16 +19,11 @@ #define TLS_VERSION_1 0x0301 /* TLSv1 */ #define TLS_VERSION_1_1 0x0302 /* TLSv1.1 */ -#define TLS_VERSION_1_2 0x0303 /* TLSv1.2 */ -#ifdef CONFIG_TLSV12 -#define TLS_VERSION TLS_VERSION_1_2 -#else /* CONFIG_TLSV12 */ #ifdef CONFIG_TLSV11 #define TLS_VERSION TLS_VERSION_1_1 #else /* CONFIG_TLSV11 */ #define TLS_VERSION TLS_VERSION_1 #endif /* CONFIG_TLSV11 */ -#endif /* CONFIG_TLSV12 */ #define TLS_RANDOM_LEN 32 #define TLS_PRE_MASTER_SECRET_LEN 48 #define TLS_MASTER_SECRET_LEN 48 @@ -93,42 +88,10 @@ enum { #define TLS_DHE_DSS_WITH_AES_256_CBC_SHA 0x0038 /* RFC 3268 */ #define TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x0039 /* RFC 3268 */ #define TLS_DH_anon_WITH_AES_256_CBC_SHA 0x003A /* RFC 3268 */ -#define TLS_RSA_WITH_NULL_SHA256 0x003B /* RFC 5246 */ -#define TLS_RSA_WITH_AES_128_CBC_SHA256 0x003C /* RFC 5246 */ -#define TLS_RSA_WITH_AES_256_CBC_SHA256 0x003D /* RFC 5246 */ -#define TLS_DH_DSS_WITH_AES_128_CBC_SHA256 0x003E /* RFC 5246 */ -#define TLS_DH_RSA_WITH_AES_128_CBC_SHA256 0x003F /* RFC 5246 */ -#define TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 0x0040 /* RFC 5246 */ -#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x0067 /* RFC 5246 */ -#define TLS_DH_DSS_WITH_AES_256_CBC_SHA256 0x0068 /* RFC 5246 */ -#define TLS_DH_RSA_WITH_AES_256_CBC_SHA256 0x0069 /* RFC 5246 */ -#define TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 0x006A /* RFC 5246 */ -#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x006B /* RFC 5246 */ -#define TLS_DH_anon_WITH_AES_128_CBC_SHA256 0x006C /* RFC 5246 */ -#define TLS_DH_anon_WITH_AES_256_CBC_SHA256 0x006D /* RFC 5246 */ /* CompressionMethod */ #define TLS_COMPRESSION_NULL 0 -/* HashAlgorithm */ -enum { - TLS_HASH_ALG_NONE = 0, - TLS_HASH_ALG_MD5 = 1, - TLS_HASH_ALG_SHA1 = 2, - TLS_HASH_ALG_SHA224 = 3, - TLS_HASH_ALG_SHA256 = 4, - TLS_HASH_ALG_SHA384 = 5, - TLS_HASH_ALG_SHA512 = 6 -}; - -/* SignatureAlgorithm */ -enum { - TLS_SIGN_ALG_ANONYMOUS = 0, - TLS_SIGN_ALG_RSA = 1, - TLS_SIGN_ALG_DSA = 2, - TLS_SIGN_ALG_ECDSA = 3, -}; - /* AlertLevel */ #define TLS_ALERT_LEVEL_WARNING 1 #define TLS_ALERT_LEVEL_FATAL 2 @@ -212,8 +175,7 @@ typedef enum { typedef enum { TLS_HASH_NULL, TLS_HASH_MD5, - TLS_HASH_SHA, - TLS_HASH_SHA256 + TLS_HASH_SHA } tls_hash; struct tls_cipher_suite { @@ -241,13 +203,10 @@ struct tls_cipher_data { struct tls_verify_hash { struct crypto_hash *md5_client; struct crypto_hash *sha1_client; - struct crypto_hash *sha256_client; struct crypto_hash *md5_server; struct crypto_hash *sha1_server; - struct crypto_hash *sha256_server; struct crypto_hash *md5_cert; struct crypto_hash *sha1_cert; - struct crypto_hash *sha256_cert; }; @@ -259,9 +218,5 @@ int tls_verify_hash_init(struct tls_verify_hash *verify); void tls_verify_hash_add(struct tls_verify_hash *verify, const u8 *buf, size_t len); void tls_verify_hash_free(struct tls_verify_hash *verify); -int tls_version_ok(u16 ver); -const char * tls_version_str(u16 ver); -int tls_prf(u16 ver, const u8 *secret, size_t secret_len, const char *label, - const u8 *seed, size_t seed_len, u8 *out, size_t outlen); #endif /* TLSV1_COMMON_H */ diff --git a/src/tls/tlsv1_cred.c b/src/tls/tlsv1_cred.c index d846480..3e07245 100644 --- a/src/tls/tlsv1_cred.c +++ b/src/tls/tlsv1_cred.c @@ -244,17 +244,10 @@ static struct crypto_private_key * tlsv1_set_key_pem(const u8 *key, size_t len) if (!end) return NULL; } else { - const u8 *pos2; pos += os_strlen(pem_key_begin); end = search_tag(pem_key_end, pos, key + len - pos); if (!end) return NULL; - pos2 = search_tag("Proc-Type: 4,ENCRYPTED", pos, end - pos); - if (pos2) { - wpa_printf(MSG_DEBUG, "TLSv1: Unsupported private key " - "format (Proc-Type/DEK-Info)"); - return NULL; - } } der = base64_decode(pos, end - pos, &der_len); diff --git a/src/tls/tlsv1_record.c b/src/tls/tlsv1_record.c index 0314551..e072324 100644 --- a/src/tls/tlsv1_record.c +++ b/src/tls/tlsv1_record.c @@ -1,5 +1,5 @@ /* - * TLSv1 Record Protocol + * TLS v1.0 (RFC 2246) and v1.1 (RFC 4346) Record Protocol * Copyright (c) 2006-2011, Jouni Malinen * * This program is free software; you can redistribute it and/or modify @@ -17,7 +17,6 @@ #include "common.h" #include "crypto/md5.h" #include "crypto/sha1.h" -#include "crypto/sha256.h" #include "tlsv1_common.h" #include "tlsv1_record.h" @@ -53,9 +52,6 @@ int tlsv1_record_set_cipher_suite(struct tlsv1_record_layer *rl, } else if (suite->hash == TLS_HASH_SHA) { rl->hash_alg = CRYPTO_HASH_ALG_HMAC_SHA1; rl->hash_size = SHA1_MAC_LEN; - } else if (suite->hash == TLS_HASH_SHA256) { - rl->hash_alg = CRYPTO_HASH_ALG_HMAC_SHA256; - rl->hash_size = SHA256_MAC_LEN; } data = tls_get_cipher_data(suite->cipher); @@ -179,7 +175,7 @@ int tlsv1_record_send(struct tlsv1_record_layer *rl, u8 content_type, u8 *buf, cpayload = pos; explicit_iv = rl->write_cipher_suite != TLS_NULL_WITH_NULL_NULL && - rl->iv_size && rl->tls_version >= TLS_VERSION_1_1; + rl->iv_size && rl->tls_version == TLS_VERSION_1_1; if (explicit_iv) { /* opaque IV[Cipherspec.block_length] */ if (pos + rl->iv_size > buf + buf_size) @@ -275,8 +271,7 @@ int tlsv1_record_send(struct tlsv1_record_layer *rl, u8 content_type, u8 *buf, * @out_len: Set to maximum out_data length by caller; used to return the * length of the used data * @alert: Buffer for returning an alert value on failure - * Returns: Number of bytes used from in_data on success, 0 if record was not - * complete (more data needed), or -1 on failure + * Returns: 0 on success, -1 on failure * * This function decrypts the received message, verifies HMAC and TLS record * layer header. @@ -290,21 +285,30 @@ int tlsv1_record_receive(struct tlsv1_record_layer *rl, struct crypto_hash *hmac; u8 len[2], hash[100]; int force_mac_error = 0; - u8 ct; + + wpa_hexdump(MSG_MSGDUMP, "TLSv1: Record Layer - Received", + in_data, in_len); if (in_len < TLS_RECORD_HEADER_LEN) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short record (in_len=%lu) - " - "need more data", + wpa_printf(MSG_DEBUG, "TLSv1: Too short record (in_len=%lu)", (unsigned long) in_len); - wpa_hexdump(MSG_MSGDUMP, "TLSv1: Record Layer - Received", - in_data, in_len); - return 0; + *alert = TLS_ALERT_DECODE_ERROR; + return -1; } - ct = in_data[0]; - rlen = WPA_GET_BE16(in_data + 3); wpa_printf(MSG_DEBUG, "TLSv1: Received content type %d version %d.%d " - "length %d", ct, in_data[1], in_data[2], (int) rlen); + "length %d", in_data[0], in_data[1], in_data[2], + WPA_GET_BE16(in_data + 3)); + + if (in_data[0] != TLS_CONTENT_TYPE_HANDSHAKE && + in_data[0] != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC && + in_data[0] != TLS_CONTENT_TYPE_ALERT && + in_data[0] != TLS_CONTENT_TYPE_APPLICATION_DATA) { + wpa_printf(MSG_DEBUG, "TLSv1: Unexpected content type 0x%x", + in_data[0]); + *alert = TLS_ALERT_UNEXPECTED_MESSAGE; + return -1; + } /* * TLS v1.0 and v1.1 RFCs were not exactly clear on the use of the @@ -318,6 +322,8 @@ int tlsv1_record_receive(struct tlsv1_record_layer *rl, return -1; } + rlen = WPA_GET_BE16(in_data + 3); + /* TLSCiphertext must not be more than 2^14+2048 bytes */ if (TLS_RECORD_HEADER_LEN + rlen > 18432) { wpa_printf(MSG_DEBUG, "TLSv1: Record overflow (len=%lu)", @@ -333,19 +339,7 @@ int tlsv1_record_receive(struct tlsv1_record_layer *rl, wpa_printf(MSG_DEBUG, "TLSv1: Not all record data included " "(rlen=%lu > in_len=%lu)", (unsigned long) rlen, (unsigned long) in_len); - return 0; - } - - wpa_hexdump(MSG_MSGDUMP, "TLSv1: Record Layer - Received", - in_data, rlen); - - if (ct != TLS_CONTENT_TYPE_HANDSHAKE && - ct != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC && - ct != TLS_CONTENT_TYPE_ALERT && - ct != TLS_CONTENT_TYPE_APPLICATION_DATA) { - wpa_printf(MSG_DEBUG, "TLSv1: Ignore record with unknown " - "content type 0x%x", ct); - *alert = TLS_ALERT_UNEXPECTED_MESSAGE; + *alert = TLS_ALERT_DECODE_ERROR; return -1; } @@ -381,7 +375,7 @@ int tlsv1_record_receive(struct tlsv1_record_layer *rl, * attacks more difficult. */ - if (rl->tls_version >= TLS_VERSION_1_1) { + if (rl->tls_version == TLS_VERSION_1_1) { /* Remove opaque IV[Cipherspec.block_length] */ if (plen < rl->iv_size) { wpa_printf(MSG_DEBUG, "TLSv1.1: Not " @@ -423,13 +417,13 @@ int tlsv1_record_receive(struct tlsv1_record_layer *rl, } plen -= padlen + 1; - - wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Record Layer - " - "Decrypted data with IV and padding " - "removed", out_data, plen); } check_mac: + wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Record Layer - Decrypted " + "data with IV and padding removed", + out_data, plen); + if (plen < rl->hash_size) { wpa_printf(MSG_DEBUG, "TLSv1: Too short record; no " "hash value"); @@ -487,5 +481,5 @@ int tlsv1_record_receive(struct tlsv1_record_layer *rl, inc_byte_array(rl->read_seq_num, TLS_SEQ_NUM_LEN); - return TLS_RECORD_HEADER_LEN + rlen; + return 0; } diff --git a/src/tls/tlsv1_record.h b/src/tls/tlsv1_record.h index 9eb9bfd..0d62816 100644 --- a/src/tls/tlsv1_record.h +++ b/src/tls/tlsv1_record.h @@ -1,5 +1,5 @@ /* - * TLSv1 Record Protocol + * TLS v1.0 (RFC 2246) and v1.1 (RFC 4346) Record Protocol * Copyright (c) 2006-2011, Jouni Malinen * * This program is free software; you can redistribute it and/or modify @@ -17,7 +17,7 @@ #include "crypto/crypto.h" -#define TLS_MAX_WRITE_MAC_SECRET_LEN 32 +#define TLS_MAX_WRITE_MAC_SECRET_LEN 20 #define TLS_MAX_WRITE_KEY_LEN 32 #define TLS_MAX_IV_LEN 16 #define TLS_MAX_KEY_BLOCK_LEN (2 * (TLS_MAX_WRITE_MAC_SECRET_LEN + \ diff --git a/src/tls/tlsv1_server.c b/src/tls/tlsv1_server.c index 96e160c..1f48aa5 100644 --- a/src/tls/tlsv1_server.c +++ b/src/tls/tlsv1_server.c @@ -1,5 +1,5 @@ /* - * TLS v1.0/v1.1/v1.2 server (RFC 2246, RFC 4346, RFC 5246) + * TLS v1.0 (RFC 2246) and v1.1 (RFC 4346) server * Copyright (c) 2006-2011, Jouni Malinen * * This program is free software; you can redistribute it and/or modify @@ -49,8 +49,7 @@ int tlsv1_server_derive_keys(struct tlsv1_server *conn, os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN); os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random, TLS_RANDOM_LEN); - if (tls_prf(conn->rl.tls_version, - pre_master_secret, pre_master_secret_len, + if (tls_prf(pre_master_secret, pre_master_secret_len, "master secret", seed, 2 * TLS_RANDOM_LEN, conn->master_secret, TLS_MASTER_SECRET_LEN)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive " @@ -65,8 +64,7 @@ int tlsv1_server_derive_keys(struct tlsv1_server *conn, os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, TLS_RANDOM_LEN); key_block_len = 2 * (conn->rl.hash_size + conn->rl.key_material_len + conn->rl.iv_size); - if (tls_prf(conn->rl.tls_version, - conn->master_secret, TLS_MASTER_SECRET_LEN, + if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, "key expansion", seed, 2 * TLS_RANDOM_LEN, key_block, key_block_len)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive key_block"); @@ -117,7 +115,6 @@ u8 * tlsv1_server_handshake(struct tlsv1_server *conn, const u8 *pos, *end; u8 *msg = NULL, *in_msg, *in_pos, *in_end, alert, ct; size_t in_msg_len; - int used; if (in_data == NULL || in_len == 0) { wpa_printf(MSG_DEBUG, "TLSv1: No input data to server"); @@ -133,21 +130,13 @@ u8 * tlsv1_server_handshake(struct tlsv1_server *conn, /* Each received packet may include multiple records */ while (pos < end) { in_msg_len = in_len; - used = tlsv1_record_receive(&conn->rl, pos, end - pos, - in_msg, &in_msg_len, &alert); - if (used < 0) { + if (tlsv1_record_receive(&conn->rl, pos, end - pos, + in_msg, &in_msg_len, &alert)) { wpa_printf(MSG_DEBUG, "TLSv1: Processing received " "record failed"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); goto failed; } - if (used == 0) { - /* need more data */ - wpa_printf(MSG_DEBUG, "TLSv1: Partial processing not " - "yet supported"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); - goto failed; - } ct = pos[0]; in_pos = in_msg; @@ -163,7 +152,7 @@ u8 * tlsv1_server_handshake(struct tlsv1_server *conn, in_pos += in_msg_len; } - pos += used; + pos += TLS_RECORD_HEADER_LEN + WPA_GET_BE16(pos + 3); } os_free(in_msg); @@ -241,8 +230,8 @@ int tlsv1_server_decrypt(struct tlsv1_server *conn, u8 *out_data, size_t out_len) { const u8 *in_end, *pos; - int used; - u8 alert, *out_end, *out_pos, ct; + int res; + u8 alert, *out_end, *out_pos; size_t olen; pos = in_data; @@ -251,46 +240,7 @@ int tlsv1_server_decrypt(struct tlsv1_server *conn, out_end = out_data + out_len; while (pos < in_end) { - ct = pos[0]; - olen = out_end - out_pos; - used = tlsv1_record_receive(&conn->rl, pos, in_end - pos, - out_pos, &olen, &alert); - if (used < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Record layer processing " - "failed"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); - return -1; - } - if (used == 0) { - /* need more data */ - wpa_printf(MSG_DEBUG, "TLSv1: Partial processing not " - "yet supported"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); - return -1; - } - - if (ct == TLS_CONTENT_TYPE_ALERT) { - if (olen < 2) { - wpa_printf(MSG_DEBUG, "TLSv1: Alert " - "underflow"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - wpa_printf(MSG_DEBUG, "TLSv1: Received alert %d:%d", - out_pos[0], out_pos[1]); - if (out_pos[0] == TLS_ALERT_LEVEL_WARNING) { - /* Continue processing */ - pos += used; - continue; - } - - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - out_pos[1]); - return -1; - } - - if (ct != TLS_CONTENT_TYPE_APPLICATION_DATA) { + if (pos[0] != TLS_CONTENT_TYPE_APPLICATION_DATA) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected content type " "0x%x", pos[0]); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, @@ -298,6 +248,15 @@ int tlsv1_server_decrypt(struct tlsv1_server *conn, return -1; } + olen = out_end - out_pos; + res = tlsv1_record_receive(&conn->rl, pos, in_end - pos, + out_pos, &olen, &alert); + if (res < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Record layer processing " + "failed"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); + return -1; + } out_pos += olen; if (out_pos > out_end) { wpa_printf(MSG_DEBUG, "TLSv1: Buffer not large enough " @@ -307,7 +266,7 @@ int tlsv1_server_decrypt(struct tlsv1_server *conn, return -1; } - pos += used; + pos += TLS_RECORD_HEADER_LEN + WPA_GET_BE16(pos + 3); } return out_pos - out_data; @@ -451,8 +410,7 @@ int tlsv1_server_prf(struct tlsv1_server *conn, const char *label, TLS_RANDOM_LEN); } - return tls_prf(conn->rl.tls_version, - conn->master_secret, TLS_MASTER_SECRET_LEN, + return tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, label, seed, 2 * TLS_RANDOM_LEN, out, out_len); } diff --git a/src/tls/tlsv1_server.h b/src/tls/tlsv1_server.h index daa4353..00c536c 100644 --- a/src/tls/tlsv1_server.h +++ b/src/tls/tlsv1_server.h @@ -1,6 +1,6 @@ /* - * TLS v1.0/v1.1/v1.2 server (RFC 2246, RFC 4346, RFC 5246) - * Copyright (c) 2006-2011, Jouni Malinen + * TLSv1 server (RFC 2246) + * Copyright (c) 2006-2007, Jouni Malinen * * 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 diff --git a/src/tls/tlsv1_server_read.c b/src/tls/tlsv1_server_read.c index 443c028..9ffe05c 100644 --- a/src/tls/tlsv1_server_read.c +++ b/src/tls/tlsv1_server_read.c @@ -1,6 +1,6 @@ /* * TLSv1 server - read handshake message - * Copyright (c) 2006-2011, Jouni Malinen + * Copyright (c) 2006-2007, Jouni Malinen * * 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 @@ -17,7 +17,6 @@ #include "common.h" #include "crypto/md5.h" #include "crypto/sha1.h" -#include "crypto/sha256.h" #include "crypto/tls.h" #include "x509v3.h" #include "tlsv1_common.h" @@ -99,16 +98,12 @@ static int tls_process_client_hello(struct tlsv1_server *conn, u8 ct, if (TLS_VERSION == TLS_VERSION_1) conn->rl.tls_version = TLS_VERSION_1; -#ifdef CONFIG_TLSV12 - else if (conn->client_version >= TLS_VERSION_1_2) - conn->rl.tls_version = TLS_VERSION_1_2; -#endif /* CONFIG_TLSV12 */ else if (conn->client_version > TLS_VERSION_1_1) conn->rl.tls_version = TLS_VERSION_1_1; else conn->rl.tls_version = conn->client_version; wpa_printf(MSG_DEBUG, "TLSv1: Using TLS v%s", - tls_version_str(conn->rl.tls_version)); + conn->rl.tls_version == TLS_VERSION_1_1 ? "1.1" : "1.0"); /* Random random */ if (end - pos < TLS_RANDOM_LEN) @@ -846,47 +841,6 @@ static int tls_process_certificate_verify(struct tlsv1_server *conn, u8 ct, hpos = hash; -#ifdef CONFIG_TLSV12 - if (conn->rl.tls_version == TLS_VERSION_1_2) { - /* - * RFC 5246, 4.7: - * TLS v1.2 adds explicit indication of the used signature and - * hash algorithms. - * - * struct { - * HashAlgorithm hash; - * SignatureAlgorithm signature; - * } SignatureAndHashAlgorithm; - */ - if (end - pos < 2) { - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - if (pos[0] != TLS_HASH_ALG_SHA256 || - pos[1] != TLS_SIGN_ALG_RSA) { - wpa_printf(MSG_DEBUG, "TLSv1.2: Unsupported hash(%u)/" - "signature(%u) algorithm", - pos[0], pos[1]); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - pos += 2; - - hlen = SHA256_MAC_LEN; - if (conn->verify.sha256_cert == NULL || - crypto_hash_finish(conn->verify.sha256_cert, hpos, &hlen) < - 0) { - conn->verify.sha256_cert = NULL; - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - conn->verify.sha256_cert = NULL; - } else { -#endif /* CONFIG_TLSV12 */ - if (alg == SIGN_ALG_RSA) { hlen = MD5_MAC_LEN; if (conn->verify.md5_cert == NULL || @@ -917,10 +871,6 @@ static int tls_process_certificate_verify(struct tlsv1_server *conn, u8 ct, if (alg == SIGN_ALG_RSA) hlen += MD5_MAC_LEN; -#ifdef CONFIG_TLSV12 - } -#endif /* CONFIG_TLSV12 */ - wpa_hexdump(MSG_MSGDUMP, "TLSv1: CertificateVerify hash", hash, hlen); if (end - pos < 2) { @@ -960,41 +910,6 @@ static int tls_process_certificate_verify(struct tlsv1_server *conn, u8 ct, wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Decrypted Signature", buf, buflen); -#ifdef CONFIG_TLSV12 - if (conn->rl.tls_version >= TLS_VERSION_1_2) { - /* - * RFC 3447, A.2.4 RSASSA-PKCS1-v1_5 - * - * DigestInfo ::= SEQUENCE { - * digestAlgorithm DigestAlgorithm, - * digest OCTET STRING - * } - * - * SHA-256 OID: sha256WithRSAEncryption ::= {pkcs-1 11} - * - * DER encoded DigestInfo for SHA256 per RFC 3447: - * 30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 || - * H - */ - if (buflen >= 19 + 32 && - os_memcmp(buf, "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01" - "\x65\x03\x04\x02\x01\x05\x00\x04\x20", 19) == 0) - { - wpa_printf(MSG_DEBUG, "TLSv1.2: DigestAlgorithn = " - "SHA-256"); - os_memmove(buf, buf + 19, buflen - 19); - buflen -= 19; - } else { - wpa_printf(MSG_DEBUG, "TLSv1.2: Unrecognized " - "DigestInfo"); - os_free(buf); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECRYPT_ERROR); - return -1; - } - } -#endif /* CONFIG_TLSV12 */ - if (buflen != hlen || os_memcmp(buf, hash, buflen) != 0) { wpa_printf(MSG_DEBUG, "TLSv1: Invalid Signature in " "CertificateVerify - did not match with calculated " @@ -1126,21 +1041,6 @@ static int tls_process_client_finished(struct tlsv1_server *conn, u8 ct, wpa_hexdump(MSG_MSGDUMP, "TLSv1: verify_data in Finished", pos, TLS_VERIFY_DATA_LEN); -#ifdef CONFIG_TLSV12 - if (conn->rl.tls_version >= TLS_VERSION_1_2) { - hlen = SHA256_MAC_LEN; - if (conn->verify.sha256_client == NULL || - crypto_hash_finish(conn->verify.sha256_client, hash, &hlen) - < 0) { - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - conn->verify.sha256_client = NULL; - return -1; - } - conn->verify.sha256_client = NULL; - } else { -#endif /* CONFIG_TLSV12 */ - hlen = MD5_MAC_LEN; if (conn->verify.md5_client == NULL || crypto_hash_finish(conn->verify.md5_client, hash, &hlen) < 0) { @@ -1162,15 +1062,9 @@ static int tls_process_client_finished(struct tlsv1_server *conn, u8 ct, return -1; } conn->verify.sha1_client = NULL; - hlen = MD5_MAC_LEN + SHA1_MAC_LEN; - -#ifdef CONFIG_TLSV12 - } -#endif /* CONFIG_TLSV12 */ - if (tls_prf(conn->rl.tls_version, - conn->master_secret, TLS_MASTER_SECRET_LEN, - "client finished", hash, hlen, + if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, + "client finished", hash, MD5_MAC_LEN + SHA1_MAC_LEN, verify_data, TLS_VERIFY_DATA_LEN)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive verify_data"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, diff --git a/src/tls/tlsv1_server_write.c b/src/tls/tlsv1_server_write.c index 0ca3b23..63d70a2 100644 --- a/src/tls/tlsv1_server_write.c +++ b/src/tls/tlsv1_server_write.c @@ -1,5 +1,5 @@ /* - * TLSv1 server - write handshake message + * TLS v1.0 (RFC 2246) and v1.1 (RFC 4346) server - write handshake message * Copyright (c) 2006-2011, Jouni Malinen * * This program is free software; you can redistribute it and/or modify @@ -17,7 +17,6 @@ #include "common.h" #include "crypto/md5.h" #include "crypto/sha1.h" -#include "crypto/sha256.h" #include "crypto/tls.h" #include "crypto/random.h" #include "x509v3.h" @@ -588,21 +587,6 @@ static int tls_write_server_finished(struct tlsv1_server *conn, /* Encrypted Handshake Message: Finished */ -#ifdef CONFIG_TLSV12 - if (conn->rl.tls_version >= TLS_VERSION_1_2) { - hlen = SHA256_MAC_LEN; - if (conn->verify.sha256_server == NULL || - crypto_hash_finish(conn->verify.sha256_server, hash, &hlen) - < 0) { - conn->verify.sha256_server = NULL; - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - conn->verify.sha256_server = NULL; - } else { -#endif /* CONFIG_TLSV12 */ - hlen = MD5_MAC_LEN; if (conn->verify.md5_server == NULL || crypto_hash_finish(conn->verify.md5_server, hash, &hlen) < 0) { @@ -624,15 +608,9 @@ static int tls_write_server_finished(struct tlsv1_server *conn, return -1; } conn->verify.sha1_server = NULL; - hlen = MD5_MAC_LEN + SHA1_MAC_LEN; - -#ifdef CONFIG_TLSV12 - } -#endif /* CONFIG_TLSV12 */ - if (tls_prf(conn->rl.tls_version, - conn->master_secret, TLS_MASTER_SECRET_LEN, - "server finished", hash, hlen, + if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, + "server finished", hash, MD5_MAC_LEN + SHA1_MAC_LEN, verify_data + 1 + 3, TLS_VERIFY_DATA_LEN)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate verify_data"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, diff --git a/src/utils/os_unix.c b/src/utils/os_unix.c index 9b16b33..b546201 100644 --- a/src/utils/os_unix.c +++ b/src/utils/os_unix.c @@ -27,9 +27,9 @@ #ifdef WPA_TRACE #include "common.h" +#include "list.h" #include "wpa_debug.h" #include "trace.h" -#include "list.h" static struct dl_list alloc_list; diff --git a/src/utils/radiotap.h b/src/utils/radiotap.h index 137288f..508264c 100644 --- a/src/utils/radiotap.h +++ b/src/utils/radiotap.h @@ -238,6 +238,5 @@ enum ieee80211_radiotap_type { * retries */ #define IEEE80211_RADIOTAP_F_TX_CTS 0x0002 /* used cts 'protection' */ #define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */ -#define IEEE80211_RADIOTAP_F_TX_NOACK 0x0008 /* don't expect an ACK */ #endif /* IEEE80211_RADIOTAP_H */ diff --git a/src/utils/wpa_debug.c b/src/utils/wpa_debug.c index aa7295c..b16b95b 100644 --- a/src/utils/wpa_debug.c +++ b/src/utils/wpa_debug.c @@ -290,6 +290,38 @@ static void _wpa_hexdump(int level, const char *title, const u8 *buf, size_t i; if (level < wpa_debug_level) return; +#ifdef CONFIG_DEBUG_SYSLOG + if (wpa_debug_syslog) { + const char *display; + char *strbuf = NULL; + + if (buf == NULL) { + display = " [NULL]"; + } else if (len == 0) { + display = ""; + } else if (show && len) { + strbuf = os_malloc(1 + 3 * len); + if (strbuf == NULL) { + wpa_printf(MSG_ERROR, "wpa_hexdump: Failed to " + "allocate message buffer"); + return; + } + + for (i = 0; i < len; i++) + os_snprintf(&strbuf[i * 3], 4, " %02x", + buf[i]); + + display = strbuf; + } else { + display = " [REMOVED]"; + } + + syslog(syslog_priority(level), "%s - hexdump(len=%lu):%s", + title, len, display); + os_free(strbuf); + return; + } +#endif /* CONFIG_DEBUG_SYSLOG */ wpa_debug_print_timestamp(); #ifdef CONFIG_DEBUG_FILE if (out_file) { diff --git a/src/utils/wpa_debug.h b/src/utils/wpa_debug.h index 64ada57..ae36afe 100644 --- a/src/utils/wpa_debug.h +++ b/src/utils/wpa_debug.h @@ -136,7 +136,7 @@ void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len); static inline void wpa_hexdump_buf_key(int level, const char *title, const struct wpabuf *buf) { - wpa_hexdump_key(level, title, buf ? wpabuf_head(buf) : NULL, + wpa_hexdump_key(level, title, buf ? wpabuf_head(buf) : 0, buf ? wpabuf_len(buf) : 0); } diff --git a/src/wps/wps.h b/src/wps/wps.h index 4986881..389be3e 100644 --- a/src/wps/wps.h +++ b/src/wps/wps.h @@ -457,7 +457,12 @@ enum wps_event { /** * WPS_EV_ER_SET_SELECTED_REGISTRAR - ER: SetSelectedRegistrar event */ - WPS_EV_ER_SET_SELECTED_REGISTRAR + WPS_EV_ER_SET_SELECTED_REGISTRAR, + + /** + * WPS_EV_AP_PIN_SUCCESS - External Registrar used correct AP PIN + */ + WPS_EV_AP_PIN_SUCCESS }; /** diff --git a/src/wps/wps_common.c b/src/wps/wps_common.c index 505837b..5d0508c 100644 --- a/src/wps/wps_common.c +++ b/src/wps/wps_common.c @@ -22,6 +22,7 @@ #include "crypto/sha256.h" #include "crypto/random.h" #include "wps_i.h" +#include "wps_dev_attr.h" void wps_kdf(const u8 *key, const u8 *label_prefix, size_t label_prefix_len, diff --git a/src/wps/wps_enrollee.c b/src/wps/wps_enrollee.c index 0fbaa3f..7e58291 100644 --- a/src/wps/wps_enrollee.c +++ b/src/wps/wps_enrollee.c @@ -257,20 +257,47 @@ static int wps_build_cred_ssid(struct wps_data *wps, struct wpabuf *msg) static int wps_build_cred_auth_type(struct wps_data *wps, struct wpabuf *msg) { - wpa_printf(MSG_DEBUG, "WPS: * Authentication Type"); + u16 auth_type = wps->wps->auth_types; + + /* Select the best authentication type */ + if (auth_type & WPS_AUTH_WPA2PSK) + auth_type = WPS_AUTH_WPA2PSK; + else if (auth_type & WPS_AUTH_WPAPSK) + auth_type = WPS_AUTH_WPAPSK; + else if (auth_type & WPS_AUTH_OPEN) + auth_type = WPS_AUTH_OPEN; + else if (auth_type & WPS_AUTH_SHARED) + auth_type = WPS_AUTH_SHARED; + + wpa_printf(MSG_DEBUG, "WPS: * Authentication Type (0x%x)", auth_type); wpabuf_put_be16(msg, ATTR_AUTH_TYPE); wpabuf_put_be16(msg, 2); - wpabuf_put_be16(msg, wps->wps->auth_types); + wpabuf_put_be16(msg, auth_type); return 0; } static int wps_build_cred_encr_type(struct wps_data *wps, struct wpabuf *msg) { - wpa_printf(MSG_DEBUG, "WPS: * Encryption Type"); + u16 encr_type = wps->wps->encr_types; + + /* Select the best encryption type */ + if (wps->wps->auth_types & (WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK)) { + if (encr_type & WPS_ENCR_AES) + encr_type = WPS_ENCR_AES; + else if (encr_type & WPS_ENCR_TKIP) + encr_type = WPS_ENCR_TKIP; + } else { + if (encr_type & WPS_ENCR_WEP) + encr_type = WPS_ENCR_WEP; + else if (encr_type & WPS_ENCR_NONE) + encr_type = WPS_ENCR_NONE; + } + + wpa_printf(MSG_DEBUG, "WPS: * Encryption Type (0x%x)", encr_type); wpabuf_put_be16(msg, ATTR_ENCR_TYPE); wpabuf_put_be16(msg, 2); - wpabuf_put_be16(msg, wps->wps->encr_types); + wpabuf_put_be16(msg, encr_type); return 0; } @@ -967,7 +994,7 @@ static enum wps_process_res wps_process_m4(struct wps_data *wps, return WPS_CONTINUE; } - if (wps_validate_m4_encr(decrypted, attr->version2 != NULL) < 0) { + if (wps_validate_m4_encr(decrypted, attr->version2 != 0) < 0) { wpabuf_free(decrypted); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; @@ -1020,7 +1047,7 @@ static enum wps_process_res wps_process_m6(struct wps_data *wps, return WPS_CONTINUE; } - if (wps_validate_m6_encr(decrypted, attr->version2 != NULL) < 0) { + if (wps_validate_m6_encr(decrypted, attr->version2 != 0) < 0) { wpabuf_free(decrypted); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; @@ -1037,6 +1064,10 @@ static enum wps_process_res wps_process_m6(struct wps_data *wps, } wpabuf_free(decrypted); + if (wps->wps->ap) + wps->wps->event_cb(wps->wps->cb_ctx, WPS_EV_AP_PIN_SUCCESS, + NULL); + wps->state = SEND_M7; return WPS_CONTINUE; } @@ -1086,8 +1117,8 @@ static enum wps_process_res wps_process_m8(struct wps_data *wps, return WPS_CONTINUE; } - if (wps_validate_m8_encr(decrypted, wps->wps->ap, - attr->version2 != NULL) < 0) { + if (wps_validate_m8_encr(decrypted, wps->wps->ap, attr->version2 != 0) + < 0) { wpabuf_free(decrypted); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c index eda1c70..e5e8d28 100644 --- a/src/wps/wps_registrar.c +++ b/src/wps/wps_registrar.c @@ -962,6 +962,7 @@ int wps_registrar_wps_cancel(struct wps_registrar *reg) if (reg->pbc) { wpa_printf(MSG_DEBUG, "WPS: PBC is set - cancelling it"); wps_registrar_pbc_timeout(reg, NULL); + eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL); return 1; } else if (reg->selected_registrar) { /* PIN Method */ diff --git a/src/wps/wps_ufd.c b/src/wps/wps_ufd.c index 61f6553..1a911e1 100644 --- a/src/wps/wps_ufd.c +++ b/src/wps/wps_ufd.c @@ -16,6 +16,7 @@ #include "common.h" #include #include +#include #include #include diff --git a/tests/Makefile b/tests/Makefile index 91b10c5..f8a3253 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,5 +1,5 @@ TESTS=test-base64 test-md4 test-md5 test-milenage test-ms_funcs test-sha1 \ - test-sha256 test-aes test-asn1 test-x509 test-x509v3 test-list test-rc4 + test-sha256 test-aes test-asn1 test-x509 test-x509v3 test-list all: $(TESTS) @@ -45,9 +45,6 @@ test-asn1: test-asn1.o $(LIBS) test-base64: test-base64.o $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ -test-https: test-https.o $(LIBS) - $(LDO) $(LDFLAGS) -o $@ $< $(LLIBS) - test-list: test-list.o $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ @@ -63,9 +60,6 @@ test-milenage: test-milenage.o $(LIBS) test-ms_funcs: test-ms_funcs.o $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ -test-rc4: test-rc4.o $(LIBS) - $(LDO) $(LDFLAGS) -o $@ $^ - test-sha1: test-sha1.o $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ @@ -93,6 +87,7 @@ run-tests: $(TESTS) clean: $(MAKE) -C ../src clean rm -f $(TESTS) *~ *.o *.d + rm -f test-https rm -f test_x509v3_nist.out.* rm -f test_x509v3_nist2.out.* diff --git a/tests/test-https.c b/tests/test-https.c deleted file mode 100644 index 96e894d..0000000 --- a/tests/test-https.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Testing tool for TLSv1 client routines using HTTPS - * Copyright (c) 2011, Jouni Malinen - * - * 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 - -#include "common.h" -#include "crypto/tls.h" - -extern int wpa_debug_level; -extern int wpa_debug_show_keys; - - -static void https_tls_event_cb(void *ctx, enum tls_event ev, - union tls_event_data *data) -{ - wpa_printf(MSG_DEBUG, "HTTPS: TLS event %d", ev); -} - - -static struct wpabuf * https_recv(int s) -{ - struct wpabuf *in; - int len, ret; - fd_set rfds; - struct timeval tv; - - in = wpabuf_alloc(20000); - if (in == NULL) - return NULL; - - FD_ZERO(&rfds); - FD_SET(s, &rfds); - tv.tv_sec = 5; - tv.tv_usec = 0; - - wpa_printf(MSG_DEBUG, "Waiting for more data"); - ret = select(s + 1, &rfds, NULL, NULL, &tv); - if (ret < 0) { - wpa_printf(MSG_ERROR, "select: %s", strerror(errno)); - wpabuf_free(in); - return NULL; - } - if (ret == 0) { - /* timeout */ - wpa_printf(MSG_INFO, "Timeout on waiting for data"); - wpabuf_free(in); - return NULL; - } - - len = recv(s, wpabuf_put(in, 0), wpabuf_tailroom(in), 0); - if (len < 0) { - wpa_printf(MSG_ERROR, "recv: %s", strerror(errno)); - wpabuf_free(in); - return NULL; - } - if (len == 0) { - wpa_printf(MSG_DEBUG, "No more data available"); - wpabuf_free(in); - return NULL; - } - wpa_printf(MSG_DEBUG, "Received %d bytes", len); - wpabuf_put(in, len); - - return in; -} - - -static int https_client(int s, const char *path) -{ - struct tls_config conf; - void *tls; - struct tls_connection *conn; - struct wpabuf *in, *out, *appl; - int res = -1; - int need_more_data; - - os_memset(&conf, 0, sizeof(conf)); - conf.event_cb = https_tls_event_cb; - tls = tls_init(&conf); - if (tls == NULL) - return -1; - - conn = tls_connection_init(tls); - if (conn == NULL) { - tls_deinit(tls); - return -1; - } - - in = NULL; - - for (;;) { - appl = NULL; - out = tls_connection_handshake2(tls, conn, in, &appl, - &need_more_data); - wpabuf_free(in); - in = NULL; - if (out == NULL) { - if (need_more_data) - goto read_more; - goto done; - } - if (tls_connection_get_failed(tls, conn)) { - wpa_printf(MSG_ERROR, "TLS handshake failed"); - goto done; - } - if (tls_connection_established(tls, conn)) - break; - wpa_printf(MSG_DEBUG, "Sending %d bytes", - (int) wpabuf_len(out)); - if (send(s, wpabuf_head(out), wpabuf_len(out), 0) < 0) { - wpa_printf(MSG_ERROR, "send: %s", strerror(errno)); - goto done; - } - wpabuf_free(out); - out = NULL; - - read_more: - in = https_recv(s); - if (in == NULL) - goto done; - } - wpabuf_free(out); - out = NULL; - - wpa_printf(MSG_INFO, "TLS connection established"); - if (appl) - wpa_hexdump_buf(MSG_DEBUG, "Received application data", appl); - - in = wpabuf_alloc(100 + os_strlen(path)); - if (in == NULL) - goto done; - wpabuf_put_str(in, "GET "); - wpabuf_put_str(in, path); - wpabuf_put_str(in, " HTTP/1.0\r\n\r\n"); - out = tls_connection_encrypt(tls, conn, in); - wpabuf_free(in); - in = NULL; - if (out == NULL) - goto done; - - wpa_printf(MSG_INFO, "Sending HTTP request: %d bytes", - (int) wpabuf_len(out)); - if (send(s, wpabuf_head(out), wpabuf_len(out), 0) < 0) { - wpa_printf(MSG_ERROR, "send: %s", strerror(errno)); - goto done; - } - wpabuf_free(out); - out = NULL; - - wpa_printf(MSG_INFO, "Reading HTTP response"); - for (;;) { - int need_more_data; - in = https_recv(s); - if (in == NULL) - goto done; - out = tls_connection_decrypt2(tls, conn, in, &need_more_data); - if (need_more_data) - wpa_printf(MSG_DEBUG, "HTTP: Need more data"); - wpabuf_free(in); - in = NULL; - if (out == NULL) - goto done; - wpa_hexdump_ascii(MSG_INFO, "Response", wpabuf_head(out), - wpabuf_len(out)); - wpabuf_free(out); - out = NULL; - } - - res = 0; -done: - wpabuf_free(out); - wpabuf_free(in); - wpabuf_free(appl); - tls_connection_deinit(tls, conn); - tls_deinit(tls); - - return res; -} - - -int main(int argc, char *argv[]) -{ - struct addrinfo hints, *result, *rp; - int res, s; - - wpa_debug_level = 0; - wpa_debug_show_keys = 1; - - if (argc < 4) { - wpa_printf(MSG_INFO, "usage: test-https server port path"); - return -1; - } - - os_memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - res = getaddrinfo(argv[1], argv[2], &hints, &result); - if (res) { - wpa_printf(MSG_ERROR, "getaddrinfo: %s", gai_strerror(res)); - return -1; - } - - for (rp = result; rp; rp = rp->ai_next) { - s = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); - if (s < 0) - continue; - if (connect(s, rp->ai_addr, rp->ai_addrlen) == 0) - break; - close(s); - } - freeaddrinfo(result); - - if (rp == NULL) { - wpa_printf(MSG_ERROR, "Could not connect"); - return -1; - } - - https_client(s, argv[3]); - close(s); - - return 0; -} diff --git a/tests/test-rc4.c b/tests/test-rc4.c deleted file mode 100644 index cbe2aeb..0000000 --- a/tests/test-rc4.c +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Test program for RC4 - * Copyright (c) 2011, Jouni Malinen - * - * 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 "crypto/crypto.h" - - -struct rc4_test_vector { - size_t key_len; - const u8 *key; - const u8 *stream0; - const u8 *stream240; - const u8 *stream496; - const u8 *stream752; - const u8 *stream1008; - const u8 *stream1520; - const u8 *stream2032; - const u8 *stream3056; - const u8 *stream4080; -}; - -/* RFC 6229 test vectors */ -static const struct rc4_test_vector tests[] = { - { - 5, (u8 *) "\x01\x02\x03\x04\x05", - (u8 *) "\xb2\x39\x63\x05\xf0\x3d\xc0\x27\xcc\xc3\x52\x4a\x0a\x11\x18\xa8\x69\x82\x94\x4f\x18\xfc\x82\xd5\x89\xc4\x03\xa4\x7a\x0d\x09\x19", - (u8 *) "\x28\xcb\x11\x32\xc9\x6c\xe2\x86\x42\x1d\xca\xad\xb8\xb6\x9e\xae\x1c\xfc\xf6\x2b\x03\xed\xdb\x64\x1d\x77\xdf\xcf\x7f\x8d\x8c\x93", - (u8 *) "\x42\xb7\xd0\xcd\xd9\x18\xa8\xa3\x3d\xd5\x17\x81\xc8\x1f\x40\x41\x64\x59\x84\x44\x32\xa7\xda\x92\x3c\xfb\x3e\xb4\x98\x06\x61\xf6", - (u8 *) "\xec\x10\x32\x7b\xde\x2b\xee\xfd\x18\xf9\x27\x76\x80\x45\x7e\x22\xeb\x62\x63\x8d\x4f\x0b\xa1\xfe\x9f\xca\x20\xe0\x5b\xf8\xff\x2b", - (u8 *) "\x45\x12\x90\x48\xe6\xa0\xed\x0b\x56\xb4\x90\x33\x8f\x07\x8d\xa5\x30\xab\xbc\xc7\xc2\x0b\x01\x60\x9f\x23\xee\x2d\x5f\x6b\xb7\xdf", - (u8 *) "\x32\x94\xf7\x44\xd8\xf9\x79\x05\x07\xe7\x0f\x62\xe5\xbb\xce\xea\xd8\x72\x9d\xb4\x18\x82\x25\x9b\xee\x4f\x82\x53\x25\xf5\xa1\x30", - (u8 *) "\x1e\xb1\x4a\x0c\x13\xb3\xbf\x47\xfa\x2a\x0b\xa9\x3a\xd4\x5b\x8b\xcc\x58\x2f\x8b\xa9\xf2\x65\xe2\xb1\xbe\x91\x12\xe9\x75\xd2\xd7", - (u8 *) "\xf2\xe3\x0f\x9b\xd1\x02\xec\xbf\x75\xaa\xad\xe9\xbc\x35\xc4\x3c\xec\x0e\x11\xc4\x79\xdc\x32\x9d\xc8\xda\x79\x68\xfe\x96\x56\x81", - (u8 *) "\x06\x83\x26\xa2\x11\x84\x16\xd2\x1f\x9d\x04\xb2\xcd\x1c\xa0\x50\xff\x25\xb5\x89\x95\x99\x67\x07\xe5\x1f\xbd\xf0\x8b\x34\xd8\x75" - }, - { - 7, (u8 *) "\x01\x02\x03\x04\x05\x06\x07", - (u8 *) "\x29\x3f\x02\xd4\x7f\x37\xc9\xb6\x33\xf2\xaf\x52\x85\xfe\xb4\x6b\xe6\x20\xf1\x39\x0d\x19\xbd\x84\xe2\xe0\xfd\x75\x20\x31\xaf\xc1", - (u8 *) "\x91\x4f\x02\x53\x1c\x92\x18\x81\x0d\xf6\x0f\x67\xe3\x38\x15\x4c\xd0\xfd\xb5\x83\x07\x3c\xe8\x5a\xb8\x39\x17\x74\x0e\xc0\x11\xd5", - (u8 *) "\x75\xf8\x14\x11\xe8\x71\xcf\xfa\x70\xb9\x0c\x74\xc5\x92\xe4\x54\x0b\xb8\x72\x02\x93\x8d\xad\x60\x9e\x87\xa5\xa1\xb0\x79\xe5\xe4", - (u8 *) "\xc2\x91\x12\x46\xb6\x12\xe7\xe7\xb9\x03\xdf\xed\xa1\xda\xd8\x66\x32\x82\x8f\x91\x50\x2b\x62\x91\x36\x8d\xe8\x08\x1d\xe3\x6f\xc2", - (u8 *) "\xf3\xb9\xa7\xe3\xb2\x97\xbf\x9a\xd8\x04\x51\x2f\x90\x63\xef\xf1\x8e\xcb\x67\xa9\xba\x1f\x55\xa5\xa0\x67\xe2\xb0\x26\xa3\x67\x6f", - (u8 *) "\xd2\xaa\x90\x2b\xd4\x2d\x0d\x7c\xfd\x34\x0c\xd4\x58\x10\x52\x9f\x78\xb2\x72\xc9\x6e\x42\xea\xb4\xc6\x0b\xd9\x14\xe3\x9d\x06\xe3", - (u8 *) "\xf4\x33\x2f\xd3\x1a\x07\x93\x96\xee\x3c\xee\x3f\x2a\x4f\xf0\x49\x05\x45\x97\x81\xd4\x1f\xda\x7f\x30\xc1\xbe\x7e\x12\x46\xc6\x23", - (u8 *) "\xad\xfd\x38\x68\xb8\xe5\x14\x85\xd5\xe6\x10\x01\x7e\x3d\xd6\x09\xad\x26\x58\x1c\x0c\x5b\xe4\x5f\x4c\xea\x01\xdb\x2f\x38\x05\xd5", - (u8 *) "\xf3\x17\x2c\xef\xfc\x3b\x3d\x99\x7c\x85\xcc\xd5\xaf\x1a\x95\x0c\xe7\x4b\x0b\x97\x31\x22\x7f\xd3\x7c\x0e\xc0\x8a\x47\xdd\xd8\xb8" - }, - { - 8, (u8 *) "\x01\x02\x03\x04\x05\x06\x07\x08", - (u8 *) "\x97\xab\x8a\x1b\xf0\xaf\xb9\x61\x32\xf2\xf6\x72\x58\xda\x15\xa8\x82\x63\xef\xdb\x45\xc4\xa1\x86\x84\xef\x87\xe6\xb1\x9e\x5b\x09", - (u8 *) "\x96\x36\xeb\xc9\x84\x19\x26\xf4\xf7\xd1\xf3\x62\xbd\xdf\x6e\x18\xd0\xa9\x90\xff\x2c\x05\xfe\xf5\xb9\x03\x73\xc9\xff\x4b\x87\x0a", - (u8 *) "\x73\x23\x9f\x1d\xb7\xf4\x1d\x80\xb6\x43\xc0\xc5\x25\x18\xec\x63\x16\x3b\x31\x99\x23\xa6\xbd\xb4\x52\x7c\x62\x61\x26\x70\x3c\x0f", - (u8 *) "\x49\xd6\xc8\xaf\x0f\x97\x14\x4a\x87\xdf\x21\xd9\x14\x72\xf9\x66\x44\x17\x3a\x10\x3b\x66\x16\xc5\xd5\xad\x1c\xee\x40\xc8\x63\xd0", - (u8 *) "\x27\x3c\x9c\x4b\x27\xf3\x22\xe4\xe7\x16\xef\x53\xa4\x7d\xe7\xa4\xc6\xd0\xe7\xb2\x26\x25\x9f\xa9\x02\x34\x90\xb2\x61\x67\xad\x1d", - (u8 *) "\x1f\xe8\x98\x67\x13\xf0\x7c\x3d\x9a\xe1\xc1\x63\xff\x8c\xf9\xd3\x83\x69\xe1\xa9\x65\x61\x0b\xe8\x87\xfb\xd0\xc7\x91\x62\xaa\xfb", - (u8 *) "\x0a\x01\x27\xab\xb4\x44\x84\xb9\xfb\xef\x5a\xbc\xae\x1b\x57\x9f\xc2\xcd\xad\xc6\x40\x2e\x8e\xe8\x66\xe1\xf3\x7b\xdb\x47\xe4\x2c", - (u8 *) "\x26\xb5\x1e\xa3\x7d\xf8\xe1\xd6\xf7\x6f\xc3\xb6\x6a\x74\x29\xb3\xbc\x76\x83\x20\x5d\x4f\x44\x3d\xc1\xf2\x9d\xda\x33\x15\xc8\x7b", - (u8 *) "\xd5\xfa\x5a\x34\x69\xd2\x9a\xaa\xf8\x3d\x23\x58\x9d\xb8\xc8\x5b\x3f\xb4\x6e\x2c\x8f\x0f\x06\x8e\xdc\xe8\xcd\xcd\x7d\xfc\x58\x62" - }, - { - 10, (u8 *) "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a", - (u8 *) "\xed\xe3\xb0\x46\x43\xe5\x86\xcc\x90\x7d\xc2\x18\x51\x70\x99\x02\x03\x51\x6b\xa7\x8f\x41\x3b\xeb\x22\x3a\xa5\xd4\xd2\xdf\x67\x11", - (u8 *) "\x3c\xfd\x6c\xb5\x8e\xe0\xfd\xde\x64\x01\x76\xad\x00\x00\x04\x4d\x48\x53\x2b\x21\xfb\x60\x79\xc9\x11\x4c\x0f\xfd\x9c\x04\xa1\xad", - (u8 *) "\x3e\x8c\xea\x98\x01\x71\x09\x97\x90\x84\xb1\xef\x92\xf9\x9d\x86\xe2\x0f\xb4\x9b\xdb\x33\x7e\xe4\x8b\x8d\x8d\xc0\xf4\xaf\xef\xfe", - (u8 *) "\x5c\x25\x21\xea\xcd\x79\x66\xf1\x5e\x05\x65\x44\xbe\xa0\xd3\x15\xe0\x67\xa7\x03\x19\x31\xa2\x46\xa6\xc3\x87\x5d\x2f\x67\x8a\xcb", - (u8 *) "\xa6\x4f\x70\xaf\x88\xae\x56\xb6\xf8\x75\x81\xc0\xe2\x3e\x6b\x08\xf4\x49\x03\x1d\xe3\x12\x81\x4e\xc6\xf3\x19\x29\x1f\x4a\x05\x16", - (u8 *) "\xbd\xae\x85\x92\x4b\x3c\xb1\xd0\xa2\xe3\x3a\x30\xc6\xd7\x95\x99\x8a\x0f\xed\xdb\xac\x86\x5a\x09\xbc\xd1\x27\xfb\x56\x2e\xd6\x0a", - (u8 *) "\xb5\x5a\x0a\x5b\x51\xa1\x2a\x8b\xe3\x48\x99\xc3\xe0\x47\x51\x1a\xd9\xa0\x9c\xea\x3c\xe7\x5f\xe3\x96\x98\x07\x03\x17\xa7\x13\x39", - (u8 *) "\x55\x22\x25\xed\x11\x77\xf4\x45\x84\xac\x8c\xfa\x6c\x4e\xb5\xfc\x7e\x82\xcb\xab\xfc\x95\x38\x1b\x08\x09\x98\x44\x21\x29\xc2\xf8", - (u8 *) "\x1f\x13\x5e\xd1\x4c\xe6\x0a\x91\x36\x9d\x23\x22\xbe\xf2\x5e\x3c\x08\xb6\xbe\x45\x12\x4a\x43\xe2\xeb\x77\x95\x3f\x84\xdc\x85\x53" - }, - { - 16, (u8 *) "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10", - (u8 *) "\x9a\xc7\xcc\x9a\x60\x9d\x1e\xf7\xb2\x93\x28\x99\xcd\xe4\x1b\x97\x52\x48\xc4\x95\x90\x14\x12\x6a\x6e\x8a\x84\xf1\x1d\x1a\x9e\x1c", - (u8 *) "\x06\x59\x02\xe4\xb6\x20\xf6\xcc\x36\xc8\x58\x9f\x66\x43\x2f\x2b\xd3\x9d\x56\x6b\xc6\xbc\xe3\x01\x07\x68\x15\x15\x49\xf3\x87\x3f", - (u8 *) "\xb6\xd1\xe6\xc4\xa5\xe4\x77\x1c\xad\x79\x53\x8d\xf2\x95\xfb\x11\xc6\x8c\x1d\x5c\x55\x9a\x97\x41\x23\xdf\x1d\xbc\x52\xa4\x3b\x89", - (u8 *) "\xc5\xec\xf8\x8d\xe8\x97\xfd\x57\xfe\xd3\x01\x70\x1b\x82\xa2\x59\xec\xcb\xe1\x3d\xe1\xfc\xc9\x1c\x11\xa0\xb2\x6c\x0b\xc8\xfa\x4d", - (u8 *) "\xe7\xa7\x25\x74\xf8\x78\x2a\xe2\x6a\xab\xcf\x9e\xbc\xd6\x60\x65\xbd\xf0\x32\x4e\x60\x83\xdc\xc6\xd3\xce\xdd\x3c\xa8\xc5\x3c\x16", - (u8 *) "\xb4\x01\x10\xc4\x19\x0b\x56\x22\xa9\x61\x16\xb0\x01\x7e\xd2\x97\xff\xa0\xb5\x14\x64\x7e\xc0\x4f\x63\x06\xb8\x92\xae\x66\x11\x81", - (u8 *) "\xd0\x3d\x1b\xc0\x3c\xd3\x3d\x70\xdf\xf9\xfa\x5d\x71\x96\x3e\xbd\x8a\x44\x12\x64\x11\xea\xa7\x8b\xd5\x1e\x8d\x87\xa8\x87\x9b\xf5", - (u8 *) "\xfa\xbe\xb7\x60\x28\xad\xe2\xd0\xe4\x87\x22\xe4\x6c\x46\x15\xa3\xc0\x5d\x88\xab\xd5\x03\x57\xf9\x35\xa6\x3c\x59\xee\x53\x76\x23", - (u8 *) "\xff\x38\x26\x5c\x16\x42\xc1\xab\xe8\xd3\xc2\xfe\x5e\x57\x2b\xf8\xa3\x6a\x4c\x30\x1a\xe8\xac\x13\x61\x0c\xcb\xc1\x22\x56\xca\xcc" - }, - { - 24, (u8 *) "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18", - (u8 *) "\x05\x95\xe5\x7f\xe5\xf0\xbb\x3c\x70\x6e\xda\xc8\xa4\xb2\xdb\x11\xdf\xde\x31\x34\x4a\x1a\xf7\x69\xc7\x4f\x07\x0a\xee\x9e\x23\x26", - (u8 *) "\xb0\x6b\x9b\x1e\x19\x5d\x13\xd8\xf4\xa7\x99\x5c\x45\x53\xac\x05\x6b\xd2\x37\x8e\xc3\x41\xc9\xa4\x2f\x37\xba\x79\xf8\x8a\x32\xff", - (u8 *) "\xe7\x0b\xce\x1d\xf7\x64\x5a\xdb\x5d\x2c\x41\x30\x21\x5c\x35\x22\x9a\x57\x30\xc7\xfc\xb4\xc9\xaf\x51\xff\xda\x89\xc7\xf1\xad\x22", - (u8 *) "\x04\x85\x05\x5f\xd4\xf6\xf0\xd9\x63\xef\x5a\xb9\xa5\x47\x69\x82\x59\x1f\xc6\x6b\xcd\xa1\x0e\x45\x2b\x03\xd4\x55\x1f\x6b\x62\xac", - (u8 *) "\x27\x53\xcc\x83\x98\x8a\xfa\x3e\x16\x88\xa1\xd3\xb4\x2c\x9a\x02\x93\x61\x0d\x52\x3d\x1d\x3f\x00\x62\xb3\xc2\xa3\xbb\xc7\xc7\xf0", - (u8 *) "\x96\xc2\x48\x61\x0a\xad\xed\xfe\xaf\x89\x78\xc0\x3d\xe8\x20\x5a\x0e\x31\x7b\x3d\x1c\x73\xb9\xe9\xa4\x68\x8f\x29\x6d\x13\x3a\x19", - (u8 *) "\xbd\xf0\xe6\xc3\xcc\xa5\xb5\xb9\xd5\x33\xb6\x9c\x56\xad\xa1\x20\x88\xa2\x18\xb6\xe2\xec\xe1\xe6\x24\x6d\x44\xc7\x59\xd1\x9b\x10", - (u8 *) "\x68\x66\x39\x7e\x95\xc1\x40\x53\x4f\x94\x26\x34\x21\x00\x6e\x40\x32\xcb\x0a\x1e\x95\x42\xc6\xb3\xb8\xb3\x98\xab\xc3\xb0\xf1\xd5", - (u8 *) "\x29\xa0\xb8\xae\xd5\x4a\x13\x23\x24\xc6\x2e\x42\x3f\x54\xb4\xc8\x3c\xb0\xf3\xb5\x02\x0a\x98\xb8\x2a\xf9\xfe\x15\x44\x84\xa1\x68" - }, - { - 32, (u8 *) "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20", - (u8 *) "\xea\xa6\xbd\x25\x88\x0b\xf9\x3d\x3f\x5d\x1e\x4c\xa2\x61\x1d\x91\xcf\xa4\x5c\x9f\x7e\x71\x4b\x54\xbd\xfa\x80\x02\x7c\xb1\x43\x80", - (u8 *) "\x11\x4a\xe3\x44\xde\xd7\x1b\x35\xf2\xe6\x0f\xeb\xad\x72\x7f\xd8\x02\xe1\xe7\x05\x6b\x0f\x62\x39\x00\x49\x64\x22\x94\x3e\x97\xb6", - (u8 *) "\x91\xcb\x93\xc7\x87\x96\x4e\x10\xd9\x52\x7d\x99\x9c\x6f\x93\x6b\x49\xb1\x8b\x42\xf8\xe8\x36\x7c\xbe\xb5\xef\x10\x4b\xa1\xc7\xcd", - (u8 *) "\x87\x08\x4b\x3b\xa7\x00\xba\xde\x95\x56\x10\x67\x27\x45\xb3\x74\xe7\xa7\xb9\xe9\xec\x54\x0d\x5f\xf4\x3b\xdb\x12\x79\x2d\x1b\x35", - (u8 *) "\xc7\x99\xb5\x96\x73\x8f\x6b\x01\x8c\x76\xc7\x4b\x17\x59\xbd\x90\x7f\xec\x5b\xfd\x9f\x9b\x89\xce\x65\x48\x30\x90\x92\xd7\xe9\x58", - (u8 *) "\x40\xf2\x50\xb2\x6d\x1f\x09\x6a\x4a\xfd\x4c\x34\x0a\x58\x88\x15\x3e\x34\x13\x5c\x79\xdb\x01\x02\x00\x76\x76\x51\xcf\x26\x30\x73", - (u8 *) "\xf6\x56\xab\xcc\xf8\x8d\xd8\x27\x02\x7b\x2c\xe9\x17\xd4\x64\xec\x18\xb6\x25\x03\xbf\xbc\x07\x7f\xba\xbb\x98\xf2\x0d\x98\xab\x34", - (u8 *) "\x8a\xed\x95\xee\x5b\x0d\xcb\xfb\xef\x4e\xb2\x1d\x3a\x3f\x52\xf9\x62\x5a\x1a\xb0\x0e\xe3\x9a\x53\x27\x34\x6b\xdd\xb0\x1a\x9c\x18", - (u8 *) "\xa1\x3a\x7c\x79\xc7\xe1\x19\xb5\xab\x02\x96\xab\x28\xc3\x00\xb9\xf3\xe4\xc0\xa2\xe0\x2d\x1d\x01\xf7\xf0\xa7\x46\x18\xaf\x2b\x48" - }, - { - 5, (u8 *) "\x83\x32\x22\x77\x2a", - (u8 *) "\x80\xad\x97\xbd\xc9\x73\xdf\x8a\x2e\x87\x9e\x92\xa4\x97\xef\xda\x20\xf0\x60\xc2\xf2\xe5\x12\x65\x01\xd3\xd4\xfe\xa1\x0d\x5f\xc0", - (u8 *) "\xfa\xa1\x48\xe9\x90\x46\x18\x1f\xec\x6b\x20\x85\xf3\xb2\x0e\xd9\xf0\xda\xf5\xba\xb3\xd5\x96\x83\x98\x57\x84\x6f\x73\xfb\xfe\x5a", - (u8 *) "\x1c\x7e\x2f\xc4\x63\x92\x32\xfe\x29\x75\x84\xb2\x96\x99\x6b\xc8\x3d\xb9\xb2\x49\x40\x6c\xc8\xed\xff\xac\x55\xcc\xd3\x22\xba\x12", - (u8 *) "\xe4\xf9\xf7\xe0\x06\x61\x54\xbb\xd1\x25\xb7\x45\x56\x9b\xc8\x97\x75\xd5\xef\x26\x2b\x44\xc4\x1a\x9c\xf6\x3a\xe1\x45\x68\xe1\xb9", - (u8 *) "\x6d\xa4\x53\xdb\xf8\x1e\x82\x33\x4a\x3d\x88\x66\xcb\x50\xa1\xe3\x78\x28\xd0\x74\x11\x9c\xab\x5c\x22\xb2\x94\xd7\xa9\xbf\xa0\xbb", - (u8 *) "\xad\xb8\x9c\xea\x9a\x15\xfb\xe6\x17\x29\x5b\xd0\x4b\x8c\xa0\x5c\x62\x51\xd8\x7f\xd4\xaa\xae\x9a\x7e\x4a\xd5\xc2\x17\xd3\xf3\x00", - (u8 *) "\xe7\x11\x9b\xd6\xdd\x9b\x22\xaf\xe8\xf8\x95\x85\x43\x28\x81\xe2\x78\x5b\x60\xfd\x7e\xc4\xe9\xfc\xb6\x54\x5f\x35\x0d\x66\x0f\xab", - (u8 *) "\xaf\xec\xc0\x37\xfd\xb7\xb0\x83\x8e\xb3\xd7\x0b\xcd\x26\x83\x82\xdb\xc1\xa7\xb4\x9d\x57\x35\x8c\xc9\xfa\x6d\x61\xd7\x3b\x7c\xf0", - (u8 *) "\x63\x49\xd1\x26\xa3\x7a\xfc\xba\x89\x79\x4f\x98\x04\x91\x4f\xdc\xbf\x42\xc3\x01\x8c\x2f\x7c\x66\xbf\xde\x52\x49\x75\x76\x81\x15" - }, - { - 7, (u8 *) "\x19\x10\x83\x32\x22\x77\x2a", - (u8 *) "\xbc\x92\x22\xdb\xd3\x27\x4d\x8f\xc6\x6d\x14\xcc\xbd\xa6\x69\x0b\x7a\xe6\x27\x41\x0c\x9a\x2b\xe6\x93\xdf\x5b\xb7\x48\x5a\x63\xe3", - (u8 *) "\x3f\x09\x31\xaa\x03\xde\xfb\x30\x0f\x06\x01\x03\x82\x6f\x2a\x64\xbe\xaa\x9e\xc8\xd5\x9b\xb6\x81\x29\xf3\x02\x7c\x96\x36\x11\x81", - (u8 *) "\x74\xe0\x4d\xb4\x6d\x28\x64\x8d\x7d\xee\x8a\x00\x64\xb0\x6c\xfe\x9b\x5e\x81\xc6\x2f\xe0\x23\xc5\x5b\xe4\x2f\x87\xbb\xf9\x32\xb8", - (u8 *) "\xce\x17\x8f\xc1\x82\x6e\xfe\xcb\xc1\x82\xf5\x79\x99\xa4\x61\x40\x8b\xdf\x55\xcd\x55\x06\x1c\x06\xdb\xa6\xbe\x11\xde\x4a\x57\x8a", - (u8 *) "\x62\x6f\x5f\x4d\xce\x65\x25\x01\xf3\x08\x7d\x39\xc9\x2c\xc3\x49\x42\xda\xac\x6a\x8f\x9a\xb9\xa7\xfd\x13\x7c\x60\x37\x82\x56\x82", - (u8 *) "\xcc\x03\xfd\xb7\x91\x92\xa2\x07\x31\x2f\x53\xf5\xd4\xdc\x33\xd9\xf7\x0f\x14\x12\x2a\x1c\x98\xa3\x15\x5d\x28\xb8\xa0\xa8\xa4\x1d", - (u8 *) "\x2a\x3a\x30\x7a\xb2\x70\x8a\x9c\x00\xfe\x0b\x42\xf9\xc2\xd6\xa1\x86\x26\x17\x62\x7d\x22\x61\xea\xb0\xb1\x24\x65\x97\xca\x0a\xe9", - (u8 *) "\x55\xf8\x77\xce\x4f\x2e\x1d\xdb\xbf\x8e\x13\xe2\xcd\xe0\xfd\xc8\x1b\x15\x56\xcb\x93\x5f\x17\x33\x37\x70\x5f\xbb\x5d\x50\x1f\xc1", - (u8 *) "\xec\xd0\xe9\x66\x02\xbe\x7f\x8d\x50\x92\x81\x6c\xcc\xf2\xc2\xe9\x02\x78\x81\xfa\xb4\x99\x3a\x1c\x26\x20\x24\xa9\x4f\xff\x3f\x61" - }, - { - 8, (u8 *) "\x64\x19\x10\x83\x32\x22\x77\x2a", - (u8 *) "\xbb\xf6\x09\xde\x94\x13\x17\x2d\x07\x66\x0c\xb6\x80\x71\x69\x26\x46\x10\x1a\x6d\xab\x43\x11\x5d\x6c\x52\x2b\x4f\xe9\x36\x04\xa9", - (u8 *) "\xcb\xe1\xff\xf2\x1c\x96\xf3\xee\xf6\x1e\x8f\xe0\x54\x2c\xbd\xf0\x34\x79\x38\xbf\xfa\x40\x09\xc5\x12\xcf\xb4\x03\x4b\x0d\xd1\xa7", - (u8 *) "\x78\x67\xa7\x86\xd0\x0a\x71\x47\x90\x4d\x76\xdd\xf1\xe5\x20\xe3\x8d\x3e\x9e\x1c\xae\xfc\xcc\xb3\xfb\xf8\xd1\x8f\x64\x12\x0b\x32", - (u8 *) "\x94\x23\x37\xf8\xfd\x76\xf0\xfa\xe8\xc5\x2d\x79\x54\x81\x06\x72\xb8\x54\x8c\x10\xf5\x16\x67\xf6\xe6\x0e\x18\x2f\xa1\x9b\x30\xf7", - (u8 *) "\x02\x11\xc7\xc6\x19\x0c\x9e\xfd\x12\x37\xc3\x4c\x8f\x2e\x06\xc4\xbd\xa6\x4f\x65\x27\x6d\x2a\xac\xb8\xf9\x02\x12\x20\x3a\x80\x8e", - (u8 *) "\xbd\x38\x20\xf7\x32\xff\xb5\x3e\xc1\x93\xe7\x9d\x33\xe2\x7c\x73\xd0\x16\x86\x16\x86\x19\x07\xd4\x82\xe3\x6c\xda\xc8\xcf\x57\x49", - (u8 *) "\x97\xb0\xf0\xf2\x24\xb2\xd2\x31\x71\x14\x80\x8f\xb0\x3a\xf7\xa0\xe5\x96\x16\xe4\x69\x78\x79\x39\xa0\x63\xce\xea\x9a\xf9\x56\xd1", - (u8 *) "\xc4\x7e\x0d\xc1\x66\x09\x19\xc1\x11\x01\x20\x8f\x9e\x69\xaa\x1f\x5a\xe4\xf1\x28\x96\xb8\x37\x9a\x2a\xad\x89\xb5\xb5\x53\xd6\xb0", - (u8 *) "\x6b\x6b\x09\x8d\x0c\x29\x3b\xc2\x99\x3d\x80\xbf\x05\x18\xb6\xd9\x81\x70\xcc\x3c\xcd\x92\xa6\x98\x62\x1b\x93\x9d\xd3\x8f\xe7\xb9" - }, - { - 10, (u8 *) "\x8b\x37\x64\x19\x10\x83\x32\x22\x77\x2a", - (u8 *) "\xab\x65\xc2\x6e\xdd\xb2\x87\x60\x0d\xb2\xfd\xa1\x0d\x1e\x60\x5c\xbb\x75\x90\x10\xc2\x96\x58\xf2\xc7\x2d\x93\xa2\xd1\x6d\x29\x30", - (u8 *) "\xb9\x01\xe8\x03\x6e\xd1\xc3\x83\xcd\x3c\x4c\x4d\xd0\xa6\xab\x05\x3d\x25\xce\x49\x22\x92\x4c\x55\xf0\x64\x94\x33\x53\xd7\x8a\x6c", - (u8 *) "\x12\xc1\xaa\x44\xbb\xf8\x7e\x75\xe6\x11\xf6\x9b\x2c\x38\xf4\x9b\x28\xf2\xb3\x43\x4b\x65\xc0\x98\x77\x47\x00\x44\xc6\xea\x17\x0d", - (u8 *) "\xbd\x9e\xf8\x22\xde\x52\x88\x19\x61\x34\xcf\x8a\xf7\x83\x93\x04\x67\x55\x9c\x23\xf0\x52\x15\x84\x70\xa2\x96\xf7\x25\x73\x5a\x32", - (u8 *) "\x8b\xab\x26\xfb\xc2\xc1\x2b\x0f\x13\xe2\xab\x18\x5e\xab\xf2\x41\x31\x18\x5a\x6d\x69\x6f\x0c\xfa\x9b\x42\x80\x8b\x38\xe1\x32\xa2", - (u8 *) "\x56\x4d\x3d\xae\x18\x3c\x52\x34\xc8\xaf\x1e\x51\x06\x1c\x44\xb5\x3c\x07\x78\xa7\xb5\xf7\x2d\x3c\x23\xa3\x13\x5c\x7d\x67\xb9\xf4", - (u8 *) "\xf3\x43\x69\x89\x0f\xcf\x16\xfb\x51\x7d\xca\xae\x44\x63\xb2\xdd\x02\xf3\x1c\x81\xe8\x20\x07\x31\xb8\x99\xb0\x28\xe7\x91\xbf\xa7", - (u8 *) "\x72\xda\x64\x62\x83\x22\x8c\x14\x30\x08\x53\x70\x17\x95\x61\x6f\x4e\x0a\x8c\x6f\x79\x34\xa7\x88\xe2\x26\x5e\x81\xd6\xd0\xc8\xf4", - (u8 *) "\x43\x8d\xd5\xea\xfe\xa0\x11\x1b\x6f\x36\xb4\xb9\x38\xda\x2a\x68\x5f\x6b\xfc\x73\x81\x58\x74\xd9\x71\x00\xf0\x86\x97\x93\x57\xd8" - }, - { - 16, (u8 *) "\xeb\xb4\x62\x27\xc6\xcc\x8b\x37\x64\x19\x10\x83\x32\x22\x77\x2a", - (u8 *) "\x72\x0c\x94\xb6\x3e\xdf\x44\xe1\x31\xd9\x50\xca\x21\x1a\x5a\x30\xc3\x66\xfd\xea\xcf\x9c\xa8\x04\x36\xbe\x7c\x35\x84\x24\xd2\x0b", - (u8 *) "\xb3\x39\x4a\x40\xaa\xbf\x75\xcb\xa4\x22\x82\xef\x25\xa0\x05\x9f\x48\x47\xd8\x1d\xa4\x94\x2d\xbc\x24\x9d\xef\xc4\x8c\x92\x2b\x9f", - (u8 *) "\x08\x12\x8c\x46\x9f\x27\x53\x42\xad\xda\x20\x2b\x2b\x58\xda\x95\x97\x0d\xac\xef\x40\xad\x98\x72\x3b\xac\x5d\x69\x55\xb8\x17\x61", - (u8 *) "\x3c\xb8\x99\x93\xb0\x7b\x0c\xed\x93\xde\x13\xd2\xa1\x10\x13\xac\xef\x2d\x67\x6f\x15\x45\xc2\xc1\x3d\xc6\x80\xa0\x2f\x4a\xdb\xfe", - (u8 *) "\xb6\x05\x95\x51\x4f\x24\xbc\x9f\xe5\x22\xa6\xca\xd7\x39\x36\x44\xb5\x15\xa8\xc5\x01\x17\x54\xf5\x90\x03\x05\x8b\xdb\x81\x51\x4e", - (u8 *) "\x3c\x70\x04\x7e\x8c\xbc\x03\x8e\x3b\x98\x20\xdb\x60\x1d\xa4\x95\x11\x75\xda\x6e\xe7\x56\xde\x46\xa5\x3e\x2b\x07\x56\x60\xb7\x70", - (u8 *) "\x00\xa5\x42\xbb\xa0\x21\x11\xcc\x2c\x65\xb3\x8e\xbd\xba\x58\x7e\x58\x65\xfd\xbb\x5b\x48\x06\x41\x04\xe8\x30\xb3\x80\xf2\xae\xde", - (u8 *) "\x34\xb2\x1a\xd2\xad\x44\xe9\x99\xdb\x2d\x7f\x08\x63\xf0\xd9\xb6\x84\xa9\x21\x8f\xc3\x6e\x8a\x5f\x2c\xcf\xbe\xae\x53\xa2\x7d\x25", - (u8 *) "\xa2\x22\x1a\x11\xb8\x33\xcc\xb4\x98\xa5\x95\x40\xf0\x54\x5f\x4a\x5b\xbe\xb4\x78\x7d\x59\xe5\x37\x3f\xdb\xea\x6c\x6f\x75\xc2\x9b" - }, - { - 24, (u8 *) "\xc1\x09\x16\x39\x08\xeb\xe5\x1d\xeb\xb4\x62\x27\xc6\xcc\x8b\x37\x64\x19\x10\x83\x32\x22\x77\x2a", - (u8 *) "\x54\xb6\x4e\x6b\x5a\x20\xb5\xe2\xec\x84\x59\x3d\xc7\x98\x9d\xa7\xc1\x35\xee\xe2\x37\xa8\x54\x65\xff\x97\xdc\x03\x92\x4f\x45\xce", - (u8 *) "\xcf\xcc\x92\x2f\xb4\xa1\x4a\xb4\x5d\x61\x75\xaa\xbb\xf2\xd2\x01\x83\x7b\x87\xe2\xa4\x46\xad\x0e\xf7\x98\xac\xd0\x2b\x94\x12\x4f", - (u8 *) "\x17\xa6\xdb\xd6\x64\x92\x6a\x06\x36\xb3\xf4\xc3\x7a\x4f\x46\x94\x4a\x5f\x9f\x26\xae\xee\xd4\xd4\xa2\x5f\x63\x2d\x30\x52\x33\xd9", - (u8 *) "\x80\xa3\xd0\x1e\xf0\x0c\x8e\x9a\x42\x09\xc1\x7f\x4e\xeb\x35\x8c\xd1\x5e\x7d\x5f\xfa\xaa\xbc\x02\x07\xbf\x20\x0a\x11\x77\x93\xa2", - (u8 *) "\x34\x96\x82\xbf\x58\x8e\xaa\x52\xd0\xaa\x15\x60\x34\x6a\xea\xfa\xf5\x85\x4c\xdb\x76\xc8\x89\xe3\xad\x63\x35\x4e\x5f\x72\x75\xe3", - (u8 *) "\x53\x2c\x7c\xec\xcb\x39\xdf\x32\x36\x31\x84\x05\xa4\xb1\x27\x9c\xba\xef\xe6\xd9\xce\xb6\x51\x84\x22\x60\xe0\xd1\xe0\x5e\x3b\x90", - (u8 *) "\xe8\x2d\x8c\x6d\xb5\x4e\x3c\x63\x3f\x58\x1c\x95\x2b\xa0\x42\x07\x4b\x16\xe5\x0a\xbd\x38\x1b\xd7\x09\x00\xa9\xcd\x9a\x62\xcb\x23", - (u8 *) "\x36\x82\xee\x33\xbd\x14\x8b\xd9\xf5\x86\x56\xcd\x8f\x30\xd9\xfb\x1e\x5a\x0b\x84\x75\x04\x5d\x9b\x20\xb2\x62\x86\x24\xed\xfd\x9e", - (u8 *) "\x63\xed\xd6\x84\xfb\x82\x62\x82\xfe\x52\x8f\x9c\x0e\x92\x37\xbc\xe4\xdd\x2e\x98\xd6\x96\x0f\xae\x0b\x43\x54\x54\x56\x74\x33\x91" - }, - { - 32, (u8 *) "\x1a\xda\x31\xd5\xcf\x68\x82\x21\xc1\x09\x16\x39\x08\xeb\xe5\x1d\xeb\xb4\x62\x27\xc6\xcc\x8b\x37\x64\x19\x10\x83\x32\x22\x77\x2a", - (u8 *) "\xdd\x5b\xcb\x00\x18\xe9\x22\xd4\x94\x75\x9d\x7c\x39\x5d\x02\xd3\xc8\x44\x6f\x8f\x77\xab\xf7\x37\x68\x53\x53\xeb\x89\xa1\xc9\xeb", - (u8 *) "\xaf\x3e\x30\xf9\xc0\x95\x04\x59\x38\x15\x15\x75\xc3\xfb\x90\x98\xf8\xcb\x62\x74\xdb\x99\xb8\x0b\x1d\x20\x12\xa9\x8e\xd4\x8f\x0e", - (u8 *) "\x25\xc3\x00\x5a\x1c\xb8\x5d\xe0\x76\x25\x98\x39\xab\x71\x98\xab\x9d\xcb\xc1\x83\xe8\xcb\x99\x4b\x72\x7b\x75\xbe\x31\x80\x76\x9c", - (u8 *) "\xa1\xd3\x07\x8d\xfa\x91\x69\x50\x3e\xd9\xd4\x49\x1d\xee\x4e\xb2\x85\x14\xa5\x49\x58\x58\x09\x6f\x59\x6e\x4b\xcd\x66\xb1\x06\x65", - (u8 *) "\x5f\x40\xd5\x9e\xc1\xb0\x3b\x33\x73\x8e\xfa\x60\xb2\x25\x5d\x31\x34\x77\xc7\xf7\x64\xa4\x1b\xac\xef\xf9\x0b\xf1\x4f\x92\xb7\xcc", - (u8 *) "\xac\x4e\x95\x36\x8d\x99\xb9\xeb\x78\xb8\xda\x8f\x81\xff\xa7\x95\x8c\x3c\x13\xf8\xc2\x38\x8b\xb7\x3f\x38\x57\x6e\x65\xb7\xc4\x46", - (u8 *) "\x13\xc4\xb9\xc1\xdf\xb6\x65\x79\xed\xdd\x8a\x28\x0b\x9f\x73\x16\xdd\xd2\x78\x20\x55\x01\x26\x69\x8e\xfa\xad\xc6\x4b\x64\xf6\x6e", - (u8 *) "\xf0\x8f\x2e\x66\xd2\x8e\xd1\x43\xf3\xa2\x37\xcf\x9d\xe7\x35\x59\x9e\xa3\x6c\x52\x55\x31\xb8\x80\xba\x12\x43\x34\xf5\x7b\x0b\x70", - (u8 *) "\xd5\xa3\x9e\x3d\xfc\xc5\x02\x80\xba\xc4\xa6\xb5\xaa\x0d\xca\x7d\x37\x0b\x1c\x1f\xe6\x55\x91\x6d\x97\xfd\x0d\x47\xca\x1d\x72\xb8" - } -}; - -#define NUM_TESTS (sizeof(tests) / sizeof(tests[0])) - - -static int run_test(unsigned int i, const u8 *key, size_t key_len, - const u8 *stream, int offset) -{ - u8 res[32]; - os_memset(res, 0, sizeof(res)); - if (rc4_skip(key, key_len, offset, res, sizeof(res)) < 0 || - os_memcmp(res, stream, 32) != 0) { - printf("RC4 test case %d (offset %d) - FAILED!\n", - i + 1, offset); - return 1; - } - return 0; -} - - -int main(int argc, char *argv[]) -{ - int ret = 0; - unsigned int i; - - for (i = 0; i < NUM_TESTS; i++) { - const struct rc4_test_vector *test = &tests[i]; - ret += run_test(i, test->key, test->key_len, - test->stream0, 0); - ret += run_test(i, test->key, test->key_len, - test->stream240, 240); - ret += run_test(i, test->key, test->key_len, - test->stream496, 496); - ret += run_test(i, test->key, test->key_len, - test->stream752, 752); - ret += run_test(i, test->key, test->key_len, - test->stream1008, 1008); - ret += run_test(i, test->key, test->key_len, - test->stream1520, 1520); - ret += run_test(i, test->key, test->key_len, - test->stream2032, 2032); - ret += run_test(i, test->key, test->key_len, - test->stream3056, 3056); - ret += run_test(i, test->key, test->key_len, - test->stream4080, 4080); - } - - if (ret == 0) - printf("All RC4 test cases passed\n"); - - return ret; -} diff --git a/tests/test-sha1.c b/tests/test-sha1.c index 1b390f1..6c48f2b 100644 --- a/tests/test-sha1.c +++ b/tests/test-sha1.c @@ -137,9 +137,8 @@ static int test_eap_fast(void) } printf("- PRF (TLS, SHA1/MD5) test case / key_block\n"); - if (tls_prf_sha1_md5(master_secret, sizeof(master_secret), - "key expansion", seed, sizeof(seed), - buf, sizeof(key_block)) || + if (tls_prf(master_secret, sizeof(master_secret), "key expansion", + seed, sizeof(seed), buf, sizeof(key_block)) || memcmp(key_block, buf, sizeof(key_block)) != 0) { printf("PRF test - FAILED!\n"); errors++; diff --git a/wlantest/wlantest.c b/wlantest/wlantest.c index a1a0b04..040cda1 100644 --- a/wlantest/wlantest.c +++ b/wlantest/wlantest.c @@ -1,6 +1,6 @@ /* * wlantest - IEEE 802.11 protocol monitoring and testing tool - * Copyright (c) 2010-2011, Jouni Malinen + * Copyright (c) 2010, Jouni Malinen * * 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 @@ -35,7 +35,7 @@ static void usage(void) "[-p]\n" " [-I] [-R] " "[-P]\n" - " [-w] [-f]\n"); + " [-w]\n"); } @@ -136,41 +136,6 @@ static void add_secret(struct wlantest *wt, const char *secret) } -static int add_pmk_file(struct wlantest *wt, const char *pmk_file) -{ - FILE *f; - u8 pmk[32]; - char buf[300], *pos; - struct wlantest_pmk *p; - - f = fopen(pmk_file, "r"); - if (f == NULL) { - wpa_printf(MSG_ERROR, "Could not open '%s'", pmk_file); - return -1; - } - - while (fgets(buf, sizeof(buf), f)) { - pos = buf; - while (*pos && *pos != '\r' && *pos != '\n') - pos++; - *pos = '\0'; - if (pos - buf < 2 * 32) - continue; - if (hexstr2bin(buf, pmk, 32) < 0) - continue; - p = os_zalloc(sizeof(*p)); - if (p == NULL) - break; - os_memcpy(p->pmk, pmk, 32); - dl_list_add(&wt->pmk, &p->list); - wpa_hexdump(MSG_DEBUG, "Added PMK from file", pmk, 32); - } - - fclose(f); - return 0; -} - - int add_wep(struct wlantest *wt, const char *key) { struct wlantest_wep *w; @@ -214,7 +179,7 @@ int main(int argc, char *argv[]) wlantest_init(&wt); for (;;) { - c = getopt(argc, argv, "cdf:hi:I:p:P:qr:R:w:W:"); + c = getopt(argc, argv, "cdhi:I:p:P:qr:R:w:W:"); if (c < 0) break; switch (c) { @@ -225,10 +190,6 @@ int main(int argc, char *argv[]) if (wpa_debug_level > 0) wpa_debug_level--; break; - case 'f': - if (add_pmk_file(&wt, optarg) < 0) - return -1; - break; case 'h': usage(); return 0; diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk index a656239..40fde34 100644 --- a/wpa_supplicant/Android.mk +++ b/wpa_supplicant/Android.mk @@ -19,13 +19,13 @@ LOCAL_PATH := $(call my-dir) PKG_CONFIG ?= pkg-config WPA_BUILD_SUPPLICANT := false -ifneq ($(BOARD_WPA_SUPPLICANT_DRIVER),) - WPA_BUILD_SUPPLICANT := true - CONFIG_DRIVER_$(BOARD_WPA_SUPPLICANT_DRIVER) := y +ifneq ($(TARGET_SIMULATOR),true) + ifneq ($(BOARD_WPA_SUPPLICANT_DRIVER),) + WPA_BUILD_SUPPLICANT := true + CONFIG_DRIVER_$(BOARD_WPA_SUPPLICANT_DRIVER) := y + endif endif -ifeq ($(WPA_BUILD_SUPPLICANT),true) - include $(LOCAL_PATH)/.config # To ignore possible wrong network configurations @@ -1171,17 +1171,6 @@ endif ifndef DBUS_INCLUDE DBUS_INCLUDE := $(shell $(PKG_CONFIG) --cflags dbus-1) endif -dbus_version=$(subst ., ,$(shell $(PKG_CONFIG) --modversion dbus-1)) -DBUS_VERSION_MAJOR=$(word 1,$(dbus_version)) -DBUS_VERSION_MINOR=$(word 2,$(dbus_version)) -ifeq ($(DBUS_VERSION_MAJOR),) -DBUS_VERSION_MAJOR=0 -endif -ifeq ($(DBUS_VERSION_MINOR),) -DBUS_VERSION_MINOR=0 -endif -DBUS_INCLUDE += -DDBUS_VERSION_MAJOR=$(DBUS_VERSION_MAJOR) -DBUS_INCLUDE += -DDBUS_VERSION_MINOR=$(DBUS_VERSION_MINOR) DBUS_CFLAGS += $(DBUS_INCLUDE) endif @@ -1400,6 +1389,8 @@ ifndef LDO LDO=$(CC) endif +ifeq ($(WPA_BUILD_SUPPLICANT),true) + ######################## include $(CLEAR_VARS) diff --git a/wpa_supplicant/ChangeLog b/wpa_supplicant/ChangeLog index 06119c6..a51298b 100644 --- a/wpa_supplicant/ChangeLog +++ b/wpa_supplicant/ChangeLog @@ -1,5 +1,179 @@ ChangeLog for wpa_supplicant +2012-04-18 - v1.0 + * bsd: Add support for setting HT values in IFM_MMASK. + * Delay STA entry removal until Deauth/Disassoc TX status in AP mode. + This allows the driver to use PS buffering of Deauthentication and + Disassociation frames when the STA is in power save sleep. Only + available with drivers that provide TX status events for Deauth/ + Disassoc frames (nl80211). + * Drop oldest unknown BSS table entries first. This makes it less + likely to hit connection issues in environments with huge number + of visible APs. + * Add systemd support. + * Add support for setting the syslog facility from the config file + at build time. + * atheros: Add support for IEEE 802.11w configuration. + * AP mode: Allow enable HT20 if driver supports it, by setting the + config parameter ieee80211n. + * Allow AP mode to disconnect STAs based on low ACK condition (when + the data connection is not working properly, e.g., due to the STA + going outside the range of the AP). Disabled by default, enable by + config option disassoc_low_ack. + * nl80211: + - Support GTK rekey offload. + - Support PMKSA candidate events. This adds support for RSN + pre-authentication with nl80211 interface and drivers that handle + roaming internally. + * dbus: + - Add a DBus signal for EAP SM requests, emitted on the Interface + object. + - Export max scan ssids supported by the driver as MaxScanSSID. + - Add signal Certification for information about server certification. + - Add BSSExpireAge and BSSExpireCount interface properties and + support set/get, which allows for setting BSS cache expiration age + and expiration scan count. + - Add ConfigFile to AddInterface properties. + - Add Interface.Country property and support to get/set the value. + - Add DBus property CurrentAuthMode. + - P2P DBus API added. + - Emit property changed events (for property BSSs) when adding/ + removing BSSs. + - Treat '' in SSIDs of Interface.Scan as a request for broadcast + scan, instead of ignoring it. + - Add DBus getter/setter for FastReauth. + - Raise PropertiesChanged on org.freedesktop.DBus.Properties. + * wpa_cli: + - Send AP-STA-DISCONNECTED event when an AP disconnects a station + due to inactivity. + - Make second argument to set command optional. This can be used to + indicate a zero length value. + - Add signal_poll command. + - Add bss_expire_age and bss_expire_count commands to set/get BSS + cache expiration age and expiration scan count. + - Add ability to set scan interval (the time in seconds wpa_s waits + before requesting a new scan after failing to find a suitable + network in scan results) using scan_interval command. + - Add event CTRL-EVENT-ASSOC-REJECT for association rejected. + - Add command get version, that returns wpa_supplicant version string. + - Add command sta_autoconnect for disabling automatic reconnection + on receiving disconnection event. + - Setting bssid parameter to an empty string "" or any can now be + used to clear the bssid_set flag in a network block, i.e., to remove + bssid filtering. + - Add tdls_testing command to add a special testing feature for + changing TDLS behavior. Build param CONFIG_TDLS_TESTING must be + enabled as well. + - For interworking, add wpa_cli commands interworking_select, + interworking_connect, anqp_get, fetch_anqp, and stop_fetch_anqp. + - Many P2P commands were added. See README-P2P. + - Many WPS/WPS ER commands - see WPS/WPS ER sections for details. + - Allow set command to change global config parameters. + - Add log_level command, which can be used to display the current + debugging level and to change the log level during run time. + - Add note command, which can be used to insert notes to the debug + log. + - Add internal line edit implementation. CONFIG_WPA_CLI_EDIT=y + can now be used to build wpa_cli with internal implementation of + line editing and history support. This can be used as a replacement + for CONFIG_READLINE=y. + * AP mode: Add max_num_sta config option, which can be used to limit + the number of stations allowed to connect to the AP. + * Add WPA_IGNORE_CONFIG_ERRORS build option to continue in case of bad + config file. + * wext: Increase scan timeout from 5 to 10 seconds. + * Add blacklist command, allowing an external program to + manage the BSS blacklist and display its current contents. + * WPS: + - Add wpa_cli wps_pin get command for generating random PINs. This can + be used in a UI to generate a PIN without starting WPS (or P2P) + operation. + - Set RF bands based on driver capabilities, instead of hardcoding + them. + - Add mechanism for indicating non-standard WPS errors. + - Add CONFIG_WPS_REG_DISABLE_OPEN=y option to disable open networks + by default. + - Add wps_ap_pin cli command for wpa_supplicant AP mode. + - Add wps_check_pin cli command for processing PIN from user input. + UIs can use this command to process a PIN entered by a user and to + validate the checksum digit (if present). + - Cancel WPS operation on PBC session overlap detection. + - New wps_cancel command in wpa_cli will cancel a pending WPS + operation. + - wpa_cli action: Add WPS_EVENT_SUCCESS and WPS_EVENT_FAIL handlers. + - Trigger WPS config update on Manufacturer, Model Name, Model + Number, and Serial Number changes. + - Fragment size is now configurable for EAP-WSC peer. Use + wpa_cli set wps_fragment_size . + - Disable AP PIN after 10 consecutive failures. Slow down attacks on + failures up to 10. + - Allow AP to start in Enrollee mode without AP PIN for probing, to + be compatible with Windows 7. + - Add Config Error into WPS-FAIL events to provide more info to the + user on how to resolve the issue. + - Label and Display config methods are not allowed to be enabled + at the same time, since it is unclear which PIN to use if both + methods are advertised. + - When controlling multiple interfaces: + - apply WPS commands to all interfaces configured to use WPS + - apply WPS config changes to all interfaces that use WPS + - when an attack is detected on any interface, disable AP PIN on + all interfaces + * WPS ER: + - Add special AP Setup Locked mode to allow read only ER. + ap_setup_locked=2 can now be used to enable a special mode where + WPS ER can learn the current AP settings, but cannot change them. + - Show SetSelectedRegistrar events as ctrl_iface events + - Add wps_er_set_config to enroll a network based on a local + network configuration block instead of having to (re-)learn the + current AP settings with wps_er_learn. + - Allow AP filtering based on IP address, add ctrl_iface event for + learned AP settings, add wps_er_config command to configure an AP. + * WPS 2.0: Add support for WPS 2.0 (CONFIG_WPS2) + - Add build option CONFIG_WPS_EXTENSIBILITY_TESTING to enable tool + for testing protocol extensibility. + - Add build option CONFIG_WPS_STRICT to allow disabling of WPS + workarounds. + - Add support for AuthorizedMACs attribute. + * TDLS: + - Propogate TDLS related nl80211 capability flags from kernel and + add them as driver capability flags. If the driver doesn't support + capabilities, assume TDLS is supported internally. When TDLS is + explicitly not supported, disable all user facing TDLS operations. + - Allow TDLS to be disabled at runtime (mostly for testing). + Use set tdls_disabled. + - Honor AP TDLS settings that prohibit/allow TDLS. + - Add a special testing feature for changing TDLS behavior. Use + CONFIG_TDLS_TESTING build param to enable. Configure at runtime + with tdls_testing cli command. + - Add support for TDLS 802.11z. + * wlantest: Add a tool wlantest for IEEE802.11 protocol testing. + wlantest can be used to capture frames from a monitor interface + for realtime capturing or from pcap files for offline analysis. + * Interworking: Support added for 802.11u. Enable in .config with + CONFIG_INTERWORKING. See wpa_supplicant.conf for config parameters + for interworking. wpa_cli commands added to support this are + interworking_select, interworking_connect, anqp_get, fetch_anqp, + and stop_fetch_anqp. + * Android: Add build and runtime support for Android wpa_supplicant. + * bgscan learn: Add new bgscan that learns BSS information based on + previous scans, and uses that information to dynamically generate + the list of channels for background scans. + * Add a new debug message level for excessive information. Use + -ddd to enable. + * TLS: Add support for tls_disable_time_checks=1 in client mode. + * Internal TLS: + - Add support for TLS v1.1 (RFC 4346). Enable with build parameter + CONFIG_TLSV11. + - Add domainComponent parser for X.509 names. + * Linux: Add RFKill support by adding an interface state "disabled". + * Reorder some IEs to get closer to IEEE 802.11 standard. Move + WMM into end of Beacon, Probe Resp and (Re)Assoc Resp frames. + Move HT IEs to be later in (Re)Assoc Resp. + * Solaris: Add support for wired 802.1X client. + * Wi-Fi Direct support. See README-P2P for more information. + * Many bugfixes. + 2010-04-18 - v0.7.2 * nl80211: fixed number of issues with roaming * avoid unnecessary roaming if multiple APs with similar signal diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index cab9dfd..a75a293 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -15,12 +15,13 @@ CFLAGS += -I../src/utils -include .config -ALL=wpa_supplicant wpa_cli +BINALL=wpa_supplicant wpa_cli ifndef CONFIG_NO_WPA_PASSPHRASE -ALL += wpa_passphrase +BINALL += wpa_passphrase endif +ALL = $(BINALL) ALL += systemd/wpa_supplicant.service ALL += systemd/wpa_supplicant@.service ALL += systemd/wpa_supplicant-nl80211@.service @@ -48,9 +49,10 @@ mkconfig: echo CONFIG_DRIVER_HOSTAP=y >> .config echo CONFIG_DRIVER_WEXT=y >> .config -install: all - mkdir -p $(DESTDIR)$(BINDIR) - for i in $(ALL); do cp $$i $(DESTDIR)$(BINDIR)/$$i; done +$(DESTDIR)$(BINDIR)/%: % + install -D $(<) $(@) + +install: $(addprefix $(DESTDIR)$(BINDIR)/,$(BINALL)) $(MAKE) -C ../src install OBJS = config.o @@ -830,11 +832,6 @@ ifdef CONFIG_TLSV11 CFLAGS += -DCONFIG_TLSV11 endif -ifdef CONFIG_TLSV12 -CFLAGS += -DCONFIG_TLSV12 -NEED_SHA256=y -endif - ifeq ($(CONFIG_TLS), openssl) ifdef TLS_FUNCS CFLAGS += -DEAP_TLS_OPENSSL @@ -919,9 +916,6 @@ OBJS += ../src/tls/pkcs8.o NEED_SHA256=y NEED_BASE64=y NEED_TLS_PRF=y -ifdef CONFIG_TLSV12 -NEED_TLS_PRF_SHA256=y -endif NEED_MODEXP=y NEED_CIPHER=y CFLAGS += -DCONFIG_TLS_INTERNAL_CLIENT @@ -1105,9 +1099,6 @@ SHA256OBJS += ../src/crypto/sha256.o ifdef CONFIG_INTERNAL_SHA256 SHA256OBJS += ../src/crypto/sha256-internal.o endif -ifdef NEED_TLS_PRF_SHA256 -SHA256OBJS += ../src/crypto/sha256-tlsprf.o -endif OBJS += $(SHA256OBJS) endif @@ -1164,17 +1155,6 @@ endif ifndef DBUS_INCLUDE DBUS_INCLUDE := $(shell $(PKG_CONFIG) --cflags dbus-1) endif -dbus_version=$(subst ., ,$(shell $(PKG_CONFIG) --modversion dbus-1)) -DBUS_VERSION_MAJOR=$(word 1,$(dbus_version)) -DBUS_VERSION_MINOR=$(word 2,$(dbus_version)) -ifeq ($(DBUS_VERSION_MAJOR),) -DBUS_VERSION_MAJOR=0 -endif -ifeq ($(DBUS_VERSION_MINOR),) -DBUS_VERSION_MINOR=0 -endif -DBUS_INCLUDE += -DDBUS_VERSION_MAJOR=$(DBUS_VERSION_MAJOR) -DBUS_INCLUDE += -DDBUS_VERSION_MINOR=$(DBUS_VERSION_MINOR) DBUS_CFLAGS += $(DBUS_INCLUDE) endif @@ -1289,7 +1269,6 @@ endif OBJS += $(SHA1OBJS) $(DESOBJS) OBJS_p += $(SHA1OBJS) -OBJS_p += $(SHA256OBJS) ifdef CONFIG_BGSCAN_SIMPLE CFLAGS += -DCONFIG_BGSCAN_SIMPLE @@ -1414,17 +1393,15 @@ wpa_priv: $(BCHECK) $(OBJS_priv) $(Q)$(LDO) $(LDFLAGS) -o wpa_priv $(OBJS_priv) $(LIBS) @$(E) " LD " $@ -$(OBJS_c) $(OBJS_t) $(OBJS_t2) $(OBJS) $(BCHECK) $(EXTRA_progs): .config - -wpa_supplicant: $(BCHECK) $(OBJS) $(EXTRA_progs) +wpa_supplicant: .config $(BCHECK) $(OBJS) $(EXTRA_progs) $(Q)$(LDO) $(LDFLAGS) -o wpa_supplicant $(OBJS) $(LIBS) $(EXTRALIBS) @$(E) " LD " $@ -eapol_test: $(OBJS_t) +eapol_test: .config $(OBJS_t) $(Q)$(LDO) $(LDFLAGS) -o eapol_test $(OBJS_t) $(LIBS) @$(E) " LD " $@ -preauth_test: $(OBJS_t2) +preauth_test: .config $(OBJS_t2) $(Q)$(LDO) $(LDFLAGS) -o preauth_test $(OBJS_t2) $(LIBS) @$(E) " LD " $@ @@ -1495,8 +1472,11 @@ WINALL=wpa_supplicant.exe wpa_cli.exe wpa_passphrase.exe win_if_list.exe windows-bin: $(WINALL) $(STRIP) $(WINALL) -wpa_gui: - @echo "wpa_gui has been removed - see wpa_gui-qt4 for replacement" +wpa_gui/Makefile: + qmake -o wpa_gui/Makefile wpa_gui/wpa_gui.pro + +wpa_gui: wpa_gui/Makefile + $(MAKE) -C wpa_gui wpa_gui-qt4/Makefile: qmake -o wpa_gui-qt4/Makefile wpa_gui-qt4/wpa_gui.pro diff --git a/wpa_supplicant/README b/wpa_supplicant/README index 4d02f8f..f324192 100644 --- a/wpa_supplicant/README +++ b/wpa_supplicant/README @@ -1,7 +1,7 @@ WPA Supplicant ============== -Copyright (c) 2003-2011, Jouni Malinen and contributors +Copyright (c) 2003-2012, Jouni Malinen and contributors All Rights Reserved. This program is dual-licensed under both the GPL version 2 and BSD @@ -138,6 +138,39 @@ Current hardware/software requirements: default option to start with before falling back to driver specific interface. + Host AP driver for Prism2/2.5/3 (development snapshot/v0.2.x) + (http://hostap.epitest.fi/) + Driver need to be set in Managed mode ('iwconfig wlan0 mode managed'). + Please note that station firmware version needs to be 1.7.0 or newer + to work in WPA mode. + + Linuxant DriverLoader (http://www.linuxant.com/driverloader/) + with Windows NDIS driver for your wlan card supporting WPA. + + madwifi driver for cards based on Atheros chip set (ar521x) + (http://sourceforge.net/projects/madwifi/) + Please note that you will need to modify the wpa_supplicant .config + file to use the correct path for the madwifi driver root directory + (CFLAGS += -I../madwifi/wpa line in example defconfig). + + Linux ndiswrapper (http://ndiswrapper.sourceforge.net/) with + Windows NDIS driver. + + Broadcom wl.o driver (old version only) + This is a generic Linux driver for Broadcom IEEE 802.11a/g cards. + However, it is proprietary driver that is not publicly available + except for couple of exceptions, mainly Broadcom-based APs/wireless + routers that use Linux. The driver binary can be downloaded, e.g., + from Linksys support site (http://www.linksys.com/support/gpl.asp) + for Linksys WRT54G. The GPL tarball includes cross-compiler and + the needed header file, wlioctl.h, for compiling wpa_supplicant. + This driver support in wpa_supplicant is expected to work also with + other devices based on Broadcom driver (assuming the driver includes + client mode support). Please note that the newer Broadcom driver + ("hybrid Linux driver") supports Linux wireless extensions and does + not need (or even work) with the specific driver wrapper. Use -Dwext + with that driver. + In theory, any driver that supports Linux wireless extensions can be used with IEEE 802.1X (i.e., not WPA) when using ap_scan=0 option in configuration file. @@ -314,7 +347,7 @@ and a list of available options and additional notes. The build time configuration can be used to select only the needed features and limit the binary size and requirements for external libraries. The main configuration parts are the selection of which -driver interfaces (e.g., nl80211, wext, ..) and which authentication +driver interfaces (e.g., hostap, madwifi, ..) and which authentication methods (e.g., EAP-TLS, EAP-PEAP, ..) are included. Following build time configuration options are used to control IEEE @@ -349,16 +382,21 @@ CONFIG_PCSC=y Following options can be added to .config to select which driver interfaces are included. -CONFIG_DRIVER_NL80211=y +CONFIG_DRIVER_HOSTAP=y +CONFIG_DRIVER_MADWIFI=y CONFIG_DRIVER_WEXT=y +CONFIG_DRIVER_RALINK=y +CONFIG_DRIVER_BROADCOM=y CONFIG_DRIVER_BSD=y CONFIG_DRIVER_NDIS=y -Following example includes some more features and driver interfaces that -are included in the wpa_supplicant package: +Following example includes all features and driver interfaces that are +included in the wpa_supplicant package: -CONFIG_DRIVER_NL80211=y +CONFIG_DRIVER_HOSTAP=y +CONFIG_DRIVER_MADWIFI=y CONFIG_DRIVER_WEXT=y +CONFIG_DRIVER_BROADCOM=y CONFIG_DRIVER_BSD=y CONFIG_DRIVER_NDIS=y CONFIG_IEEE8021X_EAPOL=y @@ -451,7 +489,12 @@ options: -N = start describing new interface drivers: + hostap = Host AP driver (Intersil Prism2/2.5/3) [default] + (this can also be used with Linuxant DriverLoader) + madwifi = MADWIFI 802.11 support (Atheros, etc.) (deprecated; use wext) wext = Linux wireless extensions (generic) + ralink = Ralink Client driver + broadcom = Broadcom wl.o driver wired = wpa_supplicant wired Ethernet driver roboswitch = wpa_supplicant Broadcom switch driver bsd = BSD 802.11 support (Atheros, etc.) @@ -484,15 +527,15 @@ separated with -N argument. As an example, following command would start wpa_supplicant for two interfaces: wpa_supplicant \ - -c wpa1.conf -i wlan0 -D nl80211 -N \ - -c wpa2.conf -i wlan1 -D wext + -c wpa1.conf -i wlan0 -D hostap -N \ + -c wpa2.conf -i ath0 -D madwifi If the interface is added in a Linux bridge (e.g., br0), the bridge interface needs to be configured to wpa_supplicant in addition to the main interface: -wpa_supplicant -cw.conf -Dwext -iwlan0 -bbr0 +wpa_supplicant -cw.conf -Dmadwifi -iath0 -bbr0 Configuration file diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index a3b460e..75b1393 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -30,6 +30,9 @@ #include "ap/ieee802_1x.h" #include "ap/wps_hostapd.h" #include "ap/ctrl_iface_ap.h" +#include "eap_common/eap_defs.h" +#include "eap_server/eap_methods.h" +#include "eap_common/eap_wsc_common.h" #include "wps/wps.h" #include "common/ieee802_11_defs.h" #include "config_ssid.h" @@ -80,10 +83,9 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s, #ifdef CONFIG_IEEE80211N /* - * Enable HT20 if the driver supports it, by setting conf->ieee80211n - * and a mask of allowed capabilities within conf->ht_capab. + * Enable HT20 if the driver supports it, by setting conf->ieee80211n. * Using default config settings for: conf->ht_op_mode_fixed, - * conf->secondary_channel, conf->require_ht + * conf->ht_capab, conf->secondary_channel, conf->require_ht */ if (wpa_s->hw.modes) { struct hostapd_hw_modes *mode = NULL; @@ -94,21 +96,8 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s, break; } } - if (mode && mode->ht_capab) { + if (mode && mode->ht_capab) conf->ieee80211n = 1; - - /* - * white-list capabilities that won't cause issues - * to connecting stations, while leaving the current - * capabilities intact (currently disabled SMPS). - */ - conf->ht_capab |= mode->ht_capab & - (HT_CAP_INFO_GREEN_FIELD | - HT_CAP_INFO_SHORT_GI20MHZ | - HT_CAP_INFO_SHORT_GI40MHZ | - HT_CAP_INFO_RX_STBC_MASK | - HT_CAP_INFO_MAX_AMSDU_SIZE); - } } #endif /* CONFIG_IEEE80211N */ @@ -328,9 +317,9 @@ static void ap_wps_event_cb(void *ctx, enum wps_event event, static void ap_sta_authorized_cb(void *ctx, const u8 *mac_addr, - int authorized) + int authorized, const u8 *p2p_dev_addr) { - wpas_notify_sta_authorized(ctx, mac_addr, authorized); + wpas_notify_sta_authorized(ctx, mac_addr, authorized, p2p_dev_addr); } @@ -466,7 +455,6 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s, return -1; hapd_iface->owner = wpa_s; hapd_iface->drv_flags = wpa_s->drv_flags; - hapd_iface->probe_resp_offloads = wpa_s->probe_resp_offloads; wpa_s->ap_iface->conf = conf = hostapd_config_defaults(); if (conf == NULL) { @@ -586,16 +574,6 @@ void ap_tx_status(void *ctx, const u8 *addr, } -void ap_eapol_tx_status(void *ctx, const u8 *dst, - const u8 *data, size_t len, int ack) -{ -#ifdef NEED_AP_MLME - struct wpa_supplicant *wpa_s = ctx; - hostapd_tx_status(wpa_s->ap_iface->bss[0], dst, data, len, ack); -#endif /* NEED_AP_MLME */ -} - - void ap_client_poll_ok(void *ctx, const u8 *addr) { #ifdef NEED_AP_MLME @@ -913,7 +891,9 @@ int wpa_supplicant_ap_update_beacon(struct wpa_supplicant *wpa_s) struct wpa_ssid *ssid = wpa_s->current_ssid; struct hostapd_data *hapd; - if (ssid == NULL || wpa_s->ap_iface == NULL) + if (ssid == NULL || wpa_s->ap_iface == NULL || + ssid->mode == WPAS_MODE_INFRA || + ssid->mode == WPAS_MODE_IBSS) return -1; #ifdef CONFIG_P2P @@ -924,8 +904,10 @@ int wpa_supplicant_ap_update_beacon(struct wpa_supplicant *wpa_s) P2P_GROUP_FORMATION; #endif /* CONFIG_P2P */ - ieee802_11_set_beacons(iface); hapd = iface->bss[0]; + if (hapd->drv_priv == NULL) + return -1; + ieee802_11_set_beacons(iface); hostapd_set_ap_wps_ie(hapd); return 0; diff --git a/wpa_supplicant/ap.h b/wpa_supplicant/ap.h index aa4c362..567e784 100644 --- a/wpa_supplicant/ap.h +++ b/wpa_supplicant/ap.h @@ -41,8 +41,6 @@ int ap_ctrl_iface_wpa_get_status(struct wpa_supplicant *wpa_s, char *buf, size_t buflen, int verbose); void ap_tx_status(void *ctx, const u8 *addr, const u8 *buf, size_t len, int ack); -void ap_eapol_tx_status(void *ctx, const u8 *dst, - const u8 *data, size_t len, int ack); void ap_client_poll_ok(void *ctx, const u8 *addr); void ap_rx_from_unknown_sta(void *ctx, const u8 *addr, int wds); void ap_mgmt_rx(void *ctx, struct rx_mgmt *rx_mgmt); diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c index dec9323..a13a1af 100644 --- a/wpa_supplicant/bss.c +++ b/wpa_supplicant/bss.c @@ -332,6 +332,8 @@ static void wpa_bss_update(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, nbss = os_realloc(bss, sizeof(*bss) + res->ie_len + res->beacon_ie_len); if (nbss) { + if (wpa_s->current_bss == bss) + wpa_s->current_bss = nbss; bss = nbss; os_memcpy(bss + 1, res + 1, res->ie_len + res->beacon_ie_len); @@ -569,6 +571,23 @@ struct wpa_bss * wpa_bss_get_bssid(struct wpa_supplicant *wpa_s, } +#ifdef CONFIG_P2P +struct wpa_bss * wpa_bss_get_p2p_dev_addr(struct wpa_supplicant *wpa_s, + const u8 *dev_addr) +{ + struct wpa_bss *bss; + dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, list) { + u8 addr[ETH_ALEN]; + if (p2p_parse_dev_addr((const u8 *) (bss + 1), bss->ie_len, + addr) == 0 && + os_memcmp(addr, dev_addr, ETH_ALEN) == 0) + return bss; + } + return NULL; +} +#endif /* CONFIG_P2P */ + + struct wpa_bss * wpa_bss_get_id(struct wpa_supplicant *wpa_s, unsigned int id) { struct wpa_bss *bss; diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h index 5dd8972..34e386f 100644 --- a/wpa_supplicant/bss.h +++ b/wpa_supplicant/bss.h @@ -103,6 +103,8 @@ struct wpa_bss * wpa_bss_get(struct wpa_supplicant *wpa_s, const u8 *bssid, const u8 *ssid, size_t ssid_len); struct wpa_bss * wpa_bss_get_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid); +struct wpa_bss * wpa_bss_get_p2p_dev_addr(struct wpa_supplicant *wpa_s, + const u8 *dev_addr); struct wpa_bss * wpa_bss_get_id(struct wpa_supplicant *wpa_s, unsigned int id); const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie); const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type); diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index b446a3f..600e32b 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -19,6 +19,7 @@ #include "crypto/sha1.h" #include "rsn_supp/wpa.h" #include "eap_peer/eap.h" +#include "p2p/p2p.h" #include "config.h" @@ -1116,6 +1117,7 @@ static int wpa_config_parse_eap(const struct parse_data *data, wpa_hexdump(MSG_MSGDUMP, "eap methods", (u8 *) methods, num_methods * sizeof(*methods)); + os_free(ssid->eap.eap_methods); ssid->eap.eap_methods = methods; return errors ? -1 : 0; } @@ -1351,6 +1353,90 @@ static char * wpa_config_write_wep_key3(const struct parse_data *data, #endif /* NO_CONFIG_WRITE */ +#ifdef CONFIG_P2P + +static int wpa_config_parse_p2p_client_list(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +{ + const char *pos; + u8 *buf, *n, addr[ETH_ALEN]; + size_t count; + + buf = NULL; + count = 0; + + pos = value; + while (pos && *pos) { + while (*pos == ' ') + pos++; + + if (hwaddr_aton(pos, addr)) { + wpa_printf(MSG_ERROR, "Line %d: Invalid " + "p2p_client_list address '%s'.", + line, value); + /* continue anyway */ + } else { + n = os_realloc(buf, (count + 1) * ETH_ALEN); + if (n == NULL) { + os_free(buf); + return -1; + } + buf = n; + os_memcpy(buf + count * ETH_ALEN, addr, ETH_ALEN); + count++; + wpa_hexdump(MSG_MSGDUMP, "p2p_client_list", + addr, ETH_ALEN); + } + + pos = os_strchr(pos, ' '); + } + + os_free(ssid->p2p_client_list); + ssid->p2p_client_list = buf; + ssid->num_p2p_clients = count; + + return 0; +} + + +#ifndef NO_CONFIG_WRITE +static char * wpa_config_write_p2p_client_list(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + char *value, *end, *pos; + int res; + size_t i; + + if (ssid->p2p_client_list == NULL || ssid->num_p2p_clients == 0) + return NULL; + + value = os_malloc(20 * ssid->num_p2p_clients); + if (value == NULL) + return NULL; + pos = value; + end = value + 20 * ssid->num_p2p_clients; + + for (i = 0; i < ssid->num_p2p_clients; i++) { + res = os_snprintf(pos, end - pos, MACSTR " ", + MAC2STR(ssid->p2p_client_list + + i * ETH_ALEN)); + if (res < 0 || res >= end - pos) { + os_free(value); + return NULL; + } + pos += res; + } + + if (pos > value) + pos[-1] = '\0'; + + return value; +} +#endif /* NO_CONFIG_WRITE */ + +#endif /* CONFIG_P2P */ + /* Helper macros for network block parser */ #ifdef OFFSET @@ -1511,6 +1597,9 @@ static const struct parse_data ssid_fields[] = { { INT_RANGE(frequency, 0, 10000) }, { INT(wpa_ptk_rekey) }, { STR(bgscan) }, +#ifdef CONFIG_P2P + { FUNC(p2p_client_list) }, +#endif /* CONFIG_P2P */ }; #undef OFFSET @@ -1677,6 +1766,7 @@ void wpa_config_free_ssid(struct wpa_ssid *ssid) os_free(ssid->scan_freq); os_free(ssid->freq_list); os_free(ssid->bgscan); + os_free(ssid->p2p_client_list); os_free(ssid); } @@ -1732,6 +1822,7 @@ void wpa_config_free(struct wpa_config *config) os_free(config->home_ca_cert); os_free(config->home_imsi); os_free(config->home_milenage); + os_free(config->p2p_pref_chan); os_free(config); } @@ -2406,6 +2497,55 @@ static int wpa_config_process_sec_device_type( config->num_sec_device_types++; return 0; } + + +static int wpa_config_process_p2p_pref_chan( + const struct global_parse_data *data, + struct wpa_config *config, int line, const char *pos) +{ + struct p2p_channel *pref = NULL, *n; + unsigned int num = 0; + const char *pos2; + u8 op_class, chan; + + /* format: class:chan,class:chan,... */ + + while (*pos) { + op_class = atoi(pos); + pos2 = os_strchr(pos, ':'); + if (pos2 == NULL) + goto fail; + pos2++; + chan = atoi(pos2); + + n = os_realloc(pref, (num + 1) * sizeof(struct p2p_channel)); + if (n == NULL) + goto fail; + pref = n; + pref[num].op_class = op_class; + pref[num].chan = chan; + num++; + + pos = os_strchr(pos2, ','); + if (pos == NULL) + break; + pos++; + } + + os_free(config->p2p_pref_chan); + config->p2p_pref_chan = pref; + config->num_p2p_pref_chan = num; + wpa_hexdump(MSG_DEBUG, "P2P: Preferred class/channel pairs", + (u8 *) config->p2p_pref_chan, + config->num_p2p_pref_chan * sizeof(struct p2p_channel)); + + return 0; + +fail: + os_free(pref); + wpa_printf(MSG_ERROR, "Line %d: Invalid p2p_pref_chan list", line); + return -1; +} #endif /* CONFIG_P2P */ @@ -2480,6 +2620,7 @@ static const struct global_parse_data global_fields[] = { { INT_RANGE(persistent_reconnect, 0, 1), 0 }, { INT_RANGE(p2p_intra_bss, 0, 1), CFG_CHANGED_P2P_INTRA_BSS }, { INT(p2p_group_idle), 0 }, + { FUNC(p2p_pref_chan), CFG_CHANGED_P2P_PREF_CHAN }, #endif /* CONFIG_P2P */ { FUNC(country), CFG_CHANGED_COUNTRY }, { INT(bss_max_count), 0 }, diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index f9e5043..18317f5 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -47,6 +47,7 @@ #define CFG_CHANGED_VENDOR_EXTENSION BIT(10) #define CFG_CHANGED_P2P_LISTEN_CHANNEL BIT(11) #define CFG_CHANGED_P2P_OPER_CHANNEL BIT(12) +#define CFG_CHANGED_P2P_PREF_CHAN BIT(13) /** * struct wpa_config - wpa_supplicant configuration data @@ -362,6 +363,8 @@ struct wpa_config { char *p2p_ssid_postfix; int persistent_reconnect; int p2p_intra_bss; + unsigned int num_p2p_pref_chan; + struct p2p_channel *p2p_pref_chan; #define MAX_WPS_VENDOR_EXT 10 /** diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index 8ea03ab..c1075e3 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -22,6 +22,7 @@ #include "config.h" #include "base64.h" #include "uuid.h" +#include "p2p/p2p.h" /** @@ -104,7 +105,9 @@ static int wpa_config_validate_network(struct wpa_ssid *ssid, int line) wpa_config_update_psk(ssid); } - if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set) { + if ((ssid->key_mgmt & (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK | + WPA_KEY_MGMT_PSK_SHA256)) && + !ssid->psk_set) { wpa_printf(MSG_ERROR, "Line %d: WPA-PSK accepted for key " "management, but no PSK configured.", line); errors++; @@ -493,6 +496,18 @@ static void write_wep_key(FILE *f, int idx, struct wpa_ssid *ssid) } +#ifdef CONFIG_P2P +static void write_p2p_client_list(FILE *f, struct wpa_ssid *ssid) +{ + char *value = wpa_config_get(ssid, "p2p_client_list"); + if (value == NULL) + return; + fprintf(f, "\tp2p_client_list=%s\n", value); + os_free(value); +} +#endif /* CONFIG_P2P */ + + static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) { int i; @@ -512,6 +527,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) write_pairwise(f, ssid); write_group(f, ssid); write_auth_alg(f, ssid); + STR(bgscan); #ifdef IEEE8021X_EAPOL write_eap(f, ssid); STR(identity); @@ -567,6 +583,9 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) INT(ieee80211w); #endif /* CONFIG_IEEE80211W */ STR(id_str); +#ifdef CONFIG_P2P + write_p2p_client_list(f, ssid); +#endif /* CONFIG_P2P */ #undef STR #undef INT @@ -682,6 +701,16 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config) fprintf(f, "p2p_intra_bss=%u\n", config->p2p_intra_bss); if (config->p2p_group_idle) fprintf(f, "p2p_group_idle=%u\n", config->p2p_group_idle); + if (config->p2p_pref_chan) { + unsigned int i; + fprintf(f, "p2p_pref_chan="); + for (i = 0; i < config->num_p2p_pref_chan; i++) { + fprintf(f, "%s%u:%u", i > 0 ? "," : "", + config->p2p_pref_chan[i].op_class, + config->p2p_pref_chan[i].chan); + } + fprintf(f, "\n"); + } #endif /* CONFIG_P2P */ if (config->country[0] && config->country[1]) { fprintf(f, "country=%c%c\n", diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h index 8419f43..8a47c0b 100644 --- a/wpa_supplicant/config_ssid.h +++ b/wpa_supplicant/config_ssid.h @@ -387,6 +387,20 @@ struct wpa_ssid { int *freq_list; /** + * p2p_client_list - List of P2P Clients in a persistent group (GO) + * + * This is a list of P2P Clients (P2P Device Address) that have joined + * the persistent group. This is maintained on the GO for persistent + * group entries (disabled == 2). + */ + u8 *p2p_client_list; + + /** + * num_p2p_clients - Number of entries in p2p_client_list + */ + size_t num_p2p_clients; + + /** * p2p_group - Network generated as a P2P group (used internally) */ int p2p_group; diff --git a/wpa_supplicant/config_winreg.c b/wpa_supplicant/config_winreg.c index 5fb2580..ea3a2ac 100644 --- a/wpa_supplicant/config_winreg.c +++ b/wpa_supplicant/config_winreg.c @@ -350,7 +350,9 @@ static struct wpa_ssid * wpa_config_read_network(HKEY hk, const TCHAR *netw, wpa_config_update_psk(ssid); } - if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set) { + if ((ssid->key_mgmt & (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK | + WPA_KEY_MGMT_PSK_SHA256)) && + !ssid->psk_set) { wpa_printf(MSG_ERROR, "WPA-PSK accepted for key management, " "but no PSK configured for network '" TSTR "'.", netw); diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index ebf9bbb..5ff6766 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -50,76 +50,6 @@ static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global, char *buf, int len); -static int pno_start(struct wpa_supplicant *wpa_s) -{ - int ret; - size_t i, num_ssid; - struct wpa_ssid *ssid; - struct wpa_driver_scan_params params; - - if (wpa_s->pno) - return 0; - - os_memset(¶ms, 0, sizeof(params)); - - num_ssid = 0; - ssid = wpa_s->conf->ssid; - while (ssid) { - if (!ssid->disabled) - num_ssid++; - ssid = ssid->next; - } - if (num_ssid > WPAS_MAX_SCAN_SSIDS) { - wpa_printf(MSG_DEBUG, "PNO: Use only the first %u SSIDs from " - "%u", WPAS_MAX_SCAN_SSIDS, (unsigned int) num_ssid); - num_ssid = WPAS_MAX_SCAN_SSIDS; - } - - if (num_ssid == 0) { - wpa_printf(MSG_DEBUG, "PNO: No configured SSIDs"); - return -1; - } - - params.filter_ssids = os_malloc(sizeof(struct wpa_driver_scan_filter) * - num_ssid); - if (params.filter_ssids == NULL) - return -1; - i = 0; - ssid = wpa_s->conf->ssid; - while (ssid) { - if (!ssid->disabled) { - params.ssids[i].ssid = ssid->ssid; - params.ssids[i].ssid_len = ssid->ssid_len; - params.num_ssids++; - os_memcpy(params.filter_ssids[i].ssid, ssid->ssid, - ssid->ssid_len); - params.filter_ssids[i].ssid_len = ssid->ssid_len; - params.num_filter_ssids++; - i++; - if (i == num_ssid) - break; - } - ssid = ssid->next; - } - - ret = wpa_drv_sched_scan(wpa_s, ¶ms, 10 * 1000); - os_free(params.filter_ssids); - if (ret == 0) - wpa_s->pno = 1; - return ret; -} - - -static int pno_stop(struct wpa_supplicant *wpa_s) -{ - if (wpa_s->pno) { - wpa_s->pno = 0; - return wpa_drv_stop_sched_scan(wpa_s); - } - return 0; -} - - static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, char *cmd) { @@ -198,11 +128,6 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, ret = -1; wpa_tdls_enable(wpa_s->wpa, !disabled); #endif /* CONFIG_TDLS */ - } else if (os_strcasecmp(cmd, "pno") == 0) { - if (atoi(value)) - ret = pno_start(wpa_s); - else - ret = pno_stop(wpa_s); } else { value[-1] = '='; ret = wpa_config_process_global(wpa_s->conf, cmd, -1); @@ -217,22 +142,18 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) { - int res = -1; + int res; wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd); if (os_strcmp(cmd, "version") == 0) { res = os_snprintf(buf, buflen, "%s", VERSION_STR); - } else if (os_strcasecmp(cmd, "country") == 0) { - if (wpa_s->conf->country[0] && wpa_s->conf->country[1]) - res = os_snprintf(buf, buflen, "%c%c", - wpa_s->conf->country[0], - wpa_s->conf->country[1]); + if (res < 0 || (unsigned int) res >= buflen) + return -1; + return res; } - if (res < 0 || (unsigned int) res >= buflen) - return -1; - return res; + return -1; } @@ -879,10 +800,9 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s, char *buf, size_t buflen) { char *pos, *end, tmp[30]; - int res, verbose, wps, ret; + int res, verbose, ret; verbose = os_strcmp(params, "-VERBOSE") == 0; - wps = os_strcmp(params, "-WPS") == 0; pos = buf; end = buf + buflen; if (wpa_s->wpa_state >= WPA_ASSOCIATED) { @@ -911,17 +831,6 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s, return pos - buf; pos += ret; - if (wps && ssid->passphrase && - wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && - (ssid->mode == WPAS_MODE_AP || - ssid->mode == WPAS_MODE_P2P_GO)) { - ret = os_snprintf(pos, end - pos, - "passphrase=%s\n", - ssid->passphrase); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - } if (ssid->id_str) { ret = os_snprintf(pos, end - pos, "id_str=%s\n", @@ -1675,6 +1584,9 @@ static int wpa_supplicant_ctrl_iface_remove_network( } eapol_sm_invalidate_cached_session(wpa_s->eapol); if (wpa_s->current_ssid) { +#ifdef CONFIG_SME + wpa_s->sme.prev_bssid_set = 0; +#endif /* CONFIG_SME */ wpa_sm_set_config(wpa_s->wpa, NULL); eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); wpa_supplicant_disassociate(wpa_s, @@ -1697,6 +1609,9 @@ static int wpa_supplicant_ctrl_iface_remove_network( } if (ssid == wpa_s->current_ssid || wpa_s->current_ssid == NULL) { +#ifdef CONFIG_SME + wpa_s->sme.prev_bssid_set = 0; +#endif /* CONFIG_SME */ /* * Invalidate the EAP session cache if the current or * previously used network is removed. @@ -2210,6 +2125,13 @@ static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s, bss = dl_list_entry(next, struct wpa_bss, list_id); } +#ifdef CONFIG_P2P + } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) { + if (hwaddr_aton(cmd + 13, bssid) == 0) + bss = wpa_bss_get_p2p_dev_addr(wpa_s, bssid); + else + bss = NULL; +#endif /* CONFIG_P2P */ } else if (hwaddr_aton(cmd, bssid) == 0) bss = wpa_bss_get_bssid(wpa_s, bssid); else { @@ -2451,13 +2373,23 @@ static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd) { unsigned int timeout = atoi(cmd); enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL; + u8 dev_id[ETH_ALEN], *_dev_id = NULL; + char *pos; if (os_strstr(cmd, "type=social")) type = P2P_FIND_ONLY_SOCIAL; else if (os_strstr(cmd, "type=progressive")) type = P2P_FIND_PROGRESSIVE; - return wpas_p2p_find(wpa_s, timeout, type, 0, NULL); + pos = os_strstr(cmd, "dev_id="); + if (pos) { + pos += 7; + if (hwaddr_aton(pos, dev_id)) + return -1; + _dev_id = dev_id; + } + + return wpas_p2p_find(wpa_s, timeout, type, 0, NULL, _dev_id); } @@ -2619,7 +2551,8 @@ static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd, if (*pos != ' ') return -1; pos++; - ref = wpas_p2p_sd_request_upnp(wpa_s, dst, version, pos); + ref = (unsigned long) wpas_p2p_sd_request_upnp(wpa_s, dst, + version, pos); } else { len = os_strlen(pos); if (len & 1) @@ -2633,11 +2566,9 @@ static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd, return -1; } - ref = wpas_p2p_sd_request(wpa_s, dst, tlvs); + ref = (unsigned long) wpas_p2p_sd_request(wpa_s, dst, tlvs); wpabuf_free(tlvs); } - if (ref == 0) - return -1; res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref); if (res < 0 || (unsigned) res >= buflen) return -1; @@ -2653,7 +2584,7 @@ static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s, if (sscanf(cmd, "%llx", &val) != 1) return -1; req = val; - return wpas_p2p_sd_cancel_request(wpa_s, req); + return wpas_p2p_sd_cancel_request(wpa_s, (void *) (unsigned long) req); } @@ -2708,6 +2639,8 @@ static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd) static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s, char *cmd) { + if (os_strcmp(cmd, "0") && os_strcmp(cmd, "1")) + return -1; wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd); return 0; } @@ -2985,7 +2918,11 @@ static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) { u8 addr[ETH_ALEN], *addr_ptr; - int next; + int next, res; + const struct p2p_peer_info *info; + char *pos, *end; + char devtype[WPS_DEV_TYPE_BUFSIZE]; + struct wpa_ssid *ssid; if (!wpa_s->global->p2p) return -1; @@ -3005,8 +2942,54 @@ static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd, next = 0; } - return p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next, - buf, buflen); + info = p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next); + if (info == NULL) + return -1; + + pos = buf; + end = buf + buflen; + + res = os_snprintf(pos, end - pos, MACSTR "\n" + "pri_dev_type=%s\n" + "device_name=%s\n" + "manufacturer=%s\n" + "model_name=%s\n" + "model_number=%s\n" + "serial_number=%s\n" + "config_methods=0x%x\n" + "dev_capab=0x%x\n" + "group_capab=0x%x\n" + "level=%d\n", + MAC2STR(info->p2p_device_addr), + wps_dev_type_bin2str(info->pri_dev_type, + devtype, sizeof(devtype)), + info->device_name, + info->manufacturer, + info->model_name, + info->model_number, + info->serial_number, + info->config_methods, + info->dev_capab, + info->group_capab, + info->level); + if (res < 0 || res >= end - pos) + return pos - buf; + pos += res; + + ssid = wpas_p2p_get_persistent(wpa_s, info->p2p_device_addr, NULL, 0); + if (ssid) { + res = os_snprintf(pos, end - pos, "persistent=%d\n", ssid->id); + if (res < 0 || res >= end - pos) + return pos - buf; + pos += res; + } + + res = p2p_get_peer_info_txt(info, pos, end - pos); + if (res < 0) + return pos - buf; + pos += res; + + return pos - buf; } @@ -3359,7 +3342,6 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, } else if (os_strcmp(buf, "LOGOFF") == 0) { eapol_sm_notify_logoff(wpa_s->eapol, TRUE); } else if (os_strcmp(buf, "REASSOCIATE") == 0) { - wpa_s->normal_scans = 0; if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) reply_len = -1; else { @@ -3368,7 +3350,6 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, wpa_supplicant_req_scan(wpa_s, 0, 0); } } else if (os_strcmp(buf, "RECONNECT") == 0) { - wpa_s->normal_scans = 0; if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) reply_len = -1; else if (wpa_s->disconnected) { @@ -3604,13 +3585,14 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, reply_len = wpa_supplicant_ctrl_iface_list_networks( wpa_s, reply, reply_size); } else if (os_strcmp(buf, "DISCONNECT") == 0) { +#ifdef CONFIG_SME + wpa_s->sme.prev_bssid_set = 0; +#endif /* CONFIG_SME */ wpa_s->reassociate = 0; wpa_s->disconnected = 1; - wpa_supplicant_cancel_sched_scan(wpa_s); wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING); } else if (os_strcmp(buf, "SCAN") == 0) { - wpa_s->normal_scans = 0; if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) reply_len = -1; else { @@ -3716,8 +3698,6 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, } else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) { reply_len = wpa_supplicant_signal_poll(wpa_s, reply, reply_size); - } else if (os_strcmp(buf, "REAUTHENTICATE") == 0) { - eapol_sm_request_reauth(wpa_s->eapol); } else { os_memcpy(reply, "UNKNOWN COMMAND\n", 16); reply_len = 16; diff --git a/wpa_supplicant/dbus/Makefile b/wpa_supplicant/dbus/Makefile index a088200..d64c65c 100644 --- a/wpa_supplicant/dbus/Makefile +++ b/wpa_supplicant/dbus/Makefile @@ -50,18 +50,6 @@ DBUS_INCLUDE += $(shell xml2-config --cflags) DBUS_LIBS += $(shell xml2-config --libs) endif -dbus_version=$(subst ., ,$(shell $(PKG_CONFIG) --modversion dbus-1)) -DBUS_VERSION_MAJOR=$(word 1,$(dbus_version)) -DBUS_VERSION_MINOR=$(word 2,$(dbus_version)) -ifeq ($(DBUS_VERSION_MAJOR),) -DBUS_VERSION_MAJOR=0 -endif -ifeq ($(DBUS_VERSION_MINOR),) -DBUS_VERSION_MINOR=0 -endif -DBUS_INCLUDE += -DDBUS_VERSION_MAJOR=$(DBUS_VERSION_MAJOR) -DBUS_INCLUDE += -DDBUS_VERSION_MINOR=$(DBUS_VERSION_MINOR) - CFLAGS += $(DBUS_INCLUDE) LIB_OBJS= \ diff --git a/wpa_supplicant/dbus/dbus-wpa_supplicant.conf b/wpa_supplicant/dbus/dbus-wpa_supplicant.conf index 728fe06..c091234 100644 --- a/wpa_supplicant/dbus/dbus-wpa_supplicant.conf +++ b/wpa_supplicant/dbus/dbus-wpa_supplicant.conf @@ -2,19 +2,7 @@ "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> - - - - - - - - - - - - - + diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c old mode 100644 new mode 100755 index 6cb43a5..133b321 --- a/wpa_supplicant/dbus/dbus_new.c +++ b/wpa_supplicant/dbus/dbus_new.c @@ -27,6 +27,7 @@ #include "dbus_dict_helpers.h" #include "dbus_new.h" #include "dbus_new_handlers.h" +#include "dbus_common.h" #include "dbus_common_i.h" #include "dbus_new_handlers_p2p.h" #include "p2p/p2p.h" @@ -867,7 +868,7 @@ void wpas_dbus_signal_p2p_provision_discovery(struct wpa_supplicant *wpa_s, return; /* Check if this is a known peer */ - if (p2p_get_peer_info(wpa_s->global->p2p, dev_addr, 0, NULL, 0) < 0) + if (!p2p_peer_known(wpa_s->global->p2p, dev_addr)) goto error; os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, @@ -1357,7 +1358,7 @@ void wpas_dbus_signal_p2p_sd_request(struct wpa_supplicant *wpa_s, return; /* Check if this is a known peer */ - if (p2p_get_peer_info(wpa_s->global->p2p, sa, 0, NULL, 0) < 0) + if (!p2p_peer_known(wpa_s->global->p2p, sa)) goto error; os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, @@ -1426,7 +1427,7 @@ void wpas_dbus_signal_p2p_sd_response(struct wpa_supplicant *wpa_s, return; /* Check if this is a known peer */ - if (p2p_get_peer_info(wpa_s->global->p2p, sa, 0, NULL, 0) < 0) + if (!p2p_peer_known(wpa_s->global->p2p, sa)) goto error; os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, @@ -2570,6 +2571,10 @@ static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = { wpas_dbus_getter_networks, NULL }, + { "FastReauth", WPAS_DBUS_NEW_IFACE_INTERFACE, "b", + wpas_dbus_getter_fast_reauth, + wpas_dbus_setter_fast_reauth + }, #ifdef CONFIG_WPS { "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b", wpas_dbus_getter_process_credentials, @@ -2577,9 +2582,9 @@ static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = { }, #endif /* CONFIG_WPS */ #ifdef CONFIG_P2P - { "P2PDeviceProperties", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "a{sv}", - wpas_dbus_getter_p2p_device_properties, - wpas_dbus_setter_p2p_device_properties + { "P2PDeviceConfig", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "a{sv}", + wpas_dbus_getter_p2p_device_config, + wpas_dbus_setter_p2p_device_config }, { "Peers", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao", wpas_dbus_getter_p2p_peers, @@ -2908,8 +2913,36 @@ int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s) #ifdef CONFIG_P2P static const struct wpa_dbus_property_desc wpas_dbus_p2p_peer_properties[] = { - { "Properties", WPAS_DBUS_NEW_IFACE_P2P_PEER, "a{sv}", - wpas_dbus_getter_p2p_peer_properties, + { "DeviceName", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s", + wpas_dbus_getter_p2p_peer_device_name, + NULL + }, + { "PrimaryDeviceType", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay", + wpas_dbus_getter_p2p_peer_primary_device_type, + NULL + }, + { "config_method", WPAS_DBUS_NEW_IFACE_P2P_PEER, "q", + wpas_dbus_getter_p2p_peer_config_method, + NULL + }, + { "level", WPAS_DBUS_NEW_IFACE_P2P_PEER, "i", + wpas_dbus_getter_p2p_peer_level, + NULL + }, + { "devicecapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y", + wpas_dbus_getter_p2p_peer_device_capability, + NULL + }, + { "groupcapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y", + wpas_dbus_getter_p2p_peer_group_capability, + NULL + }, + { "SecondaryDeviceTypes", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay", + wpas_dbus_getter_p2p_peer_secondary_device_types, + NULL + }, + { "VendorExtension", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay", + wpas_dbus_getter_p2p_peer_vendor_extension, NULL }, { "IEs", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay", @@ -3109,10 +3142,37 @@ static const struct wpa_dbus_property_desc wpas_dbus_p2p_group_properties[] = { wpas_dbus_getter_p2p_group_members, NULL }, - { "Properties", - WPAS_DBUS_NEW_IFACE_P2P_GROUP, "a{sv}", - wpas_dbus_getter_p2p_group_properties, - wpas_dbus_setter_p2p_group_properties + { "Group", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "o", + wpas_dbus_getter_p2p_group, + NULL + }, + { "Role", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s", + wpas_dbus_getter_p2p_role, + NULL + }, + { "SSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay", + wpas_dbus_getter_p2p_group_ssid, + NULL + }, + { "BSSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay", + wpas_dbus_getter_p2p_group_bssid, + NULL + }, + { "Frequency", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "q", + wpas_dbus_getter_p2p_group_frequency, + NULL + }, + { "Passphrase", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s", + wpas_dbus_getter_p2p_group_passphrase, + NULL + }, + { "PSK", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay", + wpas_dbus_getter_p2p_group_psk, + NULL + }, + { "WPSVendorExtensions", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "aay", + wpas_dbus_getter_p2p_group_vendor_ext, + wpas_dbus_setter_p2p_group_vendor_ext }, { NULL, NULL, NULL, NULL, NULL } }; @@ -3234,10 +3294,6 @@ void wpas_dbus_unregister_p2p_group(struct wpa_supplicant *wpa_s, static const struct wpa_dbus_property_desc wpas_dbus_p2p_groupmember_properties[] = { - { "Properties", WPAS_DBUS_NEW_IFACE_P2P_GROUPMEMBER, "a{sv}", - wpas_dbus_getter_p2p_group_properties, - NULL - }, { NULL, NULL, NULL, NULL, NULL } }; diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c old mode 100644 new mode 100755 index 154a6d3..f29e128 --- a/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/wpa_supplicant/dbus/dbus_new_handlers.c @@ -25,6 +25,7 @@ #include "../wpa_supplicant_i.h" #include "../driver_i.h" #include "../notify.h" +#include "../wpas_glue.h" #include "../bss.h" #include "../scan.h" #include "../ctrl_iface.h" @@ -448,6 +449,76 @@ dbus_bool_t wpas_dbus_simple_array_property_getter(DBusMessageIter *iter, /** + * wpas_dbus_simple_array_array_property_getter - Get array array type property + * @iter: Pointer to incoming dbus message iterator + * @type: DBus type of property array elements (must be basic type) + * @array: pointer to array of elements to put into response message + * @array_len: length of above array + * @error: a pointer to an error to fill on failure + * Returns: TRUE if the request succeeded, FALSE if it failed + * + * Generic getter for array type properties. Array elements type is + * required to be basic. + */ +dbus_bool_t wpas_dbus_simple_array_array_property_getter(DBusMessageIter *iter, + const int type, + struct wpabuf **array, + size_t array_len, + DBusError *error) +{ + DBusMessageIter variant_iter, array_iter; + char type_str[] = "aa?"; + char inner_type_str[] = "a?"; + const char *sub_type_str; + size_t i; + + if (!dbus_type_is_basic(type)) { + dbus_set_error(error, DBUS_ERROR_FAILED, + "%s: given type is not basic", __func__); + return FALSE; + } + + sub_type_str = wpa_dbus_type_as_string(type); + type_str[2] = sub_type_str[0]; + inner_type_str[1] = sub_type_str[0]; + + if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, + type_str, &variant_iter)) { + dbus_set_error(error, DBUS_ERROR_FAILED, + "%s: failed to construct message 1", __func__); + return FALSE; + } + if (!dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY, + inner_type_str, &array_iter)) { + dbus_set_error(error, DBUS_ERROR_FAILED, + "%s: failed to construct message 2", __func__); + return FALSE; + } + + for (i = 0; i < array_len; i++) { + wpa_dbus_dict_bin_array_add_element(&array_iter, + wpabuf_head(array[i]), + wpabuf_len(array[i])); + + } + + if (!dbus_message_iter_close_container(&variant_iter, &array_iter)) { + dbus_set_error(error, DBUS_ERROR_FAILED, + "%s: failed to close message 2", __func__); + return FALSE; + } + + if (!dbus_message_iter_close_container(iter, &variant_iter)) { + dbus_set_error(error, DBUS_ERROR_FAILED, + "%s: failed to close message 1", __func__); + return FALSE; + } + + return TRUE; +} + + +/** * wpas_dbus_handler_create_interface - Request registration of a network iface * @message: Pointer to incoming dbus message * @global: %wpa_supplicant global data structure @@ -921,6 +992,16 @@ static int wpas_dbus_get_scan_ssids(DBusMessage *message, DBusMessageIter *var, dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len); + if (len > MAX_SSID_LEN) { + wpa_printf(MSG_DEBUG, + "wpas_dbus_handler_scan[dbus]: " + "SSID too long (len=%d max_len=%d)", + len, MAX_SSID_LEN); + *reply = wpas_dbus_error_invalid_args( + message, "Invalid SSID: too long"); + return -1; + } + if (len != 0) { ssid = os_malloc(len); if (ssid == NULL) { @@ -2224,6 +2305,54 @@ dbus_bool_t wpas_dbus_setter_ap_scan(DBusMessageIter *iter, DBusError *error, /** + * wpas_dbus_getter_fast_reauth - Control fast + * reauthentication (TLS session resumption) + * @iter: Pointer to incoming dbus message iter + * @error: Location to store error on failure + * @user_data: Function specific data + * Returns: TRUE on success, FALSE on failure + * + * Getter function for "FastReauth" property. + */ +dbus_bool_t wpas_dbus_getter_fast_reauth(DBusMessageIter *iter, + DBusError *error, + void *user_data) +{ + struct wpa_supplicant *wpa_s = user_data; + dbus_bool_t fast_reauth = wpa_s->conf->fast_reauth ? TRUE : FALSE; + + return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN, + &fast_reauth, error); +} + + +/** + * wpas_dbus_setter_fast_reauth - Control fast + * reauthentication (TLS session resumption) + * @iter: Pointer to incoming dbus message iter + * @error: Location to store error on failure + * @user_data: Function specific data + * Returns: TRUE on success, FALSE on failure + * + * Setter function for "FastReauth" property. + */ +dbus_bool_t wpas_dbus_setter_fast_reauth(DBusMessageIter *iter, + DBusError *error, + void *user_data) +{ + struct wpa_supplicant *wpa_s = user_data; + dbus_bool_t fast_reauth; + + if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN, + &fast_reauth)) + return FALSE; + + wpa_s->conf->fast_reauth = fast_reauth; + return TRUE; +} + + +/** * wpas_dbus_getter_bss_expire_age - Get BSS entry expiration age * @iter: Pointer to incoming dbus message iter * @error: Location to store error on failure @@ -2542,7 +2671,9 @@ dbus_bool_t wpas_dbus_getter_bridge_ifname(DBusMessageIter *iter, void *user_data) { struct wpa_supplicant *wpa_s = user_data; - const char *bridge_ifname = wpa_s->bridge_ifname; + const char *bridge_ifname; + + bridge_ifname = wpa_s->bridge_ifname ? wpa_s->bridge_ifname : ""; return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &bridge_ifname, error); } @@ -2862,13 +2993,15 @@ dbus_bool_t wpas_dbus_getter_bss_signal(DBusMessageIter *iter, { struct bss_handler_args *args = user_data; struct wpa_bss *res; + s16 level; res = get_bss_helper(args, error, __func__); if (!res) return FALSE; + level = (s16) res->level; return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT16, - &res->level, error); + &level, error); } @@ -2886,13 +3019,15 @@ dbus_bool_t wpas_dbus_getter_bss_frequency(DBusMessageIter *iter, { struct bss_handler_args *args = user_data; struct wpa_bss *res; + u16 freq; res = get_bss_helper(args, error, __func__); if (!res) return FALSE; + freq = (u16) res->freq; return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16, - &res->freq, error); + &freq, error); } diff --git a/wpa_supplicant/dbus/dbus_new_handlers.h b/wpa_supplicant/dbus/dbus_new_handlers.h index eb72abd..a6172fc 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.h +++ b/wpa_supplicant/dbus/dbus_new_handlers.h @@ -41,6 +41,12 @@ dbus_bool_t wpas_dbus_simple_array_property_getter(DBusMessageIter *iter, size_t array_len, DBusError *error); +dbus_bool_t wpas_dbus_simple_array_array_property_getter(DBusMessageIter *iter, + const int type, + struct wpabuf **array, + size_t array_len, + DBusError *error); + DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message, struct wpa_global *global); @@ -143,6 +149,14 @@ dbus_bool_t wpas_dbus_getter_ap_scan(DBusMessageIter *iter, DBusError *error, dbus_bool_t wpas_dbus_setter_ap_scan(DBusMessageIter *iter, DBusError *error, void *user_data); +dbus_bool_t wpas_dbus_getter_fast_reauth(DBusMessageIter *iter, + DBusError *error, + void *user_data); + +dbus_bool_t wpas_dbus_setter_fast_reauth(DBusMessageIter *iter, + DBusError *error, + void *user_data); + dbus_bool_t wpas_dbus_getter_bss_expire_age(DBusMessageIter *iter, DBusError *error, void *user_data); diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c index de0caad..aa05f58 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c +++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c @@ -131,7 +131,8 @@ DBusMessage * wpas_dbus_handler_p2p_find(DBusMessage *message, wpa_dbus_dict_entry_clear(&entry); } - wpas_p2p_find(wpa_s, timeout, type, num_req_dev_types, req_dev_types); + wpas_p2p_find(wpa_s, timeout, type, num_req_dev_types, req_dev_types, + NULL); os_free(req_dev_types); return reply; @@ -497,7 +498,7 @@ DBusMessage * wpas_dbus_handler_p2p_connect(DBusMessage *message, if (!peer_object_path || (wps_method == WPS_NOT_READY) || (parse_peer_object_path(peer_object_path, addr) < 0) || - (p2p_get_peer_info(wpa_s->global->p2p, addr, 0, NULL, 0) < 0)) + !p2p_peer_known(wpa_s->global->p2p, addr)) goto inv_args; /* @@ -603,8 +604,7 @@ DBusMessage * wpas_dbus_handler_p2p_invite(DBusMessage *message, if (!peer_object_path || (parse_peer_object_path(peer_object_path, peer_addr) < 0) || - (p2p_get_peer_info(wpa_s->global->p2p, - peer_addr, 0, NULL, 0) < 0)) { + !p2p_peer_known(wpa_s->global->p2p, peer_addr)) { goto err; } @@ -704,9 +704,9 @@ DBusMessage * wpas_dbus_handler_p2p_prov_disc_req(DBusMessage *message, * P2P Device property accessor methods. */ -dbus_bool_t wpas_dbus_getter_p2p_device_properties(DBusMessageIter *iter, - DBusError *error, - void *user_data) +dbus_bool_t wpas_dbus_getter_p2p_device_config(DBusMessageIter *iter, + DBusError *error, + void *user_data) { struct wpa_supplicant *wpa_s = user_data; DBusMessageIter variant_iter, dict_iter; @@ -782,7 +782,7 @@ dbus_bool_t wpas_dbus_getter_p2p_device_properties(DBusMessageIter *iter, goto err_no_mem; /* Persistent Reconnect */ - if (!wpa_dbus_dict_append_bool(&dict_iter, "PersistantReconnect", + if (!wpa_dbus_dict_append_bool(&dict_iter, "PersistentReconnect", wpa_s->conf->persistent_reconnect)) goto err_no_mem; @@ -839,9 +839,9 @@ err_no_mem: } -dbus_bool_t wpas_dbus_setter_p2p_device_properties(DBusMessageIter *iter, - DBusError *error, - void *user_data) +dbus_bool_t wpas_dbus_setter_p2p_device_config(DBusMessageIter *iter, + DBusError *error, + void *user_data) { struct wpa_supplicant *wpa_s = user_data; DBusMessageIter variant_iter, iter_dict; @@ -927,7 +927,7 @@ dbus_bool_t wpas_dbus_setter_p2p_device_properties(DBusMessageIter *iter, (entry.type == DBUS_TYPE_UINT32) && (entry.uint32_value <= 15)) wpa_s->conf->p2p_go_intent = entry.uint32_value; - else if ((os_strcmp(entry.key, "PersistantReconnect") == 0) && + else if ((os_strcmp(entry.key, "PersistentReconnect") == 0) && (entry.type == DBUS_TYPE_BOOLEAN)) wpa_s->conf->persistent_reconnect = entry.bool_value; else if ((os_strcmp(entry.key, "ListenRegClass") == 0) && @@ -1140,13 +1140,18 @@ dbus_bool_t wpas_dbus_getter_p2p_group(DBusMessageIter *iter, DBusError *error, void *user_data) { struct wpa_supplicant *wpa_s = user_data; + char path_buf[WPAS_DBUS_OBJECT_PATH_MAX]; + char *dbus_groupobj_path = path_buf; if (wpa_s->dbus_groupobj_path == NULL) - return FALSE; + os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX, + "/"); + else + os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX, + "%s", wpa_s->dbus_groupobj_path); return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH, - &wpa_s->dbus_groupobj_path, - error); + &dbus_groupobj_path, error); } @@ -1157,11 +1162,13 @@ dbus_bool_t wpas_dbus_getter_p2p_peergo(DBusMessageIter *iter, char go_peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path; if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_CLIENT) - return FALSE; + os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/"); + else + os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, + "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" + COMPACT_MACSTR, + wpa_s->dbus_new_path, MAC2STR(wpa_s->go_dev_addr)); - os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, - "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR, - wpa_s->dbus_new_path, MAC2STR(wpa_s->go_dev_addr)); path = go_peer_obj_path; return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH, &path, error); @@ -1172,14 +1179,13 @@ dbus_bool_t wpas_dbus_getter_p2p_peergo(DBusMessageIter *iter, * Peer object properties accessor methods */ -dbus_bool_t wpas_dbus_getter_p2p_peer_properties(DBusMessageIter *iter, - DBusError *error, void *user_data) +dbus_bool_t wpas_dbus_getter_p2p_peer_device_name(DBusMessageIter *iter, + DBusError *error, + void *user_data) { struct peer_handler_args *peer_args = user_data; - DBusMessageIter variant_iter, dict_iter; - const struct p2p_peer_info *info = NULL; - const struct wpabuf *vendor_extension[P2P_MAX_WPS_VENDOR_EXT]; - int i, num; + const struct p2p_peer_info *info; + char *tmp; if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error)) return FALSE; @@ -1188,68 +1194,264 @@ dbus_bool_t wpas_dbus_getter_p2p_peer_properties(DBusMessageIter *iter, info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, peer_args->p2p_device_addr, 0); if (info == NULL) { - dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer"); + dbus_set_error(error, DBUS_ERROR_FAILED, + "failed to find peer"); + return FALSE; + } + + tmp = os_strdup(info->device_name); + if (!tmp) { + dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); + return FALSE; + } + + if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp, + error)) { + dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); + os_free(tmp); + return FALSE; + } + + os_free(tmp); + return TRUE; +} + + +dbus_bool_t wpas_dbus_getter_p2p_peer_primary_device_type( + DBusMessageIter *iter, DBusError *error, void *user_data) +{ + struct peer_handler_args *peer_args = user_data; + const struct p2p_peer_info *info; + + info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, + peer_args->p2p_device_addr, 0); + if (info == NULL) { + dbus_set_error(error, DBUS_ERROR_FAILED, + "failed to find peer"); + return FALSE; + } + + if (!wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE, + (char *) + info->pri_dev_type, + WPS_DEV_TYPE_LEN, error)) { + dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); + return FALSE; + } + + return TRUE; +} + + +dbus_bool_t wpas_dbus_getter_p2p_peer_config_method(DBusMessageIter *iter, + DBusError *error, + void *user_data) +{ + struct peer_handler_args *peer_args = user_data; + const struct p2p_peer_info *info; + + info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, + peer_args->p2p_device_addr, 0); + if (info == NULL) { + dbus_set_error(error, DBUS_ERROR_FAILED, + "failed to find peer"); + return FALSE; + } + + if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16, + &info->config_methods, error)) { + dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); + return FALSE; + } + + return TRUE; +} + + +dbus_bool_t wpas_dbus_getter_p2p_peer_level(DBusMessageIter *iter, + DBusError *error, + void *user_data) +{ + struct peer_handler_args *peer_args = user_data; + const struct p2p_peer_info *info; + + info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, + peer_args->p2p_device_addr, 0); + if (info == NULL) { + dbus_set_error(error, DBUS_ERROR_FAILED, + "failed to find peer"); + return FALSE; + } + + if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32, + &info->level, error)) { + dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); + return FALSE; + } + + return TRUE; +} + + +dbus_bool_t wpas_dbus_getter_p2p_peer_device_capability(DBusMessageIter *iter, + DBusError *error, + void *user_data) +{ + struct peer_handler_args *peer_args = user_data; + const struct p2p_peer_info *info; + + info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, + peer_args->p2p_device_addr, 0); + if (info == NULL) { + dbus_set_error(error, DBUS_ERROR_FAILED, + "failed to find peer"); + return FALSE; + } + + if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BYTE, + &info->dev_capab, error)) { + dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); + return FALSE; + } + + return TRUE; +} + + +dbus_bool_t wpas_dbus_getter_p2p_peer_group_capability(DBusMessageIter *iter, + DBusError *error, + void *user_data) +{ + struct peer_handler_args *peer_args = user_data; + const struct p2p_peer_info *info; + + info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, + peer_args->p2p_device_addr, 0); + if (info == NULL) { + dbus_set_error(error, DBUS_ERROR_FAILED, + "failed to find peer"); + return FALSE; + } + + if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BYTE, + &info->group_capab, error)) { + dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); + return FALSE; + } + + return TRUE; +} + + +dbus_bool_t wpas_dbus_getter_p2p_peer_secondary_device_types( + DBusMessageIter *iter, DBusError *error, void *user_data) +{ + struct peer_handler_args *peer_args = user_data; + const struct p2p_peer_info *info; + DBusMessageIter variant_iter, array_iter; + + info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, + peer_args->p2p_device_addr, 0); + if (info == NULL) { + dbus_set_error(error, DBUS_ERROR_FAILED, + "failed to find peer"); return FALSE; } if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, - "a{sv}", &variant_iter) || - !wpa_dbus_dict_open_write(&variant_iter, &dict_iter)) - goto err_no_mem; + DBUS_TYPE_ARRAY_AS_STRING + DBUS_TYPE_ARRAY_AS_STRING + DBUS_TYPE_BYTE_AS_STRING, + &variant_iter)) { + dbus_set_error(error, DBUS_ERROR_FAILED, + "%s: failed to construct message 1", __func__); + return FALSE; + } - /* Fill out the dictionary */ - if (!wpa_dbus_dict_append_string(&dict_iter, "DeviceName", - info->device_name)) - goto err_no_mem; - if (!wpa_dbus_dict_append_byte_array(&dict_iter, "PrimaryDeviceType", - (char *)info->pri_dev_type, - WPS_DEV_TYPE_LEN)) - goto err_no_mem; - if (!wpa_dbus_dict_append_uint16(&dict_iter, "config_method", - info->config_methods)) - goto err_no_mem; - if (!wpa_dbus_dict_append_int32(&dict_iter, "level", - info->level)) - goto err_no_mem; - if (!wpa_dbus_dict_append_byte(&dict_iter, "devicecapability", - info->dev_capab)) - goto err_no_mem; - if (!wpa_dbus_dict_append_byte(&dict_iter, "groupcapability", - info->group_capab)) - goto err_no_mem; + if (!dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY, + DBUS_TYPE_ARRAY_AS_STRING + DBUS_TYPE_BYTE_AS_STRING, + &array_iter)) { + dbus_set_error(error, DBUS_ERROR_FAILED, + "%s: failed to construct message 2", __func__); + return FALSE; + } if (info->wps_sec_dev_type_list_len) { const u8 *sec_dev_type_list = info->wps_sec_dev_type_list; - int num_sec_dev_types = + int num_sec_device_types = info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN; - DBusMessageIter iter_secdev_dict_entry, iter_secdev_dict_val, - iter_secdev_dict_array; - - if (num_sec_dev_types) { - if (!wpa_dbus_dict_begin_array(&dict_iter, - "SecondaryDeviceTypes", - DBUS_TYPE_ARRAY_AS_STRING - DBUS_TYPE_BYTE_AS_STRING, - &iter_secdev_dict_entry, - &iter_secdev_dict_val, - &iter_secdev_dict_array)) - goto err_no_mem; - for (i = 0; i < num_sec_dev_types; i++) { - wpa_dbus_dict_bin_array_add_element( - &iter_secdev_dict_array, - sec_dev_type_list, - WPS_DEV_TYPE_LEN); - sec_dev_type_list += WPS_DEV_TYPE_LEN; + int i; + DBusMessageIter inner_array_iter; + + for (i = 0; i < num_sec_device_types; i++) { + if (!dbus_message_iter_open_container( + &array_iter, DBUS_TYPE_ARRAY, + DBUS_TYPE_BYTE_AS_STRING, + &inner_array_iter)) { + dbus_set_error(error, DBUS_ERROR_FAILED, + "%s: failed to construct " + "message 3 (%d)", + __func__, i); + return FALSE; + } + + if (!dbus_message_iter_append_fixed_array( + &inner_array_iter, DBUS_TYPE_BYTE, + &sec_dev_type_list, WPS_DEV_TYPE_LEN)) { + dbus_set_error(error, DBUS_ERROR_FAILED, + "%s: failed to construct " + "message 4 (%d)", + __func__, i); + return FALSE; + } + + if (!dbus_message_iter_close_container( + &array_iter, &inner_array_iter)) { + dbus_set_error(error, DBUS_ERROR_FAILED, + "%s: failed to construct " + "message 5 (%d)", + __func__, i); + return FALSE; } - if (!wpa_dbus_dict_end_array(&dict_iter, - &iter_secdev_dict_entry, - &iter_secdev_dict_val, - &iter_secdev_dict_array)) - goto err_no_mem; + sec_dev_type_list += WPS_DEV_TYPE_LEN; } } + if (!dbus_message_iter_close_container(&variant_iter, &array_iter)) { + dbus_set_error(error, DBUS_ERROR_FAILED, + "%s: failed to construct message 6", __func__); + return FALSE; + } + + if (!dbus_message_iter_close_container(iter, &variant_iter)) { + dbus_set_error(error, DBUS_ERROR_FAILED, + "%s: failed to construct message 7", __func__); + return FALSE; + } + + return TRUE; +} + + +dbus_bool_t wpas_dbus_getter_p2p_peer_vendor_extension(DBusMessageIter *iter, + DBusError *error, + void *user_data) +{ + struct wpabuf *vendor_extension[P2P_MAX_WPS_VENDOR_EXT]; + int i, num; + struct peer_handler_args *peer_args = user_data; + const struct p2p_peer_info *info; + + info = p2p_get_peer_found(peer_args->wpa_s->global->p2p, + peer_args->p2p_device_addr, 0); + if (info == NULL) { + dbus_set_error(error, DBUS_ERROR_FAILED, + "failed to find peer"); + return FALSE; + } + /* Add WPS vendor extensions attribute */ for (i = 0, num = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) { if (info->wps_vendor_ext[i] == NULL) @@ -1258,29 +1460,24 @@ dbus_bool_t wpas_dbus_getter_p2p_peer_properties(DBusMessageIter *iter, num++; } - if (!wpa_dbus_dict_append_wpabuf_array(&dict_iter, "VendorExtension", - vendor_extension, num)) - goto err_no_mem; - - if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) || - !dbus_message_iter_close_container(iter, &variant_iter)) - goto err_no_mem; + if (!wpas_dbus_simple_array_array_property_getter(iter, DBUS_TYPE_BYTE, + vendor_extension, + num, error)) + return FALSE; return TRUE; - -err_no_mem: - dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); - return FALSE; } dbus_bool_t wpas_dbus_getter_p2p_peer_ies(DBusMessageIter *iter, DBusError *error, void *user_data) { + dbus_bool_t success; /* struct peer_handler_args *peer_args = user_data; */ - dbus_set_error_const(error, DBUS_ERROR_FAILED, "not implemented"); - return FALSE; + success = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE, + NULL, 0, error); + return success; } @@ -1608,9 +1805,11 @@ dbus_bool_t wpas_dbus_getter_p2p_group_members(DBusMessageIter *iter, const u8 *addr; dbus_bool_t success = FALSE; - /* Ensure we are a GO */ - if (wpa_s->wpa_state != WPA_COMPLETED) - return FALSE; + /* Verify correct role for this property */ + if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_GO) { + return wpas_dbus_simple_array_property_getter( + iter, DBUS_TYPE_OBJECT_PATH, NULL, 0, error); + } ssid = wpa_s->conf->ssid; /* At present WPAS P2P_GO mode only applicable for p2p_go */ @@ -1658,53 +1857,145 @@ out_of_memory: } -dbus_bool_t wpas_dbus_getter_p2p_group_properties(DBusMessageIter *iter, +dbus_bool_t wpas_dbus_getter_p2p_group_ssid(DBusMessageIter *iter, + DBusError *error, void *user_data) +{ + struct wpa_supplicant *wpa_s = user_data; + if (wpa_s->current_ssid == NULL) + return FALSE; + return wpas_dbus_simple_array_property_getter( + iter, DBUS_TYPE_BYTE, wpa_s->current_ssid->ssid, + wpa_s->current_ssid->ssid_len, error); +} + + +dbus_bool_t wpas_dbus_getter_p2p_group_bssid(DBusMessageIter *iter, + DBusError *error, + void *user_data) +{ + struct wpa_supplicant *wpa_s = user_data; + u8 role = wpas_get_p2p_role(wpa_s); + u8 *p_bssid; + + if (role == WPAS_P2P_ROLE_CLIENT) { + if (wpa_s->current_ssid == NULL) + return FALSE; + p_bssid = wpa_s->current_ssid->bssid; + } else { + if (wpa_s->ap_iface == NULL) + return FALSE; + p_bssid = wpa_s->ap_iface->bss[0]->own_addr; + } + + return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE, + p_bssid, ETH_ALEN, + error); +} + + +dbus_bool_t wpas_dbus_getter_p2p_group_frequency(DBusMessageIter *iter, + DBusError *error, + void *user_data) +{ + struct wpa_supplicant *wpa_s = user_data; + u16 op_freq; + u8 role = wpas_get_p2p_role(wpa_s); + + if (role == WPAS_P2P_ROLE_CLIENT) { + if (wpa_s->go_params == NULL) + return FALSE; + op_freq = wpa_s->go_params->freq; + } else { + if (wpa_s->ap_iface == NULL) + return FALSE; + op_freq = wpa_s->ap_iface->freq; + } + + return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16, + &op_freq, error); +} + + +dbus_bool_t wpas_dbus_getter_p2p_group_passphrase(DBusMessageIter *iter, DBusError *error, void *user_data) { struct wpa_supplicant *wpa_s = user_data; - DBusMessageIter variant_iter, dict_iter; - struct hostapd_data *hapd = wpa_s->ap_iface->bss[0]; - const struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS]; - int num_vendor_ext = 0; - int i; + u8 role = wpas_get_p2p_role(wpa_s); + char *p_pass = NULL; - if (!hapd) { - dbus_set_error_const(error, DBUS_ERROR_FAILED, - "internal error"); - return FALSE; - } + /* Verify correct role for this property */ + if (role == WPAS_P2P_ROLE_GO) { + if (wpa_s->current_ssid == NULL) + return FALSE; + p_pass = wpa_s->current_ssid->passphrase; + } else + p_pass = ""; - if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, - "a{sv}", &variant_iter) || - !wpa_dbus_dict_open_write(&variant_iter, &dict_iter)) - goto err_no_mem; + return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, + &p_pass, error); - /* Parse WPS Vendor Extensions sent in Beacon/Probe Response */ - for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) { - if (hapd->conf->wps_vendor_ext[i] == NULL) - continue; - vendor_ext[num_vendor_ext++] = hapd->conf->wps_vendor_ext[i]; +} + + +dbus_bool_t wpas_dbus_getter_p2p_group_psk(DBusMessageIter *iter, + DBusError *error, void *user_data) +{ + struct wpa_supplicant *wpa_s = user_data; + u8 role = wpas_get_p2p_role(wpa_s); + u8 *p_psk = NULL; + u8 psk_len = 0; + + /* Verify correct role for this property */ + if (role == WPAS_P2P_ROLE_CLIENT) { + if (wpa_s->current_ssid == NULL) + return FALSE; + p_psk = wpa_s->current_ssid->psk; + psk_len = 32; } - if (!wpa_dbus_dict_append_wpabuf_array(&dict_iter, - "WPSVendorExtensions", - vendor_ext, num_vendor_ext)) - goto err_no_mem; + return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE, + &p_psk, psk_len, error); +} - if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) || - !dbus_message_iter_close_container(iter, &variant_iter)) - goto err_no_mem; - return TRUE; +dbus_bool_t wpas_dbus_getter_p2p_group_vendor_ext(DBusMessageIter *iter, + DBusError *error, + void *user_data) +{ + struct wpa_supplicant *wpa_s = user_data; + struct hostapd_data *hapd; + struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS]; + int num_vendor_ext = 0; + int i; -err_no_mem: - dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); - return FALSE; + /* Verify correct role for this property */ + if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO) { + if (wpa_s->ap_iface == NULL) + return FALSE; + hapd = wpa_s->ap_iface->bss[0]; + + /* Parse WPS Vendor Extensions sent in Beacon/Probe Response */ + for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) { + if (hapd->conf->wps_vendor_ext[i] == NULL) + vendor_ext[i] = NULL; + else { + vendor_ext[num_vendor_ext++] = + hapd->conf->wps_vendor_ext[i]; + } + } + } + + /* Return vendor extensions or no data */ + return wpas_dbus_simple_array_array_property_getter(iter, + DBUS_TYPE_BYTE, + vendor_ext, + num_vendor_ext, + error); } -dbus_bool_t wpas_dbus_setter_p2p_group_properties(DBusMessageIter *iter, +dbus_bool_t wpas_dbus_setter_p2p_group_vendor_ext(DBusMessageIter *iter, DBusError *error, void *user_data) { @@ -1712,13 +2003,13 @@ dbus_bool_t wpas_dbus_setter_p2p_group_properties(DBusMessageIter *iter, DBusMessageIter variant_iter, iter_dict; struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING }; unsigned int i; - struct hostapd_data *hapd = wpa_s->ap_iface->bss[0]; + struct hostapd_data *hapd = NULL; - if (!hapd) { - dbus_set_error_const(error, DBUS_ERROR_FAILED, - "internal error"); + if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO && + wpa_s->ap_iface != NULL) + hapd = wpa_s->ap_iface->bss[0]; + else return FALSE; - } dbus_message_iter_recurse(iter, &variant_iter); if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error)) @@ -1974,7 +2265,7 @@ DBusMessage * wpas_dbus_handler_p2p_service_sd_req( struct wpabuf *tlv = NULL; u8 version = 0; u64 ref = 0; - u8 addr[ETH_ALEN]; + u8 addr_buf[ETH_ALEN], *addr; dbus_message_iter_init(message, &iter); @@ -2011,20 +2302,27 @@ DBusMessage * wpas_dbus_handler_p2p_service_sd_req( wpa_dbus_dict_entry_clear(&entry); } - if (!peer_object_path || - (parse_peer_object_path(peer_object_path, addr) < 0) || - (p2p_get_peer_info(wpa_s->global->p2p, addr, 0, NULL, 0) < 0)) - goto error; + if (!peer_object_path) { + addr = NULL; + } else { + if (parse_peer_object_path(peer_object_path, addr_buf) < 0 || + !p2p_peer_known(wpa_s->global->p2p, addr_buf)) + goto error; + + addr = addr_buf; + } if (upnp == 1) { if (version <= 0 || service == NULL) goto error; - ref = wpas_p2p_sd_request_upnp(wpa_s, addr, version, service); + ref = (unsigned long) wpas_p2p_sd_request_upnp(wpa_s, addr, + version, + service); } else { if (tlv == NULL) goto error; - ref = wpas_p2p_sd_request(wpa_s, addr, tlv); + ref = (unsigned long)wpas_p2p_sd_request(wpa_s, addr, tlv); wpabuf_free(tlv); } @@ -2094,7 +2392,7 @@ DBusMessage * wpas_dbus_handler_p2p_service_sd_res( } if (!peer_object_path || (parse_peer_object_path(peer_object_path, addr) < 0) || - (p2p_get_peer_info(wpa_s->global->p2p, addr, 0, NULL, 0) < 0)) + !p2p_peer_known(wpa_s->global->p2p, addr)) goto error; if (tlv == NULL) @@ -2125,7 +2423,7 @@ DBusMessage * wpas_dbus_handler_p2p_service_sd_cancel_req( if (req == 0) goto error; - if (!wpas_p2p_sd_cancel_request(wpa_s, req)) + if (!wpas_p2p_sd_cancel_request(wpa_s, (void *)(unsigned long) req)) goto error; return NULL; diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.h b/wpa_supplicant/dbus/dbus_new_handlers_p2p.h index 206e904..241dd75 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.h +++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.h @@ -94,13 +94,13 @@ DBusMessage *wpas_dbus_handler_p2p_serv_disc_external( /* * P2P Device property accessor methods. */ -dbus_bool_t wpas_dbus_setter_p2p_device_properties(DBusMessageIter *iter, - DBusError *error, - void *user_data); +dbus_bool_t wpas_dbus_setter_p2p_device_config(DBusMessageIter *iter, + DBusError *error, + void *user_data); -dbus_bool_t wpas_dbus_getter_p2p_device_properties(DBusMessageIter *iter, - DBusError *error, - void *user_data); +dbus_bool_t wpas_dbus_getter_p2p_device_config(DBusMessageIter *iter, + DBusError *error, + void *user_data); dbus_bool_t wpas_dbus_getter_p2p_peers(DBusMessageIter *iter, DBusError *error, void *user_data); @@ -118,9 +118,36 @@ dbus_bool_t wpas_dbus_getter_p2p_peergo(DBusMessageIter *iter, /* * P2P Peer properties. */ -dbus_bool_t wpas_dbus_getter_p2p_peer_properties(DBusMessageIter *iter, - DBusError *error, - void *user_data); + +dbus_bool_t wpas_dbus_getter_p2p_peer_device_name(DBusMessageIter *iter, + DBusError *error, + void *user_data); + +dbus_bool_t wpas_dbus_getter_p2p_peer_primary_device_type( + DBusMessageIter *iter, DBusError *error, void *user_data); + +dbus_bool_t wpas_dbus_getter_p2p_peer_config_method(DBusMessageIter *iter, + DBusError *error, + void *user_data); + +dbus_bool_t wpas_dbus_getter_p2p_peer_level(DBusMessageIter *iter, + DBusError *error, + void *user_data); + +dbus_bool_t wpas_dbus_getter_p2p_peer_device_capability(DBusMessageIter *iter, + DBusError *error, + void *user_data); + +dbus_bool_t wpas_dbus_getter_p2p_peer_group_capability(DBusMessageIter *iter, + DBusError *error, + void *user_data); + +dbus_bool_t wpas_dbus_getter_p2p_peer_secondary_device_types( + DBusMessageIter *iter, DBusError *error, void *user_data); + +dbus_bool_t wpas_dbus_getter_p2p_peer_vendor_extension(DBusMessageIter *iter, + DBusError *error, + void *user_data); dbus_bool_t wpas_dbus_getter_p2p_peer_ies(DBusMessageIter *iter, DBusError *error, @@ -134,11 +161,31 @@ dbus_bool_t wpas_dbus_getter_p2p_group_members(DBusMessageIter *iter, DBusError *error, void *user_data); -dbus_bool_t wpas_dbus_getter_p2p_group_properties(DBusMessageIter *iter, +dbus_bool_t wpas_dbus_getter_p2p_group_ssid(DBusMessageIter *iter, + DBusError *error, + void *user_data); + +dbus_bool_t wpas_dbus_getter_p2p_group_bssid(DBusMessageIter *iter, + DBusError *error, + void *user_data); + +dbus_bool_t wpas_dbus_getter_p2p_group_frequency(DBusMessageIter *iter, + DBusError *error, + void *user_data); + +dbus_bool_t wpas_dbus_getter_p2p_group_passphrase(DBusMessageIter *iter, + DBusError *error, + void *user_data); + +dbus_bool_t wpas_dbus_getter_p2p_group_psk(DBusMessageIter *iter, + DBusError *error, + void *user_data); + +dbus_bool_t wpas_dbus_getter_p2p_group_vendor_ext(DBusMessageIter *iter, DBusError *error, void *user_data); -dbus_bool_t wpas_dbus_setter_p2p_group_properties(DBusMessageIter *iter, +dbus_bool_t wpas_dbus_setter_p2p_group_vendor_ext(DBusMessageIter *iter, DBusError *error, void *user_data); diff --git a/wpa_supplicant/dbus/dbus_new_introspect.c b/wpa_supplicant/dbus/dbus_new_introspect.c index fb29f20..d443269 100644 --- a/wpa_supplicant/dbus/dbus_new_introspect.c +++ b/wpa_supplicant/dbus/dbus_new_introspect.c @@ -164,6 +164,12 @@ static void add_interfaces(struct dl_list *list, struct wpabuf *xml) if (wpabuf_len(iface->xml) + 20 < wpabuf_tailroom(xml)) { wpabuf_put_buf(xml, iface->xml); wpabuf_put_str(xml, ""); + } else { + wpa_printf(MSG_DEBUG, "dbus: Not enough room for " + "add_interfaces inspect data: tailroom %u, " + "add %u", + (unsigned int) wpabuf_tailroom(xml), + (unsigned int) wpabuf_len(iface->xml)); } dl_list_del(&iface->list); wpabuf_free(iface->xml); @@ -251,7 +257,7 @@ DBusMessage * wpa_dbus_introspect(DBusMessage *message, DBusMessage *reply; struct wpabuf *xml; - xml = wpabuf_alloc(8000); + xml = wpabuf_alloc(10000); if (xml == NULL) return NULL; diff --git a/wpa_supplicant/dbus/dbus_old.c b/wpa_supplicant/dbus/dbus_old.c index 71ab61e..d255e14 100644 --- a/wpa_supplicant/dbus/dbus_old.c +++ b/wpa_supplicant/dbus/dbus_old.c @@ -23,6 +23,7 @@ #include "../bss.h" #include "dbus_old.h" #include "dbus_old_handlers.h" +#include "dbus_common.h" #include "dbus_common_i.h" diff --git a/wpa_supplicant/dbus/fi.epitest.hostap.WPASupplicant.service.in b/wpa_supplicant/dbus/fi.epitest.hostap.WPASupplicant.service.in index 0e4e57f..a75918f 100644 --- a/wpa_supplicant/dbus/fi.epitest.hostap.WPASupplicant.service.in +++ b/wpa_supplicant/dbus/fi.epitest.hostap.WPASupplicant.service.in @@ -1,4 +1,5 @@ [D-BUS Service] Name=fi.epitest.hostap.WPASupplicant +Exec=@BINDIR@/wpa_supplicant -u User=root SystemdService=wpa_supplicant.service diff --git a/wpa_supplicant/dbus/fi.w1.wpa_supplicant1.service.in b/wpa_supplicant/dbus/fi.w1.wpa_supplicant1.service.in index 078e713..d97ff39 100644 --- a/wpa_supplicant/dbus/fi.w1.wpa_supplicant1.service.in +++ b/wpa_supplicant/dbus/fi.w1.wpa_supplicant1.service.in @@ -1,4 +1,5 @@ [D-BUS Service] Name=fi.w1.wpa_supplicant1 +Exec=@BINDIR@/wpa_supplicant -u User=root SystemdService=wpa_supplicant.service diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig index cff25d6..0476bc3 100644 --- a/wpa_supplicant/defconfig +++ b/wpa_supplicant/defconfig @@ -165,6 +165,9 @@ CONFIG_EAP_OTP=y # EAP-PSK (experimental; this is _not_ needed for WPA-PSK) #CONFIG_EAP_PSK=y +# EAP-pwd (secure authentication using only a password) +#CONFIG_EAP_PWD=y + # EAP-PAX #CONFIG_EAP_PAX=y @@ -332,13 +335,6 @@ CONFIG_PEERKEY=y # sent prior to negotiating which version will be used) #CONFIG_TLSV11=y -# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.2) -# can be enabled to enable use of stronger crypto algorithms. It should be -# noted that some existing TLS v1.0 -based implementation may not be compatible -# with TLS v1.2 message (ClientHello is sent prior to negotiating which version -# will be used) -#CONFIG_TLSV12=y - # If CONFIG_TLS=internal is used, additional library and include paths are # needed for LibTomMath. Alternatively, an integrated, minimal version of # LibTomMath can be used. See beginning of libtommath.c for details on benefits @@ -415,7 +411,7 @@ CONFIG_PEERKEY=y # This tracks use of memory allocations and other registrations and reports # incorrect use with a backtrace of call (or allocation) location. #CONFIG_WPA_TRACE=y -# For BSD, comment out these. +# For BSD, uncomment these. #LIBS += -lexecinfo #LIBS_p += -lexecinfo #LIBS_c += -lexecinfo @@ -424,7 +420,7 @@ CONFIG_PEERKEY=y # This enables use of libbfd to get more detailed symbols for the backtraces # generated by CONFIG_WPA_TRACE=y. #CONFIG_WPA_TRACE_BFD=y -# For BSD, comment out these. +# For BSD, uncomment these. #LIBS += -lbfd -liberty -lz #LIBS_p += -lbfd -liberty -lz #LIBS_c += -lbfd -liberty -lz diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h index d61b3fd..9828aff 100644 --- a/wpa_supplicant/driver_i.h +++ b/wpa_supplicant/driver_i.h @@ -262,11 +262,11 @@ static inline int wpa_drv_set_country(struct wpa_supplicant *wpa_s, } static inline int wpa_drv_send_mlme(struct wpa_supplicant *wpa_s, - const u8 *data, size_t data_len, int noack) + const u8 *data, size_t data_len) { if (wpa_s->driver->send_mlme) return wpa_s->driver->send_mlme(wpa_s->drv_priv, - data, data_len, noack); + data, data_len); return -1; } @@ -433,6 +433,13 @@ static inline int wpa_drv_deinit_ap(struct wpa_supplicant *wpa_s) return 0; } +static inline int wpa_drv_deinit_p2p_cli(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->driver->deinit_p2p_cli) + return wpa_s->driver->deinit_p2p_cli(wpa_s->drv_priv); + return 0; +} + static inline void wpa_drv_suspend(struct wpa_supplicant *wpa_s) { if (wpa_s->driver->suspend) diff --git a/wpa_supplicant/eap_register.c b/wpa_supplicant/eap_register.c index b3faaa1..e5f43aa 100644 --- a/wpa_supplicant/eap_register.c +++ b/wpa_supplicant/eap_register.c @@ -17,7 +17,6 @@ #include "common.h" #include "eap_peer/eap_methods.h" #include "eap_server/eap_methods.h" -#include "wpa_supplicant_i.h" /** diff --git a/wpa_supplicant/eapol_test.c b/wpa_supplicant/eapol_test.c index 76f7527..024903c 100644 --- a/wpa_supplicant/eapol_test.c +++ b/wpa_supplicant/eapol_test.c @@ -284,7 +284,9 @@ static void ieee802_1x_encapsulate_radius(struct eapol_test_data *e, } } - radius_client_send(e->radius, msg, RADIUS_AUTH, e->wpa_s->own_addr); + if (radius_client_send(e->radius, msg, RADIUS_AUTH, e->wpa_s->own_addr) + < 0) + goto fail; return; fail: diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index bd3a2bc..7b289ca 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -70,7 +70,11 @@ static int wpa_supplicant_select_config(struct wpa_supplicant *wpa_s) wpa_dbg(wpa_s, MSG_DEBUG, "Network configuration found for the " "current AP"); - if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) { + if (ssid->key_mgmt & (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_IEEE8021X | + WPA_KEY_MGMT_WPA_NONE | + WPA_KEY_MGMT_FT_PSK | WPA_KEY_MGMT_FT_IEEE8021X | + WPA_KEY_MGMT_PSK_SHA256 | + WPA_KEY_MGMT_IEEE8021X_SHA256)) { u8 wpa_ie[80]; size_t wpa_ie_len = sizeof(wpa_ie); wpa_supplicant_set_suites(wpa_s, NULL, ssid, @@ -125,6 +129,9 @@ void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s) bssid_changed = !is_zero_ether_addr(wpa_s->bssid); os_memset(wpa_s->bssid, 0, ETH_ALEN); os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); +#ifdef CONFIG_P2P + os_memset(wpa_s->go_dev_addr, 0, ETH_ALEN); +#endif /* CONFIG_P2P */ wpa_s->current_bss = NULL; wpa_s->assoc_freq = 0; #ifdef CONFIG_IEEE80211R @@ -1554,13 +1561,6 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, } -static int disconnect_reason_recoverable(u16 reason_code) -{ - return reason_code == WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY || - reason_code == WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA || - reason_code == WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA; -} - /* * Mar, 16th 2012. TIZEN * A supplicant tries to scan for specific access points after coming a disassoc event from a driver @@ -1602,8 +1602,6 @@ static void wpa_supplicant_event_disassoc(struct wpa_supplicant *wpa_s, const u8 *bssid; int authenticating; u8 prev_pending_bssid[ETH_ALEN]; - struct wpa_bss *fast_reconnect = NULL; - struct wpa_ssid *fast_reconnect_ssid = NULL; authenticating = wpa_s->wpa_state == WPA_AUTHENTICATING; os_memcpy(prev_pending_bssid, wpa_s->pending_bssid, ETH_ALEN); @@ -1626,30 +1624,14 @@ static void wpa_supplicant_event_disassoc(struct wpa_supplicant *wpa_s, } if (!wpa_s->auto_reconnect_disabled || wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) { - wpa_dbg(wpa_s, MSG_DEBUG, "Auto connect enabled: try to " - "reconnect (wps=%d wpa_state=%d)", - wpa_s->key_mgmt == WPA_KEY_MGMT_WPS, - wpa_s->wpa_state); - if (wpa_s->wpa_state == WPA_COMPLETED && - wpa_s->current_ssid && - wpa_s->current_ssid->mode == WPAS_MODE_INFRA && - disconnect_reason_recoverable(reason_code)) { - /* - * It looks like the AP has dropped association with - * us, but could allow us to get back in. Try to - * reconnect to the same BSS without full scan to save - * time for some common cases. - */ - fast_reconnect = wpa_s->current_bss; - fast_reconnect_ssid = wpa_s->current_ssid; - } else if (wpa_s->wpa_state >= WPA_ASSOCIATING) + wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Auto connect enabled: try to " + "reconnect (wps=%d)", + wpa_s->key_mgmt == WPA_KEY_MGMT_WPS); + if (wpa_s->wpa_state >= WPA_ASSOCIATING) wpa_supplicant_req_scan(wpa_s, 0, 100000); - else - wpa_dbg(wpa_s, MSG_DEBUG, "Do not request new " - "immediate scan"); } else { - wpa_dbg(wpa_s, MSG_DEBUG, "Auto connect disabled: do not " - "try to re-connect"); + wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Auto connect disabled: do not " + "try to re-connect"); wpa_s->reassociate = 0; wpa_s->disconnected = 1; /* @@ -1674,8 +1656,7 @@ static void wpa_supplicant_event_disassoc(struct wpa_supplicant *wpa_s, bssid = wpa_s->bssid; if (is_zero_ether_addr(bssid)) bssid = wpa_s->pending_bssid; - if (wpa_s->wpa_state >= WPA_AUTHENTICATING) - wpas_connection_failed(wpa_s, bssid); + wpas_connection_failed(wpa_s, bssid); wpa_sm_notify_disassoc(wpa_s->wpa); wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid=" MACSTR " reason=%d", @@ -1689,17 +1670,6 @@ static void wpa_supplicant_event_disassoc(struct wpa_supplicant *wpa_s, if (authenticating && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)) sme_disassoc_while_authenticating(wpa_s, prev_pending_bssid); - - if (fast_reconnect) { -#ifndef CONFIG_NO_SCAN_PROCESSING - wpa_dbg(wpa_s, MSG_DEBUG, "Try to reconnect to the same BSS"); - if (wpa_supplicant_connect(wpa_s, fast_reconnect, - fast_reconnect_ssid) < 0) { - /* Recover through full scan */ - wpa_supplicant_req_scan(wpa_s, 0, 100000); - } -#endif /* CONFIG_NO_SCAN_PROCESSING */ - } } @@ -1839,11 +1809,13 @@ wpa_supplicant_event_interface_status(struct wpa_supplicant *wpa_s, wpa_msg(wpa_s, MSG_INFO, "Failed to initialize the " "driver after interface was added"); } + wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); break; case EVENT_INTERFACE_REMOVED: wpa_dbg(wpa_s, MSG_DEBUG, "Configured interface was removed"); wpa_s->interface_removed = 1; wpa_supplicant_mark_disassoc(wpa_s); + wpa_supplicant_set_state(wpa_s, WPA_INTERFACE_DISABLED); l2_packet_deinit(wpa_s->l2); wpa_s->l2 = NULL; #ifdef CONFIG_IBSS_RSN @@ -2070,25 +2042,8 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, return; } -#ifndef CONFIG_NO_STDOUT_DEBUG -{ - int level = MSG_DEBUG; - - if (event == EVENT_RX_MGMT && data && data->rx_mgmt.frame && - data->rx_mgmt.frame_len >= 24) { - const struct ieee80211_hdr *hdr; - u16 fc; - hdr = (const struct ieee80211_hdr *) data->rx_mgmt.frame; - fc = le_to_host16(hdr->frame_control); - if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && - WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON) - level = MSG_EXCESSIVE; - } - - wpa_dbg(wpa_s, level, "Event %s (%d) received", + wpa_dbg(wpa_s, MSG_DEBUG, "Event %s (%d) received", event_to_string(event), event); -} -#endif /* CONFIG_NO_STDOUT_DEBUG */ switch (event) { case EVENT_AUTH: @@ -2099,7 +2054,6 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, break; case EVENT_DISASSOC: wpa_dbg(wpa_s, MSG_DEBUG, "Disassociation notification"); - if (data) { wpa_dbg(wpa_s, MSG_DEBUG, " * reason %u", data->disassoc_info.reason_code); @@ -2113,6 +2067,11 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, data->disassoc_info.addr); break; } + if (wpa_s->ap_iface) { + wpa_dbg(wpa_s, MSG_DEBUG, "Ignore disassoc event in " + "AP mode"); + break; + } #endif /* CONFIG_AP */ if (data) { reason_code = data->disassoc_info.reason_code; @@ -2162,6 +2121,11 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, data->deauth_info.addr); break; } + if (wpa_s->ap_iface) { + wpa_dbg(wpa_s, MSG_DEBUG, "Ignore deauth event in " + "AP mode"); + break; + } #endif /* CONFIG_AP */ wpa_supplicant_event_disassoc(wpa_s, reason_code); break; @@ -2283,12 +2247,6 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, #endif /* CONFIG_AP */ break; #ifdef CONFIG_AP - case EVENT_EAPOL_TX_STATUS: - ap_eapol_tx_status(wpa_s, data->eapol_tx_status.dst, - data->eapol_tx_status.data, - data->eapol_tx_status.data_len, - data->eapol_tx_status.ack); - break; case EVENT_DRIVER_CLIENT_POLL_OK: ap_client_poll_ok(wpa_s, data->client_poll.addr); break; @@ -2528,6 +2486,11 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, case EVENT_CHANNEL_LIST_CHANGED: if (wpa_s->drv_priv == NULL) break; /* Ignore event during drv initialization */ + + free_hw_features(wpa_s); + wpa_s->hw.modes = wpa_drv_get_hw_feature_data( + wpa_s, &wpa_s->hw.num_modes, &wpa_s->hw.flags); + #ifdef CONFIG_P2P wpas_p2p_update_channel_list(wpa_s); #endif /* CONFIG_P2P */ diff --git a/wpa_supplicant/examples/wpas-dbus-new-signals.py b/wpa_supplicant/examples/wpas-dbus-new-signals.py index b040e0a..d90ef18 100755 --- a/wpa_supplicant/examples/wpas-dbus-new-signals.py +++ b/wpa_supplicant/examples/wpas-dbus-new-signals.py @@ -59,12 +59,12 @@ def showBss(bss): dbus_interface=dbus.PROPERTIES_IFACE) ssid = byte_array_to_string(val) - val = net_obj.Get(WPAS_DBUS_BSS_INTERFACE, 'WPAIE', + val = net_obj.Get(WPAS_DBUS_BSS_INTERFACE, 'WPA', dbus_interface=dbus.PROPERTIES_IFACE) wpa = "no" if val != None: wpa = "yes" - val = net_obj.Get(WPAS_DBUS_BSS_INTERFACE, 'RSNIE', + val = net_obj.Get(WPAS_DBUS_BSS_INTERFACE, 'RSN', dbus_interface=dbus.PROPERTIES_IFACE) wpa2 = "no" if val != None: diff --git a/wpa_supplicant/examples/wps-ap-cli b/wpa_supplicant/examples/wps-ap-cli deleted file mode 100755 index 7c6b0aa..0000000 --- a/wpa_supplicant/examples/wps-ap-cli +++ /dev/null @@ -1,78 +0,0 @@ -#!/bin/sh - -CLI=wpa_cli - -pbc() -{ - echo "Starting PBC mode" - echo "Push button on the station within two minutes" - if ! $CLI wps_pbc | grep -q OK; then - echo "Failed to enable PBC mode" - fi -} - -enter_pin() -{ - echo "Enter a PIN from a station to be enrolled to the network." - read -p "Enrollee PIN: " pin - cpin=`$CLI wps_check_pin "$pin" | tail -1` - if [ "$cpin" = "FAIL-CHECKSUM" ]; then - echo "Checksum digit is not valid" - read -p "Do you want to use this PIN (y/n)? " resp - case "$resp" in - y*) - cpin=`echo "$pin" | sed "s/[^1234567890]//g"` - ;; - *) - return 1 - ;; - esac - fi - if [ "$cpin" = "FAIL" ]; then - echo "Invalid PIN: $pin" - return 1 - fi - echo "Enabling Enrollee PIN: $cpin" - $CLI wps_pin any "$cpin" -} - -show_config() -{ - $CLI status wps -} - -main_menu() -{ - echo "WPS AP" - echo "------" - echo "1: Push button (activate PBC)" - echo "2: Enter Enrollee PIN" - echo "3: Show current configuration" - echo "0: Exit wps-ap-cli" - - read -p "Command: " cmd - - case "$cmd" in - 1) - pbc - ;; - 2) - enter_pin - ;; - 3) - show_config - ;; - 0) - exit 0 - ;; - *) - echo "Unknown command: $cmd" - ;; - esac - - echo - main_menu -} - - -main_menu diff --git a/wpa_supplicant/ibss_rsn.c b/wpa_supplicant/ibss_rsn.c index d4fa39d..fc1a586 100644 --- a/wpa_supplicant/ibss_rsn.c +++ b/wpa_supplicant/ibss_rsn.c @@ -168,8 +168,8 @@ static void supp_deauthenticate(void * ctx, int reason_code) } -static int ibss_rsn_supp_init(struct ibss_rsn_peer *peer, const u8 *own_addr, - const u8 *psk) +int ibss_rsn_supp_init(struct ibss_rsn_peer *peer, const u8 *own_addr, + const u8 *psk) { struct wpa_sm_ctx *ctx = os_zalloc(sizeof(*ctx)); if (ctx == NULL) diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c index d42aa40..cd074a3 100644 --- a/wpa_supplicant/interworking.c +++ b/wpa_supplicant/interworking.c @@ -422,8 +422,8 @@ static int nai_realm_cred_username(struct nai_realm_eap *eap) } -static struct nai_realm_eap * nai_realm_find_eap(struct wpa_supplicant *wpa_s, - struct nai_realm *realm) +struct nai_realm_eap * nai_realm_find_eap(struct wpa_supplicant *wpa_s, + struct nai_realm *realm) { u8 e; @@ -726,8 +726,8 @@ int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) goto fail; break; case NAI_REALM_INNER_NON_EAP_MSCHAP: - if (wpa_config_set(ssid, "phase2", "\"auth=CHAP\"", 0) - < 0) + if (wpa_config_set(ssid, "phase2", "\"auth=MSCHAP\"", + 0) < 0) goto fail; break; case NAI_REALM_INNER_NON_EAP_MSCHAPV2: diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c index 71778ae..136d25f 100644 --- a/wpa_supplicant/notify.c +++ b/wpa_supplicant/notify.c @@ -88,7 +88,7 @@ void wpas_notify_state_changed(struct wpa_supplicant *wpa_s, #ifdef CONFIG_P2P if (new_state == WPA_COMPLETED) wpas_p2p_notif_connected(wpa_s); - else if (new_state < WPA_ASSOCIATED) + else if (old_state >= WPA_ASSOCIATED && new_state < WPA_ASSOCIATED) wpas_p2p_notif_disconnected(wpa_s); #endif /* CONFIG_P2P */ @@ -525,9 +525,12 @@ void wpas_notify_p2p_wps_failed(struct wpa_supplicant *wpa_s, static void wpas_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s, - const u8 *sta) + const u8 *sta, + const u8 *p2p_dev_addr) { #ifdef CONFIG_P2P + wpas_p2p_notify_ap_sta_authorized(wpa_s, p2p_dev_addr); + /* * Register a group member object corresponding to this peer and * emit a PeerJoined signal. This will check if it really is a @@ -564,10 +567,11 @@ static void wpas_notify_ap_sta_deauthorized(struct wpa_supplicant *wpa_s, void wpas_notify_sta_authorized(struct wpa_supplicant *wpa_s, - const u8 *mac_addr, int authorized) + const u8 *mac_addr, int authorized, + const u8 *p2p_dev_addr) { if (authorized) - wpas_notify_ap_sta_authorized(wpa_s, mac_addr); + wpas_notify_ap_sta_authorized(wpa_s, mac_addr, p2p_dev_addr); else wpas_notify_ap_sta_deauthorized(wpa_s, mac_addr); } diff --git a/wpa_supplicant/notify.h b/wpa_supplicant/notify.h index 7d4a11e..236a31e 100644 --- a/wpa_supplicant/notify.h +++ b/wpa_supplicant/notify.h @@ -86,7 +86,8 @@ void wpas_notify_suspend(struct wpa_global *global); void wpas_notify_resume(struct wpa_global *global); void wpas_notify_sta_authorized(struct wpa_supplicant *wpa_s, - const u8 *mac_addr, int authorized); + const u8 *mac_addr, int authorized, + const u8 *p2p_dev_addr); void wpas_notify_p2p_device_found(struct wpa_supplicant *wpa_s, const u8 *dev_addr, int new_device); void wpas_notify_p2p_device_lost(struct wpa_supplicant *wpa_s, diff --git a/wpa_supplicant/offchannel.c b/wpa_supplicant/offchannel.c old mode 100644 new mode 100755 diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c old mode 100644 new mode 100755 index 7cf37d0..ae6e151 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -62,6 +62,8 @@ static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s); static void wpas_p2p_join_scan(void *eloop_ctx, void *timeout_ctx); static int wpas_p2p_join(struct wpa_supplicant *wpa_s, const u8 *iface_addr, const u8 *dev_addr, enum p2p_wps_method wps_method); +static void wpas_p2p_pd_before_join_timeout(void *eloop_ctx, + void *timeout_ctx); static int wpas_p2p_create_iface(struct wpa_supplicant *wpa_s); static void wpas_p2p_cross_connect_setup(struct wpa_supplicant *wpa_s); static void wpas_p2p_group_idle_timeout(void *eloop_ctx, void *timeout_ctx); @@ -94,7 +96,7 @@ static void wpas_p2p_scan_res_handler(struct wpa_supplicant *wpa_s, static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq, unsigned int num_req_dev_types, - const u8 *req_dev_types) + const u8 *req_dev_types, const u8 *dev_id) { struct wpa_supplicant *wpa_s = ctx; struct wpa_driver_scan_params params; @@ -130,7 +132,7 @@ static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq, wpabuf_put_buf(ies, wps_ie); wpabuf_free(wps_ie); - p2p_scan_ie(wpa_s->global->p2p, ies); + p2p_scan_ie(wpa_s->global->p2p, ies, dev_id); params.p2p_probe = 1; params.extra_ies = wpabuf_head(ies); @@ -217,8 +219,6 @@ static void wpas_p2p_group_delete(struct wpa_supplicant *wpa_s) char *gtype; const char *reason; - eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL); - ssid = wpa_s->current_ssid; if (ssid == NULL) { /* @@ -268,6 +268,8 @@ static void wpas_p2p_group_delete(struct wpa_supplicant *wpa_s) wpa_msg(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_REMOVED "%s %s%s", wpa_s->ifname, gtype, reason); + eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL); + if (ssid) wpas_notify_p2p_group_removed(wpa_s, ssid, gtype); @@ -309,11 +311,15 @@ static void wpas_p2p_group_delete(struct wpa_supplicant *wpa_s) */ wpa_config_remove_network(wpa_s->conf, id); wpa_supplicant_clear_status(wpa_s); + wpa_supplicant_cancel_sched_scan(wpa_s); } else { wpa_printf(MSG_DEBUG, "P2P: Temporary group network not " "found"); } - wpa_supplicant_ap_deinit(wpa_s); + if (wpa_s->ap_iface) + wpa_supplicant_ap_deinit(wpa_s); + else + wpa_drv_deinit_p2p_cli(wpa_s); } @@ -465,6 +471,52 @@ static int wpas_p2p_store_persistent_group(struct wpa_supplicant *wpa_s, } +static void wpas_p2p_add_persistent_group_client(struct wpa_supplicant *wpa_s, + const u8 *addr) +{ + struct wpa_ssid *ssid, *s; + u8 *n; + size_t i; + + ssid = wpa_s->current_ssid; + if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO || + !ssid->p2p_persistent_group) + return; + + for (s = wpa_s->parent->conf->ssid; s; s = s->next) { + if (s->disabled != 2 || s->mode != WPAS_MODE_P2P_GO) + continue; + + if (s->ssid_len == ssid->ssid_len && + os_memcmp(s->ssid, ssid->ssid, s->ssid_len) == 0) + break; + } + + if (s == NULL) + return; + + for (i = 0; s->p2p_client_list && i < s->num_p2p_clients; i++) { + if (os_memcmp(s->p2p_client_list + i * ETH_ALEN, addr, + ETH_ALEN) == 0) + return; /* already in list */ + } + + n = os_realloc(s->p2p_client_list, + (s->num_p2p_clients + 1) * ETH_ALEN); + if (n == NULL) + return; + os_memcpy(n + s->num_p2p_clients * ETH_ALEN, addr, ETH_ALEN); + s->p2p_client_list = n; + s->num_p2p_clients++; + +#ifndef CONFIG_NO_CONFIG_WRITE + if (wpa_s->parent->conf->update_config && + wpa_config_write(wpa_s->parent->confname, wpa_s->parent->conf)) + wpa_printf(MSG_DEBUG, "P2P: Failed to update configuration"); +#endif /* CONFIG_NO_CONFIG_WRITE */ +} + + static void wpas_group_formation_completed(struct wpa_supplicant *wpa_s, int success) { @@ -507,7 +559,7 @@ static void wpas_group_formation_completed(struct wpa_supplicant *wpa_s, client = ssid->mode == WPAS_MODE_INFRA; if (ssid->mode == WPAS_MODE_P2P_GO) { persistent = ssid->p2p_persistent_group; - os_memcpy(go_dev_addr, wpa_s->parent->own_addr, + os_memcpy(go_dev_addr, wpa_s->global->p2p_dev_addr, ETH_ALEN); } else persistent = wpas_p2p_persistent_group(wpa_s, @@ -591,12 +643,14 @@ static void wpas_p2p_send_action_tx_status(struct wpa_supplicant *wpa_s, p2p_send_action_cb(wpa_s->global->p2p, freq, dst, src, bssid, res); - if (wpa_s->pending_pd_before_join && + if (result != OFFCHANNEL_SEND_ACTION_SUCCESS && + wpa_s->pending_pd_before_join && (os_memcmp(dst, wpa_s->pending_join_dev_addr, ETH_ALEN) == 0 || os_memcmp(dst, wpa_s->pending_join_iface_addr, ETH_ALEN) == 0)) { wpa_s->pending_pd_before_join = 0; wpa_printf(MSG_DEBUG, "P2P: Starting pending " - "join-existing-group operation"); + "join-existing-group operation (no ACK for PD " + "Req)"); wpas_p2p_join_start(wpa_s); } } @@ -673,13 +727,13 @@ static void p2p_go_configured(void *ctx, void *data) wpa_ssid_txt(ssid->ssid, ssid->ssid_len), ssid->frequency, params->passphrase ? params->passphrase : "", - MAC2STR(wpa_s->parent->own_addr), + MAC2STR(wpa_s->global->p2p_dev_addr), params->persistent_group ? " [PERSISTENT]" : ""); if (params->persistent_group) network_id = wpas_p2p_store_persistent_group( wpa_s->parent, ssid, - wpa_s->parent->own_addr); + wpa_s->global->p2p_dev_addr); if (network_id < 0) network_id = ssid->id; wpas_notify_p2p_group_started(wpa_s, ssid, network_id, 0); @@ -980,7 +1034,6 @@ void wpas_dev_found(void *ctx, const u8 *addr, const struct p2p_peer_info *info, int new_device) { -#ifndef CONFIG_NO_STDOUT_DEBUG struct wpa_supplicant *wpa_s = ctx; char devtype[WPS_DEV_TYPE_BUFSIZE]; @@ -993,7 +1046,6 @@ void wpas_dev_found(void *ctx, const u8 *addr, sizeof(devtype)), info->device_name, info->config_methods, info->dev_capab, info->group_capab); -#endif /* CONFIG_NO_STDOUT_DEBUG */ wpas_notify_p2p_device_found(ctx, info->p2p_device_addr, new_device); } @@ -1057,7 +1109,7 @@ static void wpas_stop_listen(void *ctx) static int wpas_send_probe_resp(void *ctx, const struct wpabuf *buf) { struct wpa_supplicant *wpa_s = ctx; - return wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1); + return wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf)); } @@ -1352,8 +1404,11 @@ void wpas_sd_request(void *ctx, int freq, const u8 *sa, u8 dialog_token, os_free(buf); } - if (wpa_s->p2p_sd_over_ctrl_iface) + if (wpa_s->p2p_sd_over_ctrl_iface) { + wpas_notify_p2p_sd_request(wpa_s, freq, sa, dialog_token, + update_indic, tlvs, tlvs_len); return; /* to be processed by an external program */ + } resp = wpabuf_alloc(10000); if (resp == NULL) @@ -1500,26 +1555,26 @@ void wpas_sd_response(void *ctx, const u8 *sa, u16 update_indic, } -u64 wpas_p2p_sd_request(struct wpa_supplicant *wpa_s, const u8 *dst, - const struct wpabuf *tlvs) +void * wpas_p2p_sd_request(struct wpa_supplicant *wpa_s, const u8 *dst, + const struct wpabuf *tlvs) { if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) - return wpa_drv_p2p_sd_request(wpa_s, dst, tlvs); + return (void *) wpa_drv_p2p_sd_request(wpa_s, dst, tlvs); if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) - return 0; - return (uintptr_t) p2p_sd_request(wpa_s->global->p2p, dst, tlvs); + return NULL; + return p2p_sd_request(wpa_s->global->p2p, dst, tlvs); } -u64 wpas_p2p_sd_request_upnp(struct wpa_supplicant *wpa_s, const u8 *dst, - u8 version, const char *query) +void * wpas_p2p_sd_request_upnp(struct wpa_supplicant *wpa_s, const u8 *dst, + u8 version, const char *query) { struct wpabuf *tlvs; - u64 ret; + void *ret; tlvs = wpabuf_alloc(2 + 1 + 1 + 1 + os_strlen(query)); if (tlvs == NULL) - return 0; + return NULL; wpabuf_put_le16(tlvs, 1 + 1 + 1 + os_strlen(query)); wpabuf_put_u8(tlvs, P2P_SERV_UPNP); /* Service Protocol Type */ wpabuf_put_u8(tlvs, 1); /* Service Transaction ID */ @@ -1531,14 +1586,13 @@ u64 wpas_p2p_sd_request_upnp(struct wpa_supplicant *wpa_s, const u8 *dst, } -int wpas_p2p_sd_cancel_request(struct wpa_supplicant *wpa_s, u64 req) +int wpas_p2p_sd_cancel_request(struct wpa_supplicant *wpa_s, void *req) { if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) - return wpa_drv_p2p_sd_cancel_request(wpa_s, req); + return wpa_drv_p2p_sd_cancel_request(wpa_s, (u64) req); if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) return -1; - return p2p_sd_cancel_request(wpa_s->global->p2p, - (void *) (uintptr_t) req); + return p2p_sd_cancel_request(wpa_s->global->p2p, req); } @@ -1758,6 +1812,16 @@ void wpas_prov_disc_resp(void *ctx, const u8 *peer, u16 config_methods) struct wpa_supplicant *wpa_s = ctx; unsigned int generated_pin = 0; + if (wpa_s->pending_pd_before_join && + (os_memcmp(peer, wpa_s->pending_join_dev_addr, ETH_ALEN) == 0 || + os_memcmp(peer, wpa_s->pending_join_iface_addr, ETH_ALEN) == 0)) { + wpa_s->pending_pd_before_join = 0; + wpa_printf(MSG_DEBUG, "P2P: Starting pending " + "join-existing-group operation"); + wpas_p2p_join_start(wpa_s); + return; + } + if (config_methods & WPS_CONFIG_DISPLAY) wpas_prov_disc_local_keypad(wpa_s, peer, ""); else if (config_methods & WPS_CONFIG_KEYPAD) { @@ -1770,20 +1834,11 @@ void wpas_prov_disc_resp(void *ctx, const u8 *peer, u16 config_methods) wpas_notify_p2p_provision_discovery(wpa_s, peer, 0 /* response */, P2P_PROV_DISC_SUCCESS, config_methods, generated_pin); - - if (wpa_s->pending_pd_before_join && - (os_memcmp(peer, wpa_s->pending_join_dev_addr, ETH_ALEN) == 0 || - os_memcmp(peer, wpa_s->pending_join_iface_addr, ETH_ALEN) == 0)) { - wpa_s->pending_pd_before_join = 0; - wpa_printf(MSG_DEBUG, "P2P: Starting pending " - "join-existing-group operation"); - wpas_p2p_join_start(wpa_s); - } } -static void wpas_prov_disc_fail(void *ctx, const u8 *peer, - enum p2p_prov_disc_status status) +void wpas_prov_disc_fail(void *ctx, const u8 *peer, + enum p2p_prov_disc_status status) { struct wpa_supplicant *wpa_s = ctx; @@ -2157,6 +2212,27 @@ static int wpas_get_noa(void *ctx, const u8 *interface_addr, u8 *buf, } +static int wpas_go_connected(void *ctx, const u8 *dev_addr) +{ + struct wpa_supplicant *wpa_s = ctx; + + for (wpa_s = wpa_s->global->ifaces; wpa_s; wpa_s = wpa_s->next) { + struct wpa_ssid *ssid = wpa_s->current_ssid; + if (ssid == NULL) + continue; + if (ssid->mode != WPAS_MODE_INFRA) + continue; + if (wpa_s->wpa_state != WPA_COMPLETED && + wpa_s->wpa_state != WPA_GROUP_HANDSHAKE) + continue; + if (os_memcmp(wpa_s->go_dev_addr, dev_addr, ETH_ALEN) == 0) + return 1; + } + + return 0; +} + + /** * wpas_p2p_init - Initialize P2P module for %wpa_supplicant * @global: Pointer to global data from wpa_supplicant_init() @@ -2216,9 +2292,22 @@ int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s) p2p.invitation_received = wpas_invitation_received; p2p.invitation_result = wpas_invitation_result; p2p.get_noa = wpas_get_noa; - + p2p.go_connected = wpas_go_connected; + +#ifdef TIZEN_EXT +#ifdef BCM_DRIVER_V115 + char buf[64]; +// wpa_drv_driver_cmd(wpa_s, "P2P_DEV_ADDR", buf, sizeof(buf)); + wpa_s->driver->driver_cmd(wpa_s->drv_priv, "P2P_DEV_ADDR", buf, sizeof(buf)); +// os_memcpy(p2p.p2p_dev_addr, buf, ETH_ALEN); + os_memcpy(wpa_s->global->p2p_dev_addr, buf, ETH_ALEN); + wpa_printf(MSG_DEBUG, "P2P: Device address ("MACSTR")", MAC2STR(buf)); +#endif +#else os_memcpy(wpa_s->global->p2p_dev_addr, wpa_s->own_addr, ETH_ALEN); - os_memcpy(p2p.dev_addr, wpa_s->own_addr, ETH_ALEN); +#endif + + os_memcpy(p2p.dev_addr, wpa_s->global->p2p_dev_addr, ETH_ALEN); p2p.dev_name = wpa_s->conf->device_name; p2p.manufacturer = wpa_s->conf->manufacturer; p2p.model_name = wpa_s->conf->model_name; @@ -2329,13 +2418,14 @@ void wpas_p2p_deinit(struct wpa_supplicant *wpa_s) /* Clear any stored provisioning info */ p2p_clear_provisioning_info( wpa_s->global->p2p, - wpa_s->go_params->peer_interface_addr); + wpa_s->go_params->peer_device_addr); } os_free(wpa_s->go_params); wpa_s->go_params = NULL; eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s, NULL); eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL); + eloop_cancel_timeout(wpas_p2p_pd_before_join_timeout, wpa_s, NULL); wpa_s->p2p_long_listen = 0; eloop_cancel_timeout(wpas_p2p_long_listen_timeout, wpa_s, NULL); eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL); @@ -2355,7 +2445,6 @@ void wpas_p2p_deinit(struct wpa_supplicant *wpa_s) void wpas_p2p_deinit_global(struct wpa_global *global) { struct wpa_supplicant *wpa_s, *tmp; - char *ifname; if (global->p2p == NULL) return; @@ -2376,12 +2465,9 @@ void wpas_p2p_deinit_global(struct wpa_global *global) } if (tmp == NULL) break; - ifname = os_strdup(tmp->ifname); type = wpas_p2p_if_type(tmp->p2p_group_interface); - wpa_supplicant_remove_iface(global, tmp); - if (ifname) - wpa_drv_if_remove(wpa_s, type, ifname); - os_free(ifname); + /* Disconnect from the P2P group and deinit the interface */ + wpas_p2p_disconnect(tmp); } /* @@ -2470,6 +2556,21 @@ static void wpas_p2p_check_join_scan_limit(struct wpa_supplicant *wpa_s) } +static void wpas_p2p_pd_before_join_timeout(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_supplicant *wpa_s = eloop_ctx; + if (!wpa_s->pending_pd_before_join) + return; + /* + * Provision Discovery Response may have been lost - try to connect + * anyway since we do not need any information from this PD. + */ + wpa_printf(MSG_DEBUG, "P2P: PD timeout for join-existing-group - " + "try to connect anyway"); + wpas_p2p_join_start(wpa_s); +} + + static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s, struct wpa_scan_results *scan_res) { @@ -2548,7 +2649,7 @@ static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s, * We have already performed provision discovery for * joining the group. Proceed directly to join * operation without duplicated provision discovery. */ - wpa_printf(MSG_DEBUG, "P2P: Provision discovery " + wpa_printf(MSG_DEBUG, "P2P: Provisioning discovery " "with " MACSTR " already done - proceed to " "join", MAC2STR(wpa_s->pending_join_dev_addr)); @@ -2568,8 +2669,15 @@ static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s, /* * Actual join operation will be started from the Action frame - * TX status callback. + * TX status callback (if no ACK is received) or when the + * Provision Discovery Response is received. Use a short + * timeout as a backup mechanism should the Provision Discovery + * Response be lost for any reason. */ + eloop_cancel_timeout(wpas_p2p_pd_before_join_timeout, wpa_s, + NULL); + eloop_register_timeout(2, 0, wpas_p2p_pd_before_join_timeout, + wpa_s, NULL); return; } @@ -2618,7 +2726,7 @@ static void wpas_p2p_join_scan(void *eloop_ctx, void *timeout_ctx) wpabuf_put_buf(ies, wps_ie); wpabuf_free(wps_ie); - p2p_scan_ie(wpa_s->global->p2p, ies); + p2p_scan_ie(wpa_s->global->p2p, ies, NULL); params.p2p_probe = 1; params.extra_ies = wpabuf_head(ies); @@ -2668,6 +2776,7 @@ static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s) struct wpa_supplicant *group; struct p2p_go_neg_results res; + eloop_cancel_timeout(wpas_p2p_pd_before_join_timeout, wpa_s, NULL); group = wpas_p2p_get_group_iface(wpa_s, 0, 0); if (group == NULL) return -1; @@ -2683,6 +2792,13 @@ static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s) os_memcpy(res.peer_interface_addr, wpa_s->pending_join_iface_addr, ETH_ALEN); res.wps_method = wpa_s->pending_join_wps_method; + if (wpa_s->off_channel_freq || wpa_s->roc_waiting_drv_freq) { + wpa_printf(MSG_DEBUG, "P2P: Cancel remain-on-channel prior to " + "starting client"); + wpa_drv_cancel_remain_on_channel(wpa_s); + wpa_s->off_channel_freq = 0; + wpa_s->roc_waiting_drv_freq = 0; + } wpas_start_wps_enrollee(group, &res); /* @@ -2723,7 +2839,6 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr, u8 bssid[ETH_ALEN]; int ret = 0; enum wpa_driver_if_type iftype; - const u8 *if_addr; if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) return -1; @@ -2819,34 +2934,44 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr, wpa_s->create_p2p_iface = wpas_p2p_create_iface(wpa_s); - if (wpa_s->create_p2p_iface) { - /* Prepare to add a new interface for the group */ - iftype = WPA_IF_P2P_GROUP; - if (go_intent == 15) - iftype = WPA_IF_P2P_GO; - if (wpas_p2p_add_group_interface(wpa_s, iftype) < 0) { - wpa_printf(MSG_ERROR, "P2P: Failed to allocate a new " - "interface for the group"); - return -1; + if (!wpa_s->create_p2p_iface) { + if (auth) { + if (wpas_p2p_auth_go_neg(wpa_s, peer_addr, wps_method, + go_intent, wpa_s->own_addr, + force_freq, persistent_group) + < 0) + return -1; + return ret; } + if (wpas_p2p_start_go_neg(wpa_s, peer_addr, wps_method, + go_intent, wpa_s->own_addr, + force_freq, persistent_group) < 0) + return -1; + return ret; + } - if_addr = wpa_s->pending_interface_addr; - } else - if_addr = wpa_s->own_addr; + /* Prepare to add a new interface for the group */ + iftype = WPA_IF_P2P_GROUP; + if (go_intent == 15) + iftype = WPA_IF_P2P_GO; + if (wpas_p2p_add_group_interface(wpa_s, iftype) < 0) { + wpa_printf(MSG_ERROR, "P2P: Failed to allocate a new " + "interface for the group"); + return -1; + } if (auth) { if (wpas_p2p_auth_go_neg(wpa_s, peer_addr, wps_method, - go_intent, if_addr, + go_intent, + wpa_s->pending_interface_addr, force_freq, persistent_group) < 0) return -1; return ret; } - - if (wpas_p2p_start_go_neg(wpa_s, peer_addr, wps_method, - go_intent, if_addr, force_freq, - persistent_group) < 0) { - if (wpa_s->create_p2p_iface) - wpas_p2p_remove_pending_group_interface(wpa_s); + if (wpas_p2p_start_go_neg(wpa_s, peer_addr, wps_method, go_intent, + wpa_s->pending_interface_addr, + force_freq, persistent_group) < 0) { + wpas_p2p_remove_pending_group_interface(wpa_s); return -1; } return ret; @@ -2956,9 +3081,9 @@ int wpas_p2p_group_remove(struct wpa_supplicant *wpa_s, const char *ifname) } -static void wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s, - struct p2p_go_neg_results *params, - int freq) +static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s, + struct p2p_go_neg_results *params, + int freq) { u8 bssid[ETH_ALEN]; int res; @@ -3019,7 +3144,16 @@ static void wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s, wpa_printf(MSG_DEBUG, "P2P: Force GO on the channel we are " "already using on a shared interface"); params->freq = res; + } else if (res > 0 && freq != res && + !(wpa_s->drv_flags & + WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT)) { + wpa_printf(MSG_DEBUG, "P2P: Cannot start P2P group on %u MHz " + "while connected on another channel (%u MHz)", + freq, res); + return -1; } + + return 0; } @@ -3114,7 +3248,15 @@ int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group, return -1; } - wpas_p2p_init_go_params(wpa_s, ¶ms, freq); + if (wpas_p2p_init_go_params(wpa_s, ¶ms, freq)) + return -1; + if (params.freq && + !p2p_supported_freq(wpa_s->global->p2p, params.freq)) { + wpa_printf(MSG_DEBUG, "P2P: The selected channel for GO " + "(%u MHz) is not supported for P2P uses", + params.freq); + return -1; + } p2p_go_params(wpa_s->global->p2p, ¶ms); params.persistent_group = persistent_group; @@ -3197,7 +3339,8 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s, if (ssid->mode != WPAS_MODE_P2P_GO) return -1; - wpas_p2p_init_go_params(wpa_s, ¶ms, freq); + if (wpas_p2p_init_go_params(wpa_s, ¶ms, freq)) + return -1; params.role_go = 1; if (ssid->passphrase == NULL || @@ -3303,14 +3446,22 @@ struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s, void wpas_p2p_wps_success(struct wpa_supplicant *wpa_s, const u8 *peer_addr, int registrar) { + struct wpa_ssid *ssid = wpa_s->current_ssid; + if (!wpa_s->p2p_in_provisioning) { wpa_printf(MSG_DEBUG, "P2P: Ignore WPS success event - P2P " "provisioning not in progress"); return; } - /* Clear any stored provisioning info */ - p2p_clear_provisioning_info(wpa_s->global->p2p, peer_addr); + if (ssid && ssid->mode == WPAS_MODE_INFRA) { + u8 go_dev_addr[ETH_ALEN]; + os_memcpy(go_dev_addr, wpa_s->bssid, ETH_ALEN); + wpas_p2p_persistent_group(wpa_s, go_dev_addr, ssid->ssid, + ssid->ssid_len); + /* Clear any stored provisioning info */ + p2p_clear_provisioning_info(wpa_s->global->p2p, go_dev_addr); + } eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s->parent, NULL); @@ -3334,7 +3485,7 @@ void wpas_p2p_wps_failed(struct wpa_supplicant *wpa_s, if (wpa_s->go_params) { p2p_clear_provisioning_info( wpa_s->global->p2p, - wpa_s->go_params->peer_interface_addr); + wpa_s->go_params->peer_device_addr); } wpas_notify_p2p_wps_failed(wpa_s, fail); @@ -3392,7 +3543,8 @@ static void wpas_p2p_clear_pending_action_tx(struct wpa_supplicant *wpa_s) int wpas_p2p_find(struct wpa_supplicant *wpa_s, unsigned int timeout, enum p2p_discovery_type type, - unsigned int num_req_dev_types, const u8 *req_dev_types) + unsigned int num_req_dev_types, const u8 *req_dev_types, + const u8 *dev_id) { wpas_p2p_clear_pending_action_tx(wpa_s); wpa_s->p2p_long_listen = 0; @@ -3403,8 +3555,10 @@ int wpas_p2p_find(struct wpa_supplicant *wpa_s, unsigned int timeout, if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) return -1; + wpa_supplicant_cancel_sched_scan(wpa_s); + return p2p_find(wpa_s->global->p2p, timeout, type, - num_req_dev_types, req_dev_types); + num_req_dev_types, req_dev_types, dev_id); } @@ -3442,6 +3596,7 @@ int wpas_p2p_listen(struct wpa_supplicant *wpa_s, unsigned int timeout) if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) return -1; + wpa_supplicant_cancel_sched_scan(wpa_s); wpas_p2p_clear_pending_action_tx(wpa_s); if (timeout == 0) { @@ -3532,7 +3687,7 @@ void wpas_p2p_scan_ie(struct wpa_supplicant *wpa_s, struct wpabuf *ies) if (wpa_s->global->p2p == NULL) return; - p2p_scan_ie(wpa_s->global->p2p, ies); + p2p_scan_ie(wpa_s->global->p2p, ies, NULL); } @@ -3614,6 +3769,7 @@ int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname, enum p2p_invite_role role; u8 *bssid = NULL; struct wpa_ssid *ssid; + int persistent; for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { if (os_strcmp(wpa_s->ifname, ifname) == 0) @@ -3631,11 +3787,15 @@ int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname, return -1; } + persistent = ssid->p2p_persistent_group && + wpas_p2p_get_persistent(wpa_s->parent, peer_addr, + ssid->ssid, ssid->ssid_len); + if (ssid->mode == WPAS_MODE_P2P_GO) { role = P2P_INVITE_ROLE_ACTIVE_GO; bssid = wpa_s->own_addr; if (go_dev_addr == NULL) - go_dev_addr = wpa_s->parent->own_addr; + go_dev_addr = wpa_s->global->p2p_dev_addr; } else { role = P2P_INVITE_ROLE_CLIENT; if (wpa_s->wpa_state < WPA_ASSOCIATED) { @@ -3653,14 +3813,14 @@ int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname, if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) return wpa_drv_p2p_invite(wpa_s, peer_addr, role, bssid, ssid->ssid, ssid->ssid_len, - go_dev_addr, 0); + go_dev_addr, persistent); if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) return -1; return p2p_invite(wpa_s->global->p2p, peer_addr, role, bssid, ssid->ssid, ssid->ssid_len, wpa_s->assoc_freq, - go_dev_addr, 0); + go_dev_addr, persistent); } @@ -3792,6 +3952,17 @@ static void wpas_p2p_set_group_idle_timeout(struct wpa_supplicant *wpa_s) if (timeout == 0) return; + if (wpa_s->p2p_in_provisioning) { + /* + * Use the normal group formation timeout during the + * provisioning phase to avoid terminating this process too + * early due to group idle timeout. + */ + wpa_printf(MSG_DEBUG, "P2P: Do not use P2P group idle timeout " + "during provisioning"); + return; + } + wpa_printf(MSG_DEBUG, "P2P: Set P2P group idle timeout to %u seconds", timeout); eloop_register_timeout(timeout, 0, wpas_p2p_group_idle_timeout, @@ -3935,6 +4106,14 @@ void wpas_p2p_update_config(struct wpa_supplicant *wpa_s) wpa_printf(MSG_ERROR, "P2P: Own oper channel update " "failed: %d", ret); } + + if (wpa_s->conf->changed_parameters & CFG_CHANGED_P2P_PREF_CHAN) { + if (p2p_set_pref_chan(p2p, wpa_s->conf->num_p2p_pref_chan, + wpa_s->conf->p2p_pref_chan) < 0) { + wpa_printf(MSG_ERROR, "P2P: Preferred channel list " + "update failed"); + } + } } @@ -4146,6 +4325,7 @@ int wpas_p2p_cancel(struct wpa_supplicant *wpa_s) wpa_printf(MSG_DEBUG, "P2P: Unauthorize pending GO Neg peer " MACSTR, MAC2STR(peer)); p2p_unauthorize(global->p2p, peer); + found = 1; } wpas_p2p_stop_find(wpa_s); @@ -4247,13 +4427,60 @@ int wpas_p2p_in_progress(struct wpa_supplicant *wpa_s) void wpas_p2p_network_removed(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) - { if (wpa_s->p2p_in_provisioning && ssid->p2p_group && eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s->parent, NULL) > 0) { + /** + * Remove the network by scheduling the group formation + * timeout to happen immediately. The teardown code + * needs to be scheduled to run asynch later so that we + * don't delete data from under ourselves unexpectedly. + * Calling wpas_p2p_group_formation_timeout directly + * causes a series of crashes in WPS failure scenarios. + */ wpa_printf(MSG_DEBUG, "P2P: Canceled group formation due to " "P2P group network getting removed"); - wpas_p2p_group_formation_timeout(wpa_s->parent, NULL); + eloop_register_timeout(0, 0, wpas_p2p_group_formation_timeout, + wpa_s->parent, NULL); } } + + +struct wpa_ssid * wpas_p2p_get_persistent(struct wpa_supplicant *wpa_s, + const u8 *addr, const u8 *ssid, + size_t ssid_len) +{ + struct wpa_ssid *s; + size_t i; + + for (s = wpa_s->conf->ssid; s; s = s->next) { + if (s->disabled != 2) + continue; + if (ssid && + (ssid_len != s->ssid_len || + os_memcmp(ssid, s->ssid, ssid_len) != 0)) + continue; + if (os_memcmp(s->bssid, addr, ETH_ALEN) == 0) + return s; /* peer is GO in the persistent group */ + if (s->mode != WPAS_MODE_P2P_GO || s->p2p_client_list == NULL) + continue; + for (i = 0; i < s->num_p2p_clients; i++) { + if (os_memcmp(s->p2p_client_list + i * ETH_ALEN, + addr, ETH_ALEN) == 0) + return s; /* peer is P2P client in persistent + * group */ + } + } + + return NULL; +} + + +void wpas_p2p_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s, + const u8 *addr) +{ + if (addr == NULL) + return; + wpas_p2p_add_persistent_group_client(wpa_s, addr); +} diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h index 9a0af1f..4887823 100644 --- a/wpa_supplicant/p2p_supplicant.h +++ b/wpa_supplicant/p2p_supplicant.h @@ -52,7 +52,8 @@ int wpas_p2p_scan_result_text(const u8 *ies, size_t ies_len, char *buf, enum p2p_discovery_type; int wpas_p2p_find(struct wpa_supplicant *wpa_s, unsigned int timeout, enum p2p_discovery_type type, - unsigned int num_req_dev_types, const u8 *req_dev_types); + unsigned int num_req_dev_types, const u8 *req_dev_types, + const u8 *dev_id); void wpas_p2p_stop_find(struct wpa_supplicant *wpa_s); int wpas_p2p_listen(struct wpa_supplicant *wpa_s, unsigned int timeout); int wpas_p2p_assoc_req_ie(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, @@ -80,11 +81,11 @@ void wpas_sd_request(void *ctx, int freq, const u8 *sa, u8 dialog_token, u16 update_indic, const u8 *tlvs, size_t tlvs_len); void wpas_sd_response(void *ctx, const u8 *sa, u16 update_indic, const u8 *tlvs, size_t tlvs_len); -u64 wpas_p2p_sd_request(struct wpa_supplicant *wpa_s, const u8 *dst, - const struct wpabuf *tlvs); -u64 wpas_p2p_sd_request_upnp(struct wpa_supplicant *wpa_s, const u8 *dst, - u8 version, const char *query); -int wpas_p2p_sd_cancel_request(struct wpa_supplicant *wpa_s, u64 req); +void * wpas_p2p_sd_request(struct wpa_supplicant *wpa_s, const u8 *dst, + const struct wpabuf *tlvs); +void * wpas_p2p_sd_request_upnp(struct wpa_supplicant *wpa_s, const u8 *dst, + u8 version, const char *query); +int wpas_p2p_sd_cancel_request(struct wpa_supplicant *wpa_s, void *req); void wpas_p2p_sd_response(struct wpa_supplicant *wpa_s, int freq, const u8 *dst, u8 dialog_token, const struct wpabuf *resp_tlvs); @@ -131,5 +132,10 @@ void wpas_p2p_wps_failed(struct wpa_supplicant *wpa_s, int wpas_p2p_in_progress(struct wpa_supplicant *wpa_s); void wpas_p2p_network_removed(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid); +struct wpa_ssid * wpas_p2p_get_persistent(struct wpa_supplicant *wpa_s, + const u8 *addr, const u8 *ssid, + size_t ssid_len); +void wpas_p2p_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s, + const u8 *addr); #endif /* P2P_SUPPLICANT_H */ diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c old mode 100644 new mode 100755 index adc6213..ad21ea5 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -71,10 +71,12 @@ static int wpas_wps_in_use(struct wpa_supplicant *wpa_s, } #ifdef CONFIG_P2P - wpa_s->wps->dev.p2p = 1; - if (!wps) { - wps = 1; - *req_type = WPS_REQ_ENROLLEE_INFO; + if (!wpa_s->global->p2p_disabled && wpa_s->global->p2p) { + wpa_s->wps->dev.p2p = 1; + if (!wps) { + wps = 1; + *req_type = WPS_REQ_ENROLLEE_INFO; + } } #endif /* CONFIG_P2P */ @@ -203,10 +205,8 @@ int wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s, if (ret) { wpa_supplicant_notify_scanning(wpa_s, 0); wpas_notify_scan_done(wpa_s, 0); - } else { + } else wpa_s->scan_runs++; - wpa_s->normal_scans++; - } return ret; } @@ -642,6 +642,7 @@ void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec) * causes the specific SSID scan to get continually pushed back and * never happen, which causes hidden APs to never get probe-scanned. */ + if (eloop_is_timeout_registered(wpa_supplicant_scan, wpa_s, NULL) && wpa_s->conf->ap_scan == 1) { struct wpa_ssid *ssid = wpa_s->conf->ssid; @@ -703,8 +704,6 @@ int wpa_supplicant_req_sched_scan(struct wpa_supplicant *wpa_s) struct wpabuf *wps_ie = NULL; int ret; unsigned int max_sched_scan_ssids; - int wildcard = 0; - int need_ssids; if (!wpa_s->sched_scan_supported) return -1; @@ -713,40 +712,9 @@ int wpa_supplicant_req_sched_scan(struct wpa_supplicant *wpa_s) max_sched_scan_ssids = WPAS_MAX_SCAN_SSIDS; else max_sched_scan_ssids = wpa_s->max_sched_scan_ssids; - if (max_sched_scan_ssids < 1) - return -1; - if (wpa_s->sched_scanning) { - wpa_dbg(wpa_s, MSG_DEBUG, "Already sched scanning"); + if (wpa_s->sched_scanning) return 0; - } - - need_ssids = 0; - for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { - if (!ssid->disabled && !ssid->scan_ssid) { - /* Use wildcard SSID to find this network */ - wildcard = 1; - } else if (!ssid->disabled && ssid->ssid_len) - need_ssids++; - } - if (wildcard) - need_ssids++; - - if (wpa_s->normal_scans < 3 && - (need_ssids <= wpa_s->max_scan_ssids || - wpa_s->max_scan_ssids >= (int) max_sched_scan_ssids)) { - /* - * When normal scan can speed up operations, use that for the - * first operations before starting the sched_scan to allow - * user space sleep more. We do this only if the normal scan - * has functionality that is suitable for this or if the - * sched_scan does not have better support for multiple SSIDs. - */ - wpa_dbg(wpa_s, MSG_DEBUG, "Use normal scan instead of " - "sched_scan for initial scans (normal_scans=%d)", - wpa_s->normal_scans); - return -1; - } os_memset(¶ms, 0, sizeof(params)); @@ -774,46 +742,29 @@ int wpa_supplicant_req_sched_scan(struct wpa_supplicant *wpa_s) if (!ssid || !wpa_s->prev_sched_ssid) { wpa_dbg(wpa_s, MSG_DEBUG, "Beginning of SSID list"); - wpa_s->sched_scan_interval = 10; + wpa_s->sched_scan_interval = 2; wpa_s->sched_scan_timeout = max_sched_scan_ssids * 2; wpa_s->first_sched_scan = 1; ssid = wpa_s->conf->ssid; wpa_s->prev_sched_ssid = ssid; } - if (wildcard) { - wpa_dbg(wpa_s, MSG_DEBUG, "Add wildcard SSID to sched_scan"); - params.num_ssids++; - } - while (ssid) { - if (ssid->disabled) - goto next; + if (ssid->disabled) { + wpa_s->prev_sched_ssid = ssid; + ssid = ssid->next; + continue; + } - if (params.num_filter_ssids < wpa_s->max_match_sets && - params.filter_ssids && ssid->ssid && ssid->ssid_len) { - wpa_dbg(wpa_s, MSG_DEBUG, "add to filter ssid: %s", - wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); + if (params.filter_ssids && ssid->ssid && ssid->ssid_len) { os_memcpy(params.filter_ssids[params.num_filter_ssids].ssid, ssid->ssid, ssid->ssid_len); params.filter_ssids[params.num_filter_ssids].ssid_len = ssid->ssid_len; params.num_filter_ssids++; - } else if (params.filter_ssids && ssid->ssid && ssid->ssid_len) - { - wpa_dbg(wpa_s, MSG_DEBUG, "Not enough room for SSID " - "filter for sched_scan - drop filter"); - os_free(params.filter_ssids); - params.filter_ssids = NULL; - params.num_filter_ssids = 0; } - if (ssid->scan_ssid && ssid->ssid && ssid->ssid_len) { - if (params.num_ssids == max_sched_scan_ssids) - break; /* only room for broadcast SSID */ - wpa_dbg(wpa_s, MSG_DEBUG, - "add to active scan ssid: %s", - wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); + if (ssid->scan_ssid) { params.ssids[params.num_ssids].ssid = ssid->ssid; params.ssids[params.num_ssids].ssid_len = @@ -825,28 +776,23 @@ int wpa_supplicant_req_sched_scan(struct wpa_supplicant *wpa_s) } } - next: + if (params.num_filter_ssids >= wpa_s->max_match_sets) + break; wpa_s->prev_sched_ssid = ssid; ssid = ssid->next; } - if (params.num_filter_ssids == 0) { + if (!params.num_ssids) { os_free(params.filter_ssids); - params.filter_ssids = NULL; + return 0; } if (wpa_s->wps) wps_ie = wpa_supplicant_extra_ies(wpa_s, ¶ms); - if (ssid || !wpa_s->first_sched_scan) { - wpa_dbg(wpa_s, MSG_DEBUG, - "Starting sched scan: interval %d (no timeout)", - wpa_s->sched_scan_interval); - } else { - wpa_dbg(wpa_s, MSG_DEBUG, - "Starting sched scan: interval %d timeout %d", - wpa_s->sched_scan_interval, wpa_s->sched_scan_timeout); - } + wpa_dbg(wpa_s, MSG_DEBUG, + "Starting sched scan: interval %d timeout %d", + wpa_s->sched_scan_interval, wpa_s->sched_scan_timeout); ret = wpa_supplicant_start_sched_scan(wpa_s, ¶ms, wpa_s->sched_scan_interval); @@ -1168,7 +1114,6 @@ static int wpa_scan_result_wps_compar(const void *a, const void *b) static void dump_scan_res(struct wpa_scan_results *scan_res) { -#ifndef CONFIG_NO_STDOUT_DEBUG size_t i; if (scan_res->res == NULL || scan_res->num == 0) @@ -1193,7 +1138,6 @@ static void dump_scan_res(struct wpa_scan_results *scan_res) r->noise, r->level, r->flags); } } -#endif /* CONFIG_NO_STDOUT_DEBUG */ } diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index c5e47d1..4c17ef3 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -29,6 +29,7 @@ #include "wps_supplicant.h" #include "p2p_supplicant.h" #include "notify.h" +#include "blacklist.h" #include "bss.h" #include "scan.h" #include "sme.h" @@ -115,7 +116,11 @@ void sme_authenticate(struct wpa_supplicant *wpa_s, if ((wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) || wpa_bss_get_ie(bss, WLAN_EID_RSN)) && - wpa_key_mgmt_wpa(ssid->key_mgmt)) { + (ssid->key_mgmt & (WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_PSK | + WPA_KEY_MGMT_FT_IEEE8021X | + WPA_KEY_MGMT_FT_PSK | + WPA_KEY_MGMT_IEEE8021X_SHA256 | + WPA_KEY_MGMT_PSK_SHA256))) { int try_opportunistic; try_opportunistic = ssid->proactive_key_caching && (ssid->proto & WPA_PROTO_RSN); @@ -131,7 +136,11 @@ void sme_authenticate(struct wpa_supplicant *wpa_s, "key management and encryption suites"); return; } - } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) { + } else if (ssid->key_mgmt & + (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_IEEE8021X | + WPA_KEY_MGMT_WPA_NONE | WPA_KEY_MGMT_FT_PSK | + WPA_KEY_MGMT_FT_IEEE8021X | WPA_KEY_MGMT_PSK_SHA256 | + WPA_KEY_MGMT_IEEE8021X_SHA256)) { wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie); if (wpa_supplicant_set_suites(wpa_s, NULL, ssid, wpa_s->sme.assoc_req_ie, @@ -170,7 +179,8 @@ void sme_authenticate(struct wpa_supplicant *wpa_s, wpa_ft_prepare_auth_request(wpa_s->wpa, ie); } - if (md && wpa_key_mgmt_ft(ssid->key_mgmt)) { + if (md && ssid->key_mgmt & (WPA_KEY_MGMT_FT_PSK | + WPA_KEY_MGMT_FT_IEEE8021X)) { if (wpa_s->sme.assoc_req_ie_len + 5 < sizeof(wpa_s->sme.assoc_req_ie)) { struct rsn_mdie *mdie; @@ -265,8 +275,8 @@ void sme_authenticate(struct wpa_supplicant *wpa_s, if (wpa_drv_authenticate(wpa_s, ¶ms) < 0) { wpa_msg(wpa_s, MSG_INFO, "SME: Authentication request to the " "driver failed"); - wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); wpas_connection_failed(wpa_s, bss->bssid); + wpa_supplicant_mark_disassoc(wpa_s); return; } @@ -503,8 +513,8 @@ void sme_event_auth_timed_out(struct wpa_supplicant *wpa_s, union wpa_event_data *data) { wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication timed out"); - wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); wpas_connection_failed(wpa_s, wpa_s->pending_bssid); + wpa_supplicant_mark_disassoc(wpa_s); } @@ -688,7 +698,7 @@ static void sme_start_sa_query(struct wpa_supplicant *wpa_s) } -static void sme_stop_sa_query(struct wpa_supplicant *wpa_s) +void sme_stop_sa_query(struct wpa_supplicant *wpa_s) { eloop_cancel_timeout(sme_sa_query_timer, wpa_s, NULL); os_free(wpa_s->sme.sa_query_trans_id); diff --git a/wpa_supplicant/systemd/wpa_supplicant-nl80211@.service.in b/wpa_supplicant/systemd/wpa_supplicant-nl80211@.service.in index 4d9c146..76aba12 100644 --- a/wpa_supplicant/systemd/wpa_supplicant-nl80211@.service.in +++ b/wpa_supplicant/systemd/wpa_supplicant-nl80211@.service.in @@ -10,4 +10,4 @@ Type=simple ExecStart=@BINDIR@/wpa_supplicant -c/etc/wpa_supplicant/wpa_supplicant-nl80211-%I.conf -Dnl80211 -i%I [Install] -Alias=network.target.wants/wpa_supplicant-nl80211@wlan0.service +Alias=multi-user.target.wants/wpa_supplicant-nl80211@wlan0.service diff --git a/wpa_supplicant/systemd/wpa_supplicant-wired@.service.in b/wpa_supplicant/systemd/wpa_supplicant-wired@.service.in index f2e7f11..ff384ae 100644 --- a/wpa_supplicant/systemd/wpa_supplicant-wired@.service.in +++ b/wpa_supplicant/systemd/wpa_supplicant-wired@.service.in @@ -10,4 +10,4 @@ Type=simple ExecStart=@BINDIR@/wpa_supplicant -c/etc/wpa_supplicant/wpa_supplicant-wired-%I.conf -Dwired -i%I [Install] -Alias=network.target.wants/wpa_supplicant-wired@wlan0.service +Alias=multi-user.target.wants/wpa_supplicant-wired@wlan0.service diff --git a/wpa_supplicant/systemd/wpa_supplicant.service.in b/wpa_supplicant/systemd/wpa_supplicant.service.in index 5b947ac..4351ad8 100644 --- a/wpa_supplicant/systemd/wpa_supplicant.service.in +++ b/wpa_supplicant/systemd/wpa_supplicant.service.in @@ -7,5 +7,5 @@ BusName=fi.epitest.hostap.WPASupplicant ExecStart=@BINDIR@/wpa_supplicant -u [Install] -WantedBy=network.target +WantedBy=multi-user.target Alias=dbus-fi.epitest.hostap.WPASupplicant.service diff --git a/wpa_supplicant/systemd/wpa_supplicant@.service.in b/wpa_supplicant/systemd/wpa_supplicant@.service.in index 0340b4d..c215567 100644 --- a/wpa_supplicant/systemd/wpa_supplicant@.service.in +++ b/wpa_supplicant/systemd/wpa_supplicant@.service.in @@ -10,4 +10,4 @@ Type=simple ExecStart=@BINDIR@/wpa_supplicant -c/etc/wpa_supplicant/wpa_supplicant-%I.conf -i%I [Install] -Alias=network.target.wants/wpa_supplicant@wlan0.service +Alias=multi-user.target.wants/wpa_supplicant@wlan0.service diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index 6ca7939..7da13c3 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -33,7 +33,7 @@ static const char *wpa_cli_version = "wpa_cli v" VERSION_STR "\n" -"Copyright (c) 2004-2011, Jouni Malinen and contributors"; +"Copyright (c) 2004-2012, Jouni Malinen and contributors"; static const char *wpa_cli_license = @@ -454,11 +454,8 @@ static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd) static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[]) { - if (argc > 0 && os_strcmp(argv[0], "verbose") == 0) - return wpa_ctrl_command(ctrl, "STATUS-VERBOSE"); - if (argc > 0 && os_strcmp(argv[0], "wps") == 0) - return wpa_ctrl_command(ctrl, "STATUS-WPS"); - return wpa_ctrl_command(ctrl, "STATUS"); + int verbose = argc > 0 && os_strcmp(argv[0], "verbose") == 0; + return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS"); } @@ -1930,7 +1927,10 @@ static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[]) if (argc == 0) return wpa_ctrl_command(ctrl, "P2P_FIND"); - if (argc > 1) + if (argc > 2) + res = os_snprintf(cmd, sizeof(cmd), "P2P_FIND %s %s %s", + argv[0], argv[1], argv[2]); + else if (argc > 1) res = os_snprintf(cmd, sizeof(cmd), "P2P_FIND %s %s", argv[0], argv[1]); else @@ -2670,13 +2670,6 @@ static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc, } -static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "REAUTHENTICATE"); -} - - enum wpa_cli_cmd_flags { cli_cmd_flag_none = 0x00, cli_cmd_flag_sensitive = 0x01 @@ -3019,8 +3012,6 @@ static struct wpa_cli_cmd wpa_cli_commands[] = { { "signal_poll", wpa_cli_cmd_signal_poll, cli_cmd_flag_none, "= get signal parameters" }, - { "reauthenticate", wpa_cli_cmd_reauthenticate, cli_cmd_flag_none, - "= trigger IEEE 802.1X/EAPOL reauthentication" }, { NULL, NULL, cli_cmd_flag_none, NULL } }; @@ -3286,16 +3277,10 @@ static void wpa_cli_action_process(const char *msg) wpa_cli_exec(action_file, ctrl_ifname, pos); } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) { wpa_cli_exec(action_file, ctrl_ifname, pos); - } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) { - wpa_cli_exec(action_file, ctrl_ifname, pos); } else if (str_match(pos, WPS_EVENT_SUCCESS)) { wpa_cli_exec(action_file, ctrl_ifname, pos); } else if (str_match(pos, WPS_EVENT_FAIL)) { wpa_cli_exec(action_file, ctrl_ifname, pos); - } else if (str_match(pos, AP_STA_CONNECTED)) { - wpa_cli_exec(action_file, ctrl_ifname, pos); - } else if (str_match(pos, AP_STA_DISCONNECTED)) { - wpa_cli_exec(action_file, ctrl_ifname, pos); } else if (str_match(pos, WPA_EVENT_TERMINATING)) { printf("wpa_supplicant is terminating - stop monitoring\n"); wpa_cli_quit = 1; diff --git a/wpa_supplicant/wpa_gui-qt4/scanresults.cpp b/wpa_supplicant/wpa_gui-qt4/scanresults.cpp index f75f02a..459aa8c 100644 --- a/wpa_supplicant/wpa_gui-qt4/scanresults.cpp +++ b/wpa_supplicant/wpa_gui-qt4/scanresults.cpp @@ -15,7 +15,6 @@ #include #include "scanresults.h" -#include "signalbar.h" #include "wpagui.h" #include "networkconfig.h" @@ -34,7 +33,6 @@ ScanResults::ScanResults(QWidget *parent, const char *, bool, Qt::WFlags) wpagui = NULL; scanResultsWidget->setItemsExpandable(FALSE); scanResultsWidget->setRootIsDecorated(FALSE); - scanResultsWidget->setItemDelegate(new SignalBar(scanResultsWidget)); } @@ -93,7 +91,7 @@ void ScanResults::updateResults() bssid = (*it).mid(pos); else if ((*it).startsWith("freq=")) freq = (*it).mid(pos); - else if ((*it).startsWith("level=")) + else if ((*it).startsWith("qual=")) signal = (*it).mid(pos); else if ((*it).startsWith("flags=")) flags = (*it).mid(pos); diff --git a/wpa_supplicant/wpa_gui-qt4/signalbar.cpp b/wpa_supplicant/wpa_gui-qt4/signalbar.cpp deleted file mode 100644 index f2688d5..0000000 --- a/wpa_supplicant/wpa_gui-qt4/signalbar.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * wpa_gui - SignalBar class - * Copyright (c) 2011, Kel Modderman - * - * 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 -#include - -#include "signalbar.h" - - -SignalBar::SignalBar(QObject *parent) - : QStyledItemDelegate(parent) -{ -} - - -SignalBar::~SignalBar() -{ -} - - -void SignalBar::paint(QPainter *painter, - const QStyleOptionViewItem &option, - const QModelIndex &index) const -{ - QStyleOptionProgressBar opts; - int signal; - - if (index.column() != 3) { - QStyledItemDelegate::paint(painter, option, index); - return; - } - - if (index.data().toInt() > 0) - signal = 0 - (256 - index.data().toInt()); - else - signal = index.data().toInt(); - - opts.minimum = -95; - opts.maximum = -35; - if (signal < opts.minimum) - opts.progress = opts.minimum; - else if (signal > opts.maximum) - opts.progress = opts.maximum; - else - opts.progress = signal; - - opts.text = QString::number(signal) + " dBm"; - opts.textVisible = true; - opts.rect = option.rect; - - QApplication::style()->drawControl(QStyle::CE_ProgressBar, - &opts, painter); -} diff --git a/wpa_supplicant/wpa_gui-qt4/signalbar.h b/wpa_supplicant/wpa_gui-qt4/signalbar.h deleted file mode 100644 index 3d5dec1..0000000 --- a/wpa_supplicant/wpa_gui-qt4/signalbar.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * wpa_gui - SignalBar class - * Copyright (c) 2011, Kel Modderman - * - * 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 SIGNALBAR_H -#define SIGNALBAR_H - -#include -#include - -class SignalBar : public QStyledItemDelegate -{ - Q_OBJECT - -public: - SignalBar(QObject *parent = 0); - ~SignalBar(); - - virtual void paint(QPainter *painter, - const QStyleOptionViewItem &option, - const QModelIndex &index) const ; -}; - -#endif /* SIGNALBAR_H */ diff --git a/wpa_supplicant/wpa_gui-qt4/wpa_gui.pro b/wpa_supplicant/wpa_gui-qt4/wpa_gui.pro index 3c81929..85848d7 100644 --- a/wpa_supplicant/wpa_gui-qt4/wpa_gui.pro +++ b/wpa_supplicant/wpa_gui-qt4/wpa_gui.pro @@ -34,7 +34,6 @@ HEADERS += wpamsg.h \ wpagui.h \ eventhistory.h \ scanresults.h \ - signalbar.h \ userdatarequest.h \ networkconfig.h \ addinterface.h \ @@ -45,7 +44,6 @@ SOURCES += main.cpp \ wpagui.cpp \ eventhistory.cpp \ scanresults.cpp \ - signalbar.cpp \ userdatarequest.cpp \ networkconfig.cpp \ addinterface.cpp \ diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c old mode 100644 new mode 100755 index d04d32b..9d9510b --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1,6 +1,6 @@ /* * WPA Supplicant - * Copyright (c) 2003-2011, Jouni Malinen + * Copyright (c) 2003-2012, Jouni Malinen * * 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 @@ -54,7 +54,7 @@ const char *wpa_supplicant_version = "wpa_supplicant v" VERSION_STR "\n" -"Copyright (c) 2003-2011, Jouni Malinen and contributors"; +"Copyright (c) 2003-2012, Jouni Malinen and contributors"; const char *wpa_supplicant_license = "This program is free software. You can distribute it and/or modify it\n" @@ -458,7 +458,7 @@ void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s, } -static void free_hw_features(struct wpa_supplicant *wpa_s) +void free_hw_features(struct wpa_supplicant *wpa_s) { int i; if (wpa_s->hw.modes == NULL) @@ -1183,7 +1183,9 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, return -1; } - if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) { + if (ssid->key_mgmt & + (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK | WPA_KEY_MGMT_PSK_SHA256)) + { wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN); #ifndef CONFIG_NO_PBKDF2 if (bss && ssid->bssid_set && ssid->ssid_len == 0 && @@ -1325,7 +1327,11 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) || wpa_bss_get_ie(bss, WLAN_EID_RSN)) && - wpa_key_mgmt_wpa(ssid->key_mgmt)) { + (ssid->key_mgmt & (WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_PSK | + WPA_KEY_MGMT_FT_IEEE8021X | + WPA_KEY_MGMT_FT_PSK | + WPA_KEY_MGMT_IEEE8021X_SHA256 | + WPA_KEY_MGMT_PSK_SHA256))) { int try_opportunistic; try_opportunistic = ssid->proactive_key_caching && (ssid->proto & WPA_PROTO_RSN); @@ -1340,7 +1346,11 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, "key management and encryption suites"); return; } - } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) { + } else if (ssid->key_mgmt & + (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_IEEE8021X | + WPA_KEY_MGMT_WPA_NONE | WPA_KEY_MGMT_FT_PSK | + WPA_KEY_MGMT_FT_IEEE8021X | WPA_KEY_MGMT_PSK_SHA256 | + WPA_KEY_MGMT_IEEE8021X_SHA256)) { wpa_ie_len = sizeof(wpa_ie); if (wpa_supplicant_set_suites(wpa_s, NULL, ssid, wpa_ie, &wpa_ie_len)) { @@ -1377,11 +1387,10 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, u8 *pos; size_t len; int res; - int p2p_group; - p2p_group = wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_CAPABLE; pos = wpa_ie + wpa_ie_len; len = sizeof(wpa_ie) - wpa_ie_len; - res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len, p2p_group); + res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len, + ssid->p2p_group); if (res >= 0) wpa_ie_len += res; } @@ -1768,10 +1777,13 @@ void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s, struct wpa_bss *selected_bss; #endif struct wpa_ssid *other_ssid; + int disconnected = 0; - if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) + if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) { wpa_supplicant_disassociate( wpa_s, WLAN_REASON_DEAUTH_LEAVING); + disconnected = 1; + } /* * Mark all other networks disabled or mark all networks enabled if no @@ -2059,8 +2071,11 @@ static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s, for (i = 0; wpa_drivers[i]; i++) { if (os_strlen(wpa_drivers[i]->name) == len && os_strncmp(driver, wpa_drivers[i]->name, len) == - 0) - return select_driver(wpa_s, i); + 0) { + /* First driver that succeeds wins */ + if (select_driver(wpa_s, i) == 0) + return 0; + } } driver = pos + 1; @@ -2461,7 +2476,6 @@ next_driver: if (wpa_drv_get_capa(wpa_s, &capa) == 0) { wpa_s->drv_capa_known = 1; wpa_s->drv_flags = capa.flags; - wpa_s->probe_resp_offloads = capa.probe_resp_offloads; wpa_s->max_scan_ssids = capa.max_scan_ssids; wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids; wpa_s->sched_scan_supported = capa.sched_scan_supported; @@ -2984,6 +2998,11 @@ void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid) int *freqs = NULL; /* + * Remove possible authentication timeout since the connection failed. + */ + eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL); + + /* * Add the failed BSSID into the blacklist and speed up next scan * attempt if there could be other APs that could accept association. * The current blacklist count indicates how many times we have tried diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 5469129..9698c68 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -337,16 +337,8 @@ struct wpa_supplicant { int scan_runs; /* number of scan runs since WPS was started */ int *next_scan_freqs; int scan_interval; /* time in sec between scans to find suitable AP */ - int normal_scans; /* normal scans run before sched_scan */ unsigned int drv_flags; - - /* - * A bitmap of supported protocols for probe response offload. See - * struct wpa_driver_capa in driver.h - */ - unsigned int probe_resp_offloads; - int max_scan_ssids; int max_sched_scan_ssids; int sched_scan_supported; @@ -518,8 +510,6 @@ struct wpa_supplicant { u16 num_modes; u16 flags; } hw; - - int pno; }; @@ -568,6 +558,7 @@ int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s, int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level, int debug_timestamp, int debug_show_keys); +void free_hw_features(struct wpa_supplicant *wpa_s); void wpa_show_license(void); diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c index 870aff5..b0dafe4 100644 --- a/wpa_supplicant/wps_supplicant.c +++ b/wpa_supplicant/wps_supplicant.c @@ -77,8 +77,10 @@ int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s) if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS && wpa_s->current_ssid && !(wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS)) { int disabled = wpa_s->current_ssid->disabled; + unsigned int freq = wpa_s->assoc_freq; wpa_printf(MSG_DEBUG, "WPS: Network configuration replaced - " - "try to associate with the received credential"); + "try to associate with the received credential " + "(freq=%u)", freq); wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING); if (disabled) { @@ -87,8 +89,7 @@ int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s) return 1; } wpa_s->after_wps = 5; - wpa_s->wps_freq = wpa_s->assoc_freq; - wpa_s->normal_scans = 0; + wpa_s->wps_freq = freq; wpa_s->reassociate = 1; wpa_supplicant_req_scan(wpa_s, 0, 0); return 1; @@ -664,6 +665,8 @@ static void wpa_supplicant_wps_event(void *ctx, enum wps_event event, wpa_supplicant_wps_event_er_set_sel_reg(wpa_s, &data->set_sel_reg); break; + case WPS_EV_AP_PIN_SUCCESS: + break; } } @@ -819,7 +822,6 @@ static void wpas_wps_reassoc(struct wpa_supplicant *wpa_s, wpa_s->disconnected = 0; wpa_s->reassociate = 1; wpa_s->scan_runs = 0; - wpa_s->normal_scans = 0; wpa_s->wps_success = 0; wpa_s->blacklist_cleared = 0; wpa_supplicant_req_scan(wpa_s, 0, 0); -- 2.7.4