diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/devices/nm-device.c | 26 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-dhclient-utils.c | 27 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-dhclient-utils.h | 1 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-dhclient.c | 29 | ||||
| -rw-r--r-- | src/dhcp/tests/test-dhcp-dhclient.c | 110 | ||||
| -rw-r--r-- | src/dns/nm-dns-manager.c | 18 | ||||
| -rw-r--r-- | src/nm-checkpoint.c | 24 | ||||
| -rw-r--r-- | src/nm-connectivity.c | 1 | ||||
| -rw-r--r-- | src/nm-default-route-manager.c | 46 | ||||
| -rw-r--r-- | src/nm-route-manager.c | 26 | ||||
| -rw-r--r-- | src/platform/nm-linux-platform.c | 2 | ||||
| -rw-r--r-- | src/platform/tests/test-route.c | 3 |
12 files changed, 227 insertions, 86 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index fbf315ed..bacbfb33 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -3422,6 +3422,7 @@ slave_state_changed (NMDevice *slave, { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); gboolean release = FALSE; + gboolean configure; _LOGD (LOGD_DEVICE, "slave %s state change %d (%s) -> %d (%s)", nm_device_get_iface (slave), @@ -3445,8 +3446,11 @@ slave_state_changed (NMDevice *slave, } if (release) { + configure = priv->sys_iface_state == NM_DEVICE_SYS_IFACE_STATE_MANAGED + && nm_device_sys_iface_state_get (slave) != NM_DEVICE_SYS_IFACE_STATE_EXTERNAL; + nm_device_master_release_one_slave (self, slave, - priv->sys_iface_state == NM_DEVICE_SYS_IFACE_STATE_MANAGED, + configure, reason); /* Bridge/bond/team interfaces are left up until manually deactivated */ if (priv->slaves == NULL && priv->state == NM_DEVICE_STATE_ACTIVATED) @@ -3692,13 +3696,6 @@ nm_device_slave_notify_enslave (NMDevice *self, gboolean success) priv->is_enslaved = TRUE; - if ( NM_IN_SET_TYPED (NMDeviceSysIfaceState, - priv->sys_iface_state, - NM_DEVICE_SYS_IFACE_STATE_EXTERNAL, - NM_DEVICE_SYS_IFACE_STATE_ASSUME) - && nm_device_sys_iface_state_get (priv->master) == NM_DEVICE_SYS_IFACE_STATE_MANAGED) - nm_device_sys_iface_state_set (self, NM_DEVICE_SYS_IFACE_STATE_MANAGED); - _notify (self, PROP_MASTER); _notify (priv->master, PROP_SLAVES); } else if (activating) { @@ -13475,8 +13472,17 @@ _hw_addr_get_cloned (NMDevice *self, NMConnection *connection, gboolean is_wifi, } if (nm_streq (addr, NM_CLONED_MAC_PERMANENT)) { - addr = nm_device_get_permanent_hw_address (self); - if (!addr) { + gboolean is_fake; + + addr = nm_device_get_permanent_hw_address_full (self, TRUE, &is_fake); + if (is_fake) { + /* Preserve the current address if the permanent address if fake */ + NM_SET_OUT (preserve, TRUE); + NM_SET_OUT (hwaddr, NULL); + NM_SET_OUT (hwaddr_type, HW_ADDR_TYPE_UNSET); + NM_SET_OUT (hwaddr_detail, g_steal_pointer (&addr_setting_free) ?: g_strdup (addr_setting)); + return TRUE; + } else if (!addr) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, diff --git a/src/dhcp/nm-dhcp-dhclient-utils.c b/src/dhcp/nm-dhcp-dhclient-utils.c index 216319b3..6a1b6865 100644 --- a/src/dhcp/nm-dhcp-dhclient-utils.c +++ b/src/dhcp/nm-dhcp-dhclient-utils.c @@ -31,7 +31,9 @@ #include "platform/nm-platform.h" #include "NetworkManagerUtils.h" -#define CLIENTID_TAG "send dhcp-client-identifier" +#define TIMEOUT_TAG "timeout " +#define RETRY_TAG "retry " +#define CLIENTID_TAG "send dhcp-client-identifier" #define HOSTNAME4_TAG "send host-name" #define HOSTNAME4_FORMAT HOSTNAME4_TAG " \"%s\"; # added by NetworkManager" @@ -263,6 +265,7 @@ nm_dhcp_dhclient_create_config (const char *interface, GBytes *client_id, const char *anycast_addr, const char *hostname, + guint32 timeout, gboolean use_fqdn, const char *orig_path, const char *orig_contents, @@ -296,7 +299,8 @@ nm_dhcp_dhclient_create_config (const char *interface, continue; if ( !intf[0] - && g_str_has_prefix (p, "interface")) { + && g_str_has_prefix (p, "interface") + && !in_req) { if (read_interface (p, intf, sizeof (intf))) continue; } @@ -309,6 +313,17 @@ nm_dhcp_dhclient_create_config (const char *interface, if (intf[0] && !nm_streq (intf, interface)) continue; + /* Some timing parameters in dhclient should not be imported (timeout, retry). + * The retry parameter will be simply not used as we will exit on first failure. + * The timeout one instead may affect NetworkManager behavior: if the timeout + * elapses before dhcp-timeout dhclient will report failure and cause NM to + * fail the dhcp process before dhcp-timeout. So, always skip importing timeout + * as we will need to add one greater than dhcp-timeout. + */ + if ( !strncmp (p, TIMEOUT_TAG, strlen (TIMEOUT_TAG)) + || !strncmp (p, RETRY_TAG, strlen (RETRY_TAG))) + continue; + if (!strncmp (p, CLIENTID_TAG, strlen (CLIENTID_TAG))) { /* Override config file "dhcp-client-id" and use one from the connection */ if (client_id) @@ -374,6 +389,14 @@ nm_dhcp_dhclient_create_config (const char *interface, } else g_string_append_c (new_contents, '\n'); + /* ensure dhclient timeout is greater than dhcp-timeout: as dhclient timeout default value is + * 60 seconds, we need this only if dhcp-timeout is greater than 60. + */ + if (timeout >= 60) { + timeout = timeout < G_MAXINT32 ? timeout + 1 : G_MAXINT32; + g_string_append_printf (new_contents, "timeout %u;\n", timeout); + } + if (is_ip6) { add_hostname6 (new_contents, hostname); add_request (reqs, "dhcp6.name-servers"); diff --git a/src/dhcp/nm-dhcp-dhclient-utils.h b/src/dhcp/nm-dhcp-dhclient-utils.h index 994b1b9f..2268890b 100644 --- a/src/dhcp/nm-dhcp-dhclient-utils.h +++ b/src/dhcp/nm-dhcp-dhclient-utils.h @@ -27,6 +27,7 @@ char *nm_dhcp_dhclient_create_config (const char *interface, GBytes *client_id, const char *anycast_addr, const char *hostname, + guint32 timeout, gboolean use_fqdn, const char *orig_path, const char *orig_contents, diff --git a/src/dhcp/nm-dhcp-dhclient.c b/src/dhcp/nm-dhcp-dhclient.c index a56e5a3c..f20158c6 100644 --- a/src/dhcp/nm-dhcp-dhclient.c +++ b/src/dhcp/nm-dhcp-dhclient.c @@ -182,6 +182,7 @@ merge_dhclient_config (NMDhcpDhclient *self, GBytes *client_id, const char *anycast_addr, const char *hostname, + guint32 timeout, gboolean use_fqdn, const char *orig_path, GBytes **out_new_client_id, @@ -206,7 +207,8 @@ merge_dhclient_config (NMDhcpDhclient *self, if (is_ip6 && hostname && !strchr (hostname, '.')) _LOGW ("hostname is not a FQDN, it will be ignored"); - new = nm_dhcp_dhclient_create_config (iface, is_ip6, client_id, anycast_addr, hostname, use_fqdn, orig_path, orig, out_new_client_id); + new = nm_dhcp_dhclient_create_config (iface, is_ip6, client_id, anycast_addr, hostname, timeout, + use_fqdn, orig_path, orig, out_new_client_id); g_assert (new); success = g_file_set_contents (conf_file, new, -1, error); g_free (new); @@ -294,6 +296,7 @@ create_dhclient_config (NMDhcpDhclient *self, GBytes *client_id, const char *dhcp_anycast_addr, const char *hostname, + guint32 timeout, gboolean use_fqdn, GBytes **out_new_client_id) { @@ -314,7 +317,7 @@ create_dhclient_config (NMDhcpDhclient *self, error = NULL; success = merge_dhclient_config (self, iface, new, is_ip6, client_id, dhcp_anycast_addr, - hostname, use_fqdn, orig, out_new_client_id, &error); + hostname, timeout, use_fqdn, orig, out_new_client_id, &error); if (!success) { _LOGW ("error creating dhclient configuration: %s", error->message); g_error_free (error); @@ -342,8 +345,6 @@ dhclient_start (NMDhcpClient *client, char *binary_name, *cmd_str, *pid_file = NULL, *system_bus_address_env = NULL; gboolean ipv6, success; char *escaped, *preferred_leasefile_path = NULL; - guint32 timeout; - char timeout_str[64]; g_return_val_if_fail (priv->pid_file == NULL, FALSE); @@ -446,17 +447,6 @@ dhclient_start (NMDhcpClient *client, g_ptr_array_add (argv, (gpointer) priv->conf_file); } - /* Specify a timeout longer than configuration's one, - * so that dhclient doesn't send back a FAIL event before - * that time. - */ - timeout = nm_dhcp_client_get_timeout (client); - if (timeout >= 60) { - timeout = timeout < G_MAXINT32 ? timeout + 1 : G_MAXINT32; - g_ptr_array_add (argv, (gpointer) "-timeout"); - g_ptr_array_add (argv, (gpointer) nm_sprintf_buf (timeout_str, "%u", (unsigned) timeout)); - } - /* Usually the system bus address is well-known; but if it's supposed * to be something else, we need to push it to dhclient, since dhclient * sanitizes the environment it gives the action scripts. @@ -506,6 +496,7 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last GBytes *client_id; gs_unref_bytes GBytes *new_client_id = NULL; const char *iface, *uuid, *hostname; + guint32 timeout; gboolean success = FALSE; gboolean use_fqdn; @@ -513,10 +504,11 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last uuid = nm_dhcp_client_get_uuid (client); client_id = nm_dhcp_client_get_client_id (client); hostname = nm_dhcp_client_get_hostname (client); + timeout = nm_dhcp_client_get_timeout (client); use_fqdn = nm_dhcp_client_get_use_fqdn (client); priv->conf_file = create_dhclient_config (self, iface, FALSE, uuid, client_id, dhcp_anycast_addr, - hostname, use_fqdn, &new_client_id); + hostname, timeout, use_fqdn, &new_client_id); if (priv->conf_file) { if (new_client_id) nm_dhcp_client_set_client_id (client, new_client_id); @@ -539,12 +531,15 @@ ip6_start (NMDhcpClient *client, NMDhcpDhclient *self = NM_DHCP_DHCLIENT (client); NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE (self); const char *iface, *uuid, *hostname; + guint32 timeout; iface = nm_dhcp_client_get_iface (client); uuid = nm_dhcp_client_get_uuid (client); hostname = nm_dhcp_client_get_hostname (client); + timeout = nm_dhcp_client_get_timeout (client); - priv->conf_file = create_dhclient_config (self, iface, TRUE, uuid, NULL, dhcp_anycast_addr, hostname, TRUE, NULL); + priv->conf_file = create_dhclient_config (self, iface, TRUE, uuid, NULL, dhcp_anycast_addr, + hostname, timeout, TRUE, NULL); if (!priv->conf_file) { _LOGW ("error creating dhclient configuration file"); return FALSE; diff --git a/src/dhcp/tests/test-dhcp-dhclient.c b/src/dhcp/tests/test-dhcp-dhclient.c index 40a3e072..5816932b 100644 --- a/src/dhcp/tests/test-dhcp-dhclient.c +++ b/src/dhcp/tests/test-dhcp-dhclient.c @@ -40,6 +40,7 @@ test_config (const char *orig, const char *expected, gboolean ipv6, const char *hostname, + guint32 timeout, gboolean use_fqdn, const char *dhcp_client_id, GBytes *expected_new_client_id, @@ -60,23 +61,23 @@ test_config (const char *orig, client_id, anycast_addr, hostname, + timeout, use_fqdn, "/path/to/dhclient.conf", orig, &new_client_id); g_assert (new != NULL); -#if DEBUG - if ( strlen (new) != strlen (expected) - || strcmp (new, expected)) { - g_message ("\n- NEW ---------------------------------\n" + if (!nm_streq (new, expected)) { + g_message ("\n* OLD ---------------------------------\n" "%s" - "+ EXPECTED ++++++++++++++++++++++++++++++\n" + "\n- NEW -----------------------------------\n" "%s" - "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", - new, expected); + "\n+ EXPECTED ++++++++++++++++++++++++++++++\n" + "%s" + "\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + orig, new, expected); } -#endif g_assert_cmpstr (new, ==, expected); if (expected_new_client_id) { @@ -105,7 +106,7 @@ static const char *orig_missing_expected = \ static void test_orig_missing (void) { - test_config (NULL, orig_missing_expected, FALSE, NULL, FALSE, NULL, NULL, "eth0", NULL); + test_config (NULL, orig_missing_expected, FALSE, NULL, 0, FALSE, NULL, NULL, "eth0", NULL); } /*****************************************************************************/ @@ -134,7 +135,7 @@ static void test_override_client_id (void) { test_config (override_client_id_orig, override_client_id_expected, - FALSE, NULL, FALSE, + FALSE, NULL, 0, FALSE, "11:22:33:44:55:66", NULL, "eth0", @@ -163,7 +164,7 @@ static void test_quote_client_id (void) { test_config (NULL, quote_client_id_expected, - FALSE, NULL, FALSE, + FALSE, NULL, 0, FALSE, "1234", NULL, "eth0", @@ -192,7 +193,7 @@ static void test_ascii_client_id (void) { test_config (NULL, ascii_client_id_expected, - FALSE, NULL, FALSE, + FALSE, NULL, 0, FALSE, "qb:cd:ef:12:34:56", NULL, "eth0", @@ -221,7 +222,7 @@ static void test_hex_single_client_id (void) { test_config (NULL, hex_single_client_id_expected, - FALSE, NULL, FALSE, + FALSE, NULL, 0, FALSE, "ab:cd:e:12:34:56", NULL, "eth0", @@ -258,7 +259,7 @@ test_existing_hex_client_id (void) new_client_id = g_bytes_new (bytes, sizeof (bytes)); test_config (existing_hex_client_id_orig, existing_hex_client_id_expected, - FALSE, NULL, FALSE, + FALSE, NULL, 0, FALSE, NULL, new_client_id, "eth0", @@ -298,7 +299,7 @@ test_existing_ascii_client_id (void) memcpy (buf + 1, EACID, NM_STRLEN (EACID)); new_client_id = g_bytes_new (buf, sizeof (buf)); test_config (existing_ascii_client_id_orig, existing_ascii_client_id_expected, - FALSE, NULL, FALSE, + FALSE, NULL, 0, FALSE, NULL, new_client_id, "eth0", @@ -327,7 +328,7 @@ static void test_fqdn (void) { test_config (NULL, fqdn_expected, - FALSE, "foo.bar.com", + FALSE, "foo.bar.com", 0, TRUE, NULL, NULL, "eth0", @@ -367,7 +368,7 @@ test_fqdn_options_override (void) { test_config (fqdn_options_override_orig, fqdn_options_override_expected, - FALSE, "example2.com", + FALSE, "example2.com", 0, TRUE, NULL, NULL, "eth0", @@ -400,7 +401,7 @@ static void test_override_hostname (void) { test_config (override_hostname_orig, override_hostname_expected, - FALSE, "blahblah", FALSE, + FALSE, "blahblah", 0, FALSE, NULL, NULL, "eth0", @@ -429,7 +430,7 @@ static void test_override_hostname6 (void) { test_config (override_hostname6_orig, override_hostname6_expected, - TRUE, "blahblah.local", TRUE, + TRUE, "blahblah.local", 0, TRUE, NULL, NULL, "eth0", @@ -451,8 +452,8 @@ test_nonfqdn_hostname6 (void) { /* Non-FQDN hostname can't be used with dhclient */ test_config (NULL, nonfqdn_hostname6_expected, - TRUE, "blahblah", - TRUE, NULL, + TRUE, "blahblah", 0, TRUE, + NULL, NULL, "eth0", NULL); @@ -486,8 +487,7 @@ static void test_existing_alsoreq (void) { test_config (existing_alsoreq_orig, existing_alsoreq_expected, - FALSE, NULL, - FALSE, + FALSE, NULL, 0, FALSE, NULL, NULL, "eth0", @@ -525,8 +525,7 @@ static void test_existing_req (void) { test_config (existing_req_orig, existing_req_expected, - FALSE, NULL, - FALSE, + FALSE, NULL, 0, FALSE, NULL, NULL, "eth0", @@ -565,7 +564,7 @@ static void test_existing_multiline_alsoreq (void) { test_config (existing_multiline_alsoreq_orig, existing_multiline_alsoreq_expected, - FALSE, NULL, FALSE, + FALSE, NULL, 0, FALSE, NULL, NULL, "eth0", @@ -779,7 +778,7 @@ static void test_interface1 (void) { test_config (interface1_orig, interface1_expected, - FALSE, NULL, FALSE, + FALSE, NULL, 0, FALSE, NULL, NULL, "eth0", @@ -824,13 +823,67 @@ static void test_interface2 (void) { test_config (interface2_orig, interface2_expected, - FALSE, NULL, FALSE, + FALSE, NULL, 0, FALSE, NULL, NULL, "eth1", NULL); } +static void +test_config_req_intf (void) +{ + static const char *const orig = \ + "request subnet-mask, broadcast-address, routers,\n" + " rfc3442-classless-static-routes,\n" + " interface-mtu, host-name, domain-name, domain-search,\n" + " domain-name-servers, nis-domain, nis-servers,\n" + " nds-context, nds-servers, nds-tree-name,\n" + " netbios-name-servers, netbios-dd-server,\n" + " netbios-node-type, netbios-scope, ntp-servers;\n" + ""; + static const char *const expected = \ + "# Created by NetworkManager\n" + "# Merged from /path/to/dhclient.conf\n" + "\n" + "\n" + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" + "option wpad code 252 = string;\n" + "\n" + "request; # override dhclient defaults\n" + "also request subnet-mask;\n" + "also request broadcast-address;\n" + "also request routers;\n" + "also request rfc3442-classless-static-routes;\n" + "also request interface-mtu;\n" + "also request host-name;\n" + "also request domain-name;\n" + "also request domain-search;\n" + "also request domain-name-servers;\n" + "also request nis-domain;\n" + "also request nis-servers;\n" + "also request nds-context;\n" + "also request nds-servers;\n" + "also request nds-tree-name;\n" + "also request netbios-name-servers;\n" + "also request netbios-dd-server;\n" + "also request netbios-node-type;\n" + "also request netbios-scope;\n" + "also request ntp-servers;\n" + "also request ms-classless-static-routes;\n" + "also request static-routes;\n" + "also request wpad;\n" + "\n"; + + test_config (orig, expected, + FALSE, NULL, 0, FALSE, + NULL, + NULL, + "eth0", + NULL); +} + /*****************************************************************************/ static void @@ -982,6 +1035,7 @@ main (int argc, char **argv) g_test_add_func ("/dhcp/dhclient/duids", test_duids); g_test_add_func ("/dhcp/dhclient/interface/1", test_interface1); g_test_add_func ("/dhcp/dhclient/interface/2", test_interface2); + g_test_add_func ("/dhcp/dhclient/config/req_intf", test_config_req_intf); g_test_add_func ("/dhcp/dhclient/read_duid_from_leasefile", test_read_duid_from_leasefile); g_test_add_func ("/dhcp/dhclient/read_commented_duid_from_leasefile", test_read_commented_duid_from_leasefile); diff --git a/src/dns/nm-dns-manager.c b/src/dns/nm-dns-manager.c index f443f340..952468e3 100644 --- a/src/dns/nm-dns-manager.c +++ b/src/dns/nm-dns-manager.c @@ -158,12 +158,12 @@ G_DEFINE_TYPE (NMDnsManager, nm_dns_manager, NM_TYPE_EXPORTED_OBJECT) #define NM_DNS_MANAGER_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMDnsManager, NM_IS_DNS_MANAGER) static gboolean -domain_is_valid (const gchar *domain) +domain_is_valid (const gchar *domain, gboolean check_public_suffix) { if (*domain == '\0') return FALSE; #if WITH_LIBPSL - if (psl_is_public_suffix (psl_builtin (), domain)) + if (check_public_suffix && psl_is_public_suffix (psl_builtin (), domain)) return FALSE; #endif return TRUE; @@ -312,7 +312,7 @@ merge_one_ip4_config (NMResolvConfData *rc, NMIP4Config *src) const char *search; search = nm_ip4_config_get_search (src, i); - if (!domain_is_valid (search)) + if (!domain_is_valid (search, FALSE)) continue; add_string_item (rc->searches, search); } @@ -322,7 +322,7 @@ merge_one_ip4_config (NMResolvConfData *rc, NMIP4Config *src) const char *domain; domain = nm_ip4_config_get_domain (src, i); - if (!domain_is_valid (domain)) + if (!domain_is_valid (domain, FALSE)) continue; add_string_item (rc->searches, domain); } @@ -382,7 +382,7 @@ merge_one_ip6_config (NMResolvConfData *rc, NMIP6Config *src, const char *iface) const char *search; search = nm_ip6_config_get_search (src, i); - if (!domain_is_valid (search)) + if (!domain_is_valid (search, FALSE)) continue; add_string_item (rc->searches, search); } @@ -392,7 +392,7 @@ merge_one_ip6_config (NMResolvConfData *rc, NMIP6Config *src, const char *iface) const char *domain; domain = nm_ip6_config_get_domain (src, i); - if (!domain_is_valid (domain)) + if (!domain_is_valid (domain, FALSE)) continue; add_string_item (rc->searches, domain); } @@ -923,7 +923,7 @@ merge_global_dns_config (NMResolvConfData *rc, NMGlobalDnsConfig *global_conf) options = nm_global_dns_config_get_options (global_conf); for (i = 0; searches && searches[i]; i++) { - if (domain_is_valid (searches[i])) + if (domain_is_valid (searches[i], FALSE)) add_string_item (rc->searches, searches[i]); } @@ -1055,9 +1055,9 @@ _collect_resolv_conf_data (NMDnsManager *self, /* only for logging context, no o if ( hostdomain && !nm_utils_ipaddr_valid (AF_UNSPEC, hostname)) { hostdomain++; - if (domain_is_valid (hostdomain)) + if (domain_is_valid (hostdomain, TRUE)) add_string_item (rc.searches, hostdomain); - else if (domain_is_valid (hostname)) + else if (domain_is_valid (hostname, TRUE)) add_string_item (rc.searches, hostname); } } diff --git a/src/nm-checkpoint.c b/src/nm-checkpoint.c index d59bc574..04f00e89 100644 --- a/src/nm-checkpoint.c +++ b/src/nm-checkpoint.c @@ -46,7 +46,7 @@ typedef struct { guint64 ac_version_id; NMDeviceState state; bool realized:1; - bool unmanaged_explicit:1; + NMUnmanFlagOp unmanaged_explicit; } DeviceCheckpoint; NM_GOBJECT_PROPERTIES_DEFINE_BASE ( @@ -224,9 +224,19 @@ nm_checkpoint_rollback (NMCheckpoint *self) } activate: + /* Manage the device again if needed */ + if ( nm_device_get_unmanaged_flags (device, NM_UNMANAGED_USER_EXPLICIT) + && dev_checkpoint->unmanaged_explicit != NM_UNMAN_FLAG_OP_SET_UNMANAGED) { + _LOGD ("rollback: restore unmanaged user-explicit"); + nm_device_set_unmanaged_by_flags_queue (device, + NM_UNMANAGED_USER_EXPLICIT, + dev_checkpoint->unmanaged_explicit, + NM_DEVICE_STATE_REASON_NOW_MANAGED); + } + if (dev_checkpoint->state == NM_DEVICE_STATE_UNMANAGED) { if ( nm_device_get_state (device) != NM_DEVICE_STATE_UNMANAGED - || dev_checkpoint->unmanaged_explicit) { + || dev_checkpoint->unmanaged_explicit == NM_UNMAN_FLAG_OP_SET_UNMANAGED) { _LOGD ("rollback: explicitly unmanage device"); nm_device_set_unmanaged_by_flags_queue (device, NM_UNMANAGED_USER_EXPLICIT, @@ -370,19 +380,21 @@ device_checkpoint_create (NMDevice *device, NMConnection *applied_connection; NMSettingsConnection *settings_connection; const char *path; - gboolean unmanaged_explicit; NMActRequest *act_request; path = nm_exported_object_get_path (NM_EXPORTED_OBJECT (device)); - unmanaged_explicit = !!nm_device_get_unmanaged_flags (device, - NM_UNMANAGED_USER_EXPLICIT); dev_checkpoint = g_slice_new0 (DeviceCheckpoint); dev_checkpoint->device = g_object_ref (device); dev_checkpoint->original_dev_path = g_strdup (path); dev_checkpoint->state = nm_device_get_state (device); dev_checkpoint->realized = nm_device_is_real (device); - dev_checkpoint->unmanaged_explicit = unmanaged_explicit; + + if (nm_device_get_unmanaged_mask (device, NM_UNMANAGED_USER_EXPLICIT)) { + dev_checkpoint->unmanaged_explicit = + !!nm_device_get_unmanaged_flags (device, NM_UNMANAGED_USER_EXPLICIT); + } else + dev_checkpoint->unmanaged_explicit = NM_UNMAN_FLAG_OP_FORGET; applied_connection = nm_device_get_applied_connection (device); if (applied_connection) { diff --git a/src/nm-connectivity.c b/src/nm-connectivity.c index 6f16b28e..b895a82b 100644 --- a/src/nm-connectivity.c +++ b/src/nm-connectivity.c @@ -124,6 +124,7 @@ finish_cb_data (ConCheckCbData *cb_data, NMConnectivityState new_state) g_object_unref (cb_data->simple); curl_slist_free_all (cb_data->request_headers); g_free (cb_data->response); + g_free (cb_data->ifspec); g_source_remove (cb_data->timeout_id); g_slice_free (ConCheckCbData, cb_data); } diff --git a/src/nm-default-route-manager.c b/src/nm-default-route-manager.c index 9ac6d552..1ab8f02d 100644 --- a/src/nm-default-route-manager.c +++ b/src/nm-default-route-manager.c @@ -28,6 +28,7 @@ #include "devices/nm-device.h" #include "vpn/nm-vpn-connection.h" #include "platform/nm-platform.h" +#include "platform/nm-platform-utils.h" #include "nm-manager.h" #include "nm-ip4-config.h" #include "nm-ip6-config.h" @@ -266,6 +267,8 @@ _platform_route_sync_add (const VTableIP *vtable, NMDefaultRouteManager *self, g { NMDefaultRouteManagerPrivate *priv = NM_DEFAULT_ROUTE_MANAGER_GET_PRIVATE (self); GPtrArray *entries = vtable->get_entries (priv); + char buf1[sizeof (_nm_utils_to_string_buffer)]; + char buf2[sizeof (_nm_utils_to_string_buffer)]; guint i; Entry *entry_unsynced = NULL; Entry *entry = NULL; @@ -304,21 +307,64 @@ _platform_route_sync_add (const VTableIP *vtable, NMDefaultRouteManager *self, g if (vtable->vt->is_ip4) { NMPlatformIP4Route rt = entry->route.r4; + const NMPlatformIP4Route *plat_rt; rt.network = 0; rt.plen = 0; rt.metric = entry->effective_metric; + rt.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (rt.rt_source); + + plat_rt = nm_platform_ip4_route_get (priv->platform, + entry->route.r4.ifindex, + 0, + 0, + entry->effective_metric); + if (plat_rt && nm_platform_ip4_route_cmp (plat_rt, &rt) == 0) { + _LOGt (AF_INET, "already exists: %s", + nm_platform_ip4_route_to_string (&rt, NULL, 0)); + return FALSE; + } + + rt.rt_source = entry->route.r4.rt_source; + + if (plat_rt) { + _LOGt (AF_INET, "update platform route: %s; with route: %s", + nm_platform_ip4_route_to_string (plat_rt, buf1, sizeof (buf1)), + nm_platform_ip4_route_to_string (&rt, buf2, sizeof (buf2))); + } success = nm_platform_ip4_route_add (priv->platform, &rt); } else { NMPlatformIP6Route rt = entry->route.r6; + const NMPlatformIP6Route *plat_rt; rt.network = in6addr_any; rt.plen = 0; rt.metric = entry->effective_metric; + rt.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (rt.rt_source); + + plat_rt = nm_platform_ip6_route_get (priv->platform, + entry->route.r6.ifindex, + in6addr_any, + 0, + entry->effective_metric); + if (plat_rt && nm_platform_ip6_route_cmp (plat_rt, &rt) == 0) { + _LOGt (AF_INET6, "already exists: %s", + nm_platform_ip6_route_to_string (&rt, NULL, 0)); + return FALSE; + } + + rt.rt_source = entry->route.r6.rt_source; + + if (plat_rt) { + _LOGt (AF_INET, "update platform route: %s; with route: %s", + nm_platform_ip6_route_to_string (plat_rt, buf1, sizeof (buf1)), + nm_platform_ip6_route_to_string (&rt, buf2, sizeof (buf2))); + } success = nm_platform_ip6_route_add (priv->platform, &rt); } + if (!success) { _LOGW (vtable->vt->addr_family, "failed to add default route %s with effective metric %u", vtable->vt->route_to_string (&entry->route, NULL, 0), (guint) entry->effective_metric); diff --git a/src/nm-route-manager.c b/src/nm-route-manager.c index b58cdeb0..f293f130 100644 --- a/src/nm-route-manager.c +++ b/src/nm-route-manager.c @@ -25,6 +25,7 @@ #include <string.h> #include "platform/nm-platform.h" +#include "platform/nm-platform-utils.h" #include "platform/nmp-object.h" #include "nm-core-internal.h" #include "NetworkManagerUtils.h" @@ -364,19 +365,20 @@ _route_index_reverse_idx (const VTableIP *vtable, const RouteIndex *index, guint /*****************************************************************************/ static gboolean -_route_equals_ignoring_ifindex (const VTableIP *vtable, const NMPlatformIPXRoute *r1, const NMPlatformIPXRoute *r2, gint64 r2_metric) +_route_equals_ignoring_ifindex (const VTableIP *vtable, + const NMPlatformIPXRoute *plat_rt, + const NMPlatformIPXRoute *rt, + gint64 rt_metric) { - NMPlatformIPXRoute r2_backup; - - if ( r1->rx.ifindex != r2->rx.ifindex - || (r2_metric >= 0 && ((guint32) r2_metric) != r2->rx.metric)) { - memcpy (&r2_backup, r2, vtable->vt->sizeof_route); - r2_backup.rx.ifindex = r1->rx.ifindex; - if (r2_metric >= 0) - r2_backup.rx.metric = (guint32) r2_metric; - r2 = &r2_backup; - } - return vtable->vt->route_cmp (r1, r2, FALSE) == 0; + NMPlatformIPXRoute rt_backup; + + memcpy (&rt_backup, rt, vtable->vt->sizeof_route); + rt_backup.rx.ifindex = plat_rt->rx.ifindex; + if (rt_metric >= 0) + rt_backup.rx.metric = (guint32) rt_metric; + rt_backup.rx.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (rt_backup.rx.rt_source); + + return vtable->vt->route_cmp (plat_rt, &rt_backup, FALSE) == 0; } static NMPlatformIPXRoute * diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 487725e4..6b84c185 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -4230,7 +4230,7 @@ out: /* such an object still exists in the cache. To be sure, refetch it (and * hope it's gone) */ do_request_one_type (platform, NMP_OBJECT_GET_TYPE (obj_id)); - return !!nmp_cache_lookup_obj (priv->cache, obj_id); + return !nmp_cache_lookup_obj (priv->cache, obj_id); } static WaitForNlResponseResult diff --git a/src/platform/tests/test-route.c b/src/platform/tests/test-route.c index 6862f13e..9960d867 100644 --- a/src/platform/tests/test-route.c +++ b/src/platform/tests/test-route.c @@ -421,7 +421,8 @@ test_ip4_route_options (void) nmtst_platform_ip4_routes_equal ((NMPlatformIP4Route *) routes->data, rts, routes->len, TRUE); /* Remove route */ - g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, 24, 20)); + /* FIXME. Due to a bug, we cannot delete routes with non-zero TOS. See bgo#785004. */ + //g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, 24, 20)); g_array_unref (routes); } |