rfkill: Add support for reacting to radio kill switch events.
In order for this to work, the correct rfkill index must be specified with the rfkill-idx option. It might be possible to auto-detect the corresponding rfkill-idx option, but I'm not sure if there's a guaranteed mapping between rfkill name and interface name, as it seems that rfkills should represent phy devices and not wlan devices. The rfkill indexes can be found by checking /sys/class/rfkill/rfkill<IDX>.
This commit is contained in:
parent
3421f0c585
commit
e3d4d4c1aa
12
src/cfg.rl
12
src/cfg.rl
@ -163,6 +163,11 @@ struct cfgparse {
|
||||
case -1: allow_hostname = 0; default: break;
|
||||
}
|
||||
}
|
||||
action rfkill_idx {
|
||||
uint32_t t = atoi(ccfg.buf);
|
||||
client_config.rfkillIdx = t;
|
||||
client_config.enable_rfkill = 1;
|
||||
}
|
||||
action version { print_version(); exit(EXIT_SUCCESS); }
|
||||
action help { show_usage(); exit(EXIT_SUCCESS); }
|
||||
}%%
|
||||
@ -206,13 +211,14 @@ struct cfgparse {
|
||||
gw_metric = 'gw-metric' value @gw_metric;
|
||||
resolv_conf = 'resolv-conf' value @resolv_conf;
|
||||
dhcp_set_hostname = 'dhcp-set-hostname' boolval @dhcp_set_hostname;
|
||||
rfkill_idx = 'rfkill-idx' value @rfkill_idx;
|
||||
|
||||
main := blankline |
|
||||
clientid | background | pidfile | hostname | interface | now | quit |
|
||||
request | vendorid | user | ifch_user | sockd_user | chroot |
|
||||
state_dir | seccomp_enforce | relentless_defense | arp_probe_wait |
|
||||
arp_probe_num | arp_probe_min | arp_probe_max | gw_metric |
|
||||
resolv_conf | dhcp_set_hostname
|
||||
resolv_conf | dhcp_set_hostname | rfkill_idx
|
||||
;
|
||||
}%%
|
||||
|
||||
@ -278,6 +284,7 @@ static void parse_cfgfile(const char *fname)
|
||||
gw_metric = ('-t'|'--gw-metric') argval @gw_metric;
|
||||
resolv_conf = ('-R'|'--resolv-conf') argval @resolv_conf;
|
||||
dhcp_set_hostname = ('-H'|'--dhcp-set-hostname') tbv @dhcp_set_hostname;
|
||||
rfkill_idx = ('-K'|'--rfkill-idx') argval @rfkill_idx;
|
||||
version = ('-v'|'--version') 0 @version;
|
||||
help = ('-?'|'--help') 0 @help;
|
||||
|
||||
@ -286,7 +293,8 @@ static void parse_cfgfile(const char *fname)
|
||||
now | quit | request | vendorid | user | ifch_user | sockd_user |
|
||||
chroot | state_dir | seccomp_enforce | relentless_defense |
|
||||
arp_probe_wait | arp_probe_num | arp_probe_min | arp_probe_max |
|
||||
gw_metric | resolv_conf | dhcp_set_hostname | version | help
|
||||
gw_metric | resolv_conf | dhcp_set_hostname | rfkill_idx |
|
||||
version | help
|
||||
)*;
|
||||
}%%
|
||||
|
||||
|
11
src/ndhc.8
11
src/ndhc.8
@ -133,6 +133,17 @@ default is 2000ms. The precise inter-probe wait time is randomized.
|
||||
Specifies the routing metric for the default gateway entry. Defaults to
|
||||
0 if not specified. Higher values will de-prioritize the route entry.
|
||||
.TP
|
||||
.BI \-K\ RFKILLIDX ,\ \-\-rfkill\-idx= RFKILLIDX
|
||||
If set, specifies the rfkill device index that corresponds to this interface.
|
||||
ndhc will then listen for matching radio frequency kill switch events
|
||||
and will bring the interface up and down in reaction to the events.
|
||||
The rfkill devices can be found in /sys/class/rfkill/rfkill<RFKILLIDX>.
|
||||
It may be useful to check the contents of the 'name' file within this
|
||||
directory to determine the correct device index. In any event, if
|
||||
an rfkill-idx parameter is specified, ndhc will print messages for any
|
||||
rfkill events that it sees, so it should not be too difficult to locate
|
||||
the proper rfkill device by checking the logs after hitting the switch.
|
||||
.TP
|
||||
.BI \-v ,\ \-\-version
|
||||
Display the ndhc version number.
|
||||
.SH SIGNALS
|
||||
|
11
src/ndhc.c
11
src/ndhc.c
@ -71,6 +71,7 @@
|
||||
#include "ifchd.h"
|
||||
#include "duiaid.h"
|
||||
#include "sockd.h"
|
||||
#include "rfkill.h"
|
||||
|
||||
struct client_state_t cs = {
|
||||
.ifchWorking = 0,
|
||||
@ -82,6 +83,7 @@ struct client_state_t cs = {
|
||||
.arpFd = -1,
|
||||
.nlFd = -1,
|
||||
.nlPortId = -1,
|
||||
.rfkillFd = -1,
|
||||
.routerArp = "\0\0\0\0\0\0",
|
||||
.serverArp = "\0\0\0\0\0\0",
|
||||
};
|
||||
@ -275,7 +277,7 @@ static void handle_ifch_message(void)
|
||||
cs.ifchWorking = 0;
|
||||
}
|
||||
|
||||
#define NDHC_NUM_EP_FDS 7
|
||||
#define NDHC_NUM_EP_FDS 8
|
||||
static void do_ndhc_work(void)
|
||||
{
|
||||
struct epoll_event events[NDHC_NUM_EP_FDS];
|
||||
@ -295,6 +297,8 @@ static void do_ndhc_work(void)
|
||||
epoll_add(cs.epollFd, ifchSock[0]);
|
||||
epoll_add(cs.epollFd, ifchStream[0]);
|
||||
epoll_add(cs.epollFd, sockdStream[0]);
|
||||
if (client_config.enable_rfkill && cs.rfkillFd != -1)
|
||||
epoll_add(cs.epollFd, cs.nlFd);
|
||||
start_dhcp_listen(&cs);
|
||||
nowts = curms();
|
||||
goto jumpstart;
|
||||
@ -330,6 +334,9 @@ static void do_ndhc_work(void)
|
||||
} else if (fd == sockdStream[0]) {
|
||||
if (events[i].events & (EPOLLHUP|EPOLLERR|EPOLLRDHUP))
|
||||
exit(EXIT_FAILURE);
|
||||
} else if (fd == cs.rfkillFd && client_config.enable_rfkill) {
|
||||
if (events[i].events & EPOLLIN)
|
||||
handle_rfkill_notice(&cs, client_config.rfkillIdx);
|
||||
} else
|
||||
suicide("epoll_wait: unknown fd");
|
||||
}
|
||||
@ -429,6 +436,8 @@ static void ndhc_main(void) {
|
||||
if ((cs.nlFd = nl_open(NETLINK_ROUTE, RTMGRP_LINK, &cs.nlPortId)) < 0)
|
||||
suicide("%s: failed to open netlink socket", __func__);
|
||||
|
||||
cs.rfkillFd = rfkill_open(&client_config.enable_rfkill);
|
||||
|
||||
if (client_config.foreground && !client_config.background_if_no_lease) {
|
||||
if (file_exists(pidfile, "w") < 0)
|
||||
suicide("%s: can't open pidfile '%s' for write!",
|
||||
|
@ -40,7 +40,7 @@ struct client_state_t {
|
||||
int ifsPrevState;
|
||||
int ifchWorking; // ifch is performing interface changes.
|
||||
int ifDeconfig; // Set if the interface has already been deconfigured.
|
||||
int epollFd, signalFd, listenFd, arpFd, nlFd;
|
||||
int epollFd, signalFd, listenFd, arpFd, nlFd, rfkillFd;
|
||||
int nlPortId;
|
||||
uint32_t clientAddr, serverAddr, srcAddr, routerAddr;
|
||||
uint32_t lease, renewTime, rebindTime, xid;
|
||||
@ -54,6 +54,7 @@ struct client_config_t {
|
||||
char quit_after_lease; // Quit after obtaining lease
|
||||
char abort_if_no_lease; // Abort if no lease
|
||||
char background_if_no_lease; // Fork to background if no lease
|
||||
char enable_rfkill; // Listen for rfkill events
|
||||
char interface[IFNAMSIZ]; // The name of the interface to use
|
||||
char clientid[64]; // Optional client id to use
|
||||
uint8_t clientid_len; // Length of the clientid
|
||||
@ -61,6 +62,7 @@ struct client_config_t {
|
||||
char vendor[64]; // Vendor identification that will be sent
|
||||
int metric; // Metric for the default route
|
||||
int ifindex; // Index number of the interface to use
|
||||
uint32_t rfkillIdx; // Index of the corresponding rfkill device
|
||||
uint8_t arp[6]; // Our arp address
|
||||
};
|
||||
|
||||
|
92
src/rfkill.c
Normal file
92
src/rfkill.c
Normal file
@ -0,0 +1,92 @@
|
||||
/* rfkill.c - rfkill interface and handling
|
||||
*
|
||||
* Copyright (c) 2015 Nicholas J. Kain <njkain at gmail dot com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/rfkill.h>
|
||||
#include "nk/log.h"
|
||||
#include "nk/io.h"
|
||||
#include "ndhc.h"
|
||||
#include "netlink.h"
|
||||
#include "rfkill.h"
|
||||
|
||||
int rfkill_open(char enable_rfkill[static 1])
|
||||
{
|
||||
if (!*enable_rfkill)
|
||||
return -1;
|
||||
int r = open("/dev/rfkill", O_RDONLY|O_CLOEXEC|O_NONBLOCK);
|
||||
if (r < 0) {
|
||||
*enable_rfkill = 0;
|
||||
log_line("rfkill disabled: could not open /dev/rfkill: %s",
|
||||
strerror(errno));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void handle_rfkill_notice(struct client_state_t cs[static 1], uint32_t rfkidx)
|
||||
{
|
||||
struct rfkill_event event;
|
||||
ssize_t len = safe_read(cs->rfkillFd, (char *)&event, sizeof event);
|
||||
if (len < 0) {
|
||||
log_error("rfkill: safe_read failed: %s", strerror(errno));
|
||||
return;
|
||||
}
|
||||
if (len != RFKILL_EVENT_SIZE_V1) {
|
||||
log_error("rfkill: event has unexpected size: %d", len);
|
||||
return;
|
||||
}
|
||||
log_line("rfkill: idx[%u] type[%u] op[%u] soft[%u] hard[%u]",
|
||||
event.idx, event.type, event.op, event.soft, event.hard);
|
||||
if (event.idx != rfkidx)
|
||||
return;
|
||||
if (event.op != RFKILL_OP_CHANGE && event.op != RFKILL_OP_CHANGE_ALL)
|
||||
return;
|
||||
if (event.soft || event.hard) {
|
||||
if (cs->ifsPrevState == IFS_UP) {
|
||||
log_line("rfkill: radio now blocked; bringing interface down");
|
||||
cs->ifsPrevState = IFS_DOWN;
|
||||
ifnocarrier_action(cs);
|
||||
} else
|
||||
log_line("rfkill: radio now blocked, but interface isn't up");
|
||||
} else {
|
||||
if (cs->ifsPrevState == IFS_DOWN) {
|
||||
log_line("rfkill: radio now unblocked; bringing interface up");
|
||||
cs->ifsPrevState = IFS_UP;
|
||||
ifup_action(cs);
|
||||
} else {
|
||||
if (cs->ifsPrevState == IFS_SHUT)
|
||||
log_line("rfkill: radio now unblocked, but interface was shut down by user");
|
||||
else
|
||||
log_line("rfkill: radio now unblocked, but interface is removed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
35
src/rfkill.h
Normal file
35
src/rfkill.h
Normal file
@ -0,0 +1,35 @@
|
||||
#ifndef NDHC_RFKILL_H_
|
||||
#define NDHC_RFKILL_H_
|
||||
/* rfkill.h - rfkill interface and handling
|
||||
*
|
||||
* Copyright (c) 2015 Nicholas J. Kain <njkain at gmail dot com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
int rfkill_open(char enable_rfkill[static 1]);
|
||||
void handle_rfkill_notice(struct client_state_t cs[static 1], uint32_t rfkidx);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user