diff options
Diffstat (limited to 'src')
34 files changed, 757 insertions, 199 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index afc81dcd..6f9289ee 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -87,7 +87,7 @@ _LOG_DECLARE_SELF (NMDevice); #define DHCP_NUM_TRIES_MAX 3 #define DEFAULT_AUTOCONNECT TRUE -#define CARRIER_WAIT_TIME_MS 5000 +#define CARRIER_WAIT_TIME_MS 6000 #define CARRIER_WAIT_TIME_AFTER_MTU_MS 10000 #define NM_DEVICE_AUTH_RETRIES_UNSET -1 @@ -650,6 +650,8 @@ NM_UTILS_LOOKUP_STR_DEFINE (nm_device_state_reason_to_str, NMDeviceStateReason, NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_PARENT_CHANGED, "parent-changed"), NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED, "parent-managed-changed"), NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_OVSDB_FAILED, "ovsdb-failed"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE, "ip-address-duplicate"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED, "ip-method-unsupported"), ); #define reason_to_string(reason) \ @@ -1616,8 +1618,8 @@ nm_device_get_metered (NMDevice *self) return NM_DEVICE_GET_PRIVATE (self)->metered; } -static guint32 -_get_route_metric_default (NMDevice *self) +guint32 +nm_device_get_route_metric_default (NMDeviceType device_type) { /* Device 'priority' is used for the default route-metric and is based on * the device type. The settings ipv4.route-metric and ipv6.route-metric @@ -1636,7 +1638,7 @@ _get_route_metric_default (NMDevice *self) * metrics (except for IPv6, where 0 means 1024). */ - switch (nm_device_get_device_type (self)) { + switch (device_type) { /* 50 is reserved for VPN (NM_VPN_ROUTE_METRIC_DEFAULT) */ case NM_DEVICE_TYPE_ETHERNET: case NM_DEVICE_TYPE_VETH: @@ -1765,7 +1767,10 @@ nm_device_get_route_metric (NMDevice *self, if (route_metric >= 0) goto out; } - route_metric = _get_route_metric_default (self); + + route_metric = nm_manager_device_route_metric_reserve (nm_manager_get (), + nm_device_get_ip_ifindex (self), + nm_device_get_device_type (self)); out: return nm_utils_ip_route_metric_normalize (addr_family, route_metric); } @@ -5490,7 +5495,7 @@ ipv4_manual_method_apply (NMDevice *self, NMIP4Config **configs, gboolean succes g_object_unref (empty); } else { nm_device_ip_method_failed (self, AF_INET, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE); } } @@ -6074,7 +6079,7 @@ dhcp4_dad_cb (NMDevice *self, NMIP4Config **configs, gboolean success) nm_device_activate_schedule_ip4_config_result (self, configs[1]); else { nm_device_ip_method_failed (self, AF_INET, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE); } } @@ -8156,6 +8161,12 @@ nm_device_activate_stage3_ip4_start (NMDevice *self) g_assert (priv->ip4_state == IP_WAIT); + if (nm_device_sys_iface_state_is_external (self)) { + _set_ip_state (self, AF_INET, IP_DONE); + check_ip_state (self, FALSE); + return TRUE; + } + _set_ip_state (self, AF_INET, IP_CONF); ret = NM_DEVICE_GET_CLASS (self)->act_stage3_ip4_config_start (self, &ip4_config, &failure_reason); if (ret == NM_ACT_STAGE_RETURN_SUCCESS) { @@ -8197,6 +8208,12 @@ nm_device_activate_stage3_ip6_start (NMDevice *self) g_assert (priv->ip6_state == IP_WAIT); + if (nm_device_sys_iface_state_is_external (self)) { + _set_ip_state (self, AF_INET6, IP_DONE); + check_ip_state (self, FALSE); + return TRUE; + } + _set_ip_state (self, AF_INET6, IP_CONF); ret = NM_DEVICE_GET_CLASS (self)->act_stage3_ip6_config_start (self, &ip6_config, &failure_reason); if (ret == NM_ACT_STAGE_RETURN_SUCCESS) { @@ -12482,6 +12499,11 @@ _cleanup_generic_pre (NMDevice *self, CleanupType cleanup_type) _cancel_activation (self); + if (cleanup_type != CLEANUP_TYPE_KEEP) { + nm_manager_device_route_metric_clear (nm_manager_get (), + nm_device_get_ip_ifindex (self)); + } + if ( cleanup_type == CLEANUP_TYPE_DECONFIGURE && priv->fw_state >= FIREWALL_STATE_INITIALIZED && priv->fw_mgr @@ -13512,6 +13534,7 @@ nm_device_update_permanent_hw_address (NMDevice *self, gboolean force_freeze) gboolean success_read; int ifindex; const NMPlatformLink *pllink; + const NMConfigDeviceStateData *dev_state; if (priv->hw_addr_perm) { /* the permanent hardware address is only read once and not @@ -13571,23 +13594,19 @@ nm_device_update_permanent_hw_address (NMDevice *self, gboolean force_freeze) /* We also persist our choice of the fake address to the device state * file to use the same address on restart of NetworkManager. * First, try to reload the address from the state file. */ - { - gs_free NMConfigDeviceStateData *dev_state = NULL; - - dev_state = nm_config_device_state_load (ifindex); - if ( dev_state - && dev_state->perm_hw_addr_fake - && nm_utils_hwaddr_aton (dev_state->perm_hw_addr_fake, buf, priv->hw_addr_len) - && !nm_utils_hwaddr_matches (buf, priv->hw_addr_len, priv->hw_addr, -1)) { - _LOGD (LOGD_PLATFORM | LOGD_ETHER, "hw-addr: %s (use from statefile: %s, current: %s)", - success_read - ? "read HW addr length of permanent MAC address differs" - : "unable to read permanent MAC address", - dev_state->perm_hw_addr_fake, - priv->hw_addr); - priv->hw_addr_perm = nm_utils_hwaddr_ntoa (buf, priv->hw_addr_len); - goto notify_and_out; - } + dev_state = nm_config_device_state_get (nm_config_get (), ifindex); + if ( dev_state + && dev_state->perm_hw_addr_fake + && nm_utils_hwaddr_aton (dev_state->perm_hw_addr_fake, buf, priv->hw_addr_len) + && !nm_utils_hwaddr_matches (buf, priv->hw_addr_len, priv->hw_addr, -1)) { + _LOGD (LOGD_PLATFORM | LOGD_ETHER, "hw-addr: %s (use from statefile: %s, current: %s)", + success_read + ? "read HW addr length of permanent MAC address differs" + : "unable to read permanent MAC address", + dev_state->perm_hw_addr_fake, + priv->hw_addr); + priv->hw_addr_perm = nm_utils_hwaddr_ntoa (buf, priv->hw_addr_len); + goto notify_and_out; } _LOGD (LOGD_PLATFORM | LOGD_ETHER, "hw-addr: %s (use current: %s)", diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index 810a613d..ac73ee0c 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -450,6 +450,8 @@ NMMetered nm_device_get_metered (NMDevice *dev); guint32 nm_device_get_route_table (NMDevice *self, int addr_family, gboolean fallback_main); guint32 nm_device_get_route_metric (NMDevice *dev, int addr_family); +guint32 nm_device_get_route_metric_default (NMDeviceType device_type); + const char * nm_device_get_hw_address (NMDevice *dev); const char * nm_device_get_permanent_hw_address (NMDevice *self); const char * nm_device_get_permanent_hw_address_full (NMDevice *self, diff --git a/src/devices/ovs/nm-device-ovs-interface.c b/src/devices/ovs/nm-device-ovs-interface.c index 426521c5..e746a3fd 100644 --- a/src/devices/ovs/nm-device-ovs-interface.c +++ b/src/devices/ovs/nm-device-ovs-interface.c @@ -35,8 +35,13 @@ _LOG_DECLARE_SELF(NMDeviceOvsInterface); /*****************************************************************************/ +typedef struct { + bool waiting_for_interface:1; +} NMDeviceOvsInterfacePrivate; + struct _NMDeviceOvsInterface { NMDevice parent; + NMDeviceOvsInterfacePrivate _priv; }; struct _NMDeviceOvsInterfaceClass { @@ -45,6 +50,8 @@ struct _NMDeviceOvsInterfaceClass { G_DEFINE_TYPE (NMDeviceOvsInterface, nm_device_ovs_interface, NM_TYPE_DEVICE) +#define NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMDeviceOvsInterface, NM_IS_DEVICE_OVS_INTERFACE) + /*****************************************************************************/ static const char * @@ -109,7 +116,10 @@ static void link_changed (NMDevice *device, const NMPlatformLink *pllink) { - if (nm_device_get_state (device) == NM_DEVICE_STATE_IP_CONFIG) { + NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE (device); + + if (priv->waiting_for_interface) { + priv->waiting_for_interface = FALSE; nm_device_bring_up (device, TRUE, NULL); nm_device_activate_schedule_stage3_ip_config_start (device); } @@ -131,11 +141,15 @@ act_stage3_ip4_config_start (NMDevice *device, NMIP4Config **out_config, NMDeviceStateReason *out_failure_reason) { + NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE (device); + if (!_is_internal_interface (device)) return NM_ACT_STAGE_RETURN_IP_FAIL; - if (!nm_device_get_ip_ifindex (device)) + if (!nm_device_get_ip_ifindex (device)) { + priv->waiting_for_interface = TRUE; return NM_ACT_STAGE_RETURN_POSTPONE; + } return NM_DEVICE_CLASS (nm_device_ovs_interface_parent_class)->act_stage3_ip4_config_start (device, out_config, out_failure_reason); } @@ -145,11 +159,15 @@ act_stage3_ip6_config_start (NMDevice *device, NMIP6Config **out_config, NMDeviceStateReason *out_failure_reason) { + NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE (device); + if (!_is_internal_interface (device)) return NM_ACT_STAGE_RETURN_IP_FAIL; - if (!nm_device_get_ip_ifindex (device)) + if (!nm_device_get_ip_ifindex (device)) { + priv->waiting_for_interface = TRUE; return NM_ACT_STAGE_RETURN_POSTPONE; + } return NM_DEVICE_CLASS (nm_device_ovs_interface_parent_class)->act_stage3_ip6_config_start (device, out_config, out_failure_reason); } diff --git a/src/devices/tests/test-arping.c b/src/devices/tests/test-arping.c index 4b4642f3..bcbc1140 100644 --- a/src/devices/tests/test-arping.c +++ b/src/devices/tests/test-arping.c @@ -85,7 +85,7 @@ test_arping_common (test_fixture *fixture, TestInfo *info) loop = g_main_loop_new (NULL, FALSE); g_signal_connect (manager, NM_ARPING_MANAGER_PROBE_TERMINATED, G_CALLBACK (arping_manager_probe_terminated), loop); - g_assert (nm_arping_manager_start_probe (manager, 100, NULL)); + g_assert (nm_arping_manager_start_probe (manager, 250, NULL)); g_assert (nmtst_main_loop_run (loop, 2000)); for (i = 0; info->addresses[i]; i++) { diff --git a/src/devices/wwan/nm-modem-broadband.c b/src/devices/wwan/nm-modem-broadband.c index 6e5f10a0..dc0ce303 100644 --- a/src/devices/wwan/nm-modem-broadband.c +++ b/src/devices/wwan/nm-modem-broadband.c @@ -875,32 +875,37 @@ static_stage3_ip4_done (NMModemBroadband *self) NMPlatformIP4Address address; const gchar **dns; guint i; + guint32 ip4_route_table, ip4_route_metric; + NMPlatformIP4Route *r; g_assert (self->_priv.ipv4_config); g_assert (self->_priv.bearer); + self->_priv.idle_id_ip4 = 0; + _LOGI ("IPv4 static configuration:"); /* Fully fail if invalid IP address retrieved */ address_string = mm_bearer_ip_config_get_address (self->_priv.ipv4_config); - if (!nm_utils_parse_inaddr_bin (AF_INET, address_string, &address_network)) { + if ( !address_string + || !nm_utils_parse_inaddr_bin (AF_INET, address_string, &address_network)) { error = g_error_new (NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION, - "(%s) retrieving IP4 configuration failed: invalid address given '%s'", + "(%s) retrieving IP4 configuration failed: invalid address given %s%s%s", nm_modem_get_uid (NM_MODEM (self)), - address_string); + NM_PRINT_FMT_QUOTE_STRING (address_string)); goto out; } /* Missing gateway not a hard failure */ gw_string = mm_bearer_ip_config_get_gateway (self->_priv.ipv4_config); - if ( !gw_string - || !nm_utils_parse_inaddr_bin (AF_INET, gw_string, &gw)) { + if ( gw_string + && !nm_utils_parse_inaddr_bin (AF_INET, gw_string, &gw)) { error = g_error_new (NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION, - "(%s) retrieving IP4 configuration failed: invalid gateway address %s%s%s", + "(%s) retrieving IP4 configuration failed: invalid gateway address \"%s\"", nm_modem_get_uid (NM_MODEM (self)), - NM_PRINT_FMT_QUOTE_STRING (gw_string)); + gw_string); goto out; } @@ -919,26 +924,20 @@ static_stage3_ip4_done (NMModemBroadband *self) _LOGI (" address %s/%d", address_string, address.plen); - if (gw) { - guint32 ip4_route_table, ip4_route_metric; - - nm_modem_get_route_parameters (NM_MODEM (self), - &ip4_route_table, - &ip4_route_metric, - NULL, - NULL); - { - const NMPlatformIP4Route r = { - .rt_source = NM_IP_CONFIG_SOURCE_WWAN, - .gateway = gw, - .table_coerced = nm_platform_route_table_coerce (ip4_route_table), - .metric = ip4_route_metric, - }; - _LOGI (" gateway %s", gw_string); - nm_ip4_config_add_route (config, &r, NULL); - } - } + nm_modem_get_route_parameters (NM_MODEM (self), + &ip4_route_table, + &ip4_route_metric, + NULL, + NULL); + r = &(NMPlatformIP4Route) { + .rt_source = NM_IP_CONFIG_SOURCE_WWAN, + .gateway = gw, + .table_coerced = nm_platform_route_table_coerce (ip4_route_table), + .metric = ip4_route_metric, + }; + nm_ip4_config_add_route (config, r, NULL); + _LOGI (" gateway %s", gw_string); /* DNS servers */ dns = mm_bearer_ip_config_get_dns (self->_priv.ipv4_config); @@ -989,6 +988,7 @@ stage3_ip6_done (NMModemBroadband *self) g_assert (self->_priv.ipv6_config); + self->_priv.idle_id_ip6 = 0; memset (&address, 0, sizeof (address)); ip_method = get_bearer_ip_method (self->_priv.ipv6_config); diff --git a/src/devices/wwan/nm-modem.c b/src/devices/wwan/nm-modem.c index 1c32791f..010a2b60 100644 --- a/src/devices/wwan/nm-modem.c +++ b/src/devices/wwan/nm-modem.c @@ -685,9 +685,8 @@ nm_modem_stage3_ip4_config_start (NMModem *self, return NM_ACT_STAGE_RETURN_SUCCESS; if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) != 0) { - _LOGW ("unhandled WWAN IPv4 method '%s'; will fail", - method); - NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + _LOGE ("unhandled WWAN IPv4 method '%s'; will fail", method); + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED); return NM_ACT_STAGE_RETURN_FAILURE; } diff --git a/src/dhcp/nm-dhcp-client.c b/src/dhcp/nm-dhcp-client.c index 20ea092f..ea3938d6 100644 --- a/src/dhcp/nm-dhcp-client.c +++ b/src/dhcp/nm-dhcp-client.c @@ -186,19 +186,70 @@ nm_dhcp_client_get_client_id (NMDhcpClient *self) return NM_DHCP_CLIENT_GET_PRIVATE (self)->client_id; } +static void +_set_client_id (NMDhcpClient *self, GBytes *client_id, gboolean take) +{ + NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self); + + nm_assert (!client_id || g_bytes_get_size (client_id) >= 2); + + if ( priv->client_id == client_id + || ( priv->client_id + && client_id + && g_bytes_equal (priv->client_id, client_id))) { + if (take && client_id) + g_bytes_unref (client_id); + return; + } + + if (priv->client_id) + g_bytes_unref (priv->client_id); + priv->client_id = client_id; + if (!take && client_id) + g_bytes_ref (client_id); +} + void nm_dhcp_client_set_client_id (NMDhcpClient *self, GBytes *client_id) { - NMDhcpClientPrivate *priv; + g_return_if_fail (NM_IS_DHCP_CLIENT (self)); + g_return_if_fail (!client_id || g_bytes_get_size (client_id) >= 2); + + _set_client_id (self, client_id, FALSE); +} + +void +nm_dhcp_client_set_client_id_bin (NMDhcpClient *self, + guint8 type, + const guint8 *client_id, + gsize len) +{ + guint8 *buf; + GBytes *b; g_return_if_fail (NM_IS_DHCP_CLIENT (self)); + g_return_if_fail (client_id); + g_return_if_fail (len > 0); + + buf = g_malloc (len + 1); + buf[0] = type; + memcpy (buf + 1, client_id, len); + b = g_bytes_new_take (buf, len + 1); + _set_client_id (self, b, TRUE); +} - priv = NM_DHCP_CLIENT_GET_PRIVATE (self); +void +nm_dhcp_client_set_client_id_str (NMDhcpClient *self, + const char *dhcp_client_id) +{ + g_return_if_fail (NM_IS_DHCP_CLIENT (self)); + g_return_if_fail (!dhcp_client_id || dhcp_client_id[0]); - if (priv->client_id && client_id && g_bytes_equal (priv->client_id, client_id)) - return; - g_clear_pointer (&priv->client_id, g_bytes_unref); - priv->client_id = client_id ? g_bytes_ref (client_id) : NULL; + _set_client_id (self, + dhcp_client_id + ? nm_dhcp_utils_client_id_string_to_bytes (dhcp_client_id) + : NULL, + TRUE); } const char * @@ -448,7 +499,6 @@ nm_dhcp_client_start_ip4 (NMDhcpClient *self, const char *last_ip4_address) { NMDhcpClientPrivate *priv; - gs_unref_bytes GBytes *tmp = NULL; g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), FALSE); @@ -462,9 +512,7 @@ nm_dhcp_client_start_ip4 (NMDhcpClient *self, else _LOGI ("activation: beginning transaction (timeout in %u seconds)", (guint) priv->timeout); - if (dhcp_client_id) - tmp = nm_dhcp_utils_client_id_string_to_bytes (dhcp_client_id); - nm_dhcp_client_set_client_id (self, tmp); + nm_dhcp_client_set_client_id_str (self, dhcp_client_id); g_clear_pointer (&priv->hostname, g_free); priv->hostname = g_strdup (hostname); diff --git a/src/dhcp/nm-dhcp-client.h b/src/dhcp/nm-dhcp-client.h index 02804002..2c634168 100644 --- a/src/dhcp/nm-dhcp-client.h +++ b/src/dhcp/nm-dhcp-client.h @@ -173,7 +173,14 @@ gboolean nm_dhcp_client_handle_event (gpointer unused, const char *reason, NMDhcpClient *self); -void nm_dhcp_client_set_client_id (NMDhcpClient *self, GBytes *client_id); +void nm_dhcp_client_set_client_id (NMDhcpClient *self, + GBytes *client_id); +void nm_dhcp_client_set_client_id_bin (NMDhcpClient *self, + guint8 type, + const guint8 *client_id, + gsize len); +void nm_dhcp_client_set_client_id_str (NMDhcpClient *self, + const char *dhcp_client_id); /***************************************************************************** * Client data diff --git a/src/dhcp/nm-dhcp-dhclient-utils.c b/src/dhcp/nm-dhcp-dhclient-utils.c index e63e6a86..4df90d76 100644 --- a/src/dhcp/nm-dhcp-dhclient-utils.c +++ b/src/dhcp/nm-dhcp-dhclient-utils.c @@ -178,7 +178,7 @@ read_client_id (const char *str) gs_free char *s = NULL; char *p; - g_assert (!strncmp (str, CLIENTID_TAG, NM_STRLEN (CLIENTID_TAG))); + nm_assert (!strncmp (str, CLIENTID_TAG, NM_STRLEN (CLIENTID_TAG))); str += NM_STRLEN (CLIENTID_TAG); while (g_ascii_isspace (*str)) @@ -198,6 +198,9 @@ read_client_id (const char *str) if (s[strlen (s) - 1] == ';') s[strlen (s) - 1] = '\0'; + if (!s[0]) + return NULL; + return nm_dhcp_utils_client_id_string_to_bytes (s); } @@ -329,8 +332,7 @@ nm_dhcp_dhclient_create_config (const char *interface, continue; /* Otherwise capture and return the existing client id */ - if (out_new_client_id) - *out_new_client_id = read_client_id (p); + NM_SET_OUT (out_new_client_id, read_client_id (p)); } /* Override config file hostname and use one from the connection */ diff --git a/src/dhcp/nm-dhcp-systemd.c b/src/dhcp/nm-dhcp-systemd.c index 9b1a4433..f79b7cb1 100644 --- a/src/dhcp/nm-dhcp-systemd.c +++ b/src/dhcp/nm-dhcp-systemd.c @@ -489,19 +489,13 @@ _save_client_id (NMDhcpSystemd *self, const uint8_t *client_id, size_t len) { - gs_unref_bytes GBytes *b = NULL; - gs_free char *buf = NULL; - g_return_if_fail (self != NULL); g_return_if_fail (client_id != NULL); g_return_if_fail (len > 0); if (!nm_dhcp_client_get_client_id (NM_DHCP_CLIENT (self))) { - buf = g_malloc (len + 1); - buf[0] = type; - memcpy (buf + 1, client_id, len); - b = g_bytes_new (buf, len + 1); - nm_dhcp_client_set_client_id (NM_DHCP_CLIENT (self), b); + nm_dhcp_client_set_client_id_bin (NM_DHCP_CLIENT (self), + type, client_id, len); } } @@ -543,7 +537,7 @@ bound4_handle (NMDhcpSystemd *self) add_requests_to_options (options, dhcp4_requests); dhcp_lease_save (lease, priv->lease_file); - sd_dhcp_client_get_client_id(priv->client4, &type, &client_id, &client_id_len); + sd_dhcp_client_get_client_id (priv->client4, &type, &client_id, &client_id_len); if (client_id) _save_client_id (self, type, client_id, client_id_len); @@ -691,14 +685,14 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last override_client_id = nm_dhcp_client_get_client_id (client); if (override_client_id) { client_id = g_bytes_get_data (override_client_id, &client_id_len); - g_assert (client_id && client_id_len); + nm_assert (client_id && client_id_len >= 2); sd_dhcp_client_set_client_id (priv->client4, client_id[0], client_id + 1, - client_id_len - 1); + NM_MIN (client_id_len - 1, _NM_SD_MAX_CLIENT_ID_LEN)); } else if (lease) { r = sd_dhcp_lease_get_client_id (lease, (const void **) &client_id, &client_id_len); - if (r == 0 && client_id_len) { + if (r == 0 && client_id_len >= 2) { sd_dhcp_client_set_client_id (priv->client4, client_id[0], client_id + 1, diff --git a/src/dhcp/nm-dhcp-utils.c b/src/dhcp/nm-dhcp-utils.c index 4b2d57b9..50ca2abe 100644 --- a/src/dhcp/nm-dhcp-utils.c +++ b/src/dhcp/nm-dhcp-utils.c @@ -750,8 +750,15 @@ nm_dhcp_utils_client_id_string_to_bytes (const char *client_id) g_return_val_if_fail (client_id && client_id[0], NULL); /* Try as hex encoded */ - if (strchr (client_id, ':')) + if (strchr (client_id, ':')) { bytes = nm_utils_hexstr2bin (client_id); + + /* the result must be at least two bytes long, + * because @client_id contains a delimiter + * but nm_utils_hexstr2bin() does not allow + * leading nor trailing delimiters. */ + nm_assert (!bytes || g_bytes_get_size (bytes) >= 2); + } if (!bytes) { /* Fall back to string */ len = strlen (client_id); diff --git a/src/nm-config.c b/src/nm-config.c index de727c98..29f0d517 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -121,6 +121,14 @@ typedef struct { * because the state changes only on explicit actions from the daemon * itself. */ State *state; + + /* the hash table of device states. It is only loaded from disk + * once and kept immutable afterwards. + * + * We also read all state file at once. We don't want to support + * that they are changed outside of NM (at least not while NM is running). + * Hence, we read them once, that's it. */ + GHashTable *device_states; } NMConfigPrivate; struct _NMConfig { @@ -182,6 +190,33 @@ nm_config_keyfile_get_boolean (const GKeyFile *keyfile, return nm_config_parse_boolean (str, default_value); } +gint64 +nm_config_keyfile_get_int64 (const GKeyFile *keyfile, + const char *section, + const char *key, + guint base, + gint64 min, + gint64 max, + gint64 fallback) +{ + gint64 v; + int errsv; + char *str; + + g_return_val_if_fail (keyfile, fallback); + g_return_val_if_fail (section, fallback); + g_return_val_if_fail (key, fallback); + + str = g_key_file_get_value ((GKeyFile *) keyfile, section, key, NULL); + v = _nm_utils_ascii_str_to_int64 (str, base, min, max, fallback); + if (str) { + errsv = errno; + g_free (str); + errno = errsv; + } + return v; +} + char * nm_config_keyfile_get_value (const GKeyFile *keyfile, const char *section, @@ -1898,6 +1933,8 @@ _nm_config_state_set (NMConfig *self, #define DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_PERM_HW_ADDR_FAKE "perm-hw-addr-fake" #define DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_CONNECTION_UUID "connection-uuid" #define DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_NM_OWNED "nm-owned" +#define DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_ROUTE_METRIC_DEFAULT_ASPIRED "route-metric-default-aspired" +#define DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_ROUTE_METRIC_DEFAULT_EFFECTIVE "route-metric-default-effective" NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_device_state_managed_type_to_str, NMConfigDeviceStateManagedType, NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT ("unknown"), @@ -1917,47 +1954,63 @@ _config_device_state_data_new (int ifindex, GKeyFile *kf) gsize perm_hw_addr_fake_len; gint nm_owned = -1; char *p; + guint32 route_metric_default_effective; + guint32 route_metric_default_aspired; + nm_assert (kf); nm_assert (ifindex > 0); - if (kf) { - switch (nm_config_keyfile_get_boolean (kf, - DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE, - DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_MANAGED, - -1)) { - case TRUE: - managed_type = NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_MANAGED; - connection_uuid = nm_config_keyfile_get_value (kf, - DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE, - DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_CONNECTION_UUID, - NM_CONFIG_GET_VALUE_STRIP | NM_CONFIG_GET_VALUE_NO_EMPTY); - break; - case FALSE: - managed_type = NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_UNMANAGED; - break; - case -1: - /* missing property in keyfile. */ - break; - } - - perm_hw_addr_fake = nm_config_keyfile_get_value (kf, - DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE, - DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_PERM_HW_ADDR_FAKE, - NM_CONFIG_GET_VALUE_STRIP | NM_CONFIG_GET_VALUE_NO_EMPTY); - if (perm_hw_addr_fake) { - char *normalized; - - normalized = nm_utils_hwaddr_canonical (perm_hw_addr_fake, -1); - g_free (perm_hw_addr_fake); - perm_hw_addr_fake = normalized; - } - - nm_owned = nm_config_keyfile_get_boolean (kf, - DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE, - DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_NM_OWNED, - -1); + switch (nm_config_keyfile_get_boolean (kf, + DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE, + DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_MANAGED, + -1)) { + case TRUE: + managed_type = NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_MANAGED; + connection_uuid = nm_config_keyfile_get_value (kf, + DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE, + DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_CONNECTION_UUID, + NM_CONFIG_GET_VALUE_STRIP | NM_CONFIG_GET_VALUE_NO_EMPTY); + break; + case FALSE: + managed_type = NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_UNMANAGED; + break; + case -1: + /* missing property in keyfile. */ + break; } + perm_hw_addr_fake = nm_config_keyfile_get_value (kf, + DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE, + DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_PERM_HW_ADDR_FAKE, + NM_CONFIG_GET_VALUE_STRIP | NM_CONFIG_GET_VALUE_NO_EMPTY); + if (perm_hw_addr_fake) { + char *normalized; + + normalized = nm_utils_hwaddr_canonical (perm_hw_addr_fake, -1); + g_free (perm_hw_addr_fake); + perm_hw_addr_fake = normalized; + } + + nm_owned = nm_config_keyfile_get_boolean (kf, + DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE, + DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_NM_OWNED, + -1); + + /* metric zero is not a valid metric. While zero valid for IPv4, for IPv6 it is an alias + * for 1024. Since we handle here IPv4 and IPv6 the same, we cannot allow zero. */ + route_metric_default_effective = nm_config_keyfile_get_int64 (kf, + DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE, + DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_ROUTE_METRIC_DEFAULT_EFFECTIVE, + 10, 1, G_MAXUINT32, 0); + if (route_metric_default_effective) { + route_metric_default_aspired = nm_config_keyfile_get_int64 (kf, + DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE, + DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_ROUTE_METRIC_DEFAULT_EFFECTIVE, + 10, 1, route_metric_default_effective, + route_metric_default_effective); + } else + route_metric_default_aspired = 0; + connection_uuid_len = connection_uuid ? strlen (connection_uuid) + 1 : 0; perm_hw_addr_fake_len = perm_hw_addr_fake ? strlen (perm_hw_addr_fake) + 1 : 0; @@ -1970,6 +2023,8 @@ _config_device_state_data_new (int ifindex, GKeyFile *kf) device_state->connection_uuid = NULL; device_state->perm_hw_addr_fake = NULL; device_state->nm_owned = nm_owned; + device_state->route_metric_default_aspired = route_metric_default_aspired; + device_state->route_metric_default_effective = route_metric_default_effective; p = (char *) (&device_state[1]); if (connection_uuid) { @@ -2007,31 +2062,77 @@ nm_config_device_state_load (int ifindex) kf = nm_config_create_keyfile (); if (!g_key_file_load_from_file (kf, path, G_KEY_FILE_NONE, NULL)) - g_clear_pointer (&kf, g_key_file_unref); + return NULL; device_state = _config_device_state_data_new (ifindex, kf); nm_owned_str = device_state->nm_owned == TRUE ? ", nm-owned=1" : (device_state->nm_owned == FALSE ? ", nm-owned=0" : ""); - - _LOGT ("device-state: %s #%d (%s); managed=%s%s%s%s%s%s%s%s", + _LOGT ("device-state: %s #%d (%s); managed=%s%s%s%s%s%s%s%s, route-metric-default=%"G_GUINT32_FORMAT"-%"G_GUINT32_FORMAT"", kf ? "read" : "miss", ifindex, path, _device_state_managed_type_to_str (device_state->managed), NM_PRINT_FMT_QUOTED (device_state->connection_uuid, ", connection-uuid=", device_state->connection_uuid, "", ""), NM_PRINT_FMT_QUOTED (device_state->perm_hw_addr_fake, ", perm-hw-addr-fake=", device_state->perm_hw_addr_fake, "", ""), - nm_owned_str); + nm_owned_str, + device_state->route_metric_default_aspired, + device_state->route_metric_default_effective); return device_state; } +static int +_device_state_parse_filename (const char *filename) +{ + if (!filename || !filename[0]) + return 0; + if (!NM_STRCHAR_ALL (filename, ch, g_ascii_isdigit (ch))) + return 0; + return _nm_utils_ascii_str_to_int64 (filename, 10, 1, G_MAXINT, 0); +} + +GHashTable * +nm_config_device_state_load_all (void) +{ + GHashTable *states; + GDir *dir; + const char *fn; + int ifindex; + + states = g_hash_table_new_full (nm_direct_hash, NULL, NULL, g_free); + + dir = g_dir_open (NM_CONFIG_DEVICE_STATE_DIR, 0, NULL); + if (!dir) + return states; + + while ((fn = g_dir_read_name (dir))) { + NMConfigDeviceStateData *state; + + ifindex = _device_state_parse_filename (fn); + if (ifindex <= 0) + continue; + + state = nm_config_device_state_load (ifindex); + if (!state) + continue; + + if (!nm_g_hash_table_insert (states, GINT_TO_POINTER (ifindex), state)) + nm_assert_not_reached (); + } + g_dir_close (dir); + + return states; +} + gboolean nm_config_device_state_write (int ifindex, NMConfigDeviceStateManagedType managed, const char *perm_hw_addr_fake, const char *connection_uuid, - gint nm_owned) + gint nm_owned, + guint32 route_metric_default_aspired, + guint32 route_metric_default_effective) { char path[NM_STRLEN (NM_CONFIG_DEVICE_STATE_DIR) + 60]; GError *local = NULL; @@ -2073,17 +2174,31 @@ nm_config_device_state_write (int ifindex, nm_owned); } + if (route_metric_default_effective != 0) { + g_key_file_set_int64 (kf, + DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE, + DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_ROUTE_METRIC_DEFAULT_EFFECTIVE, + route_metric_default_effective); + if (route_metric_default_aspired != route_metric_default_effective) { + g_key_file_set_int64 (kf, + DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE, + DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_ROUTE_METRIC_DEFAULT_ASPIRED, + route_metric_default_aspired); + } + } if (!g_key_file_save_to_file (kf, path, &local)) { _LOGW ("device-state: write #%d (%s) failed: %s", ifindex, path, local->message); g_error_free (local); return FALSE; } - _LOGT ("device-state: write #%d (%s); managed=%s%s%s%s%s%s%s", + _LOGT ("device-state: write #%d (%s); managed=%s%s%s%s%s%s%s, route-metric-default=%"G_GUINT32_FORMAT"-%"G_GUINT32_FORMAT"", ifindex, path, _device_state_managed_type_to_str (managed), NM_PRINT_FMT_QUOTED (connection_uuid, ", connection-uuid=", connection_uuid, "", ""), - NM_PRINT_FMT_QUOTED (perm_hw_addr_fake, ", perm-hw-addr-fake=", perm_hw_addr_fake, "", "")); + NM_PRINT_FMT_QUOTED (perm_hw_addr_fake, ", perm-hw-addr-fake=", perm_hw_addr_fake, "", ""), + route_metric_default_aspired, + route_metric_default_effective); return TRUE; } @@ -2094,7 +2209,6 @@ nm_config_device_state_prune_unseen (GHashTable *seen_ifindexes) const char *fn; int ifindex; gsize fn_len; - gsize i; char buf[NM_STRLEN (NM_CONFIG_DEVICE_STATE_DIR"/") + 30 + 3] = NM_CONFIG_DEVICE_STATE_DIR"/"; char *buf_p = &buf[NM_STRLEN (NM_CONFIG_DEVICE_STATE_DIR"/")]; @@ -2105,24 +2219,20 @@ nm_config_device_state_prune_unseen (GHashTable *seen_ifindexes) return; while ((fn = g_dir_read_name (dir))) { - fn_len = strlen (fn); - - /* skip over file names that are not plain integers. */ - for (i = 0; i < fn_len; i++) { - if (!g_ascii_isdigit (fn[i])) - break; - } - if (fn_len == 0 || i != fn_len) + ifindex = _device_state_parse_filename (fn); + if (ifindex <= 0) continue; - - ifindex = _nm_utils_ascii_str_to_int64 (fn, 10, 1, G_MAXINT, 0); - if (!ifindex) - continue; - if (g_hash_table_contains (seen_ifindexes, GINT_TO_POINTER (ifindex))) continue; - memcpy (buf_p, fn, fn_len + 1); + fn_len = strlen (fn) + 1; + nm_assert (&buf_p[fn_len] < &buf[G_N_ELEMENTS (buf)]); + memcpy (buf_p, fn, fn_len); + nm_assert (({ + char bb[30]; + nm_sprintf_buf (bb, "%d", ifindex); + nm_streq0 (bb, buf_p); + })); _LOGT ("device-state: prune #%d (%s)", ifindex, buf); (void) unlink (buf); } @@ -2132,6 +2242,46 @@ nm_config_device_state_prune_unseen (GHashTable *seen_ifindexes) /*****************************************************************************/ +static GHashTable * +_device_state_get_all (NMConfig *self) +{ + NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (self); + + if (G_UNLIKELY (!priv->device_states)) + priv->device_states = nm_config_device_state_load_all (); + return priv->device_states; +} + +/** + * nm_config_device_state_get_all: + * @self: the #NMConfig + * + * This function exists to give convenient access to all + * device states. Do not ever try to modify the returned + * hash, it's supposed to be immutable. + * + * Returns: the internal #GHashTable object with all device states. + */ +const GHashTable * +nm_config_device_state_get_all (NMConfig *self) +{ + g_return_val_if_fail (NM_IS_CONFIG (self), NULL); + + return _device_state_get_all (self); +} + +const NMConfigDeviceStateData * +nm_config_device_state_get (NMConfig *self, + int ifindex) +{ + g_return_val_if_fail (NM_IS_CONFIG (self), NULL); + g_return_val_if_fail (ifindex > 0 , NULL); + + return g_hash_table_lookup (_device_state_get_all (self), GINT_TO_POINTER (ifindex)); +} + +/*****************************************************************************/ + void nm_config_reload (NMConfig *self, NMConfigChangeFlags reload_flags) { diff --git a/src/nm-config.h b/src/nm-config.h index 8bdd5002..42ab4682 100644 --- a/src/nm-config.h +++ b/src/nm-config.h @@ -165,6 +165,13 @@ gint nm_config_keyfile_get_boolean (const GKeyFile *keyfile, const char *section, const char *key, gint default_value); +gint64 nm_config_keyfile_get_int64 (const GKeyFile *keyfile, + const char *section, + const char *key, + guint base, + gint64 min, + gint64 max, + gint64 fallback); char *nm_config_keyfile_get_value (const GKeyFile *keyfile, const char *section, const char *key, @@ -205,6 +212,10 @@ struct _NMConfigDeviceStateData { int ifindex; NMConfigDeviceStateManagedType managed; + /* a value of zero means that no metric is set. */ + guint32 route_metric_default_aspired; + guint32 route_metric_default_effective; + /* the UUID of the last settings-connection active * on the device. */ const char *connection_uuid; @@ -213,17 +224,25 @@ struct _NMConfigDeviceStateData { /* whether the device was nm-owned (0/1) or -1 for * non-software devices. */ - gint nm_owned; + int nm_owned:3; }; NMConfigDeviceStateData *nm_config_device_state_load (int ifindex); +GHashTable *nm_config_device_state_load_all (void); gboolean nm_config_device_state_write (int ifindex, NMConfigDeviceStateManagedType managed, const char *perm_hw_addr_fake, const char *connection_uuid, - gint nm_owned); + gint nm_owned, + guint32 route_metric_default_aspired, + guint32 route_metric_default_effective); + void nm_config_device_state_prune_unseen (GHashTable *seen_ifindexes); +const GHashTable *nm_config_device_state_get_all (NMConfig *self); +const NMConfigDeviceStateData *nm_config_device_state_get (NMConfig *self, + int ifindex); + /*****************************************************************************/ #endif /* __NETWORKMANAGER_CONFIG_H__ */ diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c index 40a0c352..f6b33a14 100644 --- a/src/nm-core-utils.c +++ b/src/nm-core-utils.c @@ -1960,8 +1960,7 @@ nm_utils_resolve_conf_parse (int addr_family, gsize i_tokens; tokens = nm_utils_strsplit_set (s, " \t"); - nm_assert (tokens); - for (i_tokens = 0; tokens[i_tokens]; i_tokens++) { + for (i_tokens = 0; tokens && tokens[i_tokens]; i_tokens++) { gs_free char *t = g_strstrip (g_strdup (tokens[i_tokens])); if ( _nm_utils_dns_option_validate (t, NULL, NULL, diff --git a/src/nm-manager.c b/src/nm-manager.c index 7f1b9a9d..001fae55 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -160,6 +160,8 @@ typedef struct { NMAuthManager *auth_mgr; + GHashTable *device_route_metrics; + GSList *auth_chains; GHashTable *sleep_devices; @@ -324,6 +326,250 @@ static NM_CACHED_QUARK_FCN ("autoconnect-root", autoconnect_root_quark) /*****************************************************************************/ +typedef struct { + int ifindex; + guint32 aspired_metric; + guint32 effective_metric; +} DeviceRouteMetricData; + +static DeviceRouteMetricData * +_device_route_metric_data_new (int ifindex, guint32 aspired_metric, guint32 effective_metric) +{ + DeviceRouteMetricData *data; + + nm_assert (ifindex > 0); + + /* For IPv4, metrics can use the entire uint32 bit range. For IPv6, + * zero is treated like 1024. Since we handle IPv4 and IPv6 identically, + * we cannot allow a zero metric here. + */ + nm_assert (aspired_metric > 0); + nm_assert (effective_metric == 0 || aspired_metric <= effective_metric); + + data = g_slice_new0 (DeviceRouteMetricData); + data->ifindex = ifindex; + data->aspired_metric = aspired_metric; + data->effective_metric = effective_metric ?: aspired_metric; + return data; +} + +static guint +_device_route_metric_data_by_ifindex_hash (gconstpointer p) +{ + const DeviceRouteMetricData *data = p; + NMHashState h; + + nm_hash_init (&h, 1030338191); + nm_hash_update_vals (&h, data->ifindex); + return nm_hash_complete (&h); +} + +static gboolean +_device_route_metric_data_by_ifindex_equal (gconstpointer pa, gconstpointer pb) +{ + const DeviceRouteMetricData *a = pa; + const DeviceRouteMetricData *b = pb; + + return a->ifindex == b->ifindex; +} + +static guint32 +_device_route_metric_get (NMManager *self, + int ifindex, + NMDeviceType device_type, + gboolean lookup_only, + guint32 *out_aspired_metric) +{ + NMManagerPrivate *priv; + const DeviceRouteMetricData *d2; + DeviceRouteMetricData *data; + DeviceRouteMetricData data_lookup; + const NMDedupMultiHeadEntry *all_links_head; + NMPObject links_needle; + guint n_links; + gboolean cleaned = FALSE; + GHashTableIter h_iter; + guint32 metric; + + g_return_val_if_fail (NM_IS_MANAGER (self), 0); + + NM_SET_OUT (out_aspired_metric, 0); + + if (ifindex <= 0) { + if (lookup_only) + return 0; + metric = nm_device_get_route_metric_default (device_type); + NM_SET_OUT (out_aspired_metric, metric); + return metric; + } + + priv = NM_MANAGER_GET_PRIVATE (self); + + if ( lookup_only + && !priv->device_route_metrics) + return 0; + + if (G_UNLIKELY (!priv->device_route_metrics)) { + const GHashTable *h; + const NMConfigDeviceStateData *device_state; + + priv->device_route_metrics = g_hash_table_new_full (_device_route_metric_data_by_ifindex_hash, + _device_route_metric_data_by_ifindex_equal, + NULL, + nm_g_slice_free_fcn (DeviceRouteMetricData)); + cleaned = TRUE; + + /* we need to pre-populate the cache for all (still existing) devices from the state-file */ + h = nm_config_device_state_get_all (priv->config); + if (!h) + goto initited; + + g_hash_table_iter_init (&h_iter, (GHashTable *) h); + while (g_hash_table_iter_next (&h_iter, NULL, (gpointer *) &device_state)) { + if (!device_state->route_metric_default_effective) + continue; + if (!nm_platform_link_get (priv->platform, device_state->ifindex)) { + /* we have the entry in the state file, but (currently) no such + * ifindex exists in platform. Most likely the entry is obsolete, + * hence we skip it. */ + continue; + } + if (!nm_g_hash_table_add (priv->device_route_metrics, + _device_route_metric_data_new (device_state->ifindex, + device_state->route_metric_default_aspired, + device_state->route_metric_default_effective))) + nm_assert_not_reached (); + } + } + +initited: + data_lookup.ifindex = ifindex; + + data = g_hash_table_lookup (priv->device_route_metrics, &data_lookup); + if (data) + goto out; + if (lookup_only) + return 0; + + if (!cleaned) { + /* get the number of all links in the platform cache. */ + all_links_head = nm_platform_lookup_all (priv->platform, + NMP_CACHE_ID_TYPE_OBJECT_TYPE, + nmp_object_stackinit_id_link (&links_needle, 1)); + n_links = all_links_head ? all_links_head->len : 0; + + /* on systems where a lot of devices are created and go away, the index contains + * a lot of stale entries. We must from time to time clean them up. + * + * Do do this cleanup, whenever we have more enties then 2 times the number of links. */ + if (G_UNLIKELY (g_hash_table_size (priv->device_route_metrics) > NM_MAX (20, n_links * 2))) { + /* from time to time, we need to do some house-keeping and prune stale entries. + * Otherwise, on a system where interfaces frequently come and go (docker), we + * keep growing this cache for ifindexes that no longer exist. */ + g_hash_table_iter_init (&h_iter, priv->device_route_metrics); + while (g_hash_table_iter_next (&h_iter, NULL, (gpointer *) &d2)) { + if (!nm_platform_link_get (priv->platform, d2->ifindex)) + g_hash_table_iter_remove (&h_iter); + } + cleaned = TRUE; + } + } + + data = _device_route_metric_data_new (ifindex, nm_device_get_route_metric_default (device_type), 0); + + /* unfortunately, there is no stright forward way to lookup all reserved metrics. + * Note, that we don't only have to know which metrics are currently reserved, + * but also, which metrics are now seemingly un-used but caused another reserved + * metric to be bumped. Hence, the naive O(n^2) search :( + * + * Well, technically, since we limit bumping the metric to 50, this entire + * loop runs at most 50 times, so it's still O(n). Let's just say, it's not + * very efficient. */ +again: + g_hash_table_iter_init (&h_iter, priv->device_route_metrics); + while (g_hash_table_iter_next (&h_iter, NULL, (gpointer *) &d2)) { + if ( data->effective_metric < d2->aspired_metric + || data->effective_metric > d2->effective_metric) { + /* no overlap. Skip. */ + continue; + } + if ( !cleaned + && !nm_platform_link_get (priv->platform, d2->ifindex)) { + /* the metric seems taken, but there is no such interface. This entry + * is stale, forget about it. */ + g_hash_table_iter_remove (&h_iter); + continue; + } + + if (d2->effective_metric == G_MAXUINT32) { + /* we cannot bump the metric any further. Done. + * + * Actually, this can currently not happen because the aspired_metric + * are small numbers and we limit the bumping to 50. Still, for + * completeness... */ + data->effective_metric = G_MAXUINT32; + break; + } + + if (d2->effective_metric - data->aspired_metric >= 50) { + /* as one active interface reserves an entire range of metrics + * (from aspired_metric to effective_metric), that means if you + * alternatingly activate two interfaces, their metric will + * bump each other. + * + * Limit this, bump the metric at most 50 points. */ + data->effective_metric = data->aspired_metric + 50; + break; + } + + /* bump the metric, and search again. */ + data->effective_metric = d2->effective_metric + 1; + goto again; + } + + _LOGT (LOGD_DEVICE, "default-route-metric: ifindex %d reserves metric %u (aspired %u)", + data->ifindex, data->effective_metric, data->aspired_metric); + + if (!nm_g_hash_table_add (priv->device_route_metrics, data)) + nm_assert_not_reached (); + +out: + NM_SET_OUT (out_aspired_metric, data->aspired_metric); + return data->effective_metric; +} + +guint32 +nm_manager_device_route_metric_reserve (NMManager *self, + int ifindex, + NMDeviceType device_type) +{ + guint32 metric; + + metric = _device_route_metric_get (self, ifindex, device_type, FALSE, NULL); + nm_assert (metric != 0); + return metric; +} + +void +nm_manager_device_route_metric_clear (NMManager *self, + int ifindex) +{ + NMManagerPrivate *priv; + DeviceRouteMetricData data_lookup; + + priv = NM_MANAGER_GET_PRIVATE (self); + + if (!priv->device_route_metrics) + return; + data_lookup.ifindex = ifindex; + if (g_hash_table_remove (priv->device_route_metrics, &data_lookup)) { + _LOGT (LOGD_DEVICE, "default-route-metric: ifindex %d released", + ifindex); + } +} + +/*****************************************************************************/ + static void _delete_volatile_connection_do (NMManager *self, NMSettingsConnection *connection) @@ -2640,10 +2886,9 @@ platform_query_devices (NMManager *self) return; for (i = 0; i < links->len; i++) { const NMPlatformLink *link = NMP_OBJECT_CAST_LINK (links->pdata[i]); - gs_free NMConfigDeviceStateData *dev_state = NULL; - - dev_state = nm_config_device_state_load (link->ifindex); + const NMConfigDeviceStateData *dev_state; + dev_state = nm_config_device_state_get (priv->config, link->ifindex); platform_link_added (self, link->ifindex, link, @@ -5199,6 +5444,8 @@ nm_manager_write_device_state (NMManager *self) const char *uuid = NULL; const char *perm_hw_addr_fake = NULL; gboolean perm_hw_addr_is_fake; + guint32 route_metric_default_aspired; + guint32 route_metric_default_effective; ifindex = nm_device_get_ip_ifindex (device); if (ifindex <= 0) @@ -5228,11 +5475,16 @@ nm_manager_write_device_state (NMManager *self) nm_owned = nm_device_is_software (device) ? nm_device_is_nm_owned (device) : -1; + route_metric_default_effective = _device_route_metric_get (self, ifindex, NM_DEVICE_TYPE_UNKNOWN, + TRUE, &route_metric_default_aspired); + if (nm_config_device_state_write (ifindex, managed_type, perm_hw_addr_fake, uuid, - nm_owned)) + nm_owned, + route_metric_default_aspired, + route_metric_default_effective)) g_hash_table_add (seen_ifindexes, GINT_TO_POINTER (ifindex)); } @@ -6400,7 +6652,7 @@ get_property (GObject *object, guint prop_id, #else vbool = FALSE; #endif - g_value_set_boolean (value, FALSE); + g_value_set_boolean (value, vbool); break; case PROP_PRIMARY_CONNECTION: nm_utils_g_value_set_object_path (value, priv->primary_connection); @@ -6604,6 +6856,8 @@ dispose (GObject *object) nm_clear_g_source (&priv->timestamp_update_id); + g_clear_pointer (&priv->device_route_metrics, g_hash_table_destroy); + G_OBJECT_CLASS (nm_manager_parent_class)->dispose (object); } diff --git a/src/nm-manager.h b/src/nm-manager.h index 2d463c71..b4587e08 100644 --- a/src/nm-manager.h +++ b/src/nm-manager.h @@ -114,6 +114,13 @@ NMDevice * nm_manager_get_device_by_ifindex (NMManager *manager, NMDevice * nm_manager_get_device_by_path (NMManager *manager, const char *path); +guint32 nm_manager_device_route_metric_reserve (NMManager *self, + int ifindex, + NMDeviceType device_type); + +void nm_manager_device_route_metric_clear (NMManager *self, + int ifindex); + char * nm_manager_get_connection_iface (NMManager *self, NMConnection *connection, NMDevice **out_parent, diff --git a/src/nm-policy.c b/src/nm-policy.c index 8dfb0ab0..4d0ef91a 100644 --- a/src/nm-policy.c +++ b/src/nm-policy.c @@ -1409,7 +1409,7 @@ reset_autoconnect_all (NMPolicy *self, NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); NMSettingsConnection *const*connections = NULL; guint i; - gboolean changed; + gboolean changed = FALSE; _LOGD (LOGD_DEVICE, "re-enabling autoconnect for all connections%s%s%s", device ? " on " : "", diff --git a/src/nm-types.h b/src/nm-types.h index cc657397..02163f87 100644 --- a/src/nm-types.h +++ b/src/nm-types.h @@ -25,6 +25,8 @@ #error "nm-utils-private.h" must not be used outside of libnm-core/. Do you want "nm-core-internal.h"? #endif +#define _NM_SD_MAX_CLIENT_ID_LEN (sizeof (guint32) + 128) + /* core */ typedef struct _NMExportedObject NMExportedObject; typedef struct _NMActiveConnection NMActiveConnection; diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 10d1a6ef..fe270e88 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -4680,7 +4680,10 @@ do_delete_object (NMPlatform *platform, const NMPObject *obj_id, struct nl_msg * wait_for_nl_response_to_string (seq_result, s_buf, sizeof (s_buf)), log_detail); - if (NMP_OBJECT_GET_TYPE (obj_id) == NMP_OBJECT_TYPE_IP6_ADDRESS) { + if (NM_IN_SET (NMP_OBJECT_GET_TYPE (obj_id), + NMP_OBJECT_TYPE_IP6_ADDRESS, + NMP_OBJECT_TYPE_QDISC, + NMP_OBJECT_TYPE_TFILTER)) { /* In rare cases, the object is still there after we receive the ACK from * kernel. Need to refetch. * @@ -6413,7 +6416,7 @@ ip_route_get (NMPlatform *platform, int try_count = 0; WaitForNlResponseResult seq_result; int nle; - nm_auto_nlmsg NMPObject *route = NULL; + nm_auto_nmpobj NMPObject *route = NULL; nm_assert (NM_IS_LINUX_PLATFORM (platform)); nm_assert (NM_IN_SET (addr_family, AF_INET, AF_INET6)); diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index 2ca379e4..c7ed90e3 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -667,6 +667,7 @@ skip: /* There is a loop, pop the first (remaining) element from the list. * This can happen for veth pairs where each peer is parent of the other end. */ item = NMP_OBJECT_CAST_LINK (links->pdata[first_idx]); + nm_assert (item); g_hash_table_remove (unseen, GINT_TO_POINTER (item->ifindex)); g_ptr_array_add (result, links->pdata[first_idx]); links->pdata[first_idx] = NULL; @@ -5320,7 +5321,7 @@ nm_platform_qdisc_to_string (const NMPlatformQdisc *qdisc, char *buf, gsize len) void nm_platform_qdisc_hash_update (const NMPlatformQdisc *obj, NMHashState *h) { - nm_hash_update_str (h, obj->kind); + nm_hash_update_str0 (h, obj->kind); nm_hash_update_vals (h, obj->ifindex, obj->addr_family, @@ -5387,17 +5388,17 @@ nm_platform_tfilter_to_string (const NMPlatformTfilter *tfilter, char *buf, gsiz void nm_platform_tfilter_hash_update (const NMPlatformTfilter *obj, NMHashState *h) { - nm_hash_update_str (h, obj->kind); + nm_hash_update_str0 (h, obj->kind); nm_hash_update_vals (h, obj->ifindex, obj->addr_family, obj->handle, obj->parent, obj->info); - nm_hash_update_str (h, obj->action.kind); if (obj->action.kind) { + nm_hash_update_str (h, obj->action.kind); if (nm_streq (obj->action.kind, NM_PLATFORM_ACTION_KIND_SIMPLE)) - nm_hash_update_str (h, obj->action.simple.sdata); + nm_hash_update_strarr (h, obj->action.simple.sdata); } } diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c index b6e89404..37a0b3a6 100644 --- a/src/settings/nm-settings-connection.c +++ b/src/settings/nm-settings-connection.c @@ -517,6 +517,7 @@ set_persist_mode (NMSettingsConnection *self, NMSettingsConnectionPersistMode pe TRUE); return; case NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP: + case NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP_SAVED: /* Nothing to do */ return; } @@ -793,7 +794,7 @@ nm_settings_connection_delete (NMSettingsConnection *self, /* Remove connection from seen-bssids database file */ remove_entry_from_db (self, "seen-bssids"); - nm_settings_connection_signal_remove (self, FALSE); + nm_settings_connection_signal_remove (self); return TRUE; } @@ -2187,15 +2188,24 @@ impl_settings_connection_clear_secrets (NMSettingsConnection *self, /*****************************************************************************/ void -nm_settings_connection_signal_remove (NMSettingsConnection *self, gboolean allow_reuse) +nm_settings_connection_added (NMSettingsConnection *self) { NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); - if (!allow_reuse) { - if (priv->removed) - g_return_if_reached (); - priv->removed = TRUE; - } + /* FIXME: we should always dispose connections that are removed + * and not reuse them, but currently plugins keep alive unmanaged + * (e.g. NM_CONTROLLED=no) connections. */ + priv->removed = FALSE; +} + +void +nm_settings_connection_signal_remove (NMSettingsConnection *self) +{ + NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); + + if (priv->removed) + return; + priv->removed = TRUE; g_signal_emit_by_name (self, NM_SETTINGS_CONNECTION_REMOVED); } diff --git a/src/settings/nm-settings-connection.h b/src/settings/nm-settings-connection.h index fc8ad1de..29ec05dd 100644 --- a/src/settings/nm-settings-connection.h +++ b/src/settings/nm-settings-connection.h @@ -137,6 +137,9 @@ gboolean nm_settings_connection_has_unmodified_applied_connection (NMSettingsCon typedef enum { NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP, + + /* like KEEP, but always clears the UNSAVED flag */ + NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP_SAVED, NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK, /* unsaved, only sets the unsaved flag, but it doesn't touch @@ -190,7 +193,9 @@ void nm_settings_connection_recheck_visibility (NMSettingsConnection *self); gboolean nm_settings_connection_check_permission (NMSettingsConnection *self, const char *permission); -void nm_settings_connection_signal_remove (NMSettingsConnection *self, gboolean allow_reuse); +void nm_settings_connection_added (NMSettingsConnection *self); + +void nm_settings_connection_signal_remove (NMSettingsConnection *self); gboolean nm_settings_connection_get_unsaved (NMSettingsConnection *self); diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c index 21fdf9e0..51b7bea7 100644 --- a/src/settings/nm-settings.c +++ b/src/settings/nm-settings.c @@ -89,21 +89,6 @@ EXPORT(nm_settings_connection_update) /*****************************************************************************/ static NM_CACHED_QUARK_FCN ("plugin-module-path", plugin_module_path_quark) - -#if (defined(HOSTNAME_PERSIST_SUSE) + defined(HOSTNAME_PERSIST_SLACKWARE) + defined(HOSTNAME_PERSIST_GENTOO)) > 1 -#error "Can only define one of HOSTNAME_PERSIST_*" -#endif - -#if defined(HOSTNAME_PERSIST_SUSE) -#define HOSTNAME_FILE HOSTNAME_FILE_UCASE_HOSTNAME -#elif defined(HOSTNAME_PERSIST_SLACKWARE) -#define HOSTNAME_FILE HOSTNAME_FILE_UCASE_HOSTNAME -#elif defined(HOSTNAME_PERSIST_GENTOO) -#define HOSTNAME_FILE HOSTNAME_FILE_GENTOO -#else -#define HOSTNAME_FILE HOSTNAME_FILE_DEFAULT -#endif - static NM_CACHED_QUARK_FCN ("default-wired-connection", _default_wired_connection_quark) static NM_CACHED_QUARK_FCN ("default-wired-device", _default_wired_device_quark) @@ -1004,6 +989,8 @@ claim_connection (NMSettings *self, NMSettingsConnection *connection) /* Exported D-Bus signal */ g_signal_emit (self, signals[NEW_CONNECTION], 0, connection); } + + nm_settings_connection_added (connection); } static gboolean diff --git a/src/settings/plugins/ibft/nms-ibft-connection.c b/src/settings/plugins/ibft/nms-ibft-connection.c index 2a7c5f4a..fb7f18f8 100644 --- a/src/settings/plugins/ibft/nms-ibft-connection.c +++ b/src/settings/plugins/ibft/nms-ibft-connection.c @@ -62,7 +62,7 @@ nms_ibft_connection_new (const GPtrArray *block, GError **error) /* Update settings with what was read from iscsiadm */ if (!nm_settings_connection_update (NM_SETTINGS_CONNECTION (object), source, - NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP, + NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP_SAVED, NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, NULL, error)) diff --git a/src/settings/plugins/ifcfg-rh/nm-inotify-helper.c b/src/settings/plugins/ifcfg-rh/nm-inotify-helper.c index 4c65b02d..97417db9 100644 --- a/src/settings/plugins/ifcfg-rh/nm-inotify-helper.c +++ b/src/settings/plugins/ifcfg-rh/nm-inotify-helper.c @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * (C) Copyright 2008 Red Hat, Inc. + * (C) Copyright 2008 - 2017 Red Hat, Inc. */ #include "nm-default.h" @@ -44,6 +44,7 @@ static guint signals[LAST_SIGNAL] = { 0 }; typedef struct { int ifd; + guint inotify_id; GHashTable *wd_refs; } NMInotifyHelperPrivate; @@ -142,7 +143,6 @@ init_inotify (NMInotifyHelper *self) { NMInotifyHelperPrivate *priv = NM_INOTIFY_HELPER_GET_PRIVATE (self); GIOChannel *channel; - guint source_id; priv->ifd = inotify_init1 (IN_CLOEXEC); if (priv->ifd == -1) { @@ -157,10 +157,10 @@ init_inotify (NMInotifyHelper *self) g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, NULL); g_io_channel_set_encoding (channel, NULL, NULL); - source_id = g_io_add_watch (channel, - G_IO_IN | G_IO_ERR, - (GIOFunc) inotify_event_handler, - (gpointer) self); + priv->inotify_id = g_io_add_watch (channel, + G_IO_IN | G_IO_ERR, + (GIOFunc) inotify_event_handler, + (gpointer) self); g_io_channel_unref (channel); return TRUE; } @@ -188,6 +188,7 @@ finalize (GObject *object) { NMInotifyHelperPrivate *priv = NM_INOTIFY_HELPER_GET_PRIVATE ((NMInotifyHelper *) object); + nm_clear_g_source (&priv->inotify_id); nm_close (priv->ifd); g_hash_table_destroy (priv->wd_refs); diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-connection.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-connection.c index 3cf5c978..6979fdaa 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-connection.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-connection.c @@ -442,7 +442,7 @@ nm_ifcfg_connection_new (NMConnection *source, if (nm_settings_connection_update (NM_SETTINGS_CONNECTION (object), tmp, full_path - ? NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP /* connection is already on disk */ + ? NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP_SAVED : NM_SETTINGS_CONNECTION_PERSIST_MODE_UNSAVED, NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, NULL, diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c index 04e74bbd..0743fc9f 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c @@ -161,7 +161,7 @@ remove_connection (SettingsPluginIfcfg *self, NMIfcfgConnection *connection) g_object_ref (connection); g_hash_table_remove (priv->connections, nm_connection_get_uuid (NM_CONNECTION (connection))); if (!unmanaged && !unrecognized) - nm_settings_connection_signal_remove (NM_SETTINGS_CONNECTION (connection), FALSE); + nm_settings_connection_signal_remove (NM_SETTINGS_CONNECTION (connection)); g_object_unref (connection); /* Emit changes _after_ removing the connection */ @@ -315,7 +315,7 @@ update_connection (SettingsPluginIfcfg *self, if (!nm_settings_connection_update (NM_SETTINGS_CONNECTION (connection_by_uuid), NM_CONNECTION (connection_new), - NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP, + NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP_SAVED, NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, "ifcfg-update", &local)) { @@ -331,7 +331,7 @@ update_connection (SettingsPluginIfcfg *self, /* Unexport the connection by telling the settings service it's * been removed. */ - nm_settings_connection_signal_remove (NM_SETTINGS_CONNECTION (connection_by_uuid), TRUE); + nm_settings_connection_signal_remove (NM_SETTINGS_CONNECTION (connection_by_uuid)); /* Remove the path so that claim_connection() doesn't complain later when * interface gets managed and connection is re-added. */ nm_connection_set_path (NM_CONNECTION (connection_by_uuid), NULL); diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c index b9900eec..bdd3ee0a 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -294,6 +294,23 @@ make_connection_setting (const char *file, check_if_team_slave (ifcfg, s_con); nm_clear_g_free (&value); + v = svGetValueStr (ifcfg, "OVS_PORT_UUID", &value); + if (!v) + v = svGetValueStr (ifcfg, "OVS_PORT", &value); + if (v) { + const char *old_value; + + if ((old_value = nm_setting_connection_get_master (s_con))) { + PARSE_WARNING ("Already configured as slave of %s. Ignoring OVS_PORT=\"%s\"", + old_value, v); + } else { + g_object_set (s_con, NM_SETTING_CONNECTION_MASTER, v, NULL); + g_object_set (s_con, NM_SETTING_CONNECTION_SLAVE_TYPE, + NM_SETTING_OVS_PORT_SETTING_NAME, NULL); + } + } + + nm_clear_g_free (&value); v = svGetValueStr (ifcfg, "GATEWAY_PING_TIMEOUT", &value); if (v) { gint64 tmp; diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c index 5cb8ee98..e9dd08b7 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c @@ -1832,6 +1832,12 @@ write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg) NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_VLAN_SETTING_NAME)) svUnsetValue (ifcfg, "TYPE"); + } else if (nm_setting_connection_is_slave_type (s_con, NM_SETTING_OVS_PORT_SETTING_NAME)) { + svSetValueStr (ifcfg, "OVS_PORT_UUID", master); + svSetValueStr (ifcfg, "OVS_PORT", master_iface); + } else { + _LOGW ("don't know how to set master for a %s slave", + nm_setting_connection_get_slave_type (s_con)); } } diff --git a/src/settings/plugins/ifnet/nms-ifnet-connection.c b/src/settings/plugins/ifnet/nms-ifnet-connection.c index e7cd19cd..ce0b3f2b 100644 --- a/src/settings/plugins/ifnet/nms-ifnet-connection.c +++ b/src/settings/plugins/ifnet/nms-ifnet-connection.c @@ -190,7 +190,7 @@ nm_ifnet_connection_new (NMConnection *source, const char *conn_name) tmp, update_unsaved ? NM_SETTINGS_CONNECTION_PERSIST_MODE_UNSAVED - : NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP, + : NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP_SAVED, NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, NULL, NULL)) { diff --git a/src/settings/plugins/ifnet/nms-ifnet-plugin.c b/src/settings/plugins/ifnet/nms-ifnet-plugin.c index 38d23f30..8332358f 100644 --- a/src/settings/plugins/ifnet/nms-ifnet-plugin.c +++ b/src/settings/plugins/ifnet/nms-ifnet-plugin.c @@ -262,7 +262,7 @@ reload_connections (NMSettingsPlugin *config) NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)) { nm_log_info (LOGD_SETTINGS, "Auto refreshing %s", conn_name); - nm_settings_connection_signal_remove (NM_SETTINGS_CONNECTION (old), FALSE); + nm_settings_connection_signal_remove (NM_SETTINGS_CONNECTION (old)); track_new_connection (self, new); if (is_managed_plugin () && is_managed (conn_name)) g_signal_emit_by_name (self, NM_SETTINGS_PLUGIN_CONNECTION_ADDED, new); @@ -271,7 +271,7 @@ reload_connections (NMSettingsPlugin *config) /* Update existing connection with new settings */ if (!nm_settings_connection_update (NM_SETTINGS_CONNECTION (old), NM_CONNECTION (new), - NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP, + NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP_SAVED, NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, "ifnet-update", &error)) { @@ -305,7 +305,7 @@ reload_connections (NMSettingsPlugin *config) */ if ( nm_ifnet_connection_get_conn_name (NM_IFNET_CONNECTION (candidate)) && !g_hash_table_lookup (new_connections, uuid)) { - nm_settings_connection_signal_remove (candidate, FALSE); + nm_settings_connection_signal_remove (candidate); g_hash_table_iter_remove (&iter); } } diff --git a/src/settings/plugins/keyfile/nms-keyfile-connection.c b/src/settings/plugins/keyfile/nms-keyfile-connection.c index 5a6d8a76..5f72a9fa 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-connection.c +++ b/src/settings/plugins/keyfile/nms-keyfile-connection.c @@ -163,7 +163,7 @@ nms_keyfile_connection_new (NMConnection *source, tmp, update_unsaved ? NM_SETTINGS_CONNECTION_PERSIST_MODE_UNSAVED - : NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP, + : NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP_SAVED, NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, NULL, error)) { diff --git a/src/settings/plugins/keyfile/nms-keyfile-plugin.c b/src/settings/plugins/keyfile/nms-keyfile-plugin.c index bc64b3ca..cb5f2c9f 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-plugin.c +++ b/src/settings/plugins/keyfile/nms-keyfile-plugin.c @@ -107,7 +107,7 @@ remove_connection (NMSKeyfilePlugin *self, NMSKeyfileConnection *connection) g_signal_handlers_disconnect_by_func (connection, connection_removed_cb, self); removed = g_hash_table_remove (NMS_KEYFILE_PLUGIN_GET_PRIVATE (self)->connections, nm_connection_get_uuid (NM_CONNECTION (connection))); - nm_settings_connection_signal_remove (NM_SETTINGS_CONNECTION (connection), FALSE); + nm_settings_connection_signal_remove (NM_SETTINGS_CONNECTION (connection)); g_object_unref (connection); g_return_if_fail (removed); @@ -260,7 +260,7 @@ update_connection (NMSKeyfilePlugin *self, if (!nm_settings_connection_update (NM_SETTINGS_CONNECTION (connection_by_uuid), NM_CONNECTION (connection_new), - NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP, + NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP_SAVED, NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, "keyfile-update", &local)) { diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-client.c b/src/systemd/src/libsystemd-network/sd-dhcp-client.c index fc6ad422..5eab0050 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp-client.c +++ b/src/systemd/src/libsystemd-network/sd-dhcp-client.c @@ -311,6 +311,7 @@ int sd_dhcp_client_set_client_id( assert_return(client, -EINVAL); assert_return(data, -EINVAL); assert_return(data_len > 0 && data_len <= MAX_CLIENT_ID_LEN, -EINVAL); + G_STATIC_ASSERT_EXPR (_NM_SD_MAX_CLIENT_ID_LEN == MAX_CLIENT_ID_LEN); switch (type) { |