aboutsummaryrefslogtreecommitdiffstats
path: root/src/drivers/driver_wext.c
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2010-05-23 07:27:32 (GMT)
committerJouni Malinen <j@w1.fi>2010-05-23 07:27:32 (GMT)
commit8401a6b028c464a427654496b7b4a4cfb4ab8492 (patch)
tree2a58f83fd3564e81314b8620debcea376e7585c9 /src/drivers/driver_wext.c
parent6deb41e73f74270656150e70cf6323276dd54f14 (diff)
downloadhostap-8401a6b028c464a427654496b7b4a4cfb4ab8492.zip
hostap-8401a6b028c464a427654496b7b4a4cfb4ab8492.tar.gz
hostap-8401a6b028c464a427654496b7b4a4cfb4ab8492.tar.bz2
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.
Diffstat (limited to 'src/drivers/driver_wext.c')
-rw-r--r--src/drivers/driver_wext.c63
1 files changed, 61 insertions, 2 deletions
diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c
index 2614f23..ef3a30c 100644
--- a/src/drivers/driver_wext.c
+++ b/src/drivers/driver_wext.c
@@ -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);