diff options
author | sam <sam@FreeBSD.org> | 2006-03-07 05:44:45 +0000 |
---|---|---|
committer | sam <sam@FreeBSD.org> | 2006-03-07 05:44:45 +0000 |
commit | f87f3cf9d3ac68ade33194941f85722ffdff2195 (patch) | |
tree | 72b7a4837fa3c101b02d8b1b2b0cc478c8b033e3 | |
parent | 8b3f1ba26b4b0c34e27cf045b5873f791d667e6e (diff) | |
download | FreeBSD-src-f87f3cf9d3ac68ade33194941f85722ffdff2195.zip FreeBSD-src-f87f3cf9d3ac68ade33194941f85722ffdff2195.tar.gz |
resolve merge conflicts
MFC after: 2 weeks
-rw-r--r-- | contrib/wpa_supplicant/FREEBSD-Xlist | 4 | ||||
-rw-r--r-- | contrib/wpa_supplicant/common.h | 90 | ||||
-rw-r--r-- | contrib/wpa_supplicant/developer.txt | 458 | ||||
-rw-r--r-- | contrib/wpa_supplicant/events.c | 15 | ||||
-rw-r--r-- | contrib/wpa_supplicant/hostap_common.h | 557 | ||||
-rw-r--r-- | contrib/wpa_supplicant/wpa_ctrl.c | 18 | ||||
-rw-r--r-- | contrib/wpa_supplicant/wpa_supplicant.c | 2021 |
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(¶ms, 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); } |