RFKill

The rfkill subsystem in Linux provides a mechanism to disable radio transmitters, as Wi-Fi, Bluetooth cards or WWAN modems installed in the system.

From the kernel point of view, such devices typically have a associated rfkill device (also called killswitch) that is visible in the output of the rfkill utility.

$ rfkill
ID TYPE      DEVICE                 SOFT      HARD
 0 bluetooth tpacpi_bluetooth_sw blocked unblocked
 2 wlan      phy0                blocked unblocked

Each rfkill device has a type (bluetooth, wlan, wwan) and two flags to indicate whether the killswitch is hard-blocked (when radio transmission is blocked via a hardware switch) or soft-blocked (when radio is disabled but can be re-enabled in software).

Support in NetworkManager

NetworkManager can manage the global rfkill state for Wi-Fi and WWAN devices.

It uses udev to discover (at startup, but also at runtime) the available killswitches. For each of them, NetworkManager keeps track of the current state (unblocked, soft-blocked, hard-blocked).

Each killswitch can be a platform one or a non-platform (or device) one. Platform killswitches are those belonging to the “platform” or “acpi” udev subsystem. Device switches, if hard-killed typically cannot be changed except by a physical hardware switch. Also it is common that platform killswitches control device killswitches. That is, a hard-blocked device switch can often be unblocked by a platform switch.

Therefore, when determining the global killswitch state for a given hardware type (Wi-Fi or WWAN), blocked platform switches have higher priority. If all platform switches are unblocked, then the global state is the maximum blocked state of device switches.

The global killswitch state for a hardware type is “unavailable” when no killswitches of that kind were found on the system and there are no compatible devices.

D-Bus API

The rkfill state is exposed on D-Bus via the following boolean properties of the org.freedesktop.NetworkManager interface on the /org/freedesktop/NetworkManager object:

  • WirelessEnabled (read-write)
  • WirelessHardwareEnabled (read-only)
  • WwanEnabled (read-write)
  • WwanHardwareEnabled (read-only)

‘Hardware’ properties cannot be written as they refer to the hardware-blocked state. The other two properties refer to the software-blocked state.

Since version 1.38, NetworkManager also exposes a RadioFlags property on the same interface. It currently supports two flags:

  • NM_RADIO_FLAG_WLAN_AVAILABLE = 0x1
  • NM_RADIO_FLAG_WWAN_AVAILABLE = 0x2

indicating whether any Wi-fi or WWAN hardware is present in the system.

When WirelessEnabled (or WwanEnabled) gets written, NetworkManager updates the soft-blocked state of all Wi-Fi (or WWAN) killswitches in kernel; in addition, it enables or disables any NetworkManager device of type ‘wifi’ (or ‘gsm’).

The soft-blocked state set via D-Bus is also saved in a persistent state file (/var/lib/NetworkManager/NetworkManager.state) that is reloaded at the next restart.

nmcli

nmcli implements the radio subcommand to control the rfkill state.

$ nmcli radio
WIFI-HW  WIFI      WWAN-HW  WWAN
enabled  disabled  enabled  enabled

For Wi-Fi and WWAN, bot the hardware and software killswitch states are displayed.

The soft-blocked states can be changed via

nmcli radio {all | wifi | wwan} [on | off]

and this basically controls the soft-blocked D-Bus properties as described in the previous section.

Note that since version 1.38 nmcli displays missing in the *-HW column when there are no killswitches or compatible devices.