Beniamino Galvani 2022-03-29 09:37:15 +02:00
commit 7d5a8d4f74
10 changed files with 189 additions and 24 deletions

View file

@ -384,6 +384,16 @@
-->
<property name="WimaxHardwareEnabled" type="b" access="read"/>
<!--
RadioFlags:
@since: 1.38
Flags related to radio devices. See <link
linkend="NMRadioFlags">NMRadioFlags</link> for the list of flags
supported.
-->
<property name="RadioFlags" type="u" access="read"/>
<!--
ActiveConnections:

View file

@ -60,6 +60,7 @@ typedef struct {
} RfkillTypeDesc;
typedef struct {
bool available : 1;
bool user_enabled : 1;
bool sw_enabled : 1;
bool hw_enabled : 1;
@ -122,6 +123,7 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMManager,
PROP_WWAN_HARDWARE_ENABLED,
PROP_WIMAX_ENABLED,
PROP_WIMAX_HARDWARE_ENABLED,
PROP_RADIO_FLAGS,
PROP_ACTIVE_CONNECTIONS,
PROP_CONNECTIVITY,
PROP_CONNECTIVITY_CHECK_AVAILABLE,
@ -193,6 +195,8 @@ typedef struct {
guint devices_inited_id;
guint radio_flags;
NMConnectivityState connectivity_state;
guint8 device_state_prune_ratelimit_count;
@ -396,6 +400,8 @@ static void _activation_auth_done(NMManager *self,
gboolean success,
const char *error_desc);
static void _rfkill_update(NMManager *self, NMRfkillType rtype);
/*****************************************************************************/
static NM_CACHED_QUARK_FCN("autoconnect-root", autoconnect_root_quark);
@ -1715,6 +1721,7 @@ remove_device(NMManager *self, NMDevice *device, gboolean quitting)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self);
gboolean unmanage = FALSE;
NMRfkillType rtype;
_LOG2D(LOGD_DEVICE,
device,
@ -1755,6 +1762,10 @@ remove_device(NMManager *self, NMDevice *device, gboolean quitting)
_parent_notify_changed(self, device, TRUE);
rtype = nm_device_get_rfkill_type(device);
if (rtype != NM_RFKILL_TYPE_UNKNOWN)
_rfkill_update(self, rtype);
if (nm_device_is_real(device)) {
gboolean unconfigure_ip_config = !quitting || unmanage;
@ -2318,28 +2329,48 @@ _rfkill_radio_state_get_enabled(const RfkillRadioState *rstate, gboolean check_c
}
static void
_rfkill_radio_state_set_from_manager(NMRfkillManager *rfkill_mgr,
NMRfkillType rtype,
RfkillRadioState *rstate)
_rfkill_radio_state_set_from_manager(NMManager *self, NMRfkillType rtype, RfkillRadioState *rstate)
{
switch (nm_rfkill_manager_get_rfkill_state(rfkill_mgr, rtype)) {
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self);
NMDevice *device;
switch (nm_rfkill_manager_get_rfkill_state(priv->rfkill_mgr, rtype)) {
case NM_RFKILL_STATE_UNAVAILABLE:
rstate->sw_enabled = TRUE;
rstate->hw_enabled = TRUE;
rstate->os_owner = TRUE;
/* A rfkill-type is available when there is a compatible
* killswitch or a compatible device. */
c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) {
if (nm_device_get_rfkill_type(device) == rtype) {
rstate->available = TRUE;
return;
}
}
rstate->available = FALSE;
return;
case NM_RFKILL_STATE_UNBLOCKED:
rstate->available = TRUE;
rstate->sw_enabled = TRUE;
rstate->hw_enabled = TRUE;
rstate->os_owner = TRUE;
return;
case NM_RFKILL_STATE_SOFT_BLOCKED:
rstate->available = TRUE;
rstate->sw_enabled = FALSE;
rstate->hw_enabled = TRUE;
rstate->os_owner = TRUE;
return;
case NM_RFKILL_STATE_HARD_BLOCKED:
rstate->available = TRUE;
rstate->sw_enabled = FALSE;
rstate->hw_enabled = FALSE;
/* In case the OS doesn't own the NIC, we would be in NM_RFKILL_STATE_HARD_BLOCKED */
rstate->os_owner = TRUE;
return;
case NM_RFKILL_STATE_HARD_BLOCKED_OS_NOT_OWNER:
rstate->available = TRUE;
rstate->sw_enabled = FALSE;
rstate->hw_enabled = FALSE;
rstate->os_owner = FALSE;
@ -2392,20 +2423,23 @@ _rfkill_update_one_type(NMManager *self, NMRfkillType rtype)
gboolean old_rfkilled;
gboolean new_rfkilled;
gboolean old_hwe;
guint old_radio_flags;
nm_assert(_NM_INT_NOT_NEGATIVE(rtype) && rtype < G_N_ELEMENTS(priv->radio_states));
old_enabled = _rfkill_radio_state_get_enabled(rstate, TRUE);
old_rfkilled = rstate->hw_enabled && rstate->sw_enabled;
old_hwe = rstate->hw_enabled;
old_enabled = _rfkill_radio_state_get_enabled(rstate, TRUE);
old_rfkilled = rstate->hw_enabled && rstate->sw_enabled;
old_hwe = rstate->hw_enabled;
old_radio_flags = priv->radio_flags;
/* recheck kernel rfkill state */
_rfkill_radio_state_set_from_manager(priv->rfkill_mgr, rtype, rstate);
_rfkill_radio_state_set_from_manager(self, rtype, rstate);
/* Print out all states affecting device enablement */
_LOGD(LOGD_RFKILL,
"rfkill: %s hw-enabled %d sw-enabled %d os-owner %d",
"rfkill: %s available %d hw-enabled %d sw-enabled %d os-owner %d",
nm_rfkill_type_to_string(rtype),
rstate->available,
rstate->hw_enabled,
rstate->sw_enabled,
rstate->os_owner);
@ -2419,9 +2453,15 @@ _rfkill_update_one_type(NMManager *self, NMRfkillType rtype)
new_rfkilled ? "enabled" : "disabled");
}
/* Send out property changed signal for HW enabled */
if (rstate->hw_enabled != old_hwe)
_notify(self, _rfkill_type_desc[rtype].hw_prop_id);
priv->radio_flags = NM_FLAGS_ASSIGN(priv->radio_flags,
(guint) nm_rfkill_type_to_radio_available_flag(rtype),
rstate->available);
/* Send out property changed signal for HW available and enabled */
nm_gobject_notify_together(self,
rstate->hw_enabled != old_hwe ? _rfkill_type_desc[rtype].hw_prop_id
: PROP_0,
priv->radio_flags != old_radio_flags ? PROP_RADIO_FLAGS : PROP_0);
/* And finally update the actual device radio state itself; respect the
* daemon state here because this is never called from user-triggered
@ -7094,7 +7134,7 @@ nm_manager_start(NMManager *self, GError **error)
gboolean enabled;
/* recheck kernel rfkill state */
_rfkill_radio_state_set_from_manager(priv->rfkill_mgr, rtype, rstate);
_rfkill_radio_state_set_from_manager(self, rtype, rstate);
_LOGI(LOGD_RFKILL,
"rfkill: %s %s by radio killswitch; %s by state file",
@ -8076,6 +8116,9 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
case PROP_WIMAX_HARDWARE_ENABLED:
g_value_set_boolean(value, FALSE);
break;
case PROP_RADIO_FLAGS:
g_value_set_uint(value, priv->radio_flags);
break;
case PROP_ACTIVE_CONNECTIONS:
ptrarr = g_ptr_array_new();
c_list_for_each_entry_prev (ac,
@ -8531,6 +8574,9 @@ static const NMDBusInterfaceInfoExtended interface_info_manager = {
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("WimaxHardwareEnabled",
"b",
NM_MANAGER_WIMAX_HARDWARE_ENABLED),
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("RadioFlags",
"u",
NM_MANAGER_RADIO_FLAGS),
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("ActiveConnections",
"ao",
NM_MANAGER_ACTIVE_CONNECTIONS),
@ -8675,6 +8721,14 @@ nm_manager_class_init(NMManagerClass *manager_class)
TRUE,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
obj_properties[PROP_RADIO_FLAGS] = g_param_spec_uint(NM_MANAGER_RADIO_FLAGS,
"",
"",
0,
G_MAXUINT32,
NM_RADIO_FLAG_NONE,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
obj_properties[PROP_ACTIVE_CONNECTIONS] =
g_param_spec_boxed(NM_MANAGER_ACTIVE_CONNECTIONS,
"",

View file

@ -30,6 +30,7 @@
#define NM_MANAGER_WWAN_HARDWARE_ENABLED "wwan-hardware-enabled"
#define NM_MANAGER_WIMAX_ENABLED "wimax-enabled"
#define NM_MANAGER_WIMAX_HARDWARE_ENABLED "wimax-hardware-enabled"
#define NM_MANAGER_RADIO_FLAGS "radio-flags"
#define NM_MANAGER_ACTIVE_CONNECTIONS "active-connections"
#define NM_MANAGER_CONNECTIVITY "connectivity"
#define NM_MANAGER_CONNECTIVITY_CHECK_AVAILABLE "connectivity-check-available"

View file

@ -66,6 +66,20 @@ nm_rfkill_manager_get_rfkill_state(NMRfkillManager *self, NMRfkillType rtype)
return NM_RFKILL_MANAGER_GET_PRIVATE(self)->rfkill_states[rtype];
}
NMRadioFlags
nm_rfkill_type_to_radio_available_flag(NMRfkillType type)
{
switch (type) {
case NM_RFKILL_TYPE_WLAN:
return NM_RADIO_FLAG_WLAN_AVAILABLE;
case NM_RFKILL_TYPE_WWAN:
return NM_RADIO_FLAG_WWAN_AVAILABLE;
case NM_RFKILL_TYPE_UNKNOWN:
break;
}
return nm_assert_unreachable_val(NM_RADIO_FLAG_NONE);
}
const char *
nm_rfkill_type_to_string(NMRfkillType type)
{
@ -84,6 +98,8 @@ static const char *
nm_rfkill_state_to_string(NMRfkillState state)
{
switch (state) {
case NM_RFKILL_STATE_UNAVAILABLE:
return "unavailable";
case NM_RFKILL_STATE_UNBLOCKED:
return "unblocked";
case NM_RFKILL_STATE_SOFT_BLOCKED:
@ -188,8 +204,8 @@ recheck_killswitches(NMRfkillManager *self)
/* Default state is unblocked */
for (i = 0; i < NM_RFKILL_TYPE_MAX; i++) {
poll_states[i] = NM_RFKILL_STATE_UNBLOCKED;
platform_states[i] = NM_RFKILL_STATE_UNBLOCKED;
poll_states[i] = NM_RFKILL_STATE_UNAVAILABLE;
platform_states[i] = NM_RFKILL_STATE_UNAVAILABLE;
platform_checked[i] = FALSE;
}
@ -222,12 +238,12 @@ recheck_killswitches(NMRfkillManager *self)
dev_state = sysfs_state_to_nm_state(sysfs_state, sysfs_reason);
nm_log_dbg(LOGD_RFKILL,
"%s rfkill%s switch %s state now %d/%u reason: 0x%x",
"%s rfkill%s switch %s state now %d/%s reason: 0x%x",
nm_rfkill_type_to_string(ks->rtype),
ks->platform ? " platform" : "",
ks->name,
sysfs_state,
dev_state,
nm_rfkill_state_to_string(dev_state),
sysfs_reason);
if (ks->platform == FALSE) {
@ -248,7 +264,7 @@ recheck_killswitches(NMRfkillManager *self)
/* blocked platform switch state overrides device state, otherwise
* let the device state stand. (bgo #655773)
*/
if (platform_states[i] != NM_RFKILL_STATE_UNBLOCKED)
if (platform_states[i] > NM_RFKILL_STATE_UNBLOCKED)
poll_states[i] = platform_states[i];
}
@ -396,7 +412,7 @@ nm_rfkill_manager_init(NMRfkillManager *self)
c_list_init(&priv->killswitch_lst_head);
for (i = 0; i < NM_RFKILL_TYPE_MAX; i++)
priv->rfkill_states[i] = NM_RFKILL_STATE_UNBLOCKED;
priv->rfkill_states[i] = NM_RFKILL_STATE_UNAVAILABLE;
priv->udev_client = nm_udev_client_new(NM_MAKE_STRV("rfkill"), handle_uevent, self);

View file

@ -8,16 +8,17 @@
#define __NM_RFKILL_MANAGER_H__
typedef enum {
NM_RFKILL_STATE_UNBLOCKED = 0,
NM_RFKILL_STATE_SOFT_BLOCKED = 1,
NM_RFKILL_STATE_HARD_BLOCKED = 2,
NM_RFKILL_STATE_UNAVAILABLE = 0,
NM_RFKILL_STATE_UNBLOCKED = 1,
NM_RFKILL_STATE_SOFT_BLOCKED = 2,
NM_RFKILL_STATE_HARD_BLOCKED = 3,
/* NM_RFKILL_STATE_HARD_BLOCKED_OS_NOT_OWNER means that the CSME firmware
* is currently controlling the device. This feature is implmented on Intel
* wifi devices only.
* The NetworkManager can get ownership on the device, but it requires to
* first ask ownership through the iwlmei kernel module.
*/
NM_RFKILL_STATE_HARD_BLOCKED_OS_NOT_OWNER = 3,
NM_RFKILL_STATE_HARD_BLOCKED_OS_NOT_OWNER = 4,
} NMRfkillState;
typedef enum {
@ -54,4 +55,6 @@ NMRfkillManager *nm_rfkill_manager_new(void);
NMRfkillState nm_rfkill_manager_get_rfkill_state(NMRfkillManager *manager, NMRfkillType rtype);
NMRadioFlags nm_rfkill_type_to_radio_available_flag(NMRfkillType type);
#endif /* __NM_RFKILL_MANAGER_H__ */

View file

@ -1820,4 +1820,10 @@ global:
libnm_1_36_0 {
global:
nm_setting_ovs_dpdk_get_n_rxq;
} libnm_1_34_0;
} libnm_1_34_0;
libnm_1_38_0 {
global:
nm_client_get_radio_flags;
nm_radio_flags_get_type;
} libnm_1_36_0;

View file

@ -198,6 +198,7 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMClient,
PROP_WWAN_HARDWARE_ENABLED,
PROP_WIMAX_ENABLED,
PROP_WIMAX_HARDWARE_ENABLED,
PROP_RADIO_FLAGS,
PROP_ACTIVE_CONNECTIONS,
PROP_CONNECTIVITY,
PROP_CONNECTIVITY_CHECK_URI,
@ -307,6 +308,7 @@ typedef struct {
guint32 connectivity;
guint32 state;
guint32 metered;
guint32 radio_flags;
bool connectivity_check_available;
bool connectivity_check_enabled;
bool networking_enabled;
@ -4235,6 +4237,24 @@ nm_client_wireless_hardware_get_enabled(NMClient *client)
return NM_CLIENT_GET_PRIVATE(client)->nm.wireless_hardware_enabled;
}
/**
* nm_client_get_radio_flags:
* @client: a #NMClient
*
* Get radio flags.
*
* Returns: the #NMRadioFlags.
*
* Since: 1.38
**/
NMRadioFlags
nm_client_get_radio_flags(NMClient *client)
{
g_return_val_if_fail(NM_IS_CLIENT(client), NM_RADIO_FLAG_NONE);
return NM_CLIENT_GET_PRIVATE(client)->nm.radio_flags;
}
/**
* nm_client_wwan_get_enabled:
* @client: a #NMClient
@ -7454,6 +7474,9 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
case PROP_WIRELESS_HARDWARE_ENABLED:
g_value_set_boolean(value, nm_client_wireless_hardware_get_enabled(self));
break;
case PROP_RADIO_FLAGS:
g_value_set_uint(value, priv->nm.radio_flags);
break;
case PROP_WWAN_ENABLED:
g_value_set_boolean(value, nm_client_wwan_get_enabled(self));
break;
@ -8046,6 +8069,10 @@ const NMLDBusMetaIface _nml_dbus_meta_iface_nm = NML_DBUS_META_IFACE_INIT_PROP(
_priv.nm.property_o[PROPERTY_O_IDX_NM_PRIMAY_CONNECTION],
nm_active_connection_get_type),
NML_DBUS_META_PROPERTY_INIT_IGNORE("PrimaryConnectionType", "s"),
NML_DBUS_META_PROPERTY_INIT_U("RadioFlags",
PROP_RADIO_FLAGS,
NMClient,
_priv.nm.radio_flags),
NML_DBUS_META_PROPERTY_INIT_B("Startup", PROP_STARTUP, NMClient, _priv.nm.startup),
NML_DBUS_META_PROPERTY_INIT_U("State", PROP_STATE, NMClient, _priv.nm.state),
NML_DBUS_META_PROPERTY_INIT_S("Version", PROP_VERSION, NMClient, _priv.nm.version),
@ -8313,6 +8340,21 @@ nm_client_class_init(NMClientClass *client_class)
FALSE,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
/**
* NMClient:radio-flags:
*
* Flags for radio interfaces. See #NMRadioFlags.
*
* Since: 1.38
**/
obj_properties[PROP_RADIO_FLAGS] = g_param_spec_uint(NM_CLIENT_RADIO_FLAGS,
"",
"",
0,
G_MAXUINT32,
NM_RADIO_FLAG_NONE,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
/**
* NMClient:active-connections: (type GPtrArray(NMActiveConnection))
*

View file

@ -61,6 +61,8 @@ _NM_DEPRECATED_SYNC_WRITABLE_PROPERTY
#define NM_CLIENT_WWAN_HARDWARE_ENABLED "wwan-hardware-enabled"
#define NM_CLIENT_WIMAX_HARDWARE_ENABLED "wimax-hardware-enabled"
#define NM_CLIENT_RADIO_FLAGS "radio-flags"
#define NM_CLIENT_ACTIVE_CONNECTIONS "active-connections"
#define NM_CLIENT_CONNECTIVITY "connectivity"
#define NM_CLIENT_CONNECTIVITY_CHECK_URI "connectivity-check-uri"
@ -213,6 +215,9 @@ void nm_client_wimax_set_enabled(NMClient *client, gboolean enabled);
NM_DEPRECATED_IN_1_22
gboolean nm_client_wimax_hardware_get_enabled(NMClient *client);
NM_AVAILABLE_IN_1_38
NMRadioFlags nm_client_get_radio_flags(NMClient *client);
NM_AVAILABLE_IN_1_10
gboolean nm_client_connectivity_check_get_available(NMClient *client);

View file

@ -1297,4 +1297,22 @@ typedef enum {
NM_CLIENT_PERMISSION_RESULT_NO
} NMClientPermissionResult;
/**
* NMRadioFlags:
* @NM_RADIO_FLAG_NONE: an alias for numeric zero, no flags set.
* @NM_RADIO_FLAG_WLAN_AVAILABLE: A Wireless LAN device or rfkill switch
* is detected in the system.
* @NM_RADIO_FLAG_WWAN_AVAILABLE: A Wireless WAN device or rfkill switch
* is detected in the system.
*
* Flags related to radio interfaces.
*
* Since: 1.38
*/
typedef enum /*< flags >*/ {
NM_RADIO_FLAG_NONE = 0,
NM_RADIO_FLAG_WLAN_AVAILABLE = 0x1,
NM_RADIO_FLAG_WWAN_AVAILABLE = 0x2,
} NMRadioFlags;
#endif /* __NM_DBUS_INTERFACE_H__ */

View file

@ -145,12 +145,22 @@ _metagen_general_status_get_fcn(NMC_META_GENERIC_INFO_GET_FCN_ARGS)
v_bool = nm_client_networking_get_enabled(nmc->client);
goto enabled_out;
case NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WIFI_HW:
if (!(nm_client_get_radio_flags(nmc->client) & NM_RADIO_FLAG_WLAN_AVAILABLE)) {
NMC_HANDLE_COLOR(NM_META_COLOR_NONE);
value = N_("missing");
goto translate_and_out;
}
v_bool = nm_client_wireless_hardware_get_enabled(nmc->client);
goto enabled_out;
case NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WIFI:
v_bool = nm_client_wireless_get_enabled(nmc->client);
goto enabled_out;
case NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WWAN_HW:
if (!(nm_client_get_radio_flags(nmc->client) & NM_RADIO_FLAG_WWAN_AVAILABLE)) {
NMC_HANDLE_COLOR(NM_META_COLOR_NONE);
value = N_("missing");
goto translate_and_out;
}
v_bool = nm_client_wwan_hardware_get_enabled(nmc->client);
goto enabled_out;
case NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WWAN: