summaryrefslogtreecommitdiffstats
path: root/contrib/wpa_supplicant
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2006-03-07 05:44:45 +0000
committersam <sam@FreeBSD.org>2006-03-07 05:44:45 +0000
commitf87f3cf9d3ac68ade33194941f85722ffdff2195 (patch)
tree72b7a4837fa3c101b02d8b1b2b0cc478c8b033e3 /contrib/wpa_supplicant
parent8b3f1ba26b4b0c34e27cf045b5873f791d667e6e (diff)
downloadFreeBSD-src-f87f3cf9d3ac68ade33194941f85722ffdff2195.zip
FreeBSD-src-f87f3cf9d3ac68ade33194941f85722ffdff2195.tar.gz
resolve merge conflicts
MFC after: 2 weeks
Diffstat (limited to 'contrib/wpa_supplicant')
-rw-r--r--contrib/wpa_supplicant/FREEBSD-Xlist4
-rw-r--r--contrib/wpa_supplicant/common.h90
-rw-r--r--contrib/wpa_supplicant/developer.txt458
-rw-r--r--contrib/wpa_supplicant/events.c15
-rw-r--r--contrib/wpa_supplicant/hostap_common.h557
-rw-r--r--contrib/wpa_supplicant/wpa_ctrl.c18
-rw-r--r--contrib/wpa_supplicant/wpa_supplicant.c2021
7 files changed, 964 insertions, 2199 deletions
diff --git a/contrib/wpa_supplicant/FREEBSD-Xlist b/contrib/wpa_supplicant/FREEBSD-Xlist
index 7770dc5..720ff2d 100644
--- a/contrib/wpa_supplicant/FREEBSD-Xlist
+++ b/contrib/wpa_supplicant/FREEBSD-Xlist
@@ -12,7 +12,9 @@ driver_prism54.c
driver_test.c
driver_wext.c
driver_wext.h
-l2_packet.c
+l2_packet_freebsd.c
+l2_packet_linux.c
+l2_packet_pcap.c
ndis_events.cpp
priv_netlink.h
win_if_list.c
diff --git a/contrib/wpa_supplicant/common.h b/contrib/wpa_supplicant/common.h
index a075e51..eab0410 100644
--- a/contrib/wpa_supplicant/common.h
+++ b/contrib/wpa_supplicant/common.h
@@ -1,4 +1,18 @@
-/* $FreeBSD$ */
+/*
+ * wpa_supplicant/hostapd / common helper functions, etc.
+ * Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ *
+ * $FreeBSD$
+ */
#ifndef COMMON_H
#define COMMON_H
@@ -6,8 +20,9 @@
#ifdef __linux__
#include <endian.h>
#include <byteswap.h>
-#endif
-#ifdef __FreeBSD__
+#endif /* __linux__ */
+
+#if defined(__FreeBSD__) || defined(__NetBSD__)
#include <sys/types.h>
#include <sys/endian.h>
#define __BYTE_ORDER _BYTE_ORDER
@@ -16,10 +31,9 @@
#define bswap_16 bswap16
#define bswap_32 bswap32
#define bswap_64 bswap64
-#endif
+#endif /* defined(__FreeBSD__) || defined(__NetBSD__) */
#ifdef CONFIG_NATIVE_WINDOWS
-#include <winsock.h>
#include <winsock2.h>
static inline int daemon(int nochdir, int noclose)
@@ -56,6 +70,18 @@ struct timezone {
int gettimeofday(struct timeval *tv, struct timezone *tz);
+static inline long int random(void)
+{
+ return rand();
+}
+
+typedef int gid_t;
+typedef int socklen_t;
+
+#ifndef MSG_DONTWAIT
+#define MSG_DONTWAIT 0 /* not supported */
+#endif
+
#endif /* CONFIG_NATIVE_WINDOWS */
#if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS)
@@ -106,6 +132,21 @@ static inline unsigned int wpa_swap_32(unsigned int v)
#endif /* __CYGWIN__ */
+/* Macros for handling unaligned 16-bit variables */
+#define WPA_GET_BE16(a) ((u16) (((a)[0] << 8) | (a)[1]))
+#define WPA_PUT_BE16(a, val) \
+ do { \
+ (a)[0] = ((u16) (val)) >> 8; \
+ (a)[1] = ((u16) (val)) & 0xff; \
+ } while (0)
+
+#define WPA_GET_LE16(a) ((u16) (((a)[1] << 8) | (a)[0]))
+#define WPA_PUT_LE16(a, val) \
+ do { \
+ (a)[1] = ((u16) (val)) >> 8; \
+ (a)[0] = ((u16) (val)) & 0xff; \
+ } while (0)
+
#ifndef ETH_ALEN
#define ETH_ALEN 6
@@ -136,6 +177,26 @@ void fprint_char(FILE *f, char c);
enum { MSG_MSGDUMP, MSG_DEBUG, MSG_INFO, MSG_WARNING, MSG_ERROR };
+#ifdef CONFIG_NO_STDOUT_DEBUG
+
+#define wpa_debug_print_timestamp() do { } while (0)
+#define wpa_printf(args...) do { } while (0)
+#define wpa_hexdump(args...) do { } while (0)
+#define wpa_hexdump_key(args...) do { } while (0)
+#define wpa_hexdump_ascii(args...) do { } while (0)
+#define wpa_hexdump_ascii_key(args...) do { } while (0)
+
+#else /* CONFIG_NO_STDOUT_DEBUG */
+
+/**
+ * wpa_debug_printf_timestamp - Print timestamp for debug output
+ *
+ * This function prints a timestamp in <seconds from 1970>.<microsoconds>
+ * format if debug output has been configured to include timestamps in debug
+ * messages.
+ */
+void wpa_debug_print_timestamp(void);
+
/**
* wpa_printf - conditional printf
* @level: priority level (MSG_*) of the message
@@ -155,11 +216,11 @@ __attribute__ ((format (printf, 2, 3)));
* @level: priority level (MSG_*) of the message
* @title: title of for the message
* @buf: data buffer to be dumped
- * @len: length of the @buf
+ * @len: length of the buf
*
* This function is used to print conditional debugging and error messages. The
* output may be directed to stdout, stderr, and/or syslog based on
- * configuration. The contents of @buf is printed out has hex dump.
+ * configuration. The contents of buf is printed out has hex dump.
*/
void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len);
@@ -168,11 +229,11 @@ void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len);
* @level: priority level (MSG_*) of the message
* @title: title of for the message
* @buf: data buffer to be dumped
- * @len: length of the @buf
+ * @len: length of the buf
*
* This function is used to print conditional debugging and error messages. The
* output may be directed to stdout, stderr, and/or syslog based on
- * configuration. The contents of @buf is printed out has hex dump. This works
+ * configuration. The contents of buf is printed out has hex dump. This works
* like wpa_hexdump(), but by default, does not include secret keys (passwords,
* etc.) in debug output.
*/
@@ -183,11 +244,11 @@ void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len);
* @level: priority level (MSG_*) of the message
* @title: title of for the message
* @buf: data buffer to be dumped
- * @len: length of the @buf
+ * @len: length of the buf
*
* This function is used to print conditional debugging and error messages. The
* output may be directed to stdout, stderr, and/or syslog based on
- * configuration. The contents of @buf is printed out has hex dump with both
+ * configuration. The contents of buf is printed out has hex dump with both
* the hex numbers and ASCII characters (for printable range) are shown. 16
* bytes per line will be shown.
*/
@@ -199,11 +260,11 @@ void wpa_hexdump_ascii(int level, const char *title, const u8 *buf,
* @level: priority level (MSG_*) of the message
* @title: title of for the message
* @buf: data buffer to be dumped
- * @len: length of the @buf
+ * @len: length of the buf
*
* This function is used to print conditional debugging and error messages. The
* output may be directed to stdout, stderr, and/or syslog based on
- * configuration. The contents of @buf is printed out has hex dump with both
+ * configuration. The contents of buf is printed out has hex dump with both
* the hex numbers and ASCII characters (for printable range) are shown. 16
* bytes per line will be shown. This works like wpa_hexdump_ascii(), but by
* default, does not include secret keys (passwords, etc.) in debug output.
@@ -211,6 +272,9 @@ void wpa_hexdump_ascii(int level, const char *title, const u8 *buf,
void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf,
size_t len);
+#endif /* CONFIG_NO_STDOUT_DEBUG */
+
+
#ifdef EAPOL_TEST
#define WPA_ASSERT(a) \
do { \
diff --git a/contrib/wpa_supplicant/developer.txt b/contrib/wpa_supplicant/developer.txt
deleted file mode 100644
index bc5b346..0000000
--- a/contrib/wpa_supplicant/developer.txt
+++ /dev/null
@@ -1,458 +0,0 @@
-Developer notes for wpa_supplicant
-==================================
-
-The design goal for wpa_supplicant was to use hardware, driver, and OS
-independent, portable C code for all WPA functionality. All
-hardware/driver specific functionality is in separate files that
-implement a well-defined driver API.
-
-The goal of this file and the comments in the header files is to give
-enough information for other developers to be able to port the example
-code. If any information is missing, feel free to contact Jouni Malinen
-<jkmaline@cc.hut.fi> for more information. Contributions as patch files
-are also very welcome at the same address.
-
-Structure of the source code
-----------------------------
-
-Program initialization, main control loop and event handling is
-implemented in wpa_supplicant.c. WPA state machines and 4-Way/Group
-Key Handshake processing in in wpa.c. IEEE 802.1X/EAPOL processing and
-state machines are in eapol_sm.c. EAP state machine is in eap.c. EAP
-methods for the internal EAP peer are in eap_*.c. Parser for the
-configuration file is implemented in config.c.
-
-Driver interface API is defined in driver.h and all hardware/driver
-dependent functionality is implemented in driver_*.c (see below).
-
-
-Generic helper functions
-------------------------
-
-wpa_supplicant uses generic helper functions some of which are shared
-with with hostapd. The following C files are currently used:
-
-eloop.[ch]
- event loop (select() loop with registerable timeouts, socket read
- callbacks, and signal callbacks)
-
-common.[ch]
- common helper functions
-
-defs.h
- definitions shared by multiple files
-
-l2_packet.[ch]
- Layer 2 (link) access wrapper (includes native Linux implementation
- and wrappers for libdnet/libpcap)
-
-pcsc_funcs.[ch]
- Wrapper for PC/SC lite SIM and smart card readers
-
-
-Cryptographic functions
------------------------
-
-md5.c
- MD5 (replaced with openssl/crypto if TLS support is included)
- HMAC-MD5 (keyed checksum for message authenticity validation)
-
-rc4.c
- RC4 (broadcast/default key encryption)
-
-sha1.c
- SHA-1 (replaced with openssl/crypto if TLS support is included)
- HMAC-SHA-1 (keyed checksum for message authenticity validation)
- PRF-SHA-1 (pseudorandom (key/nonce generation) function)
- PBKDF2-SHA-1 (ASCII passphrase to shared secret)
- T-PRF (for EAP-FAST)
- TLS-PRF (RFC 2246)
-
-aes_wrap.[ch], aes.c
- AES
- AES Key Wrap Algorithm with 128-bit KEK, RFC3394 (broadcast/default
- key encryption)
- One-Key CBC MAC (OMAC1) hash with AES-128
- AES-128 CTR mode encryption
- AES-128 EAX mode encryption/decryption
- AES-128 CBC
-
-crypto.[ch]
- Wrapper functions for libcrypto (MD4 and DES)
-
-ms_funcs.[ch]
- Helper functions for MSCHAPV2 and LEAP
-
-tls.h
- Definition of TLS library wrapper
-
-tls_none.c
- Dummy implementation of TLS library wrapper for cases where TLS
- functionality is not included.
-
-tls_openssl.c
- TLS library wrapper for openssl
-
-
-Configuration
--------------
-
-config_ssid.h
- Definition of per network configuration items
-
-config.h
- Definition of the wpa_supplicant configuration
-
-config.c
- Configuration file parser
-
-
-Control interface
------------------
-
-wpa_supplicant has a control interface that can be used to get status
-information and manage operations from external programs. An example,
-command line interface, wpa_cli, for this interface is included in the
-wpa_supplicant distribution.
-
-ctrl_iface.[ch]
- wpa_supplicant-side of the control interface
-
-wpa_ctrl.[ch]
- Library functions for external programs to provide access to the
- wpa_supplicant control interface
-
-wpa_cli.c
- Example program for using wpa_supplicant control interface
-
-
-EAP peer
---------
-
-eap.[ch]
- EAP state machine
-
-eap_defs.h
- Common EAP definitions
-
-eap_i.h
- Internal definitions for EAP state machine and EAP methods
-
-eap_sim_common.[ch]
- Common code for EAP-SIM and EAP-AKA
-
-eap_tls_common.[ch]
- Common code for EAP-PEAP, EAP-TTLS, and EAP-FAST
-
-eap_tlv.[ch]
- EAP-TLV code for EAP-PEAP and EAP-FAST
-
-eap_{aka,fast,gtc,leap,md5,mschapv2,otp,peap,psk,sim,tls,ttls}.c
- EAP method implementations
-
-
-EAPOL supplicant
-----------------
-
-eapol_sm.[ch]
- EAPOL supplicant state machine and IEEE 802.1X processing
-
-
-Windows port
-------------
-
-ndis_events.cpp
- External program for receiving NdisMIndicateStatus() events and
- delivering them to wpa_supplicant in more easier to use form
-
-win_if_list.c
- External program for listing current network interface
-
-
-Test programs
--------------
-
-radius_client.[ch]
- RADIUS authentication client implementation for eapol_test
-
-eapol_test.c
- Standalone EAP testing tool with integrated RADIUS authentication
- client
-
-preauth_test.c
- Standalone RSN pre-authentication tool
-
-
-wpa_supplicant.c
-----------------
-
-main()
-- parse command line
-- call config file parser
-- initialize Supplicant data structures
-- call functions to initialize WPA support in the driver
-- initialize event loop
-- cleanup when exiting
-
-wpa_supplicant_dot1x_receive()
-- receive master session key update from Xsupplicant (optional)
-
-wpa_supplicant_get_beacon_ie()
-
-wpa_supplicant_deauthenticate()
-
-wpa_supplicant_disassociate()
-
-wpa_supplicant_scan()
-
-wpa_supplicant_reconfig()
-- SIGHUP signal processing
-
-wpa_supplicant_terminate()
-- SIGINT and SIGTERM processing
-
-wpa_supplicant_reload_configuration()
-
-wpa_supplicant_event()
-- receive driver events (through driver wrapper functions)
- * wpa_supplicant_scan_results(): process scan result event, BSS selection
- * wpa_supplicant_associnfo(): process association information event
-
-wpa_supplicant_associate()
-- control association (select cipher and key management suites, initiate
- association)
-
-wpa_supplicant_req_auth_timeout()
-
-wpa_supplicant_cancel_auth_timeout()
-
-wpa_supplicant_req_scan()
-
-wpa_supplicant_cancel_scan()
-
-wpa_supplicant_notify_eapol_done()
-
-wpa_eapol_send()
-- send EAPOL frames
-
-wpa_eapol_send_preauth()
-- send RSN preauthentication frames
-
-wpa_msg()
-- event/debug function
-
-
-wpa_supplicant.h
-----------------
-
-- driver event definition
-- common function definition (e.g., wpa_msg)
-
-
-wpa_supplicant_i.h
-------------------
-- internal definitions for wpa_supplicant; must not be included into
- common code, EAP methods, driver interface implementations
-
-
-wpa.[ch]
---------
-- WPA supplicant state machine and 4-Way/Group Key Handshake processing
-- PMKSA cache and RSN pre-authentication
-
-pmksa_cache_free()
-
-pmksa_cache_get()
-
-pmksa_cache_list()
-
-pmksa_candidate_free()
-
-wpa_parse_wpa_ie()
-- WPA/RSN IE parsing
-
-wpa_gen_wpa_ei()
-- WPA/RSN IE generation
-
-wpa_supplicant_get_ssid()
-
-wpa_supplicant_key_request()
-- trigger function to start key requests
-
-wpa_sm_rx_eapol()
-- WPA processing for received EAPOL-Key frames
- * wpa_supplicant_process_1_of_4() (message 1 of 4-Way Handshake)
- * wpa_supplicant_process_3_of_4() (message 3 of 4-Way Handshake)
- * wpa_supplicant_process_1_of_2() (message 1 of Group Key Handshake)
-
-wpa_supplicant_rx_eapol()
-- l2_packet RX callback for EAPOL frames; sends the frames to WPA and EAPOL
- state machines for further processing
-
-wpa_get_mib()
-
-rsn_preauth_receive()
-- l2_packet RX callback for preauthentication frames
-
-rsn_preauth_eapol_cb()
-- callback function to be called when EAPOL authentication has been completed
- (either successfully or unsuccessfully) for RSN pre-authentication
-
-rsn_preauth_init()
-rsn_preauth_deinit()
-
-pmksa_candidate_add()
-- add a BSSID to PMKSA candidate list
-
-rsn_preauth_scan_results()
-- update RSN pre-authentication candidate list based on scan results
-
-
-Driver wrapper implementation (driver.h, drivers.c)
----------------------------------------------------
-
-All hardware and driver dependent functionality is implemented in as a
-separate C file(s) implementing defined wrapper functions. Other parts
-of the wpa_supplicant are designed to be hardware, driver, and operating
-system independent.
-
-Driver wrappers need to implement whatever calls are used in the
-target operating system/driver for controlling wireless LAN
-devices. As an example, in case of Linux, these are mostly some glue
-code and ioctl() calls and netlink message parsing for Linux Wireless
-Extensions. Since all features required for WPA are not yet included
-in Wireless Extensions, some driver specific code is used in the
-example implementation for Host AP driver. These driver dependent parts
-are to be replaced with generic code once the needed changes are
-included in the Wireless Extensions. After that, all Linux drivers, at
-least in theory, could use the same driver wrapper code.
-
-A driver wrapper needs to implement some or all of the functions
-defined in driver.h (see that file for detailed documentation of the
-functions). Hardware independent parts of wpa_supplicant will call
-these functions to control the driver/wlan card. In addition, support
-for driver events is required. The event callback function,
-wpa_supplicant_event(), and its parameters are documented in
-wpa_supplicant.h. In addition, pointer to the 'struct wpa_driver_ops'
-needs to be registered in drivers.c file.
-
-When porting to other operating systems, driver wrapper should be
-modified to use the native interface of the target OS. It is possible
-that some extra requirements for the interface between the driver
-wrapper and generic wpa_supplicant code are discovered during porting
-to a new operating system. These will be addresses on case by case
-basic by modifying the interface and updating the other driver
-wrappers for this. The goal is to avoid changing this interface
-without very good reasons in order to limit the number of changes
-needed to other wrappers and hardware independent parts of
-wpa_supplicant.
-
-Generic Linux Wireless Extensions functions are implemented in
-driver_wext.c. All Linux driver wrappers can use these when the kernel
-driver supports the generic ioctl()s and wireless events. Driver
-specific functions are implemented in separate C files, e.g.,
-driver_hostap.c. These files need to define struct wpa_driver_ops
-entry that will be used in wpa_supplicant.c when calling driver
-functions. These entries need to be added to the lists in
-wpa_supplicant_set_driver() and usage() functions in wpa_supplicant.c.
-
-In general, it is likely to be useful to first take a look at couple
-of the driver interfaces before starting on implementing a new
-one. driver_hostap.c and driver_wext.c include a complete
-implementation for Linux drivers that use wpa_supplicant-based control
-of WPA IE and roaming. driver_ndis.c (with help from driver_ndis_.c)
-is an example of a complete interface for Windows NDIS interface for
-drivers that generate WPA IE themselves and decide when to roam. These
-example implementations include full support for all security modes.
-
-
-Driver requirements for WPA
----------------------------
-
-WPA introduces new requirements for the device driver. At least some
-of these need to be implemented in order to provide enough support for
-wpa_supplicant.
-
-TKIP/CCMP
-
-WPA requires that the pairwise cipher suite (encryption algorithm for
-unicast data packets) is TKIP or CCMP. These are new encryption
-protocols and thus, the driver will need to be modified to support
-them. Depending on the used wlan hardware, some parts of these may be
-implemented by the hardware/firmware.
-
-Specification for both TKIP and CCMP is available from IEEE (IEEE
-802.11i draft version 3.0). Fully functional, hardware independent
-implementation of both encryption protocols is also available in Host
-AP driver (driver/modules/hostap_{tkip,ccmp}.c).
-
-The driver will also need to provide configuration mechanism to allow
-user space programs to configure TKIP and CCMP. Current Linux Wireless
-Extensions (v16) does not yet support these algorithms or
-individual/non-default keys. Host AP driver has an example of private
-ioctl()s for this. Eventually, this should be replaced with modified
-Linux Wireless Extensions.
-
-Roaming control and scanning support
-
-wpa_supplicant controls AP selections based on the information
-received from Beacon and/or Probe Response frames. This means that the
-driver should support external control for scan process. In case of
-Linux, use of new Wireless Extensions scan support (i.e., 'iwlist
-wlan0 scan') is recommended. The current driver wrapper (driver_wext.c)
-uses this for scan results.
-
-Scan results must also include WPA information element. This is not
-yet defined in Linux Wireless Extensions and Host AP driver uses a
-custom event to provide the full WPA IE (including element id and
-length) as a hex string that is included in the scan results.
-Eventually, this should be defined as a Wireless Extensions ioctl
-that can be used both with scan results and with configuration of WPA IE
-for association request (and Beacon/Probe Response in case of an
-AP/IBSS).
-
-wpa_supplicant needs to also be able to request the driver to
-associate with a specific BSS. Current Host AP driver and matching
-driver_hostap.c wrapper uses following sequence for this
-request. Similar/identical mechanism should be usable also with other
-drivers.
-
-- set WPA IE for AssocReq with private ioctl
-- set SSID with SIOCSIWESSID
-- set channel/frequency with SIOCSIWFREQ
-- set BSSID with SIOCSIWAP
- (this last ioctl will trigger the driver to request association)
-
-WPA IE generation
-
-wpa_supplicant selects which cipher suites and key management suites
-are used. Based on this information, it generates a WPA IE. This is
-provided to the driver interface in the associate call. This does not
-match with Windows NDIS drivers which generate the WPA IE
-themselves.
-
-wpa_supplicant allows Windows NDIS-like behavior by providing the
-selected cipher and key management suites in the associate call. If
-the driver generates its own WPA IE and that differs from the one
-generated by wpa_supplicant, the driver has to inform wpa_supplicant
-about the used WPA IE (i.e., the one it used in (Re)Associate
-Request). This notification is done using EVENT_ASSOCINFO event (see
-wpa_supplicant.h).
-
-Driver events
-
-wpa_supplicant needs to receive event callbacks when certain events
-occur (association, disassociation, Michael MIC failure, scan results
-available, PMKSA caching candidate). These events and the callback
-details are defined in wpa_supplicant.h.
-
-On Linux, association and disassociation can use existing Wireless
-Extensions event that is reporting new AP with SIOCGIWAP
-event. Similarly, completion of scan can be reported with SIOCGIWSCAN
-event.
-
-Michael MIC failure event is not yet included in Wireless Extensions,
-so this needs a custom event. Host AP driver uses custom event with
-following contents: MLME-MICHAELMICFAILURE.indication(keyid=#
-broadcast/unicast addr=addr2). This is the recommended format until
-the event is added to Linux Wireless Extensions.
diff --git a/contrib/wpa_supplicant/events.c b/contrib/wpa_supplicant/events.c
index d8762e9..b1207ba 100644
--- a/contrib/wpa_supplicant/events.c
+++ b/contrib/wpa_supplicant/events.c
@@ -10,6 +10,8 @@
* license.
*
* See README and COPYING for more details.
+ *
+ * $FreeBSD$
*/
#include <stdlib.h>
@@ -698,6 +700,16 @@ wpa_supplicant_event_michael_mic_failure(struct wpa_supplicant *wpa_s,
}
+static int any_interfaces(struct wpa_supplicant *head)
+{
+ struct wpa_supplicant *wpa_s;
+
+ for (wpa_s = head; wpa_s != NULL; wpa_s = wpa_s->next)
+ if (!wpa_s->interface_removed)
+ return 1;
+ return 0;
+}
+
static void
wpa_supplicant_event_interface_status(struct wpa_supplicant *wpa_s,
union wpa_event_data *data)
@@ -722,6 +734,9 @@ wpa_supplicant_event_interface_status(struct wpa_supplicant *wpa_s,
wpa_supplicant_mark_disassoc(wpa_s);
l2_packet_deinit(wpa_s->l2);
wpa_s->l2 = NULL;
+ /* check if last interface */
+ if (!any_interfaces(wpa_s->global->ifaces))
+ eloop_terminate();
break;
}
}
diff --git a/contrib/wpa_supplicant/hostap_common.h b/contrib/wpa_supplicant/hostap_common.h
deleted file mode 100644
index 003ad9a..0000000
--- a/contrib/wpa_supplicant/hostap_common.h
+++ /dev/null
@@ -1,557 +0,0 @@
-#ifndef HOSTAP_COMMON_H
-#define HOSTAP_COMMON_H
-
-#define BIT(x) (1 << (x))
-
-#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
-#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
-
-
-#ifndef ETH_P_PAE
-#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */
-#endif /* ETH_P_PAE */
-
-#define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */
-
-
-
-/* IEEE 802.11 defines */
-
-#define WLAN_FC_PVER (BIT(1) | BIT(0))
-#define WLAN_FC_TODS BIT(8)
-#define WLAN_FC_FROMDS BIT(9)
-#define WLAN_FC_MOREFRAG BIT(10)
-#define WLAN_FC_RETRY BIT(11)
-#define WLAN_FC_PWRMGT BIT(12)
-#define WLAN_FC_MOREDATA BIT(13)
-#define WLAN_FC_ISWEP BIT(14)
-#define WLAN_FC_ORDER BIT(15)
-
-#define WLAN_FC_GET_TYPE(fc) (((fc) & (BIT(3) | BIT(2))) >> 2)
-#define WLAN_FC_GET_STYPE(fc) \
- (((fc) & (BIT(7) | BIT(6) | BIT(5) | BIT(4))) >> 4)
-
-#define WLAN_GET_SEQ_FRAG(seq) ((seq) & (BIT(3) | BIT(2) | BIT(1) | BIT(0)))
-#define WLAN_GET_SEQ_SEQ(seq) \
- (((seq) & (~(BIT(3) | BIT(2) | BIT(1) | BIT(0)))) >> 4)
-
-#define WLAN_FC_TYPE_MGMT 0
-#define WLAN_FC_TYPE_CTRL 1
-#define WLAN_FC_TYPE_DATA 2
-
-/* management */
-#define WLAN_FC_STYPE_ASSOC_REQ 0
-#define WLAN_FC_STYPE_ASSOC_RESP 1
-#define WLAN_FC_STYPE_REASSOC_REQ 2
-#define WLAN_FC_STYPE_REASSOC_RESP 3
-#define WLAN_FC_STYPE_PROBE_REQ 4
-#define WLAN_FC_STYPE_PROBE_RESP 5
-#define WLAN_FC_STYPE_BEACON 8
-#define WLAN_FC_STYPE_ATIM 9
-#define WLAN_FC_STYPE_DISASSOC 10
-#define WLAN_FC_STYPE_AUTH 11
-#define WLAN_FC_STYPE_DEAUTH 12
-
-/* control */
-#define WLAN_FC_STYPE_PSPOLL 10
-#define WLAN_FC_STYPE_RTS 11
-#define WLAN_FC_STYPE_CTS 12
-#define WLAN_FC_STYPE_ACK 13
-#define WLAN_FC_STYPE_CFEND 14
-#define WLAN_FC_STYPE_CFENDACK 15
-
-/* data */
-#define WLAN_FC_STYPE_DATA 0
-#define WLAN_FC_STYPE_DATA_CFACK 1
-#define WLAN_FC_STYPE_DATA_CFPOLL 2
-#define WLAN_FC_STYPE_DATA_CFACKPOLL 3
-#define WLAN_FC_STYPE_NULLFUNC 4
-#define WLAN_FC_STYPE_CFACK 5
-#define WLAN_FC_STYPE_CFPOLL 6
-#define WLAN_FC_STYPE_CFACKPOLL 7
-
-/* Authentication algorithms */
-#define WLAN_AUTH_OPEN 0
-#define WLAN_AUTH_SHARED_KEY 1
-
-#define WLAN_AUTH_CHALLENGE_LEN 128
-
-#define WLAN_CAPABILITY_ESS BIT(0)
-#define WLAN_CAPABILITY_IBSS BIT(1)
-#define WLAN_CAPABILITY_CF_POLLABLE BIT(2)
-#define WLAN_CAPABILITY_CF_POLL_REQUEST BIT(3)
-#define WLAN_CAPABILITY_PRIVACY BIT(4)
-
-/* Status codes */
-#define WLAN_STATUS_SUCCESS 0
-#define WLAN_STATUS_UNSPECIFIED_FAILURE 1
-#define WLAN_STATUS_CAPS_UNSUPPORTED 10
-#define WLAN_STATUS_REASSOC_NO_ASSOC 11
-#define WLAN_STATUS_ASSOC_DENIED_UNSPEC 12
-#define WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG 13
-#define WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION 14
-#define WLAN_STATUS_CHALLENGE_FAIL 15
-#define WLAN_STATUS_AUTH_TIMEOUT 16
-#define WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA 17
-#define WLAN_STATUS_ASSOC_DENIED_RATES 18
-/* 802.11b */
-#define WLAN_STATUS_ASSOC_DENIED_NOSHORT 19
-#define WLAN_STATUS_ASSOC_DENIED_NOPBCC 20
-#define WLAN_STATUS_ASSOC_DENIED_NOAGILITY 21
-/* IEEE 802.11i */
-#define WLAN_STATUS_INVALID_IE 40
-#define WLAN_STATUS_GROUP_CIPHER_NOT_VALID 41
-#define WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID 42
-#define WLAN_STATUS_AKMP_NOT_VALID 43
-#define WLAN_STATUS_UNSUPPORTED_RSN_IE_VERSION 44
-#define WLAN_STATUS_INVALID_RSN_IE_CAPAB 45
-#define WLAN_STATUS_CIPHER_REJECTED_PER_POLICY 46
-
-/* Reason codes */
-#define WLAN_REASON_UNSPECIFIED 1
-#define WLAN_REASON_PREV_AUTH_NOT_VALID 2
-#define WLAN_REASON_DEAUTH_LEAVING 3
-#define WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY 4
-#define WLAN_REASON_DISASSOC_AP_BUSY 5
-#define WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA 6
-#define WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA 7
-#define WLAN_REASON_DISASSOC_STA_HAS_LEFT 8
-#define WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH 9
-/* IEEE 802.11i */
-#define WLAN_REASON_INVALID_IE 13
-#define WLAN_REASON_MICHAEL_MIC_FAILURE 14
-#define WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT 15
-#define WLAN_REASON_GROUP_KEY_UPDATE_TIMEOUT 16
-#define WLAN_REASON_IE_IN_4WAY_DIFFERS 17
-#define WLAN_REASON_GROUP_CIPHER_NOT_VALID 18
-#define WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID 19
-#define WLAN_REASON_AKMP_NOT_VALID 20
-#define WLAN_REASON_UNSUPPORTED_RSN_IE_VERSION 21
-#define WLAN_REASON_INVALID_RSN_IE_CAPAB 22
-#define WLAN_REASON_IEEE_802_1X_AUTH_FAILED 23
-#define WLAN_REASON_CIPHER_SUITE_REJECTED 24
-
-
-/* Information Element IDs */
-#define WLAN_EID_SSID 0
-#define WLAN_EID_SUPP_RATES 1
-#define WLAN_EID_FH_PARAMS 2
-#define WLAN_EID_DS_PARAMS 3
-#define WLAN_EID_CF_PARAMS 4
-#define WLAN_EID_TIM 5
-#define WLAN_EID_IBSS_PARAMS 6
-#define WLAN_EID_CHALLENGE 16
-#define WLAN_EID_RSN 48
-#define WLAN_EID_GENERIC 221
-
-
-/* HFA384X Configuration RIDs */
-#define HFA384X_RID_CNFPORTTYPE 0xFC00
-#define HFA384X_RID_CNFOWNMACADDR 0xFC01
-#define HFA384X_RID_CNFDESIREDSSID 0xFC02
-#define HFA384X_RID_CNFOWNCHANNEL 0xFC03
-#define HFA384X_RID_CNFOWNSSID 0xFC04
-#define HFA384X_RID_CNFOWNATIMWINDOW 0xFC05
-#define HFA384X_RID_CNFSYSTEMSCALE 0xFC06
-#define HFA384X_RID_CNFMAXDATALEN 0xFC07
-#define HFA384X_RID_CNFWDSADDRESS 0xFC08
-#define HFA384X_RID_CNFPMENABLED 0xFC09
-#define HFA384X_RID_CNFPMEPS 0xFC0A
-#define HFA384X_RID_CNFMULTICASTRECEIVE 0xFC0B
-#define HFA384X_RID_CNFMAXSLEEPDURATION 0xFC0C
-#define HFA384X_RID_CNFPMHOLDOVERDURATION 0xFC0D
-#define HFA384X_RID_CNFOWNNAME 0xFC0E
-#define HFA384X_RID_CNFOWNDTIMPERIOD 0xFC10
-#define HFA384X_RID_CNFWDSADDRESS1 0xFC11 /* AP f/w only */
-#define HFA384X_RID_CNFWDSADDRESS2 0xFC12 /* AP f/w only */
-#define HFA384X_RID_CNFWDSADDRESS3 0xFC13 /* AP f/w only */
-#define HFA384X_RID_CNFWDSADDRESS4 0xFC14 /* AP f/w only */
-#define HFA384X_RID_CNFWDSADDRESS5 0xFC15 /* AP f/w only */
-#define HFA384X_RID_CNFWDSADDRESS6 0xFC16 /* AP f/w only */
-#define HFA384X_RID_CNFMULTICASTPMBUFFERING 0xFC17 /* AP f/w only */
-#define HFA384X_RID_UNKNOWN1 0xFC20
-#define HFA384X_RID_UNKNOWN2 0xFC21
-#define HFA384X_RID_CNFWEPDEFAULTKEYID 0xFC23
-#define HFA384X_RID_CNFDEFAULTKEY0 0xFC24
-#define HFA384X_RID_CNFDEFAULTKEY1 0xFC25
-#define HFA384X_RID_CNFDEFAULTKEY2 0xFC26
-#define HFA384X_RID_CNFDEFAULTKEY3 0xFC27
-#define HFA384X_RID_CNFWEPFLAGS 0xFC28
-#define HFA384X_RID_CNFWEPKEYMAPPINGTABLE 0xFC29
-#define HFA384X_RID_CNFAUTHENTICATION 0xFC2A
-#define HFA384X_RID_CNFMAXASSOCSTA 0xFC2B /* AP f/w only */
-#define HFA384X_RID_CNFTXCONTROL 0xFC2C
-#define HFA384X_RID_CNFROAMINGMODE 0xFC2D
-#define HFA384X_RID_CNFHOSTAUTHENTICATION 0xFC2E /* AP f/w only */
-#define HFA384X_RID_CNFRCVCRCERROR 0xFC30
-#define HFA384X_RID_CNFMMLIFE 0xFC31
-#define HFA384X_RID_CNFALTRETRYCOUNT 0xFC32
-#define HFA384X_RID_CNFBEACONINT 0xFC33
-#define HFA384X_RID_CNFAPPCFINFO 0xFC34 /* AP f/w only */
-#define HFA384X_RID_CNFSTAPCFINFO 0xFC35
-#define HFA384X_RID_CNFPRIORITYQUSAGE 0xFC37
-#define HFA384X_RID_CNFTIMCTRL 0xFC40
-#define HFA384X_RID_UNKNOWN3 0xFC41 /* added in STA f/w 0.7.x */
-#define HFA384X_RID_CNFTHIRTY2TALLY 0xFC42 /* added in STA f/w 0.8.0 */
-#define HFA384X_RID_CNFENHSECURITY 0xFC43 /* AP f/w or STA f/w >= 1.6.3 */
-#define HFA384X_RID_CNFDBMADJUST 0xFC46 /* added in STA f/w 1.3.1 */
-#define HFA384X_RID_GENERICELEMENT 0xFC48 /* added in STA f/w 1.7.0;
- * write only */
-#define HFA384X_RID_PROPAGATIONDELAY 0xFC49 /* added in STA f/w 1.7.6 */
-#define HFA384X_RID_GROUPADDRESSES 0xFC80
-#define HFA384X_RID_CREATEIBSS 0xFC81
-#define HFA384X_RID_FRAGMENTATIONTHRESHOLD 0xFC82
-#define HFA384X_RID_RTSTHRESHOLD 0xFC83
-#define HFA384X_RID_TXRATECONTROL 0xFC84
-#define HFA384X_RID_PROMISCUOUSMODE 0xFC85
-#define HFA384X_RID_FRAGMENTATIONTHRESHOLD0 0xFC90 /* AP f/w only */
-#define HFA384X_RID_FRAGMENTATIONTHRESHOLD1 0xFC91 /* AP f/w only */
-#define HFA384X_RID_FRAGMENTATIONTHRESHOLD2 0xFC92 /* AP f/w only */
-#define HFA384X_RID_FRAGMENTATIONTHRESHOLD3 0xFC93 /* AP f/w only */
-#define HFA384X_RID_FRAGMENTATIONTHRESHOLD4 0xFC94 /* AP f/w only */
-#define HFA384X_RID_FRAGMENTATIONTHRESHOLD5 0xFC95 /* AP f/w only */
-#define HFA384X_RID_FRAGMENTATIONTHRESHOLD6 0xFC96 /* AP f/w only */
-#define HFA384X_RID_RTSTHRESHOLD0 0xFC97 /* AP f/w only */
-#define HFA384X_RID_RTSTHRESHOLD1 0xFC98 /* AP f/w only */
-#define HFA384X_RID_RTSTHRESHOLD2 0xFC99 /* AP f/w only */
-#define HFA384X_RID_RTSTHRESHOLD3 0xFC9A /* AP f/w only */
-#define HFA384X_RID_RTSTHRESHOLD4 0xFC9B /* AP f/w only */
-#define HFA384X_RID_RTSTHRESHOLD5 0xFC9C /* AP f/w only */
-#define HFA384X_RID_RTSTHRESHOLD6 0xFC9D /* AP f/w only */
-#define HFA384X_RID_TXRATECONTROL0 0xFC9E /* AP f/w only */
-#define HFA384X_RID_TXRATECONTROL1 0xFC9F /* AP f/w only */
-#define HFA384X_RID_TXRATECONTROL2 0xFCA0 /* AP f/w only */
-#define HFA384X_RID_TXRATECONTROL3 0xFCA1 /* AP f/w only */
-#define HFA384X_RID_TXRATECONTROL4 0xFCA2 /* AP f/w only */
-#define HFA384X_RID_TXRATECONTROL5 0xFCA3 /* AP f/w only */
-#define HFA384X_RID_TXRATECONTROL6 0xFCA4 /* AP f/w only */
-#define HFA384X_RID_CNFSHORTPREAMBLE 0xFCB0
-#define HFA384X_RID_CNFEXCLUDELONGPREAMBLE 0xFCB1
-#define HFA384X_RID_CNFAUTHENTICATIONRSPTO 0xFCB2
-#define HFA384X_RID_CNFBASICRATES 0xFCB3
-#define HFA384X_RID_CNFSUPPORTEDRATES 0xFCB4
-#define HFA384X_RID_CNFFALLBACKCTRL 0xFCB5 /* added in STA f/w 1.3.1 */
-#define HFA384X_RID_WEPKEYDISABLE 0xFCB6 /* added in STA f/w 1.3.1 */
-#define HFA384X_RID_WEPKEYMAPINDEX 0xFCB7 /* ? */
-#define HFA384X_RID_BROADCASTKEYID 0xFCB8 /* ? */
-#define HFA384X_RID_ENTSECFLAGEYID 0xFCB9 /* ? */
-#define HFA384X_RID_CNFPASSIVESCANCTRL 0xFCBA /* added in STA f/w 1.5.0 */
-#define HFA384X_RID_SSNHANDLINGMODE 0xFCBB /* added in STA f/w 1.7.0 */
-#define HFA384X_RID_MDCCONTROL 0xFCBC /* added in STA f/w 1.7.0 */
-#define HFA384X_RID_MDCCOUNTRY 0xFCBD /* added in STA f/w 1.7.0 */
-#define HFA384X_RID_TXPOWERMAX 0xFCBE /* added in STA f/w 1.7.0 */
-#define HFA384X_RID_CNFLFOENABLED 0xFCBF /* added in STA f/w 1.6.3 */
-#define HFA384X_RID_CAPINFO 0xFCC0 /* added in STA f/w 1.7.0 */
-#define HFA384X_RID_LISTENINTERVAL 0xFCC1 /* added in STA f/w 1.7.0 */
-#define HFA384X_RID_SW_ANT_DIV 0xFCC2 /* added in STA f/w 1.7.0; Prism3 */
-#define HFA384X_RID_LED_CTRL 0xFCC4 /* added in STA f/w 1.7.6 */
-#define HFA384X_RID_HFODELAY 0xFCC5 /* added in STA f/w 1.7.6 */
-#define HFA384X_RID_DISALLOWEDBSSID 0xFCC6 /* added in STA f/w 1.8.0 */
-#define HFA384X_RID_TICKTIME 0xFCE0
-#define HFA384X_RID_SCANREQUEST 0xFCE1
-#define HFA384X_RID_JOINREQUEST 0xFCE2
-#define HFA384X_RID_AUTHENTICATESTATION 0xFCE3 /* AP f/w only */
-#define HFA384X_RID_CHANNELINFOREQUEST 0xFCE4 /* AP f/w only */
-#define HFA384X_RID_HOSTSCAN 0xFCE5 /* added in STA f/w 1.3.1 */
-
-/* HFA384X Information RIDs */
-#define HFA384X_RID_MAXLOADTIME 0xFD00
-#define HFA384X_RID_DOWNLOADBUFFER 0xFD01
-#define HFA384X_RID_PRIID 0xFD02
-#define HFA384X_RID_PRISUPRANGE 0xFD03
-#define HFA384X_RID_CFIACTRANGES 0xFD04
-#define HFA384X_RID_NICSERNUM 0xFD0A
-#define HFA384X_RID_NICID 0xFD0B
-#define HFA384X_RID_MFISUPRANGE 0xFD0C
-#define HFA384X_RID_CFISUPRANGE 0xFD0D
-#define HFA384X_RID_CHANNELLIST 0xFD10
-#define HFA384X_RID_REGULATORYDOMAINS 0xFD11
-#define HFA384X_RID_TEMPTYPE 0xFD12
-#define HFA384X_RID_CIS 0xFD13
-#define HFA384X_RID_STAID 0xFD20
-#define HFA384X_RID_STASUPRANGE 0xFD21
-#define HFA384X_RID_MFIACTRANGES 0xFD22
-#define HFA384X_RID_CFIACTRANGES2 0xFD23
-#define HFA384X_RID_PRODUCTNAME 0xFD24 /* added in STA f/w 1.3.1;
- * only Prism2.5(?) */
-#define HFA384X_RID_PORTSTATUS 0xFD40
-#define HFA384X_RID_CURRENTSSID 0xFD41
-#define HFA384X_RID_CURRENTBSSID 0xFD42
-#define HFA384X_RID_COMMSQUALITY 0xFD43
-#define HFA384X_RID_CURRENTTXRATE 0xFD44
-#define HFA384X_RID_CURRENTBEACONINTERVAL 0xFD45
-#define HFA384X_RID_CURRENTSCALETHRESHOLDS 0xFD46
-#define HFA384X_RID_PROTOCOLRSPTIME 0xFD47
-#define HFA384X_RID_SHORTRETRYLIMIT 0xFD48
-#define HFA384X_RID_LONGRETRYLIMIT 0xFD49
-#define HFA384X_RID_MAXTRANSMITLIFETIME 0xFD4A
-#define HFA384X_RID_MAXRECEIVELIFETIME 0xFD4B
-#define HFA384X_RID_CFPOLLABLE 0xFD4C
-#define HFA384X_RID_AUTHENTICATIONALGORITHMS 0xFD4D
-#define HFA384X_RID_PRIVACYOPTIONIMPLEMENTED 0xFD4F
-#define HFA384X_RID_DBMCOMMSQUALITY 0xFD51 /* added in STA f/w 1.3.1 */
-#define HFA384X_RID_CURRENTTXRATE1 0xFD80 /* AP f/w only */
-#define HFA384X_RID_CURRENTTXRATE2 0xFD81 /* AP f/w only */
-#define HFA384X_RID_CURRENTTXRATE3 0xFD82 /* AP f/w only */
-#define HFA384X_RID_CURRENTTXRATE4 0xFD83 /* AP f/w only */
-#define HFA384X_RID_CURRENTTXRATE5 0xFD84 /* AP f/w only */
-#define HFA384X_RID_CURRENTTXRATE6 0xFD85 /* AP f/w only */
-#define HFA384X_RID_OWNMACADDR 0xFD86 /* AP f/w only */
-#define HFA384X_RID_SCANRESULTSTABLE 0xFD88 /* added in STA f/w 0.8.3 */
-#define HFA384X_RID_HOSTSCANRESULTS 0xFD89 /* added in STA f/w 1.3.1 */
-#define HFA384X_RID_AUTHENTICATIONUSED 0xFD8A /* added in STA f/w 1.3.4 */
-#define HFA384X_RID_CNFFAASWITCHCTRL 0xFD8B /* added in STA f/w 1.6.3 */
-#define HFA384X_RID_ASSOCIATIONFAILURE 0xFD8D /* added in STA f/w 1.8.0 */
-#define HFA384X_RID_PHYTYPE 0xFDC0
-#define HFA384X_RID_CURRENTCHANNEL 0xFDC1
-#define HFA384X_RID_CURRENTPOWERSTATE 0xFDC2
-#define HFA384X_RID_CCAMODE 0xFDC3
-#define HFA384X_RID_SUPPORTEDDATARATES 0xFDC6
-#define HFA384X_RID_LFO_VOLT_REG_TEST_RES 0xFDC7 /* added in STA f/w 1.7.1 */
-#define HFA384X_RID_BUILDSEQ 0xFFFE
-#define HFA384X_RID_FWID 0xFFFF
-
-
-struct hfa384x_comp_ident
-{
- u16 id;
- u16 variant;
- u16 major;
- u16 minor;
-} __attribute__ ((packed));
-
-#define HFA384X_COMP_ID_PRI 0x15
-#define HFA384X_COMP_ID_STA 0x1f
-#define HFA384X_COMP_ID_FW_AP 0x14b
-
-struct hfa384x_sup_range
-{
- u16 role;
- u16 id;
- u16 variant;
- u16 bottom;
- u16 top;
-} __attribute__ ((packed));
-
-
-struct hfa384x_build_id
-{
- u16 pri_seq;
- u16 sec_seq;
-} __attribute__ ((packed));
-
-/* FD01 - Download Buffer */
-struct hfa384x_rid_download_buffer
-{
- u16 page;
- u16 offset;
- u16 length;
-} __attribute__ ((packed));
-
-/* BSS connection quality (RID FD43 range, RID FD51 dBm-normalized) */
-struct hfa384x_comms_quality {
- u16 comm_qual; /* 0 .. 92 */
- u16 signal_level; /* 27 .. 154 */
- u16 noise_level; /* 27 .. 154 */
-} __attribute__ ((packed));
-
-
-/* netdevice private ioctls (used, e.g., with iwpriv from user space) */
-
-/* New wireless extensions API - SET/GET convention (even ioctl numbers are
- * root only)
- */
-#define PRISM2_IOCTL_PRISM2_PARAM (SIOCIWFIRSTPRIV + 0)
-#define PRISM2_IOCTL_GET_PRISM2_PARAM (SIOCIWFIRSTPRIV + 1)
-#define PRISM2_IOCTL_WRITEMIF (SIOCIWFIRSTPRIV + 2)
-#define PRISM2_IOCTL_READMIF (SIOCIWFIRSTPRIV + 3)
-#define PRISM2_IOCTL_MONITOR (SIOCIWFIRSTPRIV + 4)
-#define PRISM2_IOCTL_RESET (SIOCIWFIRSTPRIV + 6)
-#define PRISM2_IOCTL_INQUIRE (SIOCIWFIRSTPRIV + 8)
-#define PRISM2_IOCTL_WDS_ADD (SIOCIWFIRSTPRIV + 10)
-#define PRISM2_IOCTL_WDS_DEL (SIOCIWFIRSTPRIV + 12)
-#define PRISM2_IOCTL_SET_RID_WORD (SIOCIWFIRSTPRIV + 14)
-#define PRISM2_IOCTL_MACCMD (SIOCIWFIRSTPRIV + 16)
-#define PRISM2_IOCTL_ADDMAC (SIOCIWFIRSTPRIV + 18)
-#define PRISM2_IOCTL_DELMAC (SIOCIWFIRSTPRIV + 20)
-#define PRISM2_IOCTL_KICKMAC (SIOCIWFIRSTPRIV + 22)
-
-/* following are not in SIOCGIWPRIV list; check permission in the driver code
- */
-#define PRISM2_IOCTL_DOWNLOAD (SIOCDEVPRIVATE + 13)
-#define PRISM2_IOCTL_HOSTAPD (SIOCDEVPRIVATE + 14)
-
-
-/* PRISM2_IOCTL_PRISM2_PARAM ioctl() subtypes: */
-enum {
- /* PRISM2_PARAM_PTYPE = 1, */ /* REMOVED 2003-10-22 */
- PRISM2_PARAM_TXRATECTRL = 2,
- PRISM2_PARAM_BEACON_INT = 3,
- PRISM2_PARAM_PSEUDO_IBSS = 4,
- PRISM2_PARAM_ALC = 5,
- /* PRISM2_PARAM_TXPOWER = 6, */ /* REMOVED 2003-10-22 */
- PRISM2_PARAM_DUMP = 7,
- PRISM2_PARAM_OTHER_AP_POLICY = 8,
- PRISM2_PARAM_AP_MAX_INACTIVITY = 9,
- PRISM2_PARAM_AP_BRIDGE_PACKETS = 10,
- PRISM2_PARAM_DTIM_PERIOD = 11,
- PRISM2_PARAM_AP_NULLFUNC_ACK = 12,
- PRISM2_PARAM_MAX_WDS = 13,
- PRISM2_PARAM_AP_AUTOM_AP_WDS = 14,
- PRISM2_PARAM_AP_AUTH_ALGS = 15,
- PRISM2_PARAM_MONITOR_ALLOW_FCSERR = 16,
- PRISM2_PARAM_HOST_ENCRYPT = 17,
- PRISM2_PARAM_HOST_DECRYPT = 18,
- PRISM2_PARAM_BUS_MASTER_THRESHOLD_RX = 19,
- PRISM2_PARAM_BUS_MASTER_THRESHOLD_TX = 20,
- PRISM2_PARAM_HOST_ROAMING = 21,
- PRISM2_PARAM_BCRX_STA_KEY = 22,
- PRISM2_PARAM_IEEE_802_1X = 23,
- PRISM2_PARAM_ANTSEL_TX = 24,
- PRISM2_PARAM_ANTSEL_RX = 25,
- PRISM2_PARAM_MONITOR_TYPE = 26,
- PRISM2_PARAM_WDS_TYPE = 27,
- PRISM2_PARAM_HOSTSCAN = 28,
- PRISM2_PARAM_AP_SCAN = 29,
- PRISM2_PARAM_ENH_SEC = 30,
- PRISM2_PARAM_IO_DEBUG = 31,
- PRISM2_PARAM_BASIC_RATES = 32,
- PRISM2_PARAM_OPER_RATES = 33,
- PRISM2_PARAM_HOSTAPD = 34,
- PRISM2_PARAM_HOSTAPD_STA = 35,
- PRISM2_PARAM_WPA = 36,
- PRISM2_PARAM_PRIVACY_INVOKED = 37,
- PRISM2_PARAM_TKIP_COUNTERMEASURES = 38,
- PRISM2_PARAM_DROP_UNENCRYPTED = 39,
-};
-
-enum { HOSTAP_ANTSEL_DO_NOT_TOUCH = 0, HOSTAP_ANTSEL_DIVERSITY = 1,
- HOSTAP_ANTSEL_LOW = 2, HOSTAP_ANTSEL_HIGH = 3 };
-
-
-/* PRISM2_IOCTL_MACCMD ioctl() subcommands: */
-enum { AP_MAC_CMD_POLICY_OPEN = 0, AP_MAC_CMD_POLICY_ALLOW = 1,
- AP_MAC_CMD_POLICY_DENY = 2, AP_MAC_CMD_FLUSH = 3,
- AP_MAC_CMD_KICKALL = 4 };
-
-
-/* PRISM2_IOCTL_DOWNLOAD ioctl() dl_cmd: */
-enum {
- PRISM2_DOWNLOAD_VOLATILE = 1 /* RAM */,
- /* Note! Old versions of prism2_srec have a fatal error in CRC-16
- * calculation, which will corrupt all non-volatile downloads.
- * PRISM2_DOWNLOAD_NON_VOLATILE used to be 2, but it is now 3 to
- * prevent use of old versions of prism2_srec for non-volatile
- * download. */
- PRISM2_DOWNLOAD_NON_VOLATILE = 3 /* FLASH */,
- PRISM2_DOWNLOAD_VOLATILE_GENESIS = 4 /* RAM in Genesis mode */,
- /* Persistent versions of volatile download commands (keep firmware
- * data in memory and automatically re-download after hw_reset */
- PRISM2_DOWNLOAD_VOLATILE_PERSISTENT = 5,
- PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT = 6,
-};
-
-struct prism2_download_param {
- u32 dl_cmd;
- u32 start_addr;
- u32 num_areas;
- struct prism2_download_area {
- u32 addr; /* wlan card address */
- u32 len;
- caddr_t ptr; /* pointer to data in user space */
- } data[0];
-};
-
-#define PRISM2_MAX_DOWNLOAD_AREA_LEN 131072
-#define PRISM2_MAX_DOWNLOAD_LEN 262144
-
-
-/* PRISM2_IOCTL_HOSTAPD ioctl() cmd: */
-enum {
- PRISM2_HOSTAPD_FLUSH = 1,
- PRISM2_HOSTAPD_ADD_STA = 2,
- PRISM2_HOSTAPD_REMOVE_STA = 3,
- PRISM2_HOSTAPD_GET_INFO_STA = 4,
- /* REMOVED: PRISM2_HOSTAPD_RESET_TXEXC_STA = 5, */
- PRISM2_SET_ENCRYPTION = 6,
- PRISM2_GET_ENCRYPTION = 7,
- PRISM2_HOSTAPD_SET_FLAGS_STA = 8,
- PRISM2_HOSTAPD_GET_RID = 9,
- PRISM2_HOSTAPD_SET_RID = 10,
- PRISM2_HOSTAPD_SET_ASSOC_AP_ADDR = 11,
- PRISM2_HOSTAPD_SET_GENERIC_ELEMENT = 12,
- PRISM2_HOSTAPD_MLME = 13,
- PRISM2_HOSTAPD_SCAN_REQ = 14,
- PRISM2_HOSTAPD_STA_CLEAR_STATS = 15,
-};
-
-#define PRISM2_HOSTAPD_MAX_BUF_SIZE 1024
-#define PRISM2_HOSTAPD_RID_HDR_LEN \
-((int) (&((struct prism2_hostapd_param *) 0)->u.rid.data))
-#define PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN \
-((int) (&((struct prism2_hostapd_param *) 0)->u.generic_elem.data))
-
-/* Maximum length for algorithm names (-1 for nul termination) used in ioctl()
- */
-#define HOSTAP_CRYPT_ALG_NAME_LEN 16
-
-
-struct prism2_hostapd_param {
- u32 cmd;
- u8 sta_addr[ETH_ALEN];
- union {
- struct {
- u16 aid;
- u16 capability;
- u8 tx_supp_rates;
- } add_sta;
- struct {
- u32 inactive_sec;
- } get_info_sta;
- struct {
- u8 alg[HOSTAP_CRYPT_ALG_NAME_LEN];
- u32 flags;
- u32 err;
- u8 idx;
- u8 seq[8]; /* sequence counter (set: RX, get: TX) */
- u16 key_len;
- u8 key[0];
- } crypt;
- struct {
- u32 flags_and;
- u32 flags_or;
- } set_flags_sta;
- struct {
- u16 rid;
- u16 len;
- u8 data[0];
- } rid;
- struct {
- u8 len;
- u8 data[0];
- } generic_elem;
- struct {
-#define MLME_STA_DEAUTH 0
-#define MLME_STA_DISASSOC 1
- u16 cmd;
- u16 reason_code;
- } mlme;
- struct {
- u8 ssid_len;
- u8 ssid[32];
- } scan_req;
- } u;
-};
-
-#define HOSTAP_CRYPT_FLAG_SET_TX_KEY BIT(0)
-#define HOSTAP_CRYPT_FLAG_PERMANENT BIT(1)
-
-#define HOSTAP_CRYPT_ERR_UNKNOWN_ALG 2
-#define HOSTAP_CRYPT_ERR_UNKNOWN_ADDR 3
-#define HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED 4
-#define HOSTAP_CRYPT_ERR_KEY_SET_FAILED 5
-#define HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED 6
-#define HOSTAP_CRYPT_ERR_CARD_CONF_FAILED 7
-
-
-#endif /* HOSTAP_COMMON_H */
diff --git a/contrib/wpa_supplicant/wpa_ctrl.c b/contrib/wpa_supplicant/wpa_ctrl.c
index 3c79fc4..e7a9a4f 100644
--- a/contrib/wpa_supplicant/wpa_ctrl.c
+++ b/contrib/wpa_supplicant/wpa_ctrl.c
@@ -1,5 +1,5 @@
/*
- * WPA Supplicant - wpa_supplicant control interface library
+ * wpa_supplicant/hostapd control interface library
* Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi>
*
* This program is free software; you can redistribute it and/or modify
@@ -22,6 +22,7 @@
#include <sys/time.h>
#ifndef CONFIG_NATIVE_WINDOWS
#include <sys/socket.h>
+#include <netinet/in.h>
#include <sys/un.h>
#endif /* CONFIG_NATIVE_WINDOWS */
@@ -31,6 +32,15 @@
#endif /* CONFIG_NATIVE_WINDOWS */
+/**
+ * struct wpa_ctrl - Internal structure for control interface library
+ *
+ * This structure is used by the wpa_supplicant/hostapd control interface
+ * library to store internal data. Programs using the library should not touch
+ * this data directly. They can only use the pointer to the data structure as
+ * an identifier for the control interface connection and use this as one of
+ * the arguments for most of the control interface library functions.
+ */
struct wpa_ctrl {
int s;
#ifdef CONFIG_CTRL_IFACE_UDP
@@ -74,7 +84,7 @@ struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
ctrl->dest.sin_family = AF_INET;
ctrl->dest.sin_addr.s_addr = htonl((127 << 24) | 1);
- ctrl->dest.sin_port = htons(9877);
+ ctrl->dest.sin_port = htons(WPA_CTRL_IFACE_PORT);
if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
sizeof(ctrl->dest)) < 0) {
perror("connect");
@@ -124,7 +134,7 @@ void wpa_ctrl_close(struct wpa_ctrl *ctrl)
}
-int wpa_ctrl_request(struct wpa_ctrl *ctrl, char *cmd, size_t cmd_len,
+int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
char *reply, size_t *reply_len,
void (*msg_cb)(char *msg, size_t len))
{
@@ -153,7 +163,7 @@ int wpa_ctrl_request(struct wpa_ctrl *ctrl, char *cmd, size_t cmd_len,
if (msg_cb) {
/* Make sure the message is nul
* terminated. */
- if (res == *reply_len)
+ if ((size_t) res == *reply_len)
res = (*reply_len) - 1;
reply[res] = '\0';
msg_cb(reply, res);
diff --git a/contrib/wpa_supplicant/wpa_supplicant.c b/contrib/wpa_supplicant/wpa_supplicant.c
index a1524ab..2b2d6e0 100644
--- a/contrib/wpa_supplicant/wpa_supplicant.c
+++ b/contrib/wpa_supplicant/wpa_supplicant.c
@@ -1,6 +1,6 @@
/*
* WPA Supplicant
- * Copyright (c) 2003-2005, Jouni Malinen <jkmaline@cc.hut.fi>
+ * Copyright (c) 2003-2006, Jouni Malinen <jkmaline@cc.hut.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -19,27 +19,16 @@
#include <stdarg.h>
#include <unistd.h>
#include <string.h>
-#include <sys/time.h>
#include <time.h>
#include <signal.h>
-#include <sys/types.h>
-#ifndef CONFIG_NATIVE_WINDOWS
-#include <sys/socket.h>
-#include <sys/un.h>
-#endif /* CONFIG_NATIVE_WINDOWS */
-#include <unistd.h>
-#include <ctype.h>
#ifndef CONFIG_NATIVE_WINDOWS
#include <netinet/in.h>
#endif /* CONFIG_NATIVE_WINDOWS */
-#include <fcntl.h>
-#define OPENSSL_DISABLE_OLD_DES_SUPPORT
#include "common.h"
#include "eapol_sm.h"
#include "eap.h"
#include "wpa.h"
-#include "driver.h"
#include "eloop.h"
#include "wpa_supplicant.h"
#include "config.h"
@@ -48,12 +37,14 @@
#include "ctrl_iface.h"
#include "pcsc_funcs.h"
#include "version.h"
+#include "preauth.h"
+#include "wpa_ctrl.h"
-static const char *wpa_supplicant_version =
+const char *wpa_supplicant_version =
"wpa_supplicant v" VERSION_STR "\n"
-"Copyright (c) 2003-2005, Jouni Malinen <jkmaline@cc.hut.fi> and contributors";
+"Copyright (c) 2003-2006, Jouni Malinen <jkmaline@cc.hut.fi> and contributors";
-static const char *wpa_supplicant_license =
+const char *wpa_supplicant_license =
"This program is free software. You can distribute it and/or modify it\n"
"under the terms of the GNU General Public License version 2.\n"
"\n"
@@ -65,7 +56,8 @@ static const char *wpa_supplicant_license =
#endif /* EAP_TLS_FUNCS */
;
-static const char *wpa_supplicant_full_license =
+#ifndef CONFIG_NO_STDOUT_DEBUG
+const char *wpa_supplicant_full_license =
"This program is free software; you can redistribute it and/or modify\n"
"it under the terms of the GNU General Public License version 2 as\n"
"published by the Free Software Foundation.\n"
@@ -109,25 +101,15 @@ static const char *wpa_supplicant_full_license =
"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
"\n";
+#endif /* CONFIG_NO_STDOUT_DEBUG */
extern struct wpa_driver_ops *wpa_supplicant_drivers[];
-static void wpa_supplicant_scan_results(struct wpa_supplicant *wpa_s);
-static int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s,
- int wait_for_interface);
-static void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
- struct wpa_scan_result *bss,
- struct wpa_ssid *ssid);
-static int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
- struct wpa_scan_result *bss,
- struct wpa_ssid *ssid,
- u8 *wpa_ie, int *wpa_ie_len);
-
-
extern int wpa_debug_level;
extern int wpa_debug_show_keys;
extern int wpa_debug_timestamp;
+static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx);
void wpa_msg(struct wpa_supplicant *wpa_s, int level, char *fmt, ...)
{
@@ -154,13 +136,69 @@ void wpa_msg(struct wpa_supplicant *wpa_s, int level, char *fmt, ...)
}
-int wpa_eapol_send(void *ctx, int type, u8 *buf, size_t len)
+static u8 * wpa_alloc_eapol(const struct wpa_supplicant *wpa_s, u8 type,
+ const void *data, u16 data_len,
+ size_t *msg_len, void **data_pos)
+{
+ struct ieee802_1x_hdr *hdr;
+
+ *msg_len = sizeof(*hdr) + data_len;
+ hdr = malloc(*msg_len);
+ if (hdr == NULL)
+ return NULL;
+
+ hdr->version = wpa_s->conf->eapol_version;
+ hdr->type = type;
+ hdr->length = htons(data_len);
+
+ if (data)
+ memcpy(hdr + 1, data, data_len);
+ else
+ memset(hdr + 1, 0, data_len);
+
+ if (data_pos)
+ *data_pos = hdr + 1;
+
+ return (u8 *) hdr;
+}
+
+
+/**
+ * wpa_ether_send - Send Ethernet frame
+ * @wpa_s: pointer to wpa_supplicant data
+ * @dest: Destination MAC address
+ * @proto: Ethertype
+ * @buf: Frame payload starting from IEEE 802.1X header
+ * @len: Frame payload length
+ */
+int wpa_ether_send(struct wpa_supplicant *wpa_s, const u8 *dest, u16 proto,
+ const u8 *buf, size_t len)
+{
+ if (wpa_s->l2) {
+ return l2_packet_send(wpa_s->l2, dest, proto, buf, len);
+ }
+
+ return wpa_drv_send_eapol(wpa_s, dest, proto, buf, len);
+}
+
+
+#ifdef IEEE8021X_EAPOL
+/**
+ * wpa_supplicant_eapol_send - Send IEEE 802.1X EAPOL packet to Authenticator
+ * @ctx: pointer to wpa_supplicant data
+ * @type: IEEE 802.1X packet type (IEEE802_1X_TYPE_*)
+ * @buf: EAPOL payload (after IEEE 802.1X header)
+ * @len: EAPOL payload length
+ *
+ * This function adds Ethernet and IEEE 802.1X header and sends the EAPOL frame
+ * to the current Authenticator.
+ */
+static int wpa_supplicant_eapol_send(void *ctx, int type, const u8 *buf,
+ size_t len)
{
struct wpa_supplicant *wpa_s = ctx;
u8 *msg, *dst, bssid[ETH_ALEN];
size_t msglen;
- struct l2_ethhdr *ethhdr;
- struct ieee802_1x_hdr *hdr;
int res;
/* TODO: could add l2_packet_sendmsg that allows fragments to avoid
@@ -177,7 +215,8 @@ int wpa_eapol_send(void *ctx, int type, u8 *buf, size_t len)
return -1;
}
- if (wpa_s->cur_pmksa && type == IEEE802_1X_TYPE_EAPOL_START) {
+ if (pmksa_cache_get_current(wpa_s->wpa) &&
+ type == IEEE802_1X_TYPE_EAPOL_START) {
/* Trying to use PMKSA caching - do not send EAPOL-Start frames
* since they will trigger full EAPOL authentication. */
wpa_printf(MSG_DEBUG, "RSN: PMKSA caching - do not send "
@@ -207,64 +246,12 @@ int wpa_eapol_send(void *ctx, int type, u8 *buf, size_t len)
dst = wpa_s->bssid;
}
- msglen = sizeof(*ethhdr) + sizeof(*hdr) + len;
- msg = malloc(msglen);
+ msg = wpa_alloc_eapol(wpa_s, type, buf, len, &msglen, NULL);
if (msg == NULL)
return -1;
- ethhdr = (struct l2_ethhdr *) msg;
- memcpy(ethhdr->h_dest, dst, ETH_ALEN);
- memcpy(ethhdr->h_source, wpa_s->own_addr, ETH_ALEN);
- ethhdr->h_proto = htons(ETH_P_EAPOL);
-
- hdr = (struct ieee802_1x_hdr *) (ethhdr + 1);
- hdr->version = wpa_s->conf->eapol_version;
- hdr->type = type;
- hdr->length = htons(len);
-
- memcpy((u8 *) (hdr + 1), buf, len);
-
wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", msg, msglen);
- res = l2_packet_send(wpa_s->l2, msg, msglen);
- free(msg);
- return res;
-}
-
-
-int wpa_eapol_send_preauth(void *ctx, int type, u8 *buf, size_t len)
-{
- struct wpa_supplicant *wpa_s = ctx;
- u8 *msg;
- size_t msglen;
- struct l2_ethhdr *ethhdr;
- struct ieee802_1x_hdr *hdr;
- int res;
-
- /* TODO: could add l2_packet_sendmsg that allows fragments to avoid
- * extra copy here */
-
- if (wpa_s->l2_preauth == NULL)
- return -1;
-
- msglen = sizeof(*ethhdr) + sizeof(*hdr) + len;
- msg = malloc(msglen);
- if (msg == NULL)
- return -1;
-
- ethhdr = (struct l2_ethhdr *) msg;
- memcpy(ethhdr->h_dest, wpa_s->preauth_bssid, ETH_ALEN);
- memcpy(ethhdr->h_source, wpa_s->own_addr, ETH_ALEN);
- ethhdr->h_proto = htons(ETH_P_RSN_PREAUTH);
-
- hdr = (struct ieee802_1x_hdr *) (ethhdr + 1);
- hdr->version = wpa_s->conf->eapol_version;
- hdr->type = type;
- hdr->length = htons(len);
-
- memcpy((u8 *) (hdr + 1), buf, len);
-
- wpa_hexdump(MSG_MSGDUMP, "TX EAPOL (preauth)", msg, msglen);
- res = l2_packet_send(wpa_s->l2_preauth, msg, msglen);
+ res = wpa_ether_send(wpa_s, dst, ETH_P_EAPOL, msg, msglen);
free(msg);
return res;
}
@@ -281,15 +268,33 @@ int wpa_eapol_send_preauth(void *ctx, int type, u8 *buf, size_t len)
* Returns 0 on success or < 0 on error.
*/
static int wpa_eapol_set_wep_key(void *ctx, int unicast, int keyidx,
- u8 *key, size_t keylen)
+ const u8 *key, size_t keylen)
{
struct wpa_supplicant *wpa_s = ctx;
- wpa_s->keys_cleared = 0;
return wpa_drv_set_key(wpa_s, WPA_ALG_WEP,
unicast ? wpa_s->bssid :
(u8 *) "\xff\xff\xff\xff\xff\xff",
keyidx, unicast, (u8 *) "", 0, key, keylen);
}
+#endif /* IEEE8021X_EAPOL */
+
+
+#if defined(IEEE8021X_EAPOL) || !defined(CONFIG_NO_WPA)
+static void wpa_supplicant_set_config_blob(void *ctx,
+ struct wpa_config_blob *blob)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+ wpa_config_set_blob(wpa_s->conf, blob);
+}
+
+
+static const struct wpa_config_blob *
+wpa_supplicant_get_config_blob(void *ctx, const char *name)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+ return wpa_config_get_blob(wpa_s->conf, name);
+}
+#endif /* defined(IEEE8021X_EAPOL) || !defined(CONFIG_NO_WPA) */
/* Configure default/group WEP key for static WEP */
@@ -297,7 +302,6 @@ static int wpa_set_wep_key(void *ctx, int set_tx, int keyidx, const u8 *key,
size_t keylen)
{
struct wpa_supplicant *wpa_s = ctx;
- wpa_s->keys_cleared = 0;
return wpa_drv_set_key(wpa_s, WPA_ALG_WEP,
(u8 *) "\xff\xff\xff\xff\xff\xff",
keyidx, set_tx, (u8 *) "", 0, key, keylen);
@@ -353,17 +357,24 @@ static int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
}
-void wpa_supplicant_notify_eapol_done(void *ctx)
+#ifdef IEEE8021X_EAPOL
+static void wpa_supplicant_notify_eapol_done(void *ctx)
{
struct wpa_supplicant *wpa_s = ctx;
wpa_msg(wpa_s, MSG_DEBUG, "WPA: EAPOL processing complete");
- eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL);
- wpa_supplicant_cancel_auth_timeout(wpa_s);
+ if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X) {
+ wpa_supplicant_set_state(wpa_s, WPA_4WAY_HANDSHAKE);
+ } else {
+ eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL);
+ wpa_supplicant_cancel_auth_timeout(wpa_s);
+ wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
+ }
}
+#endif /* IEEE8021X_EAPOL */
-static struct wpa_blacklist *
-wpa_blacklist_get(struct wpa_supplicant *wpa_s, const u8 *bssid)
+struct wpa_blacklist * wpa_blacklist_get(struct wpa_supplicant *wpa_s,
+ const u8 *bssid)
{
struct wpa_blacklist *e;
@@ -378,7 +389,7 @@ wpa_blacklist_get(struct wpa_supplicant *wpa_s, const u8 *bssid)
}
-static int wpa_blacklist_add(struct wpa_supplicant *wpa_s, const u8 *bssid)
+int wpa_blacklist_add(struct wpa_supplicant *wpa_s, const u8 *bssid)
{
struct wpa_blacklist *e;
@@ -406,7 +417,7 @@ static int wpa_blacklist_add(struct wpa_supplicant *wpa_s, const u8 *bssid)
}
-static int wpa_blacklist_del(struct wpa_supplicant *wpa_s, const u8 *bssid)
+int wpa_blacklist_del(struct wpa_supplicant *wpa_s, const u8 *bssid)
{
struct wpa_blacklist *e, *prev = NULL;
@@ -430,7 +441,7 @@ static int wpa_blacklist_del(struct wpa_supplicant *wpa_s, const u8 *bssid)
}
-static void wpa_blacklist_clear(struct wpa_supplicant *wpa_s)
+void wpa_blacklist_clear(struct wpa_supplicant *wpa_s)
{
struct wpa_blacklist *e, *prev;
@@ -485,6 +496,7 @@ static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
MAC2STR(wpa_s->bssid));
wpa_blacklist_add(wpa_s, wpa_s->bssid);
+ wpa_sm_notify_disassoc(wpa_s->wpa);
wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING);
wpa_s->reassociate = 1;
wpa_supplicant_req_scan(wpa_s, 0, 0);
@@ -494,6 +506,10 @@ static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
int sec, int usec)
{
+ if (wpa_s->conf && wpa_s->conf->ap_scan == 0 &&
+ wpa_s->driver && strcmp(wpa_s->driver->name, "wired") == 0)
+ return;
+
wpa_msg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
"%d usec", sec, usec);
eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
@@ -509,7 +525,7 @@ void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
}
-static void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
+void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
{
struct eapol_config eapol_conf;
struct wpa_ssid *ssid = wpa_s->current_ssid;
@@ -535,15 +551,22 @@ static void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
eapol_conf.required_keys |=
EAPOL_REQUIRE_KEY_BROADCAST;
}
+
+ if (wpa_s->conf && wpa_s->driver &&
+ strcmp(wpa_s->driver->name, "wired") == 0) {
+ eapol_conf.required_keys = 0;
+ }
}
eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
eapol_conf.workaround = ssid->eap_workaround;
+ eapol_conf.eap_disabled = wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X &&
+ wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA;
eapol_sm_notify_config(wpa_s->eapol, ssid, &eapol_conf);
}
-static void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
- struct wpa_ssid *ssid)
+void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid)
{
int i;
@@ -551,15 +574,9 @@ static void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
else
wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
- free(wpa_s->ap_wpa_ie);
- wpa_s->ap_wpa_ie = NULL;
- wpa_s->ap_wpa_ie_len = 0;
- free(wpa_s->ap_rsn_ie);
- wpa_s->ap_rsn_ie = NULL;
- wpa_s->ap_rsn_ie_len = 0;
- free(wpa_s->assoc_wpa_ie);
- wpa_s->assoc_wpa_ie = NULL;
- wpa_s->assoc_wpa_ie_len = 0;
+ wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
+ wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
+ wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
wpa_s->group_cipher = WPA_CIPHER_NONE;
@@ -575,40 +592,12 @@ static void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
}
}
- wpa_s->cur_pmksa = NULL;
-}
-
-
-static int wpa_supplicant_select_config(struct wpa_supplicant *wpa_s)
-{
- struct wpa_ssid *ssid;
-
- if (wpa_s->conf->ap_scan == 1)
- return 0;
-
- ssid = wpa_supplicant_get_ssid(wpa_s);
- if (ssid == NULL) {
- wpa_printf(MSG_INFO, "No network configuration found for the "
- "current AP");
- return -1;
- }
-
- wpa_printf(MSG_DEBUG, "Network configuration found for the current "
- "AP");
- if (ssid->key_mgmt & (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_IEEE8021X |
- WPA_KEY_MGMT_WPA_NONE)) {
- u8 wpa_ie[80];
- int wpa_ie_len;
- wpa_supplicant_set_suites(wpa_s, NULL, ssid,
- wpa_ie, &wpa_ie_len);
- } else {
- wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
- }
-
- wpa_s->current_ssid = ssid;
- wpa_supplicant_initiate_eapol(wpa_s);
+ wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
+ wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
+ wpa_s->pairwise_cipher);
+ wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
- return 0;
+ pmksa_cache_clear_current(wpa_s->wpa);
}
@@ -616,50 +605,41 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
{
scard_deinit(wpa_s->scard);
wpa_s->scard = NULL;
+ wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
l2_packet_deinit(wpa_s->l2);
wpa_s->l2 = NULL;
-#ifdef CONFIG_XSUPPLICANT_IFACE
- if (wpa_s->dot1x_s > -1) {
- close(wpa_s->dot1x_s);
- wpa_s->dot1x_s = -1;
- }
-#endif /* CONFIG_XSUPPLICANT_IFACE */
-
wpa_supplicant_ctrl_iface_deinit(wpa_s);
if (wpa_s->conf != NULL) {
wpa_config_free(wpa_s->conf);
wpa_s->conf = NULL;
}
- free(wpa_s->assoc_wpa_ie);
- wpa_s->assoc_wpa_ie = NULL;
-
- free(wpa_s->ap_wpa_ie);
- wpa_s->ap_wpa_ie = NULL;
- free(wpa_s->ap_rsn_ie);
- wpa_s->ap_rsn_ie = NULL;
-
free(wpa_s->confname);
wpa_s->confname = NULL;
+ wpa_sm_set_eapol(wpa_s->wpa, NULL);
eapol_sm_deinit(wpa_s->eapol);
wpa_s->eapol = NULL;
- rsn_preauth_deinit(wpa_s);
+ rsn_preauth_deinit(wpa_s->wpa);
- pmksa_candidate_free(wpa_s);
- pmksa_cache_free(wpa_s);
+ pmksa_candidate_free(wpa_s->wpa);
+ pmksa_cache_free(wpa_s->wpa);
+ wpa_sm_deinit(wpa_s->wpa);
+ wpa_s->wpa = NULL;
wpa_blacklist_clear(wpa_s);
free(wpa_s->scan_results);
wpa_s->scan_results = NULL;
wpa_s->num_scan_results = 0;
+
+ wpa_supplicant_cancel_scan(wpa_s);
}
-static void wpa_clear_keys(struct wpa_supplicant *wpa_s, u8 *addr)
+void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
{
u8 *bcast = (u8 *) "\xff\xff\xff\xff\xff\xff";
@@ -688,353 +668,65 @@ static void wpa_clear_keys(struct wpa_supplicant *wpa_s, u8 *addr)
}
-static void wpa_supplicant_stop_countermeasures(void *eloop_ctx,
- void *sock_ctx)
-{
- struct wpa_supplicant *wpa_s = eloop_ctx;
-
- if (wpa_s->countermeasures) {
- wpa_s->countermeasures = 0;
- wpa_drv_set_countermeasures(wpa_s, 0);
- wpa_msg(wpa_s, MSG_INFO, "WPA: TKIP countermeasures stopped");
- wpa_supplicant_req_scan(wpa_s, 0, 0);
- }
-}
-
-
-static void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s)
-{
- wpa_s->wpa_state = WPA_DISCONNECTED;
- memset(wpa_s->bssid, 0, ETH_ALEN);
- eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
- eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
- if (wpa_s->key_mgmt == WPA_KEY_MGMT_PSK)
- eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
-}
-
-
-static void wpa_find_assoc_pmkid(struct wpa_supplicant *wpa_s)
-{
- struct wpa_ie_data ie;
- int i;
-
- if (wpa_parse_wpa_ie(wpa_s, wpa_s->assoc_wpa_ie,
- wpa_s->assoc_wpa_ie_len, &ie) < 0 ||
- ie.pmkid == NULL)
- return;
-
- for (i = 0; i < ie.num_pmkid; i++) {
- wpa_s->cur_pmksa = pmksa_cache_get(wpa_s, NULL,
- ie.pmkid + i * PMKID_LEN);
- if (wpa_s->cur_pmksa) {
- eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1);
- break;
- }
- }
-
- wpa_printf(MSG_DEBUG, "RSN: PMKID from assoc IE %sfound from PMKSA "
- "cache", wpa_s->cur_pmksa ? "" : "not ");
-}
-
-
-static void wpa_supplicant_add_pmkid_candidate(struct wpa_supplicant *wpa_s,
- union wpa_event_data *data)
+const char * wpa_supplicant_state_txt(int state)
{
- if (data == NULL) {
- wpa_printf(MSG_DEBUG, "RSN: No data in PMKID candidate event");
- return;
- }
- wpa_printf(MSG_DEBUG, "RSN: PMKID candidate event - bssid=" MACSTR
- " index=%d preauth=%d",
- MAC2STR(data->pmkid_candidate.bssid),
- data->pmkid_candidate.index,
- data->pmkid_candidate.preauth);
-
- if (!data->pmkid_candidate.preauth) {
- wpa_printf(MSG_DEBUG, "RSN: Ignored PMKID candidate without "
- "preauth flag");
- return;
- }
-
- pmksa_candidate_add(wpa_s, data->pmkid_candidate.bssid,
- data->pmkid_candidate.index);
-}
-
-
-static int wpa_supplicant_dynamic_keys(struct wpa_supplicant *wpa_s)
-{
- if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
- wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
- return 0;
-
- if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
- wpa_s->current_ssid &&
- !(wpa_s->current_ssid->eapol_flags &
- (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
- EAPOL_FLAG_REQUIRE_KEY_BROADCAST))) {
- /* IEEE 802.1X, but not using dynamic WEP keys (i.e., either
- * plaintext or static WEP keys). */
- return 0;
+ switch (state) {
+ case WPA_DISCONNECTED:
+ return "DISCONNECTED";
+ case WPA_INACTIVE:
+ return "INACTIVE";
+ case WPA_SCANNING:
+ return "SCANNING";
+ case WPA_ASSOCIATING:
+ return "ASSOCIATING";
+ case WPA_ASSOCIATED:
+ return "ASSOCIATED";
+ case WPA_4WAY_HANDSHAKE:
+ return "4WAY_HANDSHAKE";
+ case WPA_GROUP_HANDSHAKE:
+ return "GROUP_HANDSHAKE";
+ case WPA_COMPLETED:
+ return "COMPLETED";
+ default:
+ return "UNKNOWN";
}
-
- return 1;
}
-static void wpa_supplicant_associnfo(struct wpa_supplicant *wpa_s,
- union wpa_event_data *data)
+void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, wpa_states state)
{
- int l, len;
- u8 *p;
-
- wpa_printf(MSG_DEBUG, "Association info event");
- wpa_hexdump(MSG_DEBUG, "req_ies", data->assoc_info.req_ies,
- data->assoc_info.req_ies_len);
- wpa_hexdump(MSG_DEBUG, "resp_ies", data->assoc_info.resp_ies,
- data->assoc_info.resp_ies_len);
- if (wpa_s->assoc_wpa_ie) {
- free(wpa_s->assoc_wpa_ie);
- wpa_s->assoc_wpa_ie = NULL;
- wpa_s->assoc_wpa_ie_len = 0;
- }
-
- p = data->assoc_info.req_ies;
- l = data->assoc_info.req_ies_len;
-
- /* Go through the IEs and make a copy of the WPA/RSN IE, if present. */
- while (l >= 2) {
- len = p[1] + 2;
- if (len > l) {
- wpa_hexdump(MSG_DEBUG, "Truncated IE in assoc_info",
- p, l);
- break;
- }
- if ((p[0] == GENERIC_INFO_ELEM && p[1] >= 6 &&
- (memcmp(&p[2], "\x00\x50\xF2\x01\x01\x00", 6) == 0)) ||
- (p[0] == RSN_INFO_ELEM && p[1] >= 2)) {
- wpa_s->assoc_wpa_ie = malloc(len);
- if (wpa_s->assoc_wpa_ie == NULL)
- break;
- wpa_s->assoc_wpa_ie_len = len;
- memcpy(wpa_s->assoc_wpa_ie, p, len);
- wpa_hexdump(MSG_DEBUG, "assoc_wpa_ie",
- wpa_s->assoc_wpa_ie,
- wpa_s->assoc_wpa_ie_len);
- wpa_find_assoc_pmkid(wpa_s);
- break;
- }
- l -= len;
- p += len;
- }
-
- /* WPA/RSN IE from Beacon/ProbeResp */
- free(wpa_s->ap_wpa_ie);
- wpa_s->ap_wpa_ie = NULL;
- wpa_s->ap_wpa_ie_len = 0;
- free(wpa_s->ap_rsn_ie);
- wpa_s->ap_rsn_ie = NULL;
- wpa_s->ap_rsn_ie_len = 0;
-
- p = data->assoc_info.beacon_ies;
- l = data->assoc_info.beacon_ies_len;
-
- /* Go through the IEs and make a copy of the WPA/RSN IEs, if present.
- */
- while (l >= 2) {
- len = p[1] + 2;
- if (len > l) {
- wpa_hexdump(MSG_DEBUG, "Truncated IE in beacon_ies",
- p, l);
- break;
- }
- if (wpa_s->ap_wpa_ie == NULL &&
- p[0] == GENERIC_INFO_ELEM && p[1] >= 6 &&
- memcmp(&p[2], "\x00\x50\xF2\x01\x01\x00", 6) == 0) {
- wpa_s->ap_wpa_ie = malloc(len);
- if (wpa_s->ap_wpa_ie) {
- memcpy(wpa_s->ap_wpa_ie, p, len);
- wpa_s->ap_wpa_ie_len = len;
- }
- }
-
- if (wpa_s->ap_rsn_ie == NULL &&
- p[0] == RSN_INFO_ELEM && p[1] >= 2) {
- wpa_s->ap_rsn_ie = malloc(len);
- if (wpa_s->ap_rsn_ie) {
- memcpy(wpa_s->ap_rsn_ie, p, len);
- wpa_s->ap_rsn_ie_len = len;
- }
-
- }
-
- l -= len;
- p += len;
- }
-
+ wpa_printf(MSG_DEBUG, "State: %s -> %s",
+ wpa_supplicant_state_txt(wpa_s->wpa_state),
+ wpa_supplicant_state_txt(state));
+ if (state == WPA_COMPLETED && wpa_s->new_connection) {
+ wpa_s->new_connection = 0;
+ wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
+ MACSTR " completed %s",
+ MAC2STR(wpa_s->bssid), wpa_s->reassociated_connection ?
+ "(reauth)" : "(auth)");
+ wpa_s->reassociated_connection = 1;
+ } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
+ state == WPA_ASSOCIATED) {
+ wpa_s->new_connection = 1;
+ }
+ wpa_s->wpa_state = state;
}
-static int any_interfaces(struct wpa_supplicant *head)
-{
- struct wpa_supplicant *wpa_s;
-
- for (wpa_s = head; wpa_s != NULL; wpa_s = wpa_s->next)
- if (!wpa_s->interface_removed)
- return 1;
- return 0;
-}
-void wpa_supplicant_event(struct wpa_supplicant *wpa_s, wpa_event_type event,
- union wpa_event_data *data)
+wpa_states wpa_supplicant_get_state(struct wpa_supplicant *wpa_s)
{
- int pairwise;
- time_t now;
- u8 bssid[ETH_ALEN];
-
- switch (event) {
- case EVENT_ASSOC:
- wpa_s->wpa_state = WPA_ASSOCIATED;
- wpa_printf(MSG_DEBUG, "Association event - clear replay "
- "counter");
- memset(wpa_s->rx_replay_counter, 0, WPA_REPLAY_COUNTER_LEN);
- wpa_s->rx_replay_counter_set = 0;
- wpa_s->renew_snonce = 1;
- if (wpa_drv_get_bssid(wpa_s, bssid) >= 0 &&
- memcmp(bssid, wpa_s->bssid, ETH_ALEN) != 0) {
- wpa_msg(wpa_s, MSG_DEBUG, "Associated to a new BSS: "
- "BSSID=" MACSTR, MAC2STR(bssid));
- memcpy(wpa_s->bssid, bssid, ETH_ALEN);
- if (wpa_supplicant_dynamic_keys(wpa_s)) {
- wpa_clear_keys(wpa_s, bssid);
- }
- wpa_supplicant_select_config(wpa_s);
- }
- wpa_msg(wpa_s, MSG_INFO, "Associated with " MACSTR,
- MAC2STR(bssid));
- /* Set portEnabled first to FALSE in order to get EAP state
- * machine out of the SUCCESS state and eapSuccess cleared.
- * Without this, EAPOL PAE state machine may transit to
- * AUTHENTICATING state based on obsolete eapSuccess and then
- * trigger BE_AUTH to SUCCESS and PAE to AUTHENTICATED without
- * ever giving chance to EAP state machine to reset the state.
- */
- eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
- eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
- if (wpa_s->key_mgmt == WPA_KEY_MGMT_PSK)
- eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
- /* 802.1X::portControl = Auto */
- eapol_sm_notify_portEnabled(wpa_s->eapol, TRUE);
- wpa_s->eapol_received = 0;
- if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
- wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
- wpa_supplicant_cancel_auth_timeout(wpa_s);
- } else {
- /* Timeout for receiving the first EAPOL packet */
- wpa_supplicant_req_auth_timeout(wpa_s, 10, 0);
- }
- break;
- case EVENT_DISASSOC:
- if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
- /* At least Host AP driver and a Prism3 card seemed to
- * be generating streams of disconnected events when
- * configuring IBSS for WPA-None. Ignore them for now.
- */
- wpa_printf(MSG_DEBUG, "Disconnect event - ignore in "
- "IBSS/WPA-None mode");
- break;
- }
- if (wpa_s->wpa_state >= WPA_ASSOCIATED)
- wpa_supplicant_req_scan(wpa_s, 0, 100000);
- wpa_blacklist_add(wpa_s, wpa_s->bssid);
- wpa_supplicant_mark_disassoc(wpa_s);
- wpa_msg(wpa_s, MSG_INFO, "Disconnect event - remove keys");
- if (wpa_supplicant_dynamic_keys(wpa_s)) {
- wpa_s->keys_cleared = 0;
- wpa_clear_keys(wpa_s, wpa_s->bssid);
- }
- break;
- case EVENT_MICHAEL_MIC_FAILURE:
- wpa_msg(wpa_s, MSG_WARNING, "Michael MIC failure detected");
- pairwise = (data && data->michael_mic_failure.unicast);
- wpa_supplicant_key_request(wpa_s, 1, pairwise);
- time(&now);
- if (wpa_s->last_michael_mic_error &&
- now - wpa_s->last_michael_mic_error <= 60) {
- /* initialize countermeasures */
- wpa_s->countermeasures = 1;
- wpa_msg(wpa_s, MSG_WARNING, "TKIP countermeasures "
- "started");
-
- /* Need to wait for completion of request frame. We do
- * not get any callback for the message completion, so
- * just wait a short while and hope for the best. */
- usleep(10000);
-
- wpa_drv_set_countermeasures(wpa_s, 1);
- wpa_supplicant_deauthenticate(
- wpa_s, REASON_MICHAEL_MIC_FAILURE);
- eloop_cancel_timeout(
- wpa_supplicant_stop_countermeasures, wpa_s,
- NULL);
- eloop_register_timeout(
- 60, 0, wpa_supplicant_stop_countermeasures,
- wpa_s, NULL);
- /* TODO: mark the AP rejected for 60 second. STA is
- * allowed to associate with another AP.. */
- }
- wpa_s->last_michael_mic_error = now;
- break;
- case EVENT_SCAN_RESULTS:
- wpa_supplicant_scan_results(wpa_s);
- break;
- case EVENT_ASSOCINFO:
- wpa_supplicant_associnfo(wpa_s, data);
- break;
- case EVENT_INTERFACE_STATUS:
- if (strcmp(wpa_s->ifname, data->interface_status.ifname) != 0)
- break;
- switch (data->interface_status.ievent) {
- case EVENT_INTERFACE_ADDED:
- if (!wpa_s->interface_removed)
- break;
- wpa_s->interface_removed = 0;
- wpa_printf(MSG_DEBUG, "Configured interface was "
- "added.");
- if (wpa_supplicant_driver_init(wpa_s, 1) < 0) {
- wpa_printf(MSG_INFO, "Failed to initialize "
- "the driver after interface was "
- "added.");
- }
- break;
- case EVENT_INTERFACE_REMOVED:
- wpa_printf(MSG_DEBUG, "Configured interface was "
- "removed.");
- wpa_s->interface_removed = 1;
- wpa_supplicant_mark_disassoc(wpa_s);
- l2_packet_deinit(wpa_s->l2);
- wpa_s->l2 = NULL;
- /* check if last interface */
- if (!any_interfaces(wpa_s->head))
- eloop_terminate();
- break;
- }
- break;
- case EVENT_PMKID_CANDIDATE:
- wpa_supplicant_add_pmkid_candidate(wpa_s, data);
- break;
- default:
- wpa_printf(MSG_INFO, "Unknown event %d", event);
- break;
- }
+ return wpa_s->wpa_state;
}
static void wpa_supplicant_terminate(int sig, void *eloop_ctx,
void *signal_ctx)
{
- struct wpa_supplicant *wpa_s = eloop_ctx;
- for (wpa_s = wpa_s->head; wpa_s; wpa_s = wpa_s->next) {
- wpa_msg(wpa_s, MSG_INFO, "Signal %d received - terminating",
- sig);
+ struct wpa_global *global = eloop_ctx;
+ struct wpa_supplicant *wpa_s;
+ for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
+ wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING "- signal %d "
+ "received", sig);
}
eloop_terminate();
}
@@ -1062,8 +754,15 @@ int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
wpa_supplicant_ctrl_iface_deinit(wpa_s);
wpa_s->current_ssid = NULL;
+ /*
+ * TODO: should notify EAPOL SM about changes in opensc_engine_path,
+ * pkcs11_engine_path, pkcs11_module_path.
+ */
eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
- rsn_preauth_deinit(wpa_s);
+ wpa_sm_set_config(wpa_s->wpa, NULL);
+ wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
+ pmksa_cache_notify_reconfig(wpa_s->wpa);
+ rsn_preauth_deinit(wpa_s->wpa);
wpa_config_free(wpa_s->conf);
wpa_s->conf = conf;
if (reconf_ctrl)
@@ -1079,9 +778,10 @@ int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
static void wpa_supplicant_reconfig(int sig, void *eloop_ctx,
void *signal_ctx)
{
- struct wpa_supplicant *wpa_s = eloop_ctx;
+ struct wpa_global *global = eloop_ctx;
+ struct wpa_supplicant *wpa_s;
wpa_printf(MSG_DEBUG, "Signal %d received - reconfiguring", sig);
- for (wpa_s = wpa_s->head; wpa_s; wpa_s = wpa_s->next) {
+ for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
eloop_terminate();
}
@@ -1099,6 +799,9 @@ static void wpa_supplicant_gen_assoc_event(struct wpa_supplicant *wpa_s)
if (ssid == NULL)
return;
+ if (wpa_s->current_ssid == NULL)
+ wpa_s->current_ssid = ssid;
+ wpa_supplicant_initiate_eapol(wpa_s);
wpa_printf(MSG_DEBUG, "Already associated with a configured network - "
"generating associated event");
memset(&data, 0, sizeof(data));
@@ -1106,26 +809,40 @@ static void wpa_supplicant_gen_assoc_event(struct wpa_supplicant *wpa_s)
}
-void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
+static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
{
struct wpa_supplicant *wpa_s = eloop_ctx;
struct wpa_ssid *ssid;
+ int enabled, scan_req = 0;
- if (wpa_s->conf->ap_scan == 0) {
- wpa_supplicant_gen_assoc_event(wpa_s);
+ if (wpa_s->disconnected)
return;
+
+ enabled = 0;
+ ssid = wpa_s->conf->ssid;
+ while (ssid) {
+ if (!ssid->disabled) {
+ enabled++;
+ break;
+ }
+ ssid = ssid->next;
}
+ if (!enabled && !wpa_s->scan_req) {
+ wpa_printf(MSG_DEBUG, "No enabled networks - do not scan");
+ wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
+ return;
+ }
+ scan_req = wpa_s->scan_req;
+ wpa_s->scan_req = 0;
- if (wpa_s->conf->ap_scan == 2) {
- ssid = wpa_s->conf->ssid;
- if (ssid == NULL)
- return;
- wpa_supplicant_associate(wpa_s, NULL, ssid);
+ if (wpa_s->conf->ap_scan == 0) {
+ wpa_supplicant_gen_assoc_event(wpa_s);
return;
}
- if (wpa_s->wpa_state == WPA_DISCONNECTED)
- wpa_s->wpa_state = WPA_SCANNING;
+ if (wpa_s->wpa_state == WPA_DISCONNECTED ||
+ wpa_s->wpa_state == WPA_INACTIVE)
+ wpa_supplicant_set_state(wpa_s, WPA_SCANNING);
ssid = wpa_s->conf->ssid;
if (wpa_s->prev_scan_ssid != BROADCAST_SSID_SCAN) {
@@ -1138,11 +855,30 @@ void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
}
}
while (ssid) {
- if (ssid->scan_ssid)
+ if (!ssid->disabled &&
+ (ssid->scan_ssid || wpa_s->conf->ap_scan == 2))
break;
ssid = ssid->next;
}
+ if (scan_req != 2 && wpa_s->conf->ap_scan == 2) {
+ /*
+ * ap_scan=2 mode - try to associate with each SSID instead of
+ * scanning for each scan_ssid=1 network.
+ */
+ if (ssid == NULL)
+ return;
+ if (ssid->next) {
+ /* Continue from the next SSID on the next attempt. */
+ wpa_s->prev_scan_ssid = ssid;
+ } else {
+ /* Start from the beginning of the SSID list. */
+ wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN;
+ }
+ wpa_supplicant_associate(wpa_s, NULL, ssid);
+ return;
+ }
+
wpa_printf(MSG_DEBUG, "Starting AP scan (%s SSID)",
ssid ? "specific": "broadcast");
if (ssid) {
@@ -1198,14 +934,14 @@ static wpa_key_mgmt key_mgmt2driver(int key_mgmt)
static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid,
- struct wpa_ie_data *ie) {
- if (wpa_s->assoc_wpa_ie == NULL)
- return -1;
-
- if (wpa_parse_wpa_ie(wpa_s, wpa_s->assoc_wpa_ie,
- wpa_s->assoc_wpa_ie_len, ie)) {
- wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE from "
- "association info");
+ struct wpa_ie_data *ie)
+{
+ int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
+ if (ret) {
+ if (ret == -2) {
+ wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
+ "from association info");
+ }
return -1;
}
@@ -1234,33 +970,36 @@ static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
}
-static int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
- struct wpa_scan_result *bss,
- struct wpa_ssid *ssid,
- u8 *wpa_ie, int *wpa_ie_len)
+int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
+ struct wpa_scan_result *bss,
+ struct wpa_ssid *ssid,
+ u8 *wpa_ie, size_t *wpa_ie_len)
{
struct wpa_ie_data ie;
int sel, proto;
- u8 *ap_ie;
- size_t ap_ie_len;
- if (bss && bss->rsn_ie_len && (ssid->proto & WPA_PROTO_RSN)) {
+ if (bss && bss->rsn_ie_len && (ssid->proto & WPA_PROTO_RSN) &&
+ wpa_parse_wpa_ie(bss->rsn_ie, bss->rsn_ie_len, &ie) == 0 &&
+ (ie.group_cipher & ssid->group_cipher) &&
+ (ie.pairwise_cipher & ssid->pairwise_cipher) &&
+ (ie.key_mgmt & ssid->key_mgmt)) {
wpa_msg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
proto = WPA_PROTO_RSN;
- ap_ie = bss->rsn_ie;
- ap_ie_len = bss->rsn_ie_len;
- } else if (bss) {
+ } else if (bss && bss->wpa_ie_len && (ssid->proto & WPA_PROTO_WPA) &&
+ wpa_parse_wpa_ie(bss->wpa_ie, bss->wpa_ie_len, &ie) == 0 &&
+ (ie.group_cipher & ssid->group_cipher) &&
+ (ie.pairwise_cipher & ssid->pairwise_cipher) &&
+ (ie.key_mgmt & ssid->key_mgmt)) {
wpa_msg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
proto = WPA_PROTO_WPA;
- ap_ie = bss->wpa_ie;
- ap_ie_len = bss->wpa_ie_len;
+ } else if (bss) {
+ wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
+ return -1;
} else {
if (ssid->proto & WPA_PROTO_RSN)
proto = WPA_PROTO_RSN;
else
proto = WPA_PROTO_WPA;
- ap_ie = NULL;
- ap_ie_len = 0;
if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
memset(&ie, 0, sizeof(ie));
ie.group_cipher = ssid->group_cipher;
@@ -1271,42 +1010,17 @@ static int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
}
}
- if (ap_ie && wpa_parse_wpa_ie(wpa_s, ap_ie, ap_ie_len, &ie)) {
- wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to parse WPA IE for "
- "the selected BSS.");
- return -1;
- }
wpa_printf(MSG_DEBUG, "WPA: Selected cipher suites: group %d "
"pairwise %d key_mgmt %d",
ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt);
- wpa_s->proto = proto;
-
- free(wpa_s->ap_wpa_ie);
- wpa_s->ap_wpa_ie = NULL;
- wpa_s->ap_wpa_ie_len = 0;
- if (bss && bss->wpa_ie_len) {
- wpa_s->ap_wpa_ie = malloc(bss->wpa_ie_len);
- if (wpa_s->ap_wpa_ie == NULL) {
- wpa_printf(MSG_INFO, "WPA: malloc failed");
- return -1;
- }
- memcpy(wpa_s->ap_wpa_ie, bss->wpa_ie, bss->wpa_ie_len);
- wpa_s->ap_wpa_ie_len = bss->wpa_ie_len;
- }
+ wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
- free(wpa_s->ap_rsn_ie);
- wpa_s->ap_rsn_ie = NULL;
- wpa_s->ap_rsn_ie_len = 0;
- if (bss && bss->rsn_ie_len) {
- wpa_s->ap_rsn_ie = malloc(bss->rsn_ie_len);
- if (wpa_s->ap_rsn_ie == NULL) {
- wpa_printf(MSG_INFO, "WPA: malloc failed");
- return -1;
- }
- memcpy(wpa_s->ap_rsn_ie, bss->rsn_ie, bss->rsn_ie_len);
- wpa_s->ap_rsn_ie_len = bss->rsn_ie_len;
- }
+ if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss ? bss->wpa_ie : NULL,
+ bss ? bss->wpa_ie_len : 0) ||
+ wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss ? bss->rsn_ie : NULL,
+ bss ? bss->rsn_ie_len : 0))
+ return -1;
sel = ie.group_cipher & ssid->group_cipher;
if (sel & WPA_CIPHER_CCMP) {
@@ -1358,61 +1072,44 @@ static int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
return -1;
}
- *wpa_ie_len = wpa_gen_wpa_ie(wpa_s, wpa_ie);
- if (*wpa_ie_len < 0) {
+ wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
+ wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
+ wpa_s->pairwise_cipher);
+ wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
+
+ if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
wpa_printf(MSG_WARNING, "WPA: Failed to generate WPA IE.");
return -1;
}
- wpa_hexdump(MSG_DEBUG, "WPA: Own WPA IE", wpa_ie, *wpa_ie_len);
- if (wpa_s->assoc_wpa_ie == NULL) {
- /*
- * Make a copy of the WPA/RSN IE so that 4-Way Handshake gets
- * the correct version of the IE even if PMKSA caching is
- * aborted (which would remove PMKID from IE generation).
- */
- wpa_s->assoc_wpa_ie = malloc(*wpa_ie_len);
- if (wpa_s->assoc_wpa_ie) {
- memcpy(wpa_s->assoc_wpa_ie, wpa_ie, *wpa_ie_len);
- wpa_s->assoc_wpa_ie_len = *wpa_ie_len;
- }
- }
- if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
- wpa_s->pmk_len = PMK_LEN;
- memcpy(wpa_s->pmk, ssid->psk, PMK_LEN);
- } else if (wpa_s->cur_pmksa) {
- wpa_s->pmk_len = wpa_s->cur_pmksa->pmk_len;
- memcpy(wpa_s->pmk, wpa_s->cur_pmksa->pmk, wpa_s->pmk_len);
- } else {
- wpa_s->pmk_len = PMK_LEN;
- memset(wpa_s->pmk, 0, PMK_LEN);
-#ifdef CONFIG_XSUPPLICANT_IFACE
- wpa_s->ext_pmk_received = 0;
-#endif /* CONFIG_XSUPPLICANT_IFACE */
- }
+ if (ssid->key_mgmt & WPA_KEY_MGMT_PSK)
+ wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN);
+ else
+ wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
return 0;
}
-static void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
- struct wpa_scan_result *bss,
- struct wpa_ssid *ssid)
+void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
+ struct wpa_scan_result *bss,
+ struct wpa_ssid *ssid)
{
u8 wpa_ie[80];
- int wpa_ie_len;
+ size_t wpa_ie_len;
int use_crypt;
int algs = AUTH_ALG_OPEN_SYSTEM;
int cipher_pairwise, cipher_group;
struct wpa_driver_associate_params params;
int wep_keys_set = 0;
struct wpa_driver_capa capa;
+ int assoc_failed = 0;
wpa_s->reassociate = 0;
if (bss) {
wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
" (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
- wpa_ssid_txt(ssid->ssid, ssid->ssid_len), bss->freq);
+ wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
memset(wpa_s->bssid, 0, ETH_ALEN);
} else {
wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
@@ -1422,9 +1119,7 @@ static void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
/* Starting new association, so clear the possibly used WPA IE from the
* previous association. */
- free(wpa_s->assoc_wpa_ie);
- wpa_s->assoc_wpa_ie = NULL;
- wpa_s->assoc_wpa_ie_len = 0;
+ wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
if (ssid->leap) {
@@ -1450,12 +1145,14 @@ static void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
if (bss && (bss->wpa_ie_len || bss->rsn_ie_len) &&
(ssid->key_mgmt & (WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_PSK))) {
- wpa_s->cur_pmksa = pmksa_cache_get(wpa_s, bss->bssid, NULL);
- if (wpa_s->cur_pmksa) {
- wpa_hexdump(MSG_DEBUG, "RSN: PMKID",
- wpa_s->cur_pmksa->pmkid, PMKID_LEN);
+ int try_opportunistic;
+ try_opportunistic = ssid->proactive_key_caching &&
+ (ssid->proto & WPA_PROTO_RSN);
+ if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
+ wpa_s->current_ssid,
+ try_opportunistic) == 0)
eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1);
- }
+ wpa_ie_len = sizeof(wpa_ie);
if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
wpa_ie, &wpa_ie_len)) {
wpa_printf(MSG_WARNING, "WPA: Failed to set WPA key "
@@ -1465,6 +1162,7 @@ static void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
} else if (ssid->key_mgmt &
(WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_IEEE8021X |
WPA_KEY_MGMT_WPA_NONE)) {
+ wpa_ie_len = sizeof(wpa_ie);
if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
wpa_ie, &wpa_ie_len)) {
wpa_printf(MSG_WARNING, "WPA: Failed to set WPA key "
@@ -1518,7 +1216,7 @@ static void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
}
wpa_drv_set_drop_unencrypted(wpa_s, use_crypt);
- wpa_s->wpa_state = WPA_ASSOCIATING;
+ wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
memset(&params, 0, sizeof(params));
if (bss) {
params.bssid = bss->bssid;
@@ -1541,6 +1239,7 @@ static void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
"failed");
/* try to continue anyway; new association will be tried again
* after timeout */
+ assoc_failed = 1;
}
if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
@@ -1550,9 +1249,17 @@ static void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
/* No need to timeout authentication since there is no key
* management. */
wpa_supplicant_cancel_auth_timeout(wpa_s);
+ wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
} else {
/* Timeout for IEEE 802.11 authentication and association */
- wpa_supplicant_req_auth_timeout(wpa_s, 5, 0);
+ int timeout;
+ if (assoc_failed)
+ timeout = 5;
+ else if (wpa_s->conf->ap_scan == 1)
+ timeout = 10;
+ else
+ timeout = 60;
+ wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
}
if (wep_keys_set && wpa_drv_get_capa(wpa_s, &capa) == 0 &&
@@ -1570,6 +1277,7 @@ static void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
}
wpa_s->current_ssid = ssid;
+ wpa_sm_set_config(wpa_s->wpa, wpa_s->current_ssid);
wpa_supplicant_initiate_eapol(wpa_s);
}
@@ -1578,13 +1286,14 @@ void wpa_supplicant_disassociate(struct wpa_supplicant *wpa_s,
int reason_code)
{
u8 *addr = NULL;
- wpa_s->wpa_state = WPA_DISCONNECTED;
+ wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
if (memcmp(wpa_s->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) != 0) {
wpa_drv_disassociate(wpa_s, wpa_s->bssid, reason_code);
addr = wpa_s->bssid;
}
wpa_clear_keys(wpa_s, addr);
wpa_s->current_ssid = NULL;
+ wpa_sm_set_config(wpa_s->wpa, NULL);
eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
@@ -1595,211 +1304,21 @@ void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
int reason_code)
{
u8 *addr = NULL;
- wpa_s->wpa_state = WPA_DISCONNECTED;
+ wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
if (memcmp(wpa_s->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) != 0) {
wpa_drv_deauthenticate(wpa_s, wpa_s->bssid, reason_code);
addr = wpa_s->bssid;
}
wpa_clear_keys(wpa_s, addr);
wpa_s->current_ssid = NULL;
+ wpa_sm_set_config(wpa_s->wpa, NULL);
eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
}
-static void wpa_supplicant_imsi_identity(struct wpa_supplicant *wpa_s,
- struct wpa_ssid *ssid)
-{
- int aka = 0;
- u8 *pos = ssid->eap_methods;
-
- while (pos && *pos != EAP_TYPE_NONE) {
- if (*pos == EAP_TYPE_AKA) {
- aka = 1;
- break;
- }
- pos++;
- }
-
- if (ssid->identity == NULL && wpa_s->imsi) {
- ssid->identity = malloc(1 + wpa_s->imsi_len);
- if (ssid->identity) {
- ssid->identity[0] = aka ? '0' : '1';
- memcpy(ssid->identity + 1, wpa_s->imsi,
- wpa_s->imsi_len);
- ssid->identity_len = 1 + wpa_s->imsi_len;
- wpa_hexdump_ascii(MSG_DEBUG, "permanent identity from "
- "IMSI", ssid->identity,
- ssid->identity_len);
- }
- }
-}
-
-
-static void wpa_supplicant_scard_init(struct wpa_supplicant *wpa_s,
- struct wpa_ssid *ssid)
-{
- char buf[100];
- size_t len;
-
- if (ssid->pcsc == NULL)
- return;
- if (wpa_s->scard != NULL) {
- wpa_supplicant_imsi_identity(wpa_s, ssid);
- return;
- }
- wpa_printf(MSG_DEBUG, "Selected network is configured to use SIM - "
- "initialize PCSC");
- wpa_s->scard = scard_init(SCARD_TRY_BOTH, ssid->pin);
- if (wpa_s->scard == NULL) {
- wpa_printf(MSG_WARNING, "Failed to initialize SIM "
- "(pcsc-lite)");
- /* TODO: what to do here? */
- return;
- }
- eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
-
- len = sizeof(buf);
- if (scard_get_imsi(wpa_s->scard, buf, &len)) {
- wpa_printf(MSG_WARNING, "Failed to get IMSI from SIM");
- /* TODO: what to do here? */
- return;
- }
-
- wpa_hexdump_ascii(MSG_DEBUG, "IMSI", (u8 *) buf, len);
- free(wpa_s->imsi);
- wpa_s->imsi = malloc(len);
- if (wpa_s->imsi) {
- memcpy(wpa_s->imsi, buf, len);
- wpa_s->imsi_len = len;
- wpa_supplicant_imsi_identity(wpa_s, ssid);
- }
-}
-
-
-static struct wpa_scan_result *
-wpa_supplicant_select_bss(struct wpa_supplicant *wpa_s, struct wpa_ssid *group,
- struct wpa_scan_result *results, int num,
- struct wpa_ssid **selected_ssid)
-{
- struct wpa_ssid *ssid;
- struct wpa_scan_result *bss, *selected = NULL;
- int i;
- struct wpa_blacklist *e;
-
- wpa_printf(MSG_DEBUG, "Selecting BSS from priority group %d",
- group->priority);
-
- bss = NULL;
- ssid = NULL;
- /* First, try to find WPA-enabled AP */
- for (i = 0; i < num && !selected; i++) {
- bss = &results[i];
- wpa_printf(MSG_DEBUG, "%d: " MACSTR " ssid='%s' "
- "wpa_ie_len=%lu rsn_ie_len=%lu",
- i, MAC2STR(bss->bssid),
- wpa_ssid_txt(bss->ssid, bss->ssid_len),
- (unsigned long) bss->wpa_ie_len,
- (unsigned long) bss->rsn_ie_len);
- if ((e = wpa_blacklist_get(wpa_s, bss->bssid)) &&
- e->count > 1) {
- wpa_printf(MSG_DEBUG, " skip - blacklisted");
- continue;
- }
-
- if (bss->wpa_ie_len == 0 && bss->rsn_ie_len == 0) {
- wpa_printf(MSG_DEBUG, " skip - no WPA/RSN IE");
- continue;
- }
-
- for (ssid = group; ssid; ssid = ssid->pnext) {
- struct wpa_ie_data ie;
- if (bss->ssid_len != ssid->ssid_len ||
- memcmp(bss->ssid, ssid->ssid,
- bss->ssid_len) != 0) {
- wpa_printf(MSG_DEBUG, " skip - "
- "SSID mismatch");
- continue;
- }
- if (ssid->bssid_set &&
- memcmp(bss->bssid, ssid->bssid, ETH_ALEN) != 0) {
- wpa_printf(MSG_DEBUG, " skip - "
- "BSSID mismatch");
- continue;
- }
- if (!(((ssid->proto & WPA_PROTO_RSN) &&
- wpa_parse_wpa_ie(wpa_s, bss->rsn_ie,
- bss->rsn_ie_len, &ie) == 0) ||
- ((ssid->proto & WPA_PROTO_WPA) &&
- wpa_parse_wpa_ie(wpa_s, bss->wpa_ie,
- bss->wpa_ie_len, &ie) == 0))) {
- wpa_printf(MSG_DEBUG, " skip - "
- "could not parse WPA/RSN IE");
- continue;
- }
- if (!(ie.proto & ssid->proto)) {
- wpa_printf(MSG_DEBUG, " skip - "
- "proto mismatch");
- continue;
- }
- if (!(ie.pairwise_cipher & ssid->pairwise_cipher)) {
- wpa_printf(MSG_DEBUG, " skip - "
- "PTK cipher mismatch");
- continue;
- }
- if (!(ie.group_cipher & ssid->group_cipher)) {
- wpa_printf(MSG_DEBUG, " skip - "
- "GTK cipher mismatch");
- continue;
- }
- if (!(ie.key_mgmt & ssid->key_mgmt)) {
- wpa_printf(MSG_DEBUG, " skip - "
- "key mgmt mismatch");
- continue;
- }
-
- selected = bss;
- *selected_ssid = ssid;
- wpa_printf(MSG_DEBUG, " selected");
- break;
- }
- }
-
- /* If no WPA-enabled AP found, try to find non-WPA AP, if configuration
- * allows this. */
- for (i = 0; i < num && !selected; i++) {
- bss = &results[i];
- if ((e = wpa_blacklist_get(wpa_s, bss->bssid)) &&
- e->count > 1) {
- continue;
- }
- for (ssid = group; ssid; ssid = ssid->pnext) {
- if (bss->ssid_len == ssid->ssid_len &&
- memcmp(bss->ssid, ssid->ssid, bss->ssid_len) == 0
- &&
- (!ssid->bssid_set ||
- memcmp(bss->bssid, ssid->bssid, ETH_ALEN) == 0) &&
- ((ssid->key_mgmt & WPA_KEY_MGMT_NONE) ||
- (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)))
- {
- selected = bss;
- *selected_ssid = ssid;
- wpa_printf(MSG_DEBUG, " selected non-WPA AP "
- MACSTR " ssid='%s'",
- MAC2STR(bss->bssid),
- wpa_ssid_txt(bss->ssid,
- bss->ssid_len));
- break;
- }
- }
- }
-
- return selected;
-}
-
-
-static int wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s)
+int wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s)
{
#define SCAN_AP_LIMIT 128
struct wpa_scan_result *results, *tmp;
@@ -1839,57 +1358,7 @@ static int wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s)
}
-static void wpa_supplicant_scan_results(struct wpa_supplicant *wpa_s)
-{
- int num, prio;
- struct wpa_scan_result *selected = NULL;
- struct wpa_ssid *ssid;
- struct wpa_scan_result *results;
-
- if (wpa_supplicant_get_scan_results(wpa_s) < 0) {
- wpa_printf(MSG_DEBUG, "Failed to get scan results - try "
- "scanning again");
- wpa_supplicant_req_scan(wpa_s, 1, 0);
- return;
- }
- results = wpa_s->scan_results;
- num = wpa_s->num_scan_results;
-
- while (selected == NULL) {
- for (prio = 0; prio < wpa_s->conf->num_prio; prio++) {
- selected = wpa_supplicant_select_bss(
- wpa_s, wpa_s->conf->pssid[prio], results, num,
- &ssid);
- if (selected)
- break;
- }
-
- if (selected == NULL && wpa_s->blacklist) {
- wpa_printf(MSG_DEBUG, "No APs found - clear blacklist "
- "and try again");
- wpa_blacklist_clear(wpa_s);
- } else if (selected == NULL) {
- break;
- }
- }
-
- if (selected) {
- if (wpa_s->reassociate ||
- memcmp(selected->bssid, wpa_s->bssid, ETH_ALEN) != 0) {
- wpa_supplicant_scard_init(wpa_s, ssid);
- wpa_supplicant_associate(wpa_s, selected, ssid);
- } else {
- wpa_printf(MSG_DEBUG, "Already associated with the "
- "selected AP.");
- }
- rsn_preauth_scan_results(wpa_s, results, num);
- } else {
- wpa_printf(MSG_DEBUG, "No suitable AP found.");
- wpa_supplicant_req_scan(wpa_s, 5, 0);
- }
-}
-
-
+#ifndef CONFIG_NO_WPA
static int wpa_get_beacon_ie(struct wpa_supplicant *wpa_s)
{
int i, ret = 0;
@@ -1908,33 +1377,11 @@ static int wpa_get_beacon_ie(struct wpa_supplicant *wpa_s)
}
if (curr) {
- free(wpa_s->ap_wpa_ie);
- wpa_s->ap_wpa_ie_len = curr->wpa_ie_len;
- if (curr->wpa_ie_len) {
- wpa_s->ap_wpa_ie = malloc(wpa_s->ap_wpa_ie_len);
- if (wpa_s->ap_wpa_ie) {
- memcpy(wpa_s->ap_wpa_ie, curr->wpa_ie,
- curr->wpa_ie_len);
- } else {
- ret = -1;
- }
- } else {
- wpa_s->ap_wpa_ie = NULL;
- }
-
- free(wpa_s->ap_rsn_ie);
- wpa_s->ap_rsn_ie_len = curr->rsn_ie_len;
- if (curr->rsn_ie_len) {
- wpa_s->ap_rsn_ie = malloc(wpa_s->ap_rsn_ie_len);
- if (wpa_s->ap_rsn_ie) {
- memcpy(wpa_s->ap_rsn_ie, curr->rsn_ie,
- curr->rsn_ie_len);
- } else {
- ret = -1;
- }
- } else {
- wpa_s->ap_rsn_ie = NULL;
- }
+ if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, curr->wpa_ie,
+ curr->wpa_ie_len) ||
+ wpa_sm_set_ap_rsn_ie(wpa_s->wpa, curr->rsn_ie,
+ curr->rsn_ie_len))
+ ret = -1;
} else {
ret = -1;
}
@@ -1943,8 +1390,9 @@ static int wpa_get_beacon_ie(struct wpa_supplicant *wpa_s)
}
-int wpa_supplicant_get_beacon_ie(struct wpa_supplicant *wpa_s)
+static int wpa_supplicant_get_beacon_ie(void *ctx)
{
+ struct wpa_supplicant *wpa_s = ctx;
if (wpa_get_beacon_ie(wpa_s) == 0) {
return 0;
}
@@ -1957,69 +1405,135 @@ int wpa_supplicant_get_beacon_ie(struct wpa_supplicant *wpa_s)
return wpa_get_beacon_ie(wpa_s);
}
+#endif /* CONFIG_NO_WPA */
-#ifdef CONFIG_XSUPPLICANT_IFACE
-static void wpa_supplicant_dot1x_receive(int sock, void *eloop_ctx,
- void *sock_ctx)
+/**
+ * wpa_supplicant_get_ssid - get a pointer to the current network structure
+ * @wpa_s: pointer to wpa_supplicant data
+ *
+ * Returns: a pointer to the current network structure or %NULL on failure
+ */
+struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
{
- struct wpa_supplicant *wpa_s = eloop_ctx;
- u8 buf[128];
- int res;
+ struct wpa_ssid *entry;
+ u8 ssid[MAX_SSID_LEN];
+ int ssid_len;
+ u8 bssid[ETH_ALEN];
- res = recv(sock, buf, sizeof(buf), 0);
- wpa_printf(MSG_DEBUG, "WPA: Receive from dot1x (Xsupplicant) socket "
- "==> %d", res);
- if (res < 0) {
- perror("recv");
- return;
+ ssid_len = wpa_drv_get_ssid(wpa_s, ssid);
+ if (ssid_len < 0) {
+ wpa_printf(MSG_WARNING, "Could not read SSID from driver.");
+ return NULL;
}
- if (res != PMK_LEN) {
- wpa_printf(MSG_WARNING, "WPA: Invalid master key length (%d) "
- "from dot1x", res);
- return;
+ if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
+ wpa_printf(MSG_WARNING, "Could not read BSSID from driver.");
+ return NULL;
}
- wpa_hexdump(MSG_DEBUG, "WPA: Master key (dot1x)", buf, PMK_LEN);
- if (wpa_s->key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
- memcpy(wpa_s->pmk, buf, PMK_LEN);
- wpa_s->ext_pmk_received = 1;
- } else {
- wpa_printf(MSG_INFO, "WPA: Not in IEEE 802.1X mode - dropping "
- "dot1x PMK update (%d)", wpa_s->key_mgmt);
+ entry = wpa_s->conf->ssid;
+ while (entry) {
+ if (!entry->disabled &&
+ ssid_len == entry->ssid_len &&
+ memcmp(ssid, entry->ssid, ssid_len) == 0 &&
+ (!entry->bssid_set ||
+ memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
+ return entry;
+ entry = entry->next;
}
+
+ return NULL;
+}
+
+
+#ifndef CONFIG_NO_WPA
+static u8 * _wpa_alloc_eapol(void *wpa_s, u8 type,
+ const void *data, u16 data_len,
+ size_t *msg_len, void **data_pos)
+{
+ return wpa_alloc_eapol(wpa_s, type, data, data_len, msg_len, data_pos);
}
-static int wpa_supplicant_802_1x_init(struct wpa_supplicant *wpa_s)
+static int _wpa_ether_send(void *wpa_s, const u8 *dest, u16 proto,
+ const u8 *buf, size_t len)
{
- int s;
- struct sockaddr_un addr;
+ return wpa_ether_send(wpa_s, dest, proto, buf, len);
+}
- s = socket(AF_LOCAL, SOCK_DGRAM, 0);
- if (s < 0) {
- perror("socket");
- return -1;
- }
- memset(&addr, 0, sizeof(addr));
- addr.sun_family = AF_LOCAL;
- addr.sun_path[0] = '\0';
- snprintf(addr.sun_path + 1, sizeof(addr.sun_path) - 1,
- "wpa_supplicant");
- if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- perror("bind");
- close(s);
- return -1;
- }
+static void _wpa_supplicant_req_scan(void *wpa_s, int sec, int usec)
+{
+ wpa_supplicant_req_scan(wpa_s, sec, usec);
+}
- wpa_s->dot1x_s = s;
- eloop_register_read_sock(s, wpa_supplicant_dot1x_receive, wpa_s,
- NULL);
- return 0;
+
+static void _wpa_supplicant_cancel_auth_timeout(void *wpa_s)
+{
+ wpa_supplicant_cancel_auth_timeout(wpa_s);
}
-#endif /* CONFIG_XSUPPLICANT_IFACE */
+
+
+static void _wpa_supplicant_set_state(void *wpa_s, wpa_states state)
+{
+ wpa_supplicant_set_state(wpa_s, state);
+}
+
+
+static wpa_states _wpa_supplicant_get_state(void *wpa_s)
+{
+ return wpa_supplicant_get_state(wpa_s);
+}
+
+
+static void _wpa_supplicant_disassociate(void *wpa_s, int reason_code)
+{
+ wpa_supplicant_disassociate(wpa_s, reason_code);
+}
+
+
+static void _wpa_supplicant_deauthenticate(void *wpa_s, int reason_code)
+{
+ wpa_supplicant_deauthenticate(wpa_s, reason_code);
+}
+
+
+static struct wpa_ssid * _wpa_supplicant_get_ssid(void *wpa_s)
+{
+ return wpa_supplicant_get_ssid(wpa_s);
+}
+
+
+static int wpa_supplicant_get_bssid(void *wpa_s, u8 *bssid)
+{
+ return wpa_drv_get_bssid(wpa_s, bssid);
+}
+
+
+static int wpa_supplicant_set_key(void *wpa_s, 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)
+{
+ return wpa_drv_set_key(wpa_s, alg, addr, key_idx, set_tx, seq, seq_len,
+ key, key_len);
+}
+
+
+static int wpa_supplicant_add_pmkid(void *wpa_s,
+ const u8 *bssid, const u8 *pmkid)
+{
+ return wpa_drv_add_pmkid(wpa_s, bssid, pmkid);
+}
+
+
+static int wpa_supplicant_remove_pmkid(void *wpa_s,
+ const u8 *bssid, const u8 *pmkid)
+{
+ return wpa_drv_remove_pmkid(wpa_s, bssid, pmkid);
+}
+#endif /* CONFIG_NO_WPA */
static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
@@ -2054,34 +1568,67 @@ static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
}
-static void wpa_supplicant_fd_workaround(void)
+void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
+ const u8 *buf, size_t len)
{
- int s, i;
- /* When started from pcmcia-cs scripts, wpa_supplicant might start with
- * fd 0, 1, and 2 closed. This will cause some issues because many
- * places in wpa_supplicant are still printing out to stdout. As a
- * workaround, make sure that fd's 0, 1, and 2 are not used for other
- * sockets. */
- for (i = 0; i < 3; i++) {
- s = open("/dev/null", O_RDWR);
- if (s > 2) {
- close(s);
- break;
- }
+ struct wpa_supplicant *wpa_s = ctx;
+
+ wpa_printf(MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
+ wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
+
+ if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
+ wpa_printf(MSG_DEBUG, "Ignored received EAPOL frame since "
+ "no key management is configured");
+ return;
+ }
+
+ if (wpa_s->eapol_received == 0) {
+ /* Timeout for completing IEEE 802.1X and WPA authentication */
+ wpa_supplicant_req_auth_timeout(
+ wpa_s,
+ (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X ||
+ wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) ?
+ 70 : 10, 0);
+ }
+ wpa_s->eapol_received++;
+
+ if (wpa_s->countermeasures) {
+ wpa_printf(MSG_INFO, "WPA: Countermeasures - dropped EAPOL "
+ "packet");
+ return;
}
+
+ /* Source address of the incoming EAPOL frame could be compared to the
+ * current BSSID. However, it is possible that a centralized
+ * Authenticator could be using another MAC address than the BSSID of
+ * an AP, so just allow any address to be used for now. The replies are
+ * still sent to the current BSSID (if available), though. */
+
+ memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
+ if (wpa_s->key_mgmt != WPA_KEY_MGMT_PSK &&
+ eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
+ return;
+ wpa_drv_poll(wpa_s);
+ wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
}
-static int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s,
- int wait_for_interface)
+int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s,
+ int wait_for_interface)
{
static int interface_count = 0;
for (;;) {
+ if (wpa_s->driver->send_eapol) {
+ const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
+ if (addr)
+ memcpy(wpa_s->own_addr, addr, ETH_ALEN);
+ break;
+ }
wpa_s->l2 = l2_packet_init(wpa_s->ifname,
wpa_drv_get_mac_addr(wpa_s),
ETH_P_EAPOL,
- wpa_supplicant_rx_eapol, wpa_s);
+ wpa_supplicant_rx_eapol, wpa_s, 0);
if (wpa_s->l2)
break;
else if (!wait_for_interface)
@@ -2090,7 +1637,7 @@ static int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s,
sleep(5);
}
- if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
+ if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
fprintf(stderr, "Failed to get own L2 address\n");
return -1;
}
@@ -2098,9 +1645,21 @@ static int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s,
wpa_printf(MSG_DEBUG, "Own MAC address: " MACSTR,
MAC2STR(wpa_s->own_addr));
+ /* Backwards compatibility call to set_wpa() handler. This is called
+ * only just after init and just before deinit, so these handler can be
+ * used to implement same functionality. */
if (wpa_drv_set_wpa(wpa_s, 1) < 0) {
- fprintf(stderr, "Failed to enable WPA in the driver.\n");
- return -1;
+ struct wpa_driver_capa capa;
+ if (wpa_drv_get_capa(wpa_s, &capa) < 0 ||
+ !(capa.flags & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
+ WPA_DRIVER_CAPA_KEY_MGMT_WPA2))) {
+ wpa_printf(MSG_DEBUG, "Driver does not support WPA.");
+ /* Continue to allow non-WPA modes to be used. */
+ } else {
+ fprintf(stderr, "Failed to enable WPA in the "
+ "driver.\n");
+ return -1;
+ }
}
wpa_clear_keys(wpa_s, NULL);
@@ -2119,50 +1678,23 @@ static int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s,
}
-static void usage(void)
+static int wpa_supplicant_daemon(const char *pid_file)
{
- int i;
- printf("%s\n\n%s\n"
- "usage:\n"
- " wpa_supplicant [-BddehLqqvw] -i<ifname> -c<config file> "
- "[-D<driver>] \\\n"
- " [-P<pid file>] "
- "[-N -i<ifname> -c<conf> [-D<driver>] ...]\n"
- "\n"
- "drivers:\n",
- wpa_supplicant_version, wpa_supplicant_license);
-
- for (i = 0; wpa_supplicant_drivers[i]; i++) {
- printf(" %s = %s\n",
- wpa_supplicant_drivers[i]->name,
- wpa_supplicant_drivers[i]->desc);
+ wpa_printf(MSG_DEBUG, "Daemonize..");
+ if (daemon(0, 0)) {
+ perror("daemon");
+ return -1;
}
- printf("options:\n"
- " -B = run daemon in the background\n"
- " -d = increase debugging verbosity (-dd even more)\n"
- " -K = include keys (passwords, etc.) in debug output\n"
- " -t = include timestamp in debug messages\n"
-#ifdef CONFIG_XSUPPLICANT_IFACE
-#ifdef IEEE8021X_EAPOL
- " -e = use external IEEE 802.1X Supplicant (e.g., "
- "xsupplicant)\n"
- " (this disables the internal Supplicant)\n"
-#endif /* IEEE8021X_EAPOL */
-#endif /* CONFIG_XSUPPLICANT_IFACE */
- " -h = show this help text\n"
- " -L = show license (GPL and BSD)\n"
- " -q = decrease debugging verbosity (-qq even less)\n"
- " -v = show version\n"
- " -w = wait for interface to be added, if needed\n"
- " -N = start describing new interface\n");
-}
-
+ if (pid_file) {
+ FILE *f = fopen(pid_file, "w");
+ if (f) {
+ fprintf(f, "%u\n", getpid());
+ fclose(f);
+ }
+ }
-static void license(void)
-{
- printf("%s\n\n%s\n",
- wpa_supplicant_version, wpa_supplicant_full_license);
+ return 0;
}
@@ -2175,92 +1707,170 @@ static struct wpa_supplicant * wpa_supplicant_alloc(void)
return NULL;
memset(wpa_s, 0, sizeof(*wpa_s));
wpa_s->ctrl_sock = -1;
-#ifdef CONFIG_XSUPPLICANT_IFACE
- wpa_s->dot1x_s = -1;
-#endif /* CONFIG_XSUPPLICANT_IFACE */
+ wpa_s->scan_req = 1;
return wpa_s;
}
-static int wpa_supplicant_init(struct wpa_supplicant *wpa_s,
- const char *confname, const char *driver,
- const char *ifname)
+static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
+ struct wpa_interface *iface)
{
wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
- "'%s'", ifname, confname, driver ? driver : "default");
+ "'%s' ctrl_interface '%s'", iface->ifname,
+ iface->confname ? iface->confname : "N/A",
+ iface->driver ? iface->driver : "default",
+ iface->ctrl_interface ? iface->ctrl_interface : "N/A");
- if (wpa_supplicant_set_driver(wpa_s, driver) < 0) {
+ if (wpa_supplicant_set_driver(wpa_s, iface->driver) < 0) {
return -1;
}
- if (confname) {
- wpa_s->confname = rel2abs_path(confname);
+ if (iface->confname) {
+#ifdef CONFIG_BACKEND_FILE
+ wpa_s->confname = rel2abs_path(iface->confname);
if (wpa_s->confname == NULL) {
wpa_printf(MSG_ERROR, "Failed to get absolute path "
- "for configuration file '%s'.", confname);
+ "for configuration file '%s'.",
+ iface->confname);
return -1;
}
wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
- confname, wpa_s->confname);
+ iface->confname, wpa_s->confname);
+#else /* CONFIG_BACKEND_FILE */
+ wpa_s->confname = strdup(iface->confname);
+#endif /* CONFIG_BACKEND_FILE */
wpa_s->conf = wpa_config_read(wpa_s->confname);
if (wpa_s->conf == NULL) {
- printf("Failed to read configuration file '%s'.\n",
- wpa_s->confname);
+ printf("Failed to read read or parse configuration "
+ "'%s'.\n", wpa_s->confname);
return -1;
}
- }
- if (wpa_s->conf == NULL || wpa_s->conf->ssid == NULL) {
- usage();
- printf("\nNo networks (SSID) configured.\n");
+ /*
+ * Override ctrl_interface and driver_param if set on command
+ * line.
+ */
+ if (iface->ctrl_interface) {
+ free(wpa_s->conf->ctrl_interface);
+ wpa_s->conf->ctrl_interface =
+ strdup(iface->ctrl_interface);
+ }
+
+ if (iface->driver_param) {
+ free(wpa_s->conf->driver_param);
+ wpa_s->conf->driver_param =
+ strdup(iface->driver_param);
+ }
+ } else
+ wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
+ iface->driver_param);
+
+ if (wpa_s->conf == NULL) {
+ printf("\nNo configuration found.\n");
return -1;
}
- if (ifname == NULL) {
- usage();
+ if (iface->ifname == NULL) {
printf("\nInterface name is required.\n");
return -1;
}
- if (strlen(ifname) >= sizeof(wpa_s->ifname)) {
- printf("Too long interface name '%s'.\n", ifname);
+ if (strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
+ printf("Too long interface name '%s'.\n", iface->ifname);
+ return -1;
+ }
+ strncpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
+
+ return 0;
+}
+
+
+static int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s)
+{
+#ifdef IEEE8021X_EAPOL
+ struct eapol_ctx *ctx;
+ ctx = malloc(sizeof(*ctx));
+ if (ctx == NULL) {
+ printf("Failed to allocate EAPOL context.\n");
+ return -1;
+ }
+
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->ctx = wpa_s;
+ ctx->msg_ctx = wpa_s;
+ ctx->eapol_send_ctx = wpa_s;
+ ctx->preauth = 0;
+ ctx->eapol_done_cb = wpa_supplicant_notify_eapol_done;
+ ctx->eapol_send = wpa_supplicant_eapol_send;
+ ctx->set_wep_key = wpa_eapol_set_wep_key;
+ ctx->set_config_blob = wpa_supplicant_set_config_blob;
+ ctx->get_config_blob = wpa_supplicant_get_config_blob;
+ ctx->opensc_engine_path = wpa_s->conf->opensc_engine_path;
+ ctx->pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path;
+ ctx->pkcs11_module_path = wpa_s->conf->pkcs11_module_path;
+ wpa_s->eapol = eapol_sm_init(ctx);
+ if (wpa_s->eapol == NULL) {
+ free(ctx);
+ printf("Failed to initialize EAPOL state machines.\n");
return -1;
}
- strncpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
+#endif /* IEEE8021X_EAPOL */
return 0;
}
-static int wpa_supplicant_init2(struct wpa_supplicant *wpa_s,
- int disable_eapol, int wait_for_interface)
+static int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s)
+{
+#ifndef CONFIG_NO_WPA
+ struct wpa_sm_ctx *ctx;
+ ctx = malloc(sizeof(*ctx));
+ if (ctx == NULL) {
+ printf("Failed to allocate WPA context.\n");
+ return -1;
+ }
+
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->ctx = wpa_s;
+ ctx->set_state = _wpa_supplicant_set_state;
+ ctx->get_state = _wpa_supplicant_get_state;
+ ctx->req_scan = _wpa_supplicant_req_scan;
+ ctx->deauthenticate = _wpa_supplicant_deauthenticate;
+ ctx->disassociate = _wpa_supplicant_disassociate;
+ ctx->set_key = wpa_supplicant_set_key;
+ ctx->scan = wpa_supplicant_scan;
+ ctx->get_ssid = _wpa_supplicant_get_ssid;
+ ctx->get_bssid = wpa_supplicant_get_bssid;
+ ctx->ether_send = _wpa_ether_send;
+ ctx->get_beacon_ie = wpa_supplicant_get_beacon_ie;
+ ctx->alloc_eapol = _wpa_alloc_eapol;
+ ctx->cancel_auth_timeout = _wpa_supplicant_cancel_auth_timeout;
+ ctx->add_pmkid = wpa_supplicant_add_pmkid;
+ ctx->remove_pmkid = wpa_supplicant_remove_pmkid;
+ ctx->set_config_blob = wpa_supplicant_set_config_blob;
+ ctx->get_config_blob = wpa_supplicant_get_config_blob;
+
+ wpa_s->wpa = wpa_sm_init(ctx);
+ if (wpa_s->wpa == NULL) {
+ fprintf(stderr, "Failed to initialize WPA state machine\n");
+ return -1;
+ }
+#endif /* CONFIG_NO_WPA */
+
+ return 0;
+}
+
+
+static int wpa_supplicant_init_iface2(struct wpa_supplicant *wpa_s,
+ int wait_for_interface)
{
const char *ifname;
wpa_printf(MSG_DEBUG, "Initializing interface (2) '%s'",
wpa_s->ifname);
- if (!disable_eapol) {
- struct eapol_ctx *ctx;
- ctx = malloc(sizeof(*ctx));
- if (ctx == NULL) {
- printf("Failed to allocate EAPOL context.\n");
- return -1;
- }
- memset(ctx, 0, sizeof(*ctx));
- ctx->ctx = wpa_s;
- ctx->msg_ctx = wpa_s;
- ctx->preauth = 0;
- ctx->eapol_done_cb = wpa_supplicant_notify_eapol_done;
- ctx->eapol_send = wpa_eapol_send;
- ctx->set_wep_key = wpa_eapol_set_wep_key;
- wpa_s->eapol = eapol_sm_init(ctx);
- if (wpa_s->eapol == NULL) {
- free(ctx);
- printf("Failed to initialize EAPOL state machines.\n");
- return -1;
- }
- }
+ if (wpa_supplicant_init_eapol(wpa_s) < 0)
+ return -1;
/* RSNA Supplicant Key Management - INITIALIZE */
eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
@@ -2275,6 +1885,11 @@ static int wpa_supplicant_init2(struct wpa_supplicant *wpa_s,
fprintf(stderr, "Failed to initialize driver interface\n");
return -1;
}
+ if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
+ fprintf(stderr, "Driver interface rejected driver_param "
+ "'%s'\n", wpa_s->conf->driver_param);
+ return -1;
+ }
ifname = wpa_drv_get_ifname(wpa_s);
if (ifname && strcmp(ifname, wpa_s->ifname) != 0) {
@@ -2283,10 +1898,41 @@ static int wpa_supplicant_init2(struct wpa_supplicant *wpa_s,
strncpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
}
- wpa_s->renew_snonce = 1;
+ if (wpa_supplicant_init_wpa(wpa_s) < 0)
+ return -1;
+
+ wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname);
+ wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
+ wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
+
+ if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
+ wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
+ wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
+ fprintf(stderr, "Invalid WPA parameter value for "
+ "dot11RSNAConfigPMKLifetime\n");
+ return -1;
+ }
+
+ if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
+ wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
+ wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
+ fprintf(stderr, "Invalid WPA parameter value for "
+ "dot11RSNAConfigPMKReauthThreshold\n");
+ return -1;
+ }
+
+ if (wpa_s->conf->dot11RSNAConfigSATimeout &&
+ wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
+ wpa_s->conf->dot11RSNAConfigSATimeout)) {
+ fprintf(stderr, "Invalid WPA parameter value for "
+ "dot11RSNAConfigSATimeout\n");
+ return -1;
+ }
+
if (wpa_supplicant_driver_init(wpa_s, wait_for_interface) < 0) {
return -1;
}
+ wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
if (wpa_supplicant_ctrl_iface_init(wpa_s)) {
printf("Failed to initialize control interface '%s'.\n"
@@ -2300,18 +1946,18 @@ static int wpa_supplicant_init2(struct wpa_supplicant *wpa_s,
return -1;
}
-#ifdef CONFIG_XSUPPLICANT_IFACE
- if (disable_eapol)
- wpa_supplicant_802_1x_init(wpa_s);
-#endif /* CONFIG_XSUPPLICANT_IFACE */
-
return 0;
}
-static void wpa_supplicant_deinit(struct wpa_supplicant *wpa_s)
+static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s)
{
if (wpa_s->drv_priv) {
+ wpa_supplicant_deauthenticate(wpa_s, REASON_DEAUTH_LEAVING);
+
+ /* Backwards compatibility call to set_wpa() handler. This is
+ * called only just after init and just before deinit, so these
+ * handler can be used to implement same functionality. */
if (wpa_drv_set_wpa(wpa_s, 0) < 0) {
fprintf(stderr, "Failed to disable WPA in the "
"driver.\n");
@@ -2327,137 +1973,176 @@ static void wpa_supplicant_deinit(struct wpa_supplicant *wpa_s)
}
-int main(int argc, char *argv[])
+/**
+ * wpa_supplicant_add_iface - Add a new network interface
+ * @global: Pointer to global data from wpa_supplicant_init()
+ * @iface: Interface configuration options
+ * Returns: Pointer to the created interface or %NULL on failure
+ *
+ * This function is used to add new network interfaces for %wpa_supplicant.
+ * This can be called before wpa_supplicant_run() to add interfaces before the
+ * main event loop has been started. In addition, new interfaces can be added
+ * dynamically while %wpa_supplicant is already running. This could happen,
+ * e.g., when a hotplug network adapter is inserted.
+ */
+struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
+ struct wpa_interface *iface)
{
- struct wpa_supplicant *head, *wpa_s;
- int c;
- const char *confname, *driver, *ifname;
- char *pid_file = NULL;
- int daemonize = 0, wait_for_interface = 0, disable_eapol = 0, exitcode;
+ struct wpa_supplicant *wpa_s;
-#ifdef CONFIG_NATIVE_WINDOWS
- WSADATA wsaData;
- if (WSAStartup(MAKEWORD(2, 0), &wsaData)) {
- printf("Could not find a usable WinSock.dll\n");
- return -1;
- }
-#endif /* CONFIG_NATIVE_WINDOWS */
+ if (global == NULL || iface == NULL)
+ return NULL;
- head = wpa_s = wpa_supplicant_alloc();
+ wpa_s = wpa_supplicant_alloc();
if (wpa_s == NULL)
- return -1;
- wpa_s->head = head;
+ return NULL;
- wpa_supplicant_fd_workaround();
- eloop_init(head);
+ if (wpa_supplicant_init_iface(wpa_s, iface) ||
+ wpa_supplicant_init_iface2(wpa_s,
+ global->params.wait_for_interface)) {
+ wpa_printf(MSG_DEBUG, "Failed to add interface %s",
+ iface->ifname);
+ wpa_supplicant_deinit_iface(wpa_s);
+ free(wpa_s);
+ return NULL;
+ }
- ifname = confname = driver = NULL;
+ wpa_s->global = global;
+ wpa_s->next = global->ifaces;
+ global->ifaces = wpa_s;
- for (;;) {
- c = getopt(argc, argv, "Bc:D:dehi:KLNP:qtvw");
- if (c < 0)
- break;
- switch (c) {
- case 'B':
- daemonize++;
- break;
- case 'c':
- confname = optarg;
- break;
- case 'D':
- driver = optarg;
- break;
- case 'd':
- wpa_debug_level--;
- break;
-#ifdef CONFIG_XSUPPLICANT_IFACE
-#ifdef IEEE8021X_EAPOL
- case 'e':
- disable_eapol++;
- break;
-#endif /* IEEE8021X_EAPOL */
-#endif /* CONFIG_XSUPPLICANT_IFACE */
- case 'h':
- usage();
- return -1;
- case 'i':
- ifname = optarg;
- break;
- case 'K':
- wpa_debug_show_keys++;
- break;
- case 'L':
- license();
- return -1;
- case 'P':
- pid_file = rel2abs_path(optarg);
- break;
- case 'q':
- wpa_debug_level++;
- break;
- case 't':
- wpa_debug_timestamp++;
- break;
- case 'v':
- printf("%s\n", wpa_supplicant_version);
- return -1;
- case 'w':
- wait_for_interface++;
- break;
- case 'N':
- if (wpa_supplicant_init(wpa_s, confname, driver,
- ifname))
- return -1;
- wpa_s->next = wpa_supplicant_alloc();
- wpa_s = wpa_s->next;
- if (wpa_s == NULL)
- return -1;
- wpa_s->head = head;
- ifname = confname = driver = NULL;
- break;
- default:
- usage();
+ wpa_printf(MSG_DEBUG, "Added interface %s", wpa_s->ifname);
+
+ return wpa_s;
+}
+
+
+/**
+ * wpa_supplicant_remove_iface - Remove a network interface
+ * @global: Pointer to global data from wpa_supplicant_init()
+ * @wpa_s: Pointer to the network interface to be removed
+ * Returns: 0 if interface was removed, -1 if interface was not found
+ *
+ * This function can be used to dynamically remove network interfaces from
+ * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
+ * addition, this function is used to remove all remaining interdaces when
+ * %wpa_supplicant is terminated.
+ */
+int wpa_supplicant_remove_iface(struct wpa_global *global,
+ struct wpa_supplicant *wpa_s)
+{
+ struct wpa_supplicant *prev;
+
+ /* Remove interface from the global list of interfaces */
+ prev = global->ifaces;
+ if (prev == wpa_s) {
+ global->ifaces = wpa_s->next;
+ } else {
+ while (prev && prev->next != wpa_s)
+ prev = prev->next;
+ if (prev == NULL)
return -1;
- }
+ prev->next = wpa_s->next;
}
- if (wpa_supplicant_init(wpa_s, confname, driver, ifname))
- return -1;
+ wpa_printf(MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
- exitcode = 0;
+ wpa_supplicant_deinit_iface(wpa_s);
+ free(wpa_s);
- if (wait_for_interface && daemonize) {
- wpa_printf(MSG_DEBUG, "Daemonize..");
- if (daemon(0, 0)) {
- perror("daemon");
- exitcode = -1;
- goto cleanup;
- }
+ return 0;
+}
+
+
+/**
+ * wpa_supplicant_get_iface - Get a new network interface
+ * @global: Pointer to global data from wpa_supplicant_init()
+ * @ifname: Interface name
+ * Returns: Pointer to the interface or %NULL if not found
+ */
+struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
+ const char *ifname)
+{
+ struct wpa_supplicant *wpa_s;
+
+ for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
+ if (strcmp(wpa_s->ifname, ifname) == 0)
+ return wpa_s;
}
+ return NULL;
+}
- for (wpa_s = head; wpa_s; wpa_s = wpa_s->next) {
- if (wpa_supplicant_init2(wpa_s, disable_eapol,
- wait_for_interface)) {
- exitcode = -1;
- goto cleanup;
- }
+
+/**
+ * wpa_supplicant_init - Initialize %wpa_supplicant
+ * @params: Parameters for %wpa_supplicant
+ * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
+ *
+ * This function is used to initialize %wpa_supplicant. After successful
+ * initialization, the returned data pointer can be used to add and remove
+ * network interfaces, and eventually, to deinitialize %wpa_supplicant.
+ */
+struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
+{
+ struct wpa_global *global;
+
+ if (params == NULL)
+ return NULL;
+ global = malloc(sizeof(*global));
+ if (global == NULL)
+ return NULL;
+ memset(global, 0, sizeof(*global));
+ global->params.daemonize = params->daemonize;
+ global->params.wait_for_interface = params->wait_for_interface;
+ global->params.wait_for_monitor = params->wait_for_monitor;
+ if (params->pid_file)
+ global->params.pid_file = strdup(params->pid_file);
+ if (params->ctrl_interface)
+ global->params.ctrl_interface = strdup(params->ctrl_interface);
+ wpa_debug_level = global->params.wpa_debug_level =
+ params->wpa_debug_level;
+ wpa_debug_show_keys = global->params.wpa_debug_show_keys =
+ params->wpa_debug_show_keys;
+ wpa_debug_timestamp = global->params.wpa_debug_timestamp =
+ params->wpa_debug_timestamp;
+
+ eloop_init(global);
+
+ if (wpa_supplicant_global_ctrl_iface_init(global)) {
+ eloop_destroy();
+ return NULL;
}
- if (!wait_for_interface && daemonize) {
- wpa_printf(MSG_DEBUG, "Daemonize..");
- if (daemon(0, 0)) {
- perror("daemon");
- exitcode = -1;
- goto cleanup;
- }
+ if (global->params.wait_for_interface && global->params.daemonize &&
+ wpa_supplicant_daemon(global->params.pid_file)) {
+ eloop_destroy();
+ return NULL;
}
- if (pid_file) {
- FILE *f = fopen(pid_file, "w");
- if (f) {
- fprintf(f, "%u\n", getpid());
- fclose(f);
- }
+ return global;
+}
+
+
+/**
+ * wpa_supplicant_run - Run the %wpa_supplicant main event loop
+ * @global: Pointer to global data from wpa_supplicant_init()
+ * Returns: 0 after successful event loop run, -1 on failure
+ *
+ * This function starts the main event loop and continues running as long as
+ * there are any remaining events. In most cases, this function is running as
+ * long as the %wpa_supplicant process in still in use.
+ */
+int wpa_supplicant_run(struct wpa_global *global)
+{
+ struct wpa_supplicant *wpa_s;
+
+ if (!global->params.wait_for_interface && global->params.daemonize &&
+ wpa_supplicant_daemon(global->params.pid_file))
+ return -1;
+
+ if (global->params.wait_for_monitor) {
+ for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
+ wpa_supplicant_ctrl_iface_wait(wpa_s);
}
eloop_register_signal(SIGINT, wpa_supplicant_terminate, NULL);
@@ -2468,30 +2153,34 @@ int main(int argc, char *argv[])
eloop_run();
- for (wpa_s = head; wpa_s; wpa_s = wpa_s->next) {
- wpa_supplicant_deauthenticate(wpa_s, REASON_DEAUTH_LEAVING);
- }
+ return 0;
+}
-cleanup:
- wpa_s = head;
- while (wpa_s) {
- struct wpa_supplicant *prev;
- wpa_supplicant_deinit(wpa_s);
- prev = wpa_s;
- wpa_s = wpa_s->next;
- free(prev);
- }
+
+/**
+ * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
+ * @global: Pointer to global data from wpa_supplicant_init()
+ *
+ * This function is called to deinitialize %wpa_supplicant and to free all
+ * allocated resources. Remaining network interfaces will also be removed.
+ */
+void wpa_supplicant_deinit(struct wpa_global *global)
+{
+ if (global == NULL)
+ return;
+
+ while (global->ifaces)
+ wpa_supplicant_remove_iface(global, global->ifaces);
+
+ wpa_supplicant_global_ctrl_iface_deinit(global);
eloop_destroy();
- if (pid_file) {
- unlink(pid_file);
- free(pid_file);
+ if (global->params.pid_file) {
+ unlink(global->params.pid_file);
+ free(global->params.pid_file);
}
+ free(global->params.ctrl_interface);
-#ifdef CONFIG_NATIVE_WINDOWS
- WSACleanup();
-#endif /* CONFIG_NATIVE_WINDOWS */
-
- return exitcode;
+ free(global);
}
OpenPOWER on IntegriCloud