diff options
Diffstat (limited to 'src/core/devices/nm-device.c')
| -rw-r--r-- | src/core/devices/nm-device.c | 776 |
1 files changed, 427 insertions, 349 deletions
diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index 50386d00..ea1b9647 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -185,7 +185,7 @@ typedef struct { typedef struct { NMDhcpClient *client; NMDhcpConfig *config; - gulong state_sigid; + gulong notify_sigid; guint grace_id; bool grace_pending : 1; bool was_active : 1; @@ -290,7 +290,8 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMDevice, PROP_STATISTICS_RX_BYTES, PROP_IP4_CONNECTIVITY, PROP_IP6_CONNECTIVITY, - PROP_INTERFACE_FLAGS, ); + PROP_INTERFACE_FLAGS, + PROP_PORTS, ); typedef struct _NMDevicePrivate { bool in_state_changed; @@ -316,7 +317,12 @@ typedef struct _NMDevicePrivate { guint queued_ip_config_id_x[2]; }; - GSList *pending_actions; + struct { + const char **arr; + guint len; + guint alloc; + } pending_actions; + GSList *dad6_failed_addrs; NMDBusTrackObjPath parent_device; @@ -500,6 +506,7 @@ typedef struct _NMDevicePrivate { NMDeviceStageState stage1_sriov_state : 3; bool ip_config_started : 1; + bool tc_committed : 1; char *current_stable_id; @@ -574,7 +581,6 @@ typedef struct _NMDevicePrivate { AppliedConfig ip6_config; /* Event ID of the current IP6 config from DHCP */ char * event_id; - gulong prefix_sigid; NMNDiscDHCPLevel mode; guint needed_prefixes; } dhcp6; @@ -696,15 +702,17 @@ typedef struct _NMDevicePrivate { guint sriov_reset_pending; struct { - guint timeout_id; - guint refresh_rate_ms; - guint64 tx_bytes; - guint64 rx_bytes; + GSource *timeout_source; + guint refresh_rate_ms; + guint64 tx_bytes; + guint64 rx_bytes; } stats; bool mtu_force_set_done : 1; NMOptionBool promisc_reset; + + GVariant *ports_variant; /* Array of port devices D-Bus path */ } NMDevicePrivate; G_DEFINE_ABSTRACT_TYPE(NMDevice, nm_device, NM_TYPE_DBUS_OBJECT) @@ -1190,6 +1198,29 @@ _prop_get_connection_llmnr(NMDevice *self) NM_SETTING_CONNECTION_LLMNR_DEFAULT); } +static NMSettingConnectionDnsOverTls +_prop_get_connection_dns_over_tls(NMDevice *self) +{ + NMConnection * connection; + NMSettingConnectionDnsOverTls dns_over_tls = NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT; + + g_return_val_if_fail(NM_IS_DEVICE(self), NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT); + + connection = nm_device_get_applied_connection(self); + if (connection) + dns_over_tls = nm_setting_connection_get_dns_over_tls( + nm_connection_get_setting_connection(connection)); + if (dns_over_tls != NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT) + return dns_over_tls; + + return nm_config_data_get_connection_default_int64(NM_CONFIG_GET_DATA, + NM_CON_DEFAULT("connection.dns-over-tls"), + self, + NM_SETTING_CONNECTION_DNS_OVER_TLS_NO, + NM_SETTING_CONNECTION_DNS_OVER_TLS_YES, + NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT); +} + static guint32 _prop_get_ipvx_route_table(NMDevice *self, int addr_family) { @@ -2407,7 +2438,7 @@ nm_device_ip_config_new(NMDevice *self, int addr_family) } NML3ConfigData * -nm_device_create_l3_config_data(NMDevice *self) +nm_device_create_l3_config_data(NMDevice *self, NMIPConfigSource source) { int ifindex; @@ -2417,7 +2448,7 @@ nm_device_create_l3_config_data(NMDevice *self) if (ifindex <= 0) g_return_val_if_reached(NULL); - return nm_l3_config_data_new(nm_device_get_multi_index(self), ifindex); + return nm_l3_config_data_new(nm_device_get_multi_index(self), ifindex, source); } static void @@ -2554,8 +2585,8 @@ nm_device_sys_iface_state_set(NMDevice *self, NMDeviceSysIfaceState sys_iface_st if (priv->sys_iface_state != sys_iface_state) { _LOGT(LOGD_DEVICE, "sys-iface-state: %s -> %s", - nm_device_sys_iface_state_to_str(priv->sys_iface_state), - nm_device_sys_iface_state_to_str(sys_iface_state)); + nm_device_sys_iface_state_to_string(priv->sys_iface_state), + nm_device_sys_iface_state_to_string(sys_iface_state)); priv->sys_iface_state_ = sys_iface_state; } @@ -2741,7 +2772,7 @@ nm_device_sysctl_ip_conf_get_int_checked(NMDevice * self, } static void -set_ipv6_token(NMDevice *self, NMUtilsIPv6IfaceId iid, const char *token_str) +set_ipv6_token(NMDevice *self, const NMUtilsIPv6IfaceId *iid, const char *token_str) { NMPlatform * platform; int ifindex; @@ -2757,7 +2788,7 @@ set_ipv6_token(NMDevice *self, NMUtilsIPv6IfaceId iid, const char *token_str) ifindex = nm_device_get_ip_ifindex(self); link = nm_platform_link_get(platform, ifindex); - if (link && link->inet6_token.id == iid.id) { + if (link && link->inet6_token.id == iid->id) { _LOGT(LOGD_DEVICE | LOGD_IP6, "token %s already set", token_str); return; } @@ -2905,7 +2936,7 @@ _set_ip_state(NMDevice *self, int addr_family, NMDeviceIPState new_state) "ip%c-state: set to %d (%s)", nm_utils_addr_family_to_char(addr_family), (int) new_state, - nm_device_ip_state_to_str(new_state)); + nm_device_ip_state_to_string(new_state)); priv->ip_state_x_[IS_IPv4] = new_state; @@ -3141,8 +3172,9 @@ _set_ip_ifindex(NMDevice *self, int ifindex, const char *ifname) nm_platform_process_events_ensure_link(platform, priv->ip_ifindex, priv->ip_iface); - if (nm_platform_kernel_support_get(NM_PLATFORM_KERNEL_SUPPORT_TYPE_USER_IPV6LL)) - nm_platform_link_set_user_ipv6ll_enabled(platform, priv->ip_ifindex, TRUE); + nm_platform_link_set_inet6_addr_gen_mode(platform, + priv->ip_ifindex, + NM_IN6_ADDR_GEN_MODE_NONE); if (!nm_platform_link_is_up(platform, priv->ip_ifindex)) nm_platform_link_change_flags(platform, priv->ip_ifindex, IFF_UP, TRUE); @@ -3444,7 +3476,7 @@ _stats_set_refresh_rate(NMDevice *self, guint refresh_rate_ms) if (_stats_refresh_rate_real(old_rate) == refresh_rate_ms) return; - nm_clear_g_source(&priv->stats.timeout_id); + nm_clear_g_source_inst(&priv->stats.timeout_source); if (!refresh_rate_ms) return; @@ -3456,7 +3488,7 @@ _stats_set_refresh_rate(NMDevice *self, guint refresh_rate_ms) if (ifindex > 0) nm_platform_link_refresh(nm_device_get_platform(self), ifindex); - priv->stats.timeout_id = g_timeout_add(refresh_rate_ms, _stats_timeout_cb, self); + priv->stats.timeout_source = nm_g_timeout_add_source(refresh_rate_ms, _stats_timeout_cb, self); } /*****************************************************************************/ @@ -4509,7 +4541,7 @@ concheck_cb(NMConnectivity * connectivity, seq = handle->seq; _LOGT(LOGD_CONCHECK, - "connectivity: [Ipv%c] complete check (seq:%llu, state:%s)", + "connectivity: [IPv%c] complete check (seq:%llu, state:%s)", nm_utils_addr_family_to_char(handle->addr_family), (long long unsigned) handle->seq, nm_connectivity_state_to_string(state)); @@ -5803,7 +5835,7 @@ nm_device_update_from_platform_link(NMDevice *self, const NMPlatformLink *plink) _notify(self, PROP_PATH); } - if (plink && !nm_str_is_empty(plink->name) && nm_utils_strdup_reset(&priv->iface_, plink->name)) + if (plink && !nm_str_is_empty(plink->name) && nm_strdup_reset(&priv->iface_, plink->name)) _notify(self, PROP_IFACE); str = plink ? plink->driver : NULL; @@ -5976,9 +6008,10 @@ config_changed(NMConfig * config, { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - if (priv->state <= NM_DEVICE_STATE_DISCONNECTED || priv->state > NM_DEVICE_STATE_ACTIVATED) { + if (priv->state <= NM_DEVICE_STATE_DISCONNECTED || priv->state >= NM_DEVICE_STATE_ACTIVATED) { priv->ignore_carrier = nm_config_data_get_ignore_carrier(config_data, self); - if (NM_FLAGS_HAS(changes, NM_CONFIG_CHANGE_VALUES)) + if (NM_FLAGS_HAS(changes, NM_CONFIG_CHANGE_VALUES) + && !nm_device_get_applied_setting(self, NM_TYPE_SETTING_SRIOV)) device_init_static_sriov_num_vfs(self); } } @@ -6023,7 +6056,7 @@ realize_start_setup(NMDevice * self, NMPlatform * platform; NMDeviceCapabilities capabilities = 0; NMConfig * config; - guint real_rate; + guint refresh_rate_ms; gboolean unmanaged; /* plink is a NMPlatformLink type, however, we require it to come from the platform @@ -6087,8 +6120,8 @@ realize_start_setup(NMDevice * self, if (priv->firmware_version) _notify(self, PROP_FIRMWARE_VERSION); - if (nm_platform_kernel_support_get(NM_PLATFORM_KERNEL_SUPPORT_TYPE_USER_IPV6LL)) - priv->ipv6ll_handle = nm_platform_link_get_user_ipv6ll_enabled(platform, priv->ifindex); + priv->ipv6ll_handle = (nm_platform_link_get_inet6_addr_gen_mode(platform, priv->ifindex) + == NM_IN6_ADDR_GEN_MODE_NONE); if (nm_platform_link_supports_sriov(platform, priv->ifindex)) capabilities |= NM_DEVICE_CAP_SRIOV; @@ -6131,10 +6164,12 @@ realize_start_setup(NMDevice * self, nm_device_set_carrier_from_platform(self); - nm_assert(!priv->stats.timeout_id); - real_rate = _stats_refresh_rate_real(priv->stats.refresh_rate_ms); - if (real_rate) - priv->stats.timeout_id = g_timeout_add(real_rate, _stats_timeout_cb, self); + nm_assert(!priv->stats.timeout_source); + refresh_rate_ms = _stats_refresh_rate_real(priv->stats.refresh_rate_ms); + if (refresh_rate_ms > 0) { + priv->stats.timeout_source = + nm_g_timeout_add_source(refresh_rate_ms, _stats_timeout_cb, self); + } klass->realize_start_notify(self, plink); @@ -6320,7 +6355,7 @@ nm_device_unrealize(NMDevice *self, gboolean remove_resources, GError **error) _notify(self, PROP_PHYSICAL_PORT_ID); } - nm_clear_g_source(&priv->stats.timeout_id); + nm_clear_g_source_inst(&priv->stats.timeout_source); _stats_update_counters(self, 0, 0); priv->hw_addr_len_ = 0; @@ -6442,9 +6477,9 @@ slave_state_changed(NMDevice * slave, "slave %s state change %d (%s) -> %d (%s)", nm_device_get_iface(slave), slave_old_state, - nm_device_state_to_str(slave_old_state), + nm_device_state_to_string(slave_old_state), slave_new_state, - nm_device_state_to_str(slave_new_state)); + nm_device_state_to_string(slave_new_state)); /* Don't try to enslave slaves until the master is ready */ if (priv->state < NM_DEVICE_STATE_CONFIG) @@ -6788,7 +6823,9 @@ nm_device_slave_notify_enslave(NMDevice *self, gboolean success) priv->is_enslaved = TRUE; _notify(self, PROP_MASTER); - _notify(priv->master, PROP_SLAVES); + + nm_clear_pointer(&NM_DEVICE_GET_PRIVATE(priv->master)->ports_variant, g_variant_unref); + nm_gobject_notify_together(priv->master, PROP_PORTS, PROP_SLAVES); } else if (activating) { _LOGW(LOGD_DEVICE, "Activation: connection '%s' could not be enslaved", @@ -6852,8 +6889,11 @@ nm_device_slave_notify_release(NMDevice *self, NMDeviceStateReason reason) if (priv->is_enslaved) { priv->is_enslaved = FALSE; + _notify(self, PROP_MASTER); - _notify(priv->master, PROP_SLAVES); + + nm_clear_pointer(&NM_DEVICE_GET_PRIVATE(priv->master)->ports_variant, g_variant_unref); + nm_gobject_notify_together(priv->master, PROP_PORTS, PROP_SLAVES); } } @@ -7339,7 +7379,7 @@ nm_device_generate_connection(NMDevice *self, NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE, NM_IN6_ADDR_GEN_MODE_EUI64, NM_SETTING_IP6_CONFIG_TOKEN, - nm_utils_inet6_interface_identifier_to_token(pllink->inet6_token, sbuf), + nm_utils_inet6_interface_identifier_to_token(&pllink->inet6_token, sbuf), NULL); } } @@ -7756,7 +7796,8 @@ recheck_available(gpointer user_data) now_available ? "" : "not ", new_state == NM_DEVICE_STATE_UNAVAILABLE ? "no change required for" : "will transition to", - nm_device_state_to_str(new_state == NM_DEVICE_STATE_UNAVAILABLE ? state : new_state)); + nm_device_state_to_string(new_state == NM_DEVICE_STATE_UNAVAILABLE ? state + : new_state)); priv->recheck_available.available_reason = NM_DEVICE_STATE_REASON_NONE; priv->recheck_available.unavailable_reason = NM_DEVICE_STATE_REASON_NONE; @@ -8259,7 +8300,7 @@ activate_stage1_device_prepare(NMDevice *self) priv->master_ready_id = g_signal_connect(active, "notify::" NM_ACTIVE_CONNECTION_INT_MASTER_READY, - (GCallback) master_ready_cb, + G_CALLBACK(master_ready_cb), self); } return; @@ -8478,10 +8519,7 @@ tc_commit(NMDevice *self) qdiscs = nm_utils_qdiscs_from_tc_setting(platform, s_tc, ip_ifindex); tfilters = nm_utils_tfilters_from_tc_setting(platform, s_tc, ip_ifindex); - if (!nm_platform_qdisc_sync(platform, ip_ifindex, qdiscs)) - return FALSE; - - if (!nm_platform_tfilter_sync(platform, ip_ifindex, tfilters)) + if (!nm_platform_tc_sync(platform, ip_ifindex, qdiscs, tfilters)) return FALSE; return TRUE; @@ -8511,13 +8549,14 @@ activate_stage2_device_config(NMDevice *self) _ethtool_state_set(self); if (!nm_device_sys_iface_state_is_external_or_assume(self)) { - if (!tc_commit(self)) { - _LOGW(LOGD_IP6, "failed applying traffic control rules"); + if (!priv->tc_committed && !tc_commit(self)) { + _LOGW(LOGD_DEVICE, "failed applying traffic control rules"); nm_device_state_changed(self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_CONFIG_FAILED); return; } + priv->tc_committed = TRUE; } _routing_rules_sync(self, NM_TERNARY_TRUE); @@ -8981,6 +9020,7 @@ ensure_con_ip_config(NMDevice *self, int addr_family) nm_connection_get_setting_ip4_config(connection), _prop_get_connection_mdns(self), _prop_get_connection_llmnr(self), + _prop_get_connection_dns_over_tls(self), nm_device_get_route_table(self, addr_family), nm_device_get_route_metric(self, addr_family)); } else { @@ -9028,7 +9068,7 @@ dhcp4_cleanup(NMDevice *self, CleanupType cleanup_type, gboolean release) if (priv->dhcp_data_4.client) { /* Stop any ongoing DHCP transaction on this device */ - nm_clear_g_signal_handler(priv->dhcp_data_4.client, &priv->dhcp_data_4.state_sigid); + nm_clear_g_signal_handler(priv->dhcp_data_4.client, &priv->dhcp_data_4.notify_sigid); if (cleanup_type == CLEANUP_TYPE_DECONFIGURE || cleanup_type == CLEANUP_TYPE_REMOVED) nm_dhcp_client_stop(priv->dhcp_data_4.client, release); @@ -9251,7 +9291,7 @@ ip_config_merge_and_apply(NMDevice *self, int addr_family, gboolean commit) if (commit && priv->ndisc_started && ip6_addr_gen_token && nm_utils_ipv6_interface_identifier_get_from_token(&iid, ip6_addr_gen_token)) { - set_ipv6_token(self, iid, ip6_addr_gen_token); + set_ipv6_token(self, &iid, ip6_addr_gen_token); } } @@ -9291,7 +9331,7 @@ dhcp4_lease_change(NMDevice *self, NMIP4Config *config, gboolean bound) return FALSE; } - nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP4_CHANGE, self, NULL, NULL, NULL, NULL); + nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP_CHANGE_4, self, NULL, NULL, NULL, NULL); return TRUE; } @@ -9373,7 +9413,7 @@ dhcp4_fail(NMDevice *self, NMDhcpState dhcp_state) _LOGD(LOGD_DHCP4, "DHCPv4 failed (ip_state %s, was_active %d)", - nm_device_ip_state_to_str(priv->ip_state_4), + nm_device_ip_state_to_string(priv->ip_state_4), priv->dhcp_data_4.was_active); /* The client is always left running after a failure. */ @@ -9429,21 +9469,27 @@ dhcp4_dad_cb(NMDevice *self, NMIP4Config **configs, gboolean success) } static void -dhcp4_state_changed(NMDhcpClient *client, - NMDhcpState state, - NMIP4Config * ip4_config, - GHashTable * options, - gpointer user_data) +dhcp4_notify(NMDhcpClient *client, const NMDhcpClientNotifyData *notify_data, NMDevice *self) { - NMDevice * self = NM_DEVICE(user_data); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - NMIP4Config * manual, **configs; + NMIP4Config * manual; + NMIP4Config ** configs; NMConnection * connection; + NMDhcpState state; + NMIP4Config * ip4_config; + GHashTable * options; + + nm_assert(nm_dhcp_client_get_addr_family(client) == AF_INET); + nm_assert(notify_data); + nm_assert(notify_data->notify_type == NM_DHCP_CLIENT_NOTIFY_TYPE_STATE_CHANGED); - g_return_if_fail(nm_dhcp_client_get_addr_family(client) == AF_INET); - g_return_if_fail(!ip4_config || NM_IS_IP4_CONFIG(ip4_config)); + state = notify_data->state_changed.dhcp_state; + ip4_config = NM_IP4_CONFIG(notify_data->state_changed.ip_config); + options = notify_data->state_changed.options; - _LOGD(LOGD_DHCP4, "new DHCPv4 client state %d", state); + nm_assert(!ip4_config || NM_IS_IP4_CONFIG(ip4_config)); + + _LOGD(LOGD_DHCP4, "new DHCPv4 client state %d", (int) state); switch (state) { case NM_DHCP_STATE_BOUND: @@ -9479,6 +9525,7 @@ dhcp4_state_changed(NMDhcpClient *client, nm_connection_get_setting_ip4_config(connection), NM_SETTING_CONNECTION_MDNS_DEFAULT, NM_SETTING_CONNECTION_LLMNR_DEFAULT, + NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT, nm_device_get_route_table(self, AF_INET), nm_device_get_route_metric(self, AF_INET)); @@ -9594,10 +9641,10 @@ dhcp4_start(NMDevice *self) return NM_ACT_STAGE_RETURN_FAILURE; } - priv->dhcp_data_4.state_sigid = g_signal_connect(priv->dhcp_data_4.client, - NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED, - G_CALLBACK(dhcp4_state_changed), - self); + priv->dhcp_data_4.notify_sigid = g_signal_connect(priv->dhcp_data_4.client, + NM_DHCP_CLIENT_NOTIFY, + G_CALLBACK(dhcp4_notify), + self); if (nm_device_sys_iface_state_is_external_or_assume(self)) priv->dhcp_data_4.was_active = TRUE; @@ -9768,8 +9815,7 @@ dhcp6_cleanup(NMDevice *self, CleanupType cleanup_type, gboolean release) priv->dhcp_data_6.grace_pending = FALSE; if (priv->dhcp_data_6.client) { - nm_clear_g_signal_handler(priv->dhcp_data_6.client, &priv->dhcp_data_6.state_sigid); - nm_clear_g_signal_handler(priv->dhcp_data_6.client, &priv->dhcp6.prefix_sigid); + nm_clear_g_signal_handler(priv->dhcp_data_6.client, &priv->dhcp_data_6.notify_sigid); if (cleanup_type == CLEANUP_TYPE_DECONFIGURE || cleanup_type == CLEANUP_TYPE_REMOVED) nm_dhcp_client_stop(priv->dhcp_data_6.client, release); @@ -9805,7 +9851,7 @@ dhcp6_lease_change(NMDevice *self) return FALSE; } - nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP6_CHANGE, self, NULL, NULL, NULL, NULL); + nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP_CHANGE_6, self, NULL, NULL, NULL, NULL); return TRUE; } @@ -9818,7 +9864,7 @@ dhcp6_fail(NMDevice *self, NMDhcpState dhcp_state) _LOGD(LOGD_DHCP6, "DHCPv6 failed (ip_state %s, was_active %d)", - nm_device_ip_state_to_str(priv->ip_state_6), + nm_device_ip_state_to_string(priv->ip_state_6), priv->dhcp_data_6.was_active); /* The client is always left running after a failure. */ @@ -9869,20 +9915,34 @@ clear_config: } static void -dhcp6_state_changed(NMDhcpClient *client, - NMDhcpState state, - NMIP6Config * ip6_config, - GHashTable * options, - gpointer user_data) +dhcp6_notify(NMDhcpClient *client, const NMDhcpClientNotifyData *notify_data, NMDevice *self) { - NMDevice * self = NM_DEVICE(user_data); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); gs_free char * event_id = NULL; + NMDhcpState state; + NMIP6Config * ip6_config; + GHashTable * options; + + nm_assert(nm_dhcp_client_get_addr_family(client) == AF_INET6); + nm_assert(notify_data); + + if (notify_data->notify_type == NM_DHCP_CLIENT_NOTIFY_TYPE_PREFIX_DELEGATED) { + /* Just re-emit. The device just contributes the prefix to the + * pool in NMPolicy, which decides about subnet allocation + * on the shared devices. */ + g_signal_emit(self, signals[IP6_PREFIX_DELEGATED], 0, notify_data->prefix_delegated.prefix); + return; + } + + nm_assert(notify_data->notify_type == NM_DHCP_CLIENT_NOTIFY_TYPE_STATE_CHANGED); - g_return_if_fail(nm_dhcp_client_get_addr_family(client) == AF_INET6); - g_return_if_fail(!ip6_config || NM_IS_IP6_CONFIG(ip6_config)); + state = notify_data->state_changed.dhcp_state; + ip6_config = NM_IP6_CONFIG(notify_data->state_changed.ip_config); + options = notify_data->state_changed.options; - _LOGD(LOGD_DHCP6, "new DHCPv6 client state %d", state); + nm_assert(!ip6_config || NM_IS_IP6_CONFIG(ip6_config)); + + _LOGD(LOGD_DHCP6, "new DHCPv6 client state %d", (int) state); switch (state) { case NM_DHCP_STATE_BOUND: @@ -9962,17 +10022,6 @@ dhcp6_state_changed(NMDhcpClient *client, } } -static void -dhcp6_prefix_delegated(NMDhcpClient *client, NMPlatformIP6Address *prefix, gpointer user_data) -{ - NMDevice *self = NM_DEVICE(user_data); - - /* Just re-emit. The device just contributes the prefix to the - * pool in NMPolicy, which decides about subnet allocation - * on the shared devices. */ - g_signal_emit(self, signals[IP6_PREFIX_DELEGATED], 0, prefix); -} - /*****************************************************************************/ static gboolean @@ -10054,14 +10103,10 @@ dhcp6_start_with_link_ready(NMDevice *self, NMConnection *connection) return FALSE; } - priv->dhcp_data_6.state_sigid = g_signal_connect(priv->dhcp_data_6.client, - NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED, - G_CALLBACK(dhcp6_state_changed), - self); - priv->dhcp6.prefix_sigid = g_signal_connect(priv->dhcp_data_6.client, - NM_DHCP_CLIENT_SIGNAL_PREFIX_DELEGATED, - G_CALLBACK(dhcp6_prefix_delegated), - self); + priv->dhcp_data_6.notify_sigid = g_signal_connect(priv->dhcp_data_6.client, + NM_DHCP_CLIENT_NOTIFY, + G_CALLBACK(dhcp6_notify), + self); if (nm_device_sys_iface_state_is_external_or_assume(self)) priv->dhcp_data_6.was_active = TRUE; @@ -10321,12 +10366,12 @@ check_and_add_ipv6ll_addr(NMDevice *self) const char * stable_id; stable_id = _prop_get_connection_stable_id(self, connection, &stable_type); - if (!nm_utils_ipv6_addr_set_stable_privacy(stable_type, - &lladdr, - nm_device_get_iface(self), - stable_id, - priv->linklocal6_dad_counter++, - &error)) { + if (!nm_utils_ipv6_addr_set_stable_privacy_may_fail(stable_type, + &lladdr, + nm_device_get_iface(self), + stable_id, + priv->linklocal6_dad_counter++, + &error)) { _LOGW(LOGD_IP6, "linklocal6: failed to generate an address: %s", error->message); g_clear_error(&error); linklocal6_failed(self); @@ -10348,7 +10393,7 @@ check_and_add_ipv6ll_addr(NMDevice *self) _LOGW(LOGD_IP6, "linklocal6: failed to get interface identifier; IPv6 cannot continue"); return; } - nm_utils_ipv6_addr_set_interface_identifier(&lladdr, iid); + nm_utils_ipv6_addr_set_interface_identifier(&lladdr, &iid); addr_type = "EUI-64"; } @@ -10616,9 +10661,9 @@ _commit_mtu(NMDevice *self, const NMIP4Config *config) _LOGT(LOGD_DEVICE, "mtu: value %u from source '%s' (%u), current source '%s' (%u)%s", (guint) mtu, - nm_device_mtu_source_to_str(source), + nm_device_mtu_source_to_string(source), (guint) source, - nm_device_mtu_source_to_str(priv->mtu_source), + nm_device_mtu_source_to_string(priv->mtu_source), (guint) priv->mtu_source, force ? " (forced)" : ""); } @@ -10801,7 +10846,7 @@ nm_device_commit_mtu(NMDevice *self) } else _LOGT(LOGD_DEVICE, "mtu: commit-mtu... skip due to state %s", - nm_device_state_to_str(state)); + nm_device_state_to_string(state)); } static void @@ -10809,66 +10854,68 @@ ndisc_config_changed(NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_int { NMNDiscConfigMap changed = changed_int; NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + int ifindex; guint i; g_return_if_fail(priv->act_request.obj); + ifindex = nm_device_get_ip_ifindex(self); + + if (ifindex <= 0 + || (applied_config_get_current(&priv->ac_ip6_config) + && ifindex + != nm_ip_config_get_ifindex(applied_config_get_current(&priv->ac_ip6_config)))) + applied_config_clear(&priv->ac_ip6_config); + + if (ifindex <= 0) + return; + if (!applied_config_get_current(&priv->ac_ip6_config)) applied_config_init_new(&priv->ac_ip6_config, self, AF_INET6); if (changed & NM_NDISC_CONFIG_ADDRESSES) { - guint8 plen; guint32 ifa_flags; /* Check, whether kernel is recent enough to help user space handling RA. * If it's not supported, we have no ipv6-privacy and must add autoconf * addresses as /128. The reason for the /128 is to prevent the kernel * from adding a prefix route for this address. */ - ifa_flags = 0; - if (nm_platform_kernel_support_get(NM_PLATFORM_KERNEL_SUPPORT_TYPE_EXTENDED_IFA_FLAGS)) { - ifa_flags |= IFA_F_NOPREFIXROUTE; - if (NM_IN_SET(priv->ndisc_use_tempaddr, - NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR, - NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR)) - ifa_flags |= IFA_F_MANAGETEMPADDR; - plen = 64; - } else - plen = 128; + ifa_flags = IFA_F_NOPREFIXROUTE; + if (NM_IN_SET(priv->ndisc_use_tempaddr, + NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR, + NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR)) + ifa_flags |= IFA_F_MANAGETEMPADDR; nm_ip6_config_reset_addresses_ndisc((NMIP6Config *) priv->ac_ip6_config.orig, rdata->addresses, rdata->addresses_n, - plen, + 64, ifa_flags); if (priv->ac_ip6_config.current) { nm_ip6_config_reset_addresses_ndisc((NMIP6Config *) priv->ac_ip6_config.current, rdata->addresses, rdata->addresses_n, - plen, + 64, ifa_flags); } } if (NM_FLAGS_ANY(changed, NM_NDISC_CONFIG_ROUTES | NM_NDISC_CONFIG_GATEWAYS)) { - nm_ip6_config_reset_routes_ndisc( - (NMIP6Config *) priv->ac_ip6_config.orig, - rdata->gateways, - rdata->gateways_n, - rdata->routes, - rdata->routes_n, - nm_device_get_route_table(self, AF_INET6), - nm_device_get_route_metric(self, AF_INET6), - nm_platform_kernel_support_get(NM_PLATFORM_KERNEL_SUPPORT_TYPE_RTA_PREF)); + nm_ip6_config_reset_routes_ndisc((NMIP6Config *) priv->ac_ip6_config.orig, + rdata->gateways, + rdata->gateways_n, + rdata->routes, + rdata->routes_n, + nm_device_get_route_table(self, AF_INET6), + nm_device_get_route_metric(self, AF_INET6)); if (priv->ac_ip6_config.current) { - nm_ip6_config_reset_routes_ndisc( - (NMIP6Config *) priv->ac_ip6_config.current, - rdata->gateways, - rdata->gateways_n, - rdata->routes, - rdata->routes_n, - nm_device_get_route_table(self, AF_INET6), - nm_device_get_route_metric(self, AF_INET6), - nm_platform_kernel_support_get(NM_PLATFORM_KERNEL_SUPPORT_TYPE_RTA_PREF)); + nm_ip6_config_reset_routes_ndisc((NMIP6Config *) priv->ac_ip6_config.current, + rdata->gateways, + rdata->gateways_n, + rdata->routes, + rdata->routes_n, + nm_device_get_route_table(self, AF_INET6), + nm_device_get_route_metric(self, AF_INET6)); } } @@ -11024,6 +11071,11 @@ addrconf6_start(NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr) guint32 ra_timeout; guint32 default_ra_timeout; + if (!g_file_test("/proc/sys/net/ipv6", G_FILE_TEST_IS_DIR)) { + _LOGI(LOGD_IP6, "addrconf6: kernel does not support IPv6"); + return FALSE; + } + connection = nm_device_get_applied_connection(self); g_assert(connection); @@ -11037,17 +11089,17 @@ addrconf6_start(NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr) g_assert(s_ip6); if (nm_streq(nm_device_get_effective_ip_config_method(self, AF_INET6), - NM_SETTING_IP4_CONFIG_METHOD_SHARED)) + NM_SETTING_IP6_CONFIG_METHOD_SHARED)) node_type = NM_NDISC_NODE_TYPE_ROUTER; else node_type = NM_NDISC_NODE_TYPE_HOST; - nm_lndp_ndisc_get_sysctl(nm_device_get_platform(self), - nm_device_get_ip_iface(self), - &max_addresses, - &router_solicitations, - &router_solicitation_interval, - &default_ra_timeout); + nm_ndisc_get_sysctl(nm_device_get_platform(self), + nm_device_get_ip_iface(self), + &max_addresses, + &router_solicitations, + &router_solicitation_interval, + &default_ra_timeout); if (node_type == NM_NDISC_NODE_TYPE_ROUTER) ra_timeout = 0u; @@ -11078,15 +11130,6 @@ addrconf6_start(NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr) priv->ndisc_use_tempaddr = use_tempaddr; - if (NM_IN_SET(use_tempaddr, - NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR, - NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR) - && !nm_platform_kernel_support_get(NM_PLATFORM_KERNEL_SUPPORT_TYPE_EXTENDED_IFA_FLAGS)) { - _LOGW(LOGD_IP6, - "The kernel does not support extended IFA_FLAGS needed by NM for " - "IPv6 private addresses. This feature is not available"); - } - /* ensure link local is ready... */ if (!linklocal6_start(self)) { /* wait for the LL address to show up */ @@ -11181,21 +11224,20 @@ set_nm_ipv6ll(NMDevice *self, gboolean enable) NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); int ifindex = nm_device_get_ip_ifindex(self); - if (!nm_platform_kernel_support_get(NM_PLATFORM_KERNEL_SUPPORT_TYPE_USER_IPV6LL)) - return; - priv->ipv6ll_handle = enable; if (ifindex > 0) { - const char *detail = enable ? "enable" : "disable"; - int r; + int r; - _LOGD(LOGD_IP6, "will %s userland IPv6LL", detail); - r = nm_platform_link_set_user_ipv6ll_enabled(nm_device_get_platform(self), ifindex, enable); + _LOGD(LOGD_IP6, "will %s userland IPv6LL", enable ? "enable" : "disable"); + r = nm_platform_link_set_inet6_addr_gen_mode(nm_device_get_platform(self), + ifindex, + enable ? NM_IN6_ADDR_GEN_MODE_NONE + : NM_IN6_ADDR_GEN_MODE_EUI64); if (r < 0) { _NMLOG(NM_IN_SET(r, -NME_PL_NOT_FOUND, -NME_PL_OPNOTSUPP) ? LOGL_DEBUG : LOGL_WARN, LOGD_IP6, "failed to %s userspace IPv6LL address handling (%s)", - detail, + enable ? "enable" : "disable", nm_strerror(r)); } @@ -11310,6 +11352,7 @@ act_stage3_ip_config_start(NMDevice * self, nm_connection_get_setting_ip4_config(connection), NM_SETTING_CONNECTION_MDNS_DEFAULT, NM_SETTING_CONNECTION_LLMNR_DEFAULT, + NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT, nm_device_get_route_table(self, AF_INET), nm_device_get_route_metric(self, AF_INET)); configs = g_new0(NMIP4Config *, 2); @@ -11521,45 +11564,6 @@ nm_device_activate_stage3_ip_start(NMDevice *self, int addr_family) return TRUE; } -/* - * activate_stage3_ip_config_start - * - * Begin automatic/manual IP configuration - * - */ -static void -activate_stage3_ip_config_start(NMDevice *self) -{ - int ifindex; - - _set_ip_state(self, AF_INET, NM_DEVICE_IP_STATE_WAIT); - _set_ip_state(self, AF_INET6, NM_DEVICE_IP_STATE_WAIT); - - _active_connection_set_state_flags(self, NM_ACTIVATION_STATE_FLAG_LAYER2_READY); - - nm_device_state_changed(self, NM_DEVICE_STATE_IP_CONFIG, NM_DEVICE_STATE_REASON_NONE); - - /* Device should be up before we can do anything with it */ - if ((ifindex = nm_device_get_ip_ifindex(self)) > 0 - && !nm_platform_link_is_up(nm_device_get_platform(self), ifindex)) - _LOGW(LOGD_DEVICE, - "interface %s not up for IP configuration", - nm_device_get_ip_iface(self)); - - if (nm_device_activate_ip4_state_in_wait(self) - && !nm_device_activate_stage3_ip_start(self, AF_INET)) - return; - - if (nm_device_activate_ip6_state_in_wait(self) - && !nm_device_activate_stage3_ip_start(self, AF_INET6)) - return; - - /* Proxy */ - nm_device_set_proxy_config(self, NULL); - - check_ip_state(self, TRUE, TRUE); -} - static void fw_change_zone_cb(NMFirewalldManager * firewalld_manager, NMFirewalldManagerCallId *call_id, @@ -11642,20 +11646,19 @@ fw_change_zone(NMDevice *self) } /* - * nm_device_activate_schedule_stage3_ip_config_start + * activate_stage3_ip_config_start + * + * Begin automatic/manual IP configuration * - * Schedule IP configuration start */ -void -nm_device_activate_schedule_stage3_ip_config_start(NMDevice *self) +static void +activate_stage3_ip_config_start(NMDevice *self) { - NMDevicePrivate *priv; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); int ifindex; - g_return_if_fail(NM_IS_DEVICE(self)); - - priv = NM_DEVICE_GET_PRIVATE(self); g_return_if_fail(priv->act_request.obj); + ifindex = nm_device_get_ip_ifindex(self); /* Add the interface to the specified firewall zone */ @@ -11676,6 +11679,51 @@ nm_device_activate_schedule_stage3_ip_config_start(NMDevice *self) nm_assert(ifindex <= 0 || priv->fw_state == FIREWALL_STATE_INITIALIZED); + _set_ip_state(self, AF_INET, NM_DEVICE_IP_STATE_WAIT); + _set_ip_state(self, AF_INET6, NM_DEVICE_IP_STATE_WAIT); + + _active_connection_set_state_flags(self, NM_ACTIVATION_STATE_FLAG_LAYER2_READY); + + nm_device_state_changed(self, NM_DEVICE_STATE_IP_CONFIG, NM_DEVICE_STATE_REASON_NONE); + + /* Device should be up before we can do anything with it */ + if (!nm_device_sys_iface_state_is_external(self) + && (ifindex = nm_device_get_ip_ifindex(self)) > 0 + && !nm_platform_link_is_up(nm_device_get_platform(self), ifindex)) + _LOGW(LOGD_DEVICE, + "interface %s not up for IP configuration", + nm_device_get_ip_iface(self)); + + if (nm_device_activate_ip4_state_in_wait(self) + && !nm_device_activate_stage3_ip_start(self, AF_INET)) + return; + + if (nm_device_activate_ip6_state_in_wait(self) + && !nm_device_activate_stage3_ip_start(self, AF_INET6)) + return; + + /* Proxy */ + nm_device_set_proxy_config(self, NULL); + + check_ip_state(self, TRUE, TRUE); +} + +/* + * nm_device_activate_schedule_stage3_ip_config_start + * + * Schedule IP configuration start + */ +void +nm_device_activate_schedule_stage3_ip_config_start(NMDevice *self) +{ + NMDevicePrivate *priv; + + g_return_if_fail(NM_IS_DEVICE(self)); + + priv = NM_DEVICE_GET_PRIVATE(self); + + g_return_if_fail(priv->act_request.obj); + activation_source_schedule(self, activate_stage3_ip_config_start, AF_INET); } @@ -11728,22 +11776,23 @@ activate_stage4_ip_config_timeout_6(NMDevice *self) activate_stage4_ip_config_timeout_x(self, AF_INET6); } +#define activate_stage4_ip_config_timeout_x_fcn(addr_family) \ + (NM_IS_IPv4(addr_family) ? activate_stage4_ip_config_timeout_4 \ + : activate_stage4_ip_config_timeout_6) + void nm_device_activate_schedule_ip_config_timeout(NMDevice *self, int addr_family) { NMDevicePrivate *priv; - const int IS_IPv4 = NM_IS_IPv4(addr_family); g_return_if_fail(NM_IS_DEVICE(self)); - g_return_if_fail(NM_IN_SET(addr_family, AF_INET, AF_INET6)); priv = NM_DEVICE_GET_PRIVATE(self); g_return_if_fail(priv->act_request.obj); activation_source_schedule(self, - IS_IPv4 ? activate_stage4_ip_config_timeout_4 - : activate_stage4_ip_config_timeout_6, + activate_stage4_ip_config_timeout_x_fcn(addr_family), addr_family); } @@ -11963,7 +12012,7 @@ activate_stage5_ip_config_result_x(NMDevice *self, int addr_family) g_return_if_fail(ip_ifindex); if (!nm_platform_link_is_up(nm_device_get_platform(self), ip_ifindex) - && !nm_device_sys_iface_state_is_external_or_assume(self)) { + && !nm_device_sys_iface_state_is_external(self)) { nm_platform_link_change_flags(nm_device_get_platform(self), ip_ifindex, IFF_UP, TRUE); if (!nm_platform_link_is_up(nm_device_get_platform(self), ip_ifindex)) _LOGW(LOGD_DEVICE, @@ -11986,7 +12035,7 @@ activate_stage5_ip_config_result_x(NMDevice *self, int addr_family) /* If IPv6 wasn't the first IP to complete, and DHCP was used, * then ensure dispatcher scripts get the DHCP lease information. */ - nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP6_CHANGE, + nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP_CHANGE_6, self, NULL, NULL, @@ -12052,7 +12101,7 @@ activate_stage5_ip_config_result_x(NMDevice *self, int addr_family) */ if (priv->dhcp_data_4.client && nm_device_activate_ip4_state_in_conf(self) && (nm_device_get_state(self) > NM_DEVICE_STATE_IP_CONFIG)) { - nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP4_CHANGE, + nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP_CHANGE_4, self, NULL, NULL, @@ -12425,7 +12474,7 @@ _nm_device_hash_check_invalid_keys(GHashTable * hash, g_hash_table_iter_init(&iter, hash); while (g_hash_table_iter_next(&iter, (gpointer *) &k, NULL)) { - if (nm_utils_strv_find_first((char **) whitelist, -1, k) < 0) { + if (nm_strv_find_first(whitelist, -1, k) < 0) { first_invalid_key = k; break; } @@ -12490,6 +12539,7 @@ nm_device_reactivate_ip_config(NMDevice * self, s_ip_new, _prop_get_connection_mdns(self), _prop_get_connection_llmnr(self), + _prop_get_connection_dns_over_tls(self), nm_device_get_route_table(self, AF_INET), nm_device_get_route_metric(self, AF_INET)); } else { @@ -12623,7 +12673,8 @@ can_reapply_change(NMDevice * self, NM_SETTING_CONNECTION_METERED, NM_SETTING_CONNECTION_LLDP, NM_SETTING_CONNECTION_MDNS, - NM_SETTING_CONNECTION_LLMNR); + NM_SETTING_CONNECTION_LLMNR, + NM_SETTING_CONNECTION_DNS_OVER_TLS); } if (NM_IN_STRSET(setting_name, @@ -12912,12 +12963,12 @@ reapply_cb(NMDevice * self, audit_args, subject, local->message); - g_dbus_method_invocation_take_error(context, local); - local = NULL; - } else { - nm_audit_log_device_op(NM_AUDIT_OP_DEVICE_REAPPLY, self, TRUE, audit_args, subject, NULL); - g_dbus_method_invocation_return_value(context, NULL); + g_dbus_method_invocation_take_error(context, g_steal_pointer(&local)); + return; } + + nm_audit_log_device_op(NM_AUDIT_OP_DEVICE_REAPPLY, self, TRUE, audit_args, subject, NULL); + g_dbus_method_invocation_return_value(context, NULL); } static void @@ -14737,15 +14788,15 @@ _unmanaged_flags2str(NMUnmanagedFlags flags, NMUnmanagedFlags mask, char *buf, g tmp = buf2; while (TRUE) { if (add_separator) - nm_utils_strbuf_append_c(&b, &len, ','); + nm_strbuf_append_c(&b, &len, ','); add_separator = TRUE; tmp2 = strchr(tmp, ','); if (tmp2) tmp2[0] = '\0'; - nm_utils_strbuf_append_c(&b, &len, '!'); - nm_utils_strbuf_append_str(&b, &len, tmp); + nm_strbuf_append_c(&b, &len, '!'); + nm_strbuf_append_str(&b, &len, tmp); if (!tmp2) break; @@ -14950,7 +15001,7 @@ _set_unmanaged_flags(NMDevice * self, priv->queued_ip_config_id_4 = g_idle_add(queued_ip4_config_change, self); priv->queued_ip_config_id_6 = g_idle_add(queued_ip6_config_change, self); - if (!priv->pending_actions) { + if (priv->pending_actions.len == 0) { do_notify_has_pending_actions = TRUE; had_pending_actions = nm_device_has_pending_action(self); } @@ -15004,7 +15055,7 @@ _set_unmanaged_flags(NMDevice * self, flags, NM_PRINT_FMT_QUOTED(allow_state_transition, ", reason ", - nm_device_state_reason_to_str_a(reason), + nm_device_state_reason_to_string_a(reason), transition_state ? ", transition-state" : "", "")); @@ -15744,37 +15795,39 @@ gboolean nm_device_add_pending_action(NMDevice *self, const char *action, gboolean assert_not_yet_pending) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - GSList * iter; - guint count = 0; + gssize idx; g_return_val_if_fail(action, FALSE); - /* Check if the action is already pending. Cannot add duplicate actions */ - for (iter = priv->pending_actions; iter; iter = iter->next) { - if (nm_streq(action, iter->data)) { - if (assert_not_yet_pending) { - _LOGW(LOGD_DEVICE, - "add_pending_action (%d): '%s' already pending", - count + g_slist_length(iter), - action); - g_return_val_if_reached(FALSE); - } else { - _LOGT(LOGD_DEVICE, - "add_pending_action (%d): '%s' already pending (expected)", - count + g_slist_length(iter), - action); - } - return FALSE; + idx = nm_strv_find_binary_search(priv->pending_actions.arr, priv->pending_actions.len, action); + if (idx >= 0) { + if (assert_not_yet_pending) { + _LOGW(LOGD_DEVICE, + "add_pending_action (%u): '%s' already pending", + priv->pending_actions.len, + action); + g_return_val_if_reached(FALSE); + } else { + _LOGT(LOGD_DEVICE, + "add_pending_action (%u): '%s' already pending (expected)", + priv->pending_actions.len, + action); } - count++; + return FALSE; } - priv->pending_actions = g_slist_prepend(priv->pending_actions, (char *) action); - count++; + if (priv->pending_actions.len == priv->pending_actions.alloc) { + nm_assert(priv->pending_actions.alloc < G_MAXUINT / 2u); + priv->pending_actions.alloc = NM_MAX(priv->pending_actions.alloc * 2u, 4u); + priv->pending_actions.arr = + g_renew(const char *, priv->pending_actions.arr, priv->pending_actions.alloc); + } + nm_arr_insert_at(priv->pending_actions.arr, priv->pending_actions.len, ~idx, action); + priv->pending_actions.len++; - _LOGD(LOGD_DEVICE, "add_pending_action (%d): '%s'", count, action); + _LOGD(LOGD_DEVICE, "add_pending_action (%u): '%s'", priv->pending_actions.len, action); - if (count == 1) + if (priv->pending_actions.len == 1) _notify(self, PROP_HAS_PENDING_ACTION); return TRUE; @@ -15796,37 +15849,38 @@ gboolean nm_device_remove_pending_action(NMDevice *self, const char *action, gboolean assert_is_pending) { NMDevicePrivate *priv; - GSList * iter, *next; - guint count = 0; + gssize idx; g_return_val_if_fail(self, FALSE); g_return_val_if_fail(action, FALSE); priv = NM_DEVICE_GET_PRIVATE(self); - for (iter = priv->pending_actions; iter; iter = next) { - next = iter->next; - if (nm_streq(action, iter->data)) { - _LOGD(LOGD_DEVICE, - "remove_pending_action (%d): '%s'", - count + g_slist_length(iter->next), /* length excluding 'iter' */ - action); - priv->pending_actions = g_slist_delete_link(priv->pending_actions, iter); - if (priv->pending_actions == NULL) - _notify(self, PROP_HAS_PENDING_ACTION); - return TRUE; - } - count++; + idx = nm_strv_find_binary_search(priv->pending_actions.arr, priv->pending_actions.len, action); + if (idx >= 0) { + _LOGD(LOGD_DEVICE, + "remove_pending_action (%u): '%s'", + priv->pending_actions.len - 1u, + action); + nm_arr_remove_at(priv->pending_actions.arr, priv->pending_actions.len, idx); + priv->pending_actions.len--; + if (priv->pending_actions.len == 0) + _notify(self, PROP_HAS_PENDING_ACTION); + return TRUE; } if (assert_is_pending) { - _LOGW(LOGD_DEVICE, "remove_pending_action (%d): '%s' not pending", count, action); + _LOGW(LOGD_DEVICE, + "remove_pending_action (%u): '%s' not pending", + priv->pending_actions.len, + action); g_return_val_if_reached(FALSE); - } else + } else { _LOGT(LOGD_DEVICE, - "remove_pending_action (%d): '%s' not pending (expected)", - count, + "remove_pending_action (%u): '%s' not pending (expected)", + priv->pending_actions.len, action); + } return FALSE; } @@ -15836,15 +15890,15 @@ nm_device_has_pending_action_reason(NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - if (priv->pending_actions) { - if (!priv->pending_actions->next && nm_device_get_state(self) == NM_DEVICE_STATE_ACTIVATED - && nm_streq(priv->pending_actions->data, NM_PENDING_ACTION_CARRIER_WAIT)) { + if (priv->pending_actions.len > 0) { + if (priv->pending_actions.len == 1 && nm_device_get_state(self) == NM_DEVICE_STATE_ACTIVATED + && nm_streq(priv->pending_actions.arr[0], NM_PENDING_ACTION_CARRIER_WAIT)) { /* if the device is already in activated state, and the only reason * why it appears still busy is "carrier-wait", then we are already complete. */ return NULL; } - return priv->pending_actions->data; + return priv->pending_actions.arr[0]; } if (nm_device_is_real(self) @@ -16014,7 +16068,7 @@ nm_device_cleanup(NMDevice *self, NMDeviceStateReason reason, CleanupType cleanu else _LOGD(LOGD_DEVICE, "deactivating device (reason '%s') [%d]", - nm_device_state_reason_to_str_a(reason), + nm_device_state_reason_to_string_a(reason), reason); /* Save whether or not we tried IPv6 for later */ @@ -16045,15 +16099,16 @@ nm_device_cleanup(NMDevice *self, NMDeviceStateReason reason, CleanupType cleanu nm_platform_ip_route_flush(platform, AF_UNSPEC, ifindex); nm_platform_ip_address_flush(platform, AF_UNSPEC, ifindex); - set_ipv6_token(self, iid, "::"); + set_ipv6_token(self, &iid, "::"); if (nm_device_get_applied_setting(self, NM_TYPE_SETTING_TC_CONFIG)) { - nm_platform_tfilter_sync(platform, ifindex, NULL); - nm_platform_qdisc_sync(platform, ifindex, NULL); + nm_platform_tc_sync(platform, ifindex, NULL, NULL); } } } + priv->tc_committed = FALSE; + _routing_rules_sync(self, cleanup_type == CLEANUP_TYPE_KEEP ? NM_TERNARY_DEFAULT : NM_TERNARY_FALSE); @@ -16508,20 +16563,20 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, && (state != NM_DEVICE_STATE_UNAVAILABLE || !priv->firmware_missing)) { _LOGD(LOGD_DEVICE, "state change: %s -> %s (reason '%s', sys-iface-state: '%s'%s)", - nm_device_state_to_str(old_state), - nm_device_state_to_str(state), - nm_device_state_reason_to_str_a(reason), - nm_device_sys_iface_state_to_str(priv->sys_iface_state), + nm_device_state_to_string(old_state), + nm_device_state_to_string(state), + nm_device_state_reason_to_string_a(reason), + nm_device_sys_iface_state_to_string(priv->sys_iface_state), priv->firmware_missing ? ", missing firmware" : ""); return; } _LOGI(LOGD_DEVICE, "state change: %s -> %s (reason '%s', sys-iface-state: '%s')", - nm_device_state_to_str(old_state), - nm_device_state_to_str(state), - nm_device_state_reason_to_str_a(reason), - nm_device_sys_iface_state_to_str(priv->sys_iface_state)); + nm_device_state_to_string(old_state), + nm_device_state_to_string(state), + nm_device_state_reason_to_string_a(reason), + nm_device_sys_iface_state_to_string(priv->sys_iface_state)); /* in order to prevent triggering any callback caused * by the device not having any pending action anymore @@ -16866,8 +16921,8 @@ queued_state_set(gpointer user_data) _LOGD(LOGD_DEVICE, "queue-state[%s, reason:%s, id:%u]: %s", - nm_device_state_to_str(priv->queued_state.state), - nm_device_state_reason_to_str_a(priv->queued_state.reason), + nm_device_state_to_string(priv->queued_state.state), + nm_device_state_reason_to_string_a(priv->queued_state.reason), priv->queued_state.id, "change state"); @@ -16879,7 +16934,7 @@ queued_state_set(gpointer user_data) new_reason = priv->queued_state.reason; nm_device_state_changed(self, new_state, new_reason); - nm_device_remove_pending_action(self, nm_device_state_queued_state_to_str(new_state), TRUE); + nm_device_remove_pending_action(self, nm_device_state_queued_state_to_string(new_state), TRUE); return G_SOURCE_REMOVE; } @@ -16896,13 +16951,13 @@ nm_device_queue_state(NMDevice *self, NMDeviceState state, NMDeviceStateReason r if (priv->queued_state.id && priv->queued_state.state == state) { _LOGD(LOGD_DEVICE, "queue-state[%s, reason:%s, id:%u]: %s%s%s%s", - nm_device_state_to_str(priv->queued_state.state), - nm_device_state_reason_to_str_a(priv->queued_state.reason), + nm_device_state_to_string(priv->queued_state.state), + nm_device_state_reason_to_string_a(priv->queued_state.reason), priv->queued_state.id, "ignore queuing same state change", NM_PRINT_FMT_QUOTED(priv->queued_state.reason != reason, " (reason differs: ", - nm_device_state_reason_to_str_a(reason), + nm_device_state_reason_to_string_a(reason), ")", "")); return; @@ -16910,20 +16965,20 @@ nm_device_queue_state(NMDevice *self, NMDeviceState state, NMDeviceStateReason r /* Add pending action for the new state before clearing the queued states, so * that we don't accidentally pop all pending states and reach 'startup complete' */ - nm_device_add_pending_action(self, nm_device_state_queued_state_to_str(state), TRUE); + nm_device_add_pending_action(self, nm_device_state_queued_state_to_string(state), TRUE); /* We should only ever have one delayed state transition at a time */ if (priv->queued_state.id) { _LOGW(LOGD_DEVICE, "queue-state[%s, reason:%s, id:%u]: %s", - nm_device_state_to_str(priv->queued_state.state), - nm_device_state_reason_to_str_a(priv->queued_state.reason), + nm_device_state_to_string(priv->queued_state.state), + nm_device_state_reason_to_string_a(priv->queued_state.reason), priv->queued_state.id, "replace previously queued state change"); nm_clear_g_source(&priv->queued_state.id); nm_device_remove_pending_action( self, - nm_device_state_queued_state_to_str(priv->queued_state.state), + nm_device_state_queued_state_to_string(priv->queued_state.state), TRUE); } @@ -16933,8 +16988,8 @@ nm_device_queue_state(NMDevice *self, NMDeviceState state, NMDeviceStateReason r _LOGD(LOGD_DEVICE, "queue-state[%s, reason:%s, id:%u]: %s", - nm_device_state_to_str(state), - nm_device_state_reason_to_str_a(reason), + nm_device_state_to_string(state), + nm_device_state_reason_to_string_a(reason), priv->queued_state.id, "queue state change"); } @@ -16949,14 +17004,15 @@ queued_state_clear(NMDevice *self) _LOGD(LOGD_DEVICE, "queue-state[%s, reason:%s, id:%u]: %s", - nm_device_state_to_str(priv->queued_state.state), - nm_device_state_reason_to_str_a(priv->queued_state.reason), + nm_device_state_to_string(priv->queued_state.state), + nm_device_state_reason_to_string_a(priv->queued_state.reason), priv->queued_state.id, "clear queued state change"); nm_clear_g_source(&priv->queued_state.id); - nm_device_remove_pending_action(self, - nm_device_state_queued_state_to_str(priv->queued_state.state), - TRUE); + nm_device_remove_pending_action( + self, + nm_device_state_queued_state_to_string(priv->queued_state.state), + TRUE); } NMDeviceState @@ -17069,11 +17125,11 @@ nm_device_update_permanent_hw_address(NMDevice *self, gboolean force_freeze) { NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); guint8 buf[_NM_UTILS_HWADDR_LEN_MAX]; - size_t len = 0; gboolean success_read; int ifindex; const NMPlatformLink * pllink; const NMConfigDeviceStateData *dev_state; + NMPLinkAddress cached_hw_addr_perm; if (priv->hw_addr_perm) { /* the permanent hardware address is only read once and not @@ -17112,11 +17168,13 @@ nm_device_update_permanent_hw_address(NMDevice *self, gboolean force_freeze) return; } - success_read = - nm_platform_link_get_permanent_address(nm_device_get_platform(self), ifindex, buf, &len); - if (success_read && priv->hw_addr_len == len) { + success_read = nm_platform_link_get_permanent_address(nm_device_get_platform(self), + pllink, + &cached_hw_addr_perm); + if (success_read && priv->hw_addr_len == cached_hw_addr_perm.len) { priv->hw_addr_perm_fake = FALSE; - priv->hw_addr_perm = nm_utils_hwaddr_ntoa(buf, len); + priv->hw_addr_perm = + nm_utils_hwaddr_ntoa(cached_hw_addr_perm.data, cached_hw_addr_perm.len); _LOGD(LOGD_DEVICE, "hw-addr: read permanent MAC address '%s'", priv->hw_addr_perm); goto notify_and_out; } @@ -17791,7 +17849,7 @@ hostname_dns_lookup_callback(GObject *source, GAsyncResult *result, gpointer use gboolean valid; resolver->hostname = g_steal_pointer(&output); - valid = nm_hostname_manager_validate_hostname(resolver->hostname); + valid = nm_utils_validate_hostname(resolver->hostname); _LOGD(LOGD_DNS, "hostname-from-dns: lookup done for %s, result %s%s%s%s", @@ -17800,7 +17858,7 @@ hostname_dns_lookup_callback(GObject *source, GAsyncResult *result, gpointer use valid ? "" : " (invalid)"); if (!valid) - g_clear_pointer(&resolver->hostname, g_free); + nm_clear_g_free(&resolver->hostname); } nm_clear_g_cancellable(&resolver->cancellable); @@ -18022,6 +18080,37 @@ _activation_func_to_string(ActivationHandleFunc func) g_return_val_if_reached("unknown"); } +static GVariant * +_device_get_ports_variant(NMDevice *device) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(device); + SlaveInfo * info; + GVariantBuilder builder; + gboolean any = FALSE; + + if (priv->ports_variant) + return priv->ports_variant; + + c_list_for_each_entry (info, &priv->slaves, lst_slave) { + const char *path; + + if (!NM_DEVICE_GET_PRIVATE(info->slave)->is_enslaved) + continue; + path = nm_dbus_object_get_path(NM_DBUS_OBJECT(info->slave)); + if (!path) + continue; + if (!any) { + any = TRUE; + g_variant_builder_init(&builder, G_VARIANT_TYPE("ao")); + } + g_variant_builder_add(&builder, "o", path); + } + priv->ports_variant = any ? g_variant_ref_sink(g_variant_builder_end(&builder)) + : g_variant_ref(nm_g_variant_singleton_ao()); + + return priv->ports_variant; +} + /*****************************************************************************/ static void @@ -18188,29 +18277,9 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) g_value_set_boolean(value, nm_device_is_real(self)); break; case PROP_SLAVES: - { - CList *slave_iter; - char **slave_list; - gsize i, n; - - n = c_list_length(&priv->slaves); - slave_list = g_new(char *, n + 1); - i = 0; - c_list_for_each (slave_iter, &priv->slaves) { - SlaveInfo * info = c_list_entry(slave_iter, SlaveInfo, lst_slave); - const char *path; - - if (!NM_DEVICE_GET_PRIVATE(info->slave)->is_enslaved) - continue; - path = nm_dbus_object_get_path(NM_DBUS_OBJECT(info->slave)); - if (path) - slave_list[i++] = g_strdup(path); - } - nm_assert(i <= n); - slave_list[i] = NULL; - g_value_take_boxed(value, slave_list); + case PROP_PORTS: + g_value_set_variant(value, _device_get_ports_variant(self)); break; - } case PROP_STATISTICS_REFRESH_RATE_MS: g_value_set_uint(value, priv->stats.refresh_rate_ms); break; @@ -18518,7 +18587,7 @@ dispose(GObject *object) nm_clear_g_source(&priv->check_delete_unrealized_id); - nm_clear_g_source(&priv->stats.timeout_id); + nm_clear_g_source_inst(&priv->stats.timeout_source); carrier_disconnected_action_cancel(self); @@ -18573,7 +18642,7 @@ finalize(GObject *object) g_free(priv->hw_addr); g_free(priv->hw_addr_perm); g_free(priv->hw_addr_initial); - g_slist_free(priv->pending_actions); + g_free(priv->pending_actions.arr); g_slist_free_full(priv->dad6_failed_addrs, (GDestroyNotify) nmp_object_unref); nm_clear_g_free(&priv->physical_port_id); g_free(priv->udi); @@ -18592,6 +18661,8 @@ finalize(GObject *object) nm_dbus_track_obj_path_deinit(&priv->parent_device); nm_dbus_track_obj_path_deinit(&priv->act_request); + nm_g_variant_unref(priv->ports_variant); + G_OBJECT_CLASS(nm_device_parent_class)->finalize(object); /* for testing, NMDeviceTest does not invoke NMDevice::constructed, @@ -18710,9 +18781,8 @@ static const NMDBusInterfaceInfoExtended interface_info_device = { NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("InterfaceFlags", "u", NM_DEVICE_INTERFACE_FLAGS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("HwAddress", - "s", - NM_DEVICE_HW_ADDRESS), ), ), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("HwAddress", "s", NM_DEVICE_HW_ADDRESS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Ports", "ao", NM_DEVICE_PORTS), ), ), }; static const NMDBusInterfaceInfoExtended interface_info_device_statistics = { @@ -19007,11 +19077,18 @@ nm_device_class_init(NMDeviceClass *klass) "", FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - obj_properties[PROP_SLAVES] = g_param_spec_boxed(NM_DEVICE_SLAVES, - "", - "", - G_TYPE_STRV, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_SLAVES] = g_param_spec_variant(NM_DEVICE_SLAVES, + "", + "", + G_VARIANT_TYPE("ao"), + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_PORTS] = g_param_spec_variant(NM_DEVICE_PORTS, + "", + "", + G_VARIANT_TYPE("ao"), + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); obj_properties[PROP_STATISTICS_REFRESH_RATE_MS] = g_param_spec_uint(NM_DEVICE_STATISTICS_REFRESH_RATE_MS, @@ -19113,16 +19190,17 @@ nm_device_class_init(NMDeviceClass *klass) G_TYPE_OBJECT, G_TYPE_OBJECT); - signals[IP6_PREFIX_DELEGATED] = g_signal_new(NM_DEVICE_IP6_PREFIX_DELEGATED, - G_OBJECT_CLASS_TYPE(object_class), - G_SIGNAL_RUN_FIRST, - 0, - NULL, - NULL, - NULL, - G_TYPE_NONE, - 1, - G_TYPE_POINTER); + signals[IP6_PREFIX_DELEGATED] = + g_signal_new(NM_DEVICE_IP6_PREFIX_DELEGATED, + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 1, + G_TYPE_POINTER /* const NMPlatformIP6Address *prefix */); signals[IP6_SUBNET_NEEDED] = g_signal_new(NM_DEVICE_IP6_SUBNET_NEEDED, G_OBJECT_CLASS_TYPE(object_class), |