Add suspend/resume notifications
wpa_supplicant can now be notified of suspend/resume events, e.g., from pm-action scripts. This allows wpa_supplicant to clear information that may become invalid during a suspend operation.
This commit is contained in:
parent
be8be6717d
commit
207ef3fb12
11 changed files with 126 additions and 5 deletions
|
@ -1731,6 +1731,18 @@ struct wpa_driver_ops {
|
||||||
* normal station operations like scanning to be completed.
|
* normal station operations like scanning to be completed.
|
||||||
*/
|
*/
|
||||||
int (*deinit_ap)(void *priv);
|
int (*deinit_ap)(void *priv);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* suspend - Notification on system suspend/hibernate event
|
||||||
|
* @priv: Private driver interface data
|
||||||
|
*/
|
||||||
|
void (*suspend)(void *priv);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* resume - Notification on system resume/thaw event
|
||||||
|
* @priv: Private driver interface data
|
||||||
|
*/
|
||||||
|
void (*resume)(void *priv);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3272,5 +3272,7 @@ const struct wpa_driver_ops wpa_driver_ndis_ops = {
|
||||||
NULL /* cancel_remain_on_channel */,
|
NULL /* cancel_remain_on_channel */,
|
||||||
NULL /* probe_req_report */,
|
NULL /* probe_req_report */,
|
||||||
NULL /* disable_11b_rates */,
|
NULL /* disable_11b_rates */,
|
||||||
NULL /* deinit_ap */
|
NULL /* deinit_ap */,
|
||||||
|
NULL /* suspend */,
|
||||||
|
NULL /* resume */
|
||||||
};
|
};
|
||||||
|
|
|
@ -4996,6 +4996,16 @@ static int wpa_driver_nl80211_deinit_ap(void *priv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void wpa_driver_nl80211_resume(void *priv)
|
||||||
|
{
|
||||||
|
struct wpa_driver_nl80211_data *drv = priv;
|
||||||
|
if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1)) {
|
||||||
|
wpa_printf(MSG_DEBUG, "nl80211: Failed to set interface up on "
|
||||||
|
"resume event");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const struct wpa_driver_ops wpa_driver_nl80211_ops = {
|
const struct wpa_driver_ops wpa_driver_nl80211_ops = {
|
||||||
.name = "nl80211",
|
.name = "nl80211",
|
||||||
.desc = "Linux nl80211/cfg80211",
|
.desc = "Linux nl80211/cfg80211",
|
||||||
|
@ -5053,4 +5063,5 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
|
||||||
.release_interface_addr = wpa_driver_nl80211_release_interface_addr,
|
.release_interface_addr = wpa_driver_nl80211_release_interface_addr,
|
||||||
.disable_11b_rates = wpa_driver_nl80211_disable_11b_rates,
|
.disable_11b_rates = wpa_driver_nl80211_disable_11b_rates,
|
||||||
.deinit_ap = wpa_driver_nl80211_deinit_ap,
|
.deinit_ap = wpa_driver_nl80211_deinit_ap,
|
||||||
|
.resume = wpa_driver_nl80211_resume,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* WPA Supplicant / Control interface (shared code for all backends)
|
* WPA Supplicant / Control interface (shared code for all backends)
|
||||||
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
@ -1812,6 +1812,10 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
|
||||||
reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
|
reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
|
||||||
reply_size);
|
reply_size);
|
||||||
#endif /* CONFIG_AP */
|
#endif /* CONFIG_AP */
|
||||||
|
} else if (os_strcmp(buf, "SUSPEND") == 0) {
|
||||||
|
wpas_notify_suspend(wpa_s->global);
|
||||||
|
} else if (os_strcmp(buf, "RESUME") == 0) {
|
||||||
|
wpas_notify_resume(wpa_s->global);
|
||||||
} else {
|
} else {
|
||||||
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
|
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
|
||||||
reply_len = 16;
|
reply_len = 16;
|
||||||
|
@ -2038,6 +2042,10 @@ char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
|
||||||
global, reply, reply_size);
|
global, reply, reply_size);
|
||||||
} else if (os_strcmp(buf, "TERMINATE") == 0) {
|
} else if (os_strcmp(buf, "TERMINATE") == 0) {
|
||||||
wpa_supplicant_terminate_proc(global);
|
wpa_supplicant_terminate_proc(global);
|
||||||
|
} else if (os_strcmp(buf, "SUSPEND") == 0) {
|
||||||
|
wpas_notify_suspend(global);
|
||||||
|
} else if (os_strcmp(buf, "RESUME") == 0) {
|
||||||
|
wpas_notify_resume(global);
|
||||||
} else {
|
} else {
|
||||||
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
|
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
|
||||||
reply_len = 16;
|
reply_len = 16;
|
||||||
|
|
|
@ -456,4 +456,16 @@ static inline int wpa_drv_deinit_ap(struct wpa_supplicant *wpa_s)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void wpa_drv_suspend(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
if (wpa_s->driver->suspend)
|
||||||
|
wpa_s->driver->suspend(wpa_s->drv_priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void wpa_drv_resume(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
if (wpa_s->driver->resume)
|
||||||
|
wpa_s->driver->resume(wpa_s->drv_priv);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* DRIVER_I_H */
|
#endif /* DRIVER_I_H */
|
||||||
|
|
17
wpa_supplicant/examples/60_wpa_supplicant
Executable file
17
wpa_supplicant/examples/60_wpa_supplicant
Executable file
|
@ -0,0 +1,17 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# /etc/pm/sleep.d/60_wpa_supplicant
|
||||||
|
# Action script to notify wpa_supplicant of pm-action events.
|
||||||
|
|
||||||
|
PATH=/sbin:/usr/sbin:/bin:/usr/bin
|
||||||
|
|
||||||
|
WPACLI=wpa_cli
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
suspend|hibernate)
|
||||||
|
$WPACLI suspend
|
||||||
|
;;
|
||||||
|
resume|thaw)
|
||||||
|
$WPACLI resume
|
||||||
|
;;
|
||||||
|
esac
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* wpa_supplicant - Event notifications
|
* wpa_supplicant - Event notifications
|
||||||
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2009-2010, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
@ -22,6 +22,8 @@
|
||||||
#include "dbus/dbus_common.h"
|
#include "dbus/dbus_common.h"
|
||||||
#include "dbus/dbus_old.h"
|
#include "dbus/dbus_old.h"
|
||||||
#include "dbus/dbus_new.h"
|
#include "dbus/dbus_new.h"
|
||||||
|
#include "driver_i.h"
|
||||||
|
#include "scan.h"
|
||||||
#include "notify.h"
|
#include "notify.h"
|
||||||
|
|
||||||
int wpas_notify_supplicant_initialized(struct wpa_global *global)
|
int wpas_notify_supplicant_initialized(struct wpa_global *global)
|
||||||
|
@ -301,3 +303,37 @@ void wpas_notify_debug_show_keys_changed(struct wpa_global *global)
|
||||||
{
|
{
|
||||||
wpas_dbus_signal_debug_show_keys_changed(global);
|
wpas_dbus_signal_debug_show_keys_changed(global);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void wpas_notify_suspend(struct wpa_global *global)
|
||||||
|
{
|
||||||
|
struct wpa_supplicant *wpa_s;
|
||||||
|
|
||||||
|
os_get_time(&global->suspend_time);
|
||||||
|
wpa_printf(MSG_DEBUG, "System suspend notification");
|
||||||
|
for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
|
||||||
|
wpa_drv_suspend(wpa_s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void wpas_notify_resume(struct wpa_global *global)
|
||||||
|
{
|
||||||
|
struct os_time now;
|
||||||
|
int slept;
|
||||||
|
struct wpa_supplicant *wpa_s;
|
||||||
|
|
||||||
|
if (global->suspend_time.sec == 0)
|
||||||
|
slept = -1;
|
||||||
|
else {
|
||||||
|
os_get_time(&now);
|
||||||
|
slept = now.sec - global->suspend_time.sec;
|
||||||
|
}
|
||||||
|
wpa_printf(MSG_DEBUG, "System resume notification (slept %d seconds)",
|
||||||
|
slept);
|
||||||
|
|
||||||
|
for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
|
||||||
|
wpa_drv_resume(wpa_s);
|
||||||
|
if (wpa_s->wpa_state == WPA_DISCONNECTED)
|
||||||
|
wpa_supplicant_req_scan(wpa_s, 0, 100000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* wpa_supplicant - Event notifications
|
* wpa_supplicant - Event notifications
|
||||||
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2009-2010, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
@ -75,5 +75,7 @@ void wpas_notify_blob_removed(struct wpa_supplicant *wpa_s, const char *name);
|
||||||
void wpas_notify_debug_level_changed(struct wpa_global *global);
|
void wpas_notify_debug_level_changed(struct wpa_global *global);
|
||||||
void wpas_notify_debug_timestamp_changed(struct wpa_global *global);
|
void wpas_notify_debug_timestamp_changed(struct wpa_global *global);
|
||||||
void wpas_notify_debug_show_keys_changed(struct wpa_global *global);
|
void wpas_notify_debug_show_keys_changed(struct wpa_global *global);
|
||||||
|
void wpas_notify_suspend(struct wpa_global *global);
|
||||||
|
void wpas_notify_resume(struct wpa_global *global);
|
||||||
|
|
||||||
#endif /* NOTIFY_H */
|
#endif /* NOTIFY_H */
|
||||||
|
|
|
@ -216,6 +216,7 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
|
||||||
#endif /* CONFIG_WPS */
|
#endif /* CONFIG_WPS */
|
||||||
struct wpa_driver_scan_params params;
|
struct wpa_driver_scan_params params;
|
||||||
size_t max_ssids;
|
size_t max_ssids;
|
||||||
|
enum wpa_states prev_state;
|
||||||
|
|
||||||
if (wpa_s->disconnected && !wpa_s->scan_req) {
|
if (wpa_s->disconnected && !wpa_s->scan_req) {
|
||||||
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
|
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
|
||||||
|
@ -271,6 +272,7 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
|
||||||
|
|
||||||
os_memset(¶ms, 0, sizeof(params));
|
os_memset(¶ms, 0, sizeof(params));
|
||||||
|
|
||||||
|
prev_state = wpa_s->wpa_state;
|
||||||
if (wpa_s->wpa_state == WPA_DISCONNECTED ||
|
if (wpa_s->wpa_state == WPA_DISCONNECTED ||
|
||||||
wpa_s->wpa_state == WPA_INACTIVE)
|
wpa_s->wpa_state == WPA_INACTIVE)
|
||||||
wpa_supplicant_set_state(wpa_s, WPA_SCANNING);
|
wpa_supplicant_set_state(wpa_s, WPA_SCANNING);
|
||||||
|
@ -368,6 +370,8 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
wpa_printf(MSG_WARNING, "Failed to initiate AP scan.");
|
wpa_printf(MSG_WARNING, "Failed to initiate AP scan.");
|
||||||
|
if (prev_state != wpa_s->wpa_state)
|
||||||
|
wpa_supplicant_set_state(wpa_s, prev_state);
|
||||||
wpa_supplicant_req_scan(wpa_s, 10, 0);
|
wpa_supplicant_req_scan(wpa_s, 10, 0);
|
||||||
} else
|
} else
|
||||||
wpa_s->scan_runs++;
|
wpa_s->scan_runs++;
|
||||||
|
|
|
@ -1403,6 +1403,18 @@ static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
||||||
#endif /* CONFIG_AP */
|
#endif /* CONFIG_AP */
|
||||||
|
|
||||||
|
|
||||||
|
static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
||||||
|
{
|
||||||
|
return wpa_ctrl_command(ctrl, "SUSPEND");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
||||||
|
{
|
||||||
|
return wpa_ctrl_command(ctrl, "RESUME");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
enum wpa_cli_cmd_flags {
|
enum wpa_cli_cmd_flags {
|
||||||
cli_cmd_flag_none = 0x00,
|
cli_cmd_flag_none = 0x00,
|
||||||
cli_cmd_flag_sensitive = 0x01
|
cli_cmd_flag_sensitive = 0x01
|
||||||
|
@ -1597,6 +1609,10 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
|
||||||
cli_cmd_flag_none,
|
cli_cmd_flag_none,
|
||||||
"= get information about all associated stations (AP)" },
|
"= get information about all associated stations (AP)" },
|
||||||
#endif /* CONFIG_AP */
|
#endif /* CONFIG_AP */
|
||||||
|
{ "suspend", wpa_cli_cmd_suspend, cli_cmd_flag_none,
|
||||||
|
"= notification of suspend/hibernate" },
|
||||||
|
{ "resume", wpa_cli_cmd_resume, cli_cmd_flag_none,
|
||||||
|
"= notification of resume/thaw" },
|
||||||
{ NULL, NULL, cli_cmd_flag_none, NULL }
|
{ NULL, NULL, cli_cmd_flag_none, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* wpa_supplicant - Internal definitions
|
* wpa_supplicant - Internal definitions
|
||||||
* Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2003-2010, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
@ -194,6 +194,7 @@ struct wpa_global {
|
||||||
struct wpas_dbus_priv *dbus;
|
struct wpas_dbus_priv *dbus;
|
||||||
void **drv_priv;
|
void **drv_priv;
|
||||||
size_t drv_count;
|
size_t drv_count;
|
||||||
|
struct os_time suspend_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue