diff options
Diffstat (limited to 'src/core')
81 files changed, 2187 insertions, 1388 deletions
diff --git a/src/core/NetworkManagerUtils.c b/src/core/NetworkManagerUtils.c index c50dbada..5727aac8 100644 --- a/src/core/NetworkManagerUtils.c +++ b/src/core/NetworkManagerUtils.c @@ -34,6 +34,11 @@ /*****************************************************************************/ +G_STATIC_ASSERT(NM_SHUTDOWN_TIMEOUT_1500_MSEC <= NM_SHUTDOWN_TIMEOUT_MAX_MSEC); +G_STATIC_ASSERT(NM_SHUTDOWN_TIMEOUT_5000_MSEC <= NM_SHUTDOWN_TIMEOUT_MAX_MSEC); + +/*****************************************************************************/ + /** * nm_utils_get_shared_wifi_permission: * @connection: the NMConnection to lookup the permission. @@ -1037,7 +1042,7 @@ _shutdown_waitobj_cb(gpointer user_data, GObject *where_the_object_was) * is still used. * * If @wait_type is %NM_SHUTDOWN_WAIT_TYPE_CANCELLABLE, then during shutdown - * (after %NM_SHUTDOWN_TIMEOUT_MS), the cancellable will be cancelled to notify + * (after %NM_SHUTDOWN_TIMEOUT_MAX_MSEC), the cancellable will be cancelled to notify * the source of the shutdown. Note that otherwise, in this mode also @watched_obj * is only tracked with a weak-pointer. Especially, it does not register to the * "cancelled" signal to automatically unregister (otherwise, you would never @@ -1046,7 +1051,7 @@ _shutdown_waitobj_cb(gpointer user_data, GObject *where_the_object_was) * FIXME(shutdown): proper shutdown is not yet implemented, and registering * an object (currently) has no effect. * - * FIXME(shutdown): during shutdown, after %NM_SHUTDOWN_TIMEOUT_MS timeout, cancel + * FIXME(shutdown): during shutdown, after %NM_SHUTDOWN_TIMEOUT_MAX_MSEC timeout, cancel * all remaining %NM_SHUTDOWN_WAIT_TYPE_CANCELLABLE instances. Also, when somebody * enqueues a cancellable after that point, cancel it right away on an idle handler. * @@ -1347,8 +1352,13 @@ nm_utils_ip_route_attribute_to_platform(int addr_family, int type; type = nm_net_aux_rtnl_rtntype_a2n(g_variant_get_string(variant, NULL)); - nm_assert( - NM_IN_SET(type, RTN_UNICAST, RTN_LOCAL, RTN_BLACKHOLE, RTN_UNREACHABLE, RTN_PROHIBIT)); + nm_assert(NM_IN_SET(type, + RTN_UNICAST, + RTN_LOCAL, + RTN_BLACKHOLE, + RTN_UNREACHABLE, + RTN_PROHIBIT, + RTN_THROW)); r->type_coerced = nm_platform_route_type_coerce(type); } else diff --git a/src/core/NetworkManagerUtils.h b/src/core/NetworkManagerUtils.h index c9210ba8..67c9cba4 100644 --- a/src/core/NetworkManagerUtils.h +++ b/src/core/NetworkManagerUtils.h @@ -103,23 +103,37 @@ NMPlatformRoutingRule *nm_ip_routing_rule_to_platform(const NMIPRoutingRule *rul /*****************************************************************************/ /* during shutdown, there are two relevant timeouts. One is - * NM_SHUTDOWN_TIMEOUT_MS which is plenty of time, that we give for all + * NM_SHUTDOWN_TIMEOUT_MAX_MSEC which is plenty of time, that we give for all * actions to complete. Of course, during shutdown components should hurry * to cleanup. * * When we initiate shutdown, we should start killing child processes - * with SIGTERM. If they don't complete within NM_SHUTDOWN_TIMEOUT_MS, we send + * with SIGTERM. If they don't complete within NM_SHUTDOWN_TIMEOUT_MAX_MSEC, we send * SIGKILL. * - * After NM_SHUTDOWN_TIMEOUT_MS, NetworkManager will however not yet terminate right - * away. It iterates the mainloop for another NM_SHUTDOWN_TIMEOUT_MS_WATCHDOG. This + * After NM_SHUTDOWN_TIMEOUT_MAX_MSEC, NetworkManager will however not yet terminate right + * away. It iterates the mainloop for another NM_SHUTDOWN_TIMEOUT_ADDITIONAL_MSEC. This * should give time to reap the child process (after SIGKILL). * * So, the maximum time we should wait before sending SIGKILL should be at most - * NM_SHUTDOWN_TIMEOUT_MS. + * NM_SHUTDOWN_TIMEOUT_MAX_MSEC. */ -#define NM_SHUTDOWN_TIMEOUT_MS 1500 -#define NM_SHUTDOWN_TIMEOUT_MS_WATCHDOG 500 +#define NM_SHUTDOWN_TIMEOUT_MAX_MSEC 5000 +#define NM_SHUTDOWN_TIMEOUT_ADDITIONAL_MSEC 500 + +/** + * NM_SHUTDOWN_TIMEOUT_1500_MSEC: this is just 1500 msec. The special + * thing about the define is that you are guaranteed that this is not + * longer than NM_SHUTDOWN_TIMEOUT_MAX_MSEC. + * When you perform an async operation, it must either be cancellable + * (and complete fast) or never take longer than NM_SHUTDOWN_TIMEOUT_MAX_MSEC. + * The usage of this macro makes that relation to NM_SHUTDOWN_TIMEOUT_MAX_MSEC + * explicit. + */ +#define NM_SHUTDOWN_TIMEOUT_1500_MSEC 1500 + +/* See NM_SHUTDOWN_TIMEOUT_1500_MSEC. */ +#define NM_SHUTDOWN_TIMEOUT_5000_MSEC 5000 typedef enum { /* There is no watched_obj argument, and the shutdown is delayed until the user @@ -131,7 +145,7 @@ typedef enum { NM_SHUTDOWN_WAIT_TYPE_OBJECT, /* The watched_obj argument is a GCancellable, and shutdown is delayed until the object - * gets destroyed (or unregistered). Note that after NM_SHUTDOWN_TIMEOUT_MS, the + * gets destroyed (or unregistered). Note that after NM_SHUTDOWN_TIMEOUT_MAX_MSEC, the * cancellable will be cancelled to notify listeners about the shutdown. */ NM_SHUTDOWN_WAIT_TYPE_CANCELLABLE, } NMShutdownWaitType; diff --git a/src/core/devices/bluetooth/nm-bluez-manager.c b/src/core/devices/bluetooth/nm-bluez-manager.c index 05f85297..6bc00faf 100644 --- a/src/core/devices/bluetooth/nm-bluez-manager.c +++ b/src/core/devices/bluetooth/nm-bluez-manager.c @@ -1352,6 +1352,7 @@ _conn_create_panu_connection(NMBluezManager *self, BzDBusObj *bzobj) bzobj->d_device.address); nm_settings_add_connection(priv->settings, + NULL, connection, NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY, NM_SETTINGS_CONNECTION_ADD_REASON_NONE, diff --git a/src/core/devices/nm-device-bond.c b/src/core/devices/nm-device-bond.c index 56b729e9..16896d57 100644 --- a/src/core/devices/nm-device-bond.c +++ b/src/core/devices/nm-device-bond.c @@ -37,17 +37,17 @@ NM_SETTING_BOND_OPTION_USE_CARRIER, NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY, \ NM_SETTING_BOND_OPTION_NUM_GRAT_ARP, NM_SETTING_BOND_OPTION_PEER_NOTIF_DELAY -#define OPTIONS_REAPPLY_SUBSET \ - NM_SETTING_BOND_OPTION_MIIMON, NM_SETTING_BOND_OPTION_UPDELAY, \ - NM_SETTING_BOND_OPTION_DOWNDELAY, NM_SETTING_BOND_OPTION_ARP_INTERVAL, \ - NM_SETTING_BOND_OPTION_ARP_VALIDATE, NM_SETTING_BOND_OPTION_PRIMARY, \ - NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM, NM_SETTING_BOND_OPTION_AD_ACTOR_SYS_PRIO, \ - NM_SETTING_BOND_OPTION_ALL_SLAVES_ACTIVE, NM_SETTING_BOND_OPTION_ARP_ALL_TARGETS, \ - NM_SETTING_BOND_OPTION_FAIL_OVER_MAC, NM_SETTING_BOND_OPTION_LP_INTERVAL, \ - NM_SETTING_BOND_OPTION_MIN_LINKS, NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE, \ - NM_SETTING_BOND_OPTION_PRIMARY_RESELECT, NM_SETTING_BOND_OPTION_RESEND_IGMP, \ - NM_SETTING_BOND_OPTION_USE_CARRIER, NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY, \ - NM_SETTING_BOND_OPTION_NUM_GRAT_ARP, NM_SETTING_BOND_OPTION_PEER_NOTIF_DELAY +#define OPTIONS_REAPPLY_SUBSET \ + NM_SETTING_BOND_OPTION_MIIMON, NM_SETTING_BOND_OPTION_UPDELAY, \ + NM_SETTING_BOND_OPTION_DOWNDELAY, NM_SETTING_BOND_OPTION_ARP_INTERVAL, \ + NM_SETTING_BOND_OPTION_ARP_VALIDATE, NM_SETTING_BOND_OPTION_PRIMARY, \ + NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM, NM_SETTING_BOND_OPTION_AD_ACTOR_SYS_PRIO, \ + NM_SETTING_BOND_OPTION_ALL_SLAVES_ACTIVE, NM_SETTING_BOND_OPTION_ARP_ALL_TARGETS, \ + NM_SETTING_BOND_OPTION_LP_INTERVAL, NM_SETTING_BOND_OPTION_MIN_LINKS, \ + NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE, NM_SETTING_BOND_OPTION_PRIMARY_RESELECT, \ + NM_SETTING_BOND_OPTION_RESEND_IGMP, NM_SETTING_BOND_OPTION_USE_CARRIER, \ + NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY, NM_SETTING_BOND_OPTION_NUM_GRAT_ARP, \ + NM_SETTING_BOND_OPTION_PEER_NOTIF_DELAY #define OPTIONS_REAPPLY_FULL \ OPTIONS_REAPPLY_SUBSET, NM_SETTING_BOND_OPTION_ACTIVE_SLAVE, \ @@ -373,7 +373,7 @@ apply_bonding_config(NMDeviceBond *self) NM_SETTING_BOND_OPTION_MODE); /* Need to release all slaves before we can change bond mode */ if (!nm_streq0(device_bond_mode, mode_str)) - nm_device_master_release_slaves(device); + nm_device_master_release_slaves_all(device); set_bond_attr_or_default(device, s_bond, NM_SETTING_BOND_OPTION_MODE); diff --git a/src/core/devices/nm-device-bridge.c b/src/core/devices/nm-device-bridge.c index 4e4c2637..f11c172a 100644 --- a/src/core/devices/nm-device-bridge.c +++ b/src/core/devices/nm-device-bridge.c @@ -22,11 +22,17 @@ /*****************************************************************************/ +enum _NMBtCbState { + _NM_BT_CB_STATE_NONE = 0, /* Registration not done */ + _NM_BT_CB_STATE_WAIT = 1, /* Waiting for the callback */ + _NM_BT_CB_STATE_SUCCESS = 2, /* Callback succeeded */ +}; + struct _NMDeviceBridge { NMDevice parent; GCancellable *bt_cancellable; bool vlan_configured : 1; - bool bt_registered : 1; + unsigned bt_cb_state : 2; }; struct _NMDeviceBridgeClass { @@ -76,7 +82,8 @@ check_connection_available(NMDevice *device, if (!nm_bt_vtable_network_server->is_available( nm_bt_vtable_network_server, bdaddr, - (self->bt_cancellable || self->bt_registered) ? device : NULL)) { + (self->bt_cancellable || self->bt_cb_state != _NM_BT_CB_STATE_NONE) ? device + : NULL)) { if (bdaddr) nm_utils_error_set(error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, @@ -791,23 +798,68 @@ bridge_set_vlan_options(NMDevice *device, NMSettingBridge *s_bridge) return TRUE; } +static void +_platform_lnk_bridge_init_from_setting(NMSettingBridge *s_bridge, NMPlatformLnkBridge *props) +{ + *props = (NMPlatformLnkBridge){ + .forward_delay = _DEFAULT_IF_ZERO(nm_setting_bridge_get_forward_delay(s_bridge) * 100u, + NM_BRIDGE_FORWARD_DELAY_DEF_SYS), + .hello_time = _DEFAULT_IF_ZERO(nm_setting_bridge_get_hello_time(s_bridge) * 100u, + NM_BRIDGE_HELLO_TIME_DEF_SYS), + .max_age = _DEFAULT_IF_ZERO(nm_setting_bridge_get_max_age(s_bridge) * 100u, + NM_BRIDGE_MAX_AGE_DEF_SYS), + .ageing_time = nm_setting_bridge_get_ageing_time(s_bridge) * 100u, + .stp_state = nm_setting_bridge_get_stp(s_bridge), + .priority = nm_setting_bridge_get_priority(s_bridge), + .vlan_protocol = to_sysfs_vlan_protocol_sys(nm_setting_bridge_get_vlan_protocol(s_bridge)), + .vlan_stats_enabled = nm_setting_bridge_get_vlan_stats_enabled(s_bridge), + .group_fwd_mask = nm_setting_bridge_get_group_forward_mask(s_bridge), + .mcast_snooping = nm_setting_bridge_get_multicast_snooping(s_bridge), + .mcast_router = + to_sysfs_multicast_router_sys(nm_setting_bridge_get_multicast_router(s_bridge)), + .mcast_query_use_ifaddr = nm_setting_bridge_get_multicast_query_use_ifaddr(s_bridge), + .mcast_querier = nm_setting_bridge_get_multicast_querier(s_bridge), + .mcast_hash_max = nm_setting_bridge_get_multicast_hash_max(s_bridge), + .mcast_last_member_count = nm_setting_bridge_get_multicast_last_member_count(s_bridge), + .mcast_startup_query_count = nm_setting_bridge_get_multicast_startup_query_count(s_bridge), + .mcast_last_member_interval = + nm_setting_bridge_get_multicast_last_member_interval(s_bridge), + .mcast_membership_interval = nm_setting_bridge_get_multicast_membership_interval(s_bridge), + .mcast_querier_interval = nm_setting_bridge_get_multicast_querier_interval(s_bridge), + .mcast_query_interval = nm_setting_bridge_get_multicast_query_interval(s_bridge), + .mcast_query_response_interval = + nm_setting_bridge_get_multicast_query_response_interval(s_bridge), + .mcast_startup_query_interval = + nm_setting_bridge_get_multicast_startup_query_interval(s_bridge), + }; + + to_sysfs_group_address_sys(nm_setting_bridge_get_group_address(s_bridge), &props->group_addr); +} + static NMActStageReturn act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) { - NMConnection *connection; - NMSetting *s_bridge; - const Option *option; + NMConnection *connection; + NMSettingBridge *s_bridge; + NMPlatformLnkBridge props; + int r; + int ifindex = nm_device_get_ifindex(device); connection = nm_device_get_applied_connection(device); g_return_val_if_fail(connection, NM_ACT_STAGE_RETURN_FAILURE); - s_bridge = (NMSetting *) nm_connection_get_setting_bridge(connection); + s_bridge = nm_connection_get_setting_bridge(connection); g_return_val_if_fail(s_bridge, NM_ACT_STAGE_RETURN_FAILURE); - for (option = master_options; option->name; option++) - commit_option(device, s_bridge, option, FALSE); + _platform_lnk_bridge_init_from_setting(s_bridge, &props); + + r = nm_platform_link_bridge_change(nm_device_get_platform(device), ifindex, &props); + if (r < 0) { + NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_CONFIG_FAILED); + return NM_ACT_STAGE_RETURN_FAILURE; + } - if (!bridge_set_vlan_options(device, (NMSettingBridge *) s_bridge)) { + if (!bridge_set_vlan_options(device, s_bridge)) { NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_CONFIG_FAILED); return NM_ACT_STAGE_RETURN_FAILURE; } @@ -835,6 +887,7 @@ _bt_register_bridge_cb(GError *error, gpointer user_data) return; } + self->bt_cb_state = _NM_BT_CB_STATE_SUCCESS; nm_device_activate_schedule_stage2_device_config(NM_DEVICE(self), FALSE); } @@ -846,12 +899,12 @@ _nm_device_bridge_notify_unregister_bt_nap(NMDevice *device, const char *reason) _LOGD(LOGD_DEVICE, "bluetooth NAP server unregistered from bridge: %s%s", reason, - self->bt_registered ? "" : " (was no longer registered)"); + self->bt_cb_state != _NM_BT_CB_STATE_NONE ? "" : " (was no longer registered)"); nm_clear_g_cancellable(&self->bt_cancellable); - if (self->bt_registered) { - self->bt_registered = FALSE; + if (self->bt_cb_state != _NM_BT_CB_STATE_NONE) { + self->bt_cb_state = _NM_BT_CB_STATE_NONE; nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_BT_FAILED); } } @@ -879,9 +932,12 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) if (self->bt_cancellable) return NM_ACT_STAGE_RETURN_POSTPONE; - if (self->bt_registered) + if (self->bt_cb_state == _NM_BT_CB_STATE_WAIT) return NM_ACT_STAGE_RETURN_POSTPONE; + if (self->bt_cb_state == _NM_BT_CB_STATE_SUCCESS) + return NM_ACT_STAGE_RETURN_SUCCESS; + self->bt_cancellable = g_cancellable_new(); if (!nm_bt_vtable_network_server->register_bridge(nm_bt_vtable_network_server, nm_setting_bluetooth_get_bdaddr(s_bt), @@ -895,7 +951,7 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) return NM_ACT_STAGE_RETURN_FAILURE; } - self->bt_registered = TRUE; + self->bt_cb_state = _NM_BT_CB_STATE_WAIT; return NM_ACT_STAGE_RETURN_POSTPONE; } @@ -906,14 +962,14 @@ deactivate(NMDevice *device) _LOGD(LOGD_DEVICE, "deactivate bridge%s", - self->bt_registered ? " (registered as NAP bluetooth device)" : ""); + self->bt_cb_state != _NM_BT_CB_STATE_NONE ? " (registered as NAP bluetooth device)" : ""); self->vlan_configured = FALSE; nm_clear_g_cancellable(&self->bt_cancellable); - if (self->bt_registered) { - self->bt_registered = FALSE; + if (self->bt_cb_state != _NM_BT_CB_STATE_NONE) { + self->bt_cb_state = _NM_BT_CB_STATE_NONE; nm_bt_vtable_network_server->unregister_bridge(nm_bt_vtable_network_server, device); } } @@ -1054,39 +1110,7 @@ create_and_realize(NMDevice *device, } } - props = (NMPlatformLnkBridge){ - .forward_delay = _DEFAULT_IF_ZERO(nm_setting_bridge_get_forward_delay(s_bridge) * 100u, - NM_BRIDGE_FORWARD_DELAY_DEF_SYS), - .hello_time = _DEFAULT_IF_ZERO(nm_setting_bridge_get_hello_time(s_bridge) * 100u, - NM_BRIDGE_HELLO_TIME_DEF_SYS), - .max_age = _DEFAULT_IF_ZERO(nm_setting_bridge_get_max_age(s_bridge) * 100u, - NM_BRIDGE_MAX_AGE_DEF_SYS), - .ageing_time = nm_setting_bridge_get_ageing_time(s_bridge) * 100u, - .stp_state = nm_setting_bridge_get_stp(s_bridge), - .priority = nm_setting_bridge_get_priority(s_bridge), - .vlan_protocol = to_sysfs_vlan_protocol_sys(nm_setting_bridge_get_vlan_protocol(s_bridge)), - .vlan_stats_enabled = nm_setting_bridge_get_vlan_stats_enabled(s_bridge), - .group_fwd_mask = nm_setting_bridge_get_group_forward_mask(s_bridge), - .mcast_snooping = nm_setting_bridge_get_multicast_snooping(s_bridge), - .mcast_router = - to_sysfs_multicast_router_sys(nm_setting_bridge_get_multicast_router(s_bridge)), - .mcast_query_use_ifaddr = nm_setting_bridge_get_multicast_query_use_ifaddr(s_bridge), - .mcast_querier = nm_setting_bridge_get_multicast_querier(s_bridge), - .mcast_hash_max = nm_setting_bridge_get_multicast_hash_max(s_bridge), - .mcast_last_member_count = nm_setting_bridge_get_multicast_last_member_count(s_bridge), - .mcast_startup_query_count = nm_setting_bridge_get_multicast_startup_query_count(s_bridge), - .mcast_last_member_interval = - nm_setting_bridge_get_multicast_last_member_interval(s_bridge), - .mcast_membership_interval = nm_setting_bridge_get_multicast_membership_interval(s_bridge), - .mcast_querier_interval = nm_setting_bridge_get_multicast_querier_interval(s_bridge), - .mcast_query_interval = nm_setting_bridge_get_multicast_query_interval(s_bridge), - .mcast_query_response_interval = - nm_setting_bridge_get_multicast_query_response_interval(s_bridge), - .mcast_startup_query_interval = - nm_setting_bridge_get_multicast_startup_query_interval(s_bridge), - }; - - to_sysfs_group_address_sys(nm_setting_bridge_get_group_address(s_bridge), &props.group_addr); + _platform_lnk_bridge_init_from_setting(s_bridge, &props); /* If mtu != 0, we set the MTU of the new bridge at creation time. However, kernel will still * automatically adjust the MTU of the bridge based on the minimum of the slave's MTU. diff --git a/src/core/devices/nm-device-ethernet.c b/src/core/devices/nm-device-ethernet.c index 407f8ab8..32f2fbf9 100644 --- a/src/core/devices/nm-device-ethernet.c +++ b/src/core/devices/nm-device-ethernet.c @@ -1014,7 +1014,7 @@ act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) * get confused and fail to negotiate the new connection. (rh #1023503) * * FIXME(shutdown): when exiting, we also need to wait before quitting, - * at least for additional NM_SHUTDOWN_TIMEOUT_MS seconds because + * at least for additional NM_SHUTDOWN_TIMEOUT_MAX_MSEC seconds because * otherwise after restart the device won't work for the first seconds. */ if (priv->ppp_data.last_pppoe_time_msec != 0) { diff --git a/src/core/devices/nm-device-private.h b/src/core/devices/nm-device-private.h index 790bb823..b54aed6a 100644 --- a/src/core/devices/nm-device-private.h +++ b/src/core/devices/nm-device-private.h @@ -61,7 +61,7 @@ void nm_device_recheck_available_connections(NMDevice *device); void nm_device_master_check_slave_physical_port(NMDevice *self, NMDevice *slave, NMLogDomain log_domain); -void nm_device_master_release_slaves(NMDevice *self); +void nm_device_master_release_slaves_all(NMDevice *self); void nm_device_set_carrier(NMDevice *self, gboolean carrier); diff --git a/src/core/devices/nm-device-tun.c b/src/core/devices/nm-device-tun.c index b6c4f88b..e623e9c0 100644 --- a/src/core/devices/nm-device-tun.c +++ b/src/core/devices/nm-device-tun.c @@ -542,6 +542,12 @@ create_device(NMDeviceFactory *factory, NM_SETTING_TUN_SETTING_NAME), NULL); + /* OpenvSwitch will create a tun device named ovs-netdev when the datapath selected is netdev */ + if (nm_streq0(iface, "ovs-netdev")) { + *out_ignore = TRUE; + return NULL; + } + return g_object_new(NM_TYPE_DEVICE_TUN, NM_DEVICE_IFACE, iface, diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index a11486d5..1d9f235a 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -101,6 +101,12 @@ typedef void (*ActivationHandleFunc)(NMDevice *self); typedef enum { + RELEASE_SLAVE_TYPE_NO_CONFIG, + RELEASE_SLAVE_TYPE_CONFIG, + RELEASE_SLAVE_TYPE_CONFIG_FORCE, +} ReleaseSlaveType; + +typedef enum { CLEANUP_TYPE_KEEP, CLEANUP_TYPE_REMOVED, CLEANUP_TYPE_DECONFIGURE, @@ -362,7 +368,6 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMDevice, PROP_FIRMWARE_MISSING, PROP_NM_PLUGIN_MISSING, PROP_TYPE_DESC, - PROP_RFKILL_TYPE, PROP_IFINDEX, PROP_AVAILABLE_CONNECTIONS, PROP_PHYSICAL_PORT_ID, @@ -474,7 +479,6 @@ typedef struct _NMDevicePrivate { char *driver; char *driver_version; char *firmware_version; - RfKillType rfkill_type; bool firmware_missing : 1; bool nm_plugin_missing : 1; bool @@ -1135,7 +1139,7 @@ _prop_get_ipv6_dhcp_duid(NMDevice *self, duid_out = nm_utils_generate_duid_llt(arp_type, hwaddr_bin, hwaddr_len, - nm_utils_host_id_get_timestamp_ns() + nm_utils_host_id_get_timestamp_nsec() / NM_UTILS_NSEC_PER_SEC); } @@ -1236,7 +1240,7 @@ _prop_get_ipv6_dhcp_duid(NMDevice *self, * before. Let's compute the time (in seconds) from 0 to 3 years; then we'll * subtract it from the host_id timestamp. */ - time = nm_utils_host_id_get_timestamp_ns() / NM_UTILS_NSEC_PER_SEC; + time = nm_utils_host_id_get_timestamp_nsec() / NM_UTILS_NSEC_PER_SEC; /* don't use too old timestamps. They cannot be expressed in DUID-LLT and * would all be truncated to zero. */ @@ -3855,6 +3859,7 @@ update_external_connection(NMDevice *self) if (connection_new) { nm_settings_connection_update(settings_connection, + NULL, connection_new, NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY, NM_SETTINGS_CONNECTION_INT_FLAGS_NONE, @@ -3893,12 +3898,15 @@ _dev_l3_cfg_notify_cb(NML3Cfg *l3cfg, const NML3ConfigNotifyData *notify_data, N case NM_L3_CONFIG_NOTIFY_TYPE_PRE_COMMIT: { const NML3ConfigData *l3cd; + NMDeviceState state = nm_device_get_state(self); - /* FIXME(l3cfg): MTU handling should be moved to l3cfg. */ - l3cd = nm_l3cfg_get_combined_l3cd(l3cfg, TRUE); - if (l3cd) - priv->ip6_mtu = nm_l3_config_data_get_ip6_mtu(l3cd); - _commit_mtu(self); + if (state >= NM_DEVICE_STATE_IP_CONFIG && state < NM_DEVICE_STATE_DEACTIVATING) { + /* FIXME(l3cfg): MTU handling should be moved to l3cfg. */ + l3cd = nm_l3cfg_get_combined_l3cd(l3cfg, TRUE); + if (l3cd) + priv->ip6_mtu = nm_l3_config_data_get_ip6_mtu(l3cd); + _commit_mtu(self); + } return; } case NM_L3_CONFIG_NOTIFY_TYPE_POST_COMMIT: @@ -3976,7 +3984,9 @@ _dev_l3_cfg_commit_type_reset(NMDevice *self) commit_type = NM_L3_CFG_COMMIT_TYPE_NONE; goto do_set; case NM_DEVICE_SYS_IFACE_STATE_ASSUME: - commit_type = NM_L3_CFG_COMMIT_TYPE_ASSUME; + /* TODO: NM_DEVICE_SYS_IFACE_STATE_ASSUME, will be dropped from the code. + * Meanwhile, the commit type must be updated. */ + commit_type = NM_L3_CFG_COMMIT_TYPE_UPDATE; goto do_set; case NM_DEVICE_SYS_IFACE_STATE_MANAGED: commit_type = NM_L3_CFG_COMMIT_TYPE_UPDATE; @@ -4455,9 +4465,9 @@ _parent_set_ifindex(NMDevice *self, int parent_ifindex, gboolean force_check) _LOGD(LOGD_DEVICE, "parent: ifindex %d, no device", priv->parent_ifindex); else { _LOGD(LOGD_DEVICE, - "parent: ifindex %d, device %p, %s", + "parent: ifindex %d, device " NM_HASH_OBFUSCATE_PTR_FMT ", %s", priv->parent_ifindex, - priv->parent_device.obj, + NM_HASH_OBFUSCATE_PTR(priv->parent_device.obj), nm_device_get_iface(priv->parent_device.obj)); } @@ -4719,7 +4729,7 @@ nm_device_get_ip_iface_identifier(NMDevice *self, gboolean *out_is_token) { NMSettingIP6Config *s_ip6; - const char *token = NULL; + const char *token; g_return_val_if_fail(NM_IS_DEVICE(self), FALSE); @@ -4731,13 +4741,12 @@ nm_device_get_ip_iface_identifier(NMDevice *self, g_return_val_if_fail(s_ip6, FALSE); token = nm_setting_ip6_config_get_token(s_ip6); - if (token) + if (token) { NM_SET_OUT(out_is_token, TRUE); + return nm_utils_ipv6_interface_identifier_get_from_token(iid, token); + } } - if (token) - return nm_utils_ipv6_interface_identifier_get_from_token(iid, token); - else - return NM_DEVICE_GET_CLASS(self)->get_ip_iface_identifier(self, iid); + return NM_DEVICE_GET_CLASS(self)->get_ip_iface_identifier(self, iid); } const char * @@ -5162,12 +5171,17 @@ nm_device_get_applied_setting(NMDevice *self, GType setting_type) return connection ? nm_connection_get_setting(connection, setting_type) : NULL; } -RfKillType +NMRfkillType nm_device_get_rfkill_type(NMDevice *self) { + NMRfkillType t; + g_return_val_if_fail(NM_IS_DEVICE(self), FALSE); - return NM_DEVICE_GET_PRIVATE(self)->rfkill_type; + t = NM_DEVICE_GET_CLASS(self)->rfkill_type; + + nm_assert(NM_IN_SET(t, NM_RFKILL_TYPE_UNKNOWN, NM_RFKILL_TYPE_WLAN, NM_RFKILL_TYPE_WWAN)); + return t; } static const char * @@ -5875,11 +5889,9 @@ static SlaveInfo * find_slave_info(NMDevice *self, NMDevice *slave) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - CList *iter; SlaveInfo *info; - c_list_for_each (iter, &priv->slaves) { - info = c_list_entry(iter, SlaveInfo, lst_slave); + c_list_for_each_entry (info, &priv->slaves, lst_slave) { if (info->slave == slave) return info; } @@ -5947,12 +5959,12 @@ nm_device_master_enslave_slave(NMDevice *self, NMDevice *slave, NMConnection *co } /** - * nm_device_master_release_one_slave: + * nm_device_master_release_slave: * @self: the master device * @slave: the slave device to release * @configure: whether @self needs to actually release @slave - * @force: force the release of @slave even if it wasn't added - * to @master by NetworkManager + * @release_type: whether @self needs to actually release slave + * and whether that is forced. * @reason: the state change reason for the @slave * * If @self is capable of enslaving other devices (ie it's a bridge, bond, team, @@ -5960,11 +5972,10 @@ nm_device_master_enslave_slave(NMDevice *self, NMDevice *slave, NMConnection *co * updates the state of @self and @slave to reflect its release. */ static void -nm_device_master_release_one_slave(NMDevice *self, - NMDevice *slave, - gboolean configure, - gboolean force, - NMDeviceStateReason reason) +nm_device_master_release_slave(NMDevice *self, + NMDevice *slave, + ReleaseSlaveType release_type, + NMDeviceStateReason reason) { NMDevicePrivate *priv; NMDevicePrivate *slave_priv; @@ -5973,17 +5984,22 @@ nm_device_master_release_one_slave(NMDevice *self, g_return_if_fail(NM_DEVICE(self)); g_return_if_fail(NM_DEVICE(slave)); - g_return_if_fail(!force || configure); + nm_assert(NM_IN_SET(release_type, + RELEASE_SLAVE_TYPE_NO_CONFIG, + RELEASE_SLAVE_TYPE_CONFIG, + RELEASE_SLAVE_TYPE_CONFIG_FORCE)); g_return_if_fail(NM_DEVICE_GET_CLASS(self)->release_slave != NULL); info = find_slave_info(self, slave); _LOGT(LOGD_CORE, - "master: release one slave %p/%s %s%s", - slave, + "master: release one slave " NM_HASH_OBFUSCATE_PTR_FMT "/%s %s%s", + NM_HASH_OBFUSCATE_PTR(slave), nm_device_get_iface(slave), !info ? "(not registered)" : (info->slave_is_enslaved ? "(enslaved)" : "(not enslaved)"), - force ? " (force-configure)" : (configure ? " (configure)" : "")); + release_type == RELEASE_SLAVE_TYPE_CONFIG_FORCE + ? " (force-configure)" + : (release_type == RELEASE_SLAVE_TYPE_CONFIG ? " (configure)" : "(no-config)")); if (!info) g_return_if_reached(); @@ -5995,8 +6011,11 @@ nm_device_master_release_one_slave(NMDevice *self, nm_assert(slave == info->slave); /* first, let subclasses handle the release ... */ - if (info->slave_is_enslaved || nm_device_sys_iface_state_is_external(slave) || force) - NM_DEVICE_GET_CLASS(self)->release_slave(self, slave, configure); + if (info->slave_is_enslaved || nm_device_sys_iface_state_is_external(slave) + || release_type >= RELEASE_SLAVE_TYPE_CONFIG_FORCE) + NM_DEVICE_GET_CLASS(self)->release_slave(self, + slave, + release_type >= RELEASE_SLAVE_TYPE_CONFIG); /* raise notifications about the release, including clearing is_enslaved. */ nm_device_slave_notify_release(slave, reason); @@ -6314,7 +6333,8 @@ device_recheck_slave_status(NMDevice *self, const NMPlatformLink *plink) plink_master = nm_platform_link_get(nm_device_get_platform(self), plink->master); plink_master_keep_alive = nmp_object_ref(NMP_OBJECT_UP_CAST(plink_master)); - if (master == NULL && plink_master && nm_streq0(plink_master->name, "ovs-system") + if (master == NULL && plink_master + && NM_IN_STRSET(plink_master->name, "ovs-system", "ovs-netdev") && plink_master->type == NM_LINK_TYPE_OPENVSWITCH) { _LOGD(LOGD_DEVICE, "the device claimed by openvswitch"); goto out; @@ -6330,11 +6350,10 @@ device_recheck_slave_status(NMDevice *self, const NMPlatformLink *plink) goto out; } - nm_device_master_release_one_slave(priv->master, - self, - FALSE, - FALSE, - NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); + nm_device_master_release_slave(priv->master, + self, + RELEASE_SLAVE_TYPE_NO_CONFIG, + NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); } if (master && NM_DEVICE_GET_CLASS(master)->enslave_slave) { @@ -6638,7 +6657,7 @@ static void link_changed_cb(NMPlatform *platform, int obj_type_i, int ifindex, - NMPlatformLink *info, + NMPlatformLink *pllink, int change_type_i, NMDevice *self) { @@ -6651,7 +6670,7 @@ link_changed_cb(NMPlatform *platform, priv = NM_DEVICE_GET_PRIVATE(self); if (ifindex == nm_device_get_ifindex(self)) { - if (!(info->n_ifi_flags & IFF_UP)) + if (!(pllink->n_ifi_flags & IFF_UP)) priv->device_link_changed_down = TRUE; if (!priv->device_link_changed_id) { priv->device_link_changed_id = g_idle_add(device_link_changed, self); @@ -7004,7 +7023,7 @@ sriov_op_queue(NMDevice *self, * * FIXME(shutdown): However, during shutdown we don't have a follow-up write request to cancel * this operation and we have to give it at least some time to complete. The solution is that - * we register a way to abort the last call during shutdown, and after NM_SHUTDOWN_TIMEOUT_MS + * we register a way to abort the last call during shutdown, and after NM_SHUTDOWN_TIMEOUT_MAX_MSEC * grace period we pull the plug and cancel it. */ op = g_slice_new(SriovOp); @@ -7527,7 +7546,11 @@ slave_state_changed(NMDevice *slave, configure = priv->sys_iface_state == NM_DEVICE_SYS_IFACE_STATE_MANAGED && nm_device_sys_iface_state_get(slave) != NM_DEVICE_SYS_IFACE_STATE_EXTERNAL; - nm_device_master_release_one_slave(self, slave, configure, FALSE, reason); + nm_device_master_release_slave(self, + slave, + configure ? RELEASE_SLAVE_TYPE_CONFIG + : RELEASE_SLAVE_TYPE_NO_CONFIG, + reason); /* Bridge/bond/team interfaces are left up until manually deactivated */ if (c_list_is_empty(&priv->slaves) && priv->state == NM_DEVICE_STATE_ACTIVATED) _LOGD(LOGD_DEVICE, "last slave removed; remaining activated"); @@ -7565,8 +7588,8 @@ nm_device_master_add_slave(NMDevice *self, NMDevice *slave, gboolean configure) info = find_slave_info(self, slave); _LOGT(LOGD_CORE, - "master: add one slave %p/%s%s", - slave, + "master: add one slave " NM_HASH_OBFUSCATE_PTR_FMT "/%s%s", + NM_HASH_OBFUSCATE_PTR(slave), nm_device_get_iface(slave), info ? " (already registered)" : ""); @@ -7624,14 +7647,12 @@ nm_device_master_check_slave_physical_port(NMDevice *self, NMDevice *slave, NMLo NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); const char *slave_physical_port_id, *existing_physical_port_id; SlaveInfo *info; - CList *iter; slave_physical_port_id = nm_device_get_physical_port_id(slave); if (!slave_physical_port_id) return; - c_list_for_each (iter, &priv->slaves) { - info = c_list_entry(iter, SlaveInfo, lst_slave); + c_list_for_each_entry (info, &priv->slaves, lst_slave) { if (info->slave == slave) continue; @@ -7651,13 +7672,13 @@ nm_device_master_check_slave_physical_port(NMDevice *self, NMDevice *slave, NMLo } } -/* release all slaves */ void -nm_device_master_release_slaves(NMDevice *self) +nm_device_master_release_slaves_all(NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); NMDeviceStateReason reason; - CList *iter, *safe; + SlaveInfo *info; + SlaveInfo *safe; /* Don't release the slaves if this connection doesn't belong to NM. */ if (nm_device_sys_iface_state_is_external(self)) @@ -7667,9 +7688,7 @@ nm_device_master_release_slaves(NMDevice *self) if (priv->state == NM_DEVICE_STATE_FAILED) reason = NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED; - c_list_for_each_safe (iter, safe, &priv->slaves) { - SlaveInfo *info = c_list_entry(iter, SlaveInfo, lst_slave); - + c_list_for_each_entry_safe (info, safe, &priv->slaves, lst_slave) { if (priv->activation_state_preserve_external_ports && nm_device_sys_iface_state_is_external(info->slave)) { _LOGT(LOGD_DEVICE, @@ -7677,7 +7696,7 @@ nm_device_master_release_slaves(NMDevice *self) nm_device_get_iface(info->slave)); continue; } - nm_device_master_release_one_slave(self, info->slave, TRUE, FALSE, reason); + nm_device_master_release_slave(self, info->slave, RELEASE_SLAVE_TYPE_CONFIG, reason); } /* We only need this flag for a short time. It served its purpose. Clear @@ -7852,11 +7871,10 @@ nm_device_removed(NMDevice *self, gboolean unconfigure_ip_config) if (priv->master) { /* this is called when something externally messes with the slave or during shut-down. * Release the slave from master, but don't touch the device. */ - nm_device_master_release_one_slave(priv->master, - self, - FALSE, - FALSE, - NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); + nm_device_master_release_slave(priv->master, + self, + RELEASE_SLAVE_TYPE_NO_CONFIG, + NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); } _dev_l3_register_l3cds(self, priv->l3cfg, FALSE, unconfigure_ip_config); @@ -8928,11 +8946,10 @@ master_ready(NMDevice *self, NMActiveConnection *active) _LOGD(LOGD_DEVICE, "master connection ready; master device %s", nm_device_get_iface(master)); if (priv->master && priv->master != master) - nm_device_master_release_one_slave(priv->master, - self, - FALSE, - FALSE, - NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); + nm_device_master_release_slave(priv->master, + self, + RELEASE_SLAVE_TYPE_NO_CONFIG, + NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); /* If the master didn't change, add-slave only rechecks whether to assume a connection. */ nm_device_master_add_slave(master, @@ -9214,11 +9231,10 @@ activate_stage1_device_prepare(NMDevice *self) if (master) master_ready(self, active); else if (priv->master) { - nm_device_master_release_one_slave(priv->master, - self, - TRUE, - TRUE, - NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); + nm_device_master_release_slave(priv->master, + self, + RELEASE_SLAVE_TYPE_CONFIG_FORCE, + NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); } nm_device_activate_schedule_stage2_device_config(self, TRUE); @@ -9434,7 +9450,7 @@ activate_stage2_device_config(NMDevice *self) NMActStageReturn ret; NMSettingWired *s_wired; gboolean no_firmware = FALSE; - CList *iter; + SlaveInfo *info; NMTernary accept_all_mac_addresses; nm_device_state_changed(self, NM_DEVICE_STATE_CONFIG, NM_DEVICE_STATE_REASON_NONE); @@ -9481,8 +9497,7 @@ activate_stage2_device_config(NMDevice *self) } /* If we have slaves that aren't yet enslaved, do that now */ - c_list_for_each (iter, &priv->slaves) { - SlaveInfo *info = c_list_entry(iter, SlaveInfo, lst_slave); + c_list_for_each_entry (info, &priv->slaves, lst_slave) { NMDeviceState slave_state = nm_device_get_state(info->slave); if (slave_state == NM_DEVICE_STATE_IP_CONFIG) @@ -9517,8 +9532,6 @@ activate_stage2_device_config(NMDevice *self) lldp_setup(self, NM_TERNARY_DEFAULT); - _commit_mtu(self); - nm_device_activate_schedule_stage3_ip_config(self, TRUE); } @@ -10410,14 +10423,12 @@ have_any_ready_slaves(NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); SlaveInfo *info; - CList *iter; /* Any enslaved slave is "ready" in the generic case as it's - * at least >= NM_DEVCIE_STATE_IP_CONFIG and has had Layer 2 + * at least >= NM_DEVICE_STATE_IP_CONFIG and has had Layer 2 * properties set up. */ - c_list_for_each (iter, &priv->slaves) { - info = c_list_entry(iter, SlaveInfo, lst_slave); + c_list_for_each_entry (info, &priv->slaves, lst_slave) { if (NM_DEVICE_GET_PRIVATE(info->slave)->is_enslaved) return TRUE; } @@ -10440,7 +10451,7 @@ void nm_device_use_ip6_subnet(NMDevice *self, const NMPlatformIP6Address *subnet) { nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL; - char sbuf[sizeof(_nm_utils_to_string_buffer)]; + char sbuf[NM_UTILS_TO_STRING_BUFFER_SIZE]; NMPlatformIP6Address address; l3cd = nm_device_create_l3_config_data(self, NM_IP_CONFIG_SOURCE_SHARED); @@ -11864,6 +11875,15 @@ activate_stage3_ip_config(NMDevice *self) nm_device_get_ip_iface(self)); } + /* We currently will attach ports in the state change NM_DEVICE_STATE_IP_CONFIG above. + * Note that kernel changes the MTU of bond ports, so we want to commit the MTU + * afterwards! + * + * This might reset the MTU to something different from the bond controller and + * it might not be a working configuration. But it's what the user asked for, so + * let's do it! */ + _commit_mtu(self); + ipv4_method = nm_device_get_effective_ip_config_method(self, AF_INET); if (nm_streq(ipv4_method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) { /* "auto" usually means DHCPv4 or autoconf6, but it doesn't have to be. Subclasses @@ -12455,6 +12475,7 @@ can_reapply_change(NMDevice *self, NM_SETTING_CONNECTION_UUID, NM_SETTING_CONNECTION_STABLE_ID, NM_SETTING_CONNECTION_AUTOCONNECT, + NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES, NM_SETTING_CONNECTION_ZONE, NM_SETTING_CONNECTION_METERED, NM_SETTING_CONNECTION_LLDP, @@ -15085,7 +15106,7 @@ nm_device_cleanup(NMDevice *self, NMDeviceStateReason reason, CleanupType cleanu if (cleanup_type == CLEANUP_TYPE_DECONFIGURE) { /* master: release slaves */ - nm_device_master_release_slaves(self); + nm_device_master_release_slaves_all(self); /* Take out any entries in the routing table and any IP address the device had. */ if (ifindex > 0) { @@ -15109,12 +15130,12 @@ nm_device_cleanup(NMDevice *self, NMDeviceStateReason reason, CleanupType cleanu /* slave: mark no longer enslaved */ if (priv->master && priv->ifindex > 0 - && nm_platform_link_get_master(nm_device_get_platform(self), priv->ifindex) <= 0) - nm_device_master_release_one_slave(priv->master, - self, - FALSE, - FALSE, - NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); + && nm_platform_link_get_master(nm_device_get_platform(self), priv->ifindex) <= 0) { + nm_device_master_release_slave(priv->master, + self, + RELEASE_SLAVE_TYPE_NO_CONFIG, + NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); + } lldp_setup(self, NM_TERNARY_FALSE); @@ -15614,7 +15635,7 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, sett_conn ? nm_settings_connection_get_id(sett_conn) : "<unknown>"); /* Notify any slaves of the unexpected failure */ - nm_device_master_release_slaves(self); + nm_device_master_release_slaves_all(self); /* If the connection doesn't yet have a timestamp, set it to zero so that * we can distinguish between connections we've tried to activate and have @@ -17070,9 +17091,6 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) case PROP_TYPE_DESC: g_value_set_string(value, priv->type_desc); break; - case PROP_RFKILL_TYPE: - g_value_set_uint(value, priv->rfkill_type); - break; case PROP_AVAILABLE_CONNECTIONS: nm_dbus_utils_g_value_set_object_path_from_hash(value, priv->available_connections, TRUE); break; @@ -17208,10 +17226,6 @@ set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *ps /* construct-only */ priv->type_desc = g_value_dup_string(value); break; - case PROP_RFKILL_TYPE: - /* construct-only */ - priv->rfkill_type = g_value_get_uint(value); - break; case PROP_PERM_HW_ADDRESS: /* construct-only */ priv->hw_addr_perm = g_value_dup_string(value); @@ -17261,7 +17275,6 @@ nm_device_init(NMDevice *self) priv->capabilities = NM_DEVICE_CAP_NM_SUPPORTED; priv->state = NM_DEVICE_STATE_UNMANAGED; priv->state_reason = NM_DEVICE_STATE_REASON_NONE; - priv->rfkill_type = RFKILL_TYPE_UNKNOWN; priv->unmanaged_flags = NM_UNMANAGED_PLATFORM_INIT; priv->unmanaged_mask = priv->unmanaged_flags; priv->available_connections = g_hash_table_new_full(nm_direct_hash, NULL, g_object_unref, NULL); @@ -17664,6 +17677,8 @@ nm_device_class_init(NMDeviceClass *klass) klass->reapply_connection = reapply_connection; klass->set_platform_mtu = set_platform_mtu; + klass->rfkill_type = NM_RFKILL_TYPE_UNKNOWN; + obj_properties[PROP_UDI] = g_param_spec_string(NM_DEVICE_UDI, "", @@ -17821,14 +17836,6 @@ nm_device_class_init(NMDeviceClass *klass) "", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - obj_properties[PROP_RFKILL_TYPE] = - g_param_spec_uint(NM_DEVICE_RFKILL_TYPE, - "", - "", - RFKILL_TYPE_WLAN, - RFKILL_TYPE_MAX, - RFKILL_TYPE_UNKNOWN, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); obj_properties[PROP_IFINDEX] = g_param_spec_int(NM_DEVICE_IFINDEX, "", "", diff --git a/src/core/devices/nm-device.h b/src/core/devices/nm-device.h index a7badb86..80def125 100644 --- a/src/core/devices/nm-device.h +++ b/src/core/devices/nm-device.h @@ -65,7 +65,6 @@ #define NM_DEVICE_SLAVES "slaves" /* partially internal */ #define NM_DEVICE_TYPE_DESC "type-desc" /* Internal only */ -#define NM_DEVICE_RFKILL_TYPE "rfkill-type" /* Internal only */ #define NM_DEVICE_IFINDEX "ifindex" /* Internal only */ #define NM_DEVICE_MASTER "master" /* Internal only */ #define NM_DEVICE_HAS_PENDING_ACTION "has-pending-action" /* Internal only */ @@ -105,38 +104,38 @@ typedef enum NMActStageReturn NMActStageReturn; * a condition, so that adding a flag might make a connection available that would * not be available otherwise. Adding a flag should never make a connection * not available if it would be available otherwise. */ -typedef enum { /*< skip >*/ - NM_DEVICE_CHECK_CON_AVAILABLE_NONE = 0, +typedef enum { + NM_DEVICE_CHECK_CON_AVAILABLE_NONE = 0, - /* since NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST is a collection of flags with more fine grained + /* since NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST is a collection of flags with more fine grained * parts, this flag in general indicates that this is a user-request. */ - _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST = (1L << 0), + _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST = (1L << 0), - /* we also consider devices which have no carrier but are still waiting for the driver + /* we also consider devices which have no carrier but are still waiting for the driver * to detect carrier. Usually, such devices are not yet available, however for a user-request * they are. They might fail later if carrier doesn't come. */ - _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER = (1L << 1), + _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER = (1L << 1), - /* usually, a profile is only available if the Wi-Fi AP is in range. For an + /* usually, a profile is only available if the Wi-Fi AP is in range. For an * explicit user request, we also consider profiles for APs that are not (yet) * visible. */ - _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_IGNORE_AP = (1L << 2), + _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_IGNORE_AP = (1L << 2), - /* a device can be marked as unmanaged for various reasons. Some of these reasons + /* a device can be marked as unmanaged for various reasons. Some of these reasons * are authoritative, others not. Non-authoritative reasons can be overruled by * `nmcli device set $DEVICE managed yes`. Also, for an explicit user activation * request we may want to consider the device as managed. This flag makes devices * that are unmanaged appear available. */ - _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_OVERRULE_UNMANAGED = (1L << 3), + _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_OVERRULE_UNMANAGED = (1L << 3), - /* a collection of flags, that are commonly set for an explicit user-request. */ - NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST = - _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST - | _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER - | _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_IGNORE_AP - | _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_OVERRULE_UNMANAGED, + /* a collection of flags, that are commonly set for an explicit user-request. */ + NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST = + _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST + | _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER + | _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_IGNORE_AP + | _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_OVERRULE_UNMANAGED, - NM_DEVICE_CHECK_CON_AVAILABLE_ALL = (1L << 4) - 1, + NM_DEVICE_CHECK_CON_AVAILABLE_ALL = (1L << 4) - 1, } NMDeviceCheckConAvailableFlags; struct _NMDevicePrivate; @@ -149,19 +148,18 @@ struct _NMDevice { /* The flags have an relaxing meaning, that means, specifying more flags, can make * a device appear more available. It can never make a device less available. */ -typedef enum { /*< skip >*/ - NM_DEVICE_CHECK_DEV_AVAILABLE_NONE = 0, +typedef enum { + NM_DEVICE_CHECK_DEV_AVAILABLE_NONE = 0, - /* the device is considered available, even if it has no carrier. + /* the device is considered available, even if it has no carrier. * * For various device types (software devices) we ignore carrier based * on the type. So, for them, this flag has no effect anyway. */ - _NM_DEVICE_CHECK_DEV_AVAILABLE_IGNORE_CARRIER = (1L << 0), + _NM_DEVICE_CHECK_DEV_AVAILABLE_IGNORE_CARRIER = (1L << 0), - NM_DEVICE_CHECK_DEV_AVAILABLE_FOR_USER_REQUEST = - _NM_DEVICE_CHECK_DEV_AVAILABLE_IGNORE_CARRIER, + NM_DEVICE_CHECK_DEV_AVAILABLE_FOR_USER_REQUEST = _NM_DEVICE_CHECK_DEV_AVAILABLE_IGNORE_CARRIER, - NM_DEVICE_CHECK_DEV_AVAILABLE_ALL = (1L << 1) - 1, + NM_DEVICE_CHECK_DEV_AVAILABLE_ALL = (1L << 1) - 1, } NMDeviceCheckDevAvailableFlags; typedef void (*NMDeviceDeactivateCallback)(NMDevice *self, GError *error, gpointer user_data); @@ -209,6 +207,8 @@ typedef struct _NMDeviceClass { bool can_reapply_change_ovs_external_ids : 1; + NMRfkillType rfkill_type : 4; + void (*state_changed)(NMDevice *device, NMDeviceState new_state, NMDeviceState old_state, @@ -410,7 +410,6 @@ typedef struct _NMDeviceClass { gboolean (*set_platform_mtu)(NMDevice *self, guint32 mtu); const char *(*get_dhcp_anycast_address)(NMDevice *self); - } NMDeviceClass; GType nm_device_get_type(void); @@ -538,7 +537,7 @@ gboolean nm_device_get_enabled(NMDevice *device); void nm_device_set_enabled(NMDevice *device, gboolean enabled); -RfKillType nm_device_get_rfkill_type(NMDevice *device); +NMRfkillType nm_device_get_rfkill_type(NMDevice *device); /* IPv6 prefix delegation */ diff --git a/src/core/devices/ovs/nm-device-ovs-interface.c b/src/core/devices/ovs/nm-device-ovs-interface.c index 74707d24..6b9d3d7e 100644 --- a/src/core/devices/ovs/nm-device-ovs-interface.c +++ b/src/core/devices/ovs/nm-device-ovs-interface.c @@ -13,6 +13,7 @@ #include "devices/nm-device-private.h" #include "nm-active-connection.h" #include "nm-setting-connection.h" +#include "nm-setting-ovs-bridge.h" #include "nm-setting-ovs-interface.h" #include "nm-setting-ovs-port.h" @@ -23,7 +24,10 @@ typedef struct { NMOvsdb *ovsdb; - bool waiting_for_interface : 1; + GSource *wait_link_idle_source; + gulong wait_link_signal_id; + int wait_link_ifindex; + bool wait_link_is_waiting : 1; } NMDeviceOvsInterfacePrivate; struct _NMDeviceOvsInterface { @@ -115,10 +119,10 @@ link_changed(NMDevice *device, const NMPlatformLink *pllink) { NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(device); - if (!pllink || !priv->waiting_for_interface) + if (!pllink || !priv->wait_link_is_waiting) return; - priv->waiting_for_interface = FALSE; + priv->wait_link_is_waiting = FALSE; if (nm_device_get_state(device) == NM_DEVICE_STATE_IP_CONFIG) { if (!nm_device_hw_addr_set_cloned(device, @@ -199,17 +203,83 @@ ready_for_ip_config(NMDevice *device) return nm_device_get_ip_ifindex(device) > 0; } +static gboolean +_set_ip_ifindex_tun(gpointer user_data) +{ + NMDevice *device = user_data; + NMDeviceOvsInterface *self = NM_DEVICE_OVS_INTERFACE(device); + NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self); + + nm_clear_g_source_inst(&priv->wait_link_idle_source); + + priv->wait_link_is_waiting = FALSE; + nm_device_set_ip_ifindex(device, priv->wait_link_ifindex); + + nm_device_devip_set_state(device, AF_INET, NM_DEVICE_IP_STATE_PENDING, NULL); + nm_device_devip_set_state(device, AF_INET6, NM_DEVICE_IP_STATE_PENDING, NULL); + nm_device_activate_schedule_stage3_ip_config(device, FALSE); + + return G_SOURCE_CONTINUE; +} + +static void +_netdev_tun_link_cb(NMPlatform *platform, + int obj_type_i, + int ifindex, + NMPlatformLink *pllink, + int change_type_i, + NMDevice *device) +{ + const NMPlatformSignalChangeType change_type = change_type_i; + NMDeviceOvsInterface *self = NM_DEVICE_OVS_INTERFACE(device); + NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self); + + if (change_type == NM_PLATFORM_SIGNAL_ADDED) { + if (pllink->type == NM_LINK_TYPE_TUN + && nm_streq0(pllink->name, nm_device_get_iface(device))) { + nm_clear_g_signal_handler(platform, &priv->wait_link_signal_id); + + priv->wait_link_ifindex = ifindex; + + priv->wait_link_idle_source = nm_g_idle_add_source(_set_ip_ifindex_tun, device); + } + } +} + static void act_stage3_ip_config(NMDevice *device, int addr_family) { - NMDeviceOvsInterface *self = NM_DEVICE_OVS_INTERFACE(device); - NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self); + NMActiveConnection *controller_act = NULL; + NMSettingOvsBridge *s_ovs_bridge = NULL; + NMDeviceOvsInterface *self = NM_DEVICE_OVS_INTERFACE(device); + NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self); if (!_is_internal_interface(device)) { nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, NULL); return; } + /* When the ovs-bridge controller is using netdev datapath, the interface + * link created is a tun device instead of a ovs-interface. NetworkManager must + * detect the creation of the tun link and attach the ifindex to the + * ovs-interface device. */ + controller_act = NM_ACTIVE_CONNECTION(nm_device_get_act_request(device)); + if (controller_act && nm_device_get_ip_ifindex(device) <= 0 && priv->wait_link_signal_id == 0) { + controller_act = nm_active_connection_get_master(controller_act); + if (controller_act) { + controller_act = nm_active_connection_get_master(controller_act); + if (controller_act) + s_ovs_bridge = nm_connection_get_setting_ovs_bridge( + nm_active_connection_get_applied_connection(controller_act)); + if (s_ovs_bridge + && nm_streq0(nm_setting_ovs_bridge_get_datapath_type(s_ovs_bridge), "netdev")) + priv->wait_link_signal_id = g_signal_connect(nm_device_get_platform(device), + NM_PLATFORM_SIGNAL_LINK_CHANGED, + G_CALLBACK(_netdev_tun_link_cb), + self); + } + } + /* FIXME(l3cfg): we should create the IP ifindex before stage3 start. * * For now it's here because when the ovs-interface enters stage3, then it's added to the @@ -219,11 +289,15 @@ act_stage3_ip_config(NMDevice *device, int addr_family) * This should change. */ if (nm_device_get_ip_ifindex(device) <= 0) { _LOGT(LOGD_DEVICE, "waiting for link to appear"); - priv->waiting_for_interface = TRUE; + priv->wait_link_is_waiting = TRUE; nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_PENDING, NULL); return; } + priv->wait_link_is_waiting = FALSE; + nm_clear_g_source_inst(&priv->wait_link_idle_source); + nm_clear_g_signal_handler(nm_device_get_platform(device), &priv->wait_link_signal_id); + if (!nm_device_hw_addr_set_cloned(device, nm_device_get_applied_connection(device), FALSE)) { nm_device_devip_set_failed(device, addr_family, NM_DEVICE_STATE_REASON_CONFIG_FAILED); return; @@ -244,7 +318,8 @@ deactivate(NMDevice *device) NMDeviceOvsInterface *self = NM_DEVICE_OVS_INTERFACE(device); NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self); - priv->waiting_for_interface = FALSE; + priv->wait_link_is_waiting = FALSE; + nm_clear_g_source_inst(&priv->wait_link_idle_source); } typedef struct { @@ -351,7 +426,7 @@ deactivate_async(NMDevice *device, .callback_user_data = callback_user_data, }; - if (!priv->waiting_for_interface + if (!priv->wait_link_is_waiting && !nm_platform_link_get_by_ifname(nm_device_get_platform(device), nm_device_get_iface(device))) { _LOGT(LOGD_CORE, "deactivate: link not present, proceeding"); @@ -360,7 +435,9 @@ deactivate_async(NMDevice *device, return; } - if (priv->waiting_for_interface) { + nm_clear_g_source_inst(&priv->wait_link_idle_source); + + if (priv->wait_link_is_waiting) { /* At this point we have issued an INSERT and a DELETE * command for the interface to ovsdb. We don't know if * vswitchd will see the two updates or only one. We diff --git a/src/core/devices/ovs/nm-ovsdb.c b/src/core/devices/ovs/nm-ovsdb.c index 7c45e0e4..44e16cb7 100644 --- a/src/core/devices/ovs/nm-ovsdb.c +++ b/src/core/devices/ovs/nm-ovsdb.c @@ -104,6 +104,7 @@ typedef struct { OvsdbMethodCallback callback; gpointer user_data; OvsdbMethodPayload payload; + GObject *shutdown_wait_obj; } OvsdbMethodCall; /*****************************************************************************/ @@ -245,6 +246,8 @@ static NM_UTILS_LOOKUP_STR_DEFINE(_device_type_to_table, static void _call_complete(OvsdbMethodCall *call, json_t *response, GError *error) { + g_clear_object(&call->shutdown_wait_obj); + if (response) { gs_free char *str = NULL; @@ -378,12 +381,14 @@ ovsdb_call_method(NMOvsdb *self, call = g_slice_new(OvsdbMethodCall); *call = (OvsdbMethodCall){ - .self = self, - .call_id = CALL_ID_UNSPEC, - .command = command, - .callback = callback, - .user_data = user_data, + .self = self, + .call_id = CALL_ID_UNSPEC, + .command = command, + .callback = callback, + .user_data = user_data, + .shutdown_wait_obj = g_object_new(G_TYPE_OBJECT, NULL), }; + nm_shutdown_wait_obj_register_object(call->shutdown_wait_obj, "ovsdb-call"); if (add_first) c_list_link_front(&priv->calls_lst_head, &call->calls_lst); @@ -2481,29 +2486,27 @@ typedef struct { static void _transact_cb(NMOvsdb *self, json_t *result, GError *error, gpointer user_data) { - OvsdbCall *call = user_data; - const char *err; - const char *err_details; - size_t index; - json_t *value; - - if (error) - goto out; - - json_array_foreach (result, index, value) { - if (json_unpack(value, "{s:s, s:s}", "error", &err, "details", &err_details) == 0) { - g_set_error(&error, - G_IO_ERROR, - G_IO_ERROR_FAILED, - "Error running the transaction: %s: %s", - err, - err_details); - goto out; + OvsdbCall *call = user_data; + gs_free_error GError *local = NULL; + const char *err; + const char *err_details; + size_t index; + json_t *value; + + if (!error) { + json_array_foreach (result, index, value) { + if (json_unpack(value, "{s:s, s:s}", "error", &err, "details", &err_details) == 0) { + local = g_error_new(G_IO_ERROR, + G_IO_ERROR_FAILED, + "Error running the transaction: %s: %s", + err, + err_details); + break; + } } } -out: - call->callback(error, call->user_data); + call->callback(local ?: error, call->user_data); nm_g_slice_free(call); } diff --git a/src/core/devices/wifi/nm-device-iwd-p2p.c b/src/core/devices/wifi/nm-device-iwd-p2p.c index 01774b12..40e38321 100644 --- a/src/core/devices/wifi/nm-device-iwd-p2p.c +++ b/src/core/devices/wifi/nm-device-iwd-p2p.c @@ -1196,8 +1196,6 @@ nm_device_iwd_p2p_new(GDBusObject *dbus_obj) NM_DEVICE_TYPE_WIFI_P2P, NM_DEVICE_LINK_TYPE, NM_LINK_TYPE_WIFI, - NM_DEVICE_RFKILL_TYPE, - RFKILL_TYPE_WLAN, NULL); if (!self || !nm_device_iwd_p2p_set_dbus_obj(self, dbus_obj)) @@ -1252,6 +1250,8 @@ nm_device_iwd_p2p_class_init(NMDeviceIwdP2PClass *klass) device_class->state_changed = device_state_changed; + device_class->rfkill_type = NM_RFKILL_TYPE_WLAN; + obj_properties[PROP_PEERS] = g_param_spec_boxed(NM_DEVICE_IWD_P2P_PEERS, "", "", diff --git a/src/core/devices/wifi/nm-device-iwd.c b/src/core/devices/wifi/nm-device-iwd.c index 7543d9da..ab37cbec 100644 --- a/src/core/devices/wifi/nm-device-iwd.c +++ b/src/core/devices/wifi/nm-device-iwd.c @@ -3426,8 +3426,6 @@ nm_device_iwd_new(const char *iface) NM_DEVICE_TYPE_WIFI, NM_DEVICE_LINK_TYPE, NM_LINK_TYPE_WIFI, - NM_DEVICE_RFKILL_TYPE, - RFKILL_TYPE_WLAN, NULL); } @@ -3490,6 +3488,8 @@ nm_device_iwd_class_init(NMDeviceIwdClass *klass) device_class->state_changed = device_state_changed; + device_class->rfkill_type = NM_RFKILL_TYPE_WLAN; + obj_properties[PROP_MODE] = g_param_spec_uint(NM_DEVICE_IWD_MODE, "", "", diff --git a/src/core/devices/wifi/nm-device-wifi-p2p.c b/src/core/devices/wifi/nm-device-wifi-p2p.c index dfbf8978..4576af95 100644 --- a/src/core/devices/wifi/nm-device-wifi-p2p.c +++ b/src/core/devices/wifi/nm-device-wifi-p2p.c @@ -1229,8 +1229,6 @@ nm_device_wifi_p2p_new(const char *iface) NM_DEVICE_TYPE_WIFI_P2P, NM_DEVICE_LINK_TYPE, NM_LINK_TYPE_WIFI, - NM_DEVICE_RFKILL_TYPE, - RFKILL_TYPE_WLAN, NULL); } @@ -1293,6 +1291,8 @@ nm_device_wifi_p2p_class_init(NMDeviceWifiP2PClass *klass) device_class->state_changed = device_state_changed; + device_class->rfkill_type = NM_RFKILL_TYPE_WLAN; + obj_properties[PROP_PEERS] = g_param_spec_boxed(NM_DEVICE_WIFI_P2P_PEERS, "", "", diff --git a/src/core/devices/wifi/nm-device-wifi.c b/src/core/devices/wifi/nm-device-wifi.c index 010cee08..d83b1f35 100644 --- a/src/core/devices/wifi/nm-device-wifi.c +++ b/src/core/devices/wifi/nm-device-wifi.c @@ -978,14 +978,16 @@ deactivate_reset_hw_addr(NMDevice *device) static gboolean check_connection_compatible(NMDevice *device, NMConnection *connection, GError **error) { - NMDeviceWifi *self = NM_DEVICE_WIFI(device); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); - NMSettingWireless *s_wireless; - const char *mac; - const char *const *mac_blacklist; - int i; - const char *mode; - const char *perm_hw_addr; + NMDeviceWifi *self = NM_DEVICE_WIFI(device); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); + NMSettingWireless *s_wireless; + NMSettingWirelessSecurity *s_wsec; + const char *mac; + const char *const *mac_blacklist; + int i; + const char *mode; + const char *perm_hw_addr; + const char *key_mgmt; if (!NM_DEVICE_CLASS(nm_device_wifi_parent_class) ->check_connection_compatible(device, connection, error)) @@ -1070,6 +1072,20 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError * } } + s_wsec = nm_connection_get_setting_wireless_security(connection); + if (s_wsec) { + key_mgmt = nm_setting_wireless_security_get_key_mgmt(s_wsec); + + if (nm_supplicant_interface_get_capability(priv->sup_iface, NM_SUPPL_CAP_TYPE_WEP) + == NM_TERNARY_FALSE + && NM_IN_STRSET(key_mgmt, "ieee8021x", "none")) { + nm_utils_error_set_literal(error, + NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, + "wpa_supplicant does not support WEP encryption"); + return FALSE; + } + } + // FIXME: check channel/freq/band against bands the hardware supports // FIXME: check encryption against device capabilities // FIXME: check bitrate against device capabilities @@ -2936,14 +2952,16 @@ build_supplicant_config(NMDeviceWifi *self, } s_8021x = nm_connection_get_setting_802_1x(connection); - if (!nm_supplicant_config_add_setting_wireless_security(config, - s_wireless_sec, - s_8021x, - con_uuid, - mtu, - pmf, - fils, - error)) { + if (!nm_supplicant_config_add_setting_wireless_security( + config, + s_wireless_sec, + s_8021x, + con_uuid, + nm_setting_wireless_get_mode(s_wireless), + mtu, + pmf, + fils, + error)) { g_prefix_error(error, "802-11-wireless-security: "); goto error; } @@ -3103,28 +3121,75 @@ act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) static void ensure_hotspot_frequency(NMDeviceWifi *self, NMSettingWireless *s_wifi, NMWifiAP *ap) { - NMDevice *device = NM_DEVICE(self); - const char *band = nm_setting_wireless_get_band(s_wifi); - const guint32 a_freqs[] = {5180, 5200, 5220, 5745, 5765, 5785, 5805, 0}; - const guint32 bg_freqs[] = {2412, 2437, 2462, 2472, 0}; - guint32 freq = 0; + guint32 a_freqs[] = {5180, 5200, 5220, 5745, 5765, 5785, 5805, 0}; + guint32 bg_freqs[] = {2412, 2437, 2462, 2472, 0}; + guint32 *rnd_freqs; + guint rnd_freqs_len; + NMDevice *device = NM_DEVICE(self); + const char *band = nm_setting_wireless_get_band(s_wifi); + guint32 freq; + guint64 rnd; + guint i; + guint l; - g_assert(ap); + nm_assert(ap); + nm_assert(NM_IN_STRSET(band, NULL, "a", "bg")); if (nm_wifi_ap_get_freq(ap)) return; - if (g_strcmp0(band, "a") == 0) - freq = nm_platform_wifi_find_frequency(nm_device_get_platform(device), - nm_device_get_ifindex(device), - a_freqs); - else - freq = nm_platform_wifi_find_frequency(nm_device_get_platform(device), - nm_device_get_ifindex(device), - bg_freqs); + { + GBytes *ssid; + gsize ssid_len; + const guint8 *ssid_data; + const guint8 random_seed[16] = {0x9a, + 0xdc, + 0x86, + 0x9a, + 0xa8, + 0xa2, + 0x07, + 0x97, + 0xbe, + 0x6d, + 0xe6, + 0x99, + 0x9f, + 0xa8, + 0x09, + 0x2b}; + + /* Calculate a stable "random" number based on the SSID. */ + ssid = nm_setting_wireless_get_ssid(s_wifi); + ssid_data = g_bytes_get_data(ssid, &ssid_len); + rnd = c_siphash_hash(random_seed, ssid_data, ssid_len); + } + + if (nm_streq0(band, "a")) { + rnd_freqs = a_freqs; + rnd_freqs_len = G_N_ELEMENTS(a_freqs) - 1; + } else { + rnd_freqs = bg_freqs; + rnd_freqs_len = G_N_ELEMENTS(bg_freqs) - 1; + } + + /* shuffle the frequencies (inplace). The idea is to choose + * a different frequency depending on the SSID. */ + for (i = 0, l = rnd_freqs_len; l > 1; i++, l--) { + /* Add an arbitrary chosen (prime) number to rnd, to get more "random" + * numbers. Since we only shuffle a handful of elements, that's good + * enough (and stable). */ + rnd += 5630246189u; + NM_SWAP(&rnd_freqs[i], &rnd_freqs[i + (rnd % l)]); + } + + freq = nm_platform_wifi_find_frequency(nm_device_get_platform(device), + nm_device_get_ifindex(device), + rnd_freqs); + if (freq == 0) + freq = rnd_freqs[0]; - if (!freq) - freq = (g_strcmp0(band, "a") == 0) ? 5180 : 2462; + _LOGD(LOGD_WIFI, "set frequency for hotspot AP to %u", freq); if (nm_wifi_ap_set_freq(ap, freq)) _ap_dump(self, LOGL_DEBUG, ap, "updated", 0); @@ -3663,8 +3728,6 @@ nm_device_wifi_new(const char *iface, _NMDeviceWifiCapabilities capabilities) NM_DEVICE_TYPE_WIFI, NM_DEVICE_LINK_TYPE, NM_LINK_TYPE_WIFI, - NM_DEVICE_RFKILL_TYPE, - RFKILL_TYPE_WLAN, NM_DEVICE_WIFI_CAPABILITIES, (guint) capabilities, NULL); @@ -3756,6 +3819,8 @@ nm_device_wifi_class_init(NMDeviceWifiClass *klass) device_class->state_changed = device_state_changed; + device_class->rfkill_type = NM_RFKILL_TYPE_WLAN; + obj_properties[PROP_MODE] = g_param_spec_uint(NM_DEVICE_WIFI_MODE, "", "", diff --git a/src/core/devices/wifi/nm-iwd-manager.c b/src/core/devices/wifi/nm-iwd-manager.c index 5563ebf8..27222aae 100644 --- a/src/core/devices/wifi/nm-iwd-manager.c +++ b/src/core/devices/wifi/nm-iwd-manager.c @@ -948,6 +948,7 @@ mirror_connection(NMIwdManager *self, if (!nm_settings_add_connection( priv->settings, + NULL, connection, NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY, NM_SETTINGS_CONNECTION_ADD_REASON_NONE, diff --git a/src/core/devices/wifi/nm-wifi-ap.c b/src/core/devices/wifi/nm-wifi-ap.c index ac0b748a..825a5aa8 100644 --- a/src/core/devices/wifi/nm-wifi-ap.c +++ b/src/core/devices/wifi/nm-wifi-ap.c @@ -1037,9 +1037,10 @@ nm_wifi_ap_lookup_for_device(NMDevice *device, const char *exported_path) g_return_val_if_fail(NM_IS_DEVICE(device), NULL); - ap = nm_dbus_manager_lookup_object(nm_dbus_object_get_manager(NM_DBUS_OBJECT(device)), - exported_path); - if (!ap || !NM_IS_WIFI_AP(ap) || ap->wifi_device != device) + ap = nm_dbus_manager_lookup_object_with_type(nm_dbus_object_get_manager(NM_DBUS_OBJECT(device)), + NM_TYPE_WIFI_AP, + exported_path); + if (!ap || ap->wifi_device != device) return NULL; return ap; diff --git a/src/core/devices/wifi/nm-wifi-p2p-peer.c b/src/core/devices/wifi/nm-wifi-p2p-peer.c index 0a174270..8ccb2a4d 100644 --- a/src/core/devices/wifi/nm-wifi-p2p-peer.c +++ b/src/core/devices/wifi/nm-wifi-p2p-peer.c @@ -139,10 +139,11 @@ nm_wifi_p2p_peer_lookup_for_device(NMDevice *device, const char *exported_path) g_return_val_if_fail(NM_IS_DEVICE(device), NULL); - peer = (NMWifiP2PPeer *) nm_dbus_manager_lookup_object( - nm_dbus_object_get_manager(NM_DBUS_OBJECT(device)), - exported_path); - if (!peer || !NM_IS_WIFI_P2P_PEER(peer) || peer->wifi_device != device) + peer = + nm_dbus_manager_lookup_object_with_type(nm_dbus_object_get_manager(NM_DBUS_OBJECT(device)), + NM_TYPE_WIFI_P2P_PEER, + exported_path); + if (!peer || peer->wifi_device != device) return NULL; return peer; diff --git a/src/core/devices/wwan/nm-device-modem.c b/src/core/devices/wwan/nm-device-modem.c index ef802a44..77ba1b24 100644 --- a/src/core/devices/wwan/nm-device-modem.c +++ b/src/core/devices/wwan/nm-device-modem.c @@ -181,8 +181,10 @@ modem_new_config(NMModem *modem, return; } - if (!IS_IPv4) + if (!IS_IPv4) { priv->iid = iid ? *iid : ((NMUtilsIPv6IfaceId) NM_UTILS_IPV6_IFACE_ID_INIT); + nm_device_sysctl_ip_conf_set(device, AF_INET6, "disable_ipv6", "0"); + } if (do_auto) { if (IS_IPv4) @@ -757,8 +759,6 @@ nm_device_modem_new(NMModem *modem) "Broadband", NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_MODEM, - NM_DEVICE_RFKILL_TYPE, - RFKILL_TYPE_WWAN, NM_DEVICE_MODEM_MODEM, modem, NM_DEVICE_MODEM_CAPABILITIES, @@ -840,6 +840,8 @@ nm_device_modem_class_init(NMDeviceModemClass *klass) device_class->state_changed = device_state_changed; + device_class->rfkill_type = NM_RFKILL_TYPE_WWAN; + obj_properties[PROP_MODEM] = g_param_spec_object(NM_DEVICE_MODEM_MODEM, "", diff --git a/src/core/devices/wwan/nm-modem-broadband.c b/src/core/devices/wwan/nm-modem-broadband.c index b585652e..cbf30f56 100644 --- a/src/core/devices/wwan/nm-modem-broadband.c +++ b/src/core/devices/wwan/nm-modem-broadband.c @@ -957,7 +957,7 @@ stage3_ip_config_start(NMModem *modem, int addr_family, NMModemIPMethod ip_metho const int IS_IPv4 = NM_IS_IPv4(addr_family); NMModemBroadband *self = NM_MODEM_BROADBAND(modem); nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL; - char sbuf[sizeof(_nm_utils_to_string_buffer)]; + char sbuf[NM_UTILS_TO_STRING_BUFFER_SIZE]; gs_free_error GError *error = NULL; const char *data_port; const char *address_string; diff --git a/src/core/devices/wwan/nm-modem-ofono.c b/src/core/devices/wwan/nm-modem-ofono.c index cac90d32..0db30046 100644 --- a/src/core/devices/wwan/nm-modem-ofono.c +++ b/src/core/devices/wwan/nm-modem-ofono.c @@ -734,7 +734,7 @@ handle_settings(GVariant *v_dict, gpointer user_data) { NMModemOfono *self = NM_MODEM_OFONO(user_data); NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self); - char sbuf[sizeof(_nm_utils_to_string_buffer)]; + char sbuf[NM_UTILS_TO_STRING_BUFFER_SIZE]; NMPlatformIP4Address address; gboolean ret = FALSE; const char *interface; diff --git a/src/core/dhcp/nm-dhcp-client.c b/src/core/dhcp/nm-dhcp-client.c index 85e48ff7..2bfd7e01 100644 --- a/src/core/dhcp/nm-dhcp-client.c +++ b/src/core/dhcp/nm-dhcp-client.c @@ -109,25 +109,22 @@ nm_dhcp_client_get_pid(NMDhcpClient *self) return NM_DHCP_CLIENT_GET_PRIVATE(self)->pid; } -static void -_set_effective_client_id(NMDhcpClient *self, GBytes *client_id, gboolean take) +void +nm_dhcp_client_set_effective_client_id(NMDhcpClient *self, GBytes *client_id) { NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self); - nm_assert(!client_id || g_bytes_get_size(client_id) >= 2); + g_return_if_fail(NM_IS_DHCP_CLIENT(self)); + g_return_if_fail(!client_id || g_bytes_get_size(client_id) >= 2); + + priv = NM_DHCP_CLIENT_GET_PRIVATE(self); - if (priv->effective_client_id == client_id - || (priv->effective_client_id && client_id - && g_bytes_equal(priv->effective_client_id, client_id))) { - if (take && client_id) - g_bytes_unref(client_id); + if (nm_g_bytes_equal0(priv->effective_client_id, client_id)) return; - } - if (priv->effective_client_id) - g_bytes_unref(priv->effective_client_id); + g_bytes_unref(priv->effective_client_id); priv->effective_client_id = client_id; - if (!take && client_id) + if (client_id) g_bytes_ref(client_id); { @@ -141,15 +138,6 @@ _set_effective_client_id(NMDhcpClient *self, GBytes *client_id, gboolean take) } } -void -nm_dhcp_client_set_effective_client_id(NMDhcpClient *self, GBytes *client_id) -{ - g_return_if_fail(NM_IS_DHCP_CLIENT(self)); - g_return_if_fail(!client_id || g_bytes_get_size(client_id) >= 2); - - _set_effective_client_id(self, client_id, FALSE); -} - /*****************************************************************************/ NM_UTILS_LOOKUP_STR_DEFINE(nm_dhcp_state_to_string, @@ -678,7 +666,7 @@ nm_dhcp_client_start_ip6(NMDhcpClient *self, GError **error) if (!priv->config.v6.enforce_duid) own_client_id = NM_DHCP_CLIENT_GET_CLASS(self)->get_duid(self); - _set_effective_client_id(self, own_client_id ?: priv->config.client_id, FALSE); + nm_dhcp_client_set_effective_client_id(self, own_client_id ?: priv->config.client_id); addr = ipv6_lladdr_find(self); if (!addr) { diff --git a/src/core/dhcp/nm-dhcp-dhcpcd.c b/src/core/dhcp/nm-dhcp-dhcpcd.c index 4b3429ef..280d9ce6 100644 --- a/src/core/dhcp/nm-dhcp-dhcpcd.c +++ b/src/core/dhcp/nm-dhcp-dhcpcd.c @@ -70,7 +70,7 @@ ip4_start(NMDhcpClient *client, GError **error) const NMDhcpClientConfig *client_config; gs_unref_ptrarray GPtrArray *argv = NULL; pid_t pid; - GError *local = NULL; + gs_free_error GError *local = NULL; gs_free char *cmd_str = NULL; const char *dhcpcd_path; @@ -143,7 +143,6 @@ ip4_start(NMDhcpClient *client, GError **error) NM_UTILS_ERROR_UNKNOWN, "dhcpcd failed to start: %s", local->message); - g_error_free(local); return FALSE; } diff --git a/src/core/dhcp/nm-dhcp-nettools.c b/src/core/dhcp/nm-dhcp-nettools.c index d7fbe356..aac18967 100644 --- a/src/core/dhcp/nm-dhcp-nettools.c +++ b/src/core/dhcp/nm-dhcp-nettools.c @@ -154,6 +154,7 @@ static gboolean lease_parse_address(NDhcp4ClientLease *lease, NML3ConfigData *l3cd, GHashTable *options, + in_addr_t *out_address, GError **error) { struct in_addr a_address; @@ -268,6 +269,8 @@ lease_parse_address(NDhcp4ClientLease *lease, .preferred = a_lifetime, })); + NM_SET_OUT(out_address, a_address.s_addr); + return TRUE; } @@ -326,6 +329,7 @@ lease_parse_address_list(NDhcp4ClientLease *lease, static void lease_parse_routes(NDhcp4ClientLease *lease, NML3ConfigData *l3cd, + in_addr_t lease_address, GHashTable *options, NMStrBuf *sbuf) { @@ -343,6 +347,17 @@ lease_parse_routes(NDhcp4ClientLease *lease, int r; guint i; + /* Routes can be in option 33 (static-route), 121 (classless-static-route) and 249 (a non-standard classless-static-route). + * Option 249 (Microsoft Classless Static Route), is described here: + * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dhcpe/f9c19c79-1c7f-4746-b555-0c0fc523f3f9 + * + * We will anyway parse all these 3 options and add them to the "options" hash (as distinct entries). + * We will however also parse one of the options into the "l3cd" for configuring routing. + * Thereby we prefer 121 over 249 over 33. + * + * Preferring 121 over 33 is defined by RFC 3443. + * Preferring 121 over 249 over 33 is made up as it makes sense (the MS docs are not very clear). + */ for (i = 0; i < 2; i++) { const guint8 option_code = (i == 0) ? NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE : NM_DHCP_OPTION_DHCP4_PRIVATE_CLASSLESS_STATIC_ROUTE; @@ -373,10 +388,11 @@ lease_parse_routes(NDhcp4ClientLease *lease, nm_l3_config_data_add_route_4(l3cd, &((const NMPlatformIP4Route){ + .rt_source = NM_IP_CONFIG_SOURCE_DHCP, .network = dest, .plen = plen, .gateway = gateway, - .rt_source = NM_IP_CONFIG_SOURCE_DHCP, + .pref_src = lease_address, .table_any = TRUE, .table_coerced = 0, .metric_any = TRUE, @@ -416,10 +432,11 @@ lease_parse_routes(NDhcp4ClientLease *lease, nm_l3_config_data_add_route_4(l3cd, &((const NMPlatformIP4Route){ + .rt_source = NM_IP_CONFIG_SOURCE_DHCP, .network = dest, .plen = plen, .gateway = gateway, - .rt_source = NM_IP_CONFIG_SOURCE_DHCP, + .pref_src = lease_address, .table_any = TRUE, .table_coerced = 0, .metric_any = TRUE, @@ -464,6 +481,7 @@ lease_parse_routes(NDhcp4ClientLease *lease, &((const NMPlatformIP4Route){ .rt_source = NM_IP_CONFIG_SOURCE_DHCP, .gateway = gateway, + .pref_src = lease_address, .table_any = TRUE, .table_coerced = 0, .metric_any = TRUE, @@ -547,6 +565,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, const char *v_str; guint16 v_u16; in_addr_t v_inaddr; + in_addr_t lease_address; struct in_addr v_inaddr_s; int r; @@ -556,7 +575,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, options = nm_dhcp_option_create_options_dict(); - if (!lease_parse_address(lease, l3cd, options, error)) + if (!lease_parse_address(lease, l3cd, options, &lease_address, error)) return NULL; r = n_dhcp4_client_lease_get_server_identifier(lease, &v_inaddr_s); @@ -575,7 +594,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, v_inaddr); } - lease_parse_routes(lease, l3cd, options, &sbuf); + lease_parse_routes(lease, l3cd, lease_address, options, &sbuf); lease_parse_address_list(lease, l3cd, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER, options, &sbuf); diff --git a/src/core/dhcp/nm-dhcp-systemd.c b/src/core/dhcp/nm-dhcp-systemd.c index 0884def3..14a121e7 100644 --- a/src/core/dhcp/nm-dhcp-systemd.c +++ b/src/core/dhcp/nm-dhcp-systemd.c @@ -81,16 +81,20 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, const struct in_addr *addr_list; char addr_str[NM_UTILS_INET_ADDRSTRLEN]; const char *s; - nm_auto_free_gstring GString *str = NULL; - nm_auto_free sd_dhcp_route **routes = NULL; - const char *const *search_domains = NULL; + nm_auto_free_gstring GString *str = NULL; + nm_auto_free sd_dhcp_route **routes_static = NULL; + nm_auto_free sd_dhcp_route **routes_classless = NULL; + const char *const *search_domains = NULL; + guint32 default_route_metric_offset; guint16 mtu; - int i, num; + int i; + int num; + int is_classless; + int n_routes_static; + int n_routes_classless; const void *data; gsize data_len; gboolean has_router_from_classless = FALSE; - gboolean has_classless_route = FALSE; - gboolean has_static_route = FALSE; const gint32 ts = nm_utils_get_monotonic_timestamp_sec(); gint64 ts_time = time(NULL); struct in_addr a_address; @@ -226,44 +230,27 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_HOST_NAME, s); } - num = sd_dhcp_lease_get_routes(lease, &routes); - if (num > 0) { - nm_auto_free_gstring GString *str_classless = NULL; - nm_auto_free_gstring GString *str_static = NULL; - guint32 default_route_metric_offset = 0; + default_route_metric_offset = 0; + n_routes_static = sd_dhcp_lease_get_static_routes(lease, &routes_static); + n_routes_classless = sd_dhcp_lease_get_classless_routes(lease, &routes_classless); + for (is_classless = 1; is_classless >= 0; is_classless--) { + int n_routes = (is_classless ? n_routes_classless : n_routes_static); + sd_dhcp_route *const *routes = (is_classless ? routes_classless : routes_static); - for (i = 0; i < num; i++) { - switch (sd_dhcp_route_get_option(routes[i])) { - case NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE: - has_classless_route = TRUE; - break; - case NM_DHCP_OPTION_DHCP4_STATIC_ROUTE: - has_static_route = TRUE; - break; - } - } + if (n_routes <= 0) + continue; - if (has_classless_route) - str_classless = g_string_sized_new(30); - if (has_static_route) - str_static = g_string_sized_new(30); + nm_gstring_prepare(&str); - for (i = 0; i < num; i++) { + for (i = 0; i < n_routes; i++) { char network_net_str[NM_UTILS_INET_ADDRSTRLEN]; char gateway_str[NM_UTILS_INET_ADDRSTRLEN]; guint8 r_plen; struct in_addr r_network; struct in_addr r_gateway; in_addr_t network_net; - int option; guint32 m; - option = sd_dhcp_route_get_option(routes[i]); - if (!NM_IN_SET(option, - NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE, - NM_DHCP_OPTION_DHCP4_STATIC_ROUTE)) - continue; - if (sd_dhcp_route_get_destination(routes[i], &r_network) < 0) continue; if (sd_dhcp_route_get_destination_prefix_length(routes[i], &r_plen) < 0 || r_plen > 32) @@ -275,31 +262,28 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, _nm_utils_inet4_ntop(network_net, network_net_str); _nm_utils_inet4_ntop(r_gateway.s_addr, gateway_str); - g_string_append_printf( - nm_gstring_add_space_delimiter(option == NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE - ? str_classless - : str_static), - "%s/%d %s", - network_net_str, - (int) r_plen, - gateway_str); + g_string_append_printf(nm_gstring_add_space_delimiter(str), + "%s/%d %s", + network_net_str, + (int) r_plen, + gateway_str); - if (option == NM_DHCP_OPTION_DHCP4_STATIC_ROUTE && has_classless_route) { + if (!is_classless && n_routes_classless > 0) { /* RFC 3443: if the DHCP server returns both a Classless Static Routes * option and a Static Routes option, the DHCP client MUST ignore the * Static Routes option. */ continue; } - if (r_plen == 0 && option == NM_DHCP_OPTION_DHCP4_STATIC_ROUTE) { - /* for option 33 (static route), RFC 2132 says: - * - * The default route (0.0.0.0) is an illegal destination for a static - * route. */ - continue; - } - if (r_plen == 0) { + if (!is_classless) { + /* for option 33 (static route), RFC 2132 says: + * + * The default route (0.0.0.0) is an illegal destination for a static + * route. */ + continue; + } + /* if there are multiple default routes, we add them with differing * metrics. */ m = default_route_metric_offset++; @@ -309,10 +293,11 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, nm_l3_config_data_add_route_4(l3cd, &((const NMPlatformIP4Route){ + .rt_source = NM_IP_CONFIG_SOURCE_DHCP, .network = network_net, .plen = r_plen, .gateway = r_gateway.s_addr, - .rt_source = NM_IP_CONFIG_SOURCE_DHCP, + .pref_src = a_address.s_addr, .metric_any = TRUE, .metric = m, .table_any = TRUE, @@ -320,21 +305,18 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, })); } - if (str_classless && str_classless->len > 0) - nm_dhcp_option_add_option(options, - AF_INET, - NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE, - str_classless->str); - if (str_static && str_static->len > 0) + if (str->len > 0) { nm_dhcp_option_add_option(options, AF_INET, - NM_DHCP_OPTION_DHCP4_STATIC_ROUTE, - str_static->str); + is_classless ? NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE + : NM_DHCP_OPTION_DHCP4_STATIC_ROUTE, + str->str); + } } num = sd_dhcp_lease_get_router(lease, &a_router); if (num > 0) { - guint32 default_route_metric_offset = 0; + default_route_metric_offset = 0; nm_gstring_prepare(&str); for (i = 0; i < num; i++) { @@ -366,6 +348,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, &((const NMPlatformIP4Route){ .rt_source = NM_IP_CONFIG_SOURCE_DHCP, .gateway = a_router[i].s_addr, + .pref_src = a_address.s_addr, .table_any = TRUE, .table_coerced = 0, .metric_any = TRUE, diff --git a/src/core/dhcp/nm-dhcp-utils.c b/src/core/dhcp/nm-dhcp-utils.c index 214e94cd..a0eec6e0 100644 --- a/src/core/dhcp/nm-dhcp-utils.c +++ b/src/core/dhcp/nm-dhcp-utils.c @@ -28,7 +28,8 @@ static gboolean ip4_process_dhcpcd_rfc3442_routes(const char *iface, const char *str, NML3ConfigData *l3cd, - guint32 *gwaddr) + in_addr_t address, + guint32 *out_gwaddr) { gs_free const char **routes = NULL; const char **r; @@ -79,7 +80,7 @@ ip4_process_dhcpcd_rfc3442_routes(const char *iface, have_routes = TRUE; if (rt_cidr == 0 && rt_addr == 0) { /* FIXME: how to handle multiple routers? */ - *gwaddr = rt_route; + *out_gwaddr = rt_route; } else { _LOG2I(LOGD_DHCP4, iface, @@ -91,13 +92,13 @@ ip4_process_dhcpcd_rfc3442_routes(const char *iface, nm_l3_config_data_add_route_4( l3cd, &((const NMPlatformIP4Route){ + .rt_source = NM_IP_CONFIG_SOURCE_DHCP, .network = nm_utils_ip4_address_clear_host_address(rt_addr, rt_cidr), .plen = rt_cidr, .gateway = rt_route, - .rt_source = NM_IP_CONFIG_SOURCE_DHCP, + .pref_src = address, .metric_any = TRUE, .table_any = TRUE, - })); } } @@ -158,7 +159,8 @@ static gboolean ip4_process_dhclient_rfc3442_routes(const char *iface, const char *str, NML3ConfigData *l3cd, - guint32 *gwaddr) + in_addr_t address, + guint32 *out_gwaddr) { gs_free const char **octets = NULL; const char *const *o; @@ -182,13 +184,14 @@ ip4_process_dhclient_rfc3442_routes(const char *iface, have_routes = TRUE; if (!route.plen) { /* gateway passed as classless static route */ - *gwaddr = route.gateway; + *out_gwaddr = route.gateway; } else { char b1[INET_ADDRSTRLEN]; char b2[INET_ADDRSTRLEN]; /* normal route */ route.rt_source = NM_IP_CONFIG_SOURCE_DHCP; + route.pref_src = address; route.table_any = TRUE; route.table_coerced = 0; route.metric_any = TRUE; @@ -212,14 +215,15 @@ static gboolean ip4_process_classless_routes(const char *iface, GHashTable *options, NML3ConfigData *l3cd, - guint32 *gwaddr) + in_addr_t address, + guint32 *out_gwaddr) { const char *str, *p; g_return_val_if_fail(options != NULL, FALSE); g_return_val_if_fail(l3cd != NULL, FALSE); - *gwaddr = 0; + *out_gwaddr = 0; /* dhcpd/dhclient in Fedora has support for rfc3442 implemented using a * slightly different format: @@ -266,14 +270,17 @@ ip4_process_classless_routes(const char *iface, if (strchr(str, '/')) { /* dhcpcd format */ - return ip4_process_dhcpcd_rfc3442_routes(iface, str, l3cd, gwaddr); + return ip4_process_dhcpcd_rfc3442_routes(iface, str, l3cd, address, out_gwaddr); } - return ip4_process_dhclient_rfc3442_routes(iface, str, l3cd, gwaddr); + return ip4_process_dhclient_rfc3442_routes(iface, str, l3cd, address, out_gwaddr); } static void -process_classful_routes(const char *iface, GHashTable *options, NML3ConfigData *l3cd) +process_classful_routes(const char *iface, + GHashTable *options, + NML3ConfigData *l3cd, + in_addr_t address) { gs_free const char **searches = NULL; const char **s; @@ -293,6 +300,7 @@ process_classful_routes(const char *iface, GHashTable *options, NML3ConfigData * } for (s = searches; *s; s += 2) { + char sbuf[NM_UTILS_TO_STRING_BUFFER_SIZE]; NMPlatformIP4Route route; guint32 rt_addr, rt_route; @@ -321,6 +329,7 @@ process_classful_routes(const char *iface, GHashTable *options, NML3ConfigData * route.plen = 32; } route.gateway = rt_route; + route.pref_src = address; route.rt_source = NM_IP_CONFIG_SOURCE_DHCP; route.table_any = TRUE; route.table_coerced = 0; @@ -334,7 +343,7 @@ process_classful_routes(const char *iface, GHashTable *options, NML3ConfigData * _LOG2I(LOGD_DHCP, iface, " static route %s", - nm_platform_ip4_route_to_string(&route, NULL, 0)); + nm_platform_ip4_route_to_string(&route, sbuf, sizeof(sbuf))); } } @@ -422,8 +431,8 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx, /* Routes: if the server returns classless static routes, we MUST ignore * the 'static_routes' option. */ - if (!ip4_process_classless_routes(iface, options, l3cd, &gateway)) - process_classful_routes(iface, options, l3cd); + if (!ip4_process_classless_routes(iface, options, l3cd, address.address, &gateway)) + process_classful_routes(iface, options, l3cd, address.address); if (gateway) { _LOG2I(LOGD_DHCP4, iface, " gateway %s", _nm_utils_inet4_ntop(gateway, sbuf)); @@ -453,6 +462,7 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx, const NMPlatformIP4Route r = { .rt_source = NM_IP_CONFIG_SOURCE_DHCP, .gateway = gateway, + .pref_src = address.address, .table_any = TRUE, .table_coerced = 0, .metric_any = TRUE, diff --git a/src/core/dns/nm-dns-dnsmasq.c b/src/core/dns/nm-dns-dnsmasq.c index f0abf564..43426882 100644 --- a/src/core/dns/nm-dns-dnsmasq.c +++ b/src/core/dns/nm-dns-dnsmasq.c @@ -39,10 +39,10 @@ #define _NMLOG(level, ...) __NMLOG_DEFAULT(level, _NMLOG_DOMAIN, "dnsmasq", __VA_ARGS__) #define WAIT_MSEC_AFTER_SIGTERM 1000 -G_STATIC_ASSERT(WAIT_MSEC_AFTER_SIGTERM <= NM_SHUTDOWN_TIMEOUT_MS); +G_STATIC_ASSERT(WAIT_MSEC_AFTER_SIGTERM <= NM_SHUTDOWN_TIMEOUT_MAX_MSEC); #define WAIT_MSEC_AFTER_SIGKILL 400 -G_STATIC_ASSERT(WAIT_MSEC_AFTER_SIGKILL + 100 <= NM_SHUTDOWN_TIMEOUT_MS_WATCHDOG); +G_STATIC_ASSERT(WAIT_MSEC_AFTER_SIGKILL + 100 <= NM_SHUTDOWN_TIMEOUT_ADDITIONAL_MSEC); typedef void (*GlPidSpawnAsyncNotify)(GCancellable *cancellable, GPid pid, @@ -848,7 +848,7 @@ static GVariant * create_update_args(NMDnsDnsmasq *self, const NMGlobalDnsConfig *global_config, const CList *ip_data_lst_head, - const char *hostname) + const char *hostdomain) { GVariantBuilder servers; const NMDnsConfigIPData *ip_data; @@ -1124,7 +1124,7 @@ static gboolean update(NMDnsPlugin *plugin, const NMGlobalDnsConfig *global_config, const CList *ip_data_lst_head, - const char *hostname, + const char *hostdomain, GError **error) { NMDnsDnsmasq *self = NM_DNS_DNSMASQ(plugin); @@ -1135,7 +1135,7 @@ update(NMDnsPlugin *plugin, nm_clear_pointer(&priv->set_server_ex_args, g_variant_unref); priv->set_server_ex_args = - g_variant_ref_sink(create_update_args(self, global_config, ip_data_lst_head, hostname)); + g_variant_ref_sink(create_update_args(self, global_config, ip_data_lst_head, hostdomain)); send_dnsmasq_update(self); return TRUE; diff --git a/src/core/dns/nm-dns-manager.c b/src/core/dns/nm-dns-manager.c index efbf847b..566f3d66 100644 --- a/src/core/dns/nm-dns-manager.c +++ b/src/core/dns/nm-dns-manager.c @@ -26,6 +26,7 @@ #include "libnm-core-intern/nm-core-internal.h" #include "libnm-glib-aux/nm-str-buf.h" +#include "libnm-systemd-shared/nm-sd-utils-shared.h" #include "NetworkManagerUtils.h" #include "devices/nm-device.h" @@ -97,7 +98,7 @@ typedef struct { bool config_changed : 1; - char *hostname; + char *hostdomain; guint updates_queue; guint8 hash[HASH_LEN]; /* SHA1 hash of current DNS config */ @@ -1260,24 +1261,8 @@ _collect_resolv_conf_data(NMDnsManager *self, } } - /* If the hostname is a FQDN ("dcbw.example.com"), then add the domain part of it - * ("example.com") to the searches list, to ensure that we can still resolve its - * non-FQ form ("dcbw") too. (Also, if there are no other search domains specified, - * this makes a good default.) However, if the hostname is the top level of a domain - * (eg, "example.com"), then use the hostname itself as the search (since the user is - * unlikely to want "com" as a search domain). - */ - if (priv->hostname) { - const char *hostdomain = strchr(priv->hostname, '.'); - - if (hostdomain && !nm_utils_ipaddr_is_valid(AF_UNSPEC, priv->hostname)) { - hostdomain++; - if (domain_is_valid(hostdomain, TRUE)) - add_string_item(rc.searches, hostdomain, TRUE); - else if (domain_is_valid(priv->hostname, TRUE)) - add_string_item(rc.searches, priv->hostname, TRUE); - } - } + if (priv->hostdomain) + add_string_item(rc.searches, priv->hostdomain, TRUE); if (rc.has_trust_ad == NM_TERNARY_TRUE) g_ptr_array_add(rc.options, g_strdup(NM_SETTING_DNS_OPTION_TRUST_AD)); @@ -1695,7 +1680,7 @@ update_dns(NMDnsManager *self, gboolean no_caching, gboolean force_emit, GError nm_dns_plugin_update(priv->sd_resolve_plugin, global_config, _mgr_get_ip_data_lst_head(self), - priv->hostname, + priv->hostdomain, NULL); } @@ -1717,7 +1702,7 @@ update_dns(NMDnsManager *self, gboolean no_caching, gboolean force_emit, GError if (!nm_dns_plugin_update(plugin, global_config, _mgr_get_ip_data_lst_head(self), - priv->hostname, + priv->hostdomain, &plugin_error)) { _LOGW("update-dns: plugin %s update failed: %s", plugin_name, plugin_error->message); @@ -2003,27 +1988,39 @@ done: } void -nm_dns_manager_set_initial_hostname(NMDnsManager *self, const char *hostname) -{ - NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE(self); - - g_free(priv->hostname); - priv->hostname = g_strdup(hostname); -} - -void nm_dns_manager_set_hostname(NMDnsManager *self, const char *hostname, gboolean skip_update) { - NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE(self); + NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE(self); + const char *domain = NULL; /* Certain hostnames we don't want to include in resolv.conf 'searches' */ - if (hostname && nm_utils_is_specific_hostname(hostname) && !strstr(hostname, ".in-addr.arpa") - && strchr(hostname, '.')) { - /* pass */ - } else - hostname = NULL; + if (hostname && nm_utils_is_specific_hostname(hostname) + && !g_str_has_suffix(hostname, ".in-addr.arpa") + && !nm_utils_ipaddr_is_valid(AF_UNSPEC, hostname)) { + domain = strchr(hostname, '.'); + if (domain) { + domain++; + /* If the hostname is a FQDN ("dcbw.example.com"), then add + * the domain part of it ("example.com") to the searches list, + * to ensure that we can still resolve its non-FQ form + * ("dcbw") too. (Also, if there are no other search domains + * specified, this makes a good default.) However, if the + * hostname is the top level of a domain (eg, "example.com"), + * then use the hostname itself as the search (since the user + * is unlikely to want "com" as a search domain).a + */ + if (domain_is_valid(domain, TRUE)) { + /* pass */ + } else if (domain_is_valid(hostname, TRUE)) { + domain = hostname; + } + + if (!nm_sd_hostname_is_valid(domain, FALSE)) + domain = NULL; + } + } - if (!nm_strdup_reset(&priv->hostname, hostname)) + if (!nm_strdup_reset(&priv->hostdomain, domain)) return; if (skip_update) @@ -2668,7 +2665,7 @@ finalize(GObject *object) NMDnsManager *self = NM_DNS_MANAGER(object); NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE(self); - g_free(priv->hostname); + g_free(priv->hostdomain); g_free(priv->mode); G_OBJECT_CLASS(nm_dns_manager_parent_class)->finalize(object); diff --git a/src/core/dns/nm-dns-manager.h b/src/core/dns/nm-dns-manager.h index 84821ece..c30d4b3a 100644 --- a/src/core/dns/nm-dns-manager.h +++ b/src/core/dns/nm-dns-manager.h @@ -105,7 +105,6 @@ gboolean nm_dns_manager_set_ip_config(NMDnsManager *self, NMDnsIPConfigType ip_config_type, gboolean replace_all); -void nm_dns_manager_set_initial_hostname(NMDnsManager *self, const char *hostname); void nm_dns_manager_set_hostname(NMDnsManager *self, const char *hostname, gboolean skip_update); /** diff --git a/src/core/dns/nm-dns-plugin.c b/src/core/dns/nm-dns-plugin.c index 2126da77..847d7839 100644 --- a/src/core/dns/nm-dns-plugin.c +++ b/src/core/dns/nm-dns-plugin.c @@ -60,7 +60,7 @@ gboolean nm_dns_plugin_update(NMDnsPlugin *self, const NMGlobalDnsConfig *global_config, const CList *ip_config_lst_head, - const char *hostname, + const char *hostdomain, GError **error) { g_return_val_if_fail(NM_DNS_PLUGIN_GET_CLASS(self)->update != NULL, FALSE); @@ -68,7 +68,7 @@ nm_dns_plugin_update(NMDnsPlugin *self, return NM_DNS_PLUGIN_GET_CLASS(self)->update(self, global_config, ip_config_lst_head, - hostname, + hostdomain, error); } diff --git a/src/core/dns/nm-dns-plugin.h b/src/core/dns/nm-dns-plugin.h index bc854cce..f9c424ab 100644 --- a/src/core/dns/nm-dns-plugin.h +++ b/src/core/dns/nm-dns-plugin.h @@ -34,7 +34,7 @@ typedef struct { gboolean (*update)(NMDnsPlugin *self, const NMGlobalDnsConfig *global_config, const CList *ip_config_lst_head, - const char *hostname, + const char *hostdomain, GError **error); void (*stop)(NMDnsPlugin *self); diff --git a/src/core/dns/nm-dns-systemd-resolved.c b/src/core/dns/nm-dns-systemd-resolved.c index a043e855..c4993884 100644 --- a/src/core/dns/nm-dns-systemd-resolved.c +++ b/src/core/dns/nm-dns-systemd-resolved.c @@ -551,7 +551,7 @@ static gboolean update(NMDnsPlugin *plugin, const NMGlobalDnsConfig *global_config, const CList *ip_data_lst_head, - const char *hostname, + const char *hostdomain, GError **error) { NMDnsSystemdResolved *self = NM_DNS_SYSTEMD_RESOLVED(plugin); diff --git a/src/core/dns/nm-dns-unbound.c b/src/core/dns/nm-dns-unbound.c index f5a53332..8a75cf08 100644 --- a/src/core/dns/nm-dns-unbound.c +++ b/src/core/dns/nm-dns-unbound.c @@ -28,7 +28,7 @@ static gboolean update(NMDnsPlugin *plugin, const NMGlobalDnsConfig *global_config, const CList *ip_config_lst_head, - const char *hostname, + const char *hostdomain, GError **error) { char *argv[] = {DNSSEC_TRIGGER_PATH, "--async", "--update", NULL}; diff --git a/src/core/dnsmasq/nm-dnsmasq-manager.c b/src/core/dnsmasq/nm-dnsmasq-manager.c index 4ab91e7e..be463da3 100644 --- a/src/core/dnsmasq/nm-dnsmasq-manager.c +++ b/src/core/dnsmasq/nm-dnsmasq-manager.c @@ -67,9 +67,12 @@ dm_watch_cb(GPid pid, int status, gpointer user_data) guint err; if (WIFEXITED(status)) { + char sbuf[NM_UTILS_TO_STRING_BUFFER_SIZE]; + err = WEXITSTATUS(status); if (err != 0) { - _LOGW("dnsmasq exited with error: %s", nm_utils_dnsmasq_status_to_string(err, NULL, 0)); + _LOGW("dnsmasq exited with error: %s", + nm_utils_dnsmasq_status_to_string(err, sbuf, sizeof(sbuf))); } } else if (WIFSTOPPED(status)) { _LOGW("dnsmasq stopped unexpectedly with signal %d", WSTOPSIG(status)); @@ -188,8 +191,6 @@ create_dm_cmd_line(const char *iface, nm_strv_ptrarray_add_string_dup(cmd, "--dhcp-option-force=43,ANDROID_METERED"); } - nm_strv_ptrarray_add_string_dup(cmd, "--dhcp-lease-max=50"); - nm_strv_ptrarray_add_string_printf(cmd, "--dhcp-leasefile=%s/dnsmasq-%s.leases", NMSTATEDIR, diff --git a/src/core/main.c b/src/core/main.c index e39a9614..1a9c3a65 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -302,8 +302,6 @@ main(int argc, char *argv[]) g_type_ensure(G_TYPE_DBUS_CONNECTION); g_type_ensure(NM_TYPE_DBUS_MANAGER); - main_loop = g_main_loop_new(NULL, FALSE); - /* we determine a first-start (contrary to a restart during the same boot) * based on the existence of NM_CONFIG_DEVICE_STATE_DIR directory. */ config_cli = nm_config_cmd_line_options_new( @@ -403,6 +401,8 @@ main(int argc, char *argv[]) wrote_pidfile = nm_main_utils_write_pidfile(global_opt.pidfile); } + main_loop = g_main_loop_new(NULL, FALSE); + /* Set up unix signal handling - before creating threads, but after daemonizing! */ nm_main_utils_setup_signals(main_loop); diff --git a/src/core/ndisc/nm-ndisc.c b/src/core/ndisc/nm-ndisc.c index 969eacfa..04b673e5 100644 --- a/src/core/ndisc/nm-ndisc.c +++ b/src/core/ndisc/nm-ndisc.c @@ -996,6 +996,7 @@ nm_ndisc_set_config(NMNDisc *ndisc, const NML3ConfigData *l3cd) const NMPObject *obj; guint len; guint i; + gint32 fake_now = NM_NDISC_EXPIRY_BASE_TIMESTAMP / 1000; nm_assert(NM_IS_NDISC(ndisc)); nm_assert(nm_ndisc_get_node_type(ndisc) == NM_NDISC_NODE_TYPE_ROUTER); @@ -1018,7 +1019,7 @@ nm_ndisc_set_config(NMNDisc *ndisc, const NML3ConfigData *l3cd) lifetime = nmp_utils_lifetime_get(addr->timestamp, addr->lifetime, addr->preferred, - NM_NDISC_EXPIRY_BASE_TIMESTAMP / 1000, + &fake_now, &preferred); if (!lifetime) continue; diff --git a/src/core/nm-checkpoint-manager.c b/src/core/nm-checkpoint-manager.c index 4a3e7aaf..6c9ea2a6 100644 --- a/src/core/nm-checkpoint-manager.c +++ b/src/core/nm-checkpoint-manager.c @@ -259,10 +259,11 @@ nm_checkpoint_manager_lookup_by_path(NMCheckpointManager *self, const char *path g_return_val_if_fail(self, NULL); - checkpoint = - nm_dbus_manager_lookup_object(nm_dbus_object_get_manager(NM_DBUS_OBJECT(GET_MANAGER(self))), - path); - if (!checkpoint || !NM_IS_CHECKPOINT(checkpoint)) { + checkpoint = nm_dbus_manager_lookup_object_with_type( + nm_dbus_object_get_manager(NM_DBUS_OBJECT(GET_MANAGER(self))), + NM_TYPE_CHECKPOINT, + path); + if (!checkpoint) { g_set_error(error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_INVALID_ARGUMENTS, diff --git a/src/core/nm-checkpoint.c b/src/core/nm-checkpoint.c index 5b48f91a..15667332 100644 --- a/src/core/nm-checkpoint.c +++ b/src/core/nm-checkpoint.c @@ -231,6 +231,7 @@ restore_and_activate_connection(NMCheckpoint *self, DeviceCheckpoint *dev_checkp persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP; nm_settings_connection_update( connection, + NULL, dev_checkpoint->settings_connection, persist_mode, sett_flags, @@ -247,6 +248,7 @@ restore_and_activate_connection(NMCheckpoint *self, DeviceCheckpoint *dev_checkp persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_TO_DISK; if (!nm_settings_add_connection(NM_SETTINGS_GET, + NULL, dev_checkpoint->settings_connection, persist_mode, NM_SETTINGS_CONNECTION_ADD_REASON_NONE, diff --git a/src/core/nm-config.c b/src/core/nm-config.c index 60a2f1df..ea1c2ab3 100644 --- a/src/core/nm-config.c +++ b/src/core/nm-config.c @@ -2870,6 +2870,7 @@ _set_config_data(NMConfig *self, NMConfigData *new_data, NMConfigChangeFlags rel NMConfigData *old_data = priv->config_data; NMConfigChangeFlags changes, changes_diff; gboolean had_new_data = !!new_data; + char sbuf[NM_UTILS_TO_STRING_BUFFER_SIZE]; nm_assert(reload_flags); nm_assert(!NM_FLAGS_ANY(reload_flags, ~NM_CONFIG_CHANGE_CAUSES)); @@ -2901,15 +2902,15 @@ _set_config_data(NMConfig *self, NMConfigData *new_data, NMConfigChangeFlags rel if (new_data) { _LOGI("signal: %s (%s)", - nm_config_change_flags_to_string(changes, NULL, 0), + nm_config_change_flags_to_string(changes, sbuf, sizeof(sbuf)), nm_config_data_get_config_description(new_data)); nm_config_data_log(new_data, "CONFIG: ", " ", priv->no_auto_default_file, NULL); priv->config_data = new_data; } else if (had_new_data) _LOGI("signal: %s (no changes from disk)", - nm_config_change_flags_to_string(changes, NULL, 0)); + nm_config_change_flags_to_string(changes, sbuf, sizeof(sbuf))); else - _LOGI("signal: %s", nm_config_change_flags_to_string(changes, NULL, 0)); + _LOGI("signal: %s", nm_config_change_flags_to_string(changes, sbuf, sizeof(sbuf))); g_signal_emit(self, signals[SIGNAL_CONFIG_CHANGED], 0, new_data ?: old_data, changes, old_data); if (new_data) g_object_unref(old_data); diff --git a/src/core/nm-connectivity.c b/src/core/nm-connectivity.c index c84d8a56..eea8adb2 100644 --- a/src/core/nm-connectivity.c +++ b/src/core/nm-connectivity.c @@ -622,6 +622,75 @@ _timeout_cb(gpointer user_data) cb_data_complete(cb_data, NM_CONNECTIVITY_LIMITED, "timeout"); return G_SOURCE_REMOVE; } + +static gboolean +easy_debug_enabled(void) +{ + static int enabled = 0; + int e; + + /* libcurl debug logging can be useful, but is very verbose. + * Only enable it when we have a certain environment variable set. */ + +again: + e = g_atomic_int_get(&enabled); + if (G_UNLIKELY(e == 0)) { + e = _nm_utils_ascii_str_to_bool(g_getenv("NM_LOG_CONCHECK"), FALSE) ? 1 : -1; + if (G_UNLIKELY(!g_atomic_int_compare_and_exchange(&enabled, 0, e))) + goto again; + } + return e >= 0; +} + +static int +easy_debug_cb(CURL *handle, curl_infotype type, char *data, size_t size, void *userptr) +{ + NMConnectivityCheckHandle *cb_data = userptr; + gs_free char *data_escaped = NULL; + const char *msg; + gboolean print_data = FALSE; + + switch (type) { + case CURLINFO_TEXT: + print_data = TRUE; + msg = "== Info: "; + break; + case CURLINFO_DATA_OUT: + msg = "=> Send data"; + break; + case CURLINFO_SSL_DATA_OUT: + msg = "=> Send SSL data"; + break; + case CURLINFO_HEADER_IN: + msg = "<= Recv header"; + break; + case CURLINFO_DATA_IN: + msg = "<= Recv data"; + break; + case CURLINFO_SSL_DATA_IN: + msg = "<= Recv SSL data"; + break; + case CURLINFO_HEADER_OUT: + print_data = TRUE; + msg = "=> Send header: "; + return 0; + default: + return 0; + } + + _LOG2T("libcurl %s%s%s%s", + msg, + NM_PRINT_FMT_QUOTED(print_data, + "[", + (data_escaped = nm_utils_buf_utf8safe_escape_cp( + data, + size, + NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL)) + ?: "", + "]", + "")); + return 0; +} #endif static gboolean @@ -641,12 +710,14 @@ _idle_cb(gpointer user_data) #if WITH_CONCHECK static void -do_curl_request(NMConnectivityCheckHandle *cb_data) +do_curl_request(NMConnectivityCheckHandle *cb_data, const char *hosts) { CURLM *mhandle; CURL *ehandle; long resolve; + _LOG2T("set curl resolve list to '%s'", hosts); + mhandle = curl_multi_init(); if (!mhandle) { cb_data_complete(cb_data, NM_CONNECTIVITY_ERROR, "curl error"); @@ -660,6 +731,8 @@ do_curl_request(NMConnectivityCheckHandle *cb_data) return; } + cb_data->concheck.hosts = curl_slist_append(NULL, hosts); + cb_data->concheck.curl_mhandle = mhandle; cb_data->concheck.curl_ehandle = ehandle; cb_data->concheck.request_headers = curl_slist_append(NULL, "Connection: close"); @@ -696,12 +769,103 @@ do_curl_request(NMConnectivityCheckHandle *cb_data) curl_easy_setopt(ehandle, CURLOPT_RESOLVE, cb_data->concheck.hosts); curl_easy_setopt(ehandle, CURLOPT_IPRESOLVE, resolve); curl_easy_setopt(ehandle, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); + if (_LOGT_ENABLED() && easy_debug_enabled()) { + curl_easy_setopt(ehandle, CURLOPT_DEBUGFUNCTION, easy_debug_cb); + curl_easy_setopt(ehandle, CURLOPT_DEBUGDATA, cb_data); + curl_easy_setopt(ehandle, CURLOPT_VERBOSE, 1L); + } curl_multi_add_handle(mhandle, ehandle); } static void -resolve_cb(GObject *object, GAsyncResult *res, gpointer user_data) +system_resolver_resolve_cb(GObject *source_object, GAsyncResult *res, gpointer user_data) +{ + nm_auto_str_buf NMStrBuf strbuf_hosts = NM_STR_BUF_INIT(0, FALSE); + gs_free_error GError *resolv_error = NULL; + GList *list; + GList *iter; + NMConnectivityCheckHandle *cb_data; + + list = g_resolver_lookup_by_name_finish(G_RESOLVER(source_object), res, &resolv_error); + + if (nm_utils_error_is_cancelled(resolv_error)) + return; + + cb_data = user_data; + + nm_assert(cb_data); + nm_assert(NM_IS_CONNECTIVITY(cb_data->self)); + + if (resolv_error) { + _LOG2D("failure to resolve name: %s", resolv_error->message); + cb_data_complete(cb_data, NM_CONNECTIVITY_LIMITED, "resolve-error"); + return; + } + + for (iter = list; iter; iter = iter->next) { + GInetAddress *a = iter->data; + char str_addr[NM_UTILS_INET_ADDRSTRLEN]; + int addr_family; + + switch (g_inet_address_get_family(a)) { + case G_SOCKET_FAMILY_IPV4: + addr_family = AF_INET; + break; + case G_SOCKET_FAMILY_IPV6: + addr_family = AF_INET6; + break; + default: + addr_family = AF_UNSPEC; + break; + } + if (cb_data->addr_family != AF_UNSPEC && cb_data->addr_family != addr_family) + continue; + + if (strbuf_hosts.len == 0) { + nm_str_buf_append_printf(&strbuf_hosts, + "%s:%s:", + cb_data->concheck.con_config->host, + cb_data->concheck.con_config->port ?: "80"); + } else + nm_str_buf_append_c(&strbuf_hosts, ','); + + nm_str_buf_append(&strbuf_hosts, + nm_utils_inet_ntop(addr_family, g_inet_address_to_bytes(a), str_addr)); + } + + g_list_free_full(list, g_object_unref); + + if (strbuf_hosts.len == 0) { + _LOG2D("system resolver returned no usable IPv%c addresses", + nm_utils_addr_family_to_char(cb_data->addr_family)); + cb_data_complete(cb_data, NM_CONNECTIVITY_LIMITED, "resolve-error"); + return; + } + + do_curl_request(cb_data, nm_str_buf_get_str(&strbuf_hosts)); +} + +static void +system_resolver_resolve(NMConnectivityCheckHandle *cb_data) +{ + gs_unref_object GResolver *resolver = NULL; + + _LOG2D("start request to '%s' (try resolving '%s' using system resolver)", + cb_data->concheck.con_config->uri, + cb_data->concheck.con_config->host); + + resolver = g_resolver_get_default(); + + g_resolver_lookup_by_name_async(resolver, + cb_data->concheck.con_config->host, + cb_data->concheck.resolve_cancellable, + system_resolver_resolve_cb, + cb_data); +} + +static void +systemd_resolved_resolve_cb(GObject *object, GAsyncResult *res, gpointer user_data) { NMConnectivityCheckHandle *cb_data; gs_unref_variant GVariant *result = NULL; @@ -715,17 +879,24 @@ resolve_cb(GObject *object, GAsyncResult *res, gpointer user_data) nm_auto_str_buf NMStrBuf strbuf_hosts = NM_STR_BUF_INIT(0, FALSE); result = g_dbus_connection_call_finish(G_DBUS_CONNECTION(object), res, &error); - if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + if (nm_utils_error_is_cancelled(error)) return; cb_data = user_data; - g_clear_object(&cb_data->concheck.resolve_cancellable); - if (!result) { - /* Never mind. Just let do curl do its own resolving. */ + gs_free char *dbus_error = NULL; + _LOG2D("can't resolve a name via systemd-resolved: %s", error->message); - do_curl_request(cb_data); + + dbus_error = g_dbus_error_get_remote_error(error); + if (nm_streq0(dbus_error, "org.freedesktop.resolve1.NoNameServers")) { + cb_data_complete(cb_data, NM_CONNECTIVITY_LIMITED, "resolve-error"); + return; + } + + /* Never mind. Fallback to the system resolver. */ + system_resolver_resolve(cb_data); return; } @@ -759,14 +930,14 @@ resolve_cb(GObject *object, GAsyncResult *res, gpointer user_data) nm_str_buf_append(&strbuf_hosts, nm_utils_inet_ntop(addr_family, address_buf, str_addr)); } - if (strbuf_hosts.len > 0) { - const char *s = nm_str_buf_get_str(&strbuf_hosts); - - cb_data->concheck.hosts = curl_slist_append(NULL, s); - _LOG2T("set curl resolve list to '%s'", s); + if (strbuf_hosts.len == 0) { + _LOG2D("systemd-resolve returned no usable IPv%c addresses", + nm_utils_addr_family_to_char(cb_data->addr_family)); + cb_data_complete(cb_data, NM_CONNECTIVITY_LIMITED, "resolve-error"); + return; } - do_curl_request(cb_data); + do_curl_request(cb_data, nm_str_buf_get_str(&strbuf_hosts)); } #endif @@ -892,6 +1063,8 @@ nm_connectivity_check_start(NMConnectivity *self, } } + cb_data->concheck.resolve_cancellable = g_cancellable_new(); + /* note that we pick up support for systemd-resolved right away when we need it. * We don't need to remember the setting, because we can (cheaply) check anew * on each request. @@ -927,8 +1100,6 @@ nm_connectivity_check_start(NMConnectivity *self, return cb_data; } - cb_data->concheck.resolve_cancellable = g_cancellable_new(); - g_dbus_connection_call(dbus_connection, "org.freedesktop.resolve1", "/org/freedesktop/resolve1", @@ -943,17 +1114,15 @@ nm_connectivity_check_start(NMConnectivity *self, G_DBUS_CALL_FLAGS_NONE, -1, cb_data->concheck.resolve_cancellable, - resolve_cb, + systemd_resolved_resolve_cb, cb_data); _LOG2D("start request to '%s' (try resolving '%s' using systemd-resolved)", cb_data->concheck.con_config->uri, cb_data->concheck.con_config->host); - } else { - _LOG2D("start request to '%s' (systemd-resolved not available)", - cb_data->concheck.con_config->uri); - do_curl_request(cb_data); + return cb_data; } + system_resolver_resolve(cb_data); return cb_data; } #endif diff --git a/src/core/nm-core-utils.c b/src/core/nm-core-utils.c index e05638e4..c8b789b3 100644 --- a/src/core/nm-core-utils.c +++ b/src/core/nm-core-utils.c @@ -30,6 +30,7 @@ #include "libnm-glib-aux/nm-secret-utils.h" #include "libnm-glib-aux/nm-time-utils.h" #include "libnm-glib-aux/nm-str-buf.h" +#include "libnm-systemd-shared/nm-sd-utils-shared.h" #include "nm-utils.h" #include "libnm-core-intern/nm-core-internal.h" #include "nm-setting-connection.h" @@ -2692,8 +2693,9 @@ _host_id_read_timestamp(gboolean use_secret_key_file, * timestamp. It is wrong to worry about using a fake timestamp (which is tied to * the secret_key) if we are unable to access the secret_key file in the first place. * - * Pick a random timestamp from the past two years. Yes, this timestamp - * is not stable across restarts, but apparently neither is the host-id + * Pick a timestamp from the past two years, by using a generated timespan + * by hashing the host-id. Yes, this timestamp counts back from @now, and is + * thus not stable across restarts. But apparently neither is the host-id * nor the secret_key itself. */ #define EPOCH_TWO_YEARS (G_GINT64_CONSTANT(2 * 365 * 24 * 3600) * NM_UTILS_NSEC_PER_SEC) @@ -2874,9 +2876,15 @@ out: typedef struct { guint8 *host_id; gsize host_id_len; - gint64 timestamp_ns; - bool is_good : 1; - bool timestamp_is_good : 1; + + /* The timestamp (in nsec since the Epoch) returned by nm_utils_host_id_get_timestamp_nsec(). + * It is associated with the host (and the host-id). We currently use this for the LLT DUID + * generation for IPv6. Instead of persisting the timestamp separately to disk, we re-use the + * file timestamp of the secret_key file. */ + gint64 timestamp_nsec; + + bool is_good : 1; + bool timestamp_is_good : 1; } HostIdData; static const HostIdData *volatile host_id_static; @@ -2900,7 +2908,7 @@ again: host_id_data.timestamp_is_good = _host_id_read_timestamp(host_id_data.is_good, host_id_data.host_id, host_id_data.host_id_len, - &host_id_data.timestamp_ns); + &host_id_data.timestamp_nsec); if (!host_id_data.timestamp_is_good && host_id_data.is_good) nm_log_warn(LOGD_CORE, "secret-key: failure reading host timestamp (use fake one)"); @@ -2939,9 +2947,9 @@ nm_utils_host_id_get(const guint8 **out_host_id, gsize *out_host_id_len) } gint64 -nm_utils_host_id_get_timestamp_ns(void) +nm_utils_host_id_get_timestamp_nsec(void) { - return _host_id_get()->timestamp_ns; + return _host_id_get()->timestamp_nsec; } static GArray *nmtst_host_id_stack = NULL; @@ -2952,7 +2960,7 @@ void nmtst_utils_host_id_push(const guint8 *host_id, gssize host_id_len, gboolean is_good, - const gint64 *timestamp_ns) + const gint64 *p_timestamp_nsec) { NM_G_MUTEX_LOCKED(&nmtst_host_id_lock); gs_free char *str1_to_free = NULL; @@ -2971,8 +2979,8 @@ nmtst_utils_host_id_push(const guint8 *host_id, &str1_to_free), (gsize) host_id_len, !!is_good, - timestamp_ns ? *timestamp_ns : 0, - timestamp_ns ? "" : " (not-good)"); + p_timestamp_nsec ? *p_timestamp_nsec : 0, + p_timestamp_nsec ? "" : " (not-good)"); if (!nmtst_host_id_stack) { nmtst_host_id_stack = g_array_new(FALSE, FALSE, sizeof(HostIdData)); @@ -2984,9 +2992,9 @@ nmtst_utils_host_id_push(const guint8 *host_id, *h = (HostIdData){ .host_id = nm_memdup(host_id, host_id_len), .host_id_len = host_id_len, - .timestamp_ns = timestamp_ns ? *timestamp_ns : 0, + .timestamp_nsec = p_timestamp_nsec ? *p_timestamp_nsec : 0, .is_good = is_good, - .timestamp_is_good = !!timestamp_ns, + .timestamp_is_good = !!p_timestamp_nsec, }; g_atomic_pointer_set(&host_id_static, h); @@ -3342,8 +3350,13 @@ nm_utils_stable_id_generated_complete(const char *stable_id_generated) static void _stable_id_append(GString *str, const char *substitution) { - if (!substitution) + if (!substitution) { + /* Would have been nicer to append "=NIL;" to differentiate between + * empty and NULL. + * + * Can't do that now, as it would change behavior. */ substitution = ""; + } g_string_append_printf(str, "=%zu{%s}", strlen(substitution), substitution); } @@ -3413,7 +3426,7 @@ nm_utils_stable_id_parse(const char *stable_id, ({ \ gboolean _match = FALSE; \ \ - if (g_str_has_prefix(&stable_id[i], "" prefix "")) { \ + if (NM_STR_HAS_PREFIX(&stable_id[i], "" prefix "")) { \ _match = TRUE; \ if (!str) \ str = g_string_sized_new(256); \ @@ -5201,3 +5214,50 @@ again: return g; } + +/*****************************************************************************/ + +/** + * nm_utils_shorten_hostname: + * @hostname: the input hostname + * @shortened: (out) (transfer full): on return, the shortened hostname + * + * Checks whether the input hostname is valid. If not, tries to shorten it + * to HOST_NAME_MAX or to the first dot, whatever comes earlier. + * The new hostname is returned in @shortened. + * + * Returns: %TRUE if the input hostname was already valid or if was shortened + * successfully; %FALSE otherwise + */ +gboolean +nm_utils_shorten_hostname(const char *hostname, char **shortened) +{ + gs_free char *s = NULL; + const char *dot; + gsize l; + + nm_assert(hostname); + nm_assert(shortened); + + if (nm_sd_hostname_is_valid(hostname, FALSE)) { + *shortened = NULL; + return TRUE; + } + + dot = strchr(hostname, '.'); + if (dot) + l = (dot - hostname); + else + l = strlen(hostname); + l = MIN(l, (gsize) HOST_NAME_MAX); + + s = g_strndup(hostname, l); + + if (!nm_sd_hostname_is_valid(s, FALSE)) { + *shortened = NULL; + return FALSE; + } + + *shortened = g_steal_pointer(&s); + return TRUE; +} diff --git a/src/core/nm-core-utils.h b/src/core/nm-core-utils.h index 7079ab2f..d1a62a60 100644 --- a/src/core/nm-core-utils.h +++ b/src/core/nm-core-utils.h @@ -233,6 +233,7 @@ void nm_utils_log_connection_diff(NMConnection *connection, const char *dbus_path); gboolean nm_utils_is_specific_hostname(const char *name); +gboolean nm_utils_shorten_hostname(const char *hostname, char **shortened); struct _NMUuid; @@ -246,7 +247,7 @@ const char *nm_utils_proc_cmdline(void); const char *const *nm_utils_proc_cmdline_split(void); gboolean nm_utils_host_id_get(const guint8 **out_host_id, gsize *out_host_id_len); -gint64 nm_utils_host_id_get_timestamp_ns(void); +gint64 nm_utils_host_id_get_timestamp_nsec(void); void nmtst_utils_host_id_push(const guint8 *host_id, gssize host_id_len, diff --git a/src/core/nm-dbus-manager.c b/src/core/nm-dbus-manager.c index 2c5f7ace..7fcbf6ca 100644 --- a/src/core/nm-dbus-manager.c +++ b/src/core/nm-dbus-manager.c @@ -1082,6 +1082,21 @@ nm_dbus_manager_lookup_object(NMDBusManager *self, const char *path) return obj; } +gpointer +nm_dbus_manager_lookup_object_with_type(NMDBusManager *self, GType gtype, const char *path) +{ + gpointer ptr; + + nm_assert(g_type_is_a(gtype, NM_TYPE_DBUS_OBJECT)); + nm_assert(gtype != NM_TYPE_DBUS_OBJECT); + + ptr = nm_dbus_manager_lookup_object(self, path); + if (!ptr || !G_TYPE_CHECK_INSTANCE_TYPE(ptr, gtype)) + return NULL; + + return ptr; +} + void _nm_dbus_manager_obj_export(NMDBusObject *obj) { diff --git a/src/core/nm-dbus-manager.h b/src/core/nm-dbus-manager.h index d7ca78d1..d977f99f 100644 --- a/src/core/nm-dbus-manager.h +++ b/src/core/nm-dbus-manager.h @@ -52,6 +52,9 @@ gboolean nm_dbus_manager_is_stopping(NMDBusManager *self); gpointer nm_dbus_manager_lookup_object(NMDBusManager *self, const char *path); +gpointer +nm_dbus_manager_lookup_object_with_type(NMDBusManager *self, GType gtype, const char *path); + void _nm_dbus_manager_obj_export(NMDBusObject *obj); void _nm_dbus_manager_obj_unexport(NMDBusObject *obj); void diff --git a/src/core/nm-firewall-utils.c b/src/core/nm-firewall-utils.c index ddac1137..8fa8059e 100644 --- a/src/core/nm-firewall-utils.c +++ b/src/core/nm-firewall-utils.c @@ -422,7 +422,7 @@ _fw_nft_call_communicate_cb(GObject *source, GAsyncResult *result, gpointer user nm_g_main_context_push_thread_default_if_necessary(NULL); nm_shutdown_wait_obj_register_object(call_data->subprocess, "nft-terminate"); - G_STATIC_ASSERT_EXPR(200 < NM_SHUTDOWN_TIMEOUT_MS_WATCHDOG * 2 / 3); + G_STATIC_ASSERT_EXPR(200 < NM_SHUTDOWN_TIMEOUT_ADDITIONAL_MSEC * 2 / 3); nm_g_subprocess_terminate_in_background(call_data->subprocess, 200); } } else if (g_subprocess_get_successful(call_data->subprocess)) { @@ -546,7 +546,7 @@ _fw_nft_call(GBytes *stdin_buf, call_data); call_data->timeout_source = - nm_g_source_attach(nm_g_timeout_source_new((NM_SHUTDOWN_TIMEOUT_MS * 2) / 3, + nm_g_source_attach(nm_g_timeout_source_new((NM_SHUTDOWN_TIMEOUT_1500_MSEC * 2) / 3, G_PRIORITY_DEFAULT, _fw_nft_call_timeout_cb, call_data, diff --git a/src/core/nm-l3-config-data.c b/src/core/nm-l3-config-data.c index 03593ea2..5ab2f6b8 100644 --- a/src/core/nm-l3-config-data.c +++ b/src/core/nm-l3-config-data.c @@ -349,7 +349,7 @@ nm_l3_config_data_log(const NML3ConfigData *self, NMLogLevel log_level, NMLogDomain log_domain) { - char sbuf[sizeof(_nm_utils_to_string_buffer)]; + char sbuf[NM_UTILS_TO_STRING_BUFFER_SIZE]; char sbuf_addr[NM_UTILS_INET_ADDRSTRLEN]; int IS_IPv4; guint i; @@ -1172,13 +1172,6 @@ _l3_config_data_add_obj(NMDedupMultiIndex *multi_idx, modified = TRUE; } - /* OR assume_config_once flag */ - if (obj_new->ip_address.a_assume_config_once - && !obj_old->ip_address.a_assume_config_once) { - obj_new = nmp_object_stackinit_obj(&obj_new_stackinit, obj_new); - obj_new_stackinit.ip_address.a_assume_config_once = TRUE; - modified = TRUE; - } break; case NMP_OBJECT_TYPE_IP4_ROUTE: case NMP_OBJECT_TYPE_IP6_ROUTE: @@ -1189,13 +1182,6 @@ _l3_config_data_add_obj(NMDedupMultiIndex *multi_idx, modified = TRUE; } - /* OR assume_config_once flag */ - if (obj_new->ip_route.r_assume_config_once - && !obj_old->ip_route.r_assume_config_once) { - obj_new = nmp_object_stackinit_obj(&obj_new_stackinit, obj_new); - obj_new_stackinit.ip_route.r_assume_config_once = TRUE; - modified = TRUE; - } break; default: nm_assert_not_reached(); @@ -3056,9 +3042,8 @@ nm_l3_config_data_merge(NML3ConfigData *self, const NMPlatformIPAddress *a_src = NMP_OBJECT_CAST_IP_ADDRESS(obj); NMPlatformIPXAddress a; NML3ConfigMergeHookResult hook_result = { - .ip4acd_not_ready = NM_OPTION_BOOL_DEFAULT, - .assume_config_once = NM_OPTION_BOOL_DEFAULT, - .force_commit = NM_OPTION_BOOL_DEFAULT, + .ip4acd_not_ready = NM_OPTION_BOOL_DEFAULT, + .force_commit = NM_OPTION_BOOL_DEFAULT, }; #define _ensure_a() \ @@ -3091,12 +3076,6 @@ nm_l3_config_data_merge(NML3ConfigData *self, a.a4.a_acd_not_ready = (!!hook_result.ip4acd_not_ready); } - if (hook_result.assume_config_once != NM_OPTION_BOOL_DEFAULT - && (!!hook_result.assume_config_once) != a_src->a_assume_config_once) { - _ensure_a(); - a.ax.a_assume_config_once = (!!hook_result.assume_config_once); - } - if (hook_result.force_commit != NM_OPTION_BOOL_DEFAULT && (!!hook_result.force_commit) != a_src->a_force_commit) { _ensure_a(); @@ -3121,9 +3100,8 @@ nm_l3_config_data_merge(NML3ConfigData *self, const NMPlatformIPRoute *r_src = NMP_OBJECT_CAST_IP_ROUTE(obj); NMPlatformIPXRoute r; NML3ConfigMergeHookResult hook_result = { - .ip4acd_not_ready = NM_OPTION_BOOL_DEFAULT, - .assume_config_once = NM_OPTION_BOOL_DEFAULT, - .force_commit = NM_OPTION_BOOL_DEFAULT, + .ip4acd_not_ready = NM_OPTION_BOOL_DEFAULT, + .force_commit = NM_OPTION_BOOL_DEFAULT, }; #define _ensure_r() \ @@ -3149,12 +3127,6 @@ nm_l3_config_data_merge(NML3ConfigData *self, r.rx.ifindex = self->ifindex; } - if (hook_result.assume_config_once != NM_OPTION_BOOL_DEFAULT - && (!!hook_result.assume_config_once) != r_src->r_assume_config_once) { - _ensure_r(); - r.rx.r_assume_config_once = (!!hook_result.assume_config_once); - } - if (hook_result.force_commit != NM_OPTION_BOOL_DEFAULT && (!!hook_result.force_commit) != r_src->r_force_commit) { _ensure_r(); diff --git a/src/core/nm-l3-config-data.h b/src/core/nm-l3-config-data.h index b7a1bb32..20a32c62 100644 --- a/src/core/nm-l3-config-data.h +++ b/src/core/nm-l3-config-data.h @@ -137,7 +137,6 @@ NML3ConfigData *nm_l3_config_data_new_from_platform(NMDedupMultiIndex *mu typedef struct { NMOptionBool ip4acd_not_ready; - NMOptionBool assume_config_once; NMOptionBool force_commit; } NML3ConfigMergeHookResult; diff --git a/src/core/nm-l3-ipv4ll.c b/src/core/nm-l3-ipv4ll.c index 68cb17fb..2aedab56 100644 --- a/src/core/nm-l3-ipv4ll.c +++ b/src/core/nm-l3-ipv4ll.c @@ -600,7 +600,7 @@ _l3cd_config_add(NML3IPv4LL *self) nm_assert_not_reached(); self->l3cfg_commit_handle = nm_l3cfg_commit_type_register(self->l3cfg, - NM_L3_CFG_COMMIT_TYPE_ASSUME, + NM_L3_CFG_COMMIT_TYPE_UPDATE, self->l3cfg_commit_handle, "ipv4ll"); nm_l3cfg_commit_on_idle_schedule(self->l3cfg, NM_L3_CFG_COMMIT_TYPE_AUTO); @@ -748,12 +748,8 @@ _ipv4ll_set_timed_out_update(NML3IPv4LL *self, TimedOutState new_state) if (self->timed_out_expiry_msec == 0 || self->timed_out_expiry_msec < expiry_msec) { self->timed_out_expiry_msec = expiry_msec; nm_clear_g_source_inst(&self->timed_out_source); - self->timed_out_source = nm_g_timeout_source_new(timeout_msec, - G_PRIORITY_DEFAULT, - _ipv4ll_set_timed_out_timeout_cb, - self, - NULL); - g_source_attach(self->timed_out_source, NULL); + self->timed_out_source = + nm_g_timeout_add_source(timeout_msec, _ipv4ll_set_timed_out_timeout_cb, self); } break; } @@ -922,8 +918,7 @@ _ipv4ll_state_change_on_idle(NML3IPv4LL *self) if (!self->state_change_on_idle_source) { self->state_change_on_idle_source = - nm_g_idle_source_new(G_PRIORITY_DEFAULT, _ipv4ll_state_change_on_idle_cb, self, NULL); - g_source_attach(self->state_change_on_idle_source, NULL); + nm_g_idle_add_source(_ipv4ll_state_change_on_idle_cb, self); } } diff --git a/src/core/nm-l3-ipv6ll.c b/src/core/nm-l3-ipv6ll.c index 60da4ee8..2b9a1a0e 100644 --- a/src/core/nm-l3-ipv6ll.c +++ b/src/core/nm-l3-ipv6ll.c @@ -398,10 +398,7 @@ _lladdr_handle_changed(NML3IPv6LL *self) * NML3IPv4LL, where we use NM_L3_CONFIG_MERGE_FLAGS_ONLY_FOR_ACD. The difference * is that for IPv6 we let kernel do DAD, so we need to actually configure the * address. For IPv4, we can run ACD without configuring anything in kernel, - * and let the user decide how to proceed. - * - * Also in this case, we use the most graceful commit-type (NM_L3_CFG_COMMIT_TYPE_ASSUME), - * but for that to work, we also need NM_L3CFG_CONFIG_FLAGS_ASSUME_CONFIG_ONCE flag. */ + * and let the user decide how to proceed. */ l3cd = nm_l3_ipv6ll_get_l3cd(self); @@ -421,7 +418,7 @@ _lladdr_handle_changed(NML3IPv6LL *self) NM_DNS_PRIORITY_DEFAULT_NORMAL, NM_L3_ACD_DEFEND_TYPE_ALWAYS, 0, - NM_L3CFG_CONFIG_FLAGS_ASSUME_CONFIG_ONCE, + NM_L3CFG_CONFIG_FLAGS_NONE, NM_L3_CONFIG_MERGE_FLAGS_NONE)) changed = TRUE; } else { @@ -430,7 +427,7 @@ _lladdr_handle_changed(NML3IPv6LL *self) } self->l3cfg_commit_handle = nm_l3cfg_commit_type_register(self->l3cfg, - l3cd ? NM_L3_CFG_COMMIT_TYPE_ASSUME + l3cd ? NM_L3_CFG_COMMIT_TYPE_UPDATE : NM_L3_CFG_COMMIT_TYPE_NONE, self->l3cfg_commit_handle, "ipv6ll"); diff --git a/src/core/nm-l3cfg.c b/src/core/nm-l3cfg.c index eeb041d0..6b7e6f4b 100644 --- a/src/core/nm-l3cfg.c +++ b/src/core/nm-l3cfg.c @@ -363,7 +363,6 @@ static NM_UTILS_ENUM2STR_DEFINE(_l3_cfg_commit_type_to_string, NML3CfgCommitType, NM_UTILS_ENUM2STR(NM_L3_CFG_COMMIT_TYPE_AUTO, "auto"), NM_UTILS_ENUM2STR(NM_L3_CFG_COMMIT_TYPE_NONE, "none"), - NM_UTILS_ENUM2STR(NM_L3_CFG_COMMIT_TYPE_ASSUME, "assume"), NM_UTILS_ENUM2STR(NM_L3_CFG_COMMIT_TYPE_UPDATE, "update"), NM_UTILS_ENUM2STR(NM_L3_CFG_COMMIT_TYPE_REAPPLY, "reapply"), ); @@ -585,7 +584,7 @@ _l3_config_notify_data_to_string(const NML3ConfigNotifyData *notify_data, void _nm_l3cfg_emit_signal_notify(NML3Cfg *self, const NML3ConfigNotifyData *notify_data) { - char sbuf[sizeof(_nm_utils_to_string_buffer)]; + char sbuf[NM_UTILS_TO_STRING_BUFFER_SIZE]; nm_assert(notify_data); nm_assert(_NM_INT_NOT_NEGATIVE(notify_data->notify_type)); @@ -768,14 +767,6 @@ _nm_n_acd_data_probe_new(NML3Cfg *self, in_addr_t addr, guint32 timeout_msec, gp } \ G_STMT_END -static gboolean -_obj_state_data_get_assume_config_once(const ObjStateData *obj_state) -{ - nm_assert_obj_state(NULL, obj_state); - - return nmp_object_get_assume_config_once(obj_state->obj); -} - static ObjStateData * _obj_state_data_new(const NMPObject *obj, const NMPObject *plobj) { @@ -885,7 +876,7 @@ _obj_state_data_update(ObjStateData *obj_state, const NMPObject *obj) static void _obj_states_externally_removed_track(NML3Cfg *self, const NMPObject *obj, gboolean in_platform) { - char sbuf[sizeof(_nm_utils_to_string_buffer)]; + char sbuf[NM_UTILS_TO_STRING_BUFFER_SIZE]; ObjStateData *obj_state; nm_assert(NM_IS_L3CFG(self)); @@ -946,7 +937,7 @@ _obj_states_update_all(NML3Cfg *self) NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE, }; - char sbuf[sizeof(_nm_utils_to_string_buffer)]; + char sbuf[NM_UTILS_TO_STRING_BUFFER_SIZE]; ObjStateData *obj_state; int i; gboolean any_dirty = FALSE; @@ -1037,7 +1028,7 @@ typedef struct { static gboolean _obj_states_sync_filter(NML3Cfg *self, const NMPObject *obj, NML3CfgCommitType commit_type) { - char sbuf[sizeof(_nm_utils_to_string_buffer)]; + char sbuf[NM_UTILS_TO_STRING_BUFFER_SIZE]; NMPObjectType obj_type; ObjStateData *obj_state; @@ -1054,10 +1045,6 @@ _obj_states_sync_filter(NML3Cfg *self, const NMPObject *obj, NML3CfgCommitType c nm_assert(c_list_is_empty(&obj_state->os_zombie_lst)); if (!obj_state->os_nm_configured) { - if (commit_type == NM_L3_CFG_COMMIT_TYPE_ASSUME - && !_obj_state_data_get_assume_config_once(obj_state)) - return FALSE; - obj_state->os_nm_configured = TRUE; _LOGD("obj-state: configure-first-time: %s", @@ -1152,7 +1139,7 @@ _obj_state_zombie_lst_get_prune_lists(NML3Cfg *self, const int IS_IPv4 = NM_IS_IPv4(addr_family); const NMPObjectType obj_type_route = NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4); const NMPObjectType obj_type_address = NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4); - char sbuf[sizeof(_nm_utils_to_string_buffer)]; + char sbuf[NM_UTILS_TO_STRING_BUFFER_SIZE]; ObjStateData *obj_state; ObjStateData *obj_state_safe; @@ -1198,7 +1185,7 @@ _obj_state_zombie_lst_get_prune_lists(NML3Cfg *self, static void _obj_state_zombie_lst_prune_all(NML3Cfg *self, int addr_family) { - char sbuf[sizeof(_nm_utils_to_string_buffer)]; + char sbuf[NM_UTILS_TO_STRING_BUFFER_SIZE]; ObjStateData *obj_state; ObjStateData *obj_state_safe; @@ -1743,9 +1730,7 @@ again: n_acd_get_fd(self->priv.p->nacd, &fd); - self->priv.p->nacd_source = - nm_g_unix_fd_source_new(fd, G_IO_IN, G_PRIORITY_DEFAULT, _l3_acd_nacd_event, self, NULL); - nm_g_source_attach(self->priv.p->nacd_source, NULL); + self->priv.p->nacd_source = nm_g_unix_fd_add_source(fd, G_IO_IN, _l3_acd_nacd_event, self); NM_SET_OUT(out_acd_not_supported, FALSE); return self->priv.p->nacd; @@ -3088,7 +3073,6 @@ nm_l3cfg_commit_on_idle_schedule(NML3Cfg *self, NML3CfgCommitType commit_type) nm_assert(NM_IS_L3CFG(self)); nm_assert(NM_IN_SET(commit_type, NM_L3_CFG_COMMIT_TYPE_AUTO, - NM_L3_CFG_COMMIT_TYPE_ASSUME, NM_L3_CFG_COMMIT_TYPE_UPDATE, NM_L3_CFG_COMMIT_TYPE_REAPPLY)); @@ -3503,7 +3487,6 @@ out_clear: typedef struct { NML3Cfg *self; gconstpointer tag; - bool assume_config_once; bool to_commit; bool force_commit_once; } L3ConfigMergeHookAddObjData; @@ -3523,11 +3506,9 @@ _l3_hook_add_obj_cb(const NML3ConfigData *l3cd, nm_assert(obj); nm_assert(hook_result); nm_assert(hook_result->ip4acd_not_ready == NM_OPTION_BOOL_DEFAULT); - nm_assert(hook_result->assume_config_once == NM_OPTION_BOOL_DEFAULT); nm_assert(hook_result->force_commit == NM_OPTION_BOOL_DEFAULT); - hook_result->assume_config_once = hook_data->assume_config_once; - hook_result->force_commit = hook_data->force_commit_once; + hook_result->force_commit = hook_data->force_commit_once; switch (NMP_OBJECT_GET_TYPE(obj)) { case NMP_OBJECT_TYPE_IP4_ADDRESS: @@ -3683,9 +3664,7 @@ _l3cfg_update_combined_config(NML3Cfg *self, if (NM_FLAGS_HAS(l3cd_data->config_flags, NM_L3CFG_CONFIG_FLAGS_ONLY_FOR_ACD)) continue; - hook_data.tag = l3cd_data->tag_confdata; - hook_data.assume_config_once = - NM_FLAGS_HAS(l3cd_data->config_flags, NM_L3CFG_CONFIG_FLAGS_ASSUME_CONFIG_ONCE); + hook_data.tag = l3cd_data->tag_confdata; hook_data.force_commit_once = l3cd_data->force_commit_once; nm_l3_config_data_merge(l3cd, @@ -3859,7 +3838,7 @@ _routes_temporary_not_available_update(NML3Cfg *self, for (i = 0; i < routes_temporary_not_available_arr->len; i++) { const NMPObject *o = routes_temporary_not_available_arr->pdata[i]; - char sbuf[sizeof(_nm_utils_to_string_buffer)]; + char sbuf[NM_UTILS_TO_STRING_BUFFER_SIZE]; nm_assert(NMP_OBJECT_GET_TYPE(o) == NMP_OBJECT_TYPE_IP_ROUTE(NM_IS_IPv4(addr_family))); @@ -4212,8 +4191,7 @@ _l3_commit_one(NML3Cfg *self, nm_assert(NM_IN_SET(commit_type, NM_L3_CFG_COMMIT_TYPE_NONE, NM_L3_CFG_COMMIT_TYPE_REAPPLY, - NM_L3_CFG_COMMIT_TYPE_UPDATE, - NM_L3_CFG_COMMIT_TYPE_ASSUME)); + NM_L3_CFG_COMMIT_TYPE_UPDATE)); nm_assert_addr_family(addr_family); _LOGT("committing IPv%c configuration (%s)", @@ -4299,7 +4277,6 @@ _l3_commit(NML3Cfg *self, NML3CfgCommitType commit_type, gboolean is_idle) nm_assert(NM_IN_SET(commit_type, NM_L3_CFG_COMMIT_TYPE_NONE, NM_L3_CFG_COMMIT_TYPE_AUTO, - NM_L3_CFG_COMMIT_TYPE_ASSUME, NM_L3_CFG_COMMIT_TYPE_UPDATE, NM_L3_CFG_COMMIT_TYPE_REAPPLY)); nm_assert(self->priv.p->commit_reentrant_count == 0); @@ -4423,10 +4400,7 @@ nm_l3cfg_commit_type_register(NML3Cfg *self, char buf[64]; nm_assert(NM_IS_L3CFG(self)); - nm_assert(NM_IN_SET(commit_type, - NM_L3_CFG_COMMIT_TYPE_NONE, - NM_L3_CFG_COMMIT_TYPE_ASSUME, - NM_L3_CFG_COMMIT_TYPE_UPDATE)); + nm_assert(NM_IN_SET(commit_type, NM_L3_CFG_COMMIT_TYPE_NONE, NM_L3_CFG_COMMIT_TYPE_UPDATE)); /* It would be easy (and maybe convenient) to allow that @existing_handle * can currently be registered on another NML3Cfg instance. But then we couldn't diff --git a/src/core/nm-l3cfg.h b/src/core/nm-l3cfg.h index 0ea68646..f6ec39ce 100644 --- a/src/core/nm-l3cfg.h +++ b/src/core/nm-l3cfg.h @@ -363,15 +363,6 @@ typedef enum _nm_packed { /* Don't touch the interface. */ NM_L3_CFG_COMMIT_TYPE_NONE, - /* ASSUME means to keep any pre-existing extra routes/addresses, while - * also not adding routes/addresses that are not present yet. This is to - * gracefully take over after restart, where the existing IP configuration - * should not change. - * - * The flag NM_L3CFG_CONFIG_FLAGS_ASSUME_CONFIG_ONCE can make certain addresses/ - * routes commitable also during "assume". */ - NM_L3_CFG_COMMIT_TYPE_ASSUME, - /* UPDATE means to add new addresses/routes, while also removing addresses/routes * that are no longer present (but were previously configured by NetworkManager). * Routes/addresses that were removed externally won't be re-added, and routes/addresses diff --git a/src/core/nm-manager.c b/src/core/nm-manager.c index 6c73d237..52153697 100644 --- a/src/core/nm-manager.c +++ b/src/core/nm-manager.c @@ -54,15 +54,18 @@ /*****************************************************************************/ typedef struct { - gboolean user_enabled; - gboolean sw_enabled; - gboolean hw_enabled; - RfKillType rtype; + guint prop_id; + guint hw_prop_id; NMConfigRunStatePropertyType key; - const char *desc; - const char *prop; - const char *hw_prop; -} RadioState; +} RfkillTypeDesc; + +typedef struct { + bool available : 1; + bool user_enabled : 1; + bool sw_enabled : 1; + bool hw_enabled : 1; + bool os_owner : 1; +} RfkillRadioState; typedef enum { ASYNC_OP_TYPE_AC_AUTH_ACTIVATE_INTERNAL, @@ -120,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, @@ -169,7 +173,8 @@ typedef struct { NMSettings *settings; - RadioState radio_states[RFKILL_TYPE_MAX]; + RfkillRadioState radio_states[NM_RFKILL_TYPE_MAX]; + NMVpnManager *vpn_manager; NMSleepMonitor *sleep_monitor; @@ -190,6 +195,8 @@ typedef struct { guint devices_inited_id; + guint radio_flags; + NMConnectivityState connectivity_state; guint8 device_state_prune_ratelimit_count; @@ -393,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); @@ -1156,8 +1165,10 @@ active_connection_get_by_path(NMManager *self, const char *path) NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); NMActiveConnection *ac; - ac = nm_dbus_manager_lookup_object(nm_dbus_object_get_manager(NM_DBUS_OBJECT(self)), path); - if (!ac || !NM_IS_ACTIVE_CONNECTION(ac) || c_list_is_empty(&ac->active_connections_lst)) + ac = nm_dbus_manager_lookup_object_with_type(nm_dbus_object_get_manager(NM_DBUS_OBJECT(self)), + NM_TYPE_ACTIVE_CONNECTION, + path); + if (!ac || c_list_is_empty(&ac->active_connections_lst)) return NULL; nm_assert(c_list_contains(&priv->active_connections_lst_head, &ac->active_connections_lst)); @@ -1289,8 +1300,11 @@ nm_manager_get_device_by_path(NMManager *self, const char *path) g_return_val_if_fail(path, NULL); - device = nm_dbus_manager_lookup_object(nm_dbus_object_get_manager(NM_DBUS_OBJECT(self)), path); - if (!device || !NM_IS_DEVICE(device) || c_list_is_empty(&device->devices_lst)) + device = + nm_dbus_manager_lookup_object_with_type(nm_dbus_object_get_manager(NM_DBUS_OBJECT(self)), + NM_TYPE_DEVICE, + path); + if (!device || c_list_is_empty(&device->devices_lst)) return NULL; nm_assert(c_list_contains(&priv->devices_lst_head, &device->devices_lst)); @@ -1637,6 +1651,9 @@ check_if_startup_complete(NMManager *self) return; } + /* Most of our logging is not API/stable, but this line is kinda important and + * what people will look for when debugging NetworkManager-wait-online.service. + * Take care before rewording this message. */ _LOGI(LOGD_CORE, "startup complete"); priv->startup = FALSE; @@ -1704,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, @@ -1744,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; @@ -2276,39 +2298,104 @@ _static_hostname_changed_cb(NMHostnameManager *hostname_manager, GParamSpec *psp } /*****************************************************************************/ -/* General NMManager stuff */ -/*****************************************************************************/ + +static const RfkillTypeDesc _rfkill_type_desc[NM_RFKILL_TYPE_MAX] = { + [NM_RFKILL_TYPE_WLAN] = + { + .prop_id = PROP_WIRELESS_ENABLED, + .hw_prop_id = PROP_WIRELESS_HARDWARE_ENABLED, + .key = NM_CONFIG_STATE_PROPERTY_WIFI_ENABLED, + }, + [NM_RFKILL_TYPE_WWAN] = + { + .prop_id = PROP_WWAN_ENABLED, + .hw_prop_id = PROP_WWAN_HARDWARE_ENABLED, + .key = NM_CONFIG_STATE_PROPERTY_WWAN_ENABLED, + }, +}; static gboolean -radio_enabled_for_rstate(RadioState *rstate, gboolean check_changeable) +_rfkill_radio_state_get_enabled(const RfkillRadioState *rstate, gboolean check_changeable) { gboolean enabled; + /* If the device is not owned by the os, hw_enabled will be FALSE, hence + * we don't need to consider os_owner here. + */ enabled = rstate->user_enabled && rstate->hw_enabled; if (check_changeable) enabled &= rstate->sw_enabled; return enabled; } +static void +_rfkill_radio_state_set_from_manager(NMManager *self, NMRfkillType rtype, RfkillRadioState *rstate) +{ + 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; + return; + } + nm_assert_not_reached(); +} + static gboolean -radio_enabled_for_type(NMManager *self, RfKillType rtype, gboolean check_changeable) +_rfkill_radio_state_get(NMManager *self, NMRfkillType rtype) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); - return radio_enabled_for_rstate(&priv->radio_states[rtype], check_changeable); + nm_assert(_NM_INT_NOT_NEGATIVE(rtype) && rtype < G_N_ELEMENTS(priv->radio_states)); + + return _rfkill_radio_state_get_enabled(&priv->radio_states[rtype], TRUE); } static void -manager_update_radio_enabled(NMManager *self, RadioState *rstate, gboolean enabled) +_rfkill_update_devices(NMManager *self, NMRfkillType rtype, gboolean enabled) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); NMDevice *device; - /* Do nothing for radio types not yet implemented */ - if (!rstate->prop) - return; - - g_object_notify(G_OBJECT(self), rstate->prop); + _notify(self, _rfkill_type_desc[rtype].prop_id); /* Don't touch devices if asleep/networking disabled */ if (manager_sleeping(self)) @@ -2316,7 +2403,7 @@ manager_update_radio_enabled(NMManager *self, RadioState *rstate, gboolean enabl /* enable/disable wireless devices as required */ c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { - if (nm_device_get_rfkill_type(device) == rstate->rtype) { + if (nm_device_get_rfkill_type(device) == rtype) { _LOG2D(LOGD_RFKILL, device, "rfkill: setting radio %s", @@ -2327,89 +2414,195 @@ manager_update_radio_enabled(NMManager *self, RadioState *rstate, gboolean enabl } static void -update_rstate_from_rfkill(NMRfkillManager *rfkill_mgr, RadioState *rstate) +_rfkill_update_one_type(NMManager *self, NMRfkillType rtype) { - switch (nm_rfkill_manager_get_rfkill_state(rfkill_mgr, rstate->rtype)) { - case RFKILL_UNBLOCKED: - rstate->sw_enabled = TRUE; - rstate->hw_enabled = TRUE; - break; - case RFKILL_SOFT_BLOCKED: - rstate->sw_enabled = FALSE; - rstate->hw_enabled = TRUE; - break; - case RFKILL_HARD_BLOCKED: - rstate->sw_enabled = FALSE; - rstate->hw_enabled = FALSE; - break; - default: - g_warn_if_reached(); - break; - } -} + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + RfkillRadioState *rstate = &priv->radio_states[rtype]; + gboolean old_enabled; + gboolean new_enabled; + gboolean old_rfkilled; + gboolean new_rfkilled; + gboolean old_hwe; + guint old_radio_flags; -static void -manager_rfkill_update_one_type(NMManager *self, RadioState *rstate, RfKillType rtype) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); - gboolean old_enabled, new_enabled, old_rfkilled, new_rfkilled, old_hwe; + nm_assert(_NM_INT_NOT_NEGATIVE(rtype) && rtype < G_N_ELEMENTS(priv->radio_states)); - old_enabled = radio_enabled_for_rstate(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 */ - update_rstate_from_rfkill(priv->rfkill_mgr, rstate); + _rfkill_radio_state_set_from_manager(self, rtype, rstate); /* Print out all states affecting device enablement */ - if (rstate->desc) { - _LOGD(LOGD_RFKILL, - "rfkill: %s hw-enabled %d sw-enabled %d", - rstate->desc, - rstate->hw_enabled, - rstate->sw_enabled); - } + _LOGD(LOGD_RFKILL, + "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); /* Log new killswitch state */ new_rfkilled = rstate->hw_enabled && rstate->sw_enabled; if (old_rfkilled != new_rfkilled) { _LOGI(LOGD_RFKILL, "rfkill: %s now %s by radio killswitch", - rstate->desc, + nm_rfkill_type_to_string(rtype), new_rfkilled ? "enabled" : "disabled"); } - /* Send out property changed signal for HW enabled */ - if (rstate->hw_enabled != old_hwe) { - if (rstate->hw_prop) - g_object_notify(G_OBJECT(self), rstate->hw_prop); - } + 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 * radio changes and we only want to ignore the daemon enabled state when * handling user radio change requests. */ - new_enabled = radio_enabled_for_rstate(rstate, TRUE); + new_enabled = _rfkill_radio_state_get_enabled(rstate, TRUE); if (new_enabled != old_enabled) - manager_update_radio_enabled(self, rstate, new_enabled); + _rfkill_update_devices(self, rtype, new_enabled); } static void -nm_manager_rfkill_update(NMManager *self, RfKillType rtype) +_rfkill_update(NMManager *self, NMRfkillType rtype) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); - guint i; + guint i; - if (rtype != RFKILL_TYPE_UNKNOWN) - manager_rfkill_update_one_type(self, &priv->radio_states[rtype], rtype); + if (rtype != NM_RFKILL_TYPE_UNKNOWN) + _rfkill_update_one_type(self, rtype); else { /* Otherwise, sync all radio types */ - for (i = 0; i < RFKILL_TYPE_MAX; i++) - manager_rfkill_update_one_type(self, &priv->radio_states[i], i); + for (i = 0; i < NM_RFKILL_TYPE_MAX; i++) + _rfkill_update_one_type(self, i); } } +/*****************************************************************************/ + +#define KERN_RFKILL_OP_CHANGE_ALL 3 +#define KERN_RFKILL_TYPE_WLAN 1 +#define KERN_RFKILL_TYPE_WWAN 5 + +struct rfkill_event { + uint32_t idx; + uint8_t type; + uint8_t op; + uint8_t soft; + uint8_t hard; +} _nm_packed; + +static void +_rfkill_update_system(NMManager *self, NMRfkillType rtype, gboolean enabled) +{ + nm_auto_close int fd = -1; + struct rfkill_event event; + ssize_t len; + int errsv; + + nm_assert(NM_IN_SET(rtype, NM_RFKILL_TYPE_WLAN, NM_RFKILL_TYPE_WWAN)); + + fd = open("/dev/rfkill", O_RDWR | O_CLOEXEC); + if (fd < 0) { + if (errno == EACCES) + _LOGW(LOGD_RFKILL, + "rfkill: (%s): failed to open killswitch device", + nm_rfkill_type_to_string(rtype)); + return; + } + + if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) { + _LOGW(LOGD_RFKILL, + "rfkill: (%s): failed to set killswitch device for " + "non-blocking operation", + nm_rfkill_type_to_string(rtype)); + return; + } + + memset(&event, 0, sizeof(event)); + event.op = KERN_RFKILL_OP_CHANGE_ALL; + switch (rtype) { + case NM_RFKILL_TYPE_WLAN: + event.type = KERN_RFKILL_TYPE_WLAN; + break; + case NM_RFKILL_TYPE_WWAN: + event.type = KERN_RFKILL_TYPE_WWAN; + break; + default: + nm_assert_not_reached(); + } + event.soft = enabled ? 0 : 1; + + len = write(fd, &event, sizeof(event)); + if (len < 0) { + errsv = errno; + _LOGW(LOGD_RFKILL, + "rfkill: (%s): failed to change Wi-Fi killswitch state: (%d) %s", + nm_rfkill_type_to_string(rtype), + errsv, + nm_strerror_native(errsv)); + } else if (len == sizeof(event)) { + _LOGI(LOGD_RFKILL, + "rfkill: %s hardware radio set %s", + nm_rfkill_type_to_string(rtype), + enabled ? "enabled" : "disabled"); + } else { + /* Failed to write full structure */ + _LOGW(LOGD_RFKILL, + "rfkill: (%s): failed to change Wi-Fi killswitch state", + nm_rfkill_type_to_string(rtype)); + } +} + +static void +_rfkill_update_from_user(NMManager *self, NMRfkillType rtype, gboolean enabled) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + RfkillRadioState *rstate = &priv->radio_states[rtype]; + gboolean old_enabled, new_enabled; + + /* Don't touch devices if asleep/networking disabled */ + if (manager_sleeping(self)) + return; + + _LOGD(LOGD_RFKILL, + "rfkill: (%s): setting radio %s by user", + nm_rfkill_type_to_string(rtype), + enabled ? "enabled" : "disabled"); + + /* Update enabled key in state file */ + nm_config_state_set(priv->config, TRUE, FALSE, _rfkill_type_desc[rtype].key, enabled); + + /* When the user toggles the radio, their request should override any + * daemon (like ModemManager) enabled state that can be changed. For WWAN + * for example, we want the WwanEnabled property to reflect the daemon state + * too so that users can toggle the modem powered, but we don't want that + * daemon state to affect whether or not the user *can* turn it on, which is + * what the kernel rfkill state does. So we ignore daemon enabled state + * when determining what the new state should be since it shouldn't block + * the user's request. + */ + old_enabled = _rfkill_radio_state_get_enabled(rstate, TRUE); + rstate->user_enabled = enabled; + new_enabled = _rfkill_radio_state_get_enabled(rstate, FALSE); + if (new_enabled != old_enabled) { + /* Try to change the kernel rfkill state */ + _rfkill_update_system(self, rtype, new_enabled); + _rfkill_update_devices(self, rtype, new_enabled); + } +} + +/*****************************************************************************/ + static void device_auth_done_cb(NMAuthChain *chain, GDBusMethodInvocation *context, gpointer user_data) { @@ -2599,7 +2792,7 @@ get_existing_connection(NMManager *self, NMDevice *device, gboolean *out_generat int master_ifindex = nm_platform_link_get_master(priv->platform, ifindex); /* Check that the master is activating before assuming a - * slave connection. However, ignore ovs-system master as + * slave connection. However, ignore ovs-system/ovs-netdev master as * we never manage it. */ if (master_ifindex @@ -2786,6 +2979,7 @@ get_existing_connection(NMManager *self, NMDevice *device, gboolean *out_generat nm_device_assume_state_reset(device); if (!nm_settings_add_connection(priv->settings, + NULL, connection, NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY, NM_SETTINGS_CONNECTION_ADD_REASON_NONE, @@ -2906,6 +3100,7 @@ recheck_assume_connection(NMManager *self, NMDevice *device) nm_settings_connection_update( sett_conn, + NULL, con2, NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP, NM_SETTINGS_CONNECTION_INT_FLAGS_NONE, @@ -3207,7 +3402,7 @@ add_device(NMManager *self, NMDevice *device, GError **error) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); const char *iface, *type_desc; - RfKillType rtype; + NMRfkillType rtype; GSList *iter, *remove = NULL; int ifindex; const char *dbus_path; @@ -3294,9 +3489,9 @@ add_device(NMManager *self, NMDevice *device, GError **error) * global state. */ rtype = nm_device_get_rfkill_type(device); - if (rtype != RFKILL_TYPE_UNKNOWN) { - nm_manager_rfkill_update(self, rtype); - nm_device_set_enabled(device, radio_enabled_for_type(self, rtype, TRUE)); + if (rtype != NM_RFKILL_TYPE_UNKNOWN) { + _rfkill_update(self, rtype); + nm_device_set_enabled(device, _rfkill_radio_state_get(self, rtype)); } iface = nm_device_get_iface(device); @@ -3671,12 +3866,14 @@ platform_query_devices(NMManager *self) } static void -rfkill_manager_rfkill_changed_cb(NMRfkillManager *rfkill_mgr, - RfKillType rtype, - RfKillState udev_state, - gpointer user_data) +rfkill_manager_rfkill_changed_cb(NMRfkillManager *rfkill_mgr, + /* NMRfkillType */ guint rtype, + /* NMRfkillState */ guint udev_state, + gpointer user_data) { - nm_manager_rfkill_update(NM_MANAGER(user_data), rtype); + nm_assert(rtype < NM_RFKILL_TYPE_MAX); + + _rfkill_update(NM_MANAGER(user_data), rtype); } const CList * @@ -5760,6 +5957,7 @@ _add_and_activate_auth_done(NMManager *self, * shutdown. */ nm_settings_add_connection_dbus( priv->settings, + NULL, connection, persist_mode, NM_SETTINGS_CONNECTION_ADD_REASON_NONE, @@ -6313,7 +6511,7 @@ do_sleep_wake(NMManager *self, gboolean sleeping_changed) /* Ensure rfkill state is up-to-date since we don't respond to state * changes during sleep. */ - nm_manager_rfkill_update(self, RFKILL_TYPE_UNKNOWN); + _rfkill_update(self, NM_RFKILL_TYPE_UNKNOWN); /* Re-manage managed devices */ c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { @@ -6330,20 +6528,21 @@ do_sleep_wake(NMManager *self, gboolean sleeping_changed) /* enable/disable wireless devices since that we don't respond * to killswitch changes during sleep. */ - for (i = 0; i < RFKILL_TYPE_MAX; i++) { - RadioState *rstate = &priv->radio_states[i]; - gboolean enabled = radio_enabled_for_rstate(rstate, TRUE); - - if (rstate->desc) { - _LOGD(LOGD_RFKILL, - "rfkill: %s %s devices (hw_enabled %d, sw_enabled %d, user_enabled %d)", - enabled ? "enabling" : "disabling", - rstate->desc, - rstate->hw_enabled, - rstate->sw_enabled, - rstate->user_enabled); - } - if (nm_device_get_rfkill_type(device) == rstate->rtype) + for (i = 0; i < NM_RFKILL_TYPE_MAX; i++) { + const NMRfkillType rtype = i; + const RfkillRadioState *rstate = &priv->radio_states[rtype]; + gboolean enabled = _rfkill_radio_state_get_enabled(rstate, TRUE); + + _LOGD(LOGD_RFKILL, + "rfkill: %s %s devices (hw_enabled %d, sw_enabled %d, user_enabled %d, " + "os_owner %d)", + enabled ? "enabling" : "disabling", + nm_rfkill_type_to_string(rtype), + rstate->hw_enabled, + rstate->sw_enabled, + rstate->user_enabled, + rstate->os_owner); + if (nm_device_get_rfkill_type(device) == rtype) nm_device_set_enabled(device, enabled); } @@ -6929,25 +7128,21 @@ nm_manager_start(NMManager *self, GError **error) nm_device_factory_manager_for_each_factory(start_factory, NULL); /* Set initial radio enabled/disabled state */ - for (i = 0; i < RFKILL_TYPE_MAX; i++) { - RadioState *rstate = &priv->radio_states[i]; - gboolean enabled; - - if (!rstate->desc) - continue; + for (i = 0; i < NM_RFKILL_TYPE_MAX; i++) { + const NMRfkillType rtype = i; + RfkillRadioState *rstate = &priv->radio_states[rtype]; + gboolean enabled; /* recheck kernel rfkill state */ - update_rstate_from_rfkill(priv->rfkill_mgr, rstate); - - if (rstate->desc) { - _LOGI(LOGD_RFKILL, - "rfkill: %s %s by radio killswitch; %s by state file", - rstate->desc, - (rstate->hw_enabled && rstate->sw_enabled) ? "enabled" : "disabled", - rstate->user_enabled ? "enabled" : "disabled"); - } - enabled = radio_enabled_for_rstate(rstate, TRUE); - manager_update_radio_enabled(self, rstate, enabled); + _rfkill_radio_state_set_from_manager(self, rtype, rstate); + + _LOGI(LOGD_RFKILL, + "rfkill: %s %s by radio killswitch; %s by state file", + nm_rfkill_type_to_string(rtype), + (rstate->hw_enabled && rstate->sw_enabled) ? "enabled" : "disabled", + rstate->user_enabled ? "enabled" : "disabled"); + enabled = _rfkill_radio_state_get_enabled(rstate, TRUE); + _rfkill_update_devices(self, rtype, enabled); } _LOGI(LOGD_CORE, "Networking is %s by state file", priv->net_enabled ? "enabled" : "disabled"); @@ -7605,141 +7800,7 @@ auth_mgr_changed(NMAuthManager *auth_manager, gpointer user_data) "()"); } -#define KERN_RFKILL_OP_CHANGE_ALL 3 -#define KERN_RFKILL_TYPE_WLAN 1 -#define KERN_RFKILL_TYPE_WWAN 5 -struct rfkill_event { - uint32_t idx; - uint8_t type; - uint8_t op; - uint8_t soft; - uint8_t hard; -} _nm_packed; - -static void -rfkill_change(NMManager *self, const char *desc, RfKillType rtype, gboolean enabled) -{ - int fd; - struct rfkill_event event; - ssize_t len; - int errsv; - - g_return_if_fail(rtype == RFKILL_TYPE_WLAN || rtype == RFKILL_TYPE_WWAN); - - fd = open("/dev/rfkill", O_RDWR | O_CLOEXEC); - if (fd < 0) { - if (errno == EACCES) - _LOGW(LOGD_RFKILL, "rfkill: (%s): failed to open killswitch device", desc); - return; - } - - if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) { - _LOGW(LOGD_RFKILL, - "rfkill: (%s): failed to set killswitch device for " - "non-blocking operation", - desc); - nm_close(fd); - return; - } - - memset(&event, 0, sizeof(event)); - event.op = KERN_RFKILL_OP_CHANGE_ALL; - switch (rtype) { - case RFKILL_TYPE_WLAN: - event.type = KERN_RFKILL_TYPE_WLAN; - break; - case RFKILL_TYPE_WWAN: - event.type = KERN_RFKILL_TYPE_WWAN; - break; - default: - g_assert_not_reached(); - } - event.soft = enabled ? 0 : 1; - - len = write(fd, &event, sizeof(event)); - if (len < 0) { - errsv = errno; - _LOGW(LOGD_RFKILL, - "rfkill: (%s): failed to change Wi-Fi killswitch state: (%d) %s", - desc, - errsv, - nm_strerror_native(errsv)); - } else if (len == sizeof(event)) { - _LOGI(LOGD_RFKILL, - "rfkill: %s hardware radio set %s", - desc, - enabled ? "enabled" : "disabled"); - } else { - /* Failed to write full structure */ - _LOGW(LOGD_RFKILL, "rfkill: (%s): failed to change Wi-Fi killswitch state", desc); - } - - nm_close(fd); -} - -static void -manager_radio_user_toggled(NMManager *self, RadioState *rstate, gboolean enabled) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); - gboolean old_enabled, new_enabled; - - /* Don't touch devices if asleep/networking disabled */ - if (manager_sleeping(self)) - return; - - if (rstate->desc) { - _LOGD(LOGD_RFKILL, - "rfkill: (%s): setting radio %s by user", - rstate->desc, - enabled ? "enabled" : "disabled"); - } - - /* Update enabled key in state file */ - nm_config_state_set(priv->config, TRUE, FALSE, rstate->key, enabled); - - /* When the user toggles the radio, their request should override any - * daemon (like ModemManager) enabled state that can be changed. For WWAN - * for example, we want the WwanEnabled property to reflect the daemon state - * too so that users can toggle the modem powered, but we don't want that - * daemon state to affect whether or not the user *can* turn it on, which is - * what the kernel rfkill state does. So we ignore daemon enabled state - * when determining what the new state should be since it shouldn't block - * the user's request. - */ - old_enabled = radio_enabled_for_rstate(rstate, TRUE); - rstate->user_enabled = enabled; - new_enabled = radio_enabled_for_rstate(rstate, FALSE); - if (new_enabled != old_enabled) { - /* Try to change the kernel rfkill state */ - if (rstate->rtype == RFKILL_TYPE_WLAN || rstate->rtype == RFKILL_TYPE_WWAN) - rfkill_change(self, rstate->desc, rstate->rtype, new_enabled); - - manager_update_radio_enabled(self, rstate, new_enabled); - } -} - -static gboolean -periodic_update_active_connection_timestamps(gpointer user_data) -{ - NMManager *manager = NM_MANAGER(user_data); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(manager); - NMActiveConnection *ac; - gboolean has_time = FALSE; - guint64 t = 0; - - c_list_for_each_entry (ac, &priv->active_connections_lst_head, active_connections_lst) { - if (nm_active_connection_get_state(ac) != NM_ACTIVE_CONNECTION_STATE_ACTIVATED) - continue; - - if (!has_time) { - t = time(NULL); - has_time = TRUE; - } - nm_settings_connection_update_timestamp(nm_active_connection_get_settings_connection(ac), - t); - } - return G_SOURCE_CONTINUE; -} +/*****************************************************************************/ void nm_manager_unblock_failed_ovs_interfaces(NMManager *self) @@ -7893,8 +7954,8 @@ constructed(GObject *object) priv->net_enabled = state->net_enabled; - priv->radio_states[RFKILL_TYPE_WLAN].user_enabled = state->wifi_enabled; - priv->radio_states[RFKILL_TYPE_WWAN].user_enabled = state->wwan_enabled; + priv->radio_states[NM_RFKILL_TYPE_WLAN].user_enabled = state->wifi_enabled; + priv->radio_states[NM_RFKILL_TYPE_WWAN].user_enabled = state->wwan_enabled; priv->rfkill_mgr = nm_rfkill_manager_new(); g_signal_connect(priv->rfkill_mgr, @@ -7907,21 +7968,18 @@ constructed(GObject *object) * changes to the WirelessEnabled/WWANEnabled properties which toggle kernel * rfkill. */ - rfkill_change(self, - priv->radio_states[RFKILL_TYPE_WLAN].desc, - RFKILL_TYPE_WLAN, - priv->radio_states[RFKILL_TYPE_WLAN].user_enabled); - rfkill_change(self, - priv->radio_states[RFKILL_TYPE_WWAN].desc, - RFKILL_TYPE_WWAN, - priv->radio_states[RFKILL_TYPE_WWAN].user_enabled); + _rfkill_update_system(self, + NM_RFKILL_TYPE_WLAN, + priv->radio_states[NM_RFKILL_TYPE_WLAN].user_enabled); + _rfkill_update_system(self, + NM_RFKILL_TYPE_WWAN, + priv->radio_states[NM_RFKILL_TYPE_WWAN].user_enabled); } static void nm_manager_init(NMManager *self) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); - guint i; GFile *file; c_list_init(&priv->auth_lst_head); @@ -7935,25 +7993,18 @@ nm_manager_init(NMManager *self) priv->capabilities = g_array_new(FALSE, FALSE, sizeof(guint32)); - /* Initialize rfkill structures and states */ - memset(priv->radio_states, 0, sizeof(priv->radio_states)); - - priv->radio_states[RFKILL_TYPE_WLAN].user_enabled = TRUE; - priv->radio_states[RFKILL_TYPE_WLAN].key = NM_CONFIG_STATE_PROPERTY_WIFI_ENABLED; - priv->radio_states[RFKILL_TYPE_WLAN].prop = NM_MANAGER_WIRELESS_ENABLED; - priv->radio_states[RFKILL_TYPE_WLAN].hw_prop = NM_MANAGER_WIRELESS_HARDWARE_ENABLED; - priv->radio_states[RFKILL_TYPE_WLAN].desc = "Wi-Fi"; - priv->radio_states[RFKILL_TYPE_WLAN].rtype = RFKILL_TYPE_WLAN; - - priv->radio_states[RFKILL_TYPE_WWAN].user_enabled = TRUE; - priv->radio_states[RFKILL_TYPE_WWAN].key = NM_CONFIG_STATE_PROPERTY_WWAN_ENABLED; - priv->radio_states[RFKILL_TYPE_WWAN].prop = NM_MANAGER_WWAN_ENABLED; - priv->radio_states[RFKILL_TYPE_WWAN].hw_prop = NM_MANAGER_WWAN_HARDWARE_ENABLED; - priv->radio_states[RFKILL_TYPE_WWAN].desc = "WWAN"; - priv->radio_states[RFKILL_TYPE_WWAN].rtype = RFKILL_TYPE_WWAN; - - for (i = 0; i < RFKILL_TYPE_MAX; i++) - priv->radio_states[i].hw_enabled = TRUE; + priv->radio_states[NM_RFKILL_TYPE_WLAN] = (RfkillRadioState){ + .user_enabled = TRUE, + .sw_enabled = FALSE, + .hw_enabled = TRUE, + .os_owner = TRUE, + }; + priv->radio_states[NM_RFKILL_TYPE_WWAN] = (RfkillRadioState){ + .user_enabled = TRUE, + .sw_enabled = FALSE, + .hw_enabled = TRUE, + .os_owner = TRUE, + }; priv->sleeping = FALSE; priv->state = NM_STATE_DISCONNECTED; @@ -7984,12 +8035,6 @@ nm_manager_init(NMManager *self) _LOGW(LOGD_CORE, "failed to monitor kernel firmware directory '%s'.", KERNEL_FIRMWARE_DIR); } - /* Update timestamps in active connections */ - priv->timestamp_update_id = - g_timeout_add_seconds(300, - (GSourceFunc) periodic_update_active_connection_timestamps, - self); - priv->metered = NM_METERED_UNKNOWN; priv->sleep_devices = g_hash_table_new(nm_direct_hash, NULL); } @@ -8025,16 +8070,16 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) g_value_set_boolean(value, priv->net_enabled); break; case PROP_WIRELESS_ENABLED: - g_value_set_boolean(value, radio_enabled_for_type(self, RFKILL_TYPE_WLAN, TRUE)); + g_value_set_boolean(value, _rfkill_radio_state_get(self, NM_RFKILL_TYPE_WLAN)); break; case PROP_WIRELESS_HARDWARE_ENABLED: - g_value_set_boolean(value, priv->radio_states[RFKILL_TYPE_WLAN].hw_enabled); + g_value_set_boolean(value, priv->radio_states[NM_RFKILL_TYPE_WLAN].hw_enabled); break; case PROP_WWAN_ENABLED: - g_value_set_boolean(value, radio_enabled_for_type(self, RFKILL_TYPE_WWAN, TRUE)); + g_value_set_boolean(value, _rfkill_radio_state_get(self, NM_RFKILL_TYPE_WWAN)); break; case PROP_WWAN_HARDWARE_ENABLED: - g_value_set_boolean(value, priv->radio_states[RFKILL_TYPE_WWAN].hw_enabled); + g_value_set_boolean(value, priv->radio_states[NM_RFKILL_TYPE_WWAN].hw_enabled); break; case PROP_WIMAX_ENABLED: g_value_set_boolean(value, FALSE); @@ -8042,6 +8087,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, @@ -8125,14 +8173,14 @@ set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *ps switch (prop_id) { case PROP_WIRELESS_ENABLED: - manager_radio_user_toggled(NM_MANAGER(object), - &priv->radio_states[RFKILL_TYPE_WLAN], - g_value_get_boolean(value)); + _rfkill_update_from_user(NM_MANAGER(object), + NM_RFKILL_TYPE_WLAN, + g_value_get_boolean(value)); break; case PROP_WWAN_ENABLED: - manager_radio_user_toggled(NM_MANAGER(object), - &priv->radio_states[RFKILL_TYPE_WWAN], - g_value_get_boolean(value)); + _rfkill_update_from_user(NM_MANAGER(object), + NM_RFKILL_TYPE_WWAN, + g_value_get_boolean(value)); break; case PROP_WIMAX_ENABLED: /* WIMAX is deprecated. This does nothing. */ @@ -8497,6 +8545,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), @@ -8641,6 +8692,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, "", diff --git a/src/core/nm-manager.h b/src/core/nm-manager.h index 385cdfe0..f8563c3a 100644 --- a/src/core/nm-manager.h +++ b/src/core/nm-manager.h @@ -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" diff --git a/src/core/nm-pacrunner-manager.c b/src/core/nm-pacrunner-manager.c index 5ef425bb..86a40632 100644 --- a/src/core/nm-pacrunner-manager.c +++ b/src/core/nm-pacrunner-manager.c @@ -291,7 +291,7 @@ _call_destroy_proxy_configuration(NMPacrunnerManager *self, g_variant_new("(o)", path), G_VARIANT_TYPE("()"), G_DBUS_CALL_FLAGS_NO_AUTO_START, - NM_SHUTDOWN_TIMEOUT_MS, + NM_SHUTDOWN_TIMEOUT_1500_MSEC, priv->cancellable, _call_destroy_proxy_configuration_cb, conf_id_ref(conf_id)); @@ -315,7 +315,7 @@ _call_create_proxy_configuration(NMPacrunnerManager *self, conf_id->parameters, G_VARIANT_TYPE("(o)"), G_DBUS_CALL_FLAGS_NO_AUTO_START, - NM_SHUTDOWN_TIMEOUT_MS, + NM_SHUTDOWN_TIMEOUT_1500_MSEC, priv->cancellable, _call_create_proxy_configuration_cb, conf_id_ref(conf_id)); diff --git a/src/core/nm-policy.c b/src/core/nm-policy.c index d77fc0a0..2d47772d 100644 --- a/src/core/nm-policy.c +++ b/src/core/nm-policy.c @@ -75,8 +75,9 @@ typedef struct { guint schedule_activate_all_id; /* idle handler for schedule_activate_all(). */ NMPolicyHostnameMode hostname_mode; - char *orig_hostname; /* hostname at NM start time */ - char *cur_hostname; /* hostname we want to assign */ + char *orig_hostname; /* hostname at NM start time */ + char *cur_hostname; /* hostname we want to assign */ + char *cur_hostname_full; /* similar to @last_hostname, but before shortening */ char * last_hostname; /* last hostname NM set (to detect if someone else changed it in the meanwhile) */ @@ -560,6 +561,7 @@ _set_hostname(NMPolicy *self, const char *new_hostname, const char *msg) { NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self); gs_free char *old_hostname = NULL; + gboolean cur_hostname_full_changed; const char *name; /* The incoming hostname *can* be NULL, which will get translated to @@ -568,32 +570,50 @@ _set_hostname(NMPolicy *self, const char *new_hostname, const char *msg) * there was no valid hostname to start with. */ + if (nm_strdup_reset(&priv->cur_hostname_full, new_hostname)) { + gs_free char *shortened = NULL; + + cur_hostname_full_changed = TRUE; + + if (priv->cur_hostname_full + && !nm_utils_shorten_hostname(priv->cur_hostname_full, &shortened)) { + _LOGW(LOGD_DNS, + "set-hostname: hostname '%s' %s is invalid", + priv->cur_hostname_full, + msg); + return; + } + + if (shortened) { + _LOGI(LOGD_DNS, + "set-hostname: shortened hostname %s from '%s' to '%s'", + msg, + priv->cur_hostname_full, + shortened); + nm_strdup_reset_take(&priv->cur_hostname, g_steal_pointer(&shortened)); + } else + nm_strdup_reset(&priv->cur_hostname, priv->cur_hostname_full); + } else + cur_hostname_full_changed = FALSE; + /* Update the DNS only if the hostname is actually * going to change. */ - if (!nm_streq0(priv->cur_hostname, new_hostname)) { - g_free(priv->cur_hostname); - priv->cur_hostname = g_strdup(new_hostname); - + if (cur_hostname_full_changed) { /* Notify the DNS manager of the hostname change so that the domain part, if * present, can be added to the search list. Set the @updating_dns flag * so that dns_config_changed() doesn't try again to restart DNS lookup. */ priv->updating_dns = TRUE; nm_dns_manager_set_hostname(priv->dns_manager, - priv->cur_hostname, + priv->cur_hostname_full, all_devices_not_active(self)); priv->updating_dns = FALSE; } /* Finally, set kernel hostname */ - if (!new_hostname) - name = FALLBACK_HOSTNAME4; - else if (!new_hostname[0]) { - g_warn_if_reached(); - name = FALLBACK_HOSTNAME4; - } else - name = new_hostname; + nm_assert(!priv->cur_hostname || priv->cur_hostname[0]); + name = priv->cur_hostname ?: FALLBACK_HOSTNAME4; /* Don't set the hostname if it isn't actually changing */ if ((old_hostname = _get_hostname(self)) && (nm_streq(name, old_hostname))) { @@ -602,14 +622,16 @@ _set_hostname(NMPolicy *self, const char *new_hostname, const char *msg) } /* Keep track of the last set hostname */ - g_free(priv->last_hostname); - priv->last_hostname = g_strdup(name); + nm_strdup_reset(&priv->last_hostname, name); priv->changing_hostname = TRUE; _LOGI(LOGD_DNS, "set-hostname: set hostname to '%s' (%s)", name, msg); /* Ask NMSettings to update the transient hostname using its - * systemd-hostnamed proxy */ + * systemd-hostnamed proxy. + * + * FIXME(shutdown): an async request must be cancellable, so we are guaranteed + * to tear down in a reasonable time.*/ nm_hostname_manager_set_transient_hostname(priv->hostname_manager, name, settings_set_hostname_cb, @@ -2761,7 +2783,7 @@ constructed(GObject *object) self); priv->dns_manager = g_object_ref(nm_dns_manager_get()); - nm_dns_manager_set_initial_hostname(priv->dns_manager, priv->orig_hostname); + nm_dns_manager_set_hostname(priv->dns_manager, priv->orig_hostname, TRUE); priv->config_changed_id = g_signal_connect(priv->dns_manager, NM_DNS_MANAGER_CONFIG_CHANGED, G_CALLBACK(dns_config_changed), @@ -2892,6 +2914,7 @@ dispose(GObject *object) nm_clear_g_free(&priv->orig_hostname); nm_clear_g_free(&priv->cur_hostname); + nm_clear_g_free(&priv->cur_hostname_full); nm_clear_g_free(&priv->last_hostname); if (priv->hostname_manager) { diff --git a/src/core/nm-rfkill-manager.c b/src/core/nm-rfkill-manager.c index f3851e5c..03333899 100644 --- a/src/core/nm-rfkill-manager.c +++ b/src/core/nm-rfkill-manager.c @@ -9,6 +9,7 @@ #include <libudev.h> +#include "c-list/src/c-list.h" #include "libnm-udev-aux/nm-udev-utils.h" /*****************************************************************************/ @@ -24,8 +25,9 @@ typedef struct { NMUdevClient *udev_client; /* Authoritative rfkill state (RFKILL_* enum) */ - RfKillState rfkill_states[RFKILL_TYPE_MAX]; - GSList *killswitches; + NMRfkillState rfkill_states[NM_RFKILL_TYPE_MAX]; + + CList killswitch_lst_head; } NMRfkillManagerPrivate; struct _NMRfkillManager { @@ -45,60 +47,81 @@ G_DEFINE_TYPE(NMRfkillManager, nm_rfkill_manager, G_TYPE_OBJECT) /*****************************************************************************/ typedef struct { - char *name; - guint64 seqnum; - char *path; - char *driver; - RfKillType rtype; - int state; - gboolean platform; + CList killswitch_lst; + char *name; + char *path; + char *driver; + guint64 seqnum; + NMRfkillType rtype; + int state; + bool platform : 1; } Killswitch; -RfKillState -nm_rfkill_manager_get_rfkill_state(NMRfkillManager *self, RfKillType rtype) +NMRfkillState +nm_rfkill_manager_get_rfkill_state(NMRfkillManager *self, NMRfkillType rtype) { - g_return_val_if_fail(self != NULL, RFKILL_UNBLOCKED); - g_return_val_if_fail(rtype < RFKILL_TYPE_MAX, RFKILL_UNBLOCKED); + g_return_val_if_fail(self != NULL, NM_RFKILL_STATE_UNBLOCKED); + g_return_val_if_fail(rtype < NM_RFKILL_TYPE_MAX, NM_RFKILL_STATE_UNBLOCKED); return NM_RFKILL_MANAGER_GET_PRIVATE(self)->rfkill_states[rtype]; } -static const char * -rfkill_type_to_desc(RfKillType 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) { - if (rtype == 0) + switch (type) { + case NM_RFKILL_TYPE_WLAN: return "Wi-Fi"; - else if (rtype == 1) + case NM_RFKILL_TYPE_WWAN: return "WWAN"; - else if (rtype == 2) - return "WiMAX"; - return "unknown"; + case NM_RFKILL_TYPE_UNKNOWN: + break; + } + return nm_assert_unreachable_val("unknown"); } static const char * -rfkill_state_to_desc(RfKillState rstate) +nm_rfkill_state_to_string(NMRfkillState state) { - if (rstate == 0) + switch (state) { + case NM_RFKILL_STATE_UNAVAILABLE: + return "unavailable"; + case NM_RFKILL_STATE_UNBLOCKED: return "unblocked"; - else if (rstate == 1) + case NM_RFKILL_STATE_SOFT_BLOCKED: return "soft-blocked"; - else if (rstate == 2) + case NM_RFKILL_STATE_HARD_BLOCKED: return "hard-blocked"; - return "unknown"; + case NM_RFKILL_STATE_HARD_BLOCKED_OS_NOT_OWNER: + return "hard-blocked-os-not-owner"; + } + return nm_assert_unreachable_val("unknown"); } static Killswitch * -killswitch_new(struct udev_device *device, RfKillType rtype) +killswitch_new(struct udev_device *device, NMRfkillType rtype) { Killswitch *ks; - struct udev_device *parent = NULL, *grandparent = NULL; - const char *driver, *subsys, *parent_subsys = NULL; - - ks = g_malloc0(sizeof(Killswitch)); - ks->name = g_strdup(udev_device_get_sysname(device)); - ks->seqnum = udev_device_get_seqnum(device); - ks->path = g_strdup(udev_device_get_syspath(device)); - ks->rtype = rtype; + struct udev_device *parent = NULL; + struct udev_device *grandparent = NULL; + const char *driver; + const char *subsys; + const char *parent_subsys = NULL; + gboolean platform; driver = udev_device_get_property_value(device, "DRIVER"); subsys = udev_device_get_subsystem(device); @@ -116,14 +139,23 @@ killswitch_new(struct udev_device *device, RfKillType rtype) driver = udev_device_get_property_value(grandparent, "DRIVER"); } } - if (!driver) driver = "(unknown)"; - ks->driver = g_strdup(driver); - if (g_strcmp0(subsys, "platform") == 0 || g_strcmp0(parent_subsys, "platform") == 0 - || g_strcmp0(subsys, "acpi") == 0 || g_strcmp0(parent_subsys, "acpi") == 0) - ks->platform = TRUE; + platform = FALSE; + if (nm_streq0(subsys, "platform") || nm_streq0(parent_subsys, "platform") + || nm_streq0(subsys, "acpi") || nm_streq0(parent_subsys, "acpi")) + platform = TRUE; + + ks = g_slice_new(Killswitch); + *ks = (Killswitch){ + .name = g_strdup(udev_device_get_sysname(device)), + .seqnum = udev_device_get_seqnum(device), + .path = g_strdup(udev_device_get_syspath(device)), + .rtype = rtype, + .driver = g_strdup(driver), + .platform = platform, + }; return ks; } @@ -131,55 +163,58 @@ killswitch_new(struct udev_device *device, RfKillType rtype) static void killswitch_destroy(Killswitch *ks) { - g_return_if_fail(ks != NULL); - + c_list_unlink_stale(&ks->killswitch_lst); g_free(ks->name); g_free(ks->path); g_free(ks->driver); - memset(ks, 0, sizeof(Killswitch)); - g_free(ks); + nm_g_slice_free(ks); } -static RfKillState -sysfs_state_to_nm_state(int sysfs_state) +static NMRfkillState +sysfs_state_to_nm_state(int sysfs_state, int sysfs_reason) { switch (sysfs_state) { case 0: - return RFKILL_SOFT_BLOCKED; + return NM_RFKILL_STATE_SOFT_BLOCKED; case 1: - return RFKILL_UNBLOCKED; + return NM_RFKILL_STATE_UNBLOCKED; case 2: - return RFKILL_HARD_BLOCKED; + /* sysfs reason is a bitmap, in case we have both reasons (SIGNAL and NOT_OWNER), we want + * to consider the device as not owned. + */ + if (sysfs_reason & 2) + return NM_RFKILL_STATE_HARD_BLOCKED_OS_NOT_OWNER; + return NM_RFKILL_STATE_HARD_BLOCKED; default: nm_log_warn(LOGD_RFKILL, "unhandled rfkill state %d", sysfs_state); break; } - return RFKILL_UNBLOCKED; + return NM_RFKILL_STATE_UNBLOCKED; } static void recheck_killswitches(NMRfkillManager *self) { NMRfkillManagerPrivate *priv = NM_RFKILL_MANAGER_GET_PRIVATE(self); - GSList *iter; - RfKillState poll_states[RFKILL_TYPE_MAX]; - RfKillState platform_states[RFKILL_TYPE_MAX]; - gboolean platform_checked[RFKILL_TYPE_MAX]; + Killswitch *ks; + NMRfkillState poll_states[NM_RFKILL_TYPE_MAX]; + NMRfkillState platform_states[NM_RFKILL_TYPE_MAX]; + gboolean platform_checked[NM_RFKILL_TYPE_MAX]; int i; /* Default state is unblocked */ - for (i = 0; i < RFKILL_TYPE_MAX; i++) { - poll_states[i] = RFKILL_UNBLOCKED; - platform_states[i] = RFKILL_UNBLOCKED; + for (i = 0; i < NM_RFKILL_TYPE_MAX; i++) { + poll_states[i] = NM_RFKILL_STATE_UNAVAILABLE; + platform_states[i] = NM_RFKILL_STATE_UNAVAILABLE; platform_checked[i] = FALSE; } /* Poll the states of all killswitches */ - for (iter = priv->killswitches; iter; iter = g_slist_next(iter)) { - Killswitch *ks = iter->data; + c_list_for_each_entry (ks, &priv->killswitch_lst_head, killswitch_lst) { struct udev_device *device; - RfKillState dev_state; + NMRfkillState dev_state; int sysfs_state; + int sysfs_reason; device = udev_device_new_from_subsystem_sysname(nm_udev_client_get_udev(priv->udev_client), "rfkill", @@ -192,15 +227,24 @@ recheck_killswitches(NMRfkillManager *self) G_MININT, G_MAXINT, -1); - dev_state = sysfs_state_to_nm_state(sysfs_state); + + sysfs_reason = _nm_utils_ascii_str_to_int64( + udev_device_get_property_value(device, "RFKILL_HW_BLOCK_REASON"), + 16, + G_MININT, + G_MAXINT, + 1); /* defaults to SIGNAL in case the kernel does not support this */ + + 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", - rfkill_type_to_desc(ks->rtype), + "%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) { if (dev_state > poll_states[ks->rtype]) @@ -210,27 +254,32 @@ recheck_killswitches(NMRfkillManager *self) if (dev_state > platform_states[ks->rtype]) platform_states[ks->rtype] = dev_state; } + udev_device_unref(device); } /* Log and emit change signal for final rfkill states */ - for (i = 0; i < RFKILL_TYPE_MAX; i++) { + for (i = 0; i < NM_RFKILL_TYPE_MAX; i++) { if (platform_checked[i] == TRUE) { /* blocked platform switch state overrides device state, otherwise * let the device state stand. (bgo #655773) */ - if (platform_states[i] != RFKILL_UNBLOCKED) + if (platform_states[i] > NM_RFKILL_STATE_UNBLOCKED) poll_states[i] = platform_states[i]; } if (poll_states[i] != priv->rfkill_states[i]) { nm_log_dbg(LOGD_RFKILL, "%s rfkill state now '%s'", - rfkill_type_to_desc(i), - rfkill_state_to_desc(poll_states[i])); + nm_rfkill_type_to_string(i), + nm_rfkill_state_to_string(poll_states[i])); priv->rfkill_states[i] = poll_states[i]; - g_signal_emit(self, signals[RFKILL_CHANGED], 0, i, priv->rfkill_states[i]); + g_signal_emit(self, + signals[RFKILL_CHANGED], + 0, + (guint) i, + (guint) priv->rfkill_states[i]); } } } @@ -239,52 +288,48 @@ static Killswitch * killswitch_find_by_name(NMRfkillManager *self, const char *name) { NMRfkillManagerPrivate *priv = NM_RFKILL_MANAGER_GET_PRIVATE(self); - GSList *iter; - - g_return_val_if_fail(name != NULL, NULL); + Killswitch *ks; - for (iter = priv->killswitches; iter; iter = g_slist_next(iter)) { - Killswitch *candidate = iter->data; + nm_assert(name); - if (!strcmp(name, candidate->name)) - return candidate; + c_list_for_each_entry (ks, &priv->killswitch_lst_head, killswitch_lst) { + if (nm_streq(name, ks->name)) + return ks; } return NULL; } -static RfKillType +static NMRfkillType rfkill_type_to_enum(const char *str) { - g_return_val_if_fail(str != NULL, RFKILL_TYPE_UNKNOWN); - - if (!strcmp(str, "wlan")) - return RFKILL_TYPE_WLAN; - else if (!strcmp(str, "wwan")) - return RFKILL_TYPE_WWAN; + if (str) { + if (nm_streq(str, "wlan")) + return NM_RFKILL_TYPE_WLAN; + if (nm_streq(str, "wwan")) + return NM_RFKILL_TYPE_WWAN; + } - return RFKILL_TYPE_UNKNOWN; + return NM_RFKILL_TYPE_UNKNOWN; } static void add_one_killswitch(NMRfkillManager *self, struct udev_device *device) { NMRfkillManagerPrivate *priv = NM_RFKILL_MANAGER_GET_PRIVATE(self); - const char *str_type; - RfKillType rtype; + NMRfkillType rtype; Killswitch *ks; - str_type = udev_device_get_property_value(device, "RFKILL_TYPE"); - rtype = rfkill_type_to_enum(str_type); - if (rtype == RFKILL_TYPE_UNKNOWN) + rtype = rfkill_type_to_enum(udev_device_get_property_value(device, "RFKILL_TYPE")); + if (rtype == NM_RFKILL_TYPE_UNKNOWN) return; - ks = killswitch_new(device, rtype); - priv->killswitches = g_slist_prepend(priv->killswitches, ks); + ks = killswitch_new(device, rtype); + c_list_link_front(&priv->killswitch_lst_head, &ks->killswitch_lst); nm_log_info(LOGD_RFKILL, "%s: found %s radio killswitch (at %s) (%sdriver %s)", ks->name, - rfkill_type_to_desc(rtype), + nm_rfkill_type_to_string(rtype), ks->path, ks->platform ? "platform " : "", ks->driver ?: "<unknown>"); @@ -297,6 +342,7 @@ rfkill_add(NMRfkillManager *self, struct udev_device *device) g_return_if_fail(device != NULL); name = udev_device_get_sysname(device); + g_return_if_fail(name != NULL); if (!killswitch_find_by_name(self, name)) @@ -307,21 +353,20 @@ static void rfkill_remove(NMRfkillManager *self, struct udev_device *device) { NMRfkillManagerPrivate *priv = NM_RFKILL_MANAGER_GET_PRIVATE(self); - GSList *iter; + Killswitch *ks; const char *name; g_return_if_fail(device != NULL); + name = udev_device_get_sysname(device); - g_return_if_fail(name != NULL); - for (iter = priv->killswitches; iter; iter = g_slist_next(iter)) { - Killswitch *ks = iter->data; + g_return_if_fail(name != NULL); - if (!strcmp(ks->name, name)) { + c_list_for_each_entry (ks, &priv->killswitch_lst_head, killswitch_lst) { + if (nm_streq(ks->name, name)) { nm_log_info(LOGD_RFKILL, "radio killswitch %s disappeared", ks->path); - priv->killswitches = g_slist_remove(priv->killswitches, ks); killswitch_destroy(ks); - break; + return; } } } @@ -339,16 +384,16 @@ handle_uevent(NMUdevClient *client, struct udev_device *device, gpointer user_da /* A bit paranoid */ subsys = udev_device_get_subsystem(device); - g_return_if_fail(!g_strcmp0(subsys, "rfkill")); + g_return_if_fail(nm_streq0(subsys, "rfkill")); nm_log_dbg(LOGD_PLATFORM, "udev rfkill event: action '%s' device '%s'", action, udev_device_get_sysname(device)); - if (!strcmp(action, "add")) + if (nm_streq(action, "add")) rfkill_add(self, device); - else if (!strcmp(action, "remove")) + else if (nm_streq(action, "remove")) rfkill_remove(self, device); recheck_killswitches(self); @@ -364,8 +409,10 @@ nm_rfkill_manager_init(NMRfkillManager *self) struct udev_list_entry *iter; guint i; - for (i = 0; i < RFKILL_TYPE_MAX; i++) - priv->rfkill_states[i] = RFKILL_UNBLOCKED; + c_list_init(&priv->killswitch_lst_head); + + for (i = 0; i < NM_RFKILL_TYPE_MAX; i++) + priv->rfkill_states[i] = NM_RFKILL_STATE_UNAVAILABLE; priv->udev_client = nm_udev_client_new(NM_MAKE_STRV("rfkill"), handle_uevent, self); @@ -399,11 +446,10 @@ dispose(GObject *object) { NMRfkillManager *self = NM_RFKILL_MANAGER(object); NMRfkillManagerPrivate *priv = NM_RFKILL_MANAGER_GET_PRIVATE(self); + Killswitch *ks; - if (priv->killswitches) { - g_slist_free_full(priv->killswitches, (GDestroyNotify) killswitch_destroy); - priv->killswitches = NULL; - } + while ((ks = c_list_first_entry(&priv->killswitch_lst_head, Killswitch, killswitch_lst))) + killswitch_destroy(ks); priv->udev_client = nm_udev_client_destroy(priv->udev_client); @@ -426,6 +472,6 @@ nm_rfkill_manager_class_init(NMRfkillManagerClass *klass) NULL, G_TYPE_NONE, 2, - G_TYPE_UINT, - G_TYPE_UINT); + G_TYPE_UINT /* NMRfkillType */, + G_TYPE_UINT /* NMRfkillState */); } diff --git a/src/core/nm-rfkill-manager.h b/src/core/nm-rfkill-manager.h index d3f66349..88d0421a 100644 --- a/src/core/nm-rfkill-manager.h +++ b/src/core/nm-rfkill-manager.h @@ -7,23 +7,33 @@ #ifndef __NM_RFKILL_MANAGER_H__ #define __NM_RFKILL_MANAGER_H__ -typedef enum { /*< skip >*/ - RFKILL_UNBLOCKED = 0, - RFKILL_SOFT_BLOCKED = 1, - RFKILL_HARD_BLOCKED = 2 -} RfKillState; - -typedef enum { /*< skip >*/ - RFKILL_TYPE_WLAN = 0, - RFKILL_TYPE_WWAN = 1, - - /* UNKNOWN and MAX should always be 1 more than - * the last rfkill type since RFKILL_TYPE_MAX is +typedef enum { + 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 = 4, +} NMRfkillState; + +typedef enum { + NM_RFKILL_TYPE_WLAN = 0, + NM_RFKILL_TYPE_WWAN = 1, + + /* UNKNOWN and MAX should always be 1 more than + * the last rfkill type since NM_RFKILL_TYPE_MAX is * used as an array size. */ - RFKILL_TYPE_UNKNOWN, /* KEEP LAST */ - RFKILL_TYPE_MAX = RFKILL_TYPE_UNKNOWN -} RfKillType; + NM_RFKILL_TYPE_UNKNOWN, /* KEEP LAST */ + NM_RFKILL_TYPE_MAX = NM_RFKILL_TYPE_UNKNOWN, +} NMRfkillType; + +const char *nm_rfkill_type_to_string(NMRfkillType rtype); #define NM_TYPE_RFKILL_MANAGER (nm_rfkill_manager_get_type()) #define NM_RFKILL_MANAGER(obj) \ @@ -43,6 +53,8 @@ GType nm_rfkill_manager_get_type(void); NMRfkillManager *nm_rfkill_manager_new(void); -RfKillState nm_rfkill_manager_get_rfkill_state(NMRfkillManager *manager, RfKillType rtype); +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__ */ diff --git a/src/core/nm-session-monitor.c b/src/core/nm-session-monitor.c index 08bfedca..a2e9373c 100644 --- a/src/core/nm-session-monitor.c +++ b/src/core/nm-session-monitor.c @@ -114,13 +114,10 @@ st_sd_init(NMSessionMonitor *monitor) return; } - monitor->sd.watch = nm_g_unix_fd_source_new(sd_login_monitor_get_fd(monitor->sd.monitor), + monitor->sd.watch = nm_g_unix_fd_add_source(sd_login_monitor_get_fd(monitor->sd.monitor), G_IO_IN, - G_PRIORITY_DEFAULT, st_sd_changed, - monitor, - NULL); - g_source_attach(monitor->sd.watch, NULL); + monitor); } static void diff --git a/src/core/nm-test-utils-core.h b/src/core/nm-test-utils-core.h index 6f571972..467f9bb2 100644 --- a/src/core/nm-test-utils-core.h +++ b/src/core/nm-test-utils-core.h @@ -211,12 +211,13 @@ nmtst_platform_ip4_routes_equal(const NMPlatformIP4Route *a, for (i = 0; i < len; i++) { if (nm_platform_ip4_route_cmp_full(&a[i], &b[i]) != 0) { - char buf[sizeof(_nm_utils_to_string_buffer)]; + char buf1[NM_UTILS_TO_STRING_BUFFER_SIZE]; + char buf2[NM_UTILS_TO_STRING_BUFFER_SIZE]; g_error("Error comparing IPv4 route[%lu]: %s vs %s", (unsigned long) i, - nm_platform_ip4_route_to_string(&a[i], NULL, 0), - nm_platform_ip4_route_to_string(&b[i], buf, sizeof(buf))); + nm_platform_ip4_route_to_string(&a[i], buf1, sizeof(buf1)), + nm_platform_ip4_route_to_string(&b[i], buf2, sizeof(buf2))); g_assert_not_reached(); } } @@ -280,12 +281,13 @@ nmtst_platform_ip6_routes_equal(const NMPlatformIP6Route *a, for (i = 0; i < len; i++) { if (nm_platform_ip6_route_cmp_full(&a[i], &b[i]) != 0) { - char buf[sizeof(_nm_utils_to_string_buffer)]; + char buf1[NM_UTILS_TO_STRING_BUFFER_SIZE]; + char buf2[NM_UTILS_TO_STRING_BUFFER_SIZE]; g_error("Error comparing IPv6 route[%lu]: %s vs %s", (unsigned long) i, - nm_platform_ip6_route_to_string(&a[i], NULL, 0), - nm_platform_ip6_route_to_string(&b[i], buf, sizeof(buf))); + nm_platform_ip6_route_to_string(&a[i], buf1, sizeof(buf1)), + nm_platform_ip6_route_to_string(&b[i], buf2, sizeof(buf2))); g_assert_not_reached(); } } diff --git a/src/core/platform/tests/test-common.c b/src/core/platform/tests/test-common.c index 9053d351..d7fed220 100644 --- a/src/core/platform/tests/test-common.c +++ b/src/core/platform/tests/test-common.c @@ -239,8 +239,9 @@ _nmtstp_platform_ip_addresses_assert(const char *filename, } } if ((IS_IPv4 ? force_exact_4 : force_exact_6) && nm_g_ptr_array_len(plat_addrs) > 0) { - char sbuf[sizeof(_nm_utils_to_string_buffer)]; + char sbuf[NM_UTILS_TO_STRING_BUFFER_SIZE]; + NM_PRAGMA_WARNING_DISABLE_DANGLING_POINTER g_error("%s:%d: %u IPv%c addresses found on ifindex %d that should not be there (one " "is %s)", filename, @@ -252,6 +253,7 @@ _nmtstp_platform_ip_addresses_assert(const char *filename, NMP_OBJECT_TO_STRING_PUBLIC, sbuf, sizeof(sbuf))); + NM_PRAGMA_WARNING_REENABLE } } } @@ -580,6 +582,7 @@ _nmtstp_assert_ip4_route_exists(const char *file, if (c != c_exists && c_exists != -1) { char sbuf[NM_UTILS_INET_ADDRSTRLEN]; + NM_PRAGMA_WARNING_DISABLE_DANGLING_POINTER g_error("[%s:%u] %s(): The ip4 route %s/%d metric %u tos %u shall exist %u times, but " "platform has it %u times", file, @@ -591,6 +594,7 @@ _nmtstp_assert_ip4_route_exists(const char *file, tos, c_exists, c); + NM_PRAGMA_WARNING_REENABLE } return r; @@ -673,6 +677,7 @@ _nmtstp_assert_ip6_route_exists(const char *file, char s_src[NM_UTILS_INET_ADDRSTRLEN]; char s_network[NM_UTILS_INET_ADDRSTRLEN]; + NM_PRAGMA_WARNING_DISABLE_DANGLING_POINTER g_error("[%s:%u] %s(): The ip6 route %s/%d metric %u src %s/%d shall exist %u times, but " "platform has it %u times", file, @@ -685,6 +690,7 @@ _nmtstp_assert_ip6_route_exists(const char *file, src_plen, c_exists, c); + NM_PRAGMA_WARNING_REENABLE } return r; @@ -2772,13 +2778,7 @@ nmtstp_acd_defender_new(int ifindex, in_addr_t ip_addr, const NMEtherAddr *mac_a n_acd_get_fd(defender->nacd, &fd); g_assert_cmpint(fd, >=, 0); - defender->source = nm_g_source_attach(nm_g_unix_fd_source_new(fd, - G_IO_IN, - G_PRIORITY_DEFAULT, - _l3_acd_nacd_event, - defender, - NULL), - NULL); + defender->source = nm_g_unix_fd_add_source(fd, G_IO_IN, _l3_acd_nacd_event, defender); return defender; } diff --git a/src/core/platform/tests/test-platform-general.c b/src/core/platform/tests/test-platform-general.c index 9629326a..93e525dd 100644 --- a/src/core/platform/tests/test-platform-general.c +++ b/src/core/platform/tests/test-platform-general.c @@ -101,9 +101,9 @@ static void test_platform_ip_address_pretty_sort_cmp(gconstpointer test_data) { static const char *const EXPECTED_BUFFER[3] = { - [0] = ("5b1aea34648cabfec7c3523f76cf1ce34ca17a9a32f3f0f218424e48836dd1cb504e03d53e1124c5" + [0] = ("5b1aea34648cabfec7c3523f76cf1ce34ca17a9a32f3f0f218024e48836dd1cb504e03d53e1124c5" "0065aeb2e6fbf952902383028e3b47f280f062ea1a7e0b7be218d067530e1b0487b8c3b99f2b8a1a" - "8982c42f0000003437c5156e072b2f2f0037c9cfe07c34ddb3980deb14ab7b5af84a034703000000" + "8907c42f0000003437c5156e072b2f2f0037c9cfe07c34ddb3980deb14ab7b5af84a034703000000" "883b0f3fd6ed84d6c959e553b887edcd6101f5d200000043b809d259e499db7d00f1853bdcb0e4bc" "0e2b00b667b7b16d8d1e69c803000000b973972c17a47631c169f11ff9119c40b403b6630000007a" "034f43340d01683c0045097aea4a849f060ddf57b24a5be9636360d603000000ad7c499dd538d345" @@ -115,50 +115,50 @@ test_platform_ip_address_pretty_sort_cmp(gconstpointer test_data) "6663861eea1bf42c12ea3b9503000000fb95e8332fdfff658483a2d039a7bf148e02481e00000060" "e89f7abdb682380a00eae374835b4a49a2b980b6aba92da6409969aa03000000e00473755d31e5b2" "de252167c1c91b3a36020c700000007740318db913a353ed006efc068829c0e66ad0143a0554efb4" - "40e55b8b03000000c0cfb2b4386bec092fa5757ecde9348bda002ebd000000ab667224dae775e5cc" - "0041aca2ff0f576767d3648102b61886d149f07403000000153ece68ade15cec25a59273e7519f34" - "c4458d70000000f3819aa46fbe1439340033ae6dec0fb124f264af67eed7c9a8ecc8fb1103000000" + "d149f07403000000153ece68ade15cec25a59273e7519f34c40d8d70000000f3819aa46fbe143934" + "0033ae6dec0fb124f264af67eed7c9a840e55b8b03000000c0cfb2b4386bec092fa5757ecde9348b" + "da002ebd000000ab667224dae775e5cc0041aca2ff0f576767d3648102b61886ecc8fb1103000000" "fcebbaeb0c56535923f14874042a8aff1d028e5ec3cc13cc36bbe3c9bb0ec36f00e007bb64a2827b" "7cdd38d0314c178e5a06c40b03000000ab90135fa636af4464d210a256be75e0500244770000004b" "2e69220d6c0fc09c25d6534c809829af4a9df58dbfef186d416f3a1e030000002c932e655203d82a" "3c84c4eb274ed18687030281000000f2235376239daeaacb3cae864b437baaae91921681c2162b9b" "69e66142030000004fda8a3e0b841cf76391dd68269b53eccb02a831000000b78c54dda9ac3bb1b1" "d43e6505621b9a7f0422ae3fc8979ee0416f95e70300000057d6249b652ba98c7dc7f17f666969e4" - "5c02af7a000000ee0b06fa9e988f80f0de6dc8dfcf2a3ad3bbcc0fa3b314f695111d891d03000000" - "cd897619f51f44e644d7cf1d06b2b115d800549e62c12fba5b1cdec48d10bbb13b8313d8cd2a24d3" - "4fc812bd2f8a59d90fcc00ac030000005292cd32dc096cd5d8a4c5cf3351ee1cfc03056c00000051" - "bbce426cfa4b861cc78592be7b14e7ba9c15acb881ae55f0e5fe7d360300000066a3ae3939762df3" - "3a2d55060c78d551cb0010fd00000041b9aca07b6e4925dd27943a272c171ed15abbbe1cd911db7b" - "86ed271803000000a5edc511c1507a141e0f515638c7ba31f50209450000003357ae79989870ccec" - "3def0ad92749e016663fe6ee0228c1da82d1595603000000348352d715cf9d411ea012e5307294b6" - "e301dac4000000075efee38dd16f8ee4ccd2f50c30706cae3fdcc2f0ee3d5e26bb20413203000000" - "862573c2303dd1d65c7b2cffeca6d1adaccae11f0000000f855ebf3b772eb2b1c896c9a7304f6645" - "0a5f6abd850b06e3b10123e6030000001dff045298cfee0636674cdefb57b9ae54cfe8f400000038" - "1ba2c4396de60f032bc7f34de2959871c0d4c0d4eb720c4ab550c5db03000000f32f4af595d785d5" - "c1b5aad487c192f08bd7a09b00000043288cd9bf66ec305a225a0c71b2ce78bb16104c8eaf18c565" - "b16c7376030000005219061ab4c5c79489b2cc6a883c146972decb8b000000f5e6d66df46ea13910" - "7754dee62c36d2fc70ccc567df7a49b8585287dc03000000cfb18b2b2cb749e2e03e544d0eb4f73e" - "75039fcf251b32fc79685b05ddd3aa9ba511d2e40edb4d758fb554158ae5c7c0beb42b3403000000" + "5c02af7a000000ee0b06fa9e988f80f0de6dc8dfcf2a3ad3bbcc0fa3b314f695b550c5db03000000" + "f32f4af595d785d5c1b5aad487c192f08b12a09b00000043288cd9bf66ec305a225a0c71b2ce78bb" + "16104c8eaf18c565111d891d03000000cd897619f51f44e644d7cf1d06b2b115d800549e62c12fba" + "5b1cdec48d10bbb13b8313d8cd2a24d34fc812bd2f8a59d90fcc00ac030000005292cd32dc096cd5" + "d8a4c5cf3351ee1cfc03056c00000051bbce426cfa4b861cc78592be7b14e7ba9c15acb881ae55f0" + "b16c7376030000005219061ab4c5c79489b2cc6a883c14697205cb8b000000f5e6d66df46ea13910" + "7754dee62c36d2fc70ccc567df7a49b8e5fe7d360300000066a3ae3939762df33a2d55060c78d551" + "cb0010fd00000041b9aca07b6e4925dd27943a272c171ed15abbbe1cd911db7b86ed271803000000" + "a5edc511c1507a141e0f515638c7ba31f50209450000003357ae79989870ccec3def0ad92749e016" + "663fe6ee0228c1dabb20413203000000862573c2303dd1d65c7b2cffeca6d1adac11e11f0000000f" + "855ebf3b772eb2b1c896c9a7304f66450a5f6abd850b06e382d1595603000000348352d715cf9d41" + "1ea012e5307294b6e301dac4000000075efee38dd16f8ee4ccd2f50c30706cae3fdcc2f0ee3d5e26" + "b10123e6030000001dff045298cfee0636674cdefb57b9ae541de8f4000000381ba2c4396de60f03" + "2bc7f34de2959871c0d4c0d4eb720c4a585287dc03000000cfb18b2b2cb749e2e03e544d0eb4f73e" + "751d9fcf251b32fc79685b05ddd3aa9ba511d2e40edb4d758fb554158ae5c7c0beb42b3403000000" "895d5f24037d233302ad3b82d639272e4a02eadfbd2146bf8cfdb205f90e54b58a6ee136a779f37c" - "30d2c5053c40ecaec38b6b8e03000000bea73223e59bf0193432e9fa7a899f2d8ec7e4b89bf5a5d0" + "30d2c5053c40ecaec38b6b8e03000000bea73223e59bf0193432e9fa7a899f2d8e0ae4b89bf5a5d0" "6776e66a9d80ab132e1ac921eb76adbb229df32e561fa80a0fc4676703000000a23eb66e720da9e0" "7ac998b5690807d52602369ee1af4ca5a6a95581af5fd7ceacdca10f47d7b351a36b178aabc78a4a" "1a0dd8c003000000e2815a1a37a52bddd1c2f1018b587eed720358f0e9201f17bd99fcf72909ac9e" "7a55299e9bb4fd53bc7417940fcffe3f81cafd6302000000d6732578acd14320aefd4503189f7630" - "2403501c0000002b9f3c39f24b0572b100745cb25851429b3bbfb50168dfd04eb62f22ca02000000" - "891715df7fc6a902edae579e2e10c7f7a202a0340436242cbeb0248cee3fbc160032d4f28aa28c08" - "f80dd50c6712dfb4abba4a32020000008ffe423d01883918039249f398f9b37ea091465100000064" - "3722d9b707c0d8a400b7c8307f06b4b29088f20d9ac676d5e4bafc4e02000000fde69eec3af2e6d0" - "bd68ab722af14548b29572e504265f6c72923e22594f3f790008ed2e2ebb0771db46a54cadb245ea" + "2403501c0000002b9f3c39f24b0572b100745cb25851429b3bbfb50168dfd04eabba4a3202000000" + "8ffe423d01883918039249f398f9b37ea0104651000000643722d9b707c0d8a400b7c8307f06b4b2" + "9088f20d9ac676d5b62f22ca02000000891715df7fc6a902edae579e2e10c7f7a202a0340436242c" + "beb0248cee3fbc160032d4f28aa28c08f80dd50c6712dfb4e4bafc4e02000000fde69eec3af2e6d0" + "bd68ab722af14548b20672e504265f6c72923e22594f3f790008ed2e2ebb0771db46a54cadb245ea" "8c3b371502000000710c030690f5f18ea125dbf7d7e93bd65c01a56dfdcfc1155f236c8b9c79a620" "00660bbf024b03ff0a8e27c405e64244e36f90d402000000fd41fe47684b370b6ec6584d64496089" - "570968ead4d1ae91c819bb068196d59900de3246e43f5e7945aaf95e2ffa3a11d1e1b34902000000" - "bcd7be07d78e6222e45aaf61814f703b40125e6b000000cbaaa37b861e6d46dafe7d6ec4ac1ea051" - "010911915ddb05f29c64ed0402000000a660ac824b7fae389861419c50da49bf2b02258300000025" + "570568ead4d1ae91c819bb068196d59900de3246e43f5e7945aaf95e2ffa3a11641e447502000000" + "b9b68c08a5e4351ea349e1ccf662e058b819a45100000045fcb6a035339d504c9726d80d9c2d89df" + "765b4d9a130257dc9c64ed0402000000a660ac824b7fae389861419c50da49bf2b02258300000025" "9f9f0251becc987907879cca68fec7bbbb5f8edf248b4995d184e82002000000a19cdf6dd1c173f6" "078a806d329c9b008b00c972000000f5b2cd3dbddc74e26de958e48d2ab8b0313e7f8933e315130f" - "641e447502000000b9b68c08a5e4351ea349e1ccf662e058b879a45100000045fcb6a035339d504c" - "9726d80d9c2d89df765b4d9a130257dcc43bd794010000005bfe47c6f53a54e01b0c1d89414d94d0" + "d1e1b34902000000bcd7be07d78e6222e45aaf61814f703b401f5e6b000000cbaaa37b861e6d46da" + "fe7d6ec4ac1ea051010911915ddb05f2c43bd794010000005bfe47c6f53a54e01b0c1d89414d94d0" "e0032ec50000000103781b0f294a2b7300421398f4de67e9cee64b38b56e03e01539ce4101000000" "18238487a417f3da01d99dae5f190096cc012cab0000005b2363d13edc5aa115005eb914d8fbe9a4" "fdb3d117d76b0de5bd82e9ea010000003d1b91caae8cb60b49ba9be338d856a40c02c3d400000064" @@ -172,49 +172,49 @@ test_platform_ip_address_pretty_sort_cmp(gconstpointer test_data) "b900b2061d0c334b009f2dd1cdf64b0f9a60e0e289f08db3fde6b0250100000039dd8f88152a5845" "4d9ca9d20f45dfa774028604000000fbcd7db68b9ae586da00b4070c50320427c4dd3d031e33f22c" "210aeb09010000007000b96d06992b6a58acd3995b9663d2df02f333ef467092818aa77d6732b678" - "00844ef5a943825fcd743f59bd14c89b955e1a13010000007acbce3e3bcdf3824f1b134847ff26ba" - "4400774900000017ec852d59f3d17232edd86ad6c3103a68843a9aef34983882d3d3878501000000" - "5e0dfe491d1ba96742c7b5e02b2271229c01b02a06d0dc5504b0595daf37deb499996bfb667f072d" - "ec1e5d9cdc8a11f4409bcfb30100000099d90a8543961b2ccd47724a3c460ba85103f4c500000063" - "eafb1ac4c0982b283aa9986700b2a2b3ed257b8b0489f48f053ec8ca0100000027335a25a364d101" - "5ffac03089f45539e1021784000000d7b83579b8da27345a72437f9b6245de39ec9e71ee4b951507" - "f121014a01000000efc67bce716c856e3973dc42a1003be94f89d8ee0000009b5d5bbe6c10085f3d" - "6176f78a19bb8df1804c122fce5078c156e8f3fe010000000ea8042602a1f8e6f5657f3f9e3eb807" - "cbad7645000000b8df6f628a70456d79f25d5895fb57fa60d9279fb2b8fcbac65ad47b8a01000000" - "da40d88d40a6d75bc404156225b7eedefc2b44574b15e2ae496ad01bf007eacb0a28aec868282510" - "b60291ea6480e356925b568a0000000087bb24e5264fd3ebe9cf9f6df9615189f701e815000000a7" - "5c9555876b6a3f13002b6cb8360feaac1d5c302df59dd32a7a859db500000000362956cd46646a0e" - "222160e5f769bb295703ed370000005b6a813387e99bb834009da86c64fefab2548759d313a5b92d" - "8e47935e0000000034f0386a253c21d94064f6b021281e235f00ae20000000d71fd050bf8d85055b" - "00e3756ccdb3455c60ca7b11c66af76e594f24a100000000e143fd52599364e13468f80fd514573f" - "b572671c0000006932d1d5f5d0ce2cf6007a70ba5193a162bc92ec1b11d9172c857ae81200000000" - "3e29535402e9b690c628d048eacce745ea213cb1000000b632ef3be6070dafa200187470e9da5570" - "9427c226d324d9a08487fd0d00000000b7a350f9fc1519defa7db4532545666937c22a3b000000dc" + "00844ef5a943825fcd743f59bd14c89bf121014a01000000efc67bce716c856e3973dc42a1003be9" + "4f0ed8ee0000009b5d5bbe6c10085f3d6176f78a19bb8df1804c122fce5078c1955e1a1301000000" + "7acbce3e3bcdf3824f1b134847ff26ba4400774900000017ec852d59f3d17232edd86ad6c3103a68" + "843a9aef34983882d3d38785010000005e0dfe491d1ba96742c7b5e02b2271229c01b02a06d0dc55" + "04b0595daf37deb499996bfb667f072dec1e5d9cdc8a11f4409bcfb30100000099d90a8543961b2c" + "cd47724a3c460ba85103f4c500000063eafb1ac4c0982b283aa9986700b2a2b3ed257b8b0489f48f" + "053ec8ca0100000027335a25a364d1015ffac03089f45539e1021784000000d7b83579b8da27345a" + "72437f9b6245de39ec9e71ee4b95150756e8f3fe010000000ea8042602a1f8e6f5657f3f9e3eb807" + "cb067645000000b8df6f628a70456d79f25d5895fb57fa60d9279fb2b8fcbac65ad47b8a01000000" + "da40d88d40a6d75bc404156225b7eedefc1e44574b15e2ae496ad01bf007eacb0a28aec868282510" + "b60291ea6480e356594f24a100000000e143fd52599364e13468f80fd514573fb517671c00000069" + "32d1d5f5d0ce2cf6007a70ba5193a162bc92ec1b11d9172c925b568a0000000087bb24e5264fd3eb" + "e9cf9f6df9615189f701e815000000a75c9555876b6a3f13002b6cb8360feaac1d5c302df59dd32a" + "7a859db500000000362956cd46646a0e222160e5f769bb295703ed370000005b6a813387e99bb834" + "009da86c64fefab2548759d313a5b92d8e47935e0000000034f0386a253c21d94064f6b021281e23" + "5f00ae20000000d71fd050bf8d85055b00e3756ccdb3455c60ca7b11c66af76e857ae81200000000" + "3e29535402e9b690c628d048eacce745ea053cb1000000b632ef3be6070dafa200187470e9da5570" + "9427c226d324d9a08487fd0d00000000b7a350f9fc1519defa7db45325456669371e2a3b000000dc" "c405cbee5016c25200d8901d7a0165fe20744edb6ba04f14a4c73cf500000000a4bab14874afdf54" - "e6aae816430607ca0675e09818e9bbec5918c59068baf76a008940f6fc3bbdc7f6090f756aae660b" + "e6aae816430607ca061fe09818e9bbec5918c59068baf76a008940f6fc3bbdc7f6090f756aae660b" "6e4c699300000000d9c1e67743efb54e54270e46042e91186a034e38000000376feecb80ac245409" "c0becc271d9c2f67179bff0644399ae7df6b3542000000004c5cf8107ba282f4f983821918f93e74" - "2d08f0550000006f2292362e5d68265d9f98c82d9b7a559be3acf4fc36fa6b51e3c9472e00000000" + "2d00f0550000006f2292362e5d68265d9f98c82d9b7a559be3acf4fc36fa6b51e3c9472e00000000" "c5cfd9f2343b21362c19a0921dce2f839200fa45000000270b9977e166bee737fe73670c439a644c" - "323b59b4cd20eb7dabea74f700000000f6989d2d6a909e986ff7add5df2c93e05459507b0000000f" - "466554d2ae4d52a8c67b2e48b47003c81785d3ffdbd9a61759747cf200000000ab2dadc5a39411fd" - "4ff1116d478987316a553fc2000000cfc6ebe434a7ae8ff040483e310819e3b10db116431ec6f769" - "438a72e1000000002495a609675344f7e2e3a5ebaec3c85f0a1742f70abe95c50345132a61eda239" - "d9d083c3bf085387046ef8a36f0e9e696b382ab0000000009a6ce5d906837dbca6a5ee19d6f63fe9" + "323b59b4cd20eb7dabea74f700000000f6989d2d6a909e986ff7add5df2c93e05412507b0000000f" + "466554d2ae4d52a8c67b2e48b47003c81785d3ffdbd9a617438a72e1000000002495a609675344f7" + "e2e3a5ebaec3c85f0a0042f70abe95c50345132a61eda239d9d083c3bf085387046ef8a36f0e9e69" + "59747cf200000000ab2dadc5a39411fd4ff1116d478987316a1f3fc2000000cfc6ebe434a7ae8ff0" + "40483e310819e3b10db116431ec6f7696b382ab0000000009a6ce5d906837dbca6a5ee19d6f63fe9" "cb0301f7246f13b2050424a2b3a45ef7a029c896b4132bd895072cfeffe9d6815997069500000000" "0d3c723b91adb0da7c4aa7e7eb5a15bcde035fb98b841fd84cc43c510385b9a4c2aac1d67a909b29" - "7c703915312e9c3cae02dfa000000000dd603bd35e7fa0f02f2f3313d8469d09a92409c0b7f0318a" + "7c703915312e9c3cae02dfa000000000dd603bd35e7fa0f02f2f3313d8469d09a91709c0b7f0318a" "575a4f8e061db3dd7fde25654a4059d565dbc8a91e3b4457b077ddad3108be69f9b97d05c917ad6b" - "10e693bb6e26f2ba90c8e909a9fe20e5c7a4c656482a9b0d00625009a40aeb62a42b6a62548e3c38" + "10e693bb6e26f2ba900fe909a9fe20e5c7a4c656482a9b0d00625009a40aeb62a42b6a62548e3c38" "cd3c72f203000000ca82ac5180101be4f85cef468ea086ea9a01fdc3a9fe1ec787bc45db7c52a52d" "00bd39a44e8e8bc17c01ac63eca0c1cf5ff7f03a03000000c9a89192c1c8be55281a59d1fd338f35" - "7e00f8cea9fec34573654ea6624f138ef9531cd9367a02e4d241989477a363d53b02239e03000000" - "24438387def0f4c6544e4b275d9b7146a70010d2a9fec17647176b7c07d856e3b883efebc09dd9d6" - "1966b7ae7412041d57393c6f03000000182c0287822a272bec4501a1e27acfee7a0188ffa9fe6cae" - "426de59560fad65d67c624f285d7174177a47579dda0b6eaa9a84c820300000070b1646d8026e9f1" - "704f1b16286ba2dabc01f082a9feed33ef60a8b540b26f66761d1f13badfad0fe8fa8f3c1aad2a82" - "fa40546c03000000df2d7c2790d3119a051bb2ee8192ac0cfa3abc1ea9fe3e7d75a2f42b50c6a363" - "40132378b95c59313bacba64dbe996206e6904f50200000047150b9b14010469823acb72bb89182f" + "7e00f8cea9fec34573654ea6624f138ef9531cd9367a02e4d241989477a363d5fa40546c03000000" + "df2d7c2790d3119a051bb2ee8192ac0cfa00bc1ea9fe3e7d75a2f42b50c6a36340132378b95c5931" + "3bacba64dbe996203b02239e0300000024438387def0f4c6544e4b275d9b7146a70010d2a9fec176" + "47176b7c07d856e3b883efebc09dd9d61966b7ae7412041d57393c6f03000000182c0287822a272b" + "ec4501a1e27acfee7a0188ffa9fe6cae426de59560fad65d67c624f285d7174177a47579dda0b6ea" + "a9a84c820300000070b1646d8026e9f1704f1b16286ba2dabc01f082a9feed33ef60a8b540b26f66" + "761d1f13badfad0fe8fa8f3c1aad2a826e6904f50200000047150b9b14010469823acb72bb89182f" "93002196a9feb9153b36bc60be5b534e006527f67485ab35aca0c7ee419733853cf09e8b02000000" "e79c10acfce165e332a62384ec04e5bab40085ada9fe0070a36dd51323b2c54200154d12f86c260a" "9edfa7a74c1c83c1050f63f802000000443cacf59c6379a44b7892f487afa98cb102c19ca9fe942f" @@ -222,7 +222,7 @@ test_platform_ip_address_pretty_sort_cmp(gconstpointer test_data) "36506ebd455e679cef009bb8a9fecec3f8c8fa6867a982be8a934f852cc3d4d82bc0ec7303f99f8f" "def85b7502000000a0bef8675b29a197b7b3cceaf5f1bb12c503256aa9fe6e5d58099ffc4a503a71" "2350acbd48411f0dc15d2f0f49dad345d966279502000000e06302aba042aaa218dc091e9aa1477f" - "6fdc9830a9fec95829a8838314dff34d24c332219a1b163a732d803e0e2f4f916d06412601000000" + "6f059830a9fec95829a8838314dff34d24c332219a1b163a732d803e0e2f4f916d06412601000000" "98c39e7cc282208fefc57ff447036b955101cb22a9fe793f797a3c7dadd1c86e009d0c90bc512e13" "7dcef5e4a27985bd5cfd5ce601000000152f2b70eaef7443e0f79ab6902dde533601ec71a9fe9f25" "4ac95883195580410062ed564153e17478f8c3344d89c0bbfaa100fd01000000be184524a6bdc878" @@ -230,7 +230,7 @@ test_platform_ip_address_pretty_sort_cmp(gconstpointer test_data) "0d80684e01000000ba8110fb9733cc24904f288262e6ea77a203a5f8a9feeefa701d120523bd98f2" "00098b43cd68be6e3f81268193fd637e9037d7a701000000c47cf0f551e96770a754ac19ef820fe0" "2900f2d3a9fe049150b8d10ab700cc3a7cf51be0403b654ba2f56808092069af5f5b481b01000000" - "68cb3bc873b04d937a6ed8f7bc51e54066fed098a9fe048a92d3adc69a84eb47622400207799416a" + "68cb3bc873b04d937a6ed8f7bc51e5406617d098a9fe048a92d3adc69a84eb47622400207799416a" "f1f0a086fbd7e2f7dea0077a00000000c386e9c6e6a2cbfa10ee58bdc75183609900d627a9feb1cb" "e491cbbbf9443fd6007eb3c5bf64b671d6f18dbf463f9b83f512dc1c00000000fbab244735d67c61" "283031667b2d74a10302b1b1a9fe2aa590a2312e17f1a35900459582f4ef43c780908872746e39ef" @@ -241,306 +241,306 @@ test_platform_ip_address_pretty_sort_cmp(gconstpointer test_data) "3215abf8fbdf17c3677e5a3a00000000608df061d45d864d09f4ecf17625f82da1034828a9fe1e37" "1051852c972ea7954079884af257b044fd13a6826a4c619f3d136cac000000009402a4c216772167" "3f2b02b3256ead1f2f039bc1a9fefca162fb81e733cff620ca7feefe1933631e8e69f6d9d6962d2c"), - [1] = ("54270e46020000006a894e387625da376feecb80ac245409c0becc271d9c2f67179bff0644399ae7" + [1] = ("54270e46020000006a894e387625da376feecb80ac245409c058cc271d9c2f67179bff0644399ae7" "9c64ed0432d599eaa660ac824b7fae389861419c7a899f2d010000009bf5a5d06776e66a9d80ab13" - "2e1ac921eb76adbb229df32e561fa80a40e55b8b1dd92e18c0cfb2b4386bec092fa5757ecde9348b" - "c4e1966800000000b3121cd5ef51e696c816290dbaee0e7726d082e1530ff5397c9125f59577d71c" + "2e1ac921eb04adbb229df32e561fa80a40e55b8b1dd92e18c0cfb2b4386bec092fa5757ecde9348b" + "c4e1966800000000b3121cd5ef51e696c816290dbaee0e77264c82e1530ff5397c9125f59577d71c" "4b258a005116d11354edff62ceaa458fc75a91c425a5927300000000c4458d70911714f1819aa46f" - "be143934c933ae6dec0fb124f264af67eed7c9a8c38b6b8ee2614344bea73223e59bf0193432e9fa" - "4cc43c5103000000c2aac1d67a909b297c703915312e9c3c5a06c40b20ea99d5ab90135fa636af44" + "be143934c915ae6dec0fb124f264af67eed7c9a8c38b6b8ee2614344bea73223e59bf0193432e9fa" + "4cc43c5103000000c2aac1d67a909b297c703915312e9c3c5a64c40b20ea99d5ab90135fa636af44" "64d210a256be75e0509c4477d19ac64b2e69220d12ea3b9501000000fb95e8332fdfff658483a2d0" - "39a7bf148ed3481e0bccc460e89f7abdb682380a62eae374835b4a49a2b980b6aba92da6409969aa" - "288cd9bf00000000225a0c71b2ce78bb16104c8eaf18c565ecc8fb112087b97cfcebbaeb0c565359" + "39a7bf148e4c481e0bccc460e89f7abdb682380a62eae374835b4a49a2b980b6aba92da6409969aa" + "288cd9bf00000000225a0c71b2ce78bb16104c8eaf18c565ec5ffb112087b97cfcebbaeb0c565359" "23f14874042a8aff1d1f8e5ec3cc13cc36bbe3c9bb0ec36f0000000064a2827b7cdd38d0314c178e" - "925b568ae56bc4e9fefb24e5264fd3ebe9cf9f6df9615189f78ee815b2781ea55c9555876b6a3f13" - "02e9b69000000000eacce745ea213cb1a84035b632ef3be6070dafa2fed87470e9da55709427c226" + "925b568ae566c4e9fefb24e5264fd3ebe9cf9f6df9615189f78ee815b2781ea55c9555876b6a3f13" + "02e9b69000000000eacce745ea213cb1a84035b632ef3be60755afa2fed87470e9da55709427c226" "d324d9a086ed27184b443181a5edc511c1507a142fea9bc10300000062fb81e733cff620ca7feefe" - "1933631e8e69f6d9fed62d2c6e6904f57239c09c47150b9b14010469823acb72bb89182f93112196" - "9985d62700000000e491cbbbf9443fd6a77eb3c5bf64b671d6f18dbffeff9b8306c83bc026977911" + "1933631e8e18f6d9fed62d2c6e6904f57239c09c47150b9b14010469823acb72bb89182f93112196" + "9985d62700000000e491cbbbf9443fd6a77eb3c5bf64b671d6098dbffeff9b8306c83bc026977911" "4bdade862c224f6f36506ebd455e679cef369bb8d514573f03000000f6932f6932d1d5f5d0ce2cf6" - "bf7a70ba5193a162fe92ec1b11d9172cf84a03478b82cdd8883b0f3fd6ed84d6c959e553b887edcd" - "6297dfa700000000fd0d53bb6215de4bb6f6f3d031a790287e45e9c1feb836c0a25ea71f5daaed4d" + "bf7a70ba5111a162fe92ec1b11d9172cf84a03478b82cdd8883b0f3fd6ed84d6c959e553b887edcd" + "6297dfa700000000fd0d53bb6215de4bb6f6f3d031a790287e7be9c1feb836c0a25ea71f5daaed4d" "99eb2ebebe3c432fec7d3abc4ccf30d3aaaf02a41e0f515601000000f57609453df7803357ae7998" - "9870ccec3def0ad9000000000000000000000000000000019f05a16768cb3bc873b04d937a6ed8f7" - "ae8cb60b0300000038d856a40c67c3d4afa9c8649da90bd2fff2f256000000000000000000000000" + "9870ccec3d4f0ad9000000000000000000000000000000019f05a16768cb3bc873b04d937a6ed8f7" + "ae8cb60b0300000038d856a40c67c3d4afa9c8649da90bd2ff4cf256000000000000000000000000" "00000001955e1a13d1111b067acbce3e3bcdf38200154d12010000009edfa7a74c1c83c18e47935e" - "8354846e34f0386a00000000000000000000000000000001ac26c7d41fd050bf8d85055bcfe3756c" - "a2f56808092069affaa100fdfdd68d34be184524a6bdc8789cf85178000000000000000000000000" + "8354846e346e386a00000000000000000000000000000001ac26c7d41fd050bf8d85055bcfe3756c" + "a2f56808092069affaa100fdfdd68d34be184524a6bdc8789c575178000000000000000000000000" "00000000020ffdb0e612098610e52bb2a16a40086f0e9e6903000000ec2e2924348352d715cf9d41" - "1ea012e5307294b600000000000000000000000000000000ccd2f50c30706cae3fdcc2f0ee3d5e26" - "81ae55f0030000000aa20624fbab244735d67c61283031667b2d74a1000000000000000000000000" + "1ea012e5305a94b600000000000000000000000000000000ccd2f50c30706cae3fdcc2f0ee3d5e26" + "81ae55f0030000000aa20624fbab244735d67c61283031667b2274a1000000000000000000000000" "0000000000459582f4ef43c780908872746e39efaefd545b020000007ced4f8b362956cd46646a0e" - "222160e5f769bb2900000000000000000000000000000000a19da86c64fefab2548759d313a5b92d" - "f05d7308020000009d82c856ba942455050f63f8282f3464443cacf5000000000000000000000000" + "222160e5f749bb2900000000000000000000000000000000a19da86c64fefab2548759d313a5b92d" + "f05d7308020000009d82c856ba942455050f63f8282f34644466acf5000000000000000000000000" "0000000069d9942f460bcea75481f25e307d0de96e91b91501000000be5b534e0a6527f67485ab35" - "aca0c7ee4197338500000000000000000000000000000000aefd4503189f7630248e501c9052c22b" - "5d68265d010000009b7a559be3acf4fc36fa6b513cf09e8b99289462000000000000000000000000" + "aca0c7ee4167338500000000000000000000000000000000aefd4503189f7630248e501c9052c22b" + "5d68265d010000009b7a559be3acf4fc36fa6b513cf09e8b99729462000000000000000000000000" "00000000b49185ad9b7d0070a36dd51323b2c542e5fe7d360100000066a3ae3939762df33a2d5506" - "0c78d551cbb110fd000000000000000000000000000000002c171ed15abbbe1cd911db7b56e8f3fe" - "9a6ce5d900000000a6a5ee19d6f63fe9cbdd01f7246f13b2050424a2000000000000000000000000" + "0c78d551cb7410fd000000000000000000000000000000002c171ed15abbbe1cd911db7b56e8f3fe" + "9a6ce5d900000000a6a5ee19d6f63fe9cbdd01f7246f13b2055624a2000000000000000000000000" "00000000ffe9d6812231bb02f922259b173c333cbae87d60000000005d31e5b2de252167c1c91b3a" - "36ba0c700ee78477000000000000000000000000000000006ad0143a0554efb46b382ab0404cdf02" - "7c52a52d030000004e8e8bc17c01ac63eca0c1cfbb204132fb7213e4000000000000000000000000" + "36ba0c700e538477000000000000000000000000000000006ad0143a0554efb46b382ab0404cdf02" + "7c52a52d030000004e8e8bc17c01ac63eca0c1cfbb204132fb0813e4000000000000000000000000" "00000000accae11f8045a80f855ebf3b772eb2b1d03bc90503000000eb760e3f004a2efc8ffc96b8" - "9b1bc8f415bd4e7700000000000000000000000000000000d149f074a378b881153ece68ade15cec" - "7666c05303000000ffa8e89871fb9510b900b2061d0c334b819f2dd1000000000000000000000000" + "9b1bc8f415174e7700000000000000000000000000000000d149f074a378b881153ece68ade15cec" + "7666c05303000000ffa8e89871fb9510b900b2061d0c334b816a2dd1000000000000000000000000" "00000000095a3230fde69eec3af2e6d0bd68ab7210613fc90200000016a31dc2e46a234558817151" - "b38fc9c909cf8d7100000000000000000000000000000000ae17bb4515856092b4d9e89b676761b2" - "57d6249b020000007dc7f17f666969e45c3baf7a119a65ee0b06fa9e000000000000000000000000" + "b38fc9c9093c8d7100000000000000000000000000000000ae17bb4515856092b4d9e89b676761b2" + "57d6249b020000007dc7f17f666969e45c3baf7a119a65ee0b08fa9e000000000000000000000000" "00000000b314f695bd82e9ea8891ed0a3d1b91cab56e03e0010000002f70249eefc67bce716c856e" "3973dc42a1003be9000000000000000000000000000000006176f78a19bb8df1804c122fce5078c1" - "eecc89f601000000d635edea8ffe423d01883918039249f398f9b37e000000000000000000000000" + "eecc89f601000000d635edea8ffe423d01883918039249f3984ab37e000000000000000000000000" "000000001fb7c8307f06b4b29088f20d9ac676d5f90e54b501000000a779f37c30d2c5053c40ecae" - "210aeb0934cb2a2400000000000000000000000000000000df48f333ef467092818aa77d6732b678" - "bcd7be0700000000e45aaf61814f703b40125e6baf4648cbaaa37b86000000000000000000000000" + "210aeb0934392a2400000000000000000000000000000000df48f333ef467092818aa77d6732b678" + "bcd7be0700000000e45aaf61814f703b40125e6baf4648cbaa557b86000000000000000000000000" "000000005ddb05f2a84e27c18a06e2c9cb29efdf50da49bf00000000d94beb259f9f0251becc9879" - "07879cca68fec7bb000000000000000000000000000000009402a4c2167721673f2b02b3256ead1f" - "a349e1cc00000000b879a45176740744fcb6a035339d504c9726d80d000000000000000000000000" + "07879cca6857c7bb000000000000000000000000000000009402a4c2167721673f2b02b3256ead1f" + "a349e1cc00000000b879a45176740744fcb6a035339d504c972bd80d000000000000000000000000" "000000009518862bc9a89192c1c8be55281a59d1ebfdcec30000000067a982be8a934f852cc3d4d8" - "2bc0ec7303f99f8f00000000000000000000000000000000901f55f960c55c22f32099a8020bea2a" - "5b1aea3401000000c7c3523f76cf1ce34ca17a9a32f3f0f218424e48000000000000000000000000" + "2bc0ec7303579f8f00000000000000000000000000000000901f55f960c55c22f32099a8020bea2a" + "5b1aea3401000000c7c3523f76cf1ce34ca17a9a32f3f0f2187c4e48000000000000000000000000" "00000002e6fbf952902383028e3b47f2111d891d536c75bb01000000720da9e07ac998b5690807d5" - "2617369ee1af4ca500000000000000000000ffff47d7b351a36b178aabc78a4a0d80684ee5dbf45b" - "17a4763102000000f9119c40b468b66331bca67a034f43340d01683c00000000000000000000ffff" + "2617369ee16d4ca500000000000000000000ffff47d7b351a36b178aabc78a4a0d80684ee5dbf45b" + "17a4763102000000f9119c40b468b66331bca67a034f43340d2c683c00000000000000000000ffff" "b24a5be9b10123e6e4f15ecd1dff045298cfee069c88b02a0300000004b0595daf37deb499996bfb" - "667f072dec1e5d9cdc8a11f4409bcfb3c167090e99d90a8543961b2ccd47724a3c460ba85183f4c5" - "a7afe28302000000d05ff720b16c73761a3fcb675219061ab4c5c79489b2cc6a883c146972decb8b" + "667f072dec755d9cdc8a11f4409bcfb3c167090e99d90a8543961b2ccd47724a3c460ba85183f4c5" + "a7afe28302000000d05ff720b16c73761a3fcb675219061ab466c79489b2cc6a883c146972decb8b" "5adac8f5e6d66df46ea139107754dee62c36d2fcc7a4c65601000000cd625009a40aeb62a42b6a62" - "548e3c38b96c20022753c5fbfaf1809becd2506315a6da29b2e94d3ab51fe0e9af98b180a36035fb" - "e36f90d401000000fd41fe47684b370b6ec6584d64496089570968ead4d1ae91c819bb068196d599" + "548e3c38b96620022753c5fbfaf1809becd2506315a6da29b2e94d3ab51fe0e9af98b180a36035fb" + "e36f90d401000000fd41fe47684b370b6ec6584d64496089574568ead4d1ae91c819bb068196d599" "efde3246e43f5e7945aaf95e2ffa3a11b9ef1b21cdb3455c00000000c66af76e80f062ea1a7e0b7b" - "e218d067530e1b0487b8c3b99f2b8a1a8982c42f53700a3437c5156e072b2f2fb337c9cfe07c34dd" - "c896c9a7000000000a5f6abd850b06e3d9662795ce2cc1cee06302aba042aaa218dc091e9aa1477f" + "e218d067532d1b0487b8c3b99f2b8a1a8982c42f53700a3437c5156e072b2f2fb337c9cfe07c34dd" + "c896c9a7000000000a5f6abd850b06e3d9662795ce2cc1cee03202aba042aaa218dc091e9aa1477f" "6fdc9830d7fbc95829a8838314dff34d24c332214d4647f5000000000f88e3759a08e7a56663861e" - "ea1bf42ccd3c72f2ad063857ca82ac5180101be4f85cef468ea086ea9aaafdc388811ec787bc45db" - "7625ca4a00000000e682f80f94315c45ef817264c89a736ed55ed637b077ddad3108be69f9b97d05" + "ea1bf42ccd1172f2ad063857ca82ac5180101be4f85cef468ea086ea9aaafdc388811ec787bc45db" + "7625ca4a00000000e682f80f94315c45ef817264c89a736ed580d637b077ddad3108be69f9b97d05" "c917ad6b10e693bb6e26f2ba90c8e909e85e20e5b0916e5d030000004a503a712350acbd48411f0d" - "c15d2f0f49dad345599706954d2471f00d3c723b91adb0da7c4aa7e7eb5a15bcde015fb98b841fd8" - "ba8110fb03000000904f288262e6ea77a22fa5f863eaeefa701d120523bd98f29b098b43cd68be6e" + "c15d2f0f4952d345599706954d2471f00d3c723b91adb0da7c4aa7e7eb5a15bcde015fb98b841fd8" + "ba8110fb03000000904f288262e6ea77a22fa5f863eaeefa700b120523bd98f29b098b43cd68be6e" "3f81268193fd637e585287dc6ca972a2cfb18b2b3cae864b0200000091921681c2162b9bfa40546c" - "db544e44df2d7c2790d3119a051bb2ee8192ac0cfa3abc1ea0ab3e7d75a2f42b50c6a36340132378" - "8c3b371502000000710c030690f5f18ea125dbf7d7e93bd65c1fa56dfdcfc1155f236c8b9c79a620" + "db544e44df587c2790d3119a051bb2ee8192ac0cfa3abc1ea0ab3e7d75a2f42b50c6a36340132378" + "8c3b371502000000710c030690f5f18ea125dbf7d7e93bd65c03a56dfdcfc1155f236c8b9c79a620" "5f660bbf024b03ff0a8e27c405e6424457393c6fdac12ebd01000000667224dae775e5ccd141aca2" - "ff0f576767d3648102b61886b62f22ca33478e1f891715df7fc6a902edae579e2e10c7f7a22ba034" - "abf85f0c0100000008d33a2ea67776d7f88d69c8c7e3b2d3c93ef054e93f8120abb42316c533d9c9" + "ff0f57676754648102b61886b62f22ca33478e1f891715df7fc6a902edae579e2e10c7f7a22ba034" + "abf85f0c0100000008d33a2ea67776d7f88d69c8c7e3b2d3c951f054e93f8120abb42316c533d9c9" "4d88189c471a1ff2f0ce3ff66e782110125ae2eddaae7d6300000000c0982b283aa9986700b2a2b3" - "ed257b8b0489f48f053ec8cac72105b327335a25a364d1015ffac03089f45539e1b0178462156cd6" - "6855676c00000000017c9148da5892bb4951c3a7ed55689d3391ce7d3fd48469845f0c233dbdd2a9" + "ed257b8b042ff48f053ec8cac72105b327335a25a364d1015ffac03089f45539e1b0178462156cd6" + "6855676c00000000017c9148da5892bb4951c3a7ed55689d336bce7d3fd48469845f0c233dbdd2a9" "7835df1f1782dee88487fd0db5971b46b7a350f998c39e7c00000000efc57ff447036b9551adcb22" - "fd50793f797a3c7dadd1c86e759d0c90bc512e137dcef5e4a27985bd8d1e69c83dc21056b973972c" - "bc51e540030000006c3d048a92d3adc69a84eb47622400207799416afef0a086fbd7e2f7dea0077a" + "fd50793f791c3c7dadd1c86e759d0c90bc512e137dcef5e4a27985bd8d1e69c83dc21056b973972c" + "bc51e540030000006c3d048a92d3adc69a84eb47622400207708416afef0a086fbd7e2f7dea0077a" "e9c0c0d9c386e9c6e6a2cbfa10ee58bdc75183600422ae3f03000000c43bd794c697895e5bfe47c6" - "f53a54e01b0c1d89fecd94d0e02d2ec587fc330003781b0f294a2b73c4421398f4de67e9cee64b38" - "69121aec010000000fcc00ac2daa755e5292cd32dc096cd5d8a4c5cffe91ee1cfcc2056cc1ff8e51" + "f53a54e01b211d89fecd94d0e02d2ec587fc330003781b0f294a2b73c4421398f4de67e9cee64b38" + "69121aec010000000fcc00ac2daa755e5292cd32dc096cd5d830c5cffe91ee1cfcc2056cc1ff8e51" "bbce426cfa4b861cc78592be7b14e7ba9c15acb836674cde0200000054cfe8f42bf0e9381ba2c439" - "6de60f032bc7f34dfe959871c0d4c0d4eb720c4ae3c9472e5f2da5d9c5cfd9f2343b21362c19a092" - "b2cd3dbd01000000e958e48d2ab8b0313e7f8933e315130fa9a84c82feb83f6e70b1646d8026e9f1" + "6de60f032b5af34dfe959871c0d4c0d4eb720c4ae3c9472e5f2da5d9c5cfd9f2343b21362c19a092" + "b2cd3dbd01000000e958e48d2ab8b0313e7f8933e315130fa9274c82feb83f6e70b1646d8026e9f1" "704f1b16286ba2dabc7ef0820c91ed33ef60a8b5bcfe97e1000000007ad742d3d7320a4f880cf47f" - "5dd0cf69cb22840ffeb3fe7749509cb6752b2cee30b7e7736a0afc9879ea40e69710fc9f6e8e99cd" - "1dce2f83020000003a3efc240b9977e166bee737fe73670c439a644c000000000000000000000000" + "5dd0cf69cb7f840ffeb3fe7749509cb6752b2cee30b7e7736a0afc9879ea40e69710fc9f6e8e99cd" + "1dce2f83020000003a3efc240b9977e166bee737fe73670c436b644c000000000000000000000000" "000000015e0dfe491d1ba96742c7b5e02b227122cf844ef501000000cd743f59bd14c89b5cfd5ce6" - "e82e7854152f2b700000000000000000000000000000000127e19f254ac9588319558041fc62ed56" - "b83579b80300000072437f9b6245de39ec9e71ee4b951507beb42b34000000000000000000000000" + "e82e7854157b2b700000000000000000000000000000000127e19f254ac9588319558041fc62ed56" + "b83579b80300000072437f9b6245de39ec9e71ee4b951507be0a2b34000000000000000000000000" "00000001d639272e4a46eadfbd2146bf8cfdb205b3980deb020000006c1de913df1424ce3ee1d76f" - "c1ea76e98c9dfc7800000000000000000000000000000001e44ea74b4f2b83f9b3bee14d861a4c9e" - "0436242c03000000ee3fbc164632d4f28aa28c08f80dd50c6712dfb4000000000000000000000000" + "c1ea76e98c16fc7800000000000000000000000000000001e44ea74b4f2b83f9b3bee14d861a4c9e" + "0436242c03000000ee3fbc164632d4f28aa28c08f80dd50c6705dfb4000000000000000000000000" "00000000078a806d329c9b008bbfc9723107f3f52af145480300000004265f6c72923e22594f3f79" - "e208ed2e2ebb07710000000000000000000000000000000039dd8f88152a58454d9ca9d20f45dfa7" - "922b6cb8030000001d5c302df59dd32a677e5a3af4fe297f608df061000000000000000000000000" + "e208ed2e2e7107710000000000000000000000000000000039dd8f88152a58454d9ca9d20f45dfa7" + "922b6cb8030000001d5c302df59dd32a677e5a3af4fe297f6042f061000000000000000000000000" "000000008ae21e371051852c972ea7954079884a9a1b163a030000000e2f4f911a0dd8c052ed6b13" - "e2815a1a37a52bdd00000000000000000000000000000000bd99fcf72909ac9e7a55299e9bb4fd53" - "9f3c2c8803000000f51f44e644d7cf1d06b2b115d882549e62c12fba000000000000000000000000" + "e2815a1a37322bdd00000000000000000000000000000000bd99fcf72909ac9e7a55299e9bb4fd53" + "9f3c2c8803000000f51f44e644d7cf1d06b2b115d882549e62042fba000000000000000000000000" "000000004fc812bd2f8a59d96d064126666befbbf257b044030000006a4c619f9037d7a754655354" - "c47cf0f551e967700000000000000000000000000000000050b8d10ab700cc3a7cf51be0403b654b" - "74e7860402000000cd7db68b9ae586dacdb4070c50320427c4dd3d03000000000000000000000000" + "c47cf0f5512167700000000000000000000000000000000050b8d10ab700cc3a7cf51be0403b654b" + "74e7860402000000cd7db68b9ae586dacdb4070c50320427c4803d03000000000000000000000000" "00000000d538d34574c038404923e75d0e09e2fcfc1519de010000002545666937c22a3b6e9686dc" - "c405cbee5016c252000000000000000000000000000000006e4c699341b95f41d9c1e67743efb54e" - "6aae660b01000000fc1fb23d24438387def0f4c6544e4b275d9b7146000000000000000000000000" + "c405cbee504dc252000000000000000000000000000000006e4c699341b95f41d9c1e67743efb54e" + "6aae660b01000000fc1fb23d24438387def0f4c6544e4b275d4a7146000000000000000000000000" "00000000b883efebc09dd9d61966b7ae7412041dd7ac5f9901000000822a272bec4501a1e27acfee" - "7a8588ffd5a06cae0000000000000000000000000000000077a47579dda0b6ead1e1b34901eaedd5" - "61c2f5d200000000b809d259e499db7dc8f1853bdcb0e4bc0e2b00b6000000000000000000000000" + "7a8588ffd5286cae0000000000000000000000000000000077a47579dda0b6ead1e1b34901eaedd5" + "61c2f5d200000000b809d259e499db7dc8f1853bdcb0e4bc0e0e00b6000000000000000000000000" "000000005e7fa0f02f2f3313d8469d09a92409c0b4d54acb00000000a417f3da01d99dae5f190096" - "cc582cabd5ddd15a00000000000000000000000000000000fdb3d117d76b0de5416f95e7bb75d72f" - "fc2b445700000000496ad01bf007eacb0a28aec868282510b60291ea000000000000000000000000" + "cc582cabd534d15a00000000000000000000000000000000fdb3d117d76b0de5416f95e7bb75d72f" + "fc2b445700000000496ad01bf007eacb0a28aec868282510b61b91ea000000000000000000000000" "000000005b29a197b7b3cceaf5f1bb12c535256a74993ade03000000e62112898dab2dade2ab2fc9" - "c56a7c86be5f962200000000000000000000000000000000bdd06352cb2c354434819f4b248eb2b8" - "dc335c8b030000000a3c8e7c91bf821c4b09cee3c37ff4283a631480000000000000000000000000" + "c56a7c86be73962200000000000000000000000000000000bdd06352cb2c354434819f4b248eb2b8" + "dc335c8b030000000a3c8e7c91bf821c4b09cee3c37ff4283a0c1480000000000000000000000000" "000000005588456e4ead7cbda620a3abae816e34e3ff1a5f03000000b4425486c619147eb0216050" - "ed7afd741024e83600000000000000000000000000000000f493472201e48d163106cc397446a33f" - "bc74179403000000438a72e12ae0436a2495a609675344f7e2e3a5eb000000000000000000000000" + "ed7afd74105fe83600000000000000000000000000000000f493472201e48d163106cc397446a33f" + "bc74179403000000438a72e12ae0436a2495a609675344f7e226a5eb000000000000000000000000" "0000000061eda239d9d083c3bf085387046ef8a34153e174020000004d89c0bb5408c1b7d17fb084" - "d9e1825fa638e1af000000000000000000000000000000006e08cb887464b9344ec3127c750fabdd" - "6c0fc09c02000000809829af4a9df58dbfef186d416f3a1ef170d10f000000000000000000000000" + "d9e1825fa613e1af000000000000000000000000000000006e08cb887464b9344ec3127c750fabdd" + "6c0fc09c02000000809829af4a9df58dbfef186d416f3a1ef154d10f000000000000000000000000" "0000000087780281d47a32f2235376239daeaacba9a89f8701000000fcdf6d9be94030b34774d1d7" - "dddedd9899f0f62700000000000000000000000000000000848518c4e3f6cbf25e5e1b990fc46767" - "fd338f35010000006e8cc34573654ea6624f138ef9531cd9367a02e4000000000000000000000000" + "dddedd989972f62700000000000000000000000000000000848518c4e3f6cbf25e5e1b990fc46767" + "fd338f35010000006e8cc34573654ea6624f138ef9531cd9361802e4000000000000000000000000" "00000000da40d88d40a6d75bc404156225b7eede2cb749e2010000000eb4f73e75039fcf251b32fc" - "79685b05ddd3aa9b000000000000000000000000000000000d58fbcc58fc4c2fd0d44ff1e51c3515" - "b7f0318a01000000061db3dd7fde25654a4059d565dbc8a91e3b4457000000000000000000000000" + "79685b05dd3caa9b000000000000000000000000000000000d58fbcc58fc4c2fd0d44ff1e51c3515" + "b7f0318a01000000061db3dd7fde25654a4059d565dbc8a91e004457000000000000000000000000" "00000000c1b5aad487c192f08bd7a09bdd21444359747cf200000000ab2dadc5a39411fd4ff1116d" - "478987316a553fc2000000000000000000000000000000000819e3b10db116431ec6f7691539ce41" - "b95c593100000000dbe9962069e66142e22753344fda8a3e0b841cf7000000000000000000000000" + "478987316a293fc2000000000000000000000000000000000819e3b10db116431ec6f7691539ce41" + "b95c593100000000dbe9962069e66142e22753344fda8a3e0b001cf7000000000000000000000000" "000000008c54dda9ac3bb1b1d43e6505621b9a7f672d2fa501000000e276c5661a64192db44ce7af" - "5eb888e9eb37bb0400000000000000000000000000000002641e447514ca565fb9b68c08a5e4351e" - "9f3c39f201000000de745cb25851429b3bbfb50168dfd04edf6b3542000000000000000000000000" + "5eb888e9eb73bb0400000000000000000000000000000002641e447514ca565fb9b68c08a5e4351e" + "9f3c39f201000000de745cb25851429b3bbfb50168dfd04edf2a3542000000000000000000000000" "0000000218f93e742d08f0550b55726f2292362e70ccc56700000000a4c73cf5ffa4ffc8a4bab148" - "74afdf54e6aae8160000000000000000000000000000000268baf76ab08940f6fc3bbdc7f6090f75" - "4f1b134803000000449a774929e86716ec852d59f3d17232edd86ad6000000000000000000000000" + "74afdf54e64be8160000000000000000000000000000000268baf76ab08940f6fc3bbdc7f6090f75" + "4f1b134803000000449a774929e86716ec852d59f3d17232ed3a6ad6000000000000000000000000" "000000027dba1ee7e143fd52599364e13468f80f40b26f6603000000badfad0fe8fa8f3c1aad2a82" - "530b7447d9c2f401000000000000000000000000000000028147507e1cd59ea1ae6da48b1eba6d16" - "dedea2030100000002a1f8e6f5657f3f9e3eb807cbad76451055edb8000000000000000000000000" + "530b7447d93bf401000000000000000000000000000000028147507e1cd59ea1ae6da48b1eba6d16" + "dedea2030100000002a1f8e6f5657f3f9e3eb807cbad76451013edb8000000000000000000000000" "00000002d9279fb2b8fcbac6abea74f7a6df7979f6989d2d000000006ff7add5df2c93e05459507b" - "5d8c6a0f466554d200000000000000000000ffff1785d3ffdbd9a617857ae8126b028c0e3e295354"), - [2] = ("4cc43c5103000000c2aac1d67a909b297c703915312e9c3c5a06c40b20ea99d5ab90135fa636af44" + "5d8c6a0f465354d200000000000000000000ffff1785d3ffdbd9a617857ae8126b028c0e3e295354"), + [2] = ("4cc43c5103000000c2aac1d67a909b297c703915312e9c3c5a64c40b20ea99d5ab90135fa636af44" "64d210a256be75e0509c4477d19ac64b2e69220d54270e46020000006a894e387625da376feecb80" - "ac245409c0becc271d9c2f67179bff0644399ae79c64ed0432d599eaa660ac824b7fae389861419c" - "12ea3b9501000000fb95e8332fdfff658483a2d039a7bf148ed3481e0bccc460e89f7abdb682380a" + "ac245409c058cc271d9c2f67179bff0644399ae79c64ed0432d599eaa660ac824b7fae389861419c" + "12ea3b9501000000fb95e8332fdfff658483a2d039a7bf148e4c481e0bccc460e89f7abdb682380a" "62eae374835b4a49a2b980b6aba92da6409969aa7a899f2d010000009bf5a5d06776e66a9d80ab13" - "2e1ac921eb76adbb229df32e561fa80a40e55b8b1dd92e18c0cfb2b4386bec092fa5757ecde9348b" - "288cd9bf00000000225a0c71b2ce78bb16104c8eaf18c565ecc8fb112087b97cfcebbaeb0c565359" + "2e1ac921eb04adbb229df32e561fa80a40e55b8b1dd92e18c0cfb2b4386bec092fa5757ecde9348b" + "288cd9bf00000000225a0c71b2ce78bb16104c8eaf18c565ec5ffb112087b97cfcebbaeb0c565359" "23f14874042a8aff1d1f8e5ec3cc13cc36bbe3c9c4e1966800000000b3121cd5ef51e696c816290d" - "baee0e7726d082e1530ff5397c9125f59577d71c4b258a005116d11354edff62ceaa458fc75a91c4" - "25a5927300000000c4458d70911714f1819aa46fbe143934c933ae6dec0fb124f264af67eed7c9a8" + "baee0e77264c82e1530ff5397c9125f59577d71c4b258a005116d11354edff62ceaa458fc75a91c4" + "25a5927300000000c4458d70911714f1819aa46fbe143934c915ae6dec0fb124f264af67eed7c9a8" "c38b6b8ee2614344bea73223e59bf0193432e9fa2fea9bc10300000062fb81e733cff620ca7feefe" - "1933631e8e69f6d9fed62d2c6e6904f57239c09c47150b9b14010469823acb72bb89182f93112196" - "9985d62700000000e491cbbbf9443fd6a77eb3c5bf64b671d6f18dbffeff9b8306c83bc026977911" + "1933631e8e18f6d9fed62d2c6e6904f57239c09c47150b9b14010469823acb72bb89182f93112196" + "9985d62700000000e491cbbbf9443fd6a77eb3c5bf64b671d6098dbffeff9b8306c83bc026977911" "4bdade862c224f6f36506ebd455e679cef369bb8bb0ec36f0000000064a2827b7cdd38d0314c178e" - "925b568ae56bc4e9fefb24e5264fd3ebe9cf9f6df9615189f78ee815b2781ea55c9555876b6a3f13" - "02e9b69000000000eacce745ea213cb1a84035b632ef3be6070dafa2fed87470e9da55709427c226" + "925b568ae566c4e9fefb24e5264fd3ebe9cf9f6df9615189f78ee815b2781ea55c9555876b6a3f13" + "02e9b69000000000eacce745ea213cb1a84035b632ef3be60755afa2fed87470e9da55709427c226" "d324d9a086ed27184b443181a5edc511c1507a14d514573f03000000f6932f6932d1d5f5d0ce2cf6" - "bf7a70ba5193a162fe92ec1b11d9172cf84a03478b82cdd8883b0f3fd6ed84d6c959e553b887edcd" - "6297dfa700000000fd0d53bb6215de4bb6f6f3d031a790287e45e9c1feb836c0a25ea71f5daaed4d" + "bf7a70ba5111a162fe92ec1b11d9172cf84a03478b82cdd8883b0f3fd6ed84d6c959e553b887edcd" + "6297dfa700000000fd0d53bb6215de4bb6f6f3d031a790287e7be9c1feb836c0a25ea71f5daaed4d" "99eb2ebebe3c432fec7d3abc4ccf30d3aaaf02a4ae8cb60b0300000038d856a40c67c3d4afa9c864" - "9da90bd2fff2f25600000000000000000000000000000001955e1a13d1111b067acbce3e3bcdf382" - "00154d12010000009edfa7a74c1c83c18e47935e8354846e34f0386a000000000000000000000000" + "9da90bd2ff4cf25600000000000000000000000000000001955e1a13d1111b067acbce3e3bcdf382" + "00154d12010000009edfa7a74c1c83c18e47935e8354846e346e386a000000000000000000000000" "00000001ac26c7d41fd050bf8d85055bcfe3756c1e0f515601000000f57609453df7803357ae7998" - "9870ccec3def0ad9000000000000000000000000000000019f05a16768cb3bc873b04d937a6ed8f7" - "7c52a52d030000004e8e8bc17c01ac63eca0c1cfbb204132fb7213e4000000000000000000000000" + "9870ccec3d4f0ad9000000000000000000000000000000019f05a16768cb3bc873b04d937a6ed8f7" + "7c52a52d030000004e8e8bc17c01ac63eca0c1cfbb204132fb0813e4000000000000000000000000" "00000000accae11f8045a80f855ebf3b772eb2b1d03bc90503000000eb760e3f004a2efc8ffc96b8" - "9b1bc8f415bd4e7700000000000000000000000000000000d149f074a378b881153ece68ade15cec" - "6f0e9e6903000000ec2e2924348352d715cf9d411ea012e5307294b6000000000000000000000000" + "9b1bc8f415174e7700000000000000000000000000000000d149f074a378b881153ece68ade15cec" + "6f0e9e6903000000ec2e2924348352d715cf9d411ea012e5305a94b6000000000000000000000000" "00000000ccd2f50c30706cae3fdcc2f0ee3d5e267666c05303000000ffa8e89871fb9510b900b206" - "1d0c334b819f2dd100000000000000000000000000000000095a3230fde69eec3af2e6d0bd68ab72" - "81ae55f0030000000aa20624fbab244735d67c61283031667b2d74a1000000000000000000000000" + "1d0c334b816a2dd100000000000000000000000000000000095a3230fde69eec3af2e6d0bd68ab72" + "81ae55f0030000000aa20624fbab244735d67c61283031667b2274a1000000000000000000000000" "0000000000459582f4ef43c780908872746e39ef10613fc90200000016a31dc2e46a234558817151" - "b38fc9c909cf8d7100000000000000000000000000000000ae17bb4515856092b4d9e89b676761b2" - "57d6249b020000007dc7f17f666969e45c3baf7a119a65ee0b06fa9e000000000000000000000000" + "b38fc9c9093c8d7100000000000000000000000000000000ae17bb4515856092b4d9e89b676761b2" + "57d6249b020000007dc7f17f666969e45c3baf7a119a65ee0b08fa9e000000000000000000000000" "00000000b314f695bd82e9ea8891ed0a3d1b91ca6e91b91501000000be5b534e0a6527f67485ab35" - "aca0c7ee4197338500000000000000000000000000000000aefd4503189f7630248e501c9052c22b" - "5d68265d010000009b7a559be3acf4fc36fa6b513cf09e8b99289462000000000000000000000000" + "aca0c7ee4167338500000000000000000000000000000000aefd4503189f7630248e501c9052c22b" + "5d68265d010000009b7a559be3acf4fc36fa6b513cf09e8b99729462000000000000000000000000" "00000000b49185ad9b7d0070a36dd51323b2c542b56e03e0010000002f70249eefc67bce716c856e" "3973dc42a1003be9000000000000000000000000000000006176f78a19bb8df1804c122fce5078c1" - "e5fe7d360100000066a3ae3939762df33a2d55060c78d551cbb110fd000000000000000000000000" + "e5fe7d360100000066a3ae3939762df33a2d55060c78d551cb7410fd000000000000000000000000" "000000002c171ed15abbbe1cd911db7b56e8f3feeecc89f601000000d635edea8ffe423d01883918" - "039249f398f9b37e000000000000000000000000000000001fb7c8307f06b4b29088f20d9ac676d5" - "f90e54b501000000a779f37c30d2c5053c40ecae210aeb0934cb2a24000000000000000000000000" + "039249f3984ab37e000000000000000000000000000000001fb7c8307f06b4b29088f20d9ac676d5" + "f90e54b501000000a779f37c30d2c5053c40ecae210aeb0934392a24000000000000000000000000" "00000000df48f333ef467092818aa77d6732b678bcd7be0700000000e45aaf61814f703b40125e6b" - "af4648cbaaa37b86000000000000000000000000000000005ddb05f2a84e27c18a06e2c9cb29efdf" - "50da49bf00000000d94beb259f9f0251becc987907879cca68fec7bb000000000000000000000000" + "af4648cbaa557b86000000000000000000000000000000005ddb05f2a84e27c18a06e2c9cb29efdf" + "50da49bf00000000d94beb259f9f0251becc987907879cca6857c7bb000000000000000000000000" "000000009402a4c2167721673f2b02b3256ead1fa349e1cc00000000b879a45176740744fcb6a035" - "339d504c9726d80d000000000000000000000000000000009518862bc9a89192c1c8be55281a59d1" - "bae87d60000000005d31e5b2de252167c1c91b3a36ba0c700ee78477000000000000000000000000" + "339d504c972bd80d000000000000000000000000000000009518862bc9a89192c1c8be55281a59d1" + "bae87d60000000005d31e5b2de252167c1c91b3a36ba0c700e538477000000000000000000000000" "000000006ad0143a0554efb46b382ab0404cdf02ebfdcec30000000067a982be8a934f852cc3d4d8" - "2bc0ec7303f99f8f00000000000000000000000000000000901f55f960c55c22f32099a8020bea2a" - "a2f56808092069affaa100fdfdd68d34be184524a6bdc8789cf85178000000000000000000000000" + "2bc0ec7303579f8f00000000000000000000000000000000901f55f960c55c22f32099a8020bea2a" + "a2f56808092069affaa100fdfdd68d34be184524a6bdc8789c575178000000000000000000000000" "00000000020ffdb0e612098610e52bb2a16a4008aefd545b020000007ced4f8b362956cd46646a0e" - "222160e5f769bb2900000000000000000000000000000000a19da86c64fefab2548759d313a5b92d" - "f05d7308020000009d82c856ba942455050f63f8282f3464443cacf5000000000000000000000000" + "222160e5f749bb2900000000000000000000000000000000a19da86c64fefab2548759d313a5b92d" + "f05d7308020000009d82c856ba942455050f63f8282f34644466acf5000000000000000000000000" "0000000069d9942f460bcea75481f25e307d0de99a6ce5d900000000a6a5ee19d6f63fe9cbdd01f7" - "246f13b2050424a200000000000000000000000000000000ffe9d6812231bb02f922259b173c333c" - "5b1aea3401000000c7c3523f76cf1ce34ca17a9a32f3f0f218424e48000000000000000000000000" + "246f13b2055624a200000000000000000000000000000000ffe9d6812231bb02f922259b173c333c" + "5b1aea3401000000c7c3523f76cf1ce34ca17a9a32f3f0f2187c4e48000000000000000000000000" "00000002e6fbf952902383028e3b47f2111d891d17a4763102000000f9119c40b468b66331bca67a" - "034f43340d01683c00000000000000000000ffffb24a5be9b10123e6e4f15ecd1dff045298cfee06" - "536c75bb01000000720da9e07ac998b5690807d52617369ee1af4ca500000000000000000000ffff" + "034f43340d2c683c00000000000000000000ffffb24a5be9b10123e6e4f15ecd1dff045298cfee06" + "536c75bb01000000720da9e07ac998b5690807d52617369ee16d4ca500000000000000000000ffff" "47d7b351a36b178aabc78a4a0d80684ee5dbf45bb0916e5d030000004a503a712350acbd48411f0d" - "c15d2f0f49dad345599706954d2471f00d3c723b91adb0da7c4aa7e7eb5a15bcde015fb98b841fd8" - "ba8110fb03000000904f288262e6ea77a22fa5f863eaeefa701d120523bd98f29b098b43cd68be6e" + "c15d2f0f4952d345599706954d2471f00d3c723b91adb0da7c4aa7e7eb5a15bcde015fb98b841fd8" + "ba8110fb03000000904f288262e6ea77a22fa5f863eaeefa700b120523bd98f29b098b43cd68be6e" "3f81268193fd637e585287dc6ca972a2cfb18b2b3cae864b0200000091921681c2162b9bfa40546c" - "db544e44df2d7c2790d3119a051bb2ee8192ac0cfa3abc1ea0ab3e7d75a2f42b50c6a36340132378" - "8c3b371502000000710c030690f5f18ea125dbf7d7e93bd65c1fa56dfdcfc1155f236c8b9c79a620" + "db544e44df587c2790d3119a051bb2ee8192ac0cfa3abc1ea0ab3e7d75a2f42b50c6a36340132378" + "8c3b371502000000710c030690f5f18ea125dbf7d7e93bd65c03a56dfdcfc1155f236c8b9c79a620" "5f660bbf024b03ff0a8e27c405e6424457393c6fdac12ebd01000000667224dae775e5ccd141aca2" - "ff0f576767d3648102b61886b62f22ca33478e1f891715df7fc6a902edae579e2e10c7f7a22ba034" - "abf85f0c0100000008d33a2ea67776d7f88d69c8c7e3b2d3c93ef054e93f8120abb42316c533d9c9" + "ff0f57676754648102b61886b62f22ca33478e1f891715df7fc6a902edae579e2e10c7f7a22ba034" + "abf85f0c0100000008d33a2ea67776d7f88d69c8c7e3b2d3c951f054e93f8120abb42316c533d9c9" "4d88189c471a1ff2f0ce3ff66e782110125ae2edc7a4c65601000000cd625009a40aeb62a42b6a62" - "548e3c38b96c20022753c5fbfaf1809becd2506315a6da29b2e94d3ab51fe0e9af98b180a36035fb" - "daae7d6300000000c0982b283aa9986700b2a2b3ed257b8b0489f48f053ec8cac72105b327335a25" + "548e3c38b96620022753c5fbfaf1809becd2506315a6da29b2e94d3ab51fe0e9af98b180a36035fb" + "daae7d6300000000c0982b283aa9986700b2a2b3ed257b8b042ff48f053ec8cac72105b327335a25" "a364d1015ffac03089f45539e1b0178462156cd66855676c00000000017c9148da5892bb4951c3a7" - "ed55689d3391ce7d3fd48469845f0c233dbdd2a97835df1f1782dee88487fd0db5971b46b7a350f9" - "cdb3455c00000000c66af76e80f062ea1a7e0b7be218d067530e1b0487b8c3b99f2b8a1a8982c42f" + "ed55689d336bce7d3fd48469845f0c233dbdd2a97835df1f1782dee88487fd0db5971b46b7a350f9" + "cdb3455c00000000c66af76e80f062ea1a7e0b7be218d067532d1b0487b8c3b99f2b8a1a8982c42f" "53700a3437c5156e072b2f2fb337c9cfe07c34ddc896c9a7000000000a5f6abd850b06e3d9662795" - "ce2cc1cee06302aba042aaa218dc091e9aa1477f6fdc9830d7fbc95829a8838314dff34d24c33221" - "98c39e7c00000000efc57ff447036b9551adcb22fd50793f797a3c7dadd1c86e759d0c90bc512e13" + "ce2cc1cee03202aba042aaa218dc091e9aa1477f6fdc9830d7fbc95829a8838314dff34d24c33221" + "98c39e7c00000000efc57ff447036b9551adcb22fd50793f791c3c7dadd1c86e759d0c90bc512e13" "7dcef5e4a27985bd8d1e69c83dc21056b973972c7625ca4a00000000e682f80f94315c45ef817264" - "c89a736ed55ed637b077ddad3108be69f9b97d05c917ad6b10e693bb6e26f2ba90c8e909e85e20e5" - "9c88b02a0300000004b0595daf37deb499996bfb667f072dec1e5d9cdc8a11f4409bcfb3c167090e" + "c89a736ed580d637b077ddad3108be69f9b97d05c917ad6b10e693bb6e26f2ba90c8e909e85e20e5" + "9c88b02a0300000004b0595daf37deb499996bfb667f072dec755d9cdc8a11f4409bcfb3c167090e" "99d90a8543961b2ccd47724a3c460ba85183f4c5a7afe28302000000d05ff720b16c73761a3fcb67" - "5219061ab4c5c79489b2cc6a883c146972decb8b5adac8f5e6d66df46ea139107754dee62c36d2fc" - "e36f90d401000000fd41fe47684b370b6ec6584d64496089570968ead4d1ae91c819bb068196d599" + "5219061ab466c79489b2cc6a883c146972decb8b5adac8f5e6d66df46ea139107754dee62c36d2fc" + "e36f90d401000000fd41fe47684b370b6ec6584d64496089574568ead4d1ae91c819bb068196d599" "efde3246e43f5e7945aaf95e2ffa3a11b9ef1b214d4647f5000000000f88e3759a08e7a56663861e" - "ea1bf42ccd3c72f2ad063857ca82ac5180101be4f85cef468ea086ea9aaafdc388811ec787bc45db" - "0422ae3f03000000c43bd794c697895e5bfe47c6f53a54e01b0c1d89fecd94d0e02d2ec587fc3300" + "ea1bf42ccd1172f2ad063857ca82ac5180101be4f85cef468ea086ea9aaafdc388811ec787bc45db" + "0422ae3f03000000c43bd794c697895e5bfe47c6f53a54e01b211d89fecd94d0e02d2ec587fc3300" "03781b0f294a2b73c4421398f4de67e9cee64b38bc51e540030000006c3d048a92d3adc69a84eb47" - "622400207799416afef0a086fbd7e2f7dea0077ae9c0c0d9c386e9c6e6a2cbfa10ee58bdc7518360" - "36674cde0200000054cfe8f42bf0e9381ba2c4396de60f032bc7f34dfe959871c0d4c0d4eb720c4a" + "622400207708416afef0a086fbd7e2f7dea0077ae9c0c0d9c386e9c6e6a2cbfa10ee58bdc7518360" + "36674cde0200000054cfe8f42bf0e9381ba2c4396de60f032b5af34dfe959871c0d4c0d4eb720c4a" "e3c9472e5f2da5d9c5cfd9f2343b21362c19a092b2cd3dbd01000000e958e48d2ab8b0313e7f8933" - "e315130fa9a84c82feb83f6e70b1646d8026e9f1704f1b16286ba2dabc7ef0820c91ed33ef60a8b5" - "bcfe97e1000000007ad742d3d7320a4f880cf47f5dd0cf69cb22840ffeb3fe7749509cb6752b2cee" + "e315130fa9274c82feb83f6e70b1646d8026e9f1704f1b16286ba2dabc7ef0820c91ed33ef60a8b5" + "bcfe97e1000000007ad742d3d7320a4f880cf47f5dd0cf69cb7f840ffeb3fe7749509cb6752b2cee" "30b7e7736a0afc9879ea40e69710fc9f6e8e99cd69121aec010000000fcc00ac2daa755e5292cd32" - "dc096cd5d8a4c5cffe91ee1cfcc2056cc1ff8e51bbce426cfa4b861cc78592be7b14e7ba9c15acb8" - "b83579b80300000072437f9b6245de39ec9e71ee4b951507beb42b34000000000000000000000000" + "dc096cd5d830c5cffe91ee1cfcc2056cc1ff8e51bbce426cfa4b861cc78592be7b14e7ba9c15acb8" + "b83579b80300000072437f9b6245de39ec9e71ee4b951507be0a2b34000000000000000000000000" "00000001d639272e4a46eadfbd2146bf8cfdb205b3980deb020000006c1de913df1424ce3ee1d76f" - "c1ea76e98c9dfc7800000000000000000000000000000001e44ea74b4f2b83f9b3bee14d861a4c9e" - "cf844ef501000000cd743f59bd14c89b5cfd5ce6e82e7854152f2b70000000000000000000000000" + "c1ea76e98c16fc7800000000000000000000000000000001e44ea74b4f2b83f9b3bee14d861a4c9e" + "cf844ef501000000cd743f59bd14c89b5cfd5ce6e82e7854157b2b70000000000000000000000000" "0000000127e19f254ac9588319558041fc62ed561dce2f83020000003a3efc240b9977e166bee737" - "fe73670c439a644c000000000000000000000000000000015e0dfe491d1ba96742c7b5e02b227122" - "2af145480300000004265f6c72923e22594f3f79e208ed2e2ebb0771000000000000000000000000" + "fe73670c436b644c000000000000000000000000000000015e0dfe491d1ba96742c7b5e02b227122" + "2af145480300000004265f6c72923e22594f3f79e208ed2e2e710771000000000000000000000000" "0000000039dd8f88152a58454d9ca9d20f45dfa774993ade03000000e62112898dab2dade2ab2fc9" - "c56a7c86be5f962200000000000000000000000000000000bdd06352cb2c354434819f4b248eb2b8" - "922b6cb8030000001d5c302df59dd32a677e5a3af4fe297f608df061000000000000000000000000" + "c56a7c86be73962200000000000000000000000000000000bdd06352cb2c354434819f4b248eb2b8" + "922b6cb8030000001d5c302df59dd32a677e5a3af4fe297f6042f061000000000000000000000000" "000000008ae21e371051852c972ea7954079884a9f3c2c8803000000f51f44e644d7cf1d06b2b115" - "d882549e62c12fba000000000000000000000000000000004fc812bd2f8a59d96d064126666befbb" - "dc335c8b030000000a3c8e7c91bf821c4b09cee3c37ff4283a631480000000000000000000000000" + "d882549e62042fba000000000000000000000000000000004fc812bd2f8a59d96d064126666befbb" + "dc335c8b030000000a3c8e7c91bf821c4b09cee3c37ff4283a0c1480000000000000000000000000" "000000005588456e4ead7cbda620a3abae816e34e3ff1a5f03000000b4425486c619147eb0216050" - "ed7afd741024e83600000000000000000000000000000000f493472201e48d163106cc397446a33f" - "f257b044030000006a4c619f9037d7a754655354c47cf0f551e96770000000000000000000000000" + "ed7afd74105fe83600000000000000000000000000000000f493472201e48d163106cc397446a33f" + "f257b044030000006a4c619f9037d7a754655354c47cf0f551216770000000000000000000000000" "0000000050b8d10ab700cc3a7cf51be0403b654bbc74179403000000438a72e12ae0436a2495a609" - "675344f7e2e3a5eb0000000000000000000000000000000061eda239d9d083c3bf085387046ef8a3" - "4153e174020000004d89c0bb5408c1b7d17fb084d9e1825fa638e1af000000000000000000000000" + "675344f7e226a5eb0000000000000000000000000000000061eda239d9d083c3bf085387046ef8a3" + "4153e174020000004d89c0bb5408c1b7d17fb084d9e1825fa613e1af000000000000000000000000" "000000006e08cb887464b9344ec3127c750fabdd6c0fc09c02000000809829af4a9df58dbfef186d" - "416f3a1ef170d10f0000000000000000000000000000000087780281d47a32f2235376239daeaacb" - "74e7860402000000cd7db68b9ae586dacdb4070c50320427c4dd3d03000000000000000000000000" + "416f3a1ef154d10f0000000000000000000000000000000087780281d47a32f2235376239daeaacb" + "74e7860402000000cd7db68b9ae586dacdb4070c50320427c4803d03000000000000000000000000" "00000000d538d34574c038404923e75d0e09e2fca9a89f8701000000fcdf6d9be94030b34774d1d7" - "dddedd9899f0f62700000000000000000000000000000000848518c4e3f6cbf25e5e1b990fc46767" - "fd338f35010000006e8cc34573654ea6624f138ef9531cd9367a02e4000000000000000000000000" + "dddedd989972f62700000000000000000000000000000000848518c4e3f6cbf25e5e1b990fc46767" + "fd338f35010000006e8cc34573654ea6624f138ef9531cd9361802e4000000000000000000000000" "00000000da40d88d40a6d75bc404156225b7eede2cb749e2010000000eb4f73e75039fcf251b32fc" - "79685b05ddd3aa9b000000000000000000000000000000000d58fbcc58fc4c2fd0d44ff1e51c3515" - "6aae660b01000000fc1fb23d24438387def0f4c6544e4b275d9b7146000000000000000000000000" + "79685b05dd3caa9b000000000000000000000000000000000d58fbcc58fc4c2fd0d44ff1e51c3515" + "6aae660b01000000fc1fb23d24438387def0f4c6544e4b275d4a7146000000000000000000000000" "00000000b883efebc09dd9d61966b7ae7412041db7f0318a01000000061db3dd7fde25654a4059d5" - "65dbc8a91e3b445700000000000000000000000000000000c1b5aad487c192f08bd7a09bdd214443" - "61c2f5d200000000b809d259e499db7dc8f1853bdcb0e4bc0e2b00b6000000000000000000000000" + "65dbc8a91e00445700000000000000000000000000000000c1b5aad487c192f08bd7a09bdd214443" + "61c2f5d200000000b809d259e499db7dc8f1853bdcb0e4bc0e0e00b6000000000000000000000000" "000000005e7fa0f02f2f3313d8469d09a92409c0b4d54acb00000000a417f3da01d99dae5f190096" - "cc582cabd5ddd15a00000000000000000000000000000000fdb3d117d76b0de5416f95e7bb75d72f" - "59747cf200000000ab2dadc5a39411fd4ff1116d478987316a553fc2000000000000000000000000" + "cc582cabd534d15a00000000000000000000000000000000fdb3d117d76b0de5416f95e7bb75d72f" + "59747cf200000000ab2dadc5a39411fd4ff1116d478987316a293fc2000000000000000000000000" "000000000819e3b10db116431ec6f7691539ce41b95c593100000000dbe9962069e66142e2275334" - "4fda8a3e0b841cf7000000000000000000000000000000008c54dda9ac3bb1b1d43e6505621b9a7f" - "fc2b445700000000496ad01bf007eacb0a28aec868282510b60291ea000000000000000000000000" + "4fda8a3e0b001cf7000000000000000000000000000000008c54dda9ac3bb1b1d43e6505621b9a7f" + "fc2b445700000000496ad01bf007eacb0a28aec868282510b61b91ea000000000000000000000000" "000000005b29a197b7b3cceaf5f1bb12c535256a0436242c03000000ee3fbc164632d4f28aa28c08" - "f80dd50c6712dfb400000000000000000000000000000000078a806d329c9b008bbfc9723107f3f5" - "9a1b163a030000000e2f4f911a0dd8c052ed6b13e2815a1a37a52bdd000000000000000000000000" + "f80dd50c6705dfb400000000000000000000000000000000078a806d329c9b008bbfc9723107f3f5" + "9a1b163a030000000e2f4f911a0dd8c052ed6b13e2815a1a37322bdd000000000000000000000000" "00000000bd99fcf72909ac9e7a55299e9bb4fd53fc1519de010000002545666937c22a3b6e9686dc" - "c405cbee5016c252000000000000000000000000000000006e4c699341b95f41d9c1e67743efb54e" - "d7ac5f9901000000822a272bec4501a1e27acfee7a8588ffd5a06cae000000000000000000000000" + "c405cbee504dc252000000000000000000000000000000006e4c699341b95f41d9c1e67743efb54e" + "d7ac5f9901000000822a272bec4501a1e27acfee7a8588ffd5286cae000000000000000000000000" "0000000077a47579dda0b6ead1e1b34901eaedd54f1b134803000000449a774929e86716ec852d59" - "f3d17232edd86ad6000000000000000000000000000000027dba1ee7e143fd52599364e13468f80f" - "40b26f6603000000badfad0fe8fa8f3c1aad2a82530b7447d9c2f401000000000000000000000000" + "f3d17232ed3a6ad6000000000000000000000000000000027dba1ee7e143fd52599364e13468f80f" + "40b26f6603000000badfad0fe8fa8f3c1aad2a82530b7447d93bf401000000000000000000000000" "000000028147507e1cd59ea1ae6da48b1eba6d16dedea2030100000002a1f8e6f5657f3f9e3eb807" - "cbad76451055edb800000000000000000000000000000002d9279fb2b8fcbac6abea74f7a6df7979" - "672d2fa501000000e276c5661a64192db44ce7af5eb888e9eb37bb04000000000000000000000000" + "cbad76451013edb800000000000000000000000000000002d9279fb2b8fcbac6abea74f7a6df7979" + "672d2fa501000000e276c5661a64192db44ce7af5eb888e9eb73bb04000000000000000000000000" "00000002641e447514ca565fb9b68c08a5e4351e9f3c39f201000000de745cb25851429b3bbfb501" - "68dfd04edf6b35420000000000000000000000000000000218f93e742d08f0550b55726f2292362e" - "70ccc56700000000a4c73cf5ffa4ffc8a4bab14874afdf54e6aae816000000000000000000000000" + "68dfd04edf2a35420000000000000000000000000000000218f93e742d08f0550b55726f2292362e" + "70ccc56700000000a4c73cf5ffa4ffc8a4bab14874afdf54e64be816000000000000000000000000" "0000000268baf76ab08940f6fc3bbdc7f6090f75f6989d2d000000006ff7add5df2c93e05459507b" - "5d8c6a0f466554d200000000000000000000ffff1785d3ffdbd9a617857ae8126b028c0e3e295354"), + "5d8c6a0f465354d200000000000000000000ffff1785d3ffdbd9a617857ae8126b028c0e3e295354"), }; const int TEST_DATA_I = GPOINTER_TO_INT(test_data); const int addr_family = (TEST_DATA_I == 0 ? AF_INET : AF_INET6); @@ -584,8 +584,9 @@ test_platform_ip_address_pretty_sort_cmp(gconstpointer test_data) nmtst_stable_rand(710086081, rand_map, sizeof(rand_map[0]) * N_ADDRESSES); for (i = 0; i < N_ADDRESSES; i++) { - NMPlatformIPXAddress *a = (gpointer) (&addresses[i * ELM_SIZE]); - guint64 r = rand_map[i]; + NMPlatformIPXAddress *a = (gpointer) (&addresses[i * ELM_SIZE]); + guint64 r = rand_map[i]; + guint64 r0 = r; struct in6_addr *a6; #define CONSUME_BITS(r, nbits) \ @@ -664,9 +665,10 @@ test_platform_ip_address_pretty_sort_cmp(gconstpointer test_data) a->a4.label[0] = '\0'; } } + if (a->ax.plen > 0) + a->ax.plen = (r0 + 209284393u) % ((NM_IS_IPv4(addr_family) ? 32 : 128) + 1); if (addr_family == AF_INET) { if (CONSUME_BITS(r, 2) != 0) { - /* randomly make the label empty or not. */ a->a4.plen = CONSUME_BITS(r, 2); } } @@ -731,15 +733,17 @@ test_platform_ip_address_pretty_sort_cmp(gconstpointer test_data) &bin_len); if (bin_len != ELM_SIZE * N_ADDRESSES || memcmp(addresses, bin_arr, bin_len) != 0) { - char *addresses_str = nm_utils_bin2hexstr(addresses, ELM_SIZE * N_ADDRESSES, -1); + gs_free char *addresses_str = NULL; + NM_PRAGMA_WARNING_DISABLE_DANGLING_POINTER g_error(">>> test_platform_ip_address_pretty_sort_cmp() will fail:\n" ">>> addresses[%zu]: %s\n" ">>> expected [%zu]: %s\n", ELM_SIZE * N_ADDRESSES, - addresses_str, + (addresses_str = nm_utils_bin2hexstr(addresses, ELM_SIZE * N_ADDRESSES, -1)), bin_len, EXPECTED_BUFFER[TEST_DATA_I]); + NM_PRAGMA_WARNING_REENABLE } g_assert_cmpmem(addresses, ELM_SIZE * N_ADDRESSES, bin_arr, bin_len); @@ -760,6 +764,7 @@ test_route_type_is_nodev(void) case RTN_BLACKHOLE: case RTN_UNREACHABLE: case RTN_PROHIBIT: + case RTN_THROW: is_nodev = TRUE; break; default: diff --git a/src/core/platform/tests/test-route.c b/src/core/platform/tests/test-route.c index cf0236e0..2d39cb37 100644 --- a/src/core/platform/tests/test-route.c +++ b/src/core/platform/tests/test-route.c @@ -1535,6 +1535,7 @@ _rule_fuzzy_equal(const NMPObject *obj, const NMPObject *obj_comp, int op_type) static void test_rule(gconstpointer test_data) { + char sbuf1[NM_UTILS_TO_STRING_BUFFER_SIZE]; const int TEST_IDX = GPOINTER_TO_INT(test_data); const gboolean TEST_SYNC = (TEST_IDX == 4); gs_unref_ptrarray GPtrArray *objs = NULL; @@ -1763,7 +1764,7 @@ again: g_print(">>> failing... errno=%d, rule=%s\n", r, - nmp_object_to_string(obj, NMP_OBJECT_TO_STRING_ALL, NULL, 0)); + nmp_object_to_string(obj, NMP_OBJECT_TO_STRING_ALL, sbuf1, sizeof(sbuf1))); nmp_lookup_init_obj_type(&lookup, NMP_OBJECT_TYPE_ROUTING_RULE); head_entry = nm_platform_lookup(platform, &lookup); @@ -1775,9 +1776,10 @@ again: && NMP_OBJECT_CAST_ROUTING_RULE(o)->priority == NMP_OBJECT_CAST_ROUTING_RULE(obj)->priority) ch = '*'; - g_print(">>> existing rule: %c %s\n", - ch, - nmp_object_to_string(o, NMP_OBJECT_TO_STRING_ALL, NULL, 0)); + g_print( + ">>> existing rule: %c %s\n", + ch, + nmp_object_to_string(o, NMP_OBJECT_TO_STRING_ALL, sbuf1, sizeof(sbuf1))); } nmtstp_run_command_check("ip rule"); @@ -1836,11 +1838,14 @@ again: if (!_rule_fuzzy_equal(obj, objs->pdata[k], RTM_DELRULE)) { g_print(">>> failing...\n"); - g_print(">>> no fuzzy match between: %s\n", - nmp_object_to_string(obj, NMP_OBJECT_TO_STRING_ALL, NULL, 0)); g_print( - ">>> and: %s\n", - nmp_object_to_string(objs->pdata[k], NMP_OBJECT_TO_STRING_ALL, NULL, 0)); + ">>> no fuzzy match between: %s\n", + nmp_object_to_string(obj, NMP_OBJECT_TO_STRING_ALL, sbuf1, sizeof(sbuf1))); + g_print(">>> and: %s\n", + nmp_object_to_string(objs->pdata[k], + NMP_OBJECT_TO_STRING_ALL, + sbuf1, + sizeof(sbuf1))); g_assert_not_reached(); } @@ -1899,14 +1904,17 @@ test_blackhole(gconstpointer test_data) NMPlatformIPXRoute rr = {}; int r = -1; int i; + guint8 rtn_type; + + rtn_type = nmtst_rand_select(RTN_BLACKHOLE, RTN_UNREACHABLE, RTN_PROHIBIT, RTN_THROW); if (IS_IPv4) { rr.r4 = (const NMPlatformIP4Route){ - .type_coerced = nmtst_rand_select(RTN_BLACKHOLE, RTN_UNREACHABLE, RTN_PROHIBIT), + .type_coerced = nm_platform_route_type_coerce(rtn_type), }; } else { rr.r6 = (const NMPlatformIP6Route){ - .type_coerced = nmtst_rand_select(RTN_BLACKHOLE, RTN_UNREACHABLE, RTN_PROHIBIT), + .type_coerced = nm_platform_route_type_coerce(rtn_type), .metric = 1000, }; } diff --git a/src/core/ppp/nm-ppp-manager.c b/src/core/ppp/nm-ppp-manager.c index 5761d59d..896c233d 100644 --- a/src/core/ppp/nm-ppp-manager.c +++ b/src/core/ppp/nm-ppp-manager.c @@ -1247,7 +1247,7 @@ _ppp_manager_stop(NMPPPManager *self, SIGTERM, LOGD_PPP, "pppd", - 5000, + NM_SHUTDOWN_TIMEOUT_5000_MSEC, _stop_child_cb, handle); diff --git a/src/core/settings/nm-secret-agent.c b/src/core/settings/nm-secret-agent.c index b222bd5c..a3df4497 100644 --- a/src/core/settings/nm-secret-agent.c +++ b/src/core/settings/nm-secret-agent.c @@ -511,7 +511,7 @@ nm_secret_agent_cancel_call(NMSecretAgent *self, NMSecretAgentCallId *call_id) g_variant_new("(os)", call_id->path, call_id->setting_name), G_VARIANT_TYPE("()"), G_DBUS_CALL_FLAGS_NO_AUTO_START, - NM_SHUTDOWN_TIMEOUT_MS, + NM_SHUTDOWN_TIMEOUT_1500_MSEC, NULL, /* this operation is not cancellable. We rely on the timeout. */ _call_cancel_cb, call_id); diff --git a/src/core/settings/nm-settings-connection.c b/src/core/settings/nm-settings-connection.c index 55efaebe..1638efcd 100644 --- a/src/core/settings/nm-settings-connection.c +++ b/src/core/settings/nm-settings-connection.c @@ -606,6 +606,7 @@ _secrets_update(NMConnection *connection, gboolean nm_settings_connection_update(NMSettingsConnection *self, + const char *plugin_name, NMConnection *new_connection, NMSettingsConnectionPersistMode persist_mode, NMSettingsConnectionIntFlags sett_flags, @@ -618,6 +619,7 @@ nm_settings_connection_update(NMSettingsConnection *self, return nm_settings_update_connection(NM_SETTINGS_CONNECTION_GET_PRIVATE(self)->settings, self, + plugin_name, new_connection, persist_mode, sett_flags, @@ -835,6 +837,7 @@ nm_settings_connection_new_secrets(NMSettingsConnection *self, if (!nm_settings_connection_update( self, + NULL, new_connection ?: connection, NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP, NM_SETTINGS_CONNECTION_INT_FLAGS_NONE, @@ -980,6 +983,7 @@ get_secrets_done_cb(NMAgentManager *manager, } if (!nm_settings_connection_update( self, + NULL, new_connection, agent_had_system ? NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP : NM_SETTINGS_CONNECTION_PERSIST_MODE_NO_PERSIST, @@ -1409,6 +1413,7 @@ typedef struct { NMConnection *new_settings; NMSettingsUpdate2Flags flags; char *audit_args; + char *plugin_name; bool is_update2 : 1; } UpdateInfo; @@ -1436,6 +1441,7 @@ update_complete(NMSettingsConnection *self, UpdateInfo *info, GError *error) g_clear_object(&info->agent_mgr); g_clear_object(&info->new_settings); g_free(info->audit_args); + g_free(info->plugin_name); g_slice_free(UpdateInfo, info); } @@ -1572,6 +1578,7 @@ update_auth_cb(NMSettingsConnection *self, nm_settings_connection_update( self, + info->plugin_name, info->new_settings, persist_mode, (NM_FLAGS_HAS(info->flags, NM_SETTINGS_UPDATE2_FLAG_VOLATILE) @@ -1642,6 +1649,7 @@ settings_connection_update(NMSettingsConnection *self, gboolean is_update2, GDBusMethodInvocation *context, GVariant *new_settings, + const char *plugin_name, NMSettingsUpdate2Flags flags) { NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE(self); @@ -1696,6 +1704,7 @@ settings_connection_update(NMSettingsConnection *self, info->subject = subject; info->flags = flags; info->new_settings = tmp; + info->plugin_name = g_strdup(plugin_name); permission = get_update_modify_permission(nm_settings_connection_get_connection(self), tmp ?: nm_settings_connection_get_connection(self)); @@ -1724,7 +1733,12 @@ impl_settings_connection_update(NMDBusObject *obj, gs_unref_variant GVariant *settings = NULL; g_variant_get(parameters, "(@a{sa{sv}})", &settings); - settings_connection_update(self, FALSE, invocation, settings, NM_SETTINGS_UPDATE2_FLAG_TO_DISK); + settings_connection_update(self, + FALSE, + invocation, + settings, + NULL, + NM_SETTINGS_UPDATE2_FLAG_TO_DISK); } static void @@ -1744,6 +1758,7 @@ impl_settings_connection_update_unsaved(NMDBusObject *obj, FALSE, invocation, settings, + NULL, NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY); } @@ -1758,7 +1773,12 @@ impl_settings_connection_save(NMDBusObject *obj, { NMSettingsConnection *self = NM_SETTINGS_CONNECTION(obj); - settings_connection_update(self, FALSE, invocation, NULL, NM_SETTINGS_UPDATE2_FLAG_TO_DISK); + settings_connection_update(self, + FALSE, + invocation, + NULL, + NULL, + NM_SETTINGS_UPDATE2_FLAG_TO_DISK); } static void @@ -1770,13 +1790,15 @@ impl_settings_connection_update2(NMDBusObject *obj, GDBusMethodInvocation *invocation, GVariant *parameters) { - NMSettingsConnection *self = NM_SETTINGS_CONNECTION(obj); - gs_unref_variant GVariant *settings = NULL; - gs_unref_variant GVariant *args = NULL; + NMSettingsConnection *self = NM_SETTINGS_CONNECTION(obj); + gs_unref_variant GVariant *settings = NULL; + gs_unref_variant GVariant *args = NULL; + gs_free char *plugin_name = NULL; guint32 flags_u; GError *error = NULL; GVariantIter iter; const char *args_name; + GVariant *args_value; NMSettingsUpdate2Flags flags; g_variant_get(parameters, "(@a{sa{sv}}u@a{sv})", &settings, &flags_u, &args); @@ -1812,7 +1834,13 @@ impl_settings_connection_update2(NMDBusObject *obj, nm_assert(g_variant_is_of_type(args, G_VARIANT_TYPE("a{sv}"))); g_variant_iter_init(&iter, args); - while (g_variant_iter_next(&iter, "{&sv}", &args_name, NULL)) { + while (g_variant_iter_next(&iter, "{&sv}", &args_name, &args_value)) { + if (plugin_name == NULL && nm_streq(args_name, "plugin") + && g_variant_is_of_type(args_value, G_VARIANT_TYPE_STRING)) { + plugin_name = g_variant_dup_string(args_value, NULL); + continue; + } + error = g_error_new(NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_ARGUMENTS, "Unsupported argument '%s'", @@ -1821,7 +1849,7 @@ impl_settings_connection_update2(NMDBusObject *obj, return; } - settings_connection_update(self, TRUE, invocation, settings, flags); + settings_connection_update(self, TRUE, invocation, settings, plugin_name, flags); } static void @@ -2010,6 +2038,7 @@ dbus_clear_secrets_auth_cb(NMSettingsConnection *self, if (!nm_settings_connection_update( self, + NULL, connection_cloned, NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP, NM_SETTINGS_CONNECTION_INT_FLAGS_NONE, diff --git a/src/core/settings/nm-settings-connection.h b/src/core/settings/nm-settings-connection.h index 5f8a22e8..893b0d7b 100644 --- a/src/core/settings/nm-settings-connection.h +++ b/src/core/settings/nm-settings-connection.h @@ -240,6 +240,7 @@ nm_settings_connection_has_unmodified_applied_connection(NMSettingsConnection *s NMSettingCompareFlags compare_flage); gboolean nm_settings_connection_update(NMSettingsConnection *self, + const char *plugin_name, NMConnection *new_connection, NMSettingsConnectionPersistMode persist_mode, NMSettingsConnectionIntFlags sett_flags, diff --git a/src/core/settings/nm-settings.c b/src/core/settings/nm-settings.c index 6619d3e0..1ff66e25 100644 --- a/src/core/settings/nm-settings.c +++ b/src/core/settings/nm-settings.c @@ -236,12 +236,16 @@ _sett_conn_entry_get_conn(SettConnEntry *sett_conn_entry) * update-connection. If this parameter is omitted, then it's about what happens * when adding a new profile (add-connection). * + * @storage_check_ignore is optional, and if given then it skips this particular + * storage. + * * Returns: the conflicting storage or %NULL if there is none. */ static NMSettingsStorage * _sett_conn_entry_storage_find_conflicting_storage(SettConnEntry *sett_conn_entry, NMSettingsPlugin *target_plugin, NMSettingsStorage *storage_check_including, + NMSettingsStorage *storage_check_ignore, const GSList *plugins) { StorageData *sd; @@ -269,6 +273,12 @@ _sett_conn_entry_storage_find_conflicting_storage(SettConnEntry *sett_conn_e continue; } + if (sd->storage == storage_check_ignore) { + /* We ignore this one, because we're in the process of + * replacing it. */ + continue; + } + if (sd->storage == storage_check_including) { /* ok, the storage is the one we are about to check. All other * storages are lower priority, so there is no storage that hides @@ -557,6 +567,8 @@ _startup_complete_check(NMSettings *self, gint64 now_msec) return; } + nm_clear_g_source(&priv->startup_complete_timeout_id); + if (c_list_is_empty(&priv->startup_complete_scd_lst_head)) goto ready; @@ -592,8 +604,6 @@ next_with_ready: } c_list_splice(&priv->startup_complete_scd_lst_head, &ready_lst); - nm_clear_g_source(&priv->startup_complete_timeout_id); - if (scd_not_ready) { gint64 timeout_msec; @@ -1463,6 +1473,7 @@ _plugin_connections_reload(NMSettings *self) static gboolean _add_connection_to_first_plugin(NMSettings *self, + const char *plugin_name, SettConnEntry *sett_conn_entry, NMConnection *new_connection, gboolean in_memory, @@ -1471,12 +1482,14 @@ _add_connection_to_first_plugin(NMSettings *self, gboolean shadowed_owned, NMSettingsStorage **out_new_storage, NMConnection **out_new_connection, + NMSettingsStorage *drop_storage, GError **error) { NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE(self); gs_free_error GError *first_error = NULL; GSList *iter; const char *uuid; + gboolean no_plugin = TRUE; uuid = nm_connection_get_uuid(new_connection); @@ -1493,12 +1506,18 @@ _add_connection_to_first_plugin(NMSettings *self, gboolean success; const char *filename; + if (plugin_name && strcmp(plugin_name, nm_settings_plugin_get_plugin_name(plugin))) { + /* Not the plugin we're confined to. Ignore. */ + continue; + } + if (!in_memory) { NMSettingsStorage *conflicting_storage; conflicting_storage = _sett_conn_entry_storage_find_conflicting_storage(sett_conn_entry, plugin, NULL, + drop_storage, priv->plugins); if (conflicting_storage) { /* we have a connection provided by a plugin with higher priority than the one @@ -1545,6 +1564,8 @@ _add_connection_to_first_plugin(NMSettings *self, &add_error); } + no_plugin = FALSE; + if (!success) { _LOGT("add-connection: failed to add %s/'%s': %s", nm_connection_get_uuid(new_connection), @@ -1588,8 +1609,18 @@ _add_connection_to_first_plugin(NMSettings *self, return TRUE; } - nm_assert(first_error); - g_propagate_error(error, g_steal_pointer(&first_error)); + if (no_plugin) { + nm_assert(plugin_name); + nm_assert(!first_error); + g_set_error(error, + NM_SETTINGS_ERROR, + NM_SETTINGS_ERROR_INVALID_ARGUMENTS, + "a plugin by the name of '%s' is not available", + plugin_name); + } else { + nm_assert(first_error); + g_propagate_error(error, g_steal_pointer(&first_error)); + } return FALSE; } @@ -1704,6 +1735,7 @@ _set_nmmeta_tombstone(NMSettings *self, */ gboolean nm_settings_add_connection(NMSettings *self, + const char *plugin, NMConnection *connection, NMSettingsConnectionPersistMode persist_mode, NMSettingsConnectionAddReason add_reason, @@ -1800,6 +1832,7 @@ nm_settings_add_connection(NMSettings *self, sett_conn_entry, nm_settings_storage_get_plugin(shadowed_storage), shadowed_storage, + NULL, priv->plugins); if (conflicting_storage) { /* We cannot add the profile as @shadowed_storage, because there is another, existing storage @@ -1824,6 +1857,7 @@ again_add_connection: if (!update_storage) { success = _add_connection_to_first_plugin(self, + plugin, sett_conn_entry, connection, new_in_memory, @@ -1832,6 +1866,7 @@ again_add_connection: FALSE, &new_storage, &new_connection, + NULL, &local); } else { success = _update_connection_to_plugin(self, @@ -1948,6 +1983,7 @@ again_delete_tombstone: gboolean nm_settings_update_connection(NMSettings *self, NMSettingsConnection *sett_conn, + const char *plugin_name, NMConnection *connection, NMSettingsConnectionPersistMode persist_mode, NMSettingsConnectionIntFlags sett_flags, @@ -2154,8 +2190,9 @@ nm_settings_update_connection(NMSettings *self, } else if (nm_settings_storage_is_keyfile_lib(cur_storage)) { /* the profile is a keyfile in /usr/lib. It cannot be overwritten, we must migrate it * from /usr/lib to /etc. */ - } else + } else { update_storage = cur_storage; + } if (new_in_memory) { if (persist_mode == NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY) { @@ -2174,8 +2211,22 @@ nm_settings_update_connection(NMSettings *self, } } + if (update_storage && plugin_name) { + NMSettingsPlugin *plugin = nm_settings_storage_get_plugin(update_storage); + + if (strcmp(plugin_name, nm_settings_plugin_get_plugin_name(plugin))) { + /* We're updating a connection, we're confined to a particular + * plugin, but the connection is currently using a different one. + * We need to migrate. Drop the existing storage and look out for + * a new one. */ + drop_storage = update_storage; + update_storage = NULL; + } + } + if (!update_storage) { success = _add_connection_to_first_plugin(self, + plugin_name, sett_conn_entry, connection, new_in_memory, @@ -2184,6 +2235,7 @@ nm_settings_update_connection(NMSettings *self, new_shadowed_owned, &new_storage, &new_connection, + drop_storage, &local); } else { success = _update_connection_to_plugin(self, @@ -2462,6 +2514,7 @@ pk_add_cb(NMAuthChain *chain, GDBusMethodInvocation *context, gpointer user_data nm_assert(NM_IS_CONNECTION(connection)); nm_settings_add_connection(self, + nm_auth_chain_get_data(chain, "plugin"), connection, GPOINTER_TO_UINT(nm_auth_chain_get_data(chain, "persist-mode")), GPOINTER_TO_UINT(nm_auth_chain_get_data(chain, "add-reason")), @@ -2489,6 +2542,7 @@ pk_add_cb(NMAuthChain *chain, GDBusMethodInvocation *context, gpointer user_data void nm_settings_add_connection_dbus(NMSettings *self, + const char *plugin, NMConnection *connection, NMSettingsConnectionPersistMode persist_mode, NMSettingsConnectionAddReason add_reason, @@ -2549,6 +2603,7 @@ nm_settings_add_connection_dbus(NMSettings *self, nm_auth_chain_set_data(chain, "persist-mode", GUINT_TO_POINTER(persist_mode), NULL); nm_auth_chain_set_data(chain, "add-reason", GUINT_TO_POINTER(add_reason), NULL); nm_auth_chain_set_data(chain, "sett-flags", GUINT_TO_POINTER(sett_flags), NULL); + nm_auth_chain_set_data(chain, "plugin", g_strdup(plugin), g_free); nm_auth_chain_add_call_unsafe(chain, perm, TRUE); return; @@ -2601,6 +2656,7 @@ settings_add_connection_helper(NMSettings *self, GDBusMethodInvocation *context, gboolean is_add_connection_2, GVariant *settings, + const char *plugin, NMSettingsAddConnection2Flags flags) { gs_unref_object NMConnection *connection = NULL; @@ -2636,6 +2692,7 @@ settings_add_connection_helper(NMSettings *self, nm_settings_add_connection_dbus( self, + plugin, connection, persist_mode, NM_FLAGS_HAS(flags, NM_SETTINGS_ADD_CONNECTION2_FLAG_BLOCK_AUTOCONNECT) @@ -2665,6 +2722,7 @@ impl_settings_add_connection(NMDBusObject *obj, invocation, FALSE, settings, + NULL, NM_SETTINGS_ADD_CONNECTION2_FLAG_TO_DISK); } @@ -2685,6 +2743,7 @@ impl_settings_add_connection_unsaved(NMDBusObject *obj, invocation, FALSE, settings, + NULL, NM_SETTINGS_ADD_CONNECTION2_FLAG_IN_MEMORY); } @@ -2700,8 +2759,10 @@ impl_settings_add_connection2(NMDBusObject *obj, NMSettings *self = NM_SETTINGS(obj); gs_unref_variant GVariant *settings = NULL; gs_unref_variant GVariant *args = NULL; + gs_free char *plugin = NULL; NMSettingsAddConnection2Flags flags; const char *args_name; + GVariant *args_value; GVariantIter iter; guint32 flags_u; @@ -2745,7 +2806,13 @@ impl_settings_add_connection2(NMDBusObject *obj, nm_assert(g_variant_is_of_type(args, G_VARIANT_TYPE("a{sv}"))); g_variant_iter_init(&iter, args); - while (g_variant_iter_next(&iter, "{&sv}", &args_name, NULL)) { + while (g_variant_iter_next(&iter, "{&sv}", &args_name, &args_value)) { + if (plugin == NULL && nm_streq(args_name, "plugin") + && g_variant_is_of_type(args_value, G_VARIANT_TYPE_STRING)) { + plugin = g_variant_dup_string(args_value, NULL); + continue; + } + g_dbus_method_invocation_take_error(invocation, g_error_new(NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_ARGUMENTS, @@ -2754,7 +2821,7 @@ impl_settings_add_connection2(NMDBusObject *obj, return; } - settings_add_connection_helper(self, invocation, TRUE, settings, flags); + settings_add_connection_helper(self, invocation, TRUE, settings, plugin, flags); } /*****************************************************************************/ @@ -3201,8 +3268,10 @@ nm_settings_get_connection_by_path(NMSettings *self, const char *path) priv = NM_SETTINGS_GET_PRIVATE(self); connection = - nm_dbus_manager_lookup_object(nm_dbus_object_get_manager(NM_DBUS_OBJECT(self)), path); - if (!connection || !NM_IS_SETTINGS_CONNECTION(connection)) + nm_dbus_manager_lookup_object_with_type(nm_dbus_object_get_manager(NM_DBUS_OBJECT(self)), + NM_TYPE_SETTINGS_CONNECTION, + path); + if (!connection) return NULL; nm_assert(c_list_contains(&priv->connections_lst_head, &connection->_connections_lst)); @@ -3604,6 +3673,7 @@ device_realized(NMDevice *device, GParamSpec *pspec, NMSettings *self) nm_device_get_iface(device)); nm_settings_add_connection(self, + NULL, connection, NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY, NM_SETTINGS_CONNECTION_ADD_REASON_NONE, diff --git a/src/core/settings/nm-settings.h b/src/core/settings/nm-settings.h index 56cebed0..8747d1dc 100644 --- a/src/core/settings/nm-settings.h +++ b/src/core/settings/nm-settings.h @@ -68,6 +68,7 @@ typedef void (*NMSettingsAddCallback)(NMSettings *settings, gpointer user_data); void nm_settings_add_connection_dbus(NMSettings *self, + const char *plugin, NMConnection *connection, NMSettingsConnectionPersistMode persist_mode, NMSettingsConnectionAddReason add_reason, @@ -90,6 +91,7 @@ NMSettingsConnection **nm_settings_get_connections_clone(NMSettings gpointer sort_data); gboolean nm_settings_add_connection(NMSettings *settings, + const char *plugin, NMConnection *connection, NMSettingsConnectionPersistMode persist_mode, NMSettingsConnectionAddReason add_reason, @@ -99,6 +101,7 @@ gboolean nm_settings_add_connection(NMSettings *settings, gboolean nm_settings_update_connection(NMSettings *self, NMSettingsConnection *sett_conn, + const char *plugin_name, NMConnection *new_connection, NMSettingsConnectionPersistMode persist_mode, NMSettingsConnectionIntFlags sett_flags, diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c index 48c4cae9..551f2b91 100644 --- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c @@ -397,7 +397,9 @@ write_8021x_setting(NMConnection *connection, if (wired) svSetValueStr(ifcfg, "KEY_MGMT", "IEEE8021X"); - /* EAP method */ + /* EAP method + * + * FIXME(ifcfg-full-cycle): persist all values of eap-method. */ if (nm_setting_802_1x_get_num_eap_methods(s_8021x)) { value = nm_setting_802_1x_get_eap_method(s_8021x, 0); if (value) @@ -455,11 +457,21 @@ write_8021x_setting(NMConnection *connection, value = "allow-auth"; else if (strcmp(value, "3") == 0) value = "allow-unauth allow-auth"; - else + else { + /* FIXME(ifcfg-full-cycle): does not handle the value "0". */ value = NULL; + } } svSetValueStr(ifcfg, "IEEE_8021X_FAST_PROVISIONING", value); + auth_flags = nm_setting_802_1x_get_phase1_auth_flags(s_8021x); + if (auth_flags != NM_SETTING_802_1X_AUTH_FLAGS_NONE) { + svSetValueEnum(ifcfg, + "IEEE_8021X_PHASE1_AUTH_FLAGS", + nm_setting_802_1x_auth_flags_get_type(), + auth_flags); + } + /* Phase2 auth methods */ phase2_auth = g_string_new(NULL); @@ -480,14 +492,6 @@ write_8021x_setting(NMConnection *connection, g_free(tmp); } - auth_flags = nm_setting_802_1x_get_phase1_auth_flags(s_8021x); - if (auth_flags != NM_SETTING_802_1X_AUTH_FLAGS_NONE) { - svSetValueEnum(ifcfg, - "IEEE_8021X_PHASE1_AUTH_FLAGS", - nm_setting_802_1x_auth_flags_get_type(), - auth_flags); - } - svSetValueStr(ifcfg, "IEEE_8021X_INNER_AUTH_METHODS", phase2_auth->len ? phase2_auth->str : NULL); @@ -503,6 +507,8 @@ write_8021x_setting(NMConnection *connection, str = g_string_new(NULL); num = nm_setting_802_1x_get_num_altsubject_matches(s_8021x); for (i = 0; i < num; i++) { + /* FIXME(ifcfg-full-cycle): this cannot handle values with spaces, which + * are not rejected by nm_connection_verify(). */ if (i > 0) g_string_append_c(str, ' '); match = nm_setting_802_1x_get_altsubject_match(s_8021x, i); @@ -515,6 +521,8 @@ write_8021x_setting(NMConnection *connection, str = g_string_new(NULL); num = nm_setting_802_1x_get_num_phase2_altsubject_matches(s_8021x); for (i = 0; i < num; i++) { + /* FIXME(ifcfg-full-cycle): this cannot handle values with spaces, which + * are not rejected by nm_connection_verify(). */ if (i > 0) g_string_append_c(str, ' '); match = nm_setting_802_1x_get_phase2_altsubject_match(s_8021x, i); diff --git a/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c index 7960ea2a..83e48b81 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -221,6 +221,7 @@ _assert_expected_content(NMConnection *connection, const char *filename, const c success = g_file_set_contents(expected, content_written, len_written, &error); nmtst_assert_success(success, error); } else { + NM_PRAGMA_WARNING_DISABLE_DANGLING_POINTER g_error( "The content of \"%s\" (%zu) differs from \"%s\" (%zu). Set " "NMTST_IFCFG_RH_UPDATE_EXPECTED=yes (or NM_TEST_REGENERATE=1) to update the files " @@ -231,6 +232,7 @@ _assert_expected_content(NMConnection *connection, const char *filename, const c len_expectd, content_written, content_expectd); + NM_PRAGMA_WARNING_REENABLE } } } diff --git a/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c b/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c index b4c30df7..11a8e416 100644 --- a/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c +++ b/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c @@ -2635,8 +2635,11 @@ _escape_filename(gboolean with_extension, const char *filename, gboolean would_b g_assert(esc && esc[0]); g_assert(!strchr(esc, '/')); - if (nm_keyfile_utils_ignore_filename(esc, with_extension)) + if (nm_keyfile_utils_ignore_filename(esc, with_extension)) { + NM_PRAGMA_WARNING_DISABLE_DANGLING_POINTER g_error("Escaping filename \"%s\" yielded \"%s\", but this is ignored", filename, esc); + NM_PRAGMA_WARNING_REENABLE + } } static void diff --git a/src/core/supplicant/nm-supplicant-config.c b/src/core/supplicant/nm-supplicant-config.c index 96c23579..a4e5cc4d 100644 --- a/src/core/supplicant/nm-supplicant-config.c +++ b/src/core/supplicant/nm-supplicant-config.c @@ -805,6 +805,7 @@ nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig NMSettingWirelessSecurity *setting, NMSetting8021x *setting_8021x, const char *con_uuid, + const char *mode, guint32 mtu, NMSettingWirelessSecurityPmf pmf, NMSettingWirelessSecurityFils fils, @@ -815,12 +816,20 @@ nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig const char *key_mgmt, *auth_alg; const char *psk; gboolean set_pmf, wps_disabled; + gboolean is_ap; g_return_val_if_fail(NM_IS_SUPPLICANT_CONFIG(self), FALSE); g_return_val_if_fail(setting != NULL, FALSE); g_return_val_if_fail(con_uuid != NULL, FALSE); g_return_val_if_fail(!error || !*error, FALSE); + /* Currently wpa_supplicant doesn't support FT in AP mode. Even + * if it did, it would require additional parameters as the nas + * identifier and the mobility domain. Therefore we disable all + * FT key-mgmts in AP mode. + */ + is_ap = nm_streq0(mode, NM_SETTING_WIRELESS_MODE_AP); + /* Check if we actually support FILS */ if (!_get_capability(priv, NM_SUPPL_CAP_TYPE_FILS)) { if (fils == NM_SETTING_WIRELESS_SECURITY_FILS_REQUIRED) { @@ -852,11 +861,39 @@ nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig g_string_append(key_mgmt_conf, "WPA-PSK"); if (_get_capability(priv, NM_SUPPL_CAP_TYPE_PMF)) g_string_append(key_mgmt_conf, " WPA-PSK-SHA256"); - if (_get_capability(priv, NM_SUPPL_CAP_TYPE_FT)) + if (!is_ap && _get_capability(priv, NM_SUPPL_CAP_TYPE_FT)) g_string_append(key_mgmt_conf, " FT-PSK"); - if (_get_capability(priv, NM_SUPPL_CAP_TYPE_SAE)) { + + /* For NM "key-mgmt=wpa-psk" doesn't strictly mean WPA1/wPA2 only, + * but also allows WPA3 (SAE), so that existing connections can + * benefit from the improved security when the AP gets upgraded. + * + * According to WPA3_Specification_v3.0 section 2.3, when operating + * in WPA3-Personal transition mode a STA: + * + * - should allow AKM suite selector: 00-0F-AC:6 (WPA-PSK-SHA256) to + * be selected for an association; + * - shall negotiate PMF when associating to an AP using SAE. + * + * Those conditions are met when the interface has capabilities + * SAE, PMF, BIP. + * + * According to WPA3_Specification_v3.0 section 2.3, when operating + * in WPA3-Personal transition mode an AP: + * + * - shall set MFPC to 1, MFPR to 0. + * + * Therefore, do not operate in WPA3-Personal transition mode when PMF + * is set to disabled. This also provides a way to be compatible with + * some devices that are not fully compatible with WPA3-Personal + * transition mode. + */ + if (_get_capability(priv, NM_SUPPL_CAP_TYPE_SAE) + && _get_capability(priv, NM_SUPPL_CAP_TYPE_PMF) + && _get_capability(priv, NM_SUPPL_CAP_TYPE_BIP) + && (!is_ap || pmf != NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE)) { g_string_append(key_mgmt_conf, " SAE"); - if (_get_capability(priv, NM_SUPPL_CAP_TYPE_FT)) + if (!is_ap && _get_capability(priv, NM_SUPPL_CAP_TYPE_FT)) g_string_append(key_mgmt_conf, " FT-SAE"); } @@ -864,13 +901,13 @@ nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig pmf = NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED; g_string_append(key_mgmt_conf, "SAE"); - if (_get_capability(priv, NM_SUPPL_CAP_TYPE_FT)) + if (!is_ap && _get_capability(priv, NM_SUPPL_CAP_TYPE_FT)) g_string_append(key_mgmt_conf, " FT-SAE"); } else if (nm_streq(key_mgmt, "wpa-eap")) { if (pmf != NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED) g_string_append(key_mgmt_conf, "WPA-EAP"); - if (_get_capability(priv, NM_SUPPL_CAP_TYPE_FT)) { + if (!is_ap && _get_capability(priv, NM_SUPPL_CAP_TYPE_FT)) { g_string_append(key_mgmt_conf, " FT-EAP"); if (_get_capability(priv, NM_SUPPL_CAP_TYPE_SHA384)) g_string_append(key_mgmt_conf, " FT-EAP-SHA384"); @@ -891,7 +928,7 @@ nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig case NM_SETTING_WIRELESS_SECURITY_FILS_OPTIONAL: if (_get_capability(priv, NM_SUPPL_CAP_TYPE_PMF)) { g_string_append(key_mgmt_conf, " FILS-SHA256 FILS-SHA384"); - if (_get_capability(priv, NM_SUPPL_CAP_TYPE_FT)) { + if (!is_ap && _get_capability(priv, NM_SUPPL_CAP_TYPE_FT)) { g_string_append(key_mgmt_conf, " FT-FILS-SHA256"); if (_get_capability(priv, NM_SUPPL_CAP_TYPE_SHA384)) g_string_append(key_mgmt_conf, " FT-FILS-SHA384"); @@ -907,7 +944,7 @@ nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig pmf = NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED; g_string_append(key_mgmt_conf, "WPA-EAP-SUITE-B-192"); - if (_get_capability(priv, NM_SUPPL_CAP_TYPE_FT) + if (!is_ap && _get_capability(priv, NM_SUPPL_CAP_TYPE_FT) && _get_capability(priv, NM_SUPPL_CAP_TYPE_SHA384)) g_string_append(key_mgmt_conf, " FT-EAP-SHA384"); } diff --git a/src/core/supplicant/nm-supplicant-config.h b/src/core/supplicant/nm-supplicant-config.h index 349c310f..ee7f4dc8 100644 --- a/src/core/supplicant/nm-supplicant-config.h +++ b/src/core/supplicant/nm-supplicant-config.h @@ -51,6 +51,7 @@ gboolean nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig NMSettingWirelessSecurity *setting, NMSetting8021x *setting_8021x, const char *con_uuid, + const char *mode, guint32 mtu, NMSettingWirelessSecurityPmf pmf, NMSettingWirelessSecurityFils fils, diff --git a/src/core/supplicant/nm-supplicant-interface.c b/src/core/supplicant/nm-supplicant-interface.c index d8276144..e502ae85 100644 --- a/src/core/supplicant/nm-supplicant-interface.c +++ b/src/core/supplicant/nm-supplicant-interface.c @@ -1225,8 +1225,10 @@ parse_capabilities(NMSupplicantInterface *self, GVariant *capabilities) const guint32 old_max_scan_ssids = priv->max_scan_ssids; gboolean have_ft = FALSE; gboolean have_sae = FALSE; + gboolean have_bip = FALSE; gint32 max_scan_ssids; const char **array; + guint i; nm_assert(capabilities && g_variant_is_of_type(capabilities, G_VARIANT_TYPE_VARDICT)); @@ -1236,12 +1238,28 @@ parse_capabilities(NMSupplicantInterface *self, GVariant *capabilities) g_free(array); } + if (g_variant_lookup(capabilities, "GroupMgmt", "^a&s", &array)) { + for (i = 0; array[i]; i++) { + if (NM_IN_STRSET(array[i], + "aes-128-cmac", + "bip-gmac-128", + "bip-gmac-256", + "bip-cmac-256")) { + have_bip = TRUE; + break; + } + } + } + priv->iface_capabilities = NM_SUPPL_CAP_MASK_SET(priv->iface_capabilities, NM_SUPPL_CAP_TYPE_FT, have_ft ? NM_TERNARY_TRUE : NM_TERNARY_FALSE); priv->iface_capabilities = NM_SUPPL_CAP_MASK_SET(priv->iface_capabilities, NM_SUPPL_CAP_TYPE_SAE, have_sae ? NM_TERNARY_TRUE : NM_TERNARY_FALSE); + priv->iface_capabilities = NM_SUPPL_CAP_MASK_SET(priv->iface_capabilities, + NM_SUPPL_CAP_TYPE_BIP, + have_bip ? NM_TERNARY_TRUE : NM_TERNARY_FALSE); if (g_variant_lookup(capabilities, "Modes", "^a&s", &array)) { /* Setting p2p_capable might toggle _prop_p2p_available_get(). However, @@ -1317,10 +1335,12 @@ _starting_check_ready(NMSupplicantInterface *self) " AP%c" " FT%c" " SAE%c" + " BIP%c" "", NM_SUPPL_CAP_TO_CHAR(priv->iface_capabilities, NM_SUPPL_CAP_TYPE_AP), NM_SUPPL_CAP_TO_CHAR(priv->iface_capabilities, NM_SUPPL_CAP_TYPE_FT), - NM_SUPPL_CAP_TO_CHAR(priv->iface_capabilities, NM_SUPPL_CAP_TYPE_SAE)); + NM_SUPPL_CAP_TO_CHAR(priv->iface_capabilities, NM_SUPPL_CAP_TYPE_SAE), + NM_SUPPL_CAP_TO_CHAR(priv->iface_capabilities, NM_SUPPL_CAP_TYPE_BIP)); /* Other global properties are set in constructed() because they don't * depend on interface capabilities. */ @@ -1362,6 +1382,7 @@ _get_capability(NMSupplicantInterfacePrivate *priv, NMSupplCapType type) } break; case NM_SUPPL_CAP_TYPE_SAE: + case NM_SUPPL_CAP_TYPE_BIP: nm_assert(NM_SUPPL_CAP_MASK_GET(priv->global_capabilities, type) == NM_TERNARY_DEFAULT); value = NM_SUPPL_CAP_MASK_GET(priv->iface_capabilities, type); break; @@ -1395,10 +1416,13 @@ nm_supplicant_interface_get_capabilities(NMSupplicantInterface *self) caps = NM_SUPPL_CAP_MASK_SET(caps, NM_SUPPL_CAP_TYPE_SAE, _get_capability(priv, NM_SUPPL_CAP_TYPE_SAE)); + caps = NM_SUPPL_CAP_MASK_SET(caps, + NM_SUPPL_CAP_TYPE_BIP, + _get_capability(priv, NM_SUPPL_CAP_TYPE_BIP)); nm_assert(!NM_FLAGS_ANY(priv->iface_capabilities, ~(NM_SUPPL_CAP_MASK_T_AP_MASK | NM_SUPPL_CAP_MASK_T_FT_MASK - | NM_SUPPL_CAP_MASK_T_SAE_MASK))); + | NM_SUPPL_CAP_MASK_T_SAE_MASK | NM_SUPPL_CAP_MASK_T_BIP_MASK))); #if NM_MORE_ASSERTS > 10 { diff --git a/src/core/supplicant/nm-supplicant-manager.c b/src/core/supplicant/nm-supplicant-manager.c index 9de845f0..2ec7db23 100644 --- a/src/core/supplicant/nm-supplicant-manager.c +++ b/src/core/supplicant/nm-supplicant-manager.c @@ -920,6 +920,7 @@ _dbus_get_capabilities_cb(GVariant *res, GError *error, gpointer user_data) _caps_set(priv, NM_SUPPL_CAP_TYPE_PMF, NM_TERNARY_FALSE); _caps_set(priv, NM_SUPPL_CAP_TYPE_FILS, NM_TERNARY_FALSE); _caps_set(priv, NM_SUPPL_CAP_TYPE_SUITEB192, NM_TERNARY_FALSE); + _caps_set(priv, NM_SUPPL_CAP_TYPE_WEP, NM_TERNARY_TRUE); if (array) { for (a = array; *a; a++) { if (nm_streq(*a, "ap")) { @@ -954,6 +955,10 @@ _dbus_get_capabilities_cb(GVariant *res, GError *error, gpointer user_data) _caps_set(priv, NM_SUPPL_CAP_TYPE_SUITEB192, NM_TERNARY_TRUE); continue; } + if (nm_streq(*a, "wep_disabled")) { + _caps_set(priv, NM_SUPPL_CAP_TYPE_WEP, NM_TERNARY_FALSE); + continue; + } } } } @@ -994,6 +999,7 @@ _dbus_get_capabilities_cb(GVariant *res, GError *error, gpointer user_data) " FAST%c" " WFD%c" " SUITEB192%c" + " WEP%c" "", NM_SUPPL_CAP_TO_CHAR(priv->capabilities, NM_SUPPL_CAP_TYPE_AP), NM_SUPPL_CAP_TO_CHAR(priv->capabilities, NM_SUPPL_CAP_TYPE_PMF), @@ -1004,7 +1010,8 @@ _dbus_get_capabilities_cb(GVariant *res, GError *error, gpointer user_data) NM_SUPPL_CAP_TO_CHAR(priv->capabilities, NM_SUPPL_CAP_TYPE_MESH), NM_SUPPL_CAP_TO_CHAR(priv->capabilities, NM_SUPPL_CAP_TYPE_FAST), NM_SUPPL_CAP_TO_CHAR(priv->capabilities, NM_SUPPL_CAP_TYPE_WFD), - NM_SUPPL_CAP_TO_CHAR(priv->capabilities, NM_SUPPL_CAP_TYPE_SUITEB192)); + NM_SUPPL_CAP_TO_CHAR(priv->capabilities, NM_SUPPL_CAP_TYPE_SUITEB192), + NM_SUPPL_CAP_TO_CHAR(priv->capabilities, NM_SUPPL_CAP_TYPE_WEP)); nm_assert(g_hash_table_size(priv->supp_ifaces) == 0); nm_assert(c_list_is_empty(&priv->supp_lst_head)); diff --git a/src/core/supplicant/nm-supplicant-types.h b/src/core/supplicant/nm-supplicant-types.h index d5cf1bf7..1ae67e13 100644 --- a/src/core/supplicant/nm-supplicant-types.h +++ b/src/core/supplicant/nm-supplicant-types.h @@ -48,6 +48,10 @@ typedef enum { NM_SUPPL_CAP_TYPE_FAST, NM_SUPPL_CAP_TYPE_WFD, NM_SUPPL_CAP_TYPE_SUITEB192, + NM_SUPPL_CAP_TYPE_WEP, + NM_SUPPL_CAP_TYPE_BIP, + /* Note: if you're adding a capability here, log its presence at the + * bottom of _dbus_get_capabilities_cb(). */ _NM_SUPPL_CAP_TYPE_NUM, } NMSupplCapType; @@ -75,6 +79,8 @@ typedef enum { _NM_SUPPL_CAP_MASK_DEFINE(FT), _NM_SUPPL_CAP_MASK_DEFINE(SAE), _NM_SUPPL_CAP_MASK_DEFINE(SHA384), + _NM_SUPPL_CAP_MASK_DEFINE(WEP), + _NM_SUPPL_CAP_MASK_DEFINE(BIP), #undef _NM_SUPPL_CAP_MASK_DEFINE } NMSupplCapMask; diff --git a/src/core/supplicant/tests/test-supplicant-config.c b/src/core/supplicant/tests/test-supplicant-config.c index 53c5f70f..237b1a96 100644 --- a/src/core/supplicant/tests/test-supplicant-config.c +++ b/src/core/supplicant/tests/test-supplicant-config.c @@ -116,6 +116,7 @@ build_supplicant_config(NMConnection *connection, s_wsec, s_8021x, nm_connection_get_uuid(connection), + nm_setting_wireless_get_mode(s_wifi), mtu, pmf, fils, diff --git a/src/core/tests/test-core.c b/src/core/tests/test-core.c index f61d66d9..b4e1c4d5 100644 --- a/src/core/tests/test-core.c +++ b/src/core/tests/test-core.c @@ -2319,10 +2319,25 @@ test_machine_id_read(void) char machine_id_str[33]; gpointer logstate; + /* This unit test checks our functions to read /etc/machine-id. As + * the path name is not configurable (and the test does not setup + * a chroot/mountns), we read the actual file from the system. That + * is ugly, as the test depends on the system where it's running. + * + * Still, better a bad test, than no test. Patch welcome to fix this + * shortcoming. + * + * Also, if you have a sufficiently broken system, the unit test fails. + * In particular, if the machine-id file exists but does not contain + * a valid ID. Just don't have that. Fix your system. */ + logstate = nmtst_logging_disable(FALSE); /* If you run this test as root, without a valid /etc/machine-id, * the code will try to get the secret-key. That is a bit ugly, - * but no real problem. */ + * but no real problem. + * + * The real answer is: don't run our unit tests as root. That's + * not the way to do it. */ machine_id = nm_utils_machine_id_bin(); nmtst_logging_reenable(logstate); @@ -2338,9 +2353,15 @@ test_machine_id_read(void) * is invalid. Our machine-id is fake, and we have nothing to * compare against. */ - /* NOTE: this test will fail, if you don't have /etc/machine-id, - * but a valid "LOCALSTATEDIR/lib/dbus/machine-id" file. - * Just don't do that. */ + if (g_file_test(LOCALSTATEDIR "/lib/dbus/machine-id", G_FILE_TEST_EXISTS)) { + /* Hm. So systemd failed to read /etc/machine-id, but we may have the one from D-Bus. + * With LOCALSTATEDIR"/lib/dbus/machine-id", we don't really know whether we + * parsed that file. Assume we don't know and skip the test on this system. */ + g_assert(!nm_utils_machine_id_is_fake()); + return; + } + + /* OK, in this case, our function should have generated a random machine ID. */ g_assert(nm_utils_machine_id_is_fake()); } else { g_assert(!nm_utils_machine_id_is_fake()); diff --git a/src/core/tests/test-l3cfg.c b/src/core/tests/test-l3cfg.c index 5501079e..924d98f1 100644 --- a/src/core/tests/test-l3cfg.c +++ b/src/core/tests/test-l3cfg.c @@ -382,13 +382,11 @@ test_l3cfg(gconstpointer test_data) nm_l3cfg_commit_type_register(l3cfg0, NM_L3_CFG_COMMIT_TYPE_UPDATE, NULL, "test1"); if (!nmtst_get_rand_one_case_in(4)) { - commit_type_2 = - nm_l3cfg_commit_type_register(l3cfg0, - nmtst_rand_select(NM_L3_CFG_COMMIT_TYPE_NONE, - NM_L3_CFG_COMMIT_TYPE_ASSUME, - NM_L3_CFG_COMMIT_TYPE_UPDATE), - NULL, - "test2"); + commit_type_2 = nm_l3cfg_commit_type_register( + l3cfg0, + nmtst_rand_select(NM_L3_CFG_COMMIT_TYPE_NONE, NM_L3_CFG_COMMIT_TYPE_UPDATE), + NULL, + "test2"); } else commit_type_2 = NULL; @@ -956,7 +954,7 @@ test_l3_ipv6ll(gconstpointer test_data) .steps_done = FALSE, }; TestL3IPv6LLData *const tdata = &tdata_stack; - char sbuf1[sizeof(_nm_utils_to_string_buffer)]; + char sbuf1[NM_UTILS_TO_STRING_BUFFER_SIZE]; int r; _LOGD("test start (/l3-ipv6ll/%d)", TEST_IDX); diff --git a/src/core/tests/test-utils.c b/src/core/tests/test-utils.c index 2d2b7340..ad9950dd 100644 --- a/src/core/tests/test-utils.c +++ b/src/core/tests/test-utils.c @@ -212,6 +212,52 @@ test_hw_addr_gen_stable_eth(void) "04:0D:CD:0C:9E:2C"); } +static void +test_shorten_hostname(void) +{ + gs_free char *maxhost = NULL; + char *hostname; + +#define do_test_shorten_hostname(_host, _exp_res, _exp_short) \ + G_STMT_START \ + { \ + gboolean _res; \ + gs_free char *_short = NULL; \ + \ + _res = nm_utils_shorten_hostname((_host), &_short); \ + g_assert_cmpint((_res), ==, (_exp_res)); \ + g_assert_cmpstr(_short, ==, (_exp_short)); \ + } \ + G_STMT_END + + /* 'maxhost' is the longest allowed hostname according to + * system configuration (`getconf HOST_NAME_MAX`). On Linux + * it's typically 64 characters, but POSIX allows up to + * 255 characters. + */ + maxhost = g_strnfill(HOST_NAME_MAX, 'a'); + + do_test_shorten_hostname("name1", TRUE, NULL); + + do_test_shorten_hostname("name1.example.com", TRUE, NULL); + + do_test_shorten_hostname(maxhost, TRUE, NULL); + + hostname = g_strdup_printf("%sbbb", maxhost); + do_test_shorten_hostname(hostname, TRUE, maxhost); + nm_clear_g_free(&hostname); + + hostname = g_strdup_printf("%s.com", maxhost); + do_test_shorten_hostname(hostname, TRUE, maxhost); + nm_clear_g_free(&hostname); + + hostname = g_strdup_printf("name1.%s.com", maxhost); + do_test_shorten_hostname(hostname, TRUE, "name1"); + nm_clear_g_free(&hostname); + + do_test_shorten_hostname(".name1", FALSE, NULL); +} + /*****************************************************************************/ NMTST_DEFINE(); @@ -223,6 +269,7 @@ main(int argc, char **argv) g_test_add_func("/utils/stable_privacy", test_stable_privacy); g_test_add_func("/utils/hw_addr_gen_stable_eth", test_hw_addr_gen_stable_eth); + g_test_add_func("/utils/shorten-hostname", test_shorten_hostname); return g_test_run(); } |