diff options
| author | Michael Biebl <biebl@debian.org> | 2025-08-01 19:15:13 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2025-08-01 19:15:13 +0200 |
| commit | 7e9091a5960f67a84787c03153324915220e4816 (patch) | |
| tree | dc743de962532932ebc3b4ed3a36ddd093d97d68 /src/core | |
| parent | 582eb4472a0f3375042afb9026cbeb50e058a27d (diff) | |
New upstream version 1.54.0 upstream/1.54.0
Diffstat (limited to 'src/core')
37 files changed, 785 insertions, 260 deletions
diff --git a/src/core/NetworkManagerUtils.c b/src/core/NetworkManagerUtils.c index 6c9e2f3d..32df3d6d 100644 --- a/src/core/NetworkManagerUtils.c +++ b/src/core/NetworkManagerUtils.c @@ -1509,7 +1509,6 @@ nm_utils_ip_route_attribute_to_platform(int addr_family, GET_ATTR(NM_IP_ROUTE_ATTRIBUTE_INITCWND, r->initcwnd, UINT32, uint32, 0); GET_ATTR(NM_IP_ROUTE_ATTRIBUTE_INITRWND, r->initrwnd, UINT32, uint32, 0); GET_ATTR(NM_IP_ROUTE_ATTRIBUTE_MTU, r->mtu, UINT32, uint32, 0); - GET_ATTR(NM_IP_ROUTE_ATTRIBUTE_RTO_MIN, r->rto_min, UINT32, uint32, 0); GET_ATTR(NM_IP_ROUTE_ATTRIBUTE_QUICKACK, r->quickack, BOOLEAN, boolean, FALSE); GET_ATTR(NM_IP_ROUTE_ATTRIBUTE_LOCK_WINDOW, r->lock_window, BOOLEAN, boolean, FALSE); GET_ATTR(NM_IP_ROUTE_ATTRIBUTE_LOCK_CWND, r->lock_cwnd, BOOLEAN, boolean, FALSE); @@ -1518,6 +1517,18 @@ nm_utils_ip_route_attribute_to_platform(int addr_family, GET_ATTR(NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU, r->lock_mtu, BOOLEAN, boolean, FALSE); GET_ATTR(NM_IP_ROUTE_ATTRIBUTE_LOCK_ADVMSS, r->lock_mss, BOOLEAN, boolean, FALSE); + { + GVariant *_variant = nm_ip_route_get_attribute(s_route, NM_IP_ROUTE_ATTRIBUTE_RTO_MIN); + + if (_variant && g_variant_is_of_type(_variant, G_VARIANT_TYPE_UINT32)) { + r->rto_min = g_variant_get_uint32(_variant); + r->rto_min_set = TRUE; + } else { + r->rto_min = 0; + r->rto_min_set = FALSE; + } + } + if ((variant = nm_ip_route_get_attribute(s_route, NM_IP_ROUTE_ATTRIBUTE_SRC)) && g_variant_is_of_type(variant, G_VARIANT_TYPE_STRING)) { if (inet_pton(addr_family, g_variant_get_string(variant, NULL), &addr) == 1) { diff --git a/src/core/devices/nm-device-bond.c b/src/core/devices/nm-device-bond.c index 53b32466..673d2361 100644 --- a/src/core/devices/nm-device-bond.c +++ b/src/core/devices/nm-device-bond.c @@ -137,13 +137,13 @@ _set_bond_attr(NMDevice *device, const char *attr, const char *value) return ret; } -#define _set_bond_attr_take(device, attr, value) \ - G_STMT_START \ - { \ - gs_free char *_tmp = (value); \ - \ - _set_bond_attr(device, NM_SETTING_BOND_OPTION_ARP_IP_TARGET, _tmp); \ - } \ +#define _set_bond_attr_take(device, attr, value) \ + G_STMT_START \ + { \ + gs_free char *_tmp = (value); \ + \ + _set_bond_attr(device, attr, _tmp); \ + } \ G_STMT_END #define _set_bond_attr_printf(device, attr, fmt, ...) \ @@ -902,7 +902,7 @@ reapply_connection(NMDevice *device, NMConnection *con_old, NMConnection *con_ne mode = _nm_setting_bond_mode_from_string(value); g_return_if_fail(mode != NM_BOND_MODE_UNKNOWN); - /* Below we set only the bond options that kernel allows to modify + /* Below we set only the bond options that the kernel allows modifying * while keeping the bond interface up */ set_bond_arp_ip_targets(device, s_bond); diff --git a/src/core/devices/nm-device-bridge.c b/src/core/devices/nm-device-bridge.c index 7c34fde0..45cdd83f 100644 --- a/src/core/devices/nm-device-bridge.c +++ b/src/core/devices/nm-device-bridge.c @@ -735,6 +735,11 @@ merge_bridge_vlan_default_pvid(NMPlatformBridgeVlan *vlans, guint *num_vlans, gu gboolean has_pvid = FALSE; guint i; + if (default_pvid == 0) { + /* default_pvid=0 means that the default PVID is disabled. No need to merge it. */ + return vlans; + } + for (i = 0; i < *num_vlans; i++) { if (vlans[i].pvid) { has_pvid = TRUE; diff --git a/src/core/devices/nm-device-hsr.c b/src/core/devices/nm-device-hsr.c index 8156fa77..59454ee3 100644 --- a/src/core/devices/nm-device-hsr.c +++ b/src/core/devices/nm-device-hsr.c @@ -94,8 +94,10 @@ update_properties(NMDevice *device) CHECK_PROPERTY_CHANGED(multicast_spec, PROP_MULTICAST_SPEC); CHECK_PROPERTY_CHANGED(prp, PROP_PRP); - if (!nm_ether_addr_equal(&priv->props.supervision_address, &props->supervision_address)) + if (!nm_ether_addr_equal(&priv->props.supervision_address, &props->supervision_address)) { + priv->props.supervision_address = props->supervision_address; _notify(self, PROP_SUPERVISION_ADDRESS); + } g_object_thaw_notify((GObject *) device); } diff --git a/src/core/devices/nm-device-tun.c b/src/core/devices/nm-device-tun.c index faab86d0..b277c378 100644 --- a/src/core/devices/nm-device-tun.c +++ b/src/core/devices/nm-device-tun.c @@ -242,12 +242,14 @@ create_and_realize(NMDevice *device, g_return_val_if_reached(FALSE); } - owner = _nm_utils_ascii_str_to_int64(nm_setting_tun_get_owner(s_tun), 10, 0, G_MAXINT32, -1); + owner = + _nm_utils_ascii_str_to_int64(nm_setting_tun_get_owner(s_tun), 10, 0, G_MAXUINT32 - 1, -1); if (owner != -1) { props.owner_valid = TRUE; props.owner = owner; } - group = _nm_utils_ascii_str_to_int64(nm_setting_tun_get_group(s_tun), 10, 0, G_MAXINT32, -1); + group = + _nm_utils_ascii_str_to_int64(nm_setting_tun_get_group(s_tun), 10, 0, G_MAXUINT32 - 1, -1); if (group != -1) { props.group_valid = TRUE; props.group = group; @@ -278,7 +280,7 @@ _same_og(const char *str, gboolean og_valid, guint32 og_num) { gint64 v; - v = _nm_utils_ascii_str_to_int64(str, 10, 0, G_MAXINT32, -1); + v = _nm_utils_ascii_str_to_int64(str, 10, 0, G_MAXUINT32 - 1, -1); return (!og_valid && (v == (gint64) -1)) || (og_valid && (((guint32) v) == og_num)); } diff --git a/src/core/devices/nm-device-vrf.c b/src/core/devices/nm-device-vrf.c index 7dfd6504..6d272a95 100644 --- a/src/core/devices/nm-device-vrf.c +++ b/src/core/devices/nm-device-vrf.c @@ -235,7 +235,7 @@ attach_port(NMDevice *device, _LOGI(LOGD_DEVICE, "attached VRF port %s", port_iface); } else - _LOGI(LOGD_BOND, "VRF port %s was attached", port_iface); + _LOGI(LOGD_DEVICE, "VRF port %s was attached", port_iface); return TRUE; } diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index 2f2f25a5..f6057e52 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -779,6 +779,7 @@ typedef struct _NMDevicePrivate { char *prop_ip_iface; /* IP interface D-Bus property */ GList *ping_operations; GSource *ping_timeout; + bool refresh_forwarding_done : 1; } NMDevicePrivate; G_DEFINE_ABSTRACT_TYPE(NMDevice, nm_device, NM_TYPE_DBUS_OBJECT) @@ -880,6 +881,7 @@ static void device_ifindex_changed_cb(NMManager *manager, NMDevice *device_chang static gboolean device_link_changed(gpointer user_data); static gboolean _get_maybe_ipv6_disabled(NMDevice *self); static void deactivate_ready(NMDevice *self, NMDeviceStateReason reason); +static void carrier_disconnected_action_cancel(NMDevice *self); /*****************************************************************************/ @@ -1414,6 +1416,26 @@ _prop_get_connection_mdns(NMDevice *self) NM_SETTING_CONNECTION_MDNS_DEFAULT); } +static gboolean +_prop_get_sriov_preserve_on_down(NMDevice *self, NMSettingSriov *s_sriov) +{ + NMSriovPreserveOnDown preserve; + + g_return_val_if_fail(NM_IS_DEVICE(self), FALSE); + g_return_val_if_fail(NM_IS_SETTING_SRIOV(s_sriov), FALSE); + + preserve = nm_setting_sriov_get_preserve_on_down(s_sriov); + if (NM_IN_SET(preserve, NM_SRIOV_PRESERVE_ON_DOWN_NO, NM_SRIOV_PRESERVE_ON_DOWN_YES)) + return preserve; + + return nm_config_data_get_connection_default_int64(NM_CONFIG_GET_DATA, + NM_CON_DEFAULT("sriov.preserve-on-down"), + self, + NM_SRIOV_PRESERVE_ON_DOWN_NO, + NM_SRIOV_PRESERVE_ON_DOWN_YES, + NM_SRIOV_PRESERVE_ON_DOWN_NO); +} + static NMSettingConnectionLlmnr _prop_get_connection_llmnr(NMDevice *self) { @@ -2109,6 +2131,33 @@ _prop_get_ipvx_dhcp_send_hostname(NMDevice *self, int addr_family) return send_hostname_v2; } +NMSettingIPConfigForwarding +nm_device_get_ipv4_forwarding(NMDevice *self) +{ + NMSettingIPConfig *s_ip; + NMSettingIPConfigForwarding forwarding; + + g_return_val_if_fail(NM_IS_DEVICE(self), NM_SETTING_IP_CONFIG_FORWARDING_AUTO); + + s_ip = nm_device_get_applied_setting(self, NM_TYPE_SETTING_IP4_CONFIG); + if (s_ip) + forwarding = nm_setting_ip_config_get_forwarding(s_ip); + else + forwarding = NM_SETTING_IP_CONFIG_FORWARDING_DEFAULT; + + if (forwarding == NM_SETTING_IP_CONFIG_FORWARDING_DEFAULT) { + forwarding = + nm_config_data_get_connection_default_int64(NM_CONFIG_GET_DATA, + NM_CON_DEFAULT("ipv4.forwarding"), + self, + NM_SETTING_IP_CONFIG_FORWARDING_NO, + NM_SETTING_IP_CONFIG_FORWARDING_AUTO, + NM_SETTING_IP_CONFIG_FORWARDING_AUTO); + } + + return forwarding; +} + static gboolean _prop_get_connection_ip_ping_addresses_require_all(NMDevice *self, NMSettingConnection *s_con) { @@ -2717,7 +2766,7 @@ _ethtool_features_set(NMDevice *self, if (nm_setting_ethtool_init_features(s_ethtool, ethtool_state->requested) == 0) return; - features = nm_platform_ethtool_get_link_features(platform, ethtool_state->ifindex); + features = nm_platform_ethtool_get_features(platform, ethtool_state->ifindex); if (!features) { _LOGW(LOGD_DEVICE, "ethtool: failure setting offload features (cannot read features)"); return; @@ -2836,9 +2885,9 @@ _ethtool_coalesce_set(NMDevice *self, continue; if (!has_old) { - if (!nm_platform_ethtool_get_link_coalesce(platform, - ethtool_state->ifindex, - &coalesce_old)) { + if (!nm_platform_ethtool_get_coalesce(platform, + ethtool_state->ifindex, + &coalesce_old)) { _LOGW(LOGD_DEVICE, "ethtool: failure getting coalesce settings (cannot read)"); return; } @@ -2917,7 +2966,7 @@ _ethtool_ring_set(NMDevice *self, nm_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_UINT32)); if (!has_old) { - if (!nm_platform_ethtool_get_link_ring(platform, ethtool_state->ifindex, &ring_old)) { + if (!nm_platform_ethtool_get_ring(platform, ethtool_state->ifindex, &ring_old)) { _LOGW(LOGD_DEVICE, "ethtool: failure setting ring options (cannot read existing setting)"); return; @@ -3013,9 +3062,9 @@ _ethtool_channels_set(NMDevice *self, nm_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_UINT32)); if (!has_old) { - if (!nm_platform_ethtool_get_link_channels(platform, - ethtool_state->ifindex, - &channels_old)) { + if (!nm_platform_ethtool_get_channels(platform, + ethtool_state->ifindex, + &channels_old)) { _LOGW(LOGD_DEVICE, "ethtool: failure setting channels options (cannot read existing setting)"); return; @@ -3132,7 +3181,7 @@ _ethtool_pause_set(NMDevice *self, nm_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_BOOLEAN)); if (!has_old) { - if (!nm_platform_ethtool_get_link_pause(platform, ethtool_state->ifindex, &pause_old)) { + if (!nm_platform_ethtool_get_pause(platform, ethtool_state->ifindex, &pause_old)) { _LOGW(LOGD_DEVICE, "ethtool: failure setting pause options (cannot read " "existing setting)"); @@ -3218,7 +3267,7 @@ _ethtool_eee_set(NMDevice *self, nm_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_BOOLEAN)); if (!has_old) { - if (!nm_platform_ethtool_get_link_eee(platform, ethtool_state->ifindex, &eee_old)) { + if (!nm_platform_ethtool_get_eee(platform, ethtool_state->ifindex, &eee_old)) { _LOGW(LOGD_DEVICE, "ethtool: failure setting eee options (cannot read " "existing setting)"); @@ -3729,7 +3778,7 @@ nm_device_assume_state_reset(NMDevice *self) /*****************************************************************************/ -static char * +char * nm_device_sysctl_ip_conf_get(NMDevice *self, int addr_family, const char *property) { const char *ifname; @@ -4993,6 +5042,10 @@ _set_ifindex(NMDevice *self, int ifindex, gboolean is_ip_ifindex) ip_ifindex_new = nm_device_get_ip_ifindex(self); + /* the ifindex changed; forget about any carrier change event for + * the previous ifindex */ + carrier_disconnected_action_cancel(self); + if (priv->l3cfg) { if (ip_ifindex_new <= 0 || ip_ifindex_new != nm_l3cfg_get_ifindex(priv->l3cfg)) { const NML3ConfigData *l3cd_old; @@ -6584,11 +6637,15 @@ concheck_update_state(NMDevice *self, _notify(self, IS_IPv4 ? PROP_IP4_CONNECTIVITY : PROP_IP6_CONNECTIVITY); - if (priv->state == NM_DEVICE_STATE_ACTIVATED && !nm_device_managed_type_is_external(self)) + /* State change could've affected the route metrics (removed the penalty + * once FULL connectivity is reached), redo the L3 configuration. */ + if (priv->state > NM_DEVICE_STATE_IP_CONFIG && priv->state < NM_DEVICE_STATE_DEACTIVATING + && !nm_device_managed_type_is_external(self)) { _dev_l3_register_l3cds(self, priv->l3cfg, TRUE, NM_TERNARY_DEFAULT); + } } -static const char * +const char * nm_device_get_effective_ip_config_method(NMDevice *self, int addr_family) { NMDeviceClass *klass; @@ -7725,9 +7782,7 @@ device_link_changed(gpointer user_data) * tagged for carrier ignore) ensure that when the carrier appears we * renew DHCP leases and such. */ - if (priv->state == NM_DEVICE_STATE_ACTIVATED) { - nm_device_update_dynamic_ip_setup(self, "interface got carrier"); - } + nm_device_update_dynamic_ip_setup(self, "interface got carrier"); } if (update_unmanaged_specs) @@ -8974,7 +9029,7 @@ nm_device_port_notify_attach_as_port(NMDevice *self, gboolean success) priv->is_attached = TRUE; - _notify(priv->controller, PROP_CONTROLLER); + _notify(self, PROP_CONTROLLER); nm_clear_pointer(&NM_DEVICE_GET_PRIVATE(priv->controller)->ports_variant, g_variant_unref); @@ -9053,7 +9108,7 @@ nm_device_port_notify_release(NMDevice *self, priv->is_attached = FALSE; - _notify(priv->controller, PROP_CONTROLLER); + _notify(self, PROP_CONTROLLER); nm_clear_pointer(&NM_DEVICE_GET_PRIVATE(priv->controller)->ports_variant, g_variant_unref); nm_gobject_notify_together(priv->controller, PROP_PORTS, PROP_SLAVES); @@ -9521,7 +9576,7 @@ nm_device_generate_connection(NMDevice *self, NM_SETTING_CONNECTION_ID, ifname, NM_SETTING_CONNECTION_AUTOCONNECT, - FALSE, + TRUE, NM_SETTING_CONNECTION_INTERFACE_NAME, ifname, NM_SETTING_CONNECTION_TIMESTAMP, @@ -11335,6 +11390,13 @@ _dev_ipdhcpx_notify(NMDhcpClient *client, const NMDhcpClientNotifyData *notify_d switch (notify_data->notify_type) { case NM_DHCP_CLIENT_NOTIFY_TYPE_PREFIX_DELEGATED: nm_assert(!IS_IPv4); + if (notify_data->prefix_delegated.prefix->plen == 0 + || notify_data->prefix_delegated.prefix->plen > 64) { + _LOGW_ipdhcp(addr_family, + "ignoring invalid prefix-delegation with length %u", + notify_data->prefix_delegated.prefix->plen); + return; + } /* Just re-emit. The device just contributes the prefix to the * pool in NMPolicy, which decides about subnet allocation * on the shared devices. */ @@ -13073,6 +13135,13 @@ activate_stage3_ip_config_for_addr_family(NMDevice *self, int addr_family) goto out_devip; if (IS_IPv4) { + NMSettingIPConfigForwarding ipv4_forwarding = nm_device_get_ipv4_forwarding(self); + + if (NM_IN_SET(ipv4_forwarding, + NM_SETTING_IP_CONFIG_FORWARDING_NO, + NM_SETTING_IP_CONFIG_FORWARDING_YES)) { + nm_device_sysctl_ip_conf_set(self, AF_INET, "forwarding", ipv4_forwarding ? "1" : "0"); + } priv->ipll_data_4.v4.mode = _prop_get_ipv4_link_local(self); if (priv->ipll_data_4.v4.mode == NM_SETTING_IP4_LL_ENABLED) _dev_ipll4_start(self); @@ -13369,7 +13438,8 @@ activate_stage3_ip_config(NMDevice *self) * IPv6LL if this is not an assumed connection, since assumed connections * will already have IPv6 set up. */ - if (!nm_device_managed_type_is_external_or_assume(self)) + if ((priv->state <= NM_DEVICE_STATE_IP_CONFIG || priv->ip_data_6.do_reapply) + && !nm_device_managed_type_is_external_or_assume(self)) _dev_addrgenmode6_set(self, NM_IN6_ADDR_GEN_MODE_NONE); /* Re-enable IPv6 on the interface */ @@ -13505,19 +13575,6 @@ _dev_ipshared4_init(NMDevice *self) } if (nm_platform_sysctl_get_int32(nm_device_get_platform(self), - NMP_SYSCTL_PATHID_ABSOLUTE("/proc/sys/net/ipv4/ip_forward"), - -1) - == 1) { - /* nothing to do. */ - } else if (!nm_platform_sysctl_set(nm_device_get_platform(self), - NMP_SYSCTL_PATHID_ABSOLUTE("/proc/sys/net/ipv4/ip_forward"), - "1")) { - errsv = errno; - _LOGW_ipshared(AF_INET, "error enabling IPv4 forwarding: %s", nm_strerror_native(errsv)); - return FALSE; - } - - if (nm_platform_sysctl_get_int32(nm_device_get_platform(self), NMP_SYSCTL_PATHID_ABSOLUTE("/proc/sys/net/ipv4/ip_dynaddr"), -1) == 1) { @@ -13994,13 +14051,18 @@ can_reapply_change(NMDevice *self, goto out_fail; } - if (NM_IN_STRSET(setting_name, - NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME, - NM_SETTING_OVS_OTHER_CONFIG_SETTING_NAME) - && NM_DEVICE_GET_CLASS(self)->can_reapply_change_ovs_external_ids) { - /* TODO: this means, you cannot reapply changes to the external-ids for - * OVS system interfaces. */ - return TRUE; + if (nm_streq(setting_name, NM_SETTING_BRIDGE_PORT_SETTING_NAME)) { + return nm_device_hash_check_invalid_keys(diffs, + NM_SETTING_BRIDGE_PORT_SETTING_NAME, + error, + NM_SETTING_BRIDGE_PORT_VLANS); + } + + if (nm_streq(setting_name, NM_SETTING_SRIOV_SETTING_NAME)) { + return nm_device_hash_check_invalid_keys(diffs, + NM_SETTING_SRIOV_SETTING_NAME, + error, + NM_SETTING_SRIOV_PRESERVE_ON_DOWN); } out_fail: @@ -16851,6 +16913,8 @@ _cleanup_generic_post(NMDevice *self, NMDeviceStateReason reason, CleanupType cl priv->v4_route_table_all_sync_before = FALSE; priv->v6_route_table_all_sync_before = FALSE; + priv->refresh_forwarding_done = FALSE; + priv->mtu_force_set_done = FALSE; priv->needs_ip6_subnet = FALSE; @@ -16896,6 +16960,7 @@ nm_device_cleanup(NMDevice *self, NMDeviceStateReason reason, CleanupType cleanu NMDevicePrivate *priv; NMDeviceClass *klass = NM_DEVICE_GET_CLASS(self); int ifindex; + gint32 default_forwarding_v4; g_return_if_fail(NM_IS_DEVICE(self)); @@ -16918,6 +16983,17 @@ nm_device_cleanup(NMDevice *self, NMDeviceStateReason reason, CleanupType cleanu nm_device_sysctl_ip_conf_set(self, AF_INET6, "use_tempaddr", "0"); } + /* Restoring the device's forwarding to the sysctl default is necessary because + * `refresh_forwarding()` only updates forwarding on activated devices. */ + default_forwarding_v4 = nm_platform_sysctl_get_int32( + nm_device_get_platform(self), + NMP_SYSCTL_PATHID_ABSOLUTE("/proc/sys/net/ipv4/conf/default/forwarding"), + 0); + nm_device_sysctl_ip_conf_set(self, + AF_INET, + "forwarding", + default_forwarding_v4 == 1 ? "1" : "0"); + /* Call device type-specific deactivation */ if (klass->deactivate) klass->deactivate(self); @@ -17437,7 +17513,8 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, } if (priv->ifindex > 0 - && (s_sriov = nm_device_get_applied_setting(self, NM_TYPE_SETTING_SRIOV))) { + && (s_sriov = nm_device_get_applied_setting(self, NM_TYPE_SETTING_SRIOV)) + && (!_prop_get_sriov_preserve_on_down(self, s_sriov))) { priv->sriov_reset_pending++; sriov_op_queue(self, 0, @@ -17492,7 +17569,8 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, nm_settings_connection_update_timestamp(sett_conn, (guint64) 0); if (priv->ifindex > 0 - && (s_sriov = nm_device_get_applied_setting(self, NM_TYPE_SETTING_SRIOV))) { + && (s_sriov = nm_device_get_applied_setting(self, NM_TYPE_SETTING_SRIOV)) + && (!_prop_get_sriov_preserve_on_down(self, s_sriov))) { priv->sriov_reset_pending++; sriov_op_queue(self, 0, @@ -18613,7 +18691,7 @@ hostname_dns_lookup_callback(GObject *source, GAsyncResult *result, gpointer use gboolean valid; resolver->hostname = g_steal_pointer(&output); - valid = nm_utils_validate_hostname(resolver->hostname); + valid = nm_sd_dns_name_is_valid(resolver->hostname); _LOGD(LOGD_DNS, "hostname-from-dns: ipv%c resolver %s: lookup successful for %s, result %s%s%s%s", @@ -18858,6 +18936,19 @@ nm_device_get_hostname_from_dns_lookup(NMDevice *self, int addr_family, gboolean return nm_assert_unreachable_val(NULL); } +gboolean +nm_device_get_refresh_forwarding_done(NMDevice *self) +{ + return NM_DEVICE_GET_PRIVATE(self)->refresh_forwarding_done; +} + +void +nm_device_set_refresh_forwarding_done(NMDevice *self, gboolean is_refresh_forwarding_done) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + priv->refresh_forwarding_done = is_refresh_forwarding_done; +} + /*****************************************************************************/ static const char * diff --git a/src/core/devices/nm-device.h b/src/core/devices/nm-device.h index 9b051ab4..9a663c2a 100644 --- a/src/core/devices/nm-device.h +++ b/src/core/devices/nm-device.h @@ -209,8 +209,6 @@ typedef struct _NMDeviceClass { bool act_stage1_prepare_set_hwaddr_ethernet : 1; - bool can_reapply_change_ovs_external_ids : 1; - bool allow_autoconnect_on_external : 1; NMRfkillType rfkill_type : 4; @@ -854,4 +852,14 @@ void nm_routing_rules_sync(NMConnection *applied_connection, NMDevice *self, NMNetns *netns); +NMSettingIPConfigForwarding nm_device_get_ipv4_forwarding(NMDevice *self); + +const char *nm_device_get_effective_ip_config_method(NMDevice *self, int addr_family); + +char *nm_device_sysctl_ip_conf_get(NMDevice *self, int addr_family, const char *property); + +gboolean nm_device_get_refresh_forwarding_done(NMDevice *self); + +void nm_device_set_refresh_forwarding_done(NMDevice *self, gboolean is_refresh_forwarding_done); + #endif /* __NETWORKMANAGER_DEVICE_H__ */ diff --git a/src/core/devices/nm-lldp-listener.c b/src/core/devices/nm-lldp-listener.c index e08b379a..5c90911f 100644 --- a/src/core/devices/nm-lldp-listener.c +++ b/src/core/devices/nm-lldp-listener.c @@ -310,7 +310,7 @@ format_string(const guint8 *data, gsize len, gboolean allow_trim, char **out_to_ if (len == 0) return NULL; - if (memchr(data, len, '\0')) + if (memchr(data, '\0', len)) return NULL; return nm_utils_buf_utf8safe_escape(data, diff --git a/src/core/devices/ovs/nm-device-ovs-bridge.c b/src/core/devices/ovs/nm-device-ovs-bridge.c index c9b1f4c6..c9736eeb 100644 --- a/src/core/devices/ovs/nm-device-ovs-bridge.c +++ b/src/core/devices/ovs/nm-device-ovs-bridge.c @@ -162,6 +162,11 @@ can_reapply_change(NMDevice *device, NM_SETTING_OVS_BRIDGE_STP_ENABLE); } + if (NM_IN_STRSET(setting_name, + NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME, + NM_SETTING_OVS_OTHER_CONFIG_SETTING_NAME)) + return TRUE; + return device_class->can_reapply_change(device, setting_name, s_old, s_new, diffs, error); } @@ -194,16 +199,15 @@ nm_device_ovs_bridge_class_init(NMDeviceOvsBridgeClass *klass) device_class->connection_type_check_compatible = NM_SETTING_OVS_BRIDGE_SETTING_NAME; device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES(); - device_class->is_controller = TRUE; - device_class->get_type_description = get_type_description; - device_class->create_and_realize = create_and_realize; - device_class->unrealize = unrealize; - device_class->get_generic_capabilities = get_generic_capabilities; - device_class->act_stage3_ip_config = act_stage3_ip_config; - device_class->ready_for_ip_config = ready_for_ip_config; - device_class->attach_port = attach_port; - device_class->detach_port = detach_port; - device_class->can_reapply_change = can_reapply_change; - device_class->can_reapply_change_ovs_external_ids = TRUE; - device_class->reapply_connection = nm_device_ovs_reapply_connection; + device_class->is_controller = TRUE; + device_class->get_type_description = get_type_description; + device_class->create_and_realize = create_and_realize; + device_class->unrealize = unrealize; + device_class->get_generic_capabilities = get_generic_capabilities; + device_class->act_stage3_ip_config = act_stage3_ip_config; + device_class->ready_for_ip_config = ready_for_ip_config; + device_class->attach_port = attach_port; + device_class->detach_port = detach_port; + device_class->can_reapply_change = can_reapply_change; + device_class->reapply_connection = nm_device_ovs_reapply_connection; } diff --git a/src/core/devices/ovs/nm-device-ovs-interface.c b/src/core/devices/ovs/nm-device-ovs-interface.c index 512aa5c3..922ed345 100644 --- a/src/core/devices/ovs/nm-device-ovs-interface.c +++ b/src/core/devices/ovs/nm-device-ovs-interface.c @@ -16,6 +16,8 @@ #include "nm-setting-ovs-bridge.h" #include "nm-setting-ovs-interface.h" #include "nm-setting-ovs-port.h" +#include "nm-setting-ovs-external-ids.h" +#include "nm-setting-ovs-other-config.h" #define _NMLOG_DEVICE_TYPE NMDeviceOvsInterface #include "devices/nm-device-logging.h" @@ -631,6 +633,28 @@ can_update_from_platform_link(NMDevice *device, const NMPlatformLink *plink) return !plink || nm_device_get_state(device) != NM_DEVICE_STATE_DEACTIVATING; } +static gboolean +can_reapply_change(NMDevice *device, + const char *setting_name, + NMSetting *s_old, + NMSetting *s_new, + GHashTable *diffs, + GError **error) +{ + NMDeviceClass *device_class = NM_DEVICE_CLASS(nm_device_ovs_interface_parent_class); + + if (NM_IN_STRSET(setting_name, + NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME, + NM_SETTING_OVS_OTHER_CONFIG_SETTING_NAME)) { + /* TODO: it's currently not possible to reapply those settings on OVS + * system interfaces because they have type != "ovs-interface" (e.g. + * "ethernet") */ + return TRUE; + } + + return device_class->can_reapply_change(device, setting_name, s_old, s_new, diffs, error); +} + /*****************************************************************************/ static void @@ -696,21 +720,21 @@ nm_device_ovs_interface_class_init(NMDeviceOvsInterfaceClass *klass) device_class->connection_type_check_compatible = NM_SETTING_OVS_INTERFACE_SETTING_NAME; device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES(NM_LINK_TYPE_OPENVSWITCH); - device_class->can_auto_connect = can_auto_connect; - device_class->can_update_from_platform_link = can_update_from_platform_link; - device_class->deactivate = deactivate; - device_class->deactivate_async = deactivate_async; - device_class->get_type_description = get_type_description; - device_class->create_and_realize = create_and_realize; - device_class->get_generic_capabilities = get_generic_capabilities; - device_class->is_available = is_available; - device_class->check_connection_compatible = check_connection_compatible; - device_class->link_changed = link_changed; - device_class->act_stage3_ip_config = act_stage3_ip_config; - device_class->ready_for_ip_config = ready_for_ip_config; - device_class->can_unmanaged_external_down = can_unmanaged_external_down; - device_class->set_platform_mtu = set_platform_mtu; - device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired; - device_class->can_reapply_change_ovs_external_ids = TRUE; - device_class->reapply_connection = nm_device_ovs_reapply_connection; + device_class->can_auto_connect = can_auto_connect; + device_class->can_update_from_platform_link = can_update_from_platform_link; + device_class->deactivate = deactivate; + device_class->deactivate_async = deactivate_async; + device_class->get_type_description = get_type_description; + device_class->create_and_realize = create_and_realize; + device_class->get_generic_capabilities = get_generic_capabilities; + device_class->is_available = is_available; + device_class->check_connection_compatible = check_connection_compatible; + device_class->link_changed = link_changed; + device_class->act_stage3_ip_config = act_stage3_ip_config; + device_class->ready_for_ip_config = ready_for_ip_config; + device_class->can_unmanaged_external_down = can_unmanaged_external_down; + device_class->set_platform_mtu = set_platform_mtu; + device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired; + device_class->can_reapply_change = can_reapply_change; + device_class->reapply_connection = nm_device_ovs_reapply_connection; } diff --git a/src/core/devices/ovs/nm-device-ovs-port.c b/src/core/devices/ovs/nm-device-ovs-port.c index e9928548..0e3ef92c 100644 --- a/src/core/devices/ovs/nm-device-ovs-port.c +++ b/src/core/devices/ovs/nm-device-ovs-port.c @@ -16,6 +16,8 @@ #include "nm-setting-connection.h" #include "nm-setting-ovs-port.h" #include "nm-setting-ovs-interface.h" +#include "nm-setting-ovs-external-ids.h" +#include "nm-setting-ovs-other-config.h" #include "nm-setting-wired.h" #define _NMLOG_DEVICE_TYPE NMDeviceOvsPort @@ -279,6 +281,11 @@ can_reapply_change(NMDevice *device, NM_SETTING_OVS_PORT_TRUNKS); } + if (NM_IN_STRSET(setting_name, + NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME, + NM_SETTING_OVS_OTHER_CONFIG_SETTING_NAME)) + return TRUE; + return device_class->can_reapply_change(device, setting_name, s_old, s_new, diffs, error); } @@ -311,15 +318,14 @@ nm_device_ovs_port_class_init(NMDeviceOvsPortClass *klass) device_class->connection_type_check_compatible = NM_SETTING_OVS_PORT_SETTING_NAME; device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES(); - device_class->is_controller = TRUE; - device_class->get_type_description = get_type_description; - device_class->create_and_realize = create_and_realize; - device_class->get_generic_capabilities = get_generic_capabilities; - device_class->act_stage3_ip_config = act_stage3_ip_config; - device_class->ready_for_ip_config = ready_for_ip_config; - device_class->attach_port = attach_port; - device_class->detach_port = detach_port; - device_class->can_reapply_change = can_reapply_change; - device_class->can_reapply_change_ovs_external_ids = TRUE; - device_class->reapply_connection = nm_device_ovs_reapply_connection; + device_class->is_controller = TRUE; + device_class->get_type_description = get_type_description; + device_class->create_and_realize = create_and_realize; + device_class->get_generic_capabilities = get_generic_capabilities; + device_class->act_stage3_ip_config = act_stage3_ip_config; + device_class->ready_for_ip_config = ready_for_ip_config; + device_class->attach_port = attach_port; + device_class->detach_port = detach_port; + device_class->can_reapply_change = can_reapply_change; + device_class->reapply_connection = nm_device_ovs_reapply_connection; } diff --git a/src/core/devices/ovs/nm-ovs-factory.c b/src/core/devices/ovs/nm-ovs-factory.c index 2ca1a0b5..4084356f 100644 --- a/src/core/devices/ovs/nm-ovs-factory.c +++ b/src/core/devices/ovs/nm-ovs-factory.c @@ -75,9 +75,6 @@ new_device_from_type(const char *name, NMDeviceType device_type) const char *type_desc; NMLinkType link_type = NM_LINK_TYPE_NONE; - if (nm_manager_get_device(NM_MANAGER_GET, name, device_type)) - return NULL; - if (device_type == NM_DEVICE_TYPE_OVS_INTERFACE) { type = NM_TYPE_DEVICE_OVS_INTERFACE; type_desc = "Open vSwitch Interface"; @@ -89,6 +86,7 @@ new_device_from_type(const char *name, NMDeviceType device_type) type = NM_TYPE_DEVICE_OVS_BRIDGE; type_desc = "Open vSwitch Bridge"; } else { + _LOGT(name, NULL, "Unrecognized link type: %d", device_type); return NULL; } @@ -125,6 +123,11 @@ ovsdb_device_added(NMOvsdb *ovsdb, return; } + if (nm_manager_get_device(NM_MANAGER_GET, name, device_type)) { + _LOGT(name, NULL, "Device already registered with manager, skipping."); + return; + } + device = new_device_from_type(name, device_type); if (!device) return; @@ -288,23 +291,31 @@ create_device(NMDeviceFactory *self, { NMDeviceType device_type = NM_DEVICE_TYPE_UNKNOWN; const char *connection_type = NULL; + const char *connection_uuid = NULL; if (g_strcmp0(iface, "ovs-system") == 0) { *out_ignore = TRUE; return NULL; } - if (connection) + if (connection) { connection_type = nm_connection_get_connection_type(connection); + connection_uuid = nm_connection_get_uuid(connection); + } - if (plink) + if (plink) { + _LOGD(iface, connection_uuid, "creating OVS interface (from a platform link)"); device_type = NM_DEVICE_TYPE_OVS_INTERFACE; - else if (g_strcmp0(connection_type, NM_SETTING_OVS_INTERFACE_SETTING_NAME) == 0) + } else if (nm_streq0(connection_type, NM_SETTING_OVS_INTERFACE_SETTING_NAME)) { + _LOGD(iface, connection_uuid, "creating OVS interface (from setting)"); device_type = NM_DEVICE_TYPE_OVS_INTERFACE; - else if (g_strcmp0(connection_type, NM_SETTING_OVS_PORT_SETTING_NAME) == 0) + } else if (nm_streq0(connection_type, NM_SETTING_OVS_PORT_SETTING_NAME)) { + _LOGD(iface, connection_uuid, "creating OVS port (from setting)"); device_type = NM_DEVICE_TYPE_OVS_PORT; - else if (g_strcmp0(connection_type, NM_SETTING_OVS_BRIDGE_SETTING_NAME) == 0) + } else if (nm_streq0(connection_type, NM_SETTING_OVS_BRIDGE_SETTING_NAME)) { + _LOGD(iface, connection_uuid, "creating OVS bridge (from setting)"); device_type = NM_DEVICE_TYPE_OVS_BRIDGE; + } return new_device_from_type(iface, device_type); } diff --git a/src/core/devices/ovs/nm-ovsdb.c b/src/core/devices/ovs/nm-ovsdb.c index 2dbc842a..164bfd35 100644 --- a/src/core/devices/ovs/nm-ovsdb.c +++ b/src/core/devices/ovs/nm-ovsdb.c @@ -900,15 +900,17 @@ _insert_interface(json_t *params, s_ovs_patch = nm_connection_get_setting_ovs_patch(interface); if (s_ovs_dpdk) { - const char *devargs; - guint32 n_rxq; - guint32 n_rxq_desc; - guint32 n_txq_desc; + const char *devargs; + guint32 n_rxq; + guint32 n_rxq_desc; + guint32 n_txq_desc; + NMSettingOvsDpdkLscInterrupt lsc_int; devargs = nm_setting_ovs_dpdk_get_devargs(s_ovs_dpdk); n_rxq = nm_setting_ovs_dpdk_get_n_rxq(s_ovs_dpdk); n_rxq_desc = nm_setting_ovs_dpdk_get_n_rxq_desc(s_ovs_dpdk); n_txq_desc = nm_setting_ovs_dpdk_get_n_txq_desc(s_ovs_dpdk); + lsc_int = nm_setting_ovs_dpdk_get_lsc_interrupt(s_ovs_dpdk); dpdk_array = json_array(); @@ -930,6 +932,17 @@ _insert_interface(json_t *params, json_pack("[s,s]", "n_txq_desc", nm_sprintf_buf(sbuf, "%u", n_txq_desc))); } + switch (lsc_int) { + case NM_SETTING_OVS_DPDK_LSC_INTERRUPT_IGNORE: + break; + case NM_SETTING_OVS_DPDK_LSC_INTERRUPT_ENABLED: + json_array_append_new(dpdk_array, json_pack("[s,s]", "dpdk-lsc-interrupt", "true")); + break; + case NM_SETTING_OVS_DPDK_LSC_INTERRUPT_DISABLED: + json_array_append_new(dpdk_array, json_pack("[s,s]", "dpdk-lsc-interrupt", "false")); + break; + } + json_array_append_new(options, dpdk_array); } else if (s_ovs_patch) { @@ -1374,88 +1387,113 @@ _delete_interface(NMOvsdb *self, json_t *params, const char *ifname) nm_auto_decref_json json_t *bridges = NULL; nm_auto_decref_json json_t *new_bridges = NULL; gboolean bridges_changed; - gboolean ports_changed; - gboolean interfaces_changed; - int pi; - int ii; bridges = json_array(); new_bridges = json_array(); bridges_changed = FALSE; + /* Loop over all bridges */ g_hash_table_iter_init(&iter, priv->bridges); while (g_hash_table_iter_next(&iter, (gpointer) &ovs_bridge, NULL)) { - nm_auto_decref_json json_t *ports = NULL; - nm_auto_decref_json json_t *new_ports = NULL; + nm_auto_decref_json json_t *ports = NULL; + nm_auto_decref_json json_t *new_ports = NULL; + guint num_nm_ports = 0; + gboolean ports_changed = FALSE; + int pi; - ports = json_array(); - new_ports = json_array(); - ports_changed = FALSE; + ports = json_array(); + new_ports = json_array(); + /* Add the bridge UUID to the list of known bridges for the "expect" condition */ json_array_append_new(bridges, json_pack("[s,s]", "uuid", ovs_bridge->bridge_uuid)); + if (!ovs_bridge->connection_uuid) { + /* Externally created, don't touch it */ + json_array_append_new(new_bridges, json_pack("[s,s]", "uuid", ovs_bridge->bridge_uuid)); + continue; + } + + /* Loop over all bridge's ports */ for (pi = 0; pi < ovs_bridge->ports->len; pi++) { - nm_auto_decref_json json_t *interfaces = NULL; - nm_auto_decref_json json_t *new_interfaces = NULL; + nm_auto_decref_json json_t *interfaces = NULL; + nm_auto_decref_json json_t *new_interfaces = NULL; + guint num_nm_interfaces = 0; + gboolean interfaces_changed = FALSE; + int ii; interfaces = json_array(); new_interfaces = json_array(); port_uuid = g_ptr_array_index(ovs_bridge->ports, pi); ovs_port = g_hash_table_lookup(priv->ports, &port_uuid); + /* Add the port UUID to the list of known bridge port for the "expect" condition */ json_array_append_new(ports, json_pack("[s,s]", "uuid", port_uuid)); - interfaces_changed = FALSE; - if (!ovs_port) { /* This would be a violation of ovsdb's reference integrity (a bug). */ _LOGW("Unknown port '%s' in bridge '%s'", port_uuid, ovs_bridge->bridge_uuid); continue; } + /* Loop over all port's interfaces */ for (ii = 0; ii < ovs_port->interfaces->len; ii++) { interface_uuid = g_ptr_array_index(ovs_port->interfaces, ii); ovs_interface = g_hash_table_lookup(priv->interfaces, &interface_uuid); + /* Add the interface UUID to the list of known port interfaces for the "expect" condition */ json_array_append_new(interfaces, json_pack("[s,s]", "uuid", interface_uuid)); if (ovs_interface) { if (nm_streq(ovs_interface->name, ifname)) { - /* skip the interface */ + /* We are deleting this interface, don't count it */ interfaces_changed = TRUE; continue; } + if (ovs_interface->connection_uuid) + num_nm_interfaces++; } else { /* This would be a violation of ovsdb's reference integrity (a bug). */ _LOGW("Unknown interface '%s' in port '%s'", interface_uuid, port_uuid); } + /* Add the interface to the list of new interfaces to set on the port */ json_array_append_new(new_interfaces, json_pack("[s,s]", "uuid", interface_uuid)); } - if (json_array_size(new_interfaces) == 0) { + if (num_nm_interfaces == 0) { + /* The port no longer has any NM interface. Don't add it to "new_ports" and set + * ports_changed=TRUE, so that it will be deleted. */ ports_changed = TRUE; } else { if (interfaces_changed) { + /* An interface needs to be deleted from this port */ _expect_port_interfaces(params, ovs_port->name, interfaces); _set_port_interfaces(params, ovs_port->name, new_interfaces); } + /* The port is still alive */ json_array_append_new(new_ports, json_pack("[s,s]", "uuid", port_uuid)); + if (ovs_port->connection_uuid) + num_nm_ports++; } } - if (json_array_size(new_ports) == 0) { + if (num_nm_ports == 0) { + /* The bridge no longer has any NM port. Don't add it to "new_bridges" and set + * bridges_changed=TRUE, so that it will be deleted. */ bridges_changed = TRUE; } else { if (ports_changed) { + /* A port needs to be deleted from this bridge */ _expect_bridge_ports(params, ovs_bridge->name, ports); _set_bridge_ports(params, ovs_bridge->name, new_ports); } + /* The bridge is still alive */ json_array_append_new(new_bridges, json_pack("[s,s]", "uuid", ovs_bridge->bridge_uuid)); } } if (bridges_changed) { + /* A port needs to be deleted from this bridge */ _expect_ovs_bridges(params, priv->db_uuid, bridges); _set_ovs_bridges(params, priv->db_uuid, new_bridges); } @@ -2211,7 +2249,7 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg) ovs_bridge->connection_uuid, ""), (strtmp1 = _strdict_to_string(ovs_bridge->external_ids)), - (strtmp2 = _strdict_to_string(ovs_bridge->external_ids))); + (strtmp2 = _strdict_to_string(ovs_bridge->other_config))); } } else { gs_free char *strtmp1 = NULL; diff --git a/src/core/dhcp/nm-dhcp-options.c b/src/core/dhcp/nm-dhcp-options.c index ce03c607..30cfd8e6 100644 --- a/src/core/dhcp/nm-dhcp-options.c +++ b/src/core/dhcp/nm-dhcp-options.c @@ -68,7 +68,7 @@ const NMDhcpOption _nm_dhcp_option_dhcp4_options[] = { REQ(NM_DHCP_OPTION_DHCP4_ARP_CACHE_TIMEOUT, "arp_cache_timeout", FALSE), REQ(NM_DHCP_OPTION_DHCP4_IEEE802_3_ENCAPSULATION, "ieee802_3_encapsulation", FALSE), REQ(NM_DHCP_OPTION_DHCP4_DEFAULT_TCP_TTL, "default_tcp_ttl", FALSE), - REQ(NM_DHCP_OPTION_DHCP4_TCP_KEEPALIVE_INTERVAL, "tcp_keepalive_internal", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_TCP_KEEPALIVE_INTERVAL, "tcp_keepalive_interval", FALSE), REQ(NM_DHCP_OPTION_DHCP4_TCP_KEEPALIVE_GARBAGE, "tcp_keepalive_garbage", FALSE), REQ(NM_DHCP_OPTION_DHCP4_VENDOR_SPECIFIC, "vendor_encapsulated_options", FALSE), REQ(NM_DHCP_OPTION_DHCP4_NETBIOS_NAMESERVER, "netbios_name_servers", FALSE), diff --git a/src/core/dhcp/nm-dhcp-systemd.c b/src/core/dhcp/nm-dhcp-systemd.c index e1761523..b570f7e5 100644 --- a/src/core/dhcp/nm-dhcp-systemd.c +++ b/src/core/dhcp/nm-dhcp-systemd.c @@ -395,7 +395,7 @@ ip6_start(NMDhcpClient *client, const struct in6_addr *ll_addr, GError **error) prefix_delegation = FALSE; if (client_config->v6.needed_prefixes > 0) { if (client_config->v6.needed_prefixes > 1) { - /* FIXME: systemd-networkd API only allows to request a + /* FIXME: systemd-networkd API only allows requesting a * single prefix */ _LOGW("dhcp-client6: only one prefix request is supported"); } diff --git a/src/core/dhcp/nm-dhcp-utils.c b/src/core/dhcp/nm-dhcp-utils.c index 15293fa3..949d8720 100644 --- a/src/core/dhcp/nm-dhcp-utils.c +++ b/src/core/dhcp/nm-dhcp-utils.c @@ -1224,7 +1224,7 @@ lease_option_print_domain_name(const uint8_t *cache, } case 0xC0: /* back pointer */ { - size_t offset = (c & 0x3F) << 16; + size_t offset = (c & 0x3F) << 8; /* * The offset is given as two bytes (in big endian), where the diff --git a/src/core/dhcp/tests/test-dhcp-utils.c b/src/core/dhcp/tests/test-dhcp-utils.c index b81523e1..de1be653 100644 --- a/src/core/dhcp/tests/test-dhcp-utils.c +++ b/src/core/dhcp/tests/test-dhcp-utils.c @@ -239,6 +239,76 @@ test_parse_search_list(void) g_assert_cmpint(g_strv_length(domains), ==, 1); g_assert_cmpstr(domains[0], ==, "okay"); g_strfreev(domains); + + /* Test that the message compression works when the offset uses both bytes */ + data = (guint8[]) { + /* clang-format off */ + /* offset 0 */ + 0x3e, + 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a', + 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a', + 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a', + 'a','a','a','a','a','a','a','a','a','a','a','a','a','a', + 0x00, + /* offset 0x40 */ + 0x3e, + 'b','b','b','b','b','b','b','b','b','b','b','b','b','b','b','b', + 'b','b','b','b','b','b','b','b','b','b','b','b','b','b','b','b', + 'b','b','b','b','b','b','b','b','b','b','b','b','b','b','b','b', + 'b','b','b','b','b','b','b','b','b','b','b','b','b','b', + 0x00, + /* offset 0x80 */ + 0x3e, + 'c','c','c','c','c','c','c','c','c','c','c','c','c','c','c','c', + 'c','c','c','c','c','c','c','c','c','c','c','c','c','c','c','c', + 'c','c','c','c','c','c','c','c','c','c','c','c','c','c','c','c', + 'c','c','c','c','c','c','c','c','c','c','c','c','c','c', + 0x00, + /* offset 0xc0 */ + 0x3e, + 'd','d','d','d','d','d','d','d','d','d','d','d','d','d','d','d', + 'd','d','d','d','d','d','d','d','d','d','d','d','d','d','d','d', + 'd','d','d','d','d','d','d','d','d','d','d','d','d','d','d','d', + 'd','d','d','d','d','d','d','d','d','d','d','d','d','d', + 0x00, + /* offset 0x100 */ + 0x3e, + 'e','e','e','e','e','e','e','e','e','e','e','e','e','e','e','e', + 'e','e','e','e','e','e','e','e','e','e','e','e','e','e','e','e', + 'e','e','e','e','e','e','e','e','e','e','e','e','e','e','e','e', + 'e','e','e','e','e','e','e','e','e','e','e','e','e','e', + 0x00, + /* offset 0x140 */ + 0x06, 'f','o','o','b','a','r', 0x03, 'c', 'o', 'm', 0x00, + 0x04, 't', 'e', 's', 't', 0xc1, 0x40, /* back pointer to offset 0x140*/ + /* clang-format on */ + }; + + domains = nm_dhcp_lease_data_parse_search_list(data, + 0x153, + "eth0", + AF_INET, + NM_DHCP_OPTION_DHCP4_DOMAIN_SEARCH_LIST); + g_assert(domains); + g_assert_cmpint(g_strv_length(domains), ==, 7); + g_assert_cmpstr(domains[0], + ==, + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); + g_assert_cmpstr(domains[1], + ==, + "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"); + g_assert_cmpstr(domains[2], + ==, + "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"); + g_assert_cmpstr(domains[3], + ==, + "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"); + g_assert_cmpstr(domains[4], + ==, + "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"); + g_assert_cmpstr(domains[5], ==, "foobar.com"); + g_assert_cmpstr(domains[6], ==, "test.foobar.com"); + g_strfreev(domains); } static void diff --git a/src/core/dns/nm-dns-dnsconfd.c b/src/core/dns/nm-dns-dnsconfd.c index c17fb9cf..3789caf8 100644 --- a/src/core/dns/nm-dns-dnsconfd.c +++ b/src/core/dns/nm-dns-dnsconfd.c @@ -368,7 +368,8 @@ server_builder_append_base(GVariantBuilder *argument_builder, const char *address_string, const char *const *routing_domains, const char *const *search_domains, - const char *ca) + const char *ca, + int priority) { NMDnsServer dns_server; gsize addr_size; @@ -392,6 +393,12 @@ server_builder_append_base(GVariantBuilder *argument_builder, "{sv}", "name", g_variant_new("s", dns_server.servername)); + if (dns_server.port != NM_DNS_PORT_UNDEFINED) { + g_variant_builder_add(argument_builder, + "{sv}", + "port", + g_variant_new("i", dns_server.port)); + } if (routing_domains) { g_variant_builder_add(argument_builder, "{sv}", @@ -407,6 +414,9 @@ server_builder_append_base(GVariantBuilder *argument_builder, if (ca) { g_variant_builder_add(argument_builder, "{sv}", "ca", g_variant_new("s", ca)); } + /* dnsconfd defines priority as bigger number equals bigger priority, while NM + * uses the exact opposite, thus use -priority */ + g_variant_builder_add(argument_builder, "{sv}", "priority", g_variant_new("i", -priority)); return TRUE; } @@ -443,7 +453,8 @@ parse_global_config(const NMGlobalDnsConfig *global_config, servers[j], routing_domains, searches, - *ca)) { + *ca, + NM_DNS_PRIORITY_DEFAULT_NORMAL)) { g_variant_builder_close(argument_builder); } } @@ -560,7 +571,7 @@ dnsconfd_start_done(GObject *source_object, GAsyncResult *res, gpointer user_dat g_dbus_error_strip_remote_error(error); _LOGW("failed to start Dnsconfd %s", error->message); } else { - _LOGT("succesfully started Dnsconfd"); + _LOGT("successfully started Dnsconfd"); } /* No update maybe changed or state change, as this is handled by the name owner callbacks @@ -628,6 +639,7 @@ parse_all_interface_config(GVariantBuilder *argument_builder, NMDnsConfigIPData *ip_data; const char *const *dns_server_strings; guint nameserver_count; + int priority; const char *ifname; gboolean explicit_default = is_default_interface_explicit(ip_data_lst_head); @@ -648,6 +660,9 @@ parse_all_interface_config(GVariantBuilder *argument_builder, gather_interface_domains(ip_data, explicit_default, &routing_domains, &search_domains); get_networks(ip_data, &networks); + if (!nm_l3_config_data_get_dns_priority(ip_data->l3cd, ip_data->addr_family, &priority)) { + priority = NM_DNS_PRIORITY_DEFAULT_NORMAL; + } for (guint i = 0; i < nameserver_count; i++) { if (server_builder_append_base(argument_builder, @@ -655,7 +670,8 @@ parse_all_interface_config(GVariantBuilder *argument_builder, dns_server_strings[i], routing_domains, search_domains, - ca)) { + ca, + priority)) { server_builder_append_interface_info(argument_builder, ifname, networks); } } diff --git a/src/core/ndisc/nm-lndp-ndisc.c b/src/core/ndisc/nm-lndp-ndisc.c index 33e9ebf3..f0de2fd5 100644 --- a/src/core/ndisc/nm-lndp-ndisc.c +++ b/src/core/ndisc/nm-lndp-ndisc.c @@ -218,10 +218,22 @@ receive_ra(struct ndp *ndp, struct ndp_msg *msg, gpointer user_data) /* Address */ if (r_plen == 64 && ndp_msg_opt_prefix_flag_auto_addr_conf(msg, offset)) { - const guint32 valid_time = ndp_msg_opt_prefix_valid_time(msg, offset); - const guint32 preferred_time = - NM_MIN(ndp_msg_opt_prefix_preferred_time(msg, offset), valid_time); - const NMNDiscAddress address = { + const guint32 valid_time = ndp_msg_opt_prefix_valid_time(msg, offset); + const guint32 preferred_time = ndp_msg_opt_prefix_preferred_time(msg, offset); + NMNDiscAddress address; + + /* + * RFC 4862 Section 5.5.3 states: + * c) If the preferred lifetime is greater than the valid lifetime, + * silently ignore the Prefix Information option. A node MAY wish to + * log a system management error in this case. + */ + if (preferred_time > valid_time) { + _LOGW("skipping PIO - preferred lifetime > valid lifetime"); + continue; + } + + address = (NMNDiscAddress) { .address = r_network, .expiry_msec = _nm_ndisc_lifetime_to_expiry(now_msec, valid_time), .expiry_preferred_msec = _nm_ndisc_lifetime_to_expiry(now_msec, preferred_time), diff --git a/src/core/ndisc/nm-ndisc.c b/src/core/ndisc/nm-ndisc.c index ad2edd8d..1a2bf480 100644 --- a/src/core/ndisc/nm-ndisc.c +++ b/src/core/ndisc/nm-ndisc.c @@ -1490,7 +1490,7 @@ clean_addresses(NMNDisc *ndisc, gint64 now_msec, NMNDiscConfigMap *changed, gint g_array_set_size(rdata->addresses, j); } - if (_array_set_size_max(rdata->gateways, priv->config.max_addresses)) + if (_array_set_size_max(rdata->addresses, priv->config.max_addresses)) *changed |= NM_NDISC_CONFIG_ADDRESSES; } @@ -1830,7 +1830,7 @@ _config_init(NMNDiscConfig *config, const NMNDiscConfig *src) nm_assert(config); g_return_if_fail(src); - /* we only allow to set @config if it was cleared (or is not yet initialized). */ + /* we only allow one to set @config if it was cleared (or is not yet initialized). */ nm_assert(!config->l3cfg); nm_assert(!config->ifname); nm_assert(!config->network_id); diff --git a/src/core/nm-bond-manager.c b/src/core/nm-bond-manager.c index 116cb737..abaab7d4 100644 --- a/src/core/nm-bond-manager.c +++ b/src/core/nm-bond-manager.c @@ -916,21 +916,21 @@ nm_bond_manager_send_arp(int bond_ifindex, if (announce_fdb) { /* if we are announcing the FDB we do a RARP, we don't set the * source/dest IPv4 address */ - int ifindexes[] = {bridge_ifindex, bond_ifindex}; - int i; - gs_free NMEtherAddr **fdb_addrs = NULL; + int ifindexes[] = {bridge_ifindex, bond_ifindex}; + int i; + nm_auto_freev NMEtherAddr **fdb_addrs = NULL; - fdb_addrs = nm_linux_platform_get_link_fdb_table(platform, ifindexes, 2); + fdb_addrs = nm_linux_platform_get_bridge_fdb(platform, ifindexes, 2); /* we want to send a Reverse ARP (RARP) packet */ data.op = htons(ARP_OP_RARP); i = 0; while (fdb_addrs[i] != NULL) { NMEtherAddr *tmp_hwaddr = fdb_addrs[i]; + memcpy(data.s_hw_addr, tmp_hwaddr, ETH_ALEN); memcpy(data.d_hw_addr, tmp_hwaddr, ETH_ALEN); memcpy(data.s_addr, tmp_hwaddr, ETH_ALEN); - g_free(tmp_hwaddr); if (sendto(sockfd, &data, sizeof(data), 0, (struct sockaddr *) &addr, sizeof(addr)) < 0) return FALSE; i++; diff --git a/src/core/nm-core-utils.c b/src/core/nm-core-utils.c index 895a9917..d3c2eb21 100644 --- a/src/core/nm-core-utils.c +++ b/src/core/nm-core-utils.c @@ -4642,13 +4642,13 @@ get_max_rate_vht_80_ss3(int mcs) case 5: return 702000000; case 6: - return 0; + return 0; /* invalid */ case 7: return 877500000; case 8: - return 105300000; + return 1053000000; case 9: - return 117000000; + return 1170000000; } return 0; } @@ -4732,7 +4732,7 @@ get_max_rate_vht_160_ss3(int mcs) case 8: return 2106000000; case 9: - return 0; + return 0; /* invalid */ } return 0; } @@ -5417,7 +5417,7 @@ again: if ((g = g_atomic_int_get(&g_static)) == -1) { gid_t g2; - g2 = geteuid(); + g2 = getegid(); g = g2; nm_assert(g == g2); nm_assert(g >= 0); diff --git a/src/core/nm-l3-config-data.c b/src/core/nm-l3-config-data.c index 70867ff7..20623145 100644 --- a/src/core/nm-l3-config-data.c +++ b/src/core/nm-l3-config-data.c @@ -1419,6 +1419,9 @@ _check_and_add_domain(GPtrArray **p_arr, const char *domain) if (domain[0] == '.' || strstr(domain, "..")) return FALSE; + if (!g_utf8_validate(domain, -1, NULL)) + return FALSE; + len = strlen(domain); if (domain[len - 1] == '.') { copy = g_strndup(domain, len - 1); diff --git a/src/core/nm-l3cfg.c b/src/core/nm-l3cfg.c index a9aa506d..1797cd0f 100644 --- a/src/core/nm-l3cfg.c +++ b/src/core/nm-l3cfg.c @@ -2294,7 +2294,7 @@ _l3_acd_data_timeout_schedule(AcdData *acd_data, gint64 timeout_msec) * expect timeouts in certain states. * * That means, scheduling a timeout is only correct if we are in a certain - * state, which allows to handle timeouts. This assert checks for that to + * state, which allows one to handle timeouts. This assert checks for that to * ensure we don't call a timeout in an unexpected state. */ nm_assert(NM_IN_SET(acd_data->info.state, NM_L3_ACD_ADDR_STATE_PROBING, @@ -2751,9 +2751,8 @@ handle_init: goto handle_start_defending; } - acd_data->probing_timestamp_msec = (*p_now_msec); - acd_data->probing_timeout_msec = acd_timeout_msec; - log_reason = "retry probing on timeout"; + acd_data->probing_timeout_msec = acd_timeout_msec; + log_reason = "retry probing on timeout"; goto handle_start_probing; } @@ -3050,7 +3049,7 @@ handle_start_probing: if (!acd_data->nacd_probe) { _LOGT_acd(acd_data, "probing currently %snot possible (timeout %u msec; %s, %s)", - orig_state == NM_L3_ACD_ADDR_STATE_INIT ? "" : " still", + orig_state == NM_L3_ACD_ADDR_STATE_INIT ? "" : "still ", acd_data->probing_timeout_msec, failure_reason, log_reason); diff --git a/src/core/nm-manager.c b/src/core/nm-manager.c index a861b2fe..fce37071 100644 --- a/src/core/nm-manager.c +++ b/src/core/nm-manager.c @@ -478,7 +478,9 @@ _version_info_get(void) * Each of the array's elements has 32 bits. This means that capabilities * with index 0-31 goes to element #1, with index 32-63 to element #2, * with index 64-95 to element #3 and so on. */ - 1 << NM_VERSION_INFO_CAPABILITY_SYNC_ROUTE_WITH_TABLE, + (1 << NM_VERSION_INFO_CAPABILITY_SYNC_ROUTE_WITH_TABLE) + | (1 << NM_VERSION_INFO_CAPABILITY_IP4_FORWARDING) + | (1 << NM_VERSION_INFO_CAPABILITY_SRIOV_PRESERVE_ON_DOWN), }; return nm_g_variant_new_au(arr, G_N_ELEMENTS(arr)); @@ -4250,6 +4252,7 @@ add: case NM_LINK_TYPE_OLPC_MESH: case NM_LINK_TYPE_TEAM: case NM_LINK_TYPE_WIFI: + case NM_LINK_TYPE_OPENVSWITCH: _LOGI(LOGD_PLATFORM, "(%s): '%s' plugin not available; creating generic device", plink->name, @@ -4689,16 +4692,10 @@ found_better: if (nm_g_hash_table_contains(exclude_devices, device)) continue; - /* During startup, NM performs a cleanup of the ovsdb to remove previous entries. - * Before the device is suitable for the connection, it must have ovsdb->ready set - * to TRUE. Performing this check in all kind of interfaces is too agressive and leads - * to race conditions, e.g when a non-virtual bond port gets a carrier, preventing the - * device to be a good candidate for the connection. */ - if (nm_device_get_device_type(device) == NM_DEVICE_TYPE_OVS_INTERFACE - && !nm_device_is_available(device, - for_user_request - ? NM_DEVICE_CHECK_DEV_AVAILABLE_FOR_USER_REQUEST - : NM_DEVICE_CHECK_DEV_AVAILABLE_NONE)) + if (!nm_device_is_available(device, + for_user_request + ? NM_DEVICE_CHECK_DEV_AVAILABLE_FOR_USER_REQUEST + : NM_DEVICE_CHECK_DEV_AVAILABLE_NONE)) continue; /* determine the priority of this device. Currently, this priority is independent diff --git a/src/core/nm-netns.c b/src/core/nm-netns.c index 57dbe9c5..f481bc36 100644 --- a/src/core/nm-netns.c +++ b/src/core/nm-netns.c @@ -75,7 +75,7 @@ typedef struct { /* Indexes the watcher handles. */ GHashTable *watcher_idx; - /* An index of WatcherByTag. It allows to lookup watcher handles by tag. + /* An index of WatcherByTag. It allows one to lookup watcher handles by tag. * Handles without tag are not indexed. */ GHashTable *watcher_by_tag_idx; diff --git a/src/core/nm-policy.c b/src/core/nm-policy.c index 33073e4a..fbcee40d 100644 --- a/src/core/nm-policy.c +++ b/src/core/nm-policy.c @@ -18,6 +18,7 @@ #include "NetworkManagerUtils.h" #include "devices/nm-device.h" #include "devices/nm-device-factory.h" +#include "devices/nm-device-private.h" #include "dns/nm-dns-manager.h" #include "nm-act-request.h" #include "nm-auth-utils.h" @@ -97,7 +98,6 @@ typedef struct { bool updating_dns : 1; GArray *ip6_prefix_delegations; /* pool of ip6 prefixes delegated to all devices */ - } NMPolicyPrivate; struct _NMPolicy { @@ -155,17 +155,15 @@ static gboolean hostname_retry_cb(gpointer user_data); typedef struct { NMPlatformIP6Address prefix; - NMDevice *device; /* The requesting ("uplink") device */ - guint64 next_subnet; /* Cache of the next subnet number to be - * assigned from this prefix */ - GHashTable *subnets; /* ifindex -> NMPlatformIP6Address */ + NMDevice *device; /* The requesting ("uplink") device */ + GHashTable *map_subnet_id_to_ifindex; /* (guint64 *) subnet_id -> int ifindex */ + GHashTable *map_ifindex_to_subnet; /* int ifindex -> (NMPlatformIP6Address *) prefix */ } IP6PrefixDelegation; static void -_clear_ip6_subnet(gpointer key, gpointer value, gpointer user_data) +clear_ip6_subnet(int ifindex, NMPlatformIP6Address *subnet) { - NMPlatformIP6Address *subnet = value; - NMDevice *device = nm_manager_get_device_by_ifindex(NM_MANAGER_GET, GPOINTER_TO_INT(key)); + NMDevice *device = nm_manager_get_device_by_ifindex(NM_MANAGER_GET, ifindex); if (device) { /* We can not remove a subnet we already started announcing. @@ -177,6 +175,12 @@ _clear_ip6_subnet(gpointer key, gpointer value, gpointer user_data) } static void +clear_ip6_subnet_entry(gpointer key, gpointer value, gpointer user_data) +{ + clear_ip6_subnet(GPOINTER_TO_INT(key), value); +} + +static void clear_ip6_prefix_delegation(gpointer data) { IP6PrefixDelegation *delegation = data; @@ -187,8 +191,9 @@ clear_ip6_prefix_delegation(gpointer data) nm_inet6_ntop(&delegation->prefix.address, sbuf), delegation->prefix.plen); - g_hash_table_foreach(delegation->subnets, _clear_ip6_subnet, NULL); - g_hash_table_destroy(delegation->subnets); + g_hash_table_foreach(delegation->map_ifindex_to_subnet, clear_ip6_subnet_entry, NULL); + g_hash_table_destroy(delegation->map_ifindex_to_subnet); + g_hash_table_destroy(delegation->map_subnet_id_to_ifindex); } static void @@ -215,46 +220,112 @@ expire_ip6_delegations(NMPolicy *self) static gboolean ip6_subnet_from_delegation(IP6PrefixDelegation *delegation, NMDevice *device) { - NMPlatformIP6Address *subnet; - int ifindex = nm_device_get_ifindex(device); - char sbuf[NM_INET_ADDRSTRLEN]; - - subnet = g_hash_table_lookup(delegation->subnets, GINT_TO_POINTER(ifindex)); - if (!subnet) { - /* Check for out-of-prefixes condition. */ - if (delegation->next_subnet >= (1 << (64 - delegation->prefix.plen))) { - _LOGD(LOGD_IP6, - "ipv6-pd: no more prefixes in %s/%d", - nm_inet6_ntop(&delegation->prefix.address, sbuf), - delegation->prefix.plen); - return FALSE; + NMPlatformIP6Address *subnet; + int ifindex = nm_device_get_ifindex(device); + char sbuf[NM_INET_ADDRSTRLEN]; + NMSettingPrefixDelegation *s_pd; + gint64 wanted_subnet_id = -1; + guint64 num_subnets; + guint64 old_subnet_id; + + nm_assert(delegation->prefix.plen > 0 && delegation->prefix.plen <= 64); + + s_pd = nm_device_get_applied_setting(device, NM_TYPE_SETTING_PREFIX_DELEGATION); + if (s_pd) { + wanted_subnet_id = nm_setting_prefix_delegation_get_subnet_id(s_pd); + } + + /* Try to use the cached subnet assigned to the interface */ + subnet = g_hash_table_lookup(delegation->map_ifindex_to_subnet, GINT_TO_POINTER(ifindex)); + if (subnet) { + old_subnet_id = nm_ip6_addr_get_subnet_id(&subnet->address, delegation->prefix.plen); + if (wanted_subnet_id != -1 && wanted_subnet_id != old_subnet_id) { + /* The device had a subnet assigned before, but now wants a + * different subnet-id. Release the old subnet and continue below + * to get a new one. */ + clear_ip6_subnet(ifindex, subnet); + subnet = NULL; + g_hash_table_remove(delegation->map_ifindex_to_subnet, GINT_TO_POINTER(ifindex)); + g_hash_table_remove(delegation->map_subnet_id_to_ifindex, &old_subnet_id); + } else { + goto subnet_found; } + } - /* Allocate a new subnet. */ - subnet = g_slice_new0(NMPlatformIP6Address); - g_hash_table_insert(delegation->subnets, GINT_TO_POINTER(ifindex), subnet); + /* Check for out-of-prefixes condition */ + num_subnets = 1 << (64 - delegation->prefix.plen); + if (nm_g_hash_table_size(delegation->map_subnet_id_to_ifindex) >= num_subnets) { + _LOGD(LOGD_IP6, + "ipv6-pd: no more prefixes in %s/%u", + nm_inet6_ntop(&delegation->prefix.address, sbuf), + delegation->prefix.plen); + return FALSE; + } + + /* Try to honor the "prefix-delegation.subnet-id" property */ + if (wanted_subnet_id >= 0) { + gpointer value; + NMDevice *other_device; + + if (g_hash_table_lookup_extended(delegation->map_subnet_id_to_ifindex, + &wanted_subnet_id, + NULL, + &value)) { + other_device = nm_manager_get_device_by_ifindex(NM_MANAGER_GET, GPOINTER_TO_INT(value)); + _LOGW(LOGD_IP6, + "ipv6-pd: subnet-id 0x%" G_GINT64_MODIFIER + "x wanted by device %s is already in use by " + "device %s (ifindex %d)", + (guint64) wanted_subnet_id, + nm_device_get_iface(device), + other_device ? nm_device_get_ip_iface(other_device) : NULL, + GPOINTER_TO_INT(value)); + wanted_subnet_id = -1; + } + } + + /* If we don't have a subnet-id yet, find the first one available */ + if (wanted_subnet_id < 0) { + guint64 i; - subnet->plen = 64; - subnet->address.s6_addr32[0] = - delegation->prefix.address.s6_addr32[0] | htonl(delegation->next_subnet >> 32); - subnet->address.s6_addr32[1] = - delegation->prefix.address.s6_addr32[1] | htonl(delegation->next_subnet); + for (i = 0; i < num_subnets; i++) { + if (!g_hash_table_lookup_extended(delegation->map_subnet_id_to_ifindex, + &i, + NULL, + NULL)) { + wanted_subnet_id = (gint64) i; + break; + } + } - /* Out subnet pool management is pretty unsophisticated. We only add - * the subnets and index them by ifindex. That keeps the implementation - * simple and the dead entries make it easy to reuse the same subnet on - * subsequent activations. On the other hand they may waste the subnet - * space. */ - delegation->next_subnet++; + if (wanted_subnet_id < 0) { + /* We already verified that there are available subnets, this should not happen */ + return nm_assert_unreachable_val(FALSE); + } } + /* Allocate a new subnet */ + subnet = g_slice_new0(NMPlatformIP6Address); + g_hash_table_insert(delegation->map_ifindex_to_subnet, GINT_TO_POINTER(ifindex), subnet); + g_hash_table_insert(delegation->map_subnet_id_to_ifindex, + nm_memdup(&wanted_subnet_id, sizeof(guint64)), + GINT_TO_POINTER(ifindex)); + + subnet->plen = 64; + subnet->address.s6_addr32[0] = + delegation->prefix.address.s6_addr32[0] | htonl(wanted_subnet_id >> 32); + subnet->address.s6_addr32[1] = + delegation->prefix.address.s6_addr32[1] | htonl(wanted_subnet_id); + +subnet_found: subnet->timestamp = delegation->prefix.timestamp; subnet->lifetime = delegation->prefix.lifetime; subnet->preferred = delegation->prefix.preferred; _LOGD(LOGD_IP6, - "ipv6-pd: %s allocated from a /%d prefix on %s", + "ipv6-pd: %s/64 (subnet-id 0x%" G_GINT64_MODIFIER "x) allocated from a /%d prefix on %s", nm_inet6_ntop(&subnet->address, sbuf), + (guint64) wanted_subnet_id, delegation->prefix.plen, nm_device_get_iface(device)); @@ -345,8 +416,9 @@ device_ip6_prefix_delegated(NMDevice *device, if (i == priv->ip6_prefix_delegations->len) { /* Allocate a delegation for new prefix. */ delegation = nm_g_array_append_new(priv->ip6_prefix_delegations, IP6PrefixDelegation); - delegation->subnets = g_hash_table_new(nm_direct_hash, NULL); - delegation->next_subnet = 0; + delegation->map_subnet_id_to_ifindex = + g_hash_table_new_full(nm_puint64_hash, nm_puint64_equal, g_free, NULL); + delegation->map_ifindex_to_subnet = g_hash_table_new(nm_direct_hash, NULL); } delegation->device = device; @@ -960,7 +1032,7 @@ update_system_hostname(NMPolicy *self, const char *msg, gboolean reset_retry_int /* Try a persistent hostname first */ configured_hostname = nm_hostname_manager_get_static_hostname(priv->hostname_manager); - if (configured_hostname && nm_utils_is_specific_hostname(configured_hostname)) { + if (configured_hostname && nm_utils_is_not_empty_hostname(configured_hostname)) { _set_hostname(self, configured_hostname, "from system configuration", FALSE); priv->dhcp_hostname = FALSE; return; @@ -2012,6 +2084,65 @@ unblock_autoconnect_for_ports_for_sett_conn(NMPolicy *self, NMSettingsConnection } static void +refresh_forwarding(NMPolicy *self, NMDevice *device, gboolean is_activated_shared_device) +{ + NMActiveConnection *ac; + NMDevice *tmp_device; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self); + const CList *tmp_lst; + gboolean any_shared_active = false; + gint32 default_forwarding_v4; + const char *new_value = NULL; + + /* FIXME: This implementation is still inefficient because refresh_forwarding() + * is called every time a device goes up or down, requiring a full scan of all + * active connections to determine if any shared connection is active. */ + nm_manager_for_each_active_connection (priv->manager, ac, tmp_lst) { + NMSettingIPConfig *s_ip; + NMDevice *to_device = nm_active_connection_get_device(ac); + + if (to_device) { + s_ip = nm_device_get_applied_setting(to_device, NM_TYPE_SETTING_IP4_CONFIG); + if (s_ip) { + if (nm_streq0(nm_device_get_effective_ip_config_method(to_device, AF_INET), + NM_SETTING_IP4_CONFIG_METHOD_SHARED)) { + any_shared_active = true; + break; + } + } + } + } + + default_forwarding_v4 = nm_platform_sysctl_get_int32( + NM_PLATFORM_GET, + NMP_SYSCTL_PATHID_ABSOLUTE("/proc/sys/net/ipv4/conf/default/forwarding"), + 0); + + new_value = any_shared_active ? "1" : (default_forwarding_v4 ? "1" : "0"); + + nm_manager_for_each_device (priv->manager, tmp_device, tmp_lst) { + NMDeviceState state; + NMSettingIPConfigForwarding ipv4_forwarding; + + state = nm_device_get_state(tmp_device); + if (state != NM_DEVICE_STATE_ACTIVATED) + continue; + + ipv4_forwarding = nm_device_get_ipv4_forwarding(tmp_device); + + if (ipv4_forwarding == NM_SETTING_IP_CONFIG_FORWARDING_AUTO + || (device == tmp_device && is_activated_shared_device)) { + gs_free char *sysctl_value = NULL; + + sysctl_value = nm_device_sysctl_ip_conf_get(tmp_device, AF_INET, "forwarding"); + + if (!nm_streq0(sysctl_value, new_value)) + nm_device_sysctl_ip_conf_set(tmp_device, AF_INET, "forwarding", new_value); + } + } +} + +static void activate_port_or_children_connections(NMPolicy *self, NMDevice *device, gboolean activate_children_connections_only) @@ -2155,8 +2286,9 @@ device_state_changed(NMDevice *device, NMPolicyPrivate *priv = user_data; NMPolicy *self = _PRIV_TO_SELF(priv); NMActiveConnection *ac; - NMSettingsConnection *sett_conn = nm_device_get_settings_connection(device); - NMSettingConnection *s_con = NULL; + NMSettingsConnection *sett_conn = nm_device_get_settings_connection(device); + NMSettingConnection *s_con = NULL; + gboolean is_activated_shared_device = FALSE; switch (nm_device_state_reason_check(reason)) { case NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED: @@ -2211,8 +2343,10 @@ device_state_changed(NMDevice *device, con_v = nm_settings_connection_get_last_secret_agent_version_id(sett_conn); if (con_v == 0 || con_v == nm_agent_manager_get_agent_version_id(priv->agent_mgr)) { _LOGD(LOGD_DEVICE, - "block-autoconnect: connection '%s' now blocked from autoconnect due to " - "no secrets", + "block-autoconnect: connection[" NM_HASH_OBFUSCATE_PTR_FMT + "] (%s) now blocked from " + "autoconnect due to no secrets", + NM_HASH_OBFUSCATE_PTR(sett_conn), nm_settings_connection_get_id(sett_conn)); nm_settings_connection_autoconnect_blocked_reason_set( sett_conn, @@ -2230,10 +2364,10 @@ device_state_changed(NMDevice *device, * be marked as blocked when it fails with dependency-failed. */ _LOGD(LOGD_DEVICE, - "block-autoconnect: connection[%p] (%s) now blocked from autoconnect due to " - "failed " - "dependency", - sett_conn, + "block-autoconnect: connection[" NM_HASH_OBFUSCATE_PTR_FMT + "] (%s) now blocked " + "from autoconnect due to failed dependency", + NM_HASH_OBFUSCATE_PTR(sett_conn), nm_settings_connection_get_id(sett_conn)); nm_manager_devcon_autoconnect_blocked_reason_set( priv->manager, @@ -2255,20 +2389,25 @@ device_state_changed(NMDevice *device, /* blocked */ } else if (tries != NM_AUTOCONNECT_RETRIES_FOREVER) { _LOGD(LOGD_DEVICE, - "autoconnect: connection[%p] (%s): failed to autoconnect; %u tries left", - sett_conn, + "autoconnect: connection[" NM_HASH_OBFUSCATE_PTR_FMT "] (%s): failed to " + "autoconnect; %u tries left", + NM_HASH_OBFUSCATE_PTR(sett_conn), nm_settings_connection_get_id(sett_conn), tries - 1u); _connection_autoconnect_retries_set(self, device, sett_conn, tries - 1u); } else { _LOGD(LOGD_DEVICE, - "autoconnect: connection[%p] (%s) failed to autoconnect; infinite tries " - "left", - sett_conn, + "autoconnect: connection[" NM_HASH_OBFUSCATE_PTR_FMT "] (%s) failed to " + "autoconnect; infinite tries left", + NM_HASH_OBFUSCATE_PTR(sett_conn), nm_settings_connection_get_id(sett_conn)); } } } + if (!nm_device_get_refresh_forwarding_done(device)) { + refresh_forwarding(self, device, FALSE); + nm_device_set_refresh_forwarding_done(device, TRUE); + } break; case NM_DEVICE_STATE_ACTIVATED: if (nm_device_get_device_type(device) == NM_DEVICE_TYPE_OVS_INTERFACE) { @@ -2301,11 +2440,20 @@ device_state_changed(NMDevice *device, update_system_hostname(self, "routing and dns", TRUE); nm_dns_manager_end_updates(priv->dns_manager, __func__); + is_activated_shared_device = + nm_streq0(nm_device_get_effective_ip_config_method(device, AF_INET), + NM_SETTING_IP4_CONFIG_METHOD_SHARED); + refresh_forwarding(self, device, is_activated_shared_device); + nm_device_set_refresh_forwarding_done(device, FALSE); break; case NM_DEVICE_STATE_UNMANAGED: case NM_DEVICE_STATE_UNAVAILABLE: if (old_state > NM_DEVICE_STATE_DISCONNECTED) update_routing_and_dns(self, FALSE, device); + if (!nm_device_get_refresh_forwarding_done(device)) { + refresh_forwarding(self, device, FALSE); + nm_device_set_refresh_forwarding_done(device, TRUE); + } break; case NM_DEVICE_STATE_DEACTIVATING: if (sett_conn) { @@ -2341,6 +2489,10 @@ device_state_changed(NMDevice *device, } } ip6_remove_device_prefix_delegations(self, device); + if (!nm_device_get_refresh_forwarding_done(device)) { + refresh_forwarding(self, device, FALSE); + nm_device_set_refresh_forwarding_done(device, TRUE); + } break; case NM_DEVICE_STATE_DISCONNECTED: g_signal_handlers_disconnect_by_func(device, device_dns_lookup_done, self); @@ -2357,6 +2509,10 @@ device_state_changed(NMDevice *device, /* Device is now available for auto-activation */ nm_policy_device_recheck_auto_activate_schedule(self, device); + if (!nm_device_get_refresh_forwarding_done(device)) { + refresh_forwarding(self, device, FALSE); + nm_device_set_refresh_forwarding_done(device, TRUE); + } break; case NM_DEVICE_STATE_PREPARE: @@ -2372,6 +2528,10 @@ device_state_changed(NMDevice *device, g_object_weak_unref(G_OBJECT(ac), pending_ac_gone, self); g_object_unref(self); } + if (!nm_device_get_refresh_forwarding_done(device)) { + refresh_forwarding(self, device, FALSE); + nm_device_set_refresh_forwarding_done(device, TRUE); + } break; case NM_DEVICE_STATE_IP_CONFIG: /* We must have secrets if we got here. */ @@ -2382,6 +2542,10 @@ device_state_changed(NMDevice *device, sett_conn, NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_FAILED, FALSE); + if (!nm_device_get_refresh_forwarding_done(device)) { + refresh_forwarding(self, device, FALSE); + nm_device_set_refresh_forwarding_done(device, TRUE); + } break; case NM_DEVICE_STATE_SECONDARIES: if (sett_conn) diff --git a/src/core/platform/nm-fake-platform.c b/src/core/platform/nm-fake-platform.c index 10c69f63..e0d51b70 100644 --- a/src/core/platform/nm-fake-platform.c +++ b/src/core/platform/nm-fake-platform.c @@ -117,7 +117,7 @@ ip6_address_delete(NMPlatform *platform, int ifindex, struct in6_addr addr, guin const int _dirfd = (dirfd); \ const char *const _path = (path); \ \ - g_assert(_path &&_path[0]); \ + g_assert(_path && _path[0]); \ g_assert(!strstr(_path, "/../")); \ if (_dirfd < 0) { \ g_assert(!_pathid); \ diff --git a/src/core/platform/tests/test-common.c b/src/core/platform/tests/test-common.c index 26f8b26b..91445b30 100644 --- a/src/core/platform/tests/test-common.c +++ b/src/core/platform/tests/test-common.c @@ -1356,7 +1356,7 @@ nmtstp_check_platform_full(NMPlatform *platform, guint32 obj_type_flags, gboolea /* For IPv4, it also does not reliably always work. This may * be a bug we want to fix. For now, ignore the check. * - * a) Kernel can wrongly allow to configure the same route twice. + * a) Kernel can wrongly allow one to configure the same route twice. * That means, the same route is visible in `ip route` output, * meaning, it would be added twice to the platform cache. * At least due to that problem, may the weak-id not be properly sorted. @@ -1364,7 +1364,7 @@ nmtstp_check_platform_full(NMPlatform *platform, guint32 obj_type_flags, gboolea * a bug of kernel allowing to configure the exact same route twice. * * b) See https://bugzilla.redhat.com/show_bug.cgi?id=2162315 which is - * a bug where kernel does allow to configure single-hop routes that differ by + * a bug where kernel does allow one to configure single-hop routes that differ by * their next-hop weight, but on the netlink API those routes look the same. * * Due to a) and b), the platform cache may contain only one instance diff --git a/src/core/platform/tests/test-link.c b/src/core/platform/tests/test-link.c index 4cadfe4d..fab6bd2e 100644 --- a/src/core/platform/tests/test-link.c +++ b/src/core/platform/tests/test-link.c @@ -15,6 +15,7 @@ #include "libnm-base/nm-ethtool-base.h" #include "libnm-platform/nmp-object.h" #include "libnm-platform/nmp-netns.h" +#include "libnm-platform/nmp-ethtool-ioctl.h" #include "libnm-platform/nm-platform-utils.h" #include "test-common.h" @@ -2725,6 +2726,66 @@ test_link_set_properties(void) /*****************************************************************************/ static void +test_link_get_bridge_fdb(void) +{ + const NMPlatformLink *link; + nm_auto_freev NMEtherAddr **addrs = NULL; + int ifindex[2]; + guint8 expected[][6] = { + {0x00, 0x99, 0x00, 0x00, 0x00, 0x01}, + {0x00, 0x99, 0x00, 0x00, 0x00, 0x02}, + {0x00, 0x99, 0x00, 0x00, 0x00, 0x03}, + {0x00, 0x99, 0x00, 0x00, 0x00, 0x05}, + }; + guint i; + guint j; + + ifindex[0] = + nmtstp_link_bridge_add(NULL, -1, "br-test-1", &nm_platform_lnk_bridge_default)->ifindex; + ifindex[1] = + nmtstp_link_bridge_add(NULL, -1, "br-test-2", &nm_platform_lnk_bridge_default)->ifindex; + + link = nmtstp_link_get(NULL, ifindex[0], "br-test-1"); + g_assert(link); + link = nmtstp_link_get(NULL, ifindex[1], "br-test-2"); + g_assert(link); + + nmtstp_run_command_check("bridge fdb add dev br-test-1 00:99:00:00:00:01"); + nmtstp_run_command_check("bridge fdb add dev br-test-1 00:99:00:00:00:02"); + nmtstp_run_command_check("bridge fdb add dev br-test-1 00:99:00:00:00:03"); + nmtstp_run_command_check("bridge fdb add dev br-test-2 00:99:00:00:00:01"); + nmtstp_run_command_check("bridge fdb add dev br-test-2 00:99:00:00:00:05"); + + addrs = nm_linux_platform_get_bridge_fdb(NM_PLATFORM_GET, ifindex, 2); + g_assert(addrs); + + /* Check for expected entries */ + for (i = 0; i < G_N_ELEMENTS(expected); i++) { + gboolean found = FALSE; + + for (j = 0; addrs[j]; j++) { + if (memcmp(addrs[j], expected[i], ETH_ALEN) == 0) { + found = TRUE; + break; + } + } + g_assert(found); + } + + /* No dupes */ + for (i = 0; addrs[i]; i++) { + for (j = i + 1; addrs[j]; j++) { + g_assert_cmpint(memcmp(addrs[i], addrs[j], ETH_ALEN), !=, 0); + } + } + + nmtstp_link_delete(NULL, -1, ifindex[0], "br-test-1", TRUE); + nmtstp_link_delete(NULL, -1, ifindex[1], "br-test-2", TRUE); +} + +/*****************************************************************************/ + +static void test_create_many_links_do(guint n_devices) { gint64 time, start_time = nm_utils_get_monotonic_timestamp_nsec(); @@ -3183,10 +3244,10 @@ test_netns_general(gpointer fixture, gconstpointer test_data) * Work around that and skip asserts that are known to fail. */ ethtool_support = nmtstp_run_command("ethtool -i dummy1_ > /dev/null") == 0; if (ethtool_support) { - g_assert(nmp_utils_ethtool_get_driver_info( + g_assert(nmp_ethtool_ioctl_get_driver_info( nmtstp_link_get_typed(platform_1, 0, "dummy1_", NM_LINK_TYPE_DUMMY)->ifindex, &driver_info)); - g_assert(nmp_utils_ethtool_get_driver_info( + g_assert(nmp_ethtool_ioctl_get_driver_info( nmtstp_link_get_typed(platform_1, 0, "dummy2a", NM_LINK_TYPE_DUMMY)->ifindex, &driver_info)); g_assert_cmpint(nmtstp_run_command("ethtool -i dummy1_ > /dev/null"), ==, 0); @@ -3197,10 +3258,10 @@ test_netns_general(gpointer fixture, gconstpointer test_data) g_assert(nm_platform_netns_push(platform_2, &netns_tmp)); if (ethtool_support) { - g_assert(nmp_utils_ethtool_get_driver_info( + g_assert(nmp_ethtool_ioctl_get_driver_info( nmtstp_link_get_typed(platform_2, 0, "dummy1_", NM_LINK_TYPE_DUMMY)->ifindex, &driver_info)); - g_assert(nmp_utils_ethtool_get_driver_info( + g_assert(nmp_ethtool_ioctl_get_driver_info( nmtstp_link_get_typed(platform_2, 0, "dummy2b", NM_LINK_TYPE_DUMMY)->ifindex, &driver_info)); g_assert_cmpint(nmtstp_run_command("ethtool -i dummy1_ > /dev/null"), ==, 0); @@ -4031,7 +4092,7 @@ test_ethtool_features_get(void) _LOGT(">>> ethtool-features-get RUN %u (do-set=%s", i_run, do_set ? "set" : "reset"); - features = nmp_utils_ethtool_get_features(IFINDEX); + features = nmp_ethtool_ioctl_get_features(IFINDEX); g_ptr_array_add(gfree_keeper, features); ethtool_features_dump(features); @@ -4044,7 +4105,7 @@ test_ethtool_features_get(void) features = gfree_keeper->pdata[i_run * 2 - 1]; } - nmp_utils_ethtool_set_features(IFINDEX, features, requested, do_set); + nmp_ethtool_ioctl_set_features(IFINDEX, features, requested, do_set); } } @@ -4105,6 +4166,8 @@ _nmtstp_setup_tests(void) test_software_detect_add("/link/software/detect/wireguard/1", NM_LINK_TYPE_WIREGUARD, 1); test_software_detect_add("/link/software/detect/wireguard/2", NM_LINK_TYPE_WIREGUARD, 2); + g_test_add_func("/link/get-bridge-fdb", test_link_get_bridge_fdb); + g_test_add_func("/link/software/vlan/set-xgress", test_vlan_set_xgress); g_test_add_func("/link/set-properties", test_link_set_properties); diff --git a/src/core/platform/tests/test-route.c b/src/core/platform/tests/test-route.c index a05362f2..f8f7070b 100644 --- a/src/core/platform/tests/test-route.c +++ b/src/core/platform/tests/test-route.c @@ -640,22 +640,23 @@ test_ip4_route_options(gconstpointer test_data) switch (TEST_IDX) { case 1: rts_add[rts_n++] = ((NMPlatformIP4Route) { - .ifindex = IFINDEX, - .rt_source = NM_IP_CONFIG_SOURCE_USER, - .network = nmtst_inet4_from_string("172.16.1.0"), - .plen = 24, - .metric = 20, - .tos = 0x28, - .window = 10000, - .cwnd = 16, - .initcwnd = 30, - .initrwnd = 50, - .mtu = 1350, - .lock_cwnd = TRUE, - .mss = 1300, - .quickack = TRUE, - .rto_min = 1000, - .n_nexthops = 1, + .ifindex = IFINDEX, + .rt_source = NM_IP_CONFIG_SOURCE_USER, + .network = nmtst_inet4_from_string("172.16.1.0"), + .plen = 24, + .metric = 20, + .tos = 0x28, + .window = 10000, + .cwnd = 16, + .initcwnd = 30, + .initrwnd = 50, + .mtu = 1350, + .lock_cwnd = TRUE, + .mss = 1300, + .quickack = TRUE, + .rto_min = 1000, + .rto_min_set = TRUE, + .n_nexthops = 1, }); break; case 2: diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c index d64052cb..1e2e2d92 100644 --- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -1439,7 +1439,7 @@ next:; : "")); break; case PARSE_LINE_TYPE_FLAG: - /* NOTE: the flag (for "onlink") only allows to explicitly set "TRUE". + /* NOTE: the flag (for "onlink") only allows setting "TRUE" explicitly. * There is no way to express an explicit "FALSE" setting * of this attribute, hence, the file format cannot encode * that configuration. */ 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 6e0411c6..39cbddc5 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 @@ -3769,7 +3769,7 @@ nms_ifcfg_rh_writer_write_connection(NMConnection *connection, * * FIXME: a much better solution might be, to re-read the connection only based * on the in-memory representation of what we collected above. But the reader - * does not yet allow to inject the configuration. */ + * does not yet allow one to inject the configuration. */ if (out_reread || out_reread_same) { gs_unref_object NMConnection *reread = NULL; gboolean reread_same = FALSE; 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 ea978a98..2f3035ef 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 @@ -255,8 +255,8 @@ _assert_expected_content(NMConnection *connection, const char *filename, const c GError *_error = NULL; \ gboolean _success; \ \ - g_assert(_ifcfg_dir &&_ifcfg_dir[0]); \ - g_assert(_filename &&_filename[0]); \ + g_assert(_ifcfg_dir && _ifcfg_dir[0]); \ + g_assert(_filename && _filename[0]); \ \ _success = nms_ifcfg_rh_writer_write_connection(_connection, \ _ifcfg_dir, \ @@ -9533,12 +9533,10 @@ test_svUnescape(void) .exp = v_expected, \ .can_concat = !!v_expected, \ } -#define V2(v_value, v_expected) \ - { \ - .val = "" v_value "", \ - .exp = v_expected, \ - .can_concat = TRUE, \ - .needs_ascii_separator = TRUE, \ +#define V2(v_value, v_expected) \ + { \ + .val = "" v_value "", .exp = v_expected, .can_concat = TRUE, \ + .needs_ascii_separator = TRUE, \ } const UnescapeTestData data_full[] = { V1("", ""), 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 6b6913c5..df5dfd40 100644 --- a/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c +++ b/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c @@ -61,7 +61,7 @@ check_ip_route(NMSettingIPConfig *config, gs_free_error GError *_error = NULL; \ NMConnection *_connection; \ \ - g_assert(full_filename &&full_filename[0] == '/'); \ + g_assert(full_filename && full_filename[0] == '/'); \ \ _connection = \ nms_keyfile_reader_from_file(full_filename, \ diff --git a/src/core/supplicant/nm-supplicant-interface.c b/src/core/supplicant/nm-supplicant-interface.c index d5f56dcd..514b7c0d 100644 --- a/src/core/supplicant/nm-supplicant-interface.c +++ b/src/core/supplicant/nm-supplicant-interface.c @@ -3082,7 +3082,7 @@ _signal_handle(NMSupplicantInterface *self, const char *status; const char *parameter; - if (g_variant_is_of_type(parameters, G_VARIANT_TYPE("(ss)"))) + if (!g_variant_is_of_type(parameters, G_VARIANT_TYPE("(ss)"))) return; g_variant_get(parameters, "(&s&s)", &status, ¶meter); |