Add Linux rfkill support
Add a new wpa_supplicant state: interface disabled. This can be used to allow wpa_supplicant to be running with the network interface even when the driver does not actually allow any radio operations (e.g., due to rfkill). Allow driver_nl80211.c and driver_wext.c to start while rfkill is in blocked state (i.e., when ifconfig up fails) and process rfkill events to block/unblock WLAN.
This commit is contained in:
parent
6deb41e73f
commit
8401a6b028
12 changed files with 428 additions and 13 deletions
|
@ -136,6 +136,15 @@ enum wpa_states {
|
|||
*/
|
||||
WPA_DISCONNECTED,
|
||||
|
||||
/**
|
||||
* WPA_INTERFACE_DISABLED - Interface disabled
|
||||
*
|
||||
* This stat eis entered if the network interface is disabled, e.g.,
|
||||
* due to rfkill. wpa_supplicant refuses any new operations that would
|
||||
* use the radio until the interface has been enabled.
|
||||
*/
|
||||
WPA_INTERFACE_DISABLED,
|
||||
|
||||
/**
|
||||
* WPA_INACTIVE - Inactive state (wpa_supplicant disabled)
|
||||
*
|
||||
|
|
|
@ -2046,7 +2046,23 @@ enum wpa_event_type {
|
|||
* observed in frames received from the current AP if signal strength
|
||||
* monitoring has been enabled with signal_monitor().
|
||||
*/
|
||||
EVENT_SIGNAL_CHANGE
|
||||
EVENT_SIGNAL_CHANGE,
|
||||
|
||||
/**
|
||||
* EVENT_INTERFACE_ENABLED - Notify that interface was enabled
|
||||
*
|
||||
* This event is used to indicate that the interface was enabled after
|
||||
* having been previously disabled, e.g., due to rfkill.
|
||||
*/
|
||||
EVENT_INTERFACE_ENABLED,
|
||||
|
||||
/**
|
||||
* EVENT_INTERFACE_DISABLED - Notify that interface was disabled
|
||||
*
|
||||
* This event is used to indicate that the interface was disabled,
|
||||
* e.g., due to rfkill.
|
||||
*/
|
||||
EVENT_INTERFACE_DISABLED
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "linux_ioctl.h"
|
||||
#include "radiotap.h"
|
||||
#include "radiotap_iter.h"
|
||||
#include "rfkill.h"
|
||||
#include "driver.h"
|
||||
|
||||
#ifdef CONFIG_LIBNL20
|
||||
|
@ -72,6 +73,7 @@ struct wpa_driver_nl80211_data {
|
|||
char brname[IFNAMSIZ];
|
||||
int ifindex;
|
||||
int if_removed;
|
||||
struct rfkill_data *rfkill;
|
||||
struct wpa_driver_capa capa;
|
||||
int has_capability;
|
||||
|
||||
|
@ -1347,6 +1349,27 @@ err1:
|
|||
}
|
||||
|
||||
|
||||
static void wpa_driver_nl80211_rfkill_blocked(void *ctx)
|
||||
{
|
||||
struct wpa_driver_nl80211_data *drv = ctx;
|
||||
wpa_printf(MSG_DEBUG, "nl80211: RFKILL blocked");
|
||||
wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_DISABLED, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void wpa_driver_nl80211_rfkill_unblocked(void *ctx)
|
||||
{
|
||||
struct wpa_driver_nl80211_data *drv = ctx;
|
||||
wpa_printf(MSG_DEBUG, "nl80211: RFKILL unblocked");
|
||||
if (linux_set_iface_flags(drv->ioctl_sock, drv->first_bss.ifname, 1)) {
|
||||
wpa_printf(MSG_DEBUG, "nl80211: Could not set interface UP "
|
||||
"after rfkill unblock");
|
||||
return;
|
||||
}
|
||||
wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED, NULL);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpa_driver_nl80211_init - Initialize nl80211 driver interface
|
||||
* @ctx: context to be used when calling wpa_supplicant functions,
|
||||
|
@ -1358,6 +1381,7 @@ static void * wpa_driver_nl80211_init(void *ctx, const char *ifname)
|
|||
{
|
||||
struct wpa_driver_nl80211_data *drv;
|
||||
struct netlink_config *cfg;
|
||||
struct rfkill_config *rcfg;
|
||||
struct i802_bss *bss;
|
||||
|
||||
drv = os_zalloc(sizeof(*drv));
|
||||
|
@ -1393,12 +1417,25 @@ static void * wpa_driver_nl80211_init(void *ctx, const char *ifname)
|
|||
os_free(cfg);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
rcfg = os_zalloc(sizeof(*rcfg));
|
||||
if (rcfg == NULL)
|
||||
goto failed;
|
||||
rcfg->ctx = drv;
|
||||
os_strlcpy(rcfg->ifname, ifname, sizeof(rcfg->ifname));
|
||||
rcfg->blocked_cb = wpa_driver_nl80211_rfkill_blocked;
|
||||
rcfg->unblocked_cb = wpa_driver_nl80211_rfkill_unblocked;
|
||||
drv->rfkill = rfkill_init(rcfg);
|
||||
if (drv->rfkill == NULL)
|
||||
wpa_printf(MSG_DEBUG, "nl80211: RFKILL status not available");
|
||||
|
||||
if (wpa_driver_nl80211_finish_drv_init(drv))
|
||||
goto failed;
|
||||
|
||||
return bss;
|
||||
|
||||
failed:
|
||||
rfkill_deinit(drv->rfkill);
|
||||
netlink_deinit(drv->netlink);
|
||||
if (drv->ioctl_sock >= 0)
|
||||
close(drv->ioctl_sock);
|
||||
|
@ -1459,10 +1496,17 @@ static int nl80211_register_action_frames(struct wpa_driver_nl80211_data *drv)
|
|||
}
|
||||
|
||||
|
||||
static void wpa_driver_nl80211_send_rfkill(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
wpa_supplicant_event(timeout_ctx, EVENT_INTERFACE_DISABLED, NULL);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv)
|
||||
{
|
||||
struct i802_bss *bss = &drv->first_bss;
|
||||
int send_rfkill_event = 0;
|
||||
|
||||
drv->ifindex = if_nametoindex(bss->ifname);
|
||||
drv->first_bss.ifindex = drv->ifindex;
|
||||
|
@ -1474,9 +1518,16 @@ wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv)
|
|||
}
|
||||
|
||||
if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 1)) {
|
||||
wpa_printf(MSG_ERROR, "Could not set interface '%s' UP",
|
||||
bss->ifname);
|
||||
return -1;
|
||||
if (rfkill_is_blocked(drv->rfkill)) {
|
||||
wpa_printf(MSG_DEBUG, "nl80211: Could not yet enable "
|
||||
"interface '%s' due to rfkill",
|
||||
bss->ifname);
|
||||
send_rfkill_event = 1;
|
||||
} else {
|
||||
wpa_printf(MSG_ERROR, "nl80211: Could not set "
|
||||
"interface '%s' UP", bss->ifname);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (wpa_driver_nl80211_capa(drv))
|
||||
|
@ -1496,6 +1547,11 @@ wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv)
|
|||
*/
|
||||
}
|
||||
|
||||
if (send_rfkill_event) {
|
||||
eloop_register_timeout(0, 0, wpa_driver_nl80211_send_rfkill,
|
||||
drv, drv->ctx);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1572,6 +1628,7 @@ static void wpa_driver_nl80211_deinit(void *priv)
|
|||
|
||||
netlink_send_oper_ifla(drv->netlink, drv->ifindex, 0, IF_OPER_UP);
|
||||
netlink_deinit(drv->netlink);
|
||||
rfkill_deinit(drv->rfkill);
|
||||
|
||||
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "priv_netlink.h"
|
||||
#include "netlink.h"
|
||||
#include "linux_ioctl.h"
|
||||
#include "rfkill.h"
|
||||
#include "driver.h"
|
||||
#include "driver_wext.h"
|
||||
|
||||
|
@ -687,6 +688,27 @@ static void wpa_driver_wext_event_rtm_dellink(void *ctx, struct ifinfomsg *ifi,
|
|||
}
|
||||
|
||||
|
||||
static void wpa_driver_wext_rfkill_blocked(void *ctx)
|
||||
{
|
||||
struct wpa_driver_wext_data *drv = ctx;
|
||||
wpa_printf(MSG_DEBUG, "WEXT: RFKILL blocked");
|
||||
wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_DISABLED, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void wpa_driver_wext_rfkill_unblocked(void *ctx)
|
||||
{
|
||||
struct wpa_driver_wext_data *drv = ctx;
|
||||
wpa_printf(MSG_DEBUG, "WEXT: RFKILL unblocked");
|
||||
if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1)) {
|
||||
wpa_printf(MSG_DEBUG, "WEXT: Could not set interface UP "
|
||||
"after rfkill unblock");
|
||||
return;
|
||||
}
|
||||
wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED, NULL);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpa_driver_wext_init - Initialize WE driver interface
|
||||
* @ctx: context to be used when calling wpa_supplicant functions,
|
||||
|
@ -698,6 +720,7 @@ void * wpa_driver_wext_init(void *ctx, const char *ifname)
|
|||
{
|
||||
struct wpa_driver_wext_data *drv;
|
||||
struct netlink_config *cfg;
|
||||
struct rfkill_config *rcfg;
|
||||
char path[128];
|
||||
struct stat buf;
|
||||
|
||||
|
@ -731,6 +754,17 @@ void * wpa_driver_wext_init(void *ctx, const char *ifname)
|
|||
goto err2;
|
||||
}
|
||||
|
||||
rcfg = os_zalloc(sizeof(*rcfg));
|
||||
if (rcfg == NULL)
|
||||
goto err3;
|
||||
rcfg->ctx = drv;
|
||||
os_strlcpy(rcfg->ifname, ifname, sizeof(rcfg->ifname));
|
||||
rcfg->blocked_cb = wpa_driver_wext_rfkill_blocked;
|
||||
rcfg->unblocked_cb = wpa_driver_wext_rfkill_unblocked;
|
||||
drv->rfkill = rfkill_init(rcfg);
|
||||
if (drv->rfkill == NULL)
|
||||
wpa_printf(MSG_DEBUG, "WEXT: RFKILL status not available");
|
||||
|
||||
drv->mlme_sock = -1;
|
||||
|
||||
if (wpa_driver_wext_finish_drv_init(drv) < 0)
|
||||
|
@ -741,6 +775,7 @@ void * wpa_driver_wext_init(void *ctx, const char *ifname)
|
|||
return drv;
|
||||
|
||||
err3:
|
||||
rfkill_deinit(drv->rfkill);
|
||||
netlink_deinit(drv->netlink);
|
||||
err2:
|
||||
close(drv->ioctl_sock);
|
||||
|
@ -750,10 +785,28 @@ err1:
|
|||
}
|
||||
|
||||
|
||||
static void wpa_driver_wext_send_rfkill(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
wpa_supplicant_event(timeout_ctx, EVENT_INTERFACE_DISABLED, NULL);
|
||||
}
|
||||
|
||||
|
||||
static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv)
|
||||
{
|
||||
if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1) < 0)
|
||||
return -1;
|
||||
int send_rfkill_event = 0;
|
||||
|
||||
if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1) < 0) {
|
||||
if (rfkill_is_blocked(drv->rfkill)) {
|
||||
wpa_printf(MSG_DEBUG, "WEXT: Could not yet enable "
|
||||
"interface '%s' due to rfkill",
|
||||
drv->ifname);
|
||||
send_rfkill_event = 1;
|
||||
} else {
|
||||
wpa_printf(MSG_ERROR, "WEXT: Could not set "
|
||||
"interface '%s' UP", drv->ifname);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure that the driver does not have any obsolete PMKID entries.
|
||||
|
@ -795,6 +848,11 @@ static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv)
|
|||
netlink_send_oper_ifla(drv->netlink, drv->ifindex,
|
||||
1, IF_OPER_DORMANT);
|
||||
|
||||
if (send_rfkill_event) {
|
||||
eloop_register_timeout(0, 0, wpa_driver_wext_send_rfkill,
|
||||
drv, drv->ctx);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -822,6 +880,7 @@ void wpa_driver_wext_deinit(void *priv)
|
|||
|
||||
netlink_send_oper_ifla(drv->netlink, drv->ifindex, 0, IF_OPER_UP);
|
||||
netlink_deinit(drv->netlink);
|
||||
rfkill_deinit(drv->rfkill);
|
||||
|
||||
if (drv->mlme_sock >= 0)
|
||||
eloop_unregister_read_sock(drv->mlme_sock);
|
||||
|
|
|
@ -26,6 +26,7 @@ struct wpa_driver_wext_data {
|
|||
int ifindex;
|
||||
int ifindex2;
|
||||
int if_removed;
|
||||
struct rfkill_data *rfkill;
|
||||
u8 *assoc_req_ies;
|
||||
size_t assoc_req_ies_len;
|
||||
u8 *assoc_resp_ies;
|
||||
|
|
|
@ -31,6 +31,7 @@ NEED_SME=y
|
|||
NEED_AP_MLME=y
|
||||
NEED_NETLINK=y
|
||||
NEED_LINUX_IOCTL=y
|
||||
NEED_RFKILL=y
|
||||
DRV_LIBS += -lnl
|
||||
|
||||
ifdef CONFIG_LIBNL20
|
||||
|
@ -77,6 +78,7 @@ DRV_WPA_CFLAGS += -DCONFIG_DRIVER_WEXT
|
|||
CONFIG_WIRELESS_EXTENSION=y
|
||||
NEED_NETLINK=y
|
||||
NEED_LINUX_IOCTL=y
|
||||
NEED_RFKILL=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_DRIVER_HERMES
|
||||
|
@ -162,6 +164,10 @@ ifdef NEED_LINUX_IOCTL
|
|||
DRV_OBJS += ../src/drivers/linux_ioctl.o
|
||||
endif
|
||||
|
||||
ifdef NEED_RFKILL
|
||||
DRV_OBJS += ../src/drivers/rfkill.o
|
||||
endif
|
||||
|
||||
|
||||
##### COMMON VARS
|
||||
DRV_BOTH_CFLAGS := $(DRV_CFLAGS) $(DRV_WPA_CFLAGS) $(DRV_AP_CFLAGS)
|
||||
|
|
194
src/drivers/rfkill.c
Normal file
194
src/drivers/rfkill.c
Normal file
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
* Linux rfkill helper functions for driver wrappers
|
||||
* Copyright (c) 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "rfkill.h"
|
||||
|
||||
#define RFKILL_EVENT_SIZE_V1 8
|
||||
|
||||
struct rfkill_event {
|
||||
u32 idx;
|
||||
u8 type;
|
||||
u8 op;
|
||||
u8 soft;
|
||||
u8 hard;
|
||||
} STRUCT_PACKED;
|
||||
|
||||
enum rfkill_operation {
|
||||
RFKILL_OP_ADD = 0,
|
||||
RFKILL_OP_DEL,
|
||||
RFKILL_OP_CHANGE,
|
||||
RFKILL_OP_CHANGE_ALL,
|
||||
};
|
||||
|
||||
enum rfkill_type {
|
||||
RFKILL_TYPE_ALL = 0,
|
||||
RFKILL_TYPE_WLAN,
|
||||
RFKILL_TYPE_BLUETOOTH,
|
||||
RFKILL_TYPE_UWB,
|
||||
RFKILL_TYPE_WIMAX,
|
||||
RFKILL_TYPE_WWAN,
|
||||
RFKILL_TYPE_GPS,
|
||||
RFKILL_TYPE_FM,
|
||||
NUM_RFKILL_TYPES,
|
||||
};
|
||||
|
||||
|
||||
struct rfkill_data {
|
||||
struct rfkill_config *cfg;
|
||||
int fd;
|
||||
int blocked;
|
||||
};
|
||||
|
||||
|
||||
static void rfkill_receive(int sock, void *eloop_ctx, void *sock_ctx)
|
||||
{
|
||||
struct rfkill_data *rfkill = eloop_ctx;
|
||||
struct rfkill_event event;
|
||||
ssize_t len;
|
||||
int new_blocked;
|
||||
|
||||
len = read(rfkill->fd, &event, sizeof(event));
|
||||
if (len < 0) {
|
||||
wpa_printf(MSG_ERROR, "rfkill: Event read failed: %s",
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
if (len != RFKILL_EVENT_SIZE_V1) {
|
||||
wpa_printf(MSG_DEBUG, "rfkill: Unexpected event size "
|
||||
"%d (expected %d)",
|
||||
(int) len, RFKILL_EVENT_SIZE_V1);
|
||||
return;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "rfkill: event: idx=%u type=%d "
|
||||
"op=%u soft=%u hard=%u",
|
||||
event.idx, event.type, event.op, event.soft,
|
||||
event.hard);
|
||||
if (event.op != RFKILL_OP_CHANGE || event.type != RFKILL_TYPE_WLAN)
|
||||
return;
|
||||
|
||||
if (event.hard) {
|
||||
wpa_printf(MSG_INFO, "rfkill: WLAN hard blocked");
|
||||
new_blocked = 1;
|
||||
} else if (event.soft) {
|
||||
wpa_printf(MSG_INFO, "rfkill: WLAN soft blocked");
|
||||
new_blocked = 1;
|
||||
} else {
|
||||
wpa_printf(MSG_INFO, "rfkill: WLAN unblocked");
|
||||
new_blocked = 0;
|
||||
}
|
||||
|
||||
if (new_blocked != rfkill->blocked) {
|
||||
rfkill->blocked = new_blocked;
|
||||
if (new_blocked)
|
||||
rfkill->cfg->blocked_cb(rfkill->cfg->ctx);
|
||||
else
|
||||
rfkill->cfg->unblocked_cb(rfkill->cfg->ctx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct rfkill_data * rfkill_init(struct rfkill_config *cfg)
|
||||
{
|
||||
struct rfkill_data *rfkill;
|
||||
struct rfkill_event event;
|
||||
ssize_t len;
|
||||
|
||||
rfkill = os_zalloc(sizeof(*rfkill));
|
||||
if (rfkill == NULL)
|
||||
return NULL;
|
||||
|
||||
rfkill->cfg = cfg;
|
||||
rfkill->fd = open("/dev/rfkill", O_RDONLY);
|
||||
if (rfkill->fd < 0) {
|
||||
wpa_printf(MSG_INFO, "rfkill: Cannot open RFKILL control "
|
||||
"device");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (fcntl(rfkill->fd, F_SETFL, O_NONBLOCK) < 0) {
|
||||
wpa_printf(MSG_ERROR, "rfkill: Cannot set non-blocking mode: "
|
||||
"%s", strerror(errno));
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
len = read(rfkill->fd, &event, sizeof(event));
|
||||
if (len < 0) {
|
||||
if (errno == EAGAIN)
|
||||
break; /* No more entries */
|
||||
wpa_printf(MSG_ERROR, "rfkill: Event read failed: %s",
|
||||
strerror(errno));
|
||||
break;
|
||||
}
|
||||
if (len != RFKILL_EVENT_SIZE_V1) {
|
||||
wpa_printf(MSG_DEBUG, "rfkill: Unexpected event size "
|
||||
"%d (expected %d)",
|
||||
(int) len, RFKILL_EVENT_SIZE_V1);
|
||||
continue;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "rfkill: initial event: idx=%u type=%d "
|
||||
"op=%u soft=%u hard=%u",
|
||||
event.idx, event.type, event.op, event.soft,
|
||||
event.hard);
|
||||
if (event.op != RFKILL_OP_ADD ||
|
||||
event.type != RFKILL_TYPE_WLAN)
|
||||
continue;
|
||||
if (event.hard) {
|
||||
wpa_printf(MSG_INFO, "rfkill: WLAN hard blocked");
|
||||
rfkill->blocked = 1;
|
||||
} else if (event.soft) {
|
||||
wpa_printf(MSG_INFO, "rfkill: WLAN soft blocked");
|
||||
rfkill->blocked = 1;
|
||||
}
|
||||
}
|
||||
|
||||
eloop_register_read_sock(rfkill->fd, rfkill_receive, rfkill, NULL);
|
||||
|
||||
return rfkill;
|
||||
|
||||
fail2:
|
||||
close(rfkill->fd);
|
||||
fail:
|
||||
os_free(rfkill);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void rfkill_deinit(struct rfkill_data *rfkill)
|
||||
{
|
||||
if (rfkill == NULL)
|
||||
return;
|
||||
|
||||
if (rfkill->fd >= 0) {
|
||||
eloop_unregister_read_sock(rfkill->fd);
|
||||
close(rfkill->fd);
|
||||
}
|
||||
|
||||
os_free(rfkill->cfg);
|
||||
os_free(rfkill);
|
||||
}
|
||||
|
||||
|
||||
int rfkill_is_blocked(struct rfkill_data *rfkill)
|
||||
{
|
||||
if (rfkill == NULL)
|
||||
return 0;
|
||||
|
||||
return rfkill->blocked;
|
||||
}
|
31
src/drivers/rfkill.h
Normal file
31
src/drivers/rfkill.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Linux rfkill helper functions for driver wrappers
|
||||
* Copyright (c) 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef RFKILL_H
|
||||
#define RFKILL_H
|
||||
|
||||
struct rfkill_data;
|
||||
|
||||
struct rfkill_config {
|
||||
void *ctx;
|
||||
char ifname[IFNAMSIZ];
|
||||
void (*blocked_cb)(void *ctx);
|
||||
void (*unblocked_cb)(void *ctx);
|
||||
};
|
||||
|
||||
struct rfkill_data * rfkill_init(struct rfkill_config *cfg);
|
||||
void rfkill_deinit(struct rfkill_data *rfkill);
|
||||
int rfkill_is_blocked(struct rfkill_data *rfkill);
|
||||
|
||||
#endif /* RFKILL_H */
|
|
@ -1742,11 +1742,17 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
|
|||
} else if (os_strcmp(buf, "LOGOFF") == 0) {
|
||||
eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
|
||||
} else if (os_strcmp(buf, "REASSOCIATE") == 0) {
|
||||
wpa_s->disconnected = 0;
|
||||
wpa_s->reassociate = 1;
|
||||
wpa_supplicant_req_scan(wpa_s, 0, 0);
|
||||
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
|
||||
reply_len = -1;
|
||||
else {
|
||||
wpa_s->disconnected = 0;
|
||||
wpa_s->reassociate = 1;
|
||||
wpa_supplicant_req_scan(wpa_s, 0, 0);
|
||||
}
|
||||
} else if (os_strcmp(buf, "RECONNECT") == 0) {
|
||||
if (wpa_s->disconnected) {
|
||||
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
|
||||
reply_len = -1;
|
||||
else if (wpa_s->disconnected) {
|
||||
wpa_s->disconnected = 0;
|
||||
wpa_s->reassociate = 1;
|
||||
wpa_supplicant_req_scan(wpa_s, 0, 0);
|
||||
|
@ -1832,8 +1838,12 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
|
|||
wpa_supplicant_deauthenticate(wpa_s,
|
||||
WLAN_REASON_DEAUTH_LEAVING);
|
||||
} else if (os_strcmp(buf, "SCAN") == 0) {
|
||||
wpa_s->scan_req = 2;
|
||||
wpa_supplicant_req_scan(wpa_s, 0, 0);
|
||||
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
|
||||
reply_len = -1;
|
||||
else {
|
||||
wpa_s->scan_req = 2;
|
||||
wpa_supplicant_req_scan(wpa_s, 0, 0);
|
||||
}
|
||||
} else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
|
||||
reply_len = wpa_supplicant_ctrl_iface_scan_results(
|
||||
wpa_s, reply, reply_size);
|
||||
|
|
|
@ -109,6 +109,9 @@ void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s)
|
|||
{
|
||||
int bssid_changed;
|
||||
|
||||
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
|
||||
return;
|
||||
|
||||
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
|
||||
bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
|
||||
os_memset(wpa_s->bssid, 0, ETH_ALEN);
|
||||
|
@ -1583,6 +1586,14 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
|||
struct wpa_supplicant *wpa_s = ctx;
|
||||
u16 reason_code = 0;
|
||||
|
||||
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED &&
|
||||
event != EVENT_INTERFACE_ENABLED &&
|
||||
event != EVENT_INTERFACE_STATUS) {
|
||||
wpa_printf(MSG_DEBUG, "Ignore event %d while interface is "
|
||||
"disabled", event);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event) {
|
||||
case EVENT_AUTH:
|
||||
sme_event_auth(wpa_s, data);
|
||||
|
@ -1726,6 +1737,19 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
|||
bgscan_notify_signal_change(
|
||||
wpa_s, data->signal_change.above_threshold);
|
||||
break;
|
||||
case EVENT_INTERFACE_ENABLED:
|
||||
wpa_printf(MSG_DEBUG, "Interface was enabled");
|
||||
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
|
||||
wpa_supplicant_set_state(wpa_s,
|
||||
WPA_DISCONNECTED);
|
||||
wpa_supplicant_req_scan(wpa_s, 0, 0);
|
||||
}
|
||||
break;
|
||||
case EVENT_INTERFACE_DISABLED:
|
||||
wpa_printf(MSG_DEBUG, "Interface was disabled");
|
||||
wpa_supplicant_mark_disassoc(wpa_s);
|
||||
wpa_supplicant_set_state(wpa_s, WPA_INTERFACE_DISABLED);
|
||||
break;
|
||||
default:
|
||||
wpa_printf(MSG_INFO, "Unknown event %d", event);
|
||||
break;
|
||||
|
|
|
@ -251,6 +251,11 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
|
|||
size_t max_ssids;
|
||||
enum wpa_states prev_state;
|
||||
|
||||
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
|
||||
wpa_printf(MSG_DEBUG, "Skip scan - interface disabled");
|
||||
return;
|
||||
}
|
||||
|
||||
if (wpa_s->disconnected && !wpa_s->scan_req) {
|
||||
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
|
||||
return;
|
||||
|
|
|
@ -489,6 +489,8 @@ const char * wpa_supplicant_state_txt(enum wpa_states state)
|
|||
return "DISCONNECTED";
|
||||
case WPA_INACTIVE:
|
||||
return "INACTIVE";
|
||||
case WPA_INTERFACE_DISABLED:
|
||||
return "INTERFACE_DISABLED";
|
||||
case WPA_SCANNING:
|
||||
return "SCANNING";
|
||||
case WPA_AUTHENTICATING:
|
||||
|
@ -592,7 +594,8 @@ static void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
|
|||
wpa_s->group_cipher = 0;
|
||||
wpa_s->mgmt_group_cipher = 0;
|
||||
wpa_s->key_mgmt = 0;
|
||||
wpa_s->wpa_state = WPA_DISCONNECTED;
|
||||
if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
|
||||
wpa_s->wpa_state = WPA_DISCONNECTED;
|
||||
|
||||
if (wpa_s->wpa_state != old_state)
|
||||
wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
|
||||
|
|
Loading…
Reference in a new issue