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;
|
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 version { print_version(); exit(EXIT_SUCCESS); }
|
||||||
action help { show_usage(); exit(EXIT_SUCCESS); }
|
action help { show_usage(); exit(EXIT_SUCCESS); }
|
||||||
}%%
|
}%%
|
||||||
@ -206,13 +211,14 @@ struct cfgparse {
|
|||||||
gw_metric = 'gw-metric' value @gw_metric;
|
gw_metric = 'gw-metric' value @gw_metric;
|
||||||
resolv_conf = 'resolv-conf' value @resolv_conf;
|
resolv_conf = 'resolv-conf' value @resolv_conf;
|
||||||
dhcp_set_hostname = 'dhcp-set-hostname' boolval @dhcp_set_hostname;
|
dhcp_set_hostname = 'dhcp-set-hostname' boolval @dhcp_set_hostname;
|
||||||
|
rfkill_idx = 'rfkill-idx' value @rfkill_idx;
|
||||||
|
|
||||||
main := blankline |
|
main := blankline |
|
||||||
clientid | background | pidfile | hostname | interface | now | quit |
|
clientid | background | pidfile | hostname | interface | now | quit |
|
||||||
request | vendorid | user | ifch_user | sockd_user | chroot |
|
request | vendorid | user | ifch_user | sockd_user | chroot |
|
||||||
state_dir | seccomp_enforce | relentless_defense | arp_probe_wait |
|
state_dir | seccomp_enforce | relentless_defense | arp_probe_wait |
|
||||||
arp_probe_num | arp_probe_min | arp_probe_max | gw_metric |
|
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;
|
gw_metric = ('-t'|'--gw-metric') argval @gw_metric;
|
||||||
resolv_conf = ('-R'|'--resolv-conf') argval @resolv_conf;
|
resolv_conf = ('-R'|'--resolv-conf') argval @resolv_conf;
|
||||||
dhcp_set_hostname = ('-H'|'--dhcp-set-hostname') tbv @dhcp_set_hostname;
|
dhcp_set_hostname = ('-H'|'--dhcp-set-hostname') tbv @dhcp_set_hostname;
|
||||||
|
rfkill_idx = ('-K'|'--rfkill-idx') argval @rfkill_idx;
|
||||||
version = ('-v'|'--version') 0 @version;
|
version = ('-v'|'--version') 0 @version;
|
||||||
help = ('-?'|'--help') 0 @help;
|
help = ('-?'|'--help') 0 @help;
|
||||||
|
|
||||||
@ -286,7 +293,8 @@ static void parse_cfgfile(const char *fname)
|
|||||||
now | quit | request | vendorid | user | ifch_user | sockd_user |
|
now | quit | request | vendorid | user | ifch_user | sockd_user |
|
||||||
chroot | state_dir | seccomp_enforce | relentless_defense |
|
chroot | state_dir | seccomp_enforce | relentless_defense |
|
||||||
arp_probe_wait | arp_probe_num | arp_probe_min | arp_probe_max |
|
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
|
Specifies the routing metric for the default gateway entry. Defaults to
|
||||||
0 if not specified. Higher values will de-prioritize the route entry.
|
0 if not specified. Higher values will de-prioritize the route entry.
|
||||||
.TP
|
.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
|
.BI \-v ,\ \-\-version
|
||||||
Display the ndhc version number.
|
Display the ndhc version number.
|
||||||
.SH SIGNALS
|
.SH SIGNALS
|
||||||
|
11
src/ndhc.c
11
src/ndhc.c
@ -71,6 +71,7 @@
|
|||||||
#include "ifchd.h"
|
#include "ifchd.h"
|
||||||
#include "duiaid.h"
|
#include "duiaid.h"
|
||||||
#include "sockd.h"
|
#include "sockd.h"
|
||||||
|
#include "rfkill.h"
|
||||||
|
|
||||||
struct client_state_t cs = {
|
struct client_state_t cs = {
|
||||||
.ifchWorking = 0,
|
.ifchWorking = 0,
|
||||||
@ -82,6 +83,7 @@ struct client_state_t cs = {
|
|||||||
.arpFd = -1,
|
.arpFd = -1,
|
||||||
.nlFd = -1,
|
.nlFd = -1,
|
||||||
.nlPortId = -1,
|
.nlPortId = -1,
|
||||||
|
.rfkillFd = -1,
|
||||||
.routerArp = "\0\0\0\0\0\0",
|
.routerArp = "\0\0\0\0\0\0",
|
||||||
.serverArp = "\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;
|
cs.ifchWorking = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define NDHC_NUM_EP_FDS 7
|
#define NDHC_NUM_EP_FDS 8
|
||||||
static void do_ndhc_work(void)
|
static void do_ndhc_work(void)
|
||||||
{
|
{
|
||||||
struct epoll_event events[NDHC_NUM_EP_FDS];
|
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, ifchSock[0]);
|
||||||
epoll_add(cs.epollFd, ifchStream[0]);
|
epoll_add(cs.epollFd, ifchStream[0]);
|
||||||
epoll_add(cs.epollFd, sockdStream[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);
|
start_dhcp_listen(&cs);
|
||||||
nowts = curms();
|
nowts = curms();
|
||||||
goto jumpstart;
|
goto jumpstart;
|
||||||
@ -330,6 +334,9 @@ static void do_ndhc_work(void)
|
|||||||
} else if (fd == sockdStream[0]) {
|
} else if (fd == sockdStream[0]) {
|
||||||
if (events[i].events & (EPOLLHUP|EPOLLERR|EPOLLRDHUP))
|
if (events[i].events & (EPOLLHUP|EPOLLERR|EPOLLRDHUP))
|
||||||
exit(EXIT_FAILURE);
|
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
|
} else
|
||||||
suicide("epoll_wait: unknown fd");
|
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)
|
if ((cs.nlFd = nl_open(NETLINK_ROUTE, RTMGRP_LINK, &cs.nlPortId)) < 0)
|
||||||
suicide("%s: failed to open netlink socket", __func__);
|
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 (client_config.foreground && !client_config.background_if_no_lease) {
|
||||||
if (file_exists(pidfile, "w") < 0)
|
if (file_exists(pidfile, "w") < 0)
|
||||||
suicide("%s: can't open pidfile '%s' for write!",
|
suicide("%s: can't open pidfile '%s' for write!",
|
||||||
|
@ -40,7 +40,7 @@ struct client_state_t {
|
|||||||
int ifsPrevState;
|
int ifsPrevState;
|
||||||
int ifchWorking; // ifch is performing interface changes.
|
int ifchWorking; // ifch is performing interface changes.
|
||||||
int ifDeconfig; // Set if the interface has already been deconfigured.
|
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;
|
int nlPortId;
|
||||||
uint32_t clientAddr, serverAddr, srcAddr, routerAddr;
|
uint32_t clientAddr, serverAddr, srcAddr, routerAddr;
|
||||||
uint32_t lease, renewTime, rebindTime, xid;
|
uint32_t lease, renewTime, rebindTime, xid;
|
||||||
@ -54,6 +54,7 @@ struct client_config_t {
|
|||||||
char quit_after_lease; // Quit after obtaining lease
|
char quit_after_lease; // Quit after obtaining lease
|
||||||
char abort_if_no_lease; // Abort if no lease
|
char abort_if_no_lease; // Abort if no lease
|
||||||
char background_if_no_lease; // Fork to background 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 interface[IFNAMSIZ]; // The name of the interface to use
|
||||||
char clientid[64]; // Optional client id to use
|
char clientid[64]; // Optional client id to use
|
||||||
uint8_t clientid_len; // Length of the clientid
|
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
|
char vendor[64]; // Vendor identification that will be sent
|
||||||
int metric; // Metric for the default route
|
int metric; // Metric for the default route
|
||||||
int ifindex; // Index number of the interface to use
|
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
|
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…
x
Reference in New Issue
Block a user