#include "eapol_supp/eapol_supp_sm.h"
#include "eap_peer/eap.h"
#include "eap_server/eap_methods.h"
-#include "wpa.h"
+#include "rsn_supp/wpa.h"
#include "eloop.h"
#include "config.h"
#include "l2_packet/l2_packet.h"
#include "driver_i.h"
#include "ctrl_iface.h"
#include "pcsc_funcs.h"
-#include "version.h"
-#include "preauth.h"
-#include "pmksa_cache.h"
-#include "wpa_ctrl.h"
+#include "common/version.h"
+#include "rsn_supp/preauth.h"
+#include "rsn_supp/pmksa_cache.h"
+#include "common/wpa_ctrl.h"
#include "mlme.h"
-#include "ieee802_11_defs.h"
+#include "common/ieee802_11_defs.h"
#include "blacklist.h"
#include "wpas_glue.h"
#include "wps_supplicant.h"
{
u8 key[32];
size_t keylen;
- wpa_alg alg;
+ enum wpa_alg alg;
u8 seq[6] = { 0 };
/* IBSS/WPA-None uses only one key (Group) for both receiving and
* @state: State (wpa_state; WPA_*)
* Returns: The state name as a printable text string
*/
-const char * wpa_supplicant_state_txt(int state)
+const char * wpa_supplicant_state_txt(enum wpa_states state)
{
switch (state) {
case WPA_DISCONNECTED:
* This function is called whenever the connection state changes, e.g.,
* association is completed for WPA/WPA2 4-Way Handshake is started.
*/
-void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, wpa_states state)
+void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
+ enum wpa_states state)
{
wpa_printf(MSG_DEBUG, "State: %s -> %s",
wpa_supplicant_state_txt(wpa_s->wpa_state),
}
-static void wpa_supplicant_terminate(int sig, void *eloop_ctx,
- void *signal_ctx)
+void wpa_supplicant_terminate_proc(struct wpa_global *global)
{
- struct wpa_global *global = eloop_ctx;
+ int pending = 0;
+#ifdef CONFIG_WPS
+ struct wpa_supplicant *wpa_s = global->ifaces;
+ while (wpa_s) {
+ if (wpas_wps_terminate_pending(wpa_s) == 1)
+ pending = 1;
+ wpa_s = wpa_s->next;
+ }
+#endif /* CONFIG_WPS */
+ if (pending)
+ return;
+ eloop_terminate();
+}
+
+
+static void wpa_supplicant_terminate(int sig, void *signal_ctx)
+{
+ struct wpa_global *global = signal_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();
+ wpa_supplicant_terminate_proc(global);
}
static void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
{
- wpa_states old_state = wpa_s->wpa_state;
+ enum wpa_states old_state = wpa_s->wpa_state;
wpa_s->pairwise_cipher = 0;
wpa_s->group_cipher = 0;
wpa_s->mgmt_group_cipher = 0;
}
-static void wpa_supplicant_reconfig(int sig, void *eloop_ctx,
- void *signal_ctx)
+static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
{
- struct wpa_global *global = eloop_ctx;
+ struct wpa_global *global = signal_ctx;
struct wpa_supplicant *wpa_s;
wpa_printf(MSG_DEBUG, "Signal %d received - reconfiguring", sig);
for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
- eloop_terminate();
+ wpa_supplicant_terminate_proc(global);
}
}
}
-static wpa_cipher cipher_suite2driver(int cipher)
+static enum wpa_cipher cipher_suite2driver(int cipher)
{
switch (cipher) {
case WPA_CIPHER_NONE:
}
-static wpa_key_mgmt key_mgmt2driver(int key_mgmt)
+static enum wpa_key_mgmt key_mgmt2driver(int key_mgmt)
{
switch (key_mgmt) {
case WPA_KEY_MGMT_NONE:
size_t wpa_ie_len;
int use_crypt, ret, i, bssid_changed;
int algs = AUTH_ALG_OPEN_SYSTEM;
- wpa_cipher cipher_pairwise, cipher_group;
+ enum wpa_cipher cipher_pairwise, cipher_group;
struct wpa_driver_associate_params params;
int wep_keys_set = 0;
struct wpa_driver_capa capa;
int assoc_failed = 0;
struct wpa_ssid *old_ssid;
- if (ssid->mode == 2) {
+ if (ssid->mode == IEEE80211_MODE_AP) {
#ifdef CONFIG_AP
if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
wpa_printf(MSG_INFO, "Driver does not support AP "
return;
}
- if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) {
+ if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
+ ssid->mode == IEEE80211_MODE_INFRA) {
sme_authenticate(wpa_s, bss, ssid);
return;
}
* previous association. */
wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
- if (wpa_drv_set_mode(wpa_s, ssid->mode)) {
- wpa_printf(MSG_WARNING, "Failed to set operating mode");
- assoc_failed = 1;
- }
-
#ifdef IEEE8021X_EAPOL
if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
if (ssid->leap) {
wpa_printf(MSG_DEBUG, "Overriding auth_alg selection: 0x%x",
algs);
}
- wpa_drv_set_auth_alg(wpa_s, algs);
if (bss && (wpa_scan_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
wpa_scan_get_ie(bss, WLAN_EID_RSN)) &&
wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
}
- wpa_drv_set_drop_unencrypted(wpa_s, use_crypt);
wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
os_memset(¶ms, 0, sizeof(params));
if (bss) {
* per-BSSID authentication.
*/
wpa_supplicant_cancel_auth_timeout(wpa_s);
- wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
#endif /* CONFIG_IBSS_RSN */
} else {
/* Timeout for IEEE 802.11 authentication and association */
wpa_s->reassociate = 1;
wpa_supplicant_req_scan(wpa_s, 0, 0);
- wpas_notify_network_selected(wpa_s, ssid);
+ if (ssid)
+ wpas_notify_network_selected(wpa_s, ssid);
}
}
-static struct wpa_scan_results * wpa_supplicant_get_scan_results_old(
- struct wpa_supplicant *wpa_s)
+static void notify_bss_changes(struct wpa_supplicant *wpa_s,
+ u8 (*prev_bssids)[ETH_ALEN], int prev_num,
+ struct wpa_scan_results *new)
{
-#define SCAN_AP_LIMIT 128
- struct wpa_scan_result *results;
- int num, i;
- struct wpa_scan_results *res;
-
- results = os_malloc(SCAN_AP_LIMIT * sizeof(struct wpa_scan_result));
- if (results == NULL) {
- wpa_printf(MSG_WARNING, "Failed to allocate memory for scan "
- "results");
- return NULL;
- }
+ int new_num, i, j;
- num = wpa_drv_get_scan_results(wpa_s, results, SCAN_AP_LIMIT);
- wpa_printf(MSG_DEBUG, "Scan results: %d", num);
- if (num < 0) {
- wpa_printf(MSG_DEBUG, "Failed to get scan results");
- os_free(results);
- return NULL;
- }
- if (num > SCAN_AP_LIMIT) {
- wpa_printf(MSG_INFO, "Not enough room for all APs (%d < %d)",
- num, SCAN_AP_LIMIT);
- num = SCAN_AP_LIMIT;
- }
-
- /* Convert old scan result data structure to the new one */
- res = os_zalloc(sizeof(*res));
- if (res == NULL) {
- os_free(results);
- return NULL;
- }
- res->res = os_zalloc(num * sizeof(struct wpa_scan_res *));
- if (res->res == NULL) {
- os_free(results);
- os_free(res);
- return NULL;
- }
+ new_num = new != NULL ? new->num : 0;
+ if (prev_bssids == NULL)
+ prev_num = 0;
- for (i = 0; i < num; i++) {
- struct wpa_scan_result *bss = &results[i];
- struct wpa_scan_res *r;
- size_t ie_len;
- u8 *pos;
-
- ie_len = 2 + bss->ssid_len + bss->rsn_ie_len + bss->wpa_ie_len;
- if (bss->maxrate)
- ie_len += 3;
- if (bss->mdie_present)
- ie_len += 5;
-
- r = os_zalloc(sizeof(*r) + ie_len);
- if (r == NULL)
- break;
-
- os_memcpy(r->bssid, bss->bssid, ETH_ALEN);
- r->freq = bss->freq;
- r->caps = bss->caps;
- r->qual = bss->qual;
- r->noise = bss->noise;
- r->level = bss->level;
- r->tsf = bss->tsf;
- r->ie_len = ie_len;
-
- pos = (u8 *) (r + 1);
-
- /* SSID IE */
- *pos++ = WLAN_EID_SSID;
- *pos++ = bss->ssid_len;
- os_memcpy(pos, bss->ssid, bss->ssid_len);
- pos += bss->ssid_len;
-
- if (bss->maxrate) {
- /* Fake Supported Rate IE to include max rate */
- *pos++ = WLAN_EID_SUPP_RATES;
- *pos++ = 1;
- *pos++ = bss->maxrate;
+ for (i = 0; i < prev_num; i++) {
+ for (j = 0; j < new_num; j++) {
+ if (!os_memcmp(prev_bssids[i], new->res[j]->bssid,
+ ETH_ALEN))
+ break;
}
-
- if (bss->rsn_ie_len) {
- os_memcpy(pos, bss->rsn_ie, bss->rsn_ie_len);
- pos += bss->rsn_ie_len;
- }
-
- if (bss->mdie_present) {
- os_memcpy(pos, bss->mdie, 5);
- pos += 5;
+ if (j == new_num)
+ wpas_notify_bss_removed(wpa_s, prev_bssids[i]);
+ }
+ for (i = 0; i < new_num; i++) {
+ for (j = 0; j < prev_num; j++) {
+ if (!os_memcmp(new->res[i]->bssid, prev_bssids[j],
+ ETH_ALEN))
+ break;
}
-
- if (bss->wpa_ie_len) {
- os_memcpy(pos, bss->wpa_ie, bss->wpa_ie_len);
- pos += bss->wpa_ie_len;
- }
-
- res->res[res->num++] = r;
+ if (j == prev_num)
+ wpas_notify_bss_added(wpa_s, new->res[i]->bssid);
}
-
- os_free(results);
-
- return res;
}
*/
int wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s)
{
- int ret;
+ int ret, i, prev_scan_res_num;
+ u8 (*prev_scan_bssids)[ETH_ALEN];
+
+ prev_scan_res_num = wpa_s->scan_res ? wpa_s->scan_res->num : 0;
+ prev_scan_bssids = os_malloc(prev_scan_res_num * ETH_ALEN);
+
+ if (prev_scan_bssids) {
+ for (i = 0; i < prev_scan_res_num; i++) {
+ os_memcpy(prev_scan_bssids[i],
+ wpa_s->scan_res->res[i]->bssid, ETH_ALEN);
+ }
+ } else {
+ wpa_printf(MSG_WARNING, "Not enough memory for old scan "
+ "results list");
+ prev_scan_res_num = 0;
+ }
wpa_scan_results_free(wpa_s->scan_res);
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME)
wpa_s->scan_res = ieee80211_sta_get_scan_results(wpa_s);
- else if (wpa_s->driver->get_scan_results2 == NULL)
- wpa_s->scan_res = wpa_supplicant_get_scan_results_old(wpa_s);
else
wpa_s->scan_res = wpa_drv_get_scan_results2(wpa_s);
if (wpa_s->scan_res == NULL) {
wpa_scan_sort_results(wpa_s->scan_res);
}
+ notify_bss_changes(wpa_s, prev_scan_bssids, prev_scan_res_num,
+ wpa_s->scan_res);
+ os_free(prev_scan_bssids);
+
return ret;
}
if (name == NULL) {
/* default to first driver in the list */
wpa_s->driver = wpa_drivers[0];
+ wpa_s->global_drv_priv = wpa_s->global->drv_priv[0];
return 0;
}
os_strncmp(name, wpa_drivers[i]->name, len) ==
0) {
wpa_s->driver = wpa_drivers[i];
+ wpa_s->global_drv_priv = wpa_s->global->drv_priv[i];
return 0;
}
}
if (wpa_s->eapol_received == 0 &&
(!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
- wpa_s->wpa_state != WPA_COMPLETED)) {
+ wpa_s->wpa_state != WPA_COMPLETED) &&
+ (wpa_s->current_ssid == NULL ||
+ wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
/* Timeout for completing IEEE 802.1X and WPA authentication */
wpa_supplicant_req_auth_timeout(
wpa_s,
}
}
- /* 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) {
- 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 {
- wpa_printf(MSG_ERROR, "Failed to enable WPA in the "
- "driver.");
- return -1;
- }
- }
-
wpa_clear_keys(wpa_s, NULL);
/* Make sure that TKIP countermeasures are not left enabled (could
* happen if wpa_supplicant is killed during countermeasures. */
wpa_drv_set_countermeasures(wpa_s, 0);
- wpa_drv_set_drop_unencrypted(wpa_s, 1);
-
wpa_printf(MSG_DEBUG, "RSN: flushing PMKID list in the driver");
wpa_drv_flush_pmkid(wpa_s);
if (wpa_s == NULL)
return NULL;
wpa_s->scan_req = 1;
+ wpa_s->new_connection = 1;
return wpa_s;
}
wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
if (wpa_s->drv_priv == NULL) {
const char *pos;
- pos = os_strchr(driver, ',');
+ pos = driver ? os_strchr(driver, ',') : NULL;
if (pos) {
wpa_printf(MSG_DEBUG, "Failed to initialize driver "
"interface - try next driver wrapper");
wpa_supplicant_deauthenticate(wpa_s,
WLAN_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) {
- wpa_printf(MSG_ERROR, "Failed to disable WPA in the "
- "driver.");
- }
-
- wpa_drv_set_drop_unencrypted(wpa_s, 0);
wpa_drv_set_countermeasures(wpa_s, 0);
wpa_clear_keys(wpa_s, NULL);
}
struct wpa_interface *iface)
{
struct wpa_supplicant *wpa_s;
+ struct wpa_interface t_iface;
if (global == NULL || iface == NULL)
return NULL;
if (wpa_s == NULL)
return NULL;
- if (wpa_supplicant_init_iface(wpa_s, iface)) {
+ wpa_s->global = global;
+
+ t_iface = *iface;
+ if (global->params.override_driver) {
+ wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
+ "('%s' -> '%s')",
+ iface->driver, global->params.override_driver);
+ t_iface.driver = global->params.override_driver;
+ }
+ if (global->params.override_ctrl_interface) {
+ wpa_printf(MSG_DEBUG, "Override interface parameter: "
+ "ctrl_interface ('%s' -> '%s')",
+ iface->ctrl_interface,
+ global->params.override_ctrl_interface);
+ t_iface.ctrl_interface =
+ global->params.override_ctrl_interface;
+ }
+ if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
wpa_printf(MSG_DEBUG, "Failed to add interface %s",
iface->ifname);
wpa_supplicant_deinit_iface(wpa_s);
return NULL;
}
- wpa_s->global = global;
-
/* Notify the control interfaces about new iface */
if (wpas_notify_iface_added(wpa_s)) {
wpa_supplicant_deinit_iface(wpa_s);
if (params->wpa_debug_syslog)
wpa_debug_open_syslog();
- ret = eap_peer_register_methods();
+ ret = eap_register_methods();
if (ret) {
wpa_printf(MSG_ERROR, "Failed to register EAP methods");
if (ret == -2)
return NULL;
}
-#ifdef CONFIG_AP
- ret = eap_server_register_methods();
- if (ret) {
- wpa_printf(MSG_ERROR, "Failed to register EAP server methods");
- if (ret == -2)
- wpa_printf(MSG_ERROR, "Two or more EAP methods used "
- "the same EAP type.");
- return NULL;
- }
-#endif /* CONFIG_AP */
-
global = os_zalloc(sizeof(*global));
if (global == NULL)
return NULL;
if (params->ctrl_interface)
global->params.ctrl_interface =
os_strdup(params->ctrl_interface);
+ if (params->override_driver)
+ global->params.override_driver =
+ os_strdup(params->override_driver);
+ if (params->override_ctrl_interface)
+ global->params.override_ctrl_interface =
+ os_strdup(params->override_ctrl_interface);
wpa_debug_level = global->params.wpa_debug_level =
params->wpa_debug_level;
wpa_debug_show_keys = global->params.wpa_debug_show_keys =
wpa_debug_timestamp = global->params.wpa_debug_timestamp =
params->wpa_debug_timestamp;
- if (eloop_init(global)) {
+ if (eloop_init()) {
wpa_printf(MSG_ERROR, "Failed to initialize event loop");
wpa_supplicant_deinit(global);
return NULL;
wpa_s->ctrl_iface);
}
- eloop_register_signal_terminate(wpa_supplicant_terminate, NULL);
- eloop_register_signal_reconfig(wpa_supplicant_reconfig, NULL);
+ eloop_register_signal_terminate(wpa_supplicant_terminate, global);
+ eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
eloop_run();
os_free(global->params.pid_file);
}
os_free(global->params.ctrl_interface);
+ os_free(global->params.override_driver);
+ os_free(global->params.override_ctrl_interface);
os_free(global);
wpa_debug_close_syslog();