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.
|
||||
*/
|
||||
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 /* probe_req_report */,
|
||||
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 = {
|
||||
.name = "nl80211",
|
||||
.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,
|
||||
.disable_11b_rates = wpa_driver_nl80211_disable_11b_rates,
|
||||
.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)
|
||||
* 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
|
||||
* 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_size);
|
||||
#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 {
|
||||
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
|
||||
reply_len = 16;
|
||||
|
@ -2038,6 +2042,10 @@ char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
|
|||
global, reply, reply_size);
|
||||
} else if (os_strcmp(buf, "TERMINATE") == 0) {
|
||||
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 {
|
||||
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
|
||||
reply_len = 16;
|
||||
|
|
|
@ -456,4 +456,16 @@ static inline int wpa_drv_deinit_ap(struct wpa_supplicant *wpa_s)
|
|||
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 */
|
||||
|
|
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
|
||||
* 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
|
||||
* 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_old.h"
|
||||
#include "dbus/dbus_new.h"
|
||||
#include "driver_i.h"
|
||||
#include "scan.h"
|
||||
#include "notify.h"
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
* 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
|
||||
* 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_timestamp_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 */
|
||||
|
|
|
@ -216,6 +216,7 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
|
|||
#endif /* CONFIG_WPS */
|
||||
struct wpa_driver_scan_params params;
|
||||
size_t max_ssids;
|
||||
enum wpa_states prev_state;
|
||||
|
||||
if (wpa_s->disconnected && !wpa_s->scan_req) {
|
||||
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));
|
||||
|
||||
prev_state = wpa_s->wpa_state;
|
||||
if (wpa_s->wpa_state == WPA_DISCONNECTED ||
|
||||
wpa_s->wpa_state == WPA_INACTIVE)
|
||||
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) {
|
||||
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);
|
||||
} else
|
||||
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 */
|
||||
|
||||
|
||||
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 {
|
||||
cli_cmd_flag_none = 0x00,
|
||||
cli_cmd_flag_sensitive = 0x01
|
||||
|
@ -1597,6 +1609,10 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
|
|||
cli_cmd_flag_none,
|
||||
"= get information about all associated stations (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 }
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* 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
|
||||
* 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;
|
||||
void **drv_priv;
|
||||
size_t drv_count;
|
||||
struct os_time suspend_time;
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue