diff options
| author | Michael Biebl <biebl@debian.org> | 2017-07-12 17:57:30 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2017-07-12 17:57:30 +0200 |
| commit | b9f0451fa35393ceedf6d9d20b78c43578ebea5d (patch) | |
| tree | 417afcdd717020ad44e25fadee4b89de23316e83 /src | |
| parent | c333f062ddcba9b35330647bf6cbd0a07f2d786e (diff) | |
New upstream version 1.8.2 upstream/1.8.2
Diffstat (limited to 'src')
43 files changed, 1135 insertions, 678 deletions
diff --git a/src/devices/bluetooth/nm-bluez-device.c b/src/devices/bluetooth/nm-bluez-device.c index ebfa0d64..41ef74ca 100644 --- a/src/devices/bluetooth/nm-bluez-device.c +++ b/src/devices/bluetooth/nm-bluez-device.c @@ -1187,7 +1187,11 @@ dispose (GObject *object) g_slist_free_full (priv->connections, g_object_unref); priv->connections = NULL; - g_clear_object (&priv->adapter5); + if (priv->adapter5) { + g_signal_handlers_disconnect_by_func (priv->adapter5, adapter5_on_properties_changed, self); + g_clear_object (&priv->adapter5); + } + g_clear_object (&priv->dbus_connection); G_OBJECT_CLASS (nm_bluez_device_parent_class)->dispose (object); diff --git a/src/devices/nm-device-bond.c b/src/devices/nm-device-bond.c index 3325c948..d9c2ca64 100644 --- a/src/devices/nm-device-bond.c +++ b/src/devices/nm-device-bond.c @@ -137,17 +137,22 @@ set_bond_attr (NMDevice *device, NMBondMode mode, const char *attr, const char * return ret; } -/* Ignore certain bond options if they are zero (off/disabled) */ static gboolean -ignore_if_zero (const char *option, const char *value) +ignore_option (NMSettingBond *s_bond, const char *option, const char *value) { - if (!NM_IN_STRSET (option, NM_SETTING_BOND_OPTION_ARP_INTERVAL, - NM_SETTING_BOND_OPTION_DOWNDELAY, - NM_SETTING_BOND_OPTION_MIIMON, - NM_SETTING_BOND_OPTION_UPDELAY)) - return FALSE; + const char *defvalue; + + if (nm_streq0 (option, NM_SETTING_BOND_OPTION_MIIMON)) { + /* The default value for miimon, when missing in the setting, is + * 0 if arp_interval is != 0, and 100 otherwise. So, let's ignore + * miimon=0 (which means that miimon is disabled) and accept any + * other value. Adding miimon=100 does not cause any harm. + */ + defvalue = "0"; + } else + defvalue = nm_setting_bond_get_option_default (s_bond, option); - return g_strcmp0 (value, "0") == 0 ? TRUE : FALSE; + return nm_streq0 (value, defvalue); } static void @@ -155,6 +160,7 @@ update_connection (NMDevice *device, NMConnection *connection) { NMSettingBond *s_bond = nm_connection_get_setting_bond (connection); int ifindex = nm_device_get_ifindex (device); + NMBondMode mode = NM_BOND_MODE_UNKNOWN; const char **options; if (!s_bond) { @@ -164,9 +170,8 @@ update_connection (NMDevice *device, NMConnection *connection) /* Read bond options from sysfs and update the Bond setting to match */ options = nm_setting_bond_get_valid_options (s_bond); - while (options && *options) { + for (; *options; options++) { gs_free char *value = nm_platform_sysctl_master_get_option (nm_device_get_platform (device), ifindex, *options); - const char *defvalue = nm_setting_bond_get_option_default (s_bond, *options); char *p; if ( value @@ -176,10 +181,15 @@ update_connection (NMDevice *device, NMConnection *connection) *p = '\0'; } + if (value && nm_streq (*options, NM_SETTING_BOND_OPTION_MODE)) + mode = _nm_setting_bond_mode_from_string (value); + + if (!_nm_setting_bond_option_supported (*options, mode)) + continue; + if ( value && value[0] - && !ignore_if_zero (*options, value) - && !nm_streq0 (value, defvalue)) { + && !ignore_option (s_bond, *options, value)) { /* Replace " " with "," for arp_ip_targets from the kernel */ if (strcmp (*options, NM_SETTING_BOND_OPTION_ARP_IP_TARGET) == 0) { for (p = value; *p; p++) { @@ -190,7 +200,6 @@ update_connection (NMDevice *device, NMConnection *connection) nm_setting_bond_add_option (s_bond, *options, value); } - options++; } } diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c index 4c5aeb5e..8a04d401 100644 --- a/src/devices/nm-device-ethernet.c +++ b/src/devices/nm-device-ethernet.c @@ -1597,12 +1597,11 @@ get_link_speed (NMDevice *device) } static void -carrier_changed (NMDevice *device, gboolean carrier) +carrier_changed_notify (NMDevice *device, gboolean carrier) { if (carrier) get_link_speed (device); - - NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->carrier_changed (device, carrier); + NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->carrier_changed_notify (device, carrier); } static void @@ -1764,7 +1763,7 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass) parent_class->deactivate = deactivate; parent_class->get_s390_subchannels = get_s390_subchannels; parent_class->update_connection = update_connection; - parent_class->carrier_changed = carrier_changed; + parent_class->carrier_changed_notify = carrier_changed_notify; parent_class->link_changed = link_changed; parent_class->is_available = is_available; parent_class->can_reapply_change = can_reapply_change; diff --git a/src/devices/nm-device-infiniband.c b/src/devices/nm-device-infiniband.c index f7875d09..7e041270 100644 --- a/src/devices/nm-device-infiniband.c +++ b/src/devices/nm-device-infiniband.c @@ -139,7 +139,7 @@ get_configured_mtu (NMDevice *device, gboolean *out_is_user_config) } } *out_is_user_config = (mtu != 0); - return mtu ?: NM_DEVICE_DEFAULT_MTU_INFINIBAND; + return mtu; } static gboolean diff --git a/src/devices/nm-device-ip-tunnel.c b/src/devices/nm-device-ip-tunnel.c index 53b7cf4e..2f505ef4 100644 --- a/src/devices/nm-device-ip-tunnel.c +++ b/src/devices/nm-device-ip-tunnel.c @@ -767,7 +767,7 @@ get_configured_mtu (NMDevice *self, gboolean *out_is_user_config) } } *out_is_user_config = (mtu != 0); - return mtu ?: NM_DEVICE_DEFAULT_MTU_WIRED; + return mtu; } static NMDeviceCapabilities diff --git a/src/devices/nm-device-logging.h b/src/devices/nm-device-logging.h index 419a4a51..f0c7e591 100644 --- a/src/devices/nm-device-logging.h +++ b/src/devices/nm-device-logging.h @@ -34,11 +34,21 @@ _nm_device_log_self_to_device (t *self) \ #undef _NMLOG_ENABLED #define _NMLOG_ENABLED(level, domain) ( nm_logging_enabled ((level), (domain)) ) #define _NMLOG(level, domain, ...) \ - nm_log_obj ((level), (domain), \ - (self) ? nm_device_get_iface (_nm_device_log_self_to_device (self)) : NULL, \ - NULL, (self), "device", \ - "(%s): " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ - (self) ? (nm_device_get_iface (_nm_device_log_self_to_device (self)) ?: "(null)") : "(none)" \ - _NM_UTILS_MACRO_REST(__VA_ARGS__)) + G_STMT_START { \ + const NMLogLevel _level = (level); \ + const NMLogDomain _domain = (domain); \ + \ + if (nm_logging_enabled (_level, _domain)) { \ + typeof (*self) *const _self = (self); \ + const char *const _ifname = _nm_device_get_iface (_nm_device_log_self_to_device (_self)); \ + \ + nm_log_obj (_level, _domain, \ + _ifname, NULL, \ + _self, "device", \ + "%s%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + NM_PRINT_FMT_QUOTED (_ifname, "(", _ifname, ")", "[null]") \ + _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ + } G_STMT_END #endif /* __NETWORKMANAGER_DEVICE_LOGGING_H__ */ diff --git a/src/devices/nm-device-private.h b/src/devices/nm-device-private.h index a4067f9c..9eccafdc 100644 --- a/src/devices/nm-device-private.h +++ b/src/devices/nm-device-private.h @@ -116,10 +116,6 @@ gboolean nm_device_ipv6_sysctl_set (NMDevice *self, const char *property, const /*****************************************************************************/ -#define NM_DEVICE_DEFAULT_MTU_WIRED ((guint32) 1500) -#define NM_DEVICE_DEFAULT_MTU_WIRELESS ((guint32) 1500) -#define NM_DEVICE_DEFAULT_MTU_INFINIBAND ((guint32) 0) - gint64 nm_device_get_configured_mtu_from_connection_default (NMDevice *self, const char *property_name); diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c index 06db6446..a74da8f2 100644 --- a/src/devices/nm-device-vlan.c +++ b/src/devices/nm-device-vlan.c @@ -586,7 +586,7 @@ get_configured_mtu (NMDevice *self, gboolean *out_is_user_config) if (ifindex > 0) mtu = nm_platform_link_get_mtu (nm_device_get_platform (NM_DEVICE (self)), ifindex); - return mtu ?: NM_DEVICE_DEFAULT_MTU_WIRED; + return mtu; } /*****************************************************************************/ diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index da581a0d..fbf315ed 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -262,7 +262,10 @@ typedef struct _NMDevicePrivate { NMUtilsStableType current_stable_id_type:3; - bool is_nm_owned:1; /* whether the device is a device owned and created by NM */ + bool nm_owned:1; /* whether the device is a device owned and created by NM */ + + bool assume_state_guess_assume:1; + char * assume_state_connection_uuid; GHashTable * available_connections; char * hw_addr; @@ -527,6 +530,9 @@ static gboolean dhcp6_start (NMDevice *self, gboolean wait_for_ll); static void nm_device_start_ip_check (NMDevice *self); static void realize_start_setup (NMDevice *self, const NMPlatformLink *plink, + gboolean assume_state_guess_assume, + const char *assume_state_connection_uuid, + gboolean set_nm_owned, NMUnmanFlagOp unmanaged_user_explicit); static void _commit_mtu (NMDevice *self, const NMIP4Config *config); static void dhcp_schedule_restart (NMDevice *self, int family, const char *reason); @@ -551,8 +557,8 @@ NM_UTILS_LOOKUP_STR_DEFINE_STATIC (queued_state_to_string, NMDeviceState, NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_FAILED, NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "failed"), ); -static const char * -state_to_string (NMDeviceState state) +const char * +nm_device_state_to_str (NMDeviceState state) { return queued_state_to_string (state) + NM_STRLEN (NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE); } @@ -710,6 +716,52 @@ nm_device_sys_iface_state_set (NMDevice *self, /*****************************************************************************/ +void +nm_device_assume_state_get (NMDevice *self, + gboolean *out_assume_state_guess_assume, + const char **out_assume_state_connection_uuid) +{ + NMDevicePrivate *priv; + + g_return_if_fail (NM_IS_DEVICE (self)); + + priv = NM_DEVICE_GET_PRIVATE (self); + NM_SET_OUT (out_assume_state_guess_assume, priv->assume_state_guess_assume); + NM_SET_OUT (out_assume_state_connection_uuid, priv->assume_state_connection_uuid); +} + +static void +_assume_state_set (NMDevice *self, + gboolean assume_state_guess_assume, + const char *assume_state_connection_uuid) +{ + NMDevicePrivate *priv; + + nm_assert (NM_IS_DEVICE (self)); + + priv = NM_DEVICE_GET_PRIVATE (self); + if ( priv->assume_state_guess_assume == !!assume_state_guess_assume + && nm_streq0 (priv->assume_state_connection_uuid, assume_state_connection_uuid)) + return; + + _LOGD (LOGD_DEVICE, "assume-state: set guess-assume=%c, connection=%s%s%s", + assume_state_guess_assume ? '1' : '0', + NM_PRINT_FMT_QUOTE_STRING (assume_state_connection_uuid)); + priv->assume_state_guess_assume = assume_state_guess_assume; + g_free (priv->assume_state_connection_uuid); + priv->assume_state_connection_uuid = g_strdup (assume_state_connection_uuid); +} + +void +nm_device_assume_state_reset (NMDevice *self) +{ + g_return_if_fail (NM_IS_DEVICE (self)); + + _assume_state_set (self, FALSE, NULL); +} + +/*****************************************************************************/ + static void init_ip4_config_dns_priority (NMDevice *self, NMIP4Config *config) { @@ -1775,10 +1827,13 @@ update_connectivity_state (NMDevice *self, NMConnectivityState state) priv->connectivity_state = state; _notify (self, PROP_CONNECTIVITY); - if (nm_device_get_state (self) == NM_DEVICE_STATE_ACTIVATED) { - if (!ip4_config_merge_and_apply (self, NULL, TRUE)) + if ( priv->state == NM_DEVICE_STATE_ACTIVATED + && !nm_device_sys_iface_state_is_external (self)) { + if ( priv->default_route.v4_has + && !ip4_config_merge_and_apply (self, NULL, TRUE)) _LOGW (LOGD_IP4, "Failed to update IPv4 default route metric"); - if (!ip6_config_merge_and_apply (self, TRUE)) + if ( priv->default_route.v6_has + && !ip6_config_merge_and_apply (self, TRUE)) _LOGW (LOGD_IP6, "Failed to update IPv6 default route metric"); } } @@ -1858,7 +1913,7 @@ nm_device_check_connectivity (NMDevice *self, /* Kick off a real connectivity check. */ nm_connectivity_check_async (nm_connectivity_get (), - nm_device_get_iface (self), + nm_device_get_ip_iface (self), concheck_cb, data); return; @@ -2069,7 +2124,7 @@ nm_device_master_release_one_slave (NMDevice *self, NMDevice *slave, gboolean co static gboolean can_unmanaged_external_down (NMDevice *self) { - return !NM_DEVICE_GET_PRIVATE (self)->is_nm_owned + return !NM_DEVICE_GET_PRIVATE (self)->nm_owned && nm_device_is_software (self); } @@ -2167,11 +2222,21 @@ nm_device_update_dynamic_ip_setup (NMDevice *self) } } +/*****************************************************************************/ + +static void +carrier_changed_notify (NMDevice *self, gboolean carrier) +{ + /* stub */ +} + static void carrier_changed (NMDevice *self, gboolean carrier) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NM_DEVICE_GET_CLASS (self)->carrier_changed_notify (self, carrier); + if (priv->state <= NM_DEVICE_STATE_UNMANAGED) return; @@ -2236,7 +2301,7 @@ carrier_changed (NMDevice *self, gboolean carrier) #define LINK_DISCONNECT_DELAY 4 static gboolean -link_disconnect_action_cb (gpointer user_data) +carrier_disconnected_action_cb (gpointer user_data) { NMDevice *self = NM_DEVICE (user_data); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); @@ -2244,21 +2309,19 @@ link_disconnect_action_cb (gpointer user_data) _LOGD (LOGD_DEVICE, "link disconnected (calling deferred action) (id=%u)", priv->carrier_defer_id); priv->carrier_defer_id = 0; - - NM_DEVICE_GET_CLASS (self)->carrier_changed (self, FALSE); - + carrier_changed (self, FALSE); return FALSE; } static void -link_disconnect_action_cancel (NMDevice *self) +carrier_disconnected_action_cancel (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + guint id = priv->carrier_defer_id; - if (priv->carrier_defer_id) { - g_source_remove (priv->carrier_defer_id); - _LOGD (LOGD_DEVICE, "link disconnected (canceling deferred action) (id=%u)", priv->carrier_defer_id); - priv->carrier_defer_id = 0; + if (nm_clear_g_source (&priv->carrier_defer_id)) { + _LOGD (LOGD_DEVICE, "link disconnected (canceling deferred action) (id=%u)", + id); } } @@ -2266,7 +2329,6 @@ void nm_device_set_carrier (NMDevice *self, gboolean carrier) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMDeviceClass *klass = NM_DEVICE_GET_CLASS (self); NMDeviceState state = nm_device_get_state (self); if (priv->carrier == carrier) @@ -2277,25 +2339,51 @@ nm_device_set_carrier (NMDevice *self, gboolean carrier) if (priv->carrier) { _LOGI (LOGD_DEVICE, "link connected"); - link_disconnect_action_cancel (self); - klass->carrier_changed (self, TRUE); + carrier_disconnected_action_cancel (self); + carrier_changed (self, TRUE); - if (nm_clear_g_source (&priv->carrier_wait_id)) { - nm_device_remove_pending_action (self, NM_PENDING_ACTION_CARRIER_WAIT, TRUE); + if (priv->carrier_wait_id) { + nm_device_remove_pending_action (self, NM_PENDING_ACTION_CARRIER_WAIT, FALSE); _carrier_wait_check_queued_act_request (self); } - } else if ( state <= NM_DEVICE_STATE_DISCONNECTED - && !priv->queued_act_request) { - _LOGD (LOGD_DEVICE, "link disconnected"); - klass->carrier_changed (self, FALSE); } else { - priv->carrier_defer_id = g_timeout_add_seconds (LINK_DISCONNECT_DELAY, - link_disconnect_action_cb, self); - _LOGD (LOGD_DEVICE, "link disconnected (deferring action for %d seconds) (id=%u)", - LINK_DISCONNECT_DELAY, priv->carrier_defer_id); + if (priv->carrier_wait_id) + nm_device_add_pending_action (self, NM_PENDING_ACTION_CARRIER_WAIT, FALSE); + if ( state <= NM_DEVICE_STATE_DISCONNECTED + && !priv->queued_act_request) { + _LOGD (LOGD_DEVICE, "link disconnected"); + carrier_changed (self, FALSE); + } else { + priv->carrier_defer_id = g_timeout_add_seconds (LINK_DISCONNECT_DELAY, + carrier_disconnected_action_cb, self); + _LOGD (LOGD_DEVICE, "link disconnected (deferring action for %d seconds) (id=%u)", + LINK_DISCONNECT_DELAY, priv->carrier_defer_id); + } + } +} + +static void +nm_device_set_carrier_from_platform (NMDevice *self) +{ + if (nm_device_has_capability (self, NM_DEVICE_CAP_CARRIER_DETECT)) { + if (!nm_device_has_capability (self, NM_DEVICE_CAP_NONSTANDARD_CARRIER)) { + nm_device_set_carrier (self, + nm_platform_link_is_connected (nm_device_get_platform (self), + nm_device_get_ip_ifindex (self))); + } + } else { + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + /* Fake online link when carrier detection is not available. */ + if (!priv->carrier) { + priv->carrier = TRUE; + _notify (self, PROP_CARRIER); + } } } +/*****************************************************************************/ + static void device_recheck_slave_status (NMDevice *self, const NMPlatformLink *plink) { @@ -2427,7 +2515,7 @@ device_link_changed (NMDevice *self) info = *pllink; udi = nm_platform_link_get_udi (nm_device_get_platform (self), info.ifindex); - if (udi && g_strcmp0 (udi, priv->udi)) { + if (udi && !nm_streq0 (udi, priv->udi)) { /* Update UDI to what udev gives us */ g_free (priv->udi); priv->udi = g_strdup (udi); @@ -2707,6 +2795,9 @@ link_type_compatible (NMDevice *self, * nm_device_realize_start(): * @self: the #NMDevice * @plink: an existing platform link or %NULL + * @assume_state_guess_assume: set the guess_assume state. + * @assume_state_connection_uuid: set the connection uuid to assume. + * @set_nm_owned: for software device, if TRUE set nm-owned. * @unmanaged_user_explicit: the user-explicit unmanaged flag to apply * on the device initially. * @out_compatible: %TRUE on return if @self is compatible with @plink @@ -2724,6 +2815,9 @@ link_type_compatible (NMDevice *self, gboolean nm_device_realize_start (NMDevice *self, const NMPlatformLink *plink, + gboolean assume_state_guess_assume, + const char *assume_state_connection_uuid, + gboolean set_nm_owned, NMUnmanFlagOp unmanaged_user_explicit, gboolean *out_compatible, GError **error) @@ -2748,8 +2842,11 @@ nm_device_realize_start (NMDevice *self, plink_copy = *plink; plink = &plink_copy; } - realize_start_setup (self, plink, unmanaged_user_explicit); - + realize_start_setup (self, plink, + assume_state_guess_assume, + assume_state_connection_uuid, + set_nm_owned, + unmanaged_user_explicit); return TRUE; } @@ -2776,9 +2873,9 @@ nm_device_create_and_realize (NMDevice *self, const NMPlatformLink *plink = NULL; /* Must be set before device is realized */ - priv->is_nm_owned = !nm_platform_link_get_by_ifname (nm_device_get_platform (self), priv->iface); + priv->nm_owned = !nm_platform_link_get_by_ifname (nm_device_get_platform (self), priv->iface); - _LOGD (LOGD_DEVICE, "create (is %snm-owned)", priv->is_nm_owned ? "" : "not "); + _LOGD (LOGD_DEVICE, "create (is %snm-owned)", priv->nm_owned ? "" : "not "); /* Create any resources the device needs */ if (NM_DEVICE_GET_CLASS (self)->create_and_realize) { @@ -2788,7 +2885,10 @@ nm_device_create_and_realize (NMDevice *self, plink = &plink_copy; } - realize_start_setup (self, plink, NM_UNMAN_FLAG_OP_FORGET); + realize_start_setup (self, plink, + FALSE, /* assume_state_guess_assume */ + NULL, /* assume_state_connection_uuid */ + FALSE, NM_UNMAN_FLAG_OP_FORGET); nm_device_realize_finish (self, plink); if (nm_device_get_managed (self, FALSE)) { @@ -2808,7 +2908,7 @@ update_device_from_platform_link (NMDevice *self, const NMPlatformLink *plink) g_return_if_fail (plink != NULL); udi = nm_platform_link_get_udi (nm_device_get_platform (self), plink->ifindex); - if (udi && !g_strcmp0 (udi, priv->udi)) { + if (udi && !nm_streq0 (udi, priv->udi)) { g_free (priv->udi); priv->udi = g_strdup (udi); _notify (self, PROP_UDI); @@ -2872,15 +2972,6 @@ config_changed (NMConfig *config, } static void -check_carrier (NMDevice *self) -{ - int ifindex = nm_device_get_ip_ifindex (self); - - if (!nm_device_has_capability (self, NM_DEVICE_CAP_NONSTANDARD_CARRIER)) - nm_device_set_carrier (self, nm_platform_link_is_connected (nm_device_get_platform (self), ifindex)); -} - -static void realize_start_notify (NMDevice *self, const NMPlatformLink *pllink) { @@ -2893,6 +2984,10 @@ realize_start_notify (NMDevice *self, * realize_start_setup(): * @self: the #NMDevice * @plink: the #NMPlatformLink if backed by a kernel netdevice + * @assume_state_guess_assume: set the guess_assume state. + * @assume_state_connection_uuid: set the connection uuid to assume. + * @set_nm_owned: if TRUE and device is a software-device, set nm-owned. + * TRUE. * @unmanaged_user_explicit: the user-explict unmanaged flag to set. * * Update the device from backing resource properties (like hardware @@ -2904,6 +2999,9 @@ realize_start_notify (NMDevice *self, static void realize_start_setup (NMDevice *self, const NMPlatformLink *plink, + gboolean assume_state_guess_assume, + const char *assume_state_connection_uuid, + gboolean set_nm_owned, NMUnmanFlagOp unmanaged_user_explicit) { NMDevicePrivate *priv; @@ -2942,6 +3040,8 @@ realize_start_setup (NMDevice *self, _notify (self, PROP_MTU); } + _assume_state_set (self, assume_state_guess_assume, assume_state_connection_uuid); + nm_device_sys_iface_state_set (self, NM_DEVICE_SYS_IFACE_STATE_EXTERNAL); if (plink) { @@ -2987,6 +3087,13 @@ realize_start_setup (NMDevice *self, _add_capabilities (self, capabilities); + if ( !priv->nm_owned + && set_nm_owned + && nm_device_is_software (self)) { + priv->nm_owned = TRUE; + _LOGD (LOGD_DEVICE, "set nm-owned from state file"); + } + if (!priv->udi) { /* Use a placeholder UDI until we get a real one */ priv->udi = g_strdup_printf ("/virtual/device/placeholder/%d", id++); @@ -3010,16 +3117,7 @@ realize_start_setup (NMDevice *self, self); } - if (nm_device_has_capability (self, NM_DEVICE_CAP_CARRIER_DETECT)) { - check_carrier (self); - _LOGD (LOGD_PLATFORM, - "carrier is %s%s", - priv->carrier ? "ON" : "OFF", - priv->ignore_carrier ? " (but ignored)" : ""); - } else { - /* Fake online link when carrier detection is not available. */ - priv->carrier = TRUE; - } + nm_device_set_carrier_from_platform (self); device_init_sriov_num_vfs (self); @@ -3165,6 +3263,8 @@ nm_device_unrealize (NMDevice *self, gboolean remove_resources, GError **error) _LOGD (LOGD_DEVICE, "unrealize (ifindex %d)", ifindex > 0 ? ifindex : 0); + nm_device_assume_state_reset (self); + if (remove_resources) { if (NM_DEVICE_GET_CLASS (self)->unrealize) { if (!NM_DEVICE_GET_CLASS (self)->unrealize (self, error)) @@ -3326,9 +3426,9 @@ slave_state_changed (NMDevice *slave, _LOGD (LOGD_DEVICE, "slave %s state change %d (%s) -> %d (%s)", nm_device_get_iface (slave), slave_old_state, - state_to_string (slave_old_state), + nm_device_state_to_str (slave_old_state), slave_new_state, - state_to_string (slave_new_state)); + nm_device_state_to_str (slave_new_state)); /* Don't try to enslave slaves until the master is ready */ if (priv->state < NM_DEVICE_STATE_CONFIG) @@ -4014,27 +4114,37 @@ nm_device_master_update_slave_connection (NMDevice *self, } NMConnection * -nm_device_generate_connection (NMDevice *self, NMDevice *master) +nm_device_generate_connection (NMDevice *self, + NMDevice *master, + gboolean *out_maybe_later, + GError **error) { NMDeviceClass *klass = NM_DEVICE_GET_CLASS (self); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); const char *ifname = nm_device_get_iface (self); - NMConnection *connection; + gs_unref_object NMConnection *connection = NULL; NMSetting *s_con; NMSetting *s_ip4; NMSetting *s_ip6; char uuid[37]; const char *ip4_method, *ip6_method; - GError *error = NULL; + GError *local = NULL; const NMPlatformLink *pllink; + NM_SET_OUT (out_maybe_later, FALSE); + /* If update_connection() is not implemented, just fail. */ - if (!klass->update_connection) + if (!klass->update_connection) { + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, + "device class %s does not support generating a connection", + G_OBJECT_TYPE_NAME (self)); return NULL; + } /* Return NULL if device is unconfigured. */ if (!device_has_config (self)) { - _LOGD (LOGD_DEVICE, "device has no existing configuration"); + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, + "device has no existing configuration"); return NULL; } @@ -4057,12 +4167,11 @@ nm_device_generate_connection (NMDevice *self, NMDevice *master) if (!nm_device_master_update_slave_connection (master, self, connection, - &error)) - { - _LOGE (LOGD_DEVICE, "master device '%s' failed to update slave connection: %s", - nm_device_get_iface (master), error->message); - g_error_free (error); - g_object_unref (connection); + &local)) { + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, + "master device '%s' failed to update slave connection: %s", + nm_device_get_iface (master), local->message); + g_error_free (local); return NULL; } } else { @@ -4075,7 +4184,6 @@ nm_device_generate_connection (NMDevice *self, NMDevice *master) pllink = nm_platform_link_get (nm_device_get_platform (self), priv->ifindex); if (pllink && pllink->inet6_token.id) { - _LOGD (LOGD_IP6, "IPv6 tokenized identifier present"); g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE, NM_IN6_ADDR_GEN_MODE_EUI64, NM_SETTING_IP6_CONFIG_TOKEN, nm_utils_inet6_interface_identifier_to_token (pllink->inet6_token, NULL), @@ -4085,11 +4193,11 @@ nm_device_generate_connection (NMDevice *self, NMDevice *master) klass->update_connection (self, connection); - /* Check the connection in case of update_connection() bug. */ - if (!nm_connection_verify (connection, &error)) { - _LOGE (LOGD_DEVICE, "Generated connection does not verify: %s", error->message); - g_clear_error (&error); - g_object_unref (connection); + if (!nm_connection_verify (connection, &local)) { + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, + "generated connection does not verify: %s", + local->message); + g_error_free (local); return NULL; } @@ -4102,26 +4210,28 @@ nm_device_generate_connection (NMDevice *self, NMDevice *master) && g_strcmp0 (ip6_method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) == 0 && !nm_setting_connection_get_master (NM_SETTING_CONNECTION (s_con)) && !priv->slaves) { - _LOGD (LOGD_DEVICE, "ignoring generated connection (no IP and not in master-slave relationship)"); - g_object_unref (connection); - connection = NULL; + NM_SET_OUT (out_maybe_later, TRUE); + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, + "ignoring generated connection (no IP and not in master-slave relationship)"); + return NULL; } /* Ignore any IPv6LL-only, not master connections without slaves, * unless they are in the assume-ipv6ll-only list. */ - if ( connection - && g_strcmp0 (ip4_method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0 + if ( g_strcmp0 (ip4_method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0 && g_strcmp0 (ip6_method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0 && !nm_setting_connection_get_master (NM_SETTING_CONNECTION (s_con)) && !priv->slaves && !nm_config_data_get_assume_ipv6ll_only (NM_CONFIG_GET_DATA, self)) { _LOGD (LOGD_DEVICE, "ignoring generated connection (IPv6LL-only and not in master-slave relationship)"); - g_object_unref (connection); - connection = NULL; + NM_SET_OUT (out_maybe_later, TRUE); + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, + "ignoring generated connection (IPv6LL-only and not in master-slave relationship)"); + return NULL; } - return connection; + return g_steal_pointer (&connection); } gboolean @@ -4291,10 +4401,9 @@ nm_device_emit_recheck_assume (gpointer user_data) priv = NM_DEVICE_GET_PRIVATE (self); priv->recheck_assume_id = 0; - if (!nm_device_get_act_request (self)) { - _LOGD (LOGD_DEVICE, "emit RECHECK_ASSUME signal"); + if (!nm_device_get_act_request (self)) g_signal_emit (self, signals[RECHECK_ASSUME], 0); - } + return G_SOURCE_REMOVE; } @@ -4333,7 +4442,7 @@ recheck_available (gpointer user_data) _LOGD (LOGD_DEVICE, "is %savailable, %s %s", now_available ? "" : "not ", new_state == NM_DEVICE_STATE_UNAVAILABLE ? "no change required for" : "will transition to", - state_to_string (new_state == NM_DEVICE_STATE_UNAVAILABLE ? state : new_state)); + nm_device_state_to_str (new_state == NM_DEVICE_STATE_UNAVAILABLE ? state : new_state)); priv->recheck_available.available_reason = NM_DEVICE_STATE_REASON_NONE; priv->recheck_available.unavailable_reason = NM_DEVICE_STATE_REASON_NONE; @@ -5472,8 +5581,15 @@ ip4_config_merge_and_apply (NMDevice *self, composite = nm_ip4_config_new (nm_device_get_ip_ifindex (self)); init_ip4_config_dns_priority (self, composite); - if (commit) + if (commit) { ensure_con_ip4_config (self); + if (priv->queued_ip4_config_id) { + g_clear_object (&priv->ext_ip4_config); + priv->ext_ip4_config = nm_ip4_config_capture (nm_device_get_platform (self), + nm_device_get_ip_ifindex (self), + FALSE); + } + } if (priv->dev_ip4_config) { nm_ip4_config_merge (composite, priv->dev_ip4_config, @@ -6200,7 +6316,6 @@ ip6_config_merge_and_apply (NMDevice *self, } } - /* If no config was passed in, create a new one */ composite = nm_ip6_config_new (nm_device_get_ip_ifindex (self)); nm_ip6_config_set_privacy (composite, priv->ndisc ? @@ -6208,8 +6323,19 @@ ip6_config_merge_and_apply (NMDevice *self, NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN); init_ip6_config_dns_priority (self, composite); - if (commit) + if (commit) { ensure_con_ip6_config (self); + if (priv->queued_ip6_config_id) { + g_clear_object (&priv->ext_ip6_config); + g_clear_object (&priv->ext_ip6_config_captured); + priv->ext_ip6_config_captured = nm_ip6_config_capture (nm_device_get_platform (self), + nm_device_get_ip_ifindex (self), + FALSE, + NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN); + if (priv->ext_ip6_config_captured) + priv->ext_ip6_config = nm_ip6_config_new_cloned (priv->ext_ip6_config_captured); + } + } /* Merge all the IP configs into the composite config */ if (priv->ac_ip6_config) { @@ -7023,7 +7149,7 @@ nm_device_get_configured_mtu_for_wired (NMDevice *self, gboolean *out_is_user_co } *out_is_user_config = FALSE; - return NM_DEVICE_DEFAULT_MTU_WIRED; + return 0; } /*****************************************************************************/ @@ -7725,7 +7851,7 @@ act_stage3_ip6_config_start (NMDevice *self, nm_platform_process_events (nm_device_get_platform (self)); g_clear_object (&priv->ext_ip6_config_captured); priv->ext_ip6_config_captured = nm_ip6_config_capture (nm_device_get_platform (self), - nm_device_get_ifindex (self), + nm_device_get_ip_ifindex (self), FALSE, NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN); @@ -8649,9 +8775,9 @@ _update_ip4_address (NMDevice *self) } gboolean -nm_device_get_is_nm_owned (NMDevice *self) +nm_device_is_nm_owned (NMDevice *self) { - return NM_DEVICE_GET_PRIVATE (self)->is_nm_owned; + return NM_DEVICE_GET_PRIVATE (self)->nm_owned; } /* @@ -8712,7 +8838,7 @@ delete_on_deactivate_check_and_schedule (NMDevice *self, int ifindex) if (ifindex <= 0) return; - if (!priv->is_nm_owned) + if (!priv->nm_owned) return; if (priv->queued_act_request) return; @@ -9035,10 +9161,12 @@ check_and_reapply_connection (NMDevice *self, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS, &diffs); - if (diffs && nm_audit_manager_audit_enabled (nm_audit_manager_get ())) - *audit_args = nm_utils_format_con_diff_for_audit (diffs); - else - *audit_args = NULL; + if (audit_args) { + if (diffs && nm_audit_manager_audit_enabled (nm_audit_manager_get ())) + *audit_args = nm_utils_format_con_diff_for_audit (diffs); + else + *audit_args = NULL; + } /************************************************************************** * check for unsupported changes and reject to reapply @@ -9140,6 +9268,20 @@ check_and_reapply_connection (NMDevice *self, return TRUE; } +gboolean +nm_device_reapply (NMDevice *self, + NMConnection *connection, + GError **error) +{ + g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + + return check_and_reapply_connection (self, + connection, + 0, + NULL, + error); +} + typedef struct { NMConnection *connection; guint64 version_id; @@ -10286,12 +10428,12 @@ static gboolean carrier_wait_timeout (gpointer user_data) { NMDevice *self = NM_DEVICE (user_data); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NM_DEVICE_GET_PRIVATE (self)->carrier_wait_id = 0; - nm_device_remove_pending_action (self, NM_PENDING_ACTION_CARRIER_WAIT, TRUE); - - _carrier_wait_check_queued_act_request (self); - + priv->carrier_wait_id = 0; + nm_device_remove_pending_action (self, NM_PENDING_ACTION_CARRIER_WAIT, FALSE); + if (!priv->carrier) + _carrier_wait_check_queued_act_request (self); return G_SOURCE_REMOVE; } @@ -10333,8 +10475,7 @@ nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware) } /* Store carrier immediately. */ - if (nm_device_has_capability (self, NM_DEVICE_CAP_CARRIER_DETECT)) - check_carrier (self); + nm_device_set_carrier_from_platform (self); device_is_up = nm_device_is_up (self); if (block && !device_is_up) { @@ -10369,8 +10510,14 @@ nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware) * a timeout is reached. */ if (nm_device_has_capability (self, NM_DEVICE_CAP_CARRIER_DETECT)) { - if (!nm_clear_g_source (&priv->carrier_wait_id)) - nm_device_add_pending_action (self, NM_PENDING_ACTION_CARRIER_WAIT, TRUE); + /* we start a grace period of 5 seconds during which we will schedule + * a pending action whenever we have no carrier. + * + * If during that time carrier goes away, we declare the interface + * as not ready. */ + nm_clear_g_source (&priv->carrier_wait_id); + if (!priv->carrier) + nm_device_add_pending_action (self, NM_PENDING_ACTION_CARRIER_WAIT, FALSE); priv->carrier_wait_id = g_timeout_add_seconds (5, carrier_wait_timeout, self); } @@ -11812,7 +11959,7 @@ nm_device_add_pending_action (NMDevice *self, const char *action, gboolean asser count + g_slist_length (iter), action); g_return_val_if_reached (FALSE); } else { - _LOGD (LOGD_DEVICE, "add_pending_action (%d): '%s' already pending (expected)", + _LOGT (LOGD_DEVICE, "add_pending_action (%d): '%s' already pending (expected)", count + g_slist_length (iter), action); } return FALSE; @@ -11873,7 +12020,7 @@ nm_device_remove_pending_action (NMDevice *self, const char *action, gboolean as _LOGW (LOGD_DEVICE, "remove_pending_action (%d): '%s' not pending", count, action); g_return_val_if_reached (FALSE); } else - _LOGD (LOGD_DEVICE, "remove_pending_action (%d): '%s' not pending (expected)", count, action); + _LOGT (LOGD_DEVICE, "remove_pending_action (%d): '%s' not pending (expected)", count, action); return FALSE; } @@ -12058,11 +12205,6 @@ nm_device_cleanup (NMDevice *self, NMDeviceStateReason reason, CleanupType clean /* master: release slaves */ nm_device_master_release_slaves (self); - /* slave: mark no longer enslaved */ - if ( priv->master - && nm_platform_link_get_master (nm_device_get_platform (self), priv->ifindex) <= 0) - nm_device_master_release_one_slave (priv->master, self, FALSE, NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); - /* Take out any entries in the routing table and any IP address the device had. */ ifindex = nm_device_get_ip_ifindex (self); if (ifindex > 0) { @@ -12071,6 +12213,11 @@ nm_device_cleanup (NMDevice *self, NMDeviceStateReason reason, CleanupType clean } } + /* slave: mark no longer enslaved */ + if ( priv->master + && nm_platform_link_get_master (nm_device_get_platform (self), priv->ifindex) <= 0) + nm_device_master_release_one_slave (priv->master, self, FALSE, NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); + if (priv->lldp_listener) nm_lldp_listener_stop (priv->lldp_listener); @@ -12411,24 +12558,20 @@ _set_state_full (NMDevice *self, if ( (priv->state == state) && ( state != NM_DEVICE_STATE_UNAVAILABLE || !priv->firmware_missing)) { - _LOGD (LOGD_DEVICE, "state change: %s -> %s (reason '%s') [%d %d %d]%s", - state_to_string (old_state), - state_to_string (state), + _LOGD (LOGD_DEVICE, "state change: %s -> %s (reason '%s', internal state '%s'%s)", + nm_device_state_to_str (old_state), + nm_device_state_to_str (state), reason_to_string (reason), - old_state, - state, - reason, - priv->firmware_missing ? " (missing firmware)" : ""); + _sys_iface_state_to_str (priv->sys_iface_state), + priv->firmware_missing ? ", missing firmware" : ""); return; } - _LOGI (LOGD_DEVICE, "state change: %s -> %s (reason '%s') [%d %d %d]", - state_to_string (old_state), - state_to_string (state), + _LOGI (LOGD_DEVICE, "state change: %s -> %s (reason '%s', internal state '%s')", + nm_device_state_to_str (old_state), + nm_device_state_to_str (state), reason_to_string (reason), - old_state, - state, - reason); + _sys_iface_state_to_str (priv->sys_iface_state)); priv->in_state_changed = TRUE; @@ -12453,6 +12596,9 @@ _set_state_full (NMDevice *self, NM_DEVICE_SYS_IFACE_STATE_ASSUME)) nm_device_sys_iface_state_set (self, NM_DEVICE_SYS_IFACE_STATE_MANAGED); + if (state > NM_DEVICE_STATE_DISCONNECTED) + nm_device_assume_state_reset (self); + if (state <= NM_DEVICE_STATE_UNAVAILABLE) { if (available_connections_del_all (self)) _notify (self, PROP_AVAILABLE_CONNECTIONS); @@ -12745,7 +12891,7 @@ queued_state_set (gpointer user_data) nm_assert (priv->queued_state.id); _LOGD (LOGD_DEVICE, "queue-state[%s, reason:%s, id:%u]: %s", - state_to_string (priv->queued_state.state), + nm_device_state_to_str (priv->queued_state.state), reason_to_string (priv->queued_state.reason), priv->queued_state.id, "change state"); @@ -12776,7 +12922,7 @@ nm_device_queue_state (NMDevice *self, if (priv->queued_state.id && priv->queued_state.state == state) { _LOGD (LOGD_DEVICE, "queue-state[%s, reason:%s, id:%u]: %s%s%s%s", - state_to_string (priv->queued_state.state), + nm_device_state_to_str (priv->queued_state.state), reason_to_string (priv->queued_state.reason), priv->queued_state.id, "ignore queuing same state change", @@ -12792,7 +12938,7 @@ nm_device_queue_state (NMDevice *self, /* We should only ever have one delayed state transition at a time */ if (priv->queued_state.id) { _LOGW (LOGD_DEVICE, "queue-state[%s, reason:%s, id:%u]: %s", - state_to_string (priv->queued_state.state), + nm_device_state_to_str (priv->queued_state.state), reason_to_string (priv->queued_state.reason), priv->queued_state.id, "replace previously queued state change"); @@ -12805,7 +12951,7 @@ nm_device_queue_state (NMDevice *self, priv->queued_state.id = g_idle_add (queued_state_set, self); _LOGD (LOGD_DEVICE, "queue-state[%s, reason:%s, id:%u]: %s", - state_to_string (state), + nm_device_state_to_str (state), reason_to_string (reason), priv->queued_state.id, "queue state change"); @@ -12820,7 +12966,7 @@ queued_state_clear (NMDevice *self) return; _LOGD (LOGD_DEVICE, "queue-state[%s, reason:%s, id:%u]: %s", - state_to_string (priv->queued_state.state), + nm_device_state_to_str (priv->queued_state.state), reason_to_string (priv->queued_state.reason), priv->queued_state.id, "clear queued state change"); @@ -13726,6 +13872,8 @@ dispose (GObject *object) nm_clear_g_cancellable (&priv->deactivating_cancellable); + nm_device_assume_state_reset (self); + _parent_set_ifindex (self, 0, FALSE); platform = nm_device_get_platform (self); @@ -13767,7 +13915,7 @@ dispose (GObject *object) nm_clear_g_source (&priv->stats.timeout_id); - link_disconnect_action_cancel (self); + carrier_disconnected_action_cancel (self); if (priv->ifindex > 0) { priv->ifindex = 0; @@ -13782,7 +13930,8 @@ dispose (GObject *object) available_connections_del_all (self); - nm_clear_g_source (&priv->carrier_wait_id); + if (nm_clear_g_source (&priv->carrier_wait_id)) + nm_device_remove_pending_action (self, NM_PENDING_ACTION_CARRIER_WAIT, FALSE); _clear_queued_act_request (priv); @@ -13854,14 +14003,11 @@ set_property (GObject *object, guint prop_id, switch (prop_id) { case PROP_UDI: - if (g_value_get_string (value)) { - g_free (priv->udi); - priv->udi = g_value_dup_string (value); - } + /* construct-only */ + priv->udi = g_value_dup_string (value); break; case PROP_IFACE: /* construct-only */ - g_return_if_fail (!priv->iface); priv->iface = g_value_dup_string (value); break; case PROP_DRIVER: @@ -13885,9 +14031,14 @@ set_property (GObject *object, guint prop_id, NMDeviceStateReason reason; managed = g_value_get_boolean (value); - if (managed) + if (managed) { reason = NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED; - else { + if (NM_IN_SET_TYPED (NMDeviceSysIfaceState, + priv->sys_iface_state, + NM_DEVICE_SYS_IFACE_STATE_EXTERNAL, + NM_DEVICE_SYS_IFACE_STATE_REMOVED)) + nm_device_sys_iface_state_set (self, NM_DEVICE_SYS_IFACE_STATE_ASSUME); + } else { reason = NM_DEVICE_STATE_REASON_REMOVED; nm_device_sys_iface_state_set (self, NM_DEVICE_SYS_IFACE_STATE_REMOVED); } @@ -13956,28 +14107,43 @@ get_property (GObject *object, guint prop_id, switch (prop_id) { case PROP_UDI: - g_value_set_string (value, priv->udi); + /* UDI is (depending on the device type) a path to sysfs and can contain + * non-UTF-8. + * ip link add name $'d\xccf\\c' type dummy */ + g_value_take_string (value, + nm_utils_str_utf8safe_escape_cp (priv->udi, + NM_UTILS_STR_UTF8_SAFE_FLAG_NONE)); break; case PROP_IFACE: - g_value_set_string (value, priv->iface); + g_value_take_string (value, + nm_utils_str_utf8safe_escape_cp (priv->iface, + NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL)); break; case PROP_IP_IFACE: - if (ip_config_valid (priv->state)) - g_value_set_string (value, nm_device_get_ip_iface (self)); - else + if (ip_config_valid (priv->state)) { + g_value_take_string (value, + nm_utils_str_utf8safe_escape_cp (nm_device_get_ip_iface (self), + NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL)); + } else g_value_set_string (value, NULL); break; case PROP_IFINDEX: g_value_set_int (value, priv->ifindex); break; case PROP_DRIVER: - g_value_set_string (value, priv->driver); + g_value_take_string (value, + nm_utils_str_utf8safe_escape_cp (priv->driver, + NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL)); break; case PROP_DRIVER_VERSION: - g_value_set_string (value, priv->driver_version); + g_value_take_string (value, + nm_utils_str_utf8safe_escape_cp (priv->driver_version, + NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL)); break; case PROP_FIRMWARE_VERSION: - g_value_set_string (value, priv->firmware_version); + g_value_take_string (value, + nm_utils_str_utf8safe_escape_cp (priv->firmware_version, + NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL)); break; case PROP_CAPABILITIES: g_value_set_uint (value, (priv->capabilities & ~NM_DEVICE_CAP_INTERNAL_MASK)); @@ -14161,7 +14327,7 @@ nm_device_class_init (NMDeviceClass *klass) klass->can_unmanaged_external_down = can_unmanaged_external_down; klass->realize_start_notify = realize_start_notify; klass->unrealize_notify = unrealize_notify; - klass->carrier_changed = carrier_changed; + klass->carrier_changed_notify = carrier_changed_notify; klass->get_ip_iface_identifier = get_ip_iface_identifier; klass->unmanaged_on_quit = unmanaged_on_quit; klass->deactivate_reset_hw_addr = deactivate_reset_hw_addr; @@ -14172,7 +14338,7 @@ nm_device_class_init (NMDeviceClass *klass) obj_properties[PROP_UDI] = g_param_spec_string (NM_DEVICE_UDI, "", "", NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT | + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); obj_properties[PROP_IFACE] = g_param_spec_string (NM_DEVICE_IFACE, "", "", diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index be328eb6..6d17d7c9 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -261,7 +261,7 @@ typedef struct { gboolean (*can_unmanaged_external_down) (NMDevice *self); /* Carrier state (IFF_LOWER_UP) */ - void (*carrier_changed) (NMDevice *, gboolean carrier); + void (*carrier_changed_notify) (NMDevice *, gboolean carrier); gboolean (* get_ip_iface_identifier) (NMDevice *self, NMUtilsIPv6IfaceId *out_iid); @@ -421,6 +421,15 @@ NMPlatform *nm_device_get_platform (NMDevice *self); const char * nm_device_get_udi (NMDevice *dev); const char * nm_device_get_iface (NMDevice *dev); + +static inline const char * +_nm_device_get_iface (NMDevice *device) +{ + /* like nm_device_get_iface(), but gracefully accept NULL without + * asserting. */ + return device ? nm_device_get_iface (device) : NULL; +} + int nm_device_get_ifindex (NMDevice *dev); gboolean nm_device_is_software (NMDevice *dev); gboolean nm_device_is_real (NMDevice *dev); @@ -487,7 +496,10 @@ void nm_device_removed (NMDevice *self, gboolean unconf gboolean nm_device_is_available (NMDevice *dev, NMDeviceCheckDevAvailableFlags flags); gboolean nm_device_has_carrier (NMDevice *dev); -NMConnection * nm_device_generate_connection (NMDevice *self, NMDevice *master); +NMConnection * nm_device_generate_connection (NMDevice *self, + NMDevice *master, + gboolean *out_maybe_later, + GError **error); gboolean nm_device_master_update_slave_connection (NMDevice *master, NMDevice *slave, @@ -605,12 +617,24 @@ void nm_device_set_unmanaged_by_user_settings (NMDevice *self); void nm_device_set_unmanaged_by_user_udev (NMDevice *self); void nm_device_set_unmanaged_by_quitting (NMDevice *device); -gboolean nm_device_get_is_nm_owned (NMDevice *device); +gboolean nm_device_is_nm_owned (NMDevice *device); gboolean nm_device_has_capability (NMDevice *self, NMDeviceCapabilities caps); +/*****************************************************************************/ + +void nm_device_assume_state_get (NMDevice *self, + gboolean *out_assume_state_guess_assume, + const char **out_assume_state_connection_uuid); +void nm_device_assume_state_reset (NMDevice *self); + +/*****************************************************************************/ + gboolean nm_device_realize_start (NMDevice *device, const NMPlatformLink *plink, + gboolean assume_state_guess_assume, + const char *assume_state_connection_uuid, + gboolean set_nm_owned, NMUnmanFlagOp unmanaged_user_explicit, gboolean *out_compatible, GError **error); @@ -675,6 +699,9 @@ const NMPlatformIP6Route *nm_device_get_ip6_default_route (NMDevice *self, gbool void nm_device_spawn_iface_helper (NMDevice *self); +gboolean nm_device_reapply (NMDevice *self, + NMConnection *connection, + GError **error); void nm_device_reapply_settings_immediately (NMDevice *self); void nm_device_update_firewall_zone (NMDevice *self); @@ -708,4 +735,7 @@ void nm_device_check_connectivity (NMDevice *self, gpointer user_data); NMConnectivityState nm_device_get_connectivity_state (NMDevice *self); + +const char *nm_device_state_to_str (NMDeviceState state); + #endif /* __NETWORKMANAGER_DEVICE_H__ */ diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index 7359be96..20692ed9 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -2742,7 +2742,7 @@ get_configured_mtu (NMDevice *device, gboolean *out_is_user_config) } } *out_is_user_config = (mtu != 0); - return mtu ?: NM_DEVICE_DEFAULT_MTU_WIRELESS; + return mtu; } static gboolean diff --git a/src/dhcp/nm-dhcp-utils.c b/src/dhcp/nm-dhcp-utils.c index e020ca33..e55a21b4 100644 --- a/src/dhcp/nm-dhcp-utils.c +++ b/src/dhcp/nm-dhcp-utils.c @@ -450,43 +450,6 @@ nm_dhcp_utils_ip4_config_from_options (int ifindex, } } - /* - * RFC 2132, section 9.7 - * DHCP clients use the contents of the 'server identifier' field - * as the destination address for any DHCP messages unicast to - * the DHCP server. - * - * Some ISP's provide leases from central servers that are on - * different subnets that the address offered. If the host - * does not configure the interface as the default route, the - * dhcp server may not be reachable via unicast, and a host - * specific route is needed. - **/ - str = g_hash_table_lookup (options, "dhcp_server_identifier"); - if (str) { - if (inet_pton (AF_INET, str, &tmp_addr) > 0) { - - _LOG2I (LOGD_DHCP4, iface, " server identifier %s", str); - if ( nm_utils_ip4_address_clear_host_address(tmp_addr, address.plen) != nm_utils_ip4_address_clear_host_address(address.address, address.plen) - && !nm_ip4_config_get_direct_route_for_host (ip4_config, tmp_addr)) { - /* DHCP server not on assigned subnet and the no direct route was returned. Add route */ - NMPlatformIP4Route route = { 0 }; - - route.network = tmp_addr; - route.plen = 32; - /* this will be a device route if gwaddr is 0 */ - route.gateway = gwaddr; - route.rt_source = NM_IP_CONFIG_SOURCE_DHCP; - route.metric = priority; - nm_ip4_config_add_route (ip4_config, &route); - _LOG2D (LOGD_IP, iface, "adding route for server identifier: %s", - nm_platform_ip4_route_to_string (&route, NULL, 0)); - } - } - else - _LOG2W (LOGD_DHCP4, iface, "ignoring invalid server identifier '%s'", str); - } - str = g_hash_table_lookup (options, "dhcp_lease_time"); if (str) { address.lifetime = address.preferred = strtoul (str, NULL, 10); diff --git a/src/dns/nm-dns-dnsmasq.c b/src/dns/nm-dns-dnsmasq.c index 5223638e..a6204ae4 100644 --- a/src/dns/nm-dns-dnsmasq.c +++ b/src/dns/nm-dns-dnsmasq.c @@ -554,13 +554,15 @@ start_dnsmasq (NMDnsDnsmasq *self) static gboolean update (NMDnsPlugin *plugin, - const NMDnsIPConfigData **configs, + const GPtrArray *configs, const NMGlobalDnsConfig *global_config, const char *hostname) { NMDnsDnsmasq *self = NM_DNS_DNSMASQ (plugin); NMDnsDnsmasqPrivate *priv = NM_DNS_DNSMASQ_GET_PRIVATE (self); GVariantBuilder servers; + guint i; + int prio, first_prio; start_dnsmasq (self); @@ -569,9 +571,13 @@ update (NMDnsPlugin *plugin, if (global_config) add_global_config (self, &servers, global_config); else { - while (*configs) { - add_ip_config_data (self, &servers, *configs); - configs++; + for (i = 0; i < configs->len; i++) { + prio = nm_dns_ip_config_data_get_dns_priority (configs->pdata[i]); + if (i == 0) + first_prio = prio; + else if (first_prio < 0 && first_prio != prio) + break; + add_ip_config_data (self, &servers, configs->pdata[i]); } } diff --git a/src/dns/nm-dns-manager.c b/src/dns/nm-dns-manager.c index 1f7eb964..f443f340 100644 --- a/src/dns/nm-dns-manager.c +++ b/src/dns/nm-dns-manager.c @@ -197,6 +197,19 @@ NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_config_type_to_string, NMDnsIPConfigType, NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_IP_CONFIG_TYPE_VPN, "vpn"), ); +int +nm_dns_ip_config_data_get_dns_priority (const NMDnsIPConfigData *config) +{ + g_return_val_if_fail (config, 0); + + if (NM_IS_IP4_CONFIG (config->config)) + return nm_ip4_config_get_dns_priority (config->config); + else if (NM_IS_IP6_CONFIG (config->config)) + return nm_ip6_config_get_dns_priority (config->config); + else + g_return_val_if_reached (0); +} + static NMDnsIPConfigData * ip_config_data_new (gpointer config, NMDnsIPConfigType type, const char *iface) { @@ -226,19 +239,10 @@ ip_config_data_destroy (gpointer ptr) static gint ip_config_data_compare (const NMDnsIPConfigData *a, const NMDnsIPConfigData *b) { - gboolean a_v4, b_v4; - gint a_prio, b_prio; - - a_v4 = NM_IS_IP4_CONFIG (a->config); - b_v4 = NM_IS_IP4_CONFIG (b->config); + int a_prio, b_prio; - a_prio = a_v4 ? - nm_ip4_config_get_dns_priority ((NMIP4Config *) a->config) : - nm_ip6_config_get_dns_priority ((NMIP6Config *) a->config); - - b_prio = b_v4 ? - nm_ip4_config_get_dns_priority ((NMIP4Config *) b->config) : - nm_ip6_config_get_dns_priority ((NMIP6Config *) b->config); + a_prio = nm_dns_ip_config_data_get_dns_priority (a); + b_prio = nm_dns_ip_config_data_get_dns_priority (b); /* Configurations with lower priority value first */ if (a_prio < b_prio) @@ -990,11 +994,9 @@ _collect_resolv_conf_data (NMDnsManager *self, /* only for logging context, no o char ***out_options, char ***out_nameservers, char ***out_nis_servers, - const char **out_nis_domain, - NMDnsIPConfigData ***out_plugin_confs) + const char **out_nis_domain) { - NMDnsIPConfigData **plugin_confs = NULL; - guint i, num, len; + guint i, j, num, len; NMResolvConfData rc = { .nameservers = g_ptr_array_new (), .searches = g_ptr_array_new (), @@ -1007,27 +1009,23 @@ _collect_resolv_conf_data (NMDnsManager *self, /* only for logging context, no o merge_global_dns_config (&rc, global_config); else { nm_auto_free_gstring GString *tmp_gstring = NULL; - int prio, prev_prio = 0; + int prio, first_prio = 0; NMDnsIPConfigData *current; - gboolean skip = FALSE, v4; + gboolean v4; - plugin_confs = g_new (NMDnsIPConfigData *, configs->len + 1); + for (i = 0, j = 0; i < configs->len; i++) { + gboolean skip = FALSE; - for (i = 0; i < configs->len; i++) { current = configs->pdata[i]; - v4 = NM_IS_IP4_CONFIG (current->config); - prio = v4 ? - nm_ip4_config_get_dns_priority ((NMIP4Config *) current->config) : - nm_ip6_config_get_dns_priority ((NMIP6Config *) current->config); + prio = nm_dns_ip_config_data_get_dns_priority (current); - if (prev_prio < 0 && prio != prev_prio) { + if (i == 0) + first_prio = prio; + else if (first_prio < 0 && first_prio != prio) skip = TRUE; - plugin_confs[i] = NULL; - } - - prev_prio = prio; + v4 = NM_IS_IP4_CONFIG (current->config); if ( ( v4 && nm_ip4_config_get_num_nameservers ((NMIP4Config *) current->config)) || (!v4 && nm_ip6_config_get_num_nameservers ((NMIP6Config *) current->config))) { _LOGT ("config: %8d %-7s v%c %-16s %s: %s", @@ -1039,12 +1037,9 @@ _collect_resolv_conf_data (NMDnsManager *self, /* only for logging context, no o get_nameserver_list (current->config, &tmp_gstring)); } - if (!skip) { + if (!skip) merge_one_ip_config_data (&rc, current); - plugin_confs[i] = current; - } } - plugin_confs[i] = NULL; } /* If the hostname is a FQDN ("dcbw.example.com"), then add the domain part of it @@ -1078,7 +1073,6 @@ _collect_resolv_conf_data (NMDnsManager *self, /* only for logging context, no o } g_ptr_array_set_size (rc.searches, i); - *out_plugin_confs = plugin_confs; *out_searches = _ptrarray_to_strv (rc.searches); *out_options = _ptrarray_to_strv (rc.options); *out_nameservers = _ptrarray_to_strv (rc.nameservers); @@ -1102,7 +1096,6 @@ update_dns (NMDnsManager *self, SpawnResult result = SR_ERROR; NMConfigData *data; NMGlobalDnsConfig *global_config; - gs_free NMDnsIPConfigData **plugin_confs = NULL; g_return_val_if_fail (!error || !*error, FALSE); @@ -1136,8 +1129,7 @@ update_dns (NMDnsManager *self, compute_hash (self, global_config, priv->hash); _collect_resolv_conf_data (self, global_config, priv->configs, priv->hostname, - &searches, &options, &nameservers, &nis_servers, &nis_domain, - &plugin_confs); + &searches, &options, &nameservers, &nis_servers, &nis_domain); /* Let any plugins do their thing first */ if (priv->plugin) { @@ -1155,7 +1147,7 @@ update_dns (NMDnsManager *self, _LOGD ("update-dns: updating plugin %s", plugin_name); if (!nm_dns_plugin_update (plugin, - (const NMDnsIPConfigData **) plugin_confs, + priv->configs, global_config, priv->hostname)) { _LOGW ("update-dns: plugin %s update failed", plugin_name); diff --git a/src/dns/nm-dns-manager.h b/src/dns/nm-dns-manager.h index 899e4bb8..ee835927 100644 --- a/src/dns/nm-dns-manager.h +++ b/src/dns/nm-dns-manager.h @@ -44,6 +44,8 @@ typedef struct { char *iface; } NMDnsIPConfigData; +int nm_dns_ip_config_data_get_dns_priority (const NMDnsIPConfigData *config); + #define NM_TYPE_DNS_MANAGER (nm_dns_manager_get_type ()) #define NM_DNS_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), NM_TYPE_DNS_MANAGER, NMDnsManager)) #define NM_DNS_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), NM_TYPE_DNS_MANAGER, NMDnsManagerClass)) diff --git a/src/dns/nm-dns-plugin.c b/src/dns/nm-dns-plugin.c index 00729c93..5805b7d8 100644 --- a/src/dns/nm-dns-plugin.c +++ b/src/dns/nm-dns-plugin.c @@ -77,7 +77,7 @@ G_DEFINE_TYPE_EXTENDED (NMDnsPlugin, nm_dns_plugin, G_TYPE_OBJECT, G_TYPE_FLAG_A gboolean nm_dns_plugin_update (NMDnsPlugin *self, - const NMDnsIPConfigData **configs, + const GPtrArray *configs, const NMGlobalDnsConfig *global_config, const char *hostname) { diff --git a/src/dns/nm-dns-plugin.h b/src/dns/nm-dns-plugin.h index 12109441..996695c0 100644 --- a/src/dns/nm-dns-plugin.h +++ b/src/dns/nm-dns-plugin.h @@ -50,7 +50,7 @@ typedef struct { * configuration. */ gboolean (*update) (NMDnsPlugin *self, - const NMDnsIPConfigData **configs, + const GPtrArray *configs, const NMGlobalDnsConfig *global_config, const char *hostname); @@ -80,7 +80,7 @@ gboolean nm_dns_plugin_is_caching (NMDnsPlugin *self); const char *nm_dns_plugin_get_name (NMDnsPlugin *self); gboolean nm_dns_plugin_update (NMDnsPlugin *self, - const NMDnsIPConfigData **configs, + const GPtrArray *configs, const NMGlobalDnsConfig *global_config, const char *hostname); diff --git a/src/dns/nm-dns-systemd-resolved.c b/src/dns/nm-dns-systemd-resolved.c index ed165618..fce1fef1 100644 --- a/src/dns/nm-dns-systemd-resolved.c +++ b/src/dns/nm-dns-systemd-resolved.c @@ -102,12 +102,12 @@ call_done (GObject *source, GAsyncResult *r, gpointer user_data) static void add_interface_configuration (NMDnsSystemdResolved *self, GArray *interfaces, - const NMDnsIPConfigData *data) + const NMDnsIPConfigData *data, + gboolean skip) { int i; InterfaceConfig *ic = NULL; int ifindex; - NMDevice *device; if (NM_IS_IP4_CONFIG (data->config)) ifindex = nm_ip4_config_get_ifindex (data->config); @@ -116,8 +116,6 @@ add_interface_configuration (NMDnsSystemdResolved *self, else g_return_if_reached (); - device = nm_manager_get_device_by_ifindex (nm_manager_get (), ifindex); - for (i = 0; i < interfaces->len; i++) { InterfaceConfig *tic = &g_array_index (interfaces, InterfaceConfig, i); if (ifindex == tic->ifindex) { @@ -133,7 +131,8 @@ add_interface_configuration (NMDnsSystemdResolved *self, ic->ifindex = ifindex; } - ic->configs = g_list_append (ic->configs, data->config); + if (!skip) + ic->configs = g_list_append (ic->configs, data->config); } static void @@ -291,17 +290,25 @@ send_updates (NMDnsSystemdResolved *self) static gboolean update (NMDnsPlugin *plugin, - const NMDnsIPConfigData **configs, + const GPtrArray *configs, const NMGlobalDnsConfig *global_config, const char *hostname) { NMDnsSystemdResolved *self = NM_DNS_SYSTEMD_RESOLVED (plugin); GArray *interfaces = g_array_new (TRUE, TRUE, sizeof (InterfaceConfig)); - const NMDnsIPConfigData **c; - int i; - - for (c = configs; *c != NULL; c++) - add_interface_configuration (self, interfaces, *c); + guint i; + int prio, first_prio = 0; + + for (i = 0; i < configs->len; i++) { + gboolean skip = FALSE; + + prio = nm_dns_ip_config_data_get_dns_priority (configs->pdata[i]); + if (i == 0) + first_prio = prio; + else if (first_prio < 0 && first_prio != prio) + skip = TRUE; + add_interface_configuration (self, interfaces, configs->pdata[i], skip); + } free_pending_updates (self); diff --git a/src/dns/nm-dns-unbound.c b/src/dns/nm-dns-unbound.c index 6af4bad8..0b80055f 100644 --- a/src/dns/nm-dns-unbound.c +++ b/src/dns/nm-dns-unbound.c @@ -39,7 +39,7 @@ G_DEFINE_TYPE (NMDnsUnbound, nm_dns_unbound, NM_TYPE_DNS_PLUGIN) static gboolean update (NMDnsPlugin *plugin, - const NMDnsIPConfigData **configs, + const GPtrArray *configs, const NMGlobalDnsConfig *global_config, const char *hostname) { diff --git a/src/nm-active-connection.c b/src/nm-active-connection.c index 19c0343f..862754f9 100644 --- a/src/nm-active-connection.c +++ b/src/nm-active-connection.c @@ -111,8 +111,7 @@ static void _device_cleanup (NMActiveConnection *self); static void _settings_connection_notify_flags (NMSettingsConnection *settings_connection, GParamSpec *param, NMActiveConnection *self); -static void _set_activation_type (NMActiveConnection *self, - NMActivationType activation_type); +static void _set_activation_type_managed (NMActiveConnection *self); /*****************************************************************************/ @@ -236,7 +235,7 @@ nm_active_connection_set_state (NMActiveConnection *self, /* assuming connections mean to gracefully take over an externally * configured device. Once activation is complete, an assumed * activation *is* the same as a full activation. */ - _set_activation_type (self, NM_ACTIVATION_TYPE_MANAGED); + _set_activation_type_managed (self); } old_state = priv->state; @@ -755,13 +754,31 @@ _set_activation_type (NMActiveConnection *self, if (priv->activation_type == activation_type) return; + priv->activation_type = activation_type; + + if (priv->settings_connection) { + if (activation_type == NM_ACTIVATION_TYPE_EXTERNAL) + g_signal_connect (priv->settings_connection, "notify::"NM_SETTINGS_CONNECTION_FLAGS, (GCallback) _settings_connection_notify_flags, self); + else + g_signal_handlers_disconnect_by_func (priv->settings_connection, _settings_connection_notify_flags, self); + } +} + +static void +_set_activation_type_managed (NMActiveConnection *self) +{ + NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self); + + if (priv->activation_type == NM_ACTIVATION_TYPE_MANAGED) + return; + _LOGD ("update activation type from %s to %s", nm_activation_type_to_string (priv->activation_type), - nm_activation_type_to_string (activation_type)); - priv->activation_type = activation_type; + nm_activation_type_to_string (NM_ACTIVATION_TYPE_MANAGED)); - if ( priv->activation_type == NM_ACTIVATION_TYPE_MANAGED - && priv->device + _set_activation_type (self, NM_ACTIVATION_TYPE_MANAGED); + + if ( priv->device && self == NM_ACTIVE_CONNECTION (nm_device_get_act_request (priv->device)) && NM_IN_SET (nm_device_sys_iface_state_get (priv->device), NM_DEVICE_SYS_IFACE_STATE_EXTERNAL, @@ -776,6 +793,8 @@ _settings_connection_notify_flags (NMSettingsConnection *settings_connection, GParamSpec *param, NMActiveConnection *self) { + GError *error = NULL; + nm_assert (NM_IS_ACTIVE_CONNECTION (self)); nm_assert (NM_IS_SETTINGS_CONNECTION (settings_connection)); nm_assert (nm_active_connection_get_activation_type (self) == NM_ACTIVATION_TYPE_EXTERNAL); @@ -784,9 +803,14 @@ _settings_connection_notify_flags (NMSettingsConnection *settings_connection, if (nm_settings_connection_get_nm_generated (settings_connection)) return; - g_signal_handlers_disconnect_by_func (settings_connection, _settings_connection_notify_flags, self); - _set_activation_type (self, NM_ACTIVATION_TYPE_MANAGED); - nm_device_reapply_settings_immediately (nm_active_connection_get_device (self)); + _set_activation_type_managed (self); + if (!nm_device_reapply (nm_active_connection_get_device (self), + NM_CONNECTION (nm_active_connection_get_settings_connection (self)), + &error)) { + _LOGW ("failed to reapply new device settings on previously externally managed device: %s", + error->message); + g_error_free (error); + } } /*****************************************************************************/ @@ -1147,7 +1171,7 @@ set_property (GObject *object, guint prop_id, NM_ACTIVATION_TYPE_ASSUME, NM_ACTIVATION_TYPE_EXTERNAL)) g_return_if_reached (); - priv->activation_type = (NMActivationType) i; + _set_activation_type (self, (NMActivationType) i); break; case PROP_SPECIFIC_OBJECT: tmp = g_value_get_string (value); diff --git a/src/nm-checkpoint.c b/src/nm-checkpoint.c index 3f2f0eaa..d59bc574 100644 --- a/src/nm-checkpoint.c +++ b/src/nm-checkpoint.c @@ -275,6 +275,17 @@ activate: _LOGD ("rollback: reactivating connection %s", nm_settings_connection_get_uuid (connection)); subject = nm_auth_subject_new_internal (); + + /* Disconnect the device if needed. This necessary because now + * the manager prevents the reactivation of the same connection by + * an internal subject. */ + if ( nm_device_get_state (device) > NM_DEVICE_STATE_DISCONNECTED + && nm_device_get_state (device) < NM_DEVICE_STATE_DEACTIVATING) { + nm_device_state_changed (device, + NM_DEVICE_STATE_DEACTIVATING, + NM_DEVICE_STATE_REASON_NEW_ACTIVATION); + } + if (!nm_manager_activate_connection (priv->manager, connection, dev_checkpoint->applied_connection, diff --git a/src/nm-config.c b/src/nm-config.c index 2cdf8556..91c21de7 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -1872,6 +1872,14 @@ _nm_config_state_set (NMConfig *self, #define DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_MANAGED "managed" #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" + +NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_device_state_managed_type_to_str, NMConfigDeviceStateManagedType, + NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT ("unknown"), + NM_UTILS_LOOKUP_STR_ITEM (NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_UNKNOWN, "unknown"), + NM_UTILS_LOOKUP_STR_ITEM (NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_UNMANAGED, "unmanaged"), + NM_UTILS_LOOKUP_STR_ITEM (NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_MANAGED, "managed"), +); static NMConfigDeviceStateData * _config_device_state_data_new (int ifindex, GKeyFile *kf) @@ -1882,26 +1890,29 @@ _config_device_state_data_new (int ifindex, GKeyFile *kf) gs_free char *perm_hw_addr_fake = NULL; gsize connection_uuid_len; gsize perm_hw_addr_fake_len; + gint nm_owned = -1; char *p; nm_assert (ifindex > 0); if (kf) { - gboolean managed; - - managed = nm_config_keyfile_get_boolean (kf, - DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE, - DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_MANAGED, - FALSE); - managed_type = managed - ? NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_MANAGED - : NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_UNMANAGED; - - if (managed) { + 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, @@ -1915,6 +1926,11 @@ _config_device_state_data_new (int ifindex, GKeyFile *kf) 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); } connection_uuid_len = connection_uuid ? strlen (connection_uuid) + 1 : 0; @@ -1928,6 +1944,7 @@ _config_device_state_data_new (int ifindex, GKeyFile *kf) device_state->managed = managed_type; device_state->connection_uuid = NULL; device_state->perm_hw_addr_fake = NULL; + device_state->nm_owned = nm_owned; p = (char *) (&device_state[1]); if (connection_uuid) { @@ -1957,6 +1974,7 @@ nm_config_device_state_load (int ifindex) NMConfigDeviceStateData *device_state; char path[NM_STRLEN (NM_CONFIG_DEVICE_STATE_DIR) + 60]; gs_unref_keyfile GKeyFile *kf = NULL; + const char *nm_owned_str; g_return_val_if_fail (ifindex > 0, NULL); @@ -1967,33 +1985,28 @@ nm_config_device_state_load (int ifindex) g_clear_pointer (&kf, g_key_file_unref); 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" : ""); - if (kf) { - _LOGT ("device-state: read #%d (%s); managed=%d%s%s%s%s%s%s", - ifindex, path, - 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, "", "")); - } else { - _LOGT ("device-state: read #%d (%s); no persistent state", - ifindex, path); - } + + _LOGT ("device-state: %s #%d (%s); managed=%s%s%s%s%s%s%s%s", + 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); return device_state; } -NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_device_state_managed_type_to_str, NMConfigDeviceStateManagedType, - NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT ("unknown"), - NM_UTILS_LOOKUP_STR_ITEM (NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_UNKNOWN, "unknown"), - NM_UTILS_LOOKUP_STR_ITEM (NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_UNMANAGED, "unmanaged"), - NM_UTILS_LOOKUP_STR_ITEM (NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_MANAGED, "managed"), -); - gboolean nm_config_device_state_write (int ifindex, NMConfigDeviceStateManagedType managed, const char *perm_hw_addr_fake, - const char *connection_uuid) + const char *connection_uuid, + gint nm_owned) { char path[NM_STRLEN (NM_CONFIG_DEVICE_STATE_DIR) + 60]; GError *local = NULL; @@ -2028,6 +2041,13 @@ nm_config_device_state_write (int ifindex, DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_CONNECTION_UUID, connection_uuid); } + if (nm_owned >= 0) { + g_key_file_set_boolean (kf, + DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE, + DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_NM_OWNED, + nm_owned); + } + if (!g_key_file_save_to_file (kf, path, &local)) { _LOGW ("device-state: write #%d (%s) failed: %s", ifindex, path, local->message); diff --git a/src/nm-config.h b/src/nm-config.h index 283d6a1b..c5ff7c67 100644 --- a/src/nm-config.h +++ b/src/nm-config.h @@ -63,6 +63,7 @@ #define NM_CONFIG_KEYFILE_KEY_MAIN_DHCP "dhcp" #define NM_CONFIG_KEYFILE_KEY_MAIN_DEBUG "debug" #define NM_CONFIG_KEYFILE_KEY_MAIN_HOSTNAME_MODE "hostname-mode" +#define NM_CONFIG_KEYFILE_KEY_MAIN_SLAVES_ORDER "slaves-order" #define NM_CONFIG_KEYFILE_KEY_LOGGING_BACKEND "backend" #define NM_CONFIG_KEYFILE_KEY_CONFIG_ENABLE "enable" #define NM_CONFIG_KEYFILE_KEY_ATOMIC_SECTION_WAS ".was" @@ -204,13 +205,18 @@ struct _NMConfigDeviceStateData { const char *connection_uuid; const char *perm_hw_addr_fake; + + /* whether the device was nm-owned (0/1) or -1 for + * non-software devices. */ + gint nm_owned; }; NMConfigDeviceStateData *nm_config_device_state_load (int ifindex); gboolean nm_config_device_state_write (int ifindex, NMConfigDeviceStateManagedType managed, const char *perm_hw_addr_fake, - const char *connection_uuid); + const char *connection_uuid, + gint nm_owned); void nm_config_device_state_prune_unseen (GHashTable *seen_ifindexes); /*****************************************************************************/ diff --git a/src/nm-connectivity.c b/src/nm-connectivity.c index 75bb7b63..6f16b28e 100644 --- a/src/nm-connectivity.c +++ b/src/nm-connectivity.c @@ -144,7 +144,7 @@ curl_check_connectivity (CURLM *mhandle, CURLMcode ret) continue; /* Here we have completed a session. Check easy session result. */ - eret = curl_easy_getinfo (msg->easy_handle, CURLINFO_PRIVATE, &cb_data); + eret = curl_easy_getinfo (msg->easy_handle, CURLINFO_PRIVATE, (char **) &cb_data); if (eret != CURLE_OK) { _LOG2E ("curl cannot extract cb_data for easy handle %p, skipping msg", msg->easy_handle); continue; @@ -486,27 +486,28 @@ nm_connectivity_init (NMConnectivity *self) NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self); CURLcode retv; + retv = curl_global_init (CURL_GLOBAL_ALL); + if (retv == CURLE_OK) + priv->curl_mhandle = curl_multi_init (); + + if (!priv->curl_mhandle) + _LOGE ("unable to init cURL, connectivity check will not work"); + else { + curl_multi_setopt (priv->curl_mhandle, CURLMOPT_SOCKETFUNCTION, multi_socket_cb); + curl_multi_setopt (priv->curl_mhandle, CURLMOPT_SOCKETDATA, self); + curl_multi_setopt (priv->curl_mhandle, CURLMOPT_TIMERFUNCTION, multi_timer_cb); + curl_multi_setopt (priv->curl_mhandle, CURLMOPT_TIMERDATA, self); + curl_multi_setopt (priv->curl_mhandle, CURLOPT_VERBOSE, 1); + } + priv->config = g_object_ref (nm_config_get ()); + update_config (self, nm_config_get_data (priv->config)); g_signal_connect (G_OBJECT (priv->config), NM_CONFIG_SIGNAL_CONFIG_CHANGED, G_CALLBACK (config_changed_cb), self); - retv = curl_global_init (CURL_GLOBAL_ALL); - if (retv == CURLE_OK) - priv->curl_mhandle = curl_multi_init (); - - if (priv->curl_mhandle == NULL) { - _LOGE ("cnable to init cURL, connectivity check will not work"); - return; - } - - curl_multi_setopt (priv->curl_mhandle, CURLMOPT_SOCKETFUNCTION, multi_socket_cb); - curl_multi_setopt (priv->curl_mhandle, CURLMOPT_SOCKETDATA, self); - curl_multi_setopt (priv->curl_mhandle, CURLMOPT_TIMERFUNCTION, multi_timer_cb); - curl_multi_setopt (priv->curl_mhandle, CURLMOPT_TIMERDATA, self); - curl_multi_setopt (priv->curl_mhandle, CURLOPT_VERBOSE, 1); } static void diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index 20532e86..ae6af9c3 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -248,6 +248,16 @@ notify_addresses (NMIP4Config *self) _notify (self, PROP_ADDRESSES); } +static gint +sort_captured_addresses (gconstpointer a, gconstpointer b) +{ + const NMPlatformIP4Address *addr_a = a, *addr_b = b; + + /* Primary addresses first */ + return NM_FLAGS_HAS (addr_a->n_ifa_flags, IFA_F_SECONDARY) - + NM_FLAGS_HAS (addr_b->n_ifa_flags, IFA_F_SECONDARY); +} + NMIP4Config * nm_ip4_config_capture (NMPlatform *platform, int ifindex, gboolean capture_resolv_conf) { @@ -269,6 +279,8 @@ nm_ip4_config_capture (NMPlatform *platform, int ifindex, gboolean capture_resol g_array_unref (priv->routes); priv->addresses = nm_platform_ip4_address_get_all (platform, ifindex); + g_array_sort (priv->addresses, sort_captured_addresses); + priv->routes = nm_platform_ip4_route_get_all (platform, ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT); /* Extract gateway from default route */ diff --git a/src/nm-logging.h b/src/nm-logging.h index ff1fac79..91a41412 100644 --- a/src/nm-logging.h +++ b/src/nm-logging.h @@ -306,6 +306,37 @@ gboolean nm_logging_syslog_enabled (void); #define _LOG2t_err(errsv, ...) G_STMT_START { if (FALSE) { _NMLOG2_err (errsv, LOGL_TRACE, __VA_ARGS__); } } G_STMT_END #endif +#define _NMLOG3_ENABLED(level) ( nm_logging_enabled ((level), (_NMLOG3_DOMAIN)) ) + +#define _LOG3T(...) _NMLOG3 (LOGL_TRACE, __VA_ARGS__) +#define _LOG3D(...) _NMLOG3 (LOGL_DEBUG, __VA_ARGS__) +#define _LOG3I(...) _NMLOG3 (LOGL_INFO , __VA_ARGS__) +#define _LOG3W(...) _NMLOG3 (LOGL_WARN , __VA_ARGS__) +#define _LOG3E(...) _NMLOG3 (LOGL_ERR , __VA_ARGS__) + +#define _LOG3T_ENABLED(...) _NMLOG3_ENABLED (LOGL_TRACE, ##__VA_ARGS__) +#define _LOG3D_ENABLED(...) _NMLOG3_ENABLED (LOGL_DEBUG, ##__VA_ARGS__) +#define _LOG3I_ENABLED(...) _NMLOG3_ENABLED (LOGL_INFO , ##__VA_ARGS__) +#define _LOG3W_ENABLED(...) _NMLOG3_ENABLED (LOGL_WARN , ##__VA_ARGS__) +#define _LOG3E_ENABLED(...) _NMLOG3_ENABLED (LOGL_ERR , ##__VA_ARGS__) + +#define _LOG3T_err(errsv, ...) _NMLOG3_err (errsv, LOGL_TRACE, __VA_ARGS__) +#define _LOG3D_err(errsv, ...) _NMLOG3_err (errsv, LOGL_DEBUG, __VA_ARGS__) +#define _LOG3I_err(errsv, ...) _NMLOG3_err (errsv, LOGL_INFO , __VA_ARGS__) +#define _LOG3W_err(errsv, ...) _NMLOG3_err (errsv, LOGL_WARN , __VA_ARGS__) +#define _LOG3E_err(errsv, ...) _NMLOG3_err (errsv, LOGL_ERR , __VA_ARGS__) + +#ifdef NM_MORE_LOGGING +#define _LOG3t_ENABLED(...) _NMLOG3_ENABLED (LOGL_TRACE, ##__VA_ARGS__) +#define _LOG3t(...) _NMLOG3 (LOGL_TRACE, __VA_ARGS__) +#define _LOG3t_err(errsv, ...) _NMLOG3_err (errsv, LOGL_TRACE, __VA_ARGS__) +#else +/* still call the logging macros to get compile time checks, but they will be optimized out. */ +#define _LOG3t_ENABLED(...) ( FALSE && (_NMLOG3_ENABLED (LOGL_TRACE, ##__VA_ARGS__)) ) +#define _LOG3t(...) G_STMT_START { if (FALSE) { _NMLOG3 (LOGL_TRACE, __VA_ARGS__); } } G_STMT_END +#define _LOG3t_err(errsv, ...) G_STMT_START { if (FALSE) { _NMLOG3_err (errsv, LOGL_TRACE, __VA_ARGS__); } } G_STMT_END +#endif + extern void (*_nm_logging_clear_platform_logging_cache) (void); /*****************************************************************************/ diff --git a/src/nm-manager.c b/src/nm-manager.c index a7402195..7662c2e3 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -222,19 +222,64 @@ NM_DEFINE_SINGLETON_INSTANCE (NMManager); #define _NMLOG_PREFIX_NAME "manager" #define _NMLOG(level, domain, ...) \ G_STMT_START { \ - const NMLogLevel __level = (level); \ - const NMLogDomain __domain = (domain); \ + const NMLogLevel _level = (level); \ + const NMLogDomain _domain = (domain); \ \ - if (nm_logging_enabled (__level, __domain)) { \ - const NMManager *const __self = (self); \ - char __sbuf[32]; \ + if (nm_logging_enabled (_level, _domain)) { \ + const NMManager *const _self = (self); \ + char _sbuf[32]; \ \ - _nm_log (__level, __domain, 0, NULL, NULL, \ + _nm_log (_level, _domain, 0, NULL, NULL, \ "%s%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ _NMLOG_PREFIX_NAME, \ - (__self && __self != singleton_instance) \ - ? nm_sprintf_buf (__sbuf, "[%p]", __self) \ - : "" \ + ((_self && _self != singleton_instance) \ + ? nm_sprintf_buf (_sbuf, "[%p]", _self) \ + : "") \ + _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ + } \ + } G_STMT_END + +#define _NMLOG2(level, domain, device, ...) \ + G_STMT_START { \ + const NMLogLevel _level = (level); \ + const NMLogDomain _domain = (domain); \ + \ + if (nm_logging_enabled (_level, _domain)) { \ + const NMManager *const _self = (self); \ + const char *const _ifname = _nm_device_get_iface (device); \ + char _sbuf[32]; \ + \ + _nm_log (_level, _domain, 0, \ + _ifname, NULL, \ + "%s%s: %s%s%s" _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ + _NMLOG_PREFIX_NAME, \ + ((_self && _self != singleton_instance) \ + ? nm_sprintf_buf (_sbuf, "[%p]", _self) \ + : ""), \ + NM_PRINT_FMT_QUOTED (_ifname, "(", _ifname, "): ", "") \ + _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ + } \ + } G_STMT_END + +#define _NMLOG3(level, domain, connection, ...) \ + G_STMT_START { \ + const NMLogLevel _level = (level); \ + const NMLogDomain _domain = (domain); \ + \ + if (nm_logging_enabled (_level, _domain)) { \ + const NMManager *const _self = (self); \ + NMConnection *const _connection = (connection); \ + const char *const _con_id = _nm_connection_get_id (_connection); \ + char _sbuf[32]; \ + \ + _nm_log (_level, _domain, 0, \ + NULL, _nm_connection_get_uuid (_connection), \ + "%s%s: %s%s%s" _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ + _NMLOG_PREFIX_NAME, \ + ((_self && _self != singleton_instance) \ + ? nm_sprintf_buf (_sbuf, "[%p]", _self) \ + : ""), \ + NM_PRINT_FMT_QUOTED (_con_id, "(", _con_id, ") ", "") \ _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ } \ } G_STMT_END @@ -983,8 +1028,8 @@ remove_device (NMManager *self, NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); gboolean unmanage = FALSE; - _LOGD (LOGD_DEVICE, "(%s): removing device (allow_unmanage %d, managed %d)", - nm_device_get_iface (device), allow_unmanage, nm_device_get_managed (device, FALSE)); + _LOG2D (LOGD_DEVICE, device, "removing device (allow_unmanage %d, managed %d)", + allow_unmanage, nm_device_get_managed (device, FALSE)); if (allow_unmanage && nm_device_get_managed (device, FALSE)) { @@ -1238,8 +1283,8 @@ system_create_virtual_device (NMManager *self, NMConnection *connection) iface = nm_manager_get_connection_iface (self, connection, &parent, &error); if (!iface) { - _LOGD (LOGD_DEVICE, "(%s) can't get a name of a virtual device: %s", - nm_connection_get_id (connection), error->message); + _LOG3D (LOGD_DEVICE, connection, "can't get a name of a virtual device: %s", + error->message); g_error_free (error); return NULL; } @@ -1250,8 +1295,8 @@ system_create_virtual_device (NMManager *self, NMConnection *connection) if (nm_device_check_connection_compatible (candidate, connection)) { if (nm_device_is_real (candidate)) { - _LOGD (LOGD_DEVICE, "(%s) already created virtual interface name %s", - nm_connection_get_id (connection), iface); + _LOG3D (LOGD_DEVICE, connection, "already created virtual interface name %s", + iface); return NULL; } @@ -1265,27 +1310,26 @@ system_create_virtual_device (NMManager *self, NMConnection *connection) factory = nm_device_factory_manager_find_factory_for_connection (connection); if (!factory) { - _LOGE (LOGD_DEVICE, "(%s:%s) NetworkManager plugin for '%s' unavailable", - nm_connection_get_id (connection), iface, + _LOG3E (LOGD_DEVICE, connection, "(%s) NetworkManager plugin for '%s' unavailable", + iface, nm_connection_get_connection_type (connection)); return NULL; } device = nm_device_factory_create_device (factory, iface, NULL, connection, NULL, &error); if (!device) { - _LOGW (LOGD_DEVICE, "(%s) factory can't create the device: %s", - nm_connection_get_id (connection), error->message); + _LOG3W (LOGD_DEVICE, connection, "factory can't create the device: %s", + error->message); g_error_free (error); return NULL; } - _LOGD (LOGD_DEVICE, "(%s) create virtual device %s", - nm_connection_get_id (connection), + _LOG3D (LOGD_DEVICE, connection, "create virtual device %s", nm_device_get_iface (device)); if (!add_device (self, device, &error)) { - _LOGW (LOGD_DEVICE, "(%s) can't register the device with manager: %s", - nm_connection_get_id (connection), error->message); + _LOG3W (LOGD_DEVICE, connection, "can't register the device with manager: %s", + error->message); g_error_free (error); g_object_unref (device); return NULL; @@ -1313,8 +1357,8 @@ system_create_virtual_device (NMManager *self, NMConnection *connection) /* Create any backing resources the device needs */ if (!nm_device_create_and_realize (device, connection, parent, &error)) { - _LOGW (LOGD_DEVICE, "(%s) couldn't create the device: %s", - nm_connection_get_id (connection), error->message); + _LOG3W (LOGD_DEVICE, connection, "couldn't create the device: %s", + error->message); g_error_free (error); remove_device (self, device, FALSE, TRUE); return NULL; @@ -1481,9 +1525,7 @@ manager_update_radio_enabled (NMManager *self, NMDevice *device = NM_DEVICE (iter->data); if (nm_device_get_rfkill_type (device) == rstate->rtype) { - _LOGD (LOGD_RFKILL, "(%s): setting radio %s", - nm_device_get_iface (device), - enabled ? "enabled" : "disabled"); + _LOG2D (LOGD_RFKILL, device, "rfkill: setting radio %s", enabled ? "enabled" : "disabled"); nm_device_set_enabled (device, enabled); } } @@ -1528,14 +1570,14 @@ manager_rfkill_update_one_type (NMManager *self, /* Print out all states affecting device enablement */ if (rstate->desc) { - _LOGD (LOGD_RFKILL, "%s hw-enabled %d sw-enabled %d", + _LOGD (LOGD_RFKILL, "rfkill: %s hw-enabled %d sw-enabled %d", rstate->desc, rstate->hw_enabled, rstate->sw_enabled); } /* Log new killswitch state */ new_rfkilled = rstate->hw_enabled && rstate->sw_enabled; if (old_rfkilled != new_rfkilled) { - _LOGI (LOGD_RFKILL, "%s now %s by radio killswitch", + _LOGI (LOGD_RFKILL, "rfkill: %s now %s by radio killswitch", rstate->desc, new_rfkilled ? "enabled" : "disabled"); } @@ -1691,11 +1733,6 @@ done: * get_existing_connection: * @manager: #NMManager instance * @device: #NMDevice instance - * @guess_assume: whether to employ a heuristic to search for a matching - * connection to assume. - * @assume_connection_uuid: if present, try to assume a connection with this - * UUID. If no uuid is given or no matching connection is found, we - * only do external activation. * @out_generated: (allow-none): return TRUE, if the connection was generated. * * Returns: a #NMSettingsConnection to be assumed by the device, or %NULL if @@ -1704,18 +1741,19 @@ done: static NMSettingsConnection * get_existing_connection (NMManager *self, NMDevice *device, - gboolean guess_assume, - const char *assume_connection_uuid, gboolean *out_generated) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMConnection *connection = NULL; + gs_unref_object NMConnection *connection = NULL; NMSettingsConnection *added = NULL; GError *error = NULL; NMDevice *master = NULL; int ifindex = nm_device_get_ifindex (device); NMSettingsConnection *matched; NMSettingsConnection *connection_checked = NULL; + gboolean assume_state_guess_assume = FALSE; + const char *assume_state_connection_uuid = NULL; + gboolean maybe_later; if (out_generated) *out_generated = FALSE; @@ -1728,13 +1766,15 @@ get_existing_connection (NMManager *self, if (master_ifindex) { master = nm_manager_get_device_by_ifindex (self, master_ifindex); if (!master) { - _LOGD (LOGD_DEVICE, "(%s): cannot generate connection for slave before its master (%s/%d)", - nm_device_get_iface (device), nm_platform_link_get_name (NM_PLATFORM_GET, master_ifindex), master_ifindex); + _LOG2D (LOGD_DEVICE, device, "assume: don't assume because " + "cannot generate connection for slave before its master (%s/%d)", + nm_platform_link_get_name (NM_PLATFORM_GET, master_ifindex), master_ifindex); return NULL; } if (!nm_device_get_act_request (master)) { - _LOGD (LOGD_DEVICE, "(%s): cannot generate connection for slave before master %s activates", - nm_device_get_iface (device), nm_device_get_iface (master)); + _LOG2D (LOGD_DEVICE, device, "assume: don't assume because " + "cannot generate connection for slave before master %s activates", + nm_device_get_iface (master)); return NULL; } } @@ -1746,9 +1786,19 @@ get_existing_connection (NMManager *self, * update_connection() implemented, otherwise nm_device_generate_connection() * returns NULL. */ - connection = nm_device_generate_connection (device, master); - if (!connection) + connection = nm_device_generate_connection (device, master, &maybe_later, &error); + if (!connection) { + if (!maybe_later) + nm_device_assume_state_reset (device); + _LOG2D (LOGD_DEVICE, device, "assume: cannot generate connection: %s", + error->message); + g_error_free (error); return NULL; + } + + nm_device_assume_state_get (device, + &assume_state_guess_assume, + &assume_state_connection_uuid); /* Now we need to compare the generated connection to each configured * connection. The comparison function is the heart of the connection @@ -1759,8 +1809,8 @@ get_existing_connection (NMManager *self, * When no configured connection matches the generated connection, we keep * the generated connection instead. */ - if ( assume_connection_uuid - && (connection_checked = nm_settings_get_connection_by_uuid (priv->settings, assume_connection_uuid)) + if ( assume_state_connection_uuid + && (connection_checked = nm_settings_get_connection_by_uuid (priv->settings, assume_state_connection_uuid)) && !active_connection_find_first (self, connection_checked, NULL, NM_ACTIVE_CONNECTION_STATE_DEACTIVATING) && nm_device_check_connection_compatible (device, NM_CONNECTION (connection_checked))) { @@ -1778,7 +1828,7 @@ get_existing_connection (NMManager *self, } else matched = NULL; - if (!matched && guess_assume) { + if (!matched && assume_state_guess_assume) { gs_free NMSettingsConnection **connections = NULL; guint len, i, j; @@ -1808,84 +1858,73 @@ get_existing_connection (NMManager *self, } if (matched) { - _LOGI (LOGD_DEVICE, "(%s): found matching connection '%s' (%s)%s", - nm_device_get_iface (device), - nm_settings_connection_get_id (matched), - nm_settings_connection_get_uuid (matched), - assume_connection_uuid && nm_streq (assume_connection_uuid, nm_settings_connection_get_uuid (matched)) - ? " (indicated)" : " (guessed)"); - g_object_unref (connection); + _LOG2I (LOGD_DEVICE, device, "assume: will attempt to assume matching connection '%s' (%s)%s", + nm_settings_connection_get_id (matched), + nm_settings_connection_get_uuid (matched), + assume_state_connection_uuid && nm_streq (assume_state_connection_uuid, nm_settings_connection_get_uuid (matched)) + ? " (indicated)" : " (guessed)"); + nm_device_assume_state_reset (device); return matched; } - _LOGD (LOGD_DEVICE, "(%s): generated connection '%s'", - nm_device_get_iface (device), - nm_connection_get_id (connection)); + _LOG2D (LOGD_DEVICE, device, "assume: generated connection '%s' (%s)", + nm_connection_get_id (connection), + nm_connection_get_uuid (connection)); + + nm_device_assume_state_reset (device); added = nm_settings_add_connection (priv->settings, connection, FALSE, &error); - if (added) { - nm_settings_connection_set_flags (NM_SETTINGS_CONNECTION (added), - NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED | - NM_SETTINGS_CONNECTION_FLAGS_VOLATILE, - TRUE); - if (out_generated) - *out_generated = TRUE; - } else { - _LOGW (LOGD_SETTINGS, "(%s) Couldn't save generated connection '%s': %s", - nm_device_get_iface (device), + if (!added) { + _LOG2W (LOGD_SETTINGS, device, "assume: failure to save generated connection '%s': %s", nm_connection_get_id (connection), error->message); - g_clear_error (&error); + g_error_free (error); + return NULL; } - g_object_unref (connection); - return added ? added : NULL; + nm_settings_connection_set_flags (NM_SETTINGS_CONNECTION (added), + NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED | + NM_SETTINGS_CONNECTION_FLAGS_VOLATILE, + TRUE); + NM_SET_OUT (out_generated, TRUE); + return added; } static gboolean recheck_assume_connection (NMManager *self, - NMDevice *device, - gboolean guess_assume, - const char *assume_connection_uuid) + NMDevice *device) { NMSettingsConnection *connection; gboolean was_unmanaged = FALSE; gboolean generated = FALSE; NMDeviceState state; - NMDeviceSysIfaceState if_state; - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); g_return_val_if_fail (NM_IS_MANAGER (self), FALSE); g_return_val_if_fail (NM_IS_DEVICE (device), FALSE); - if (nm_device_get_is_nm_owned (device)) - return FALSE; - - if (!nm_device_get_managed (device, FALSE)) + if (!nm_device_get_managed (device, FALSE)) { + nm_device_assume_state_reset (device); + _LOG2D (LOGD_DEVICE, device, "assume: don't assume because %s", "not managed"); return FALSE; + } state = nm_device_get_state (device); - if (state > NM_DEVICE_STATE_DISCONNECTED) - return FALSE; - - if_state = nm_device_sys_iface_state_get (device); - if (!priv->startup && (if_state == NM_DEVICE_SYS_IFACE_STATE_MANAGED)) - nm_assert (!guess_assume && (assume_connection_uuid == NULL)); - else if (if_state != NM_DEVICE_SYS_IFACE_STATE_EXTERNAL) - return FALSE; - - connection = get_existing_connection (self, device, guess_assume, assume_connection_uuid, &generated); - if (!connection) { - _LOGD (LOGD_DEVICE, "(%s): can't assume; no connection", - nm_device_get_iface (device)); + if (state > NM_DEVICE_STATE_DISCONNECTED) { + nm_device_assume_state_reset (device); + _LOG2D (LOGD_DEVICE, device, "assume: don't assume due to device state %s", + nm_device_state_to_str (state)); return FALSE; } - _LOGD (LOGD_DEVICE, "(%s): will attempt to assume connection", - nm_device_get_iface (device)); + connection = get_existing_connection (self, device, &generated); + /* log no reason. get_existing_connection() already does it. */ + if (!connection) + return FALSE; - if (!generated) - nm_device_sys_iface_state_set (device, NM_DEVICE_SYS_IFACE_STATE_ASSUME); + nm_device_sys_iface_state_set (device, + generated + ? NM_DEVICE_SYS_IFACE_STATE_EXTERNAL + : NM_DEVICE_SYS_IFACE_STATE_ASSUME); /* Move device to DISCONNECTED to activate the connection */ if (state == NM_DEVICE_STATE_UNMANAGED) { @@ -1915,7 +1954,7 @@ recheck_assume_connection (NMManager *self, &error); if (!active) { - _LOGW (LOGD_DEVICE, "assumed connection %s failed to activate: %s", + _LOGW (LOGD_DEVICE, "assume: assumed connection %s failed to activate: %s", nm_connection_get_path (NM_CONNECTION (connection)), error->message); g_error_free (error); @@ -1927,9 +1966,7 @@ recheck_assume_connection (NMManager *self, } if (generated) { - _LOGD (LOGD_DEVICE, "(%s): connection assumption failed. Deleting generated connection", - nm_device_get_iface (device)); - + _LOG2D (LOGD_DEVICE, device, "assume: deleting generated connection after assuming failed"); nm_settings_connection_delete (connection, NULL, NULL); } else { if (nm_device_sys_iface_state_get (device) == NM_DEVICE_SYS_IFACE_STATE_ASSUME) @@ -1952,9 +1989,9 @@ recheck_assume_connection (NMManager *self, } static void -recheck_assume_connection_cb (NMDevice *device, gpointer user_data) +recheck_assume_connection_cb (NMManager *self, NMDevice *device) { - recheck_assume_connection (user_data, device, FALSE, NULL); + recheck_assume_connection (self, device); } static void @@ -2047,19 +2084,19 @@ device_connectivity_changed (NMDevice *device, static void _device_realize_finish (NMManager *self, NMDevice *device, - const NMPlatformLink *plink, - gboolean guess_assume, - const char *connection_uuid_to_assume) + const NMPlatformLink *plink) { g_return_if_fail (NM_IS_MANAGER (self)); g_return_if_fail (NM_IS_DEVICE (device)); nm_device_realize_finish (device, plink); - if (!nm_device_get_managed (device, FALSE)) + if (!nm_device_get_managed (device, FALSE)) { + nm_device_assume_state_reset (device); return; + } - if (recheck_assume_connection (self, device, guess_assume, connection_uuid_to_assume)) + if (recheck_assume_connection (self, device)) return; /* if we failed to assume a connection for the managed device, but the device @@ -2129,9 +2166,9 @@ add_device (NMManager *self, NMDevice *device, GError **error) G_CALLBACK (device_removed_cb), self); - g_signal_connect (device, NM_DEVICE_RECHECK_ASSUME, - G_CALLBACK (recheck_assume_connection_cb), - self); + g_signal_connect_data (device, NM_DEVICE_RECHECK_ASSUME, + G_CALLBACK (recheck_assume_connection_cb), + self, NULL, G_CONNECT_SWAPPED); g_signal_connect (device, "notify::" NM_DEVICE_IP_IFACE, G_CALLBACK (device_ip_iface_changed), @@ -2183,7 +2220,7 @@ add_device (NMManager *self, NMDevice *device, GError **error) manager_sleeping (self)); dbus_path = nm_exported_object_export (NM_EXPORTED_OBJECT (device)); - _LOGI (LOGD_DEVICE, "(%s): new %s device (%s)", iface, type_desc, dbus_path); + _LOG2I (LOGD_DEVICE, device, "new %s device (%s)", type_desc, dbus_path); nm_settings_device_added (priv->settings, device); g_signal_emit (self, signals[INTERNAL_DEVICE_ADDED], 0, device); @@ -2213,14 +2250,16 @@ factory_device_added_cb (NMDeviceFactory *factory, if (nm_device_realize_start (device, NULL, + FALSE, /* assume_state_guess_assume */ + NULL, /* assume_state_connection_uuid */ + FALSE, /* set_nm_owned */ NM_UNMAN_FLAG_OP_FORGET, NULL, &error)) { add_device (self, device, NULL); - _device_realize_finish (self, device, NULL, FALSE, NULL); + _device_realize_finish (self, device, NULL); } else { - _LOGW (LOGD_DEVICE, "(%s): failed to realize device: %s", - nm_device_get_iface (device), error->message); + _LOG2W (LOGD_DEVICE, device, "failed to realize device: %s", error->message); g_error_free (error); } } @@ -2291,11 +2330,13 @@ platform_link_added (NMManager *self, return; } else if (nm_device_realize_start (candidate, plink, + FALSE, /* assume_state_guess_assume */ + NULL, /* assume_state_connection_uuid */ + FALSE, /* set_nm_owned */ NM_UNMAN_FLAG_OP_FORGET, &compatible, &error)) { - /* Success */ - _device_realize_finish (self, candidate, plink, FALSE, NULL); + _device_realize_finish (self, candidate, plink); return; } @@ -2362,13 +2403,14 @@ platform_link_added (NMManager *self, if (nm_device_realize_start (device, plink, + guess_assume, + dev_state ? dev_state->connection_uuid : NULL, + dev_state ? (dev_state->nm_owned == 1) : FALSE, unmanaged_user_explicit, NULL, &error)) { add_device (self, device, NULL); - _device_realize_finish (self, device, plink, - guess_assume, - dev_state ? dev_state->connection_uuid : NULL); + _device_realize_finish (self, device, plink); } else { _LOGW (LOGD_DEVICE, "%s: failed to realize device: %s", plink->name, error->message); @@ -2409,9 +2451,7 @@ _platform_link_cb_idle (PlatformLinkCbData *data) nm_device_sys_iface_state_set (device, NM_DEVICE_SYS_IFACE_STATE_REMOVED); /* Our software devices stick around until their connection is removed */ if (!nm_device_unrealize (device, FALSE, &error)) { - _LOGW (LOGD_DEVICE, "(%s): failed to unrealize: %s", - nm_device_get_iface (device), - error->message); + _LOG2W (LOGD_DEVICE, device, "failed to unrealize: %s", error->message); g_clear_error (&error); remove_device (self, device, FALSE, TRUE); } @@ -2459,10 +2499,14 @@ platform_query_devices (NMManager *self) NMPlatformLink *links; int i; gboolean guess_assume; + const char *order; guess_assume = nm_config_get_first_start (nm_config_get ()); - - links_array = nm_platform_link_get_all (NM_PLATFORM_GET); + order = nm_config_data_get_value_cached (NM_CONFIG_GET_DATA, + NM_CONFIG_KEYFILE_GROUP_MAIN, + NM_CONFIG_KEYFILE_KEY_MAIN_SLAVES_ORDER, + NM_CONFIG_GET_VALUE_STRIP); + links_array = nm_platform_link_get_all (NM_PLATFORM_GET, !nm_streq0 (order, "index")); links = (NMPlatformLink *) links_array->data; for (i = 0; i < links_array->len; i++) { gs_free NMConfigDeviceStateData *dev_state = NULL; @@ -3016,7 +3060,7 @@ out: } static gint -compare_slaves (gconstpointer a, gconstpointer b, gpointer _unused) +compare_slaves (gconstpointer a, gconstpointer b, gpointer sort_by_name) { const SlaveConnectionInfo *a_info = a; const SlaveConnectionInfo *b_info = b; @@ -3027,8 +3071,12 @@ compare_slaves (gconstpointer a, gconstpointer b, gpointer _unused) if (!b_info->device) return -1; - return g_strcmp0 (nm_device_get_iface (a_info->device), - nm_device_get_iface (b_info->device)); + if (GPOINTER_TO_INT (sort_by_name)) { + return g_strcmp0 (nm_device_get_iface (a_info->device), + nm_device_get_iface (b_info->device)); + } + + return nm_device_get_ifindex (a_info->device) - nm_device_get_ifindex (b_info->device); } static void @@ -3042,11 +3090,17 @@ autoconnect_slaves (NMManager *self, if (should_connect_slaves (NM_CONNECTION (master_connection), master_device)) { gs_free SlaveConnectionInfo *slaves = NULL; guint i, n_slaves = 0; + const char *value; slaves = find_slaves (self, master_connection, master_device, &n_slaves); if (n_slaves > 1) { + value = nm_config_data_get_value_cached (NM_CONFIG_GET_DATA, + NM_CONFIG_KEYFILE_GROUP_MAIN, + NM_CONFIG_KEYFILE_KEY_MAIN_SLAVES_ORDER, + NM_CONFIG_GET_VALUE_STRIP); g_qsort_with_data (slaves, n_slaves, sizeof (slaves[0]), - compare_slaves, NULL); + compare_slaves, + GINT_TO_POINTER (!nm_streq0 (value, "index"))); } for (i = 0; i < n_slaves; i++) { @@ -3505,6 +3559,9 @@ _new_active_connection (NMManager *self, error); } + if (device && (activation_type == NM_ACTIVATION_TYPE_MANAGED)) + nm_device_sys_iface_state_set (device, NM_DEVICE_SYS_IFACE_STATE_MANAGED); + return (NMActiveConnection *) nm_act_request_new (settings_connection, applied, specific_object, @@ -3541,10 +3598,36 @@ _internal_activation_auth_done (NMActiveConnection *active, { NMManager *self = user_data1; NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + NMActiveConnection *candidate; GError *error = NULL; + GSList *iter; priv->authorizing_connections = g_slist_remove (priv->authorizing_connections, active); + /* Don't continue with the activation if an equivalent active connection + * already exists. We also check this earlier, but there we may fail to + * detect a duplicate if the existing active connection is undergoing + * authorization in impl_manager_activate_connection(). + */ + if (success && nm_auth_subject_is_internal (nm_active_connection_get_subject (active))) { + for (iter = priv->active_connections; iter; iter = iter->next) { + candidate = iter->data; + if ( nm_active_connection_get_device (candidate) == nm_active_connection_get_device (active) + && nm_active_connection_get_settings_connection (candidate) == nm_active_connection_get_settings_connection (active) + && NM_IN_SET (nm_active_connection_get_state (candidate), + NM_ACTIVE_CONNECTION_STATE_ACTIVATING, + NM_ACTIVE_CONNECTION_STATE_ACTIVATED)) { + g_set_error (&error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_CONNECTION_ALREADY_ACTIVE, + "Connection '%s' is already active", + nm_active_connection_get_settings_connection_id (active)); + success = FALSE; + break; + } + } + } + if (success) { if (_internal_activate_generic (self, active, &error)) { g_object_unref (active); @@ -4480,7 +4563,7 @@ do_sleep_wake (NMManager *self, gboolean sleeping_changed) gboolean enabled = radio_enabled_for_rstate (rstate, TRUE); if (rstate->desc) { - _LOGD (LOGD_RFKILL, "%s %s devices (hw_enabled %d, sw_enabled %d, user_enabled %d)", + _LOGD (LOGD_RFKILL, "rfkill: %s %s devices (hw_enabled %d, sw_enabled %d, user_enabled %d)", enabled ? "enabling" : "disabling", rstate->desc, rstate->hw_enabled, rstate->sw_enabled, rstate->user_enabled); } @@ -4990,6 +5073,7 @@ nm_manager_write_device_state (NMManager *self) const GSList *devices; NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); gs_unref_hashtable GHashTable *seen_ifindexes = NULL; + gint nm_owned; seen_ifindexes = g_hash_table_new (NULL, NULL); @@ -5029,10 +5113,13 @@ nm_manager_write_device_state (NMManager *self) if (perm_hw_addr_fake && !perm_hw_addr_is_fake) perm_hw_addr_fake = NULL; + nm_owned = nm_device_is_software (device) ? nm_device_is_nm_owned (device) : -1; + if (nm_config_device_state_write (ifindex, managed_type, perm_hw_addr_fake, - uuid)) + uuid, + nm_owned)) g_hash_table_add (seen_ifindexes, GINT_TO_POINTER (ifindex)); } @@ -5073,7 +5160,7 @@ nm_manager_start (NMManager *self, GError **error) update_rstate_from_rfkill (priv->rfkill_mgr, rstate); if (rstate->desc) { - _LOGI (LOGD_RFKILL, "%s %s by radio killswitch; %s by state file", + _LOGI (LOGD_RFKILL, "rfkill: %s %s by radio killswitch; %s by state file", rstate->desc, (rstate->hw_enabled && rstate->sw_enabled) ? "enabled" : "disabled", rstate->user_enabled ? "enabled" : "disabled"); @@ -5149,8 +5236,7 @@ handle_firmware_changed (gpointer user_data) if ( nm_device_get_firmware_missing (candidate) && (state == NM_DEVICE_STATE_UNAVAILABLE)) { - _LOGI (LOGD_CORE, "(%s): firmware may now be available", - nm_device_get_iface (candidate)); + _LOG2I (LOGD_CORE, candidate, "firmware may now be available"); /* Re-set unavailable state to try bringing the device up again */ nm_device_state_changed (candidate, @@ -5782,12 +5868,12 @@ rfkill_change (NMManager *self, const char *desc, RfKillType rtype, gboolean ena fd = open ("/dev/rfkill", O_RDWR | O_CLOEXEC); if (fd < 0) { if (errno == EACCES) - _LOGW (LOGD_RFKILL, "(%s): failed to open killswitch device", desc); + _LOGW (LOGD_RFKILL, "rfkill: (%s): failed to open killswitch device", desc); return; } if (fcntl (fd, F_SETFL, O_NONBLOCK) < 0) { - _LOGW (LOGD_RFKILL, "(%s): failed to set killswitch device for " + _LOGW (LOGD_RFKILL, "rfkill: (%s): failed to set killswitch device for " "non-blocking operation", desc); close (fd); return; @@ -5809,14 +5895,14 @@ rfkill_change (NMManager *self, const char *desc, RfKillType rtype, gboolean ena len = write (fd, &event, sizeof (event)); if (len < 0) { - _LOGW (LOGD_RFKILL, "(%s): failed to change WiFi killswitch state: (%d) %s", + _LOGW (LOGD_RFKILL, "rfkill: (%s): failed to change WiFi killswitch state: (%d) %s", desc, errno, g_strerror (errno)); } else if (len == sizeof (event)) { - _LOGI (LOGD_RFKILL, "%s hardware radio set %s", + _LOGI (LOGD_RFKILL, "rfkill: %s hardware radio set %s", desc, enabled ? "enabled" : "disabled"); } else { /* Failed to write full structure */ - _LOGW (LOGD_RFKILL, "(%s): failed to change WiFi killswitch state", desc); + _LOGW (LOGD_RFKILL, "rfkill: (%s): failed to change WiFi killswitch state", desc); } close (fd); @@ -5835,7 +5921,7 @@ manager_radio_user_toggled (NMManager *self, return; if (rstate->desc) { - _LOGD (LOGD_RFKILL, "(%s): setting radio %s by user", + _LOGD (LOGD_RFKILL, "rfkill: (%s): setting radio %s by user", rstate->desc, enabled ? "enabled" : "disabled"); } diff --git a/src/nm-pacrunner-manager.c b/src/nm-pacrunner-manager.c index cfc028c2..87e0a364 100644 --- a/src/nm-pacrunner-manager.c +++ b/src/nm-pacrunner-manager.c @@ -250,6 +250,7 @@ pacrunner_send_done (GDBusProxy *proxy, GAsyncResult *res, gpointer user_data) _LOG2D (config, "sent"); if (config->removed) { + config_ref (config); g_dbus_proxy_call (priv->pacrunner, "DestroyProxyConfiguration", g_variant_new ("(o)", config->path), @@ -329,7 +330,6 @@ pacrunner_proxy_cb (GObject *source, GAsyncResult *res, gpointer user_data) priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self); priv->pacrunner = proxy; - nm_clear_g_cancellable (&priv->pacrunner_cancellable); g_signal_connect (priv->pacrunner, "notify::g-name-owner", G_CALLBACK (name_owner_changed_cb), self); diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 252f054d..487725e4 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -1529,6 +1529,23 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr if (!obj->link.name[0]) goto errout; + if (!tb[IFLA_MTU]) { + /* Kernel has two places that send RTM_GETLINK messages: + * net/core/rtnetlink.c and net/wireless/ext-core.c. + * Unfotunatelly ext-core.c sets only IFLA_WIRELESS and + * IFLA_IFNAME. This confuses code in this function, because + * it cannot get complete set of data for the interface and + * later incomplete object this function creates is used to + * overwrite existing data in NM's cache. + * Since ext-core.c doesn't set IFLA_MTU we can use it as a + * signal to ignore incoming message. + * To some extent this is a hack and correct approach is to + * merge objects per-field. + */ + goto errout; + } + obj->link.mtu = nla_get_u32 (tb[IFLA_MTU]); + if (tb[IFLA_LINKINFO]) { err = nla_parse_nested (li, IFLA_INFO_MAX, tb[IFLA_LINKINFO], policy_link_info); if (err < 0) @@ -1609,9 +1626,6 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr } } - if (tb[IFLA_MTU]) - obj->link.mtu = nla_get_u32 (tb[IFLA_MTU]); - switch (obj->link.type) { case NM_LINK_TYPE_GRE: lnk_data = _parse_lnk_gre (nl_info_kind, nl_info_data); diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index 767187d9..a244ff39 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -437,7 +437,8 @@ nm_platform_sysctl_get_int_checked (NMPlatform *self, const char *pathid, int di static int _link_get_all_presort (gconstpointer p_a, - gconstpointer p_b) + gconstpointer p_b, + gpointer sort_by_name) { const NMPlatformLink *a = p_a; const NMPlatformLink *b = p_b; @@ -448,13 +449,16 @@ _link_get_all_presort (gconstpointer p_a, if (b->ifindex == 1) return 1; - /* Initialized links first */ - if (a->initialized > b->initialized) - return -1; - if (a->initialized < b->initialized) - return 1; + if (GPOINTER_TO_INT (sort_by_name)) { + /* Initialized links first */ + if (a->initialized > b->initialized) + return -1; + if (a->initialized < b->initialized) + return 1; - return strcmp (a->name, b->name); + return strcmp (a->name, b->name); + } else + return a->ifindex - b->ifindex; } /** @@ -465,7 +469,7 @@ _link_get_all_presort (gconstpointer p_a, * owned by the caller and should be freed with g_array_unref(). */ GArray * -nm_platform_link_get_all (NMPlatform *self) +nm_platform_link_get_all (NMPlatform *self, gboolean sort_by_name) { GArray *links, *result; guint i, j, nresult; @@ -479,9 +483,9 @@ nm_platform_link_get_all (NMPlatform *self) if (!links || links->len == 0) return links; - /* first sort the links by their ifindex. Below we will sort further by moving - * children/slaves to the end. */ - g_array_sort (links, _link_get_all_presort); + /* first sort the links by their ifindex or name. Below we will sort + * further by moving children/slaves to the end. */ + g_array_sort_with_data (links, _link_get_all_presort, GINT_TO_POINTER (sort_by_name)); unseen = g_hash_table_new (g_direct_hash, g_direct_equal); for (i = 0; i < links->len; i++) { diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index 43be17fa..1b8fa133 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -763,7 +763,7 @@ const NMPlatformLink *nm_platform_link_get (NMPlatform *self, int ifindex); const NMPlatformLink *nm_platform_link_get_by_ifname (NMPlatform *self, const char *ifname); const NMPlatformLink *nm_platform_link_get_by_address (NMPlatform *self, gconstpointer address, size_t length); -GArray *nm_platform_link_get_all (NMPlatform *self); +GArray *nm_platform_link_get_all (NMPlatform *self, gboolean sort_by_name); NMPlatformError nm_platform_link_dummy_add (NMPlatform *self, const char *name, const NMPlatformLink **out_link); NMPlatformError nm_platform_link_bridge_add (NMPlatform *self, const char *name, const void *address, size_t address_len, const NMPlatformLink **out_link); NMPlatformError nm_platform_link_bond_add (NMPlatform *self, const char *name, const NMPlatformLink **out_link); diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c index 04db862d..a9d0694d 100644 --- a/src/platform/tests/test-common.c +++ b/src/platform/tests/test-common.c @@ -185,7 +185,7 @@ link_callback (NMPlatform *platform, int obj_type_i, int ifindex, NMPlatformLink /* Check the data */ g_assert (received->ifindex > 0); - links = nm_platform_link_get_all (NM_PLATFORM_GET); + links = nm_platform_link_get_all (NM_PLATFORM_GET, TRUE); for (i = 0; i < links->len; i++) { cached = &g_array_index (links, NMPlatformLink, i); if (cached->ifindex == received->ifindex) { diff --git a/src/platform/tests/test-general.c b/src/platform/tests/test-general.c index 2ccfac7d..e772662c 100644 --- a/src/platform/tests/test-general.c +++ b/src/platform/tests/test-general.c @@ -48,7 +48,7 @@ test_link_get_all (void) platform = nm_linux_platform_new (TRUE, NM_PLATFORM_NETNS_SUPPORT_DEFAULT); - links = nm_platform_link_get_all (platform); + links = nm_platform_link_get_all (platform, TRUE); } /*****************************************************************************/ diff --git a/src/ppp/nm-ppp-manager.c b/src/ppp/nm-ppp-manager.c index c7836a8f..6343df8b 100644 --- a/src/ppp/nm-ppp-manager.c +++ b/src/ppp/nm-ppp-manager.c @@ -179,14 +179,6 @@ monitor_stats (NMPPPManager *manager) /*****************************************************************************/ static void -remove_timeout_handler (NMPPPManager *manager) -{ - NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (manager); - - nm_clear_g_source (&priv->ppp_timeout_handler); -} - -static void cancel_get_secrets (NMPPPManager *self) { NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (self); @@ -365,7 +357,7 @@ impl_ppp_manager_set_state (NMPPPManager *manager, GDBusMethodInvocation *context, guint32 state) { - g_signal_emit (manager, signals[STATE_CHANGED], 0, state); + g_signal_emit (manager, signals[STATE_CHANGED], 0, (guint) state); g_dbus_method_invocation_return_value (context, NULL); } @@ -415,7 +407,7 @@ impl_ppp_manager_set_ip4_config (NMPPPManager *manager, _LOGI ("(IPv4 Config Get) reply received."); - remove_timeout_handler (manager); + nm_clear_g_source (&priv->ppp_timeout_handler); config = nm_ip4_config_new (nm_platform_link_get_ifindex (NM_PLATFORM_GET, priv->ip_iface)); @@ -511,7 +503,7 @@ impl_ppp_manager_set_ip6_config (NMPPPManager *manager, _LOGI ("(IPv6 Config Get) reply received."); - remove_timeout_handler (manager); + nm_clear_g_source (&priv->ppp_timeout_handler); config = nm_ip6_config_new (nm_platform_link_get_ifindex (NM_PLATFORM_GET, priv->ip_iface)); @@ -597,102 +589,62 @@ nm_cmd_line_add_int (NMCmdLine *cmd, int i) /*****************************************************************************/ -static void -ppp_exit_code (guint pppd_exit_status, GPid pid) -{ - const char *msg; - - switch (pppd_exit_status) { - case 1: - msg = "Fatal pppd error"; - break; - case 2: - msg = "pppd options error"; - break; - case 3: - msg = "No root priv error"; - break; - case 4: - msg = "No ppp module error"; - break; - case 5: - msg = "pppd received a signal"; - break; - case 6: - msg = "Serial port lock failed"; - break; - case 7: - msg = "Serial port open failed"; - break; - case 8: - msg = "Connect script failed"; - break; - case 9: - msg = "Pty program error"; - break; - case 10: - msg = "PPP negotiation failed"; - break; - case 11: - msg = "Peer didn't authenticatie itself"; - break; - case 12: - msg = "Link idle: Idle Seconds reached."; - break; - case 13: - msg = "Connect time limit reached."; - break; - case 14: - msg = "Callback negotiated, call should come back."; - break; - case 15: - msg = "Lack of LCP echo responses"; - break; - case 16: - msg = "A modem hung up the phone"; - break; - case 17: - msg = "Loopback detected"; - break; - case 18: - msg = "The init script failed"; - break; - case 19: - msg = "Authentication error.\n" - "We failed to authenticate ourselves to the peer.\n" - "Maybe bad account or password?"; - break; - default: - msg = "Unknown error"; - } - - _LOGW ("pppd pid %d exited with error: %s", pid, msg); -} +NM_UTILS_LOOKUP_STR_DEFINE_STATIC (pppd_exit_code_to_str, int, + NM_UTILS_LOOKUP_DEFAULT ("Unknown error"), + NM_UTILS_LOOKUP_STR_ITEM ( 1, "Fatal pppd error"); + NM_UTILS_LOOKUP_STR_ITEM ( 2, "pppd options error"), + NM_UTILS_LOOKUP_STR_ITEM ( 3, "No root priv error"), + NM_UTILS_LOOKUP_STR_ITEM ( 4, "No ppp module error"), + NM_UTILS_LOOKUP_STR_ITEM ( 5, "pppd received a signal"), + NM_UTILS_LOOKUP_STR_ITEM ( 6, "Serial port lock failed"), + NM_UTILS_LOOKUP_STR_ITEM ( 7, "Serial port open failed"), + NM_UTILS_LOOKUP_STR_ITEM ( 8, "Connect script failed"), + NM_UTILS_LOOKUP_STR_ITEM ( 9, "Pty program error"), + NM_UTILS_LOOKUP_STR_ITEM (10, "PPP negotiation failed"), + NM_UTILS_LOOKUP_STR_ITEM (11, "Peer didn't authenticatie itself"), + NM_UTILS_LOOKUP_STR_ITEM (12, "Link idle: Idle Seconds reached."), + NM_UTILS_LOOKUP_STR_ITEM (13, "Connect time limit reached."), + NM_UTILS_LOOKUP_STR_ITEM (14, "Callback negotiated, call should come back."), + NM_UTILS_LOOKUP_STR_ITEM (15, "Lack of LCP echo responses"), + NM_UTILS_LOOKUP_STR_ITEM (16, "A modem hung up the phone"), + NM_UTILS_LOOKUP_STR_ITEM (17, "Loopback detected"), + NM_UTILS_LOOKUP_STR_ITEM (18, "The init script failed"), + NM_UTILS_LOOKUP_STR_ITEM (19, "Authentication error. " + "We failed to authenticate ourselves to the peer. " + "Maybe bad account or password?"), +); static void -ppp_watch_cb (GPid pid, gint status, gpointer user_data) +ppp_watch_cb (GPid pid, int status, gpointer user_data) { NMPPPManager *manager = NM_PPP_MANAGER (user_data); NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (manager); - guint err; + int err; + const long long lpid = (long long) pid; - g_assert (pid == priv->pid); + g_return_if_fail (pid == priv->pid); if (WIFEXITED (status)) { err = WEXITSTATUS (status); - if (err != 0) - ppp_exit_code (err, priv->pid); + if (err) { + _LOGW ("pppd pid %lld exited with error %d: %s", + lpid, err, + pppd_exit_code_to_str (err)); + } else + _LOGD ("pppd pid %lld exited with success", lpid); } else if (WIFSTOPPED (status)) { - _LOGI ("pppd pid %d stopped unexpectedly with signal %d", priv->pid, WSTOPSIG (status)); + _LOGW ("pppd pid %lld stopped unexpectedly with signal %d", + lpid, WSTOPSIG (status)); } else if (WIFSIGNALED (status)) { - _LOGI ("pppd pid %d died with signal %d", priv->pid, WTERMSIG (status)); + _LOGW ("pppd pid %lld died with signal %d", + lpid, WTERMSIG (status)); } else - _LOGI ("pppd pid %d died from an unknown cause", priv->pid); + _LOGW ("pppd pid %lld died from an unknown cause", lpid); - _LOGD ("pppd pid %d cleaned up", priv->pid); priv->pid = 0; priv->ppp_watch_id = 0; - g_signal_emit (manager, signals[STATE_CHANGED], 0, NM_PPP_STATUS_DEAD); + _ppp_cleanup (manager); + g_signal_emit (manager, signals[STATE_CHANGED], 0, (guint) NM_PPP_STATUS_DEAD); } static gboolean @@ -704,7 +656,7 @@ pppd_timed_out (gpointer data) _ppp_cleanup (manager); _ppp_kill (manager); - g_signal_emit (manager, signals[STATE_CHANGED], 0, NM_PPP_STATUS_DEAD); + g_signal_emit (manager, signals[STATE_CHANGED], 0, (guint) NM_PPP_STATUS_DEAD); return FALSE; } @@ -1016,7 +968,7 @@ _ppp_manager_start (NMPPPManager *manager, goto out; } - _LOGI ("pppd started with pid %d", priv->pid); + _LOGI ("pppd started with pid %lld", (long long) priv->pid); priv->ppp_watch_id = g_child_watch_add (priv->pid, (GChildWatchFunc) ppp_watch_cb, manager); priv->ppp_timeout_handler = g_timeout_add_seconds (timeout_secs, pppd_timed_out, manager); @@ -1234,8 +1186,12 @@ static void dispose (GObject *object) { NMPPPManager *self = (NMPPPManager *) object; + NMExportedObject *exported = NM_EXPORTED_OBJECT (self); NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (self); + if (nm_exported_object_is_exported (exported)) + nm_exported_object_unexport (exported); + _ppp_cleanup (self); _ppp_kill (self); diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c index 0cb2920c..45a1b664 100644 --- a/src/settings/nm-settings-connection.c +++ b/src/settings/nm-settings-connection.c @@ -2129,6 +2129,7 @@ nm_settings_connection_set_flags_all (NMSettingsConnection *self, NMSettingsConn old_flags = priv->flags; if (old_flags != flags) { + _LOGT ("update settings-connection flags to 0x%x (was 0x%x)", (guint) flags, (guint) priv->flags); priv->flags = flags; _notify (self, PROP_FLAGS); if (NM_FLAGS_HAS (old_flags, NM_SETTINGS_CONNECTION_FLAGS_UNSAVED) != NM_FLAGS_HAS (flags, NM_SETTINGS_CONNECTION_FLAGS_UNSAVED)) @@ -2316,33 +2317,35 @@ void nm_settings_connection_read_and_fill_timestamp (NMSettingsConnection *self) { NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); + gs_unref_keyfile GKeyFile *timestamps_file = NULL; + gs_free_error GError *error = NULL; + gs_free char *tmp_str = NULL; const char *connection_uuid; - guint64 timestamp = 0; - GKeyFile *timestamps_file; - GError *err = NULL; - char *tmp_str; + gint64 timestamp; g_return_if_fail (NM_IS_SETTINGS_CONNECTION (self)); - /* Get timestamp from database file */ timestamps_file = g_key_file_new (); - g_key_file_load_from_file (timestamps_file, SETTINGS_TIMESTAMPS_FILE, G_KEY_FILE_KEEP_COMMENTS, NULL); + if (!g_key_file_load_from_file (timestamps_file, SETTINGS_TIMESTAMPS_FILE, G_KEY_FILE_KEEP_COMMENTS, &error)) { + _LOGD ("failed to read connection timestamp: %s", error->message); + return; + } + connection_uuid = nm_settings_connection_get_uuid (self); - tmp_str = g_key_file_get_value (timestamps_file, "timestamps", connection_uuid, &err); - if (tmp_str) { - timestamp = g_ascii_strtoull (tmp_str, NULL, 10); - g_free (tmp_str); + tmp_str = g_key_file_get_value (timestamps_file, "timestamps", connection_uuid, &error); + if (!tmp_str) { + _LOGD ("failed to read connection timestamp: %s", error->message); + return; } - /* Update connection's timestamp */ - if (!err) { - priv->timestamp = timestamp; - priv->timestamp_set = TRUE; - } else { - _LOGD ("failed to read connection timestamp: %s", err->message); - g_clear_error (&err); + timestamp = _nm_utils_ascii_str_to_int64 (tmp_str, 10, 0, G_MAXINT64, -1); + if (timestamp < 0) { + _LOGD ("failed to read connection timestamp: %s", "invalid number"); + return; } - g_key_file_free (timestamps_file); + + priv->timestamp = timestamp; + priv->timestamp_set = TRUE; } /** 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 d6f33c49..d2b7ff67 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c @@ -1926,12 +1926,8 @@ get_route_attributes_string (NMIPRoute *route, int family) static gboolean write_route_file_legacy (const char *filename, NMSettingIPConfig *s_ip4, GError **error) { - const char *dest, *next_hop; - char **route_items; - gs_free char *route_contents = NULL; + nm_auto_free_gstring GString *contents = NULL; NMIPRoute *route; - guint32 prefix; - gint64 metric; guint32 i, num; g_return_val_if_fail (filename != NULL, FALSE); @@ -1945,36 +1941,34 @@ write_route_file_legacy (const char *filename, NMSettingIPConfig *s_ip4, GError return TRUE; } - route_items = g_malloc0 (sizeof (char *) * (num + 1)); + contents = g_string_new (""); + for (i = 0; i < num; i++) { + const char *next_hop; gs_free char *options = NULL; + gint64 metric; route = nm_setting_ip_config_get_route (s_ip4, i); - - dest = nm_ip_route_get_dest (route); - prefix = nm_ip_route_get_prefix (route); next_hop = nm_ip_route_get_next_hop (route); metric = nm_ip_route_get_metric (route); - options = get_route_attributes_string (route, AF_INET); - if (metric == -1) { - route_items[i] = g_strdup_printf ("%s/%u via %s%s%s\n", - dest, prefix, next_hop, - options ? " " : "", - options ?: ""); - } else { - route_items[i] = g_strdup_printf ("%s/%u via %s metric %u%s%s\n", - dest, prefix, next_hop, (guint32) metric, - options ? " " : "", - options ?: ""); + g_string_append_printf (contents, "%s/%u", + nm_ip_route_get_dest (route), + nm_ip_route_get_prefix (route)); + if (next_hop) + g_string_append_printf (contents, " via %s", next_hop); + if (metric >= 0) + g_string_append_printf (contents, " metric %u", (guint) metric); + if (options) { + g_string_append_c (contents, ' '); + g_string_append (contents, options); } + + g_string_append_c (contents, '\n'); } - route_items[num] = NULL; - route_contents = g_strjoinv (NULL, route_items); - g_strfreev (route_items); - if (!g_file_set_contents (filename, route_contents, -1, NULL)) { + if (!g_file_set_contents (filename, contents->str, contents->len, NULL)) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, "Writing route file '%s' failed", filename); return FALSE; @@ -2073,6 +2067,7 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) int timeout; GString *searches; const char *method = NULL; + gboolean has_netmask; s_ip4 = nm_connection_get_setting_ip4_config (connection); if (!s_ip4) { @@ -2145,16 +2140,7 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) else if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)) svSetValueStr (ifcfg, "BOOTPROTO", "shared"); - /* Clear out un-numbered IP address fields */ - svUnsetValue (ifcfg, "IPADDR"); - svUnsetValue (ifcfg, "PREFIX"); - svUnsetValue (ifcfg, "NETMASK"); - svUnsetValue (ifcfg, "GATEWAY"); - /* Clear out zero-indexed IP address fields */ - svUnsetValue (ifcfg, "IPADDR0"); - svUnsetValue (ifcfg, "PREFIX0"); - svUnsetValue (ifcfg, "NETMASK0"); - svUnsetValue (ifcfg, "GATEWAY0"); + has_netmask = !!svFindFirstKeyWithPrefix (ifcfg, "NETMASK"); /* Write out IPADDR<n>, PREFIX<n>, GATEWAY<n> for current IP addresses * without labels. Unset obsolete NETMASK<n>. @@ -2198,19 +2184,30 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) g_free (tmp); /* If the legacy "NETMASK" is present, keep it. */ - if (svGetValue (ifcfg, netmask_key, &tmp)) { + if (has_netmask) { char buf[INET_ADDRSTRLEN]; - g_free (tmp); - svSetValueStr (ifcfg, netmask_key, nm_utils_inet4_ntop (prefix, buf)); - } + svSetValueStr (ifcfg, netmask_key, + nm_utils_inet4_ntop (nm_utils_ip4_prefix_to_netmask (prefix), buf)); + } else + svUnsetValue (ifcfg, netmask_key); svUnsetValue (ifcfg, gw_key); n++; } - /* Clear remaining IPADDR<n..255>, etc */ - for (i = n; i < 256; i++) { + svUnsetValue (ifcfg, "IPADDR0"); + svUnsetValue (ifcfg, "PREFIX0"); + svUnsetValue (ifcfg, "NETMASK0"); + svUnsetValue (ifcfg, "GATEWAY0"); + if (n == 0) { + svUnsetValue (ifcfg, "IPADDR"); + svUnsetValue (ifcfg, "PREFIX"); + svUnsetValue (ifcfg, "NETMASK"); + i = 1; + } else + i = n; + for (; i < 256; i++) { nm_sprintf_buf (addr_key, "IPADDR%u", i); nm_sprintf_buf (prefix_key, "PREFIX%u", i); nm_sprintf_buf (netmask_key, "NETMASK%u", i); @@ -2492,32 +2489,33 @@ write_route6_file (const char *filename, NMSettingIPConfig *s_ip6, GError **erro } contents = g_string_new (""); + for (i = 0; i < num; i++) { gs_free char *options = NULL; + const char *next_hop; + gint64 metric; route = nm_setting_ip_config_get_route (s_ip6, i); + next_hop = nm_ip_route_get_next_hop (route); + metric = nm_ip_route_get_metric (route); options = get_route_attributes_string (route, AF_INET6); - if (nm_ip_route_get_metric (route) == -1) { - g_string_append_printf (contents, "%s/%u via %s%s%s", - nm_ip_route_get_dest (route), - nm_ip_route_get_prefix (route), - nm_ip_route_get_next_hop (route), - options ? " " : "", - options ?: ""); - } else { - g_string_append_printf (contents, "%s/%u via %s metric %u%s%s", - nm_ip_route_get_dest (route), - nm_ip_route_get_prefix (route), - nm_ip_route_get_next_hop (route), - (unsigned) nm_ip_route_get_metric (route), - options ? " " : "", - options ?: ""); + g_string_append_printf (contents, "%s/%u", + nm_ip_route_get_dest (route), + nm_ip_route_get_prefix (route)); + if (next_hop) + g_string_append_printf (contents, " via %s", next_hop); + if (metric >= 0) + g_string_append_printf (contents, " metric %u", (guint) metric); + if (options) { + g_string_append_c (contents, ' '); + g_string_append (contents, options); } - g_string_append (contents, "\n"); + + g_string_append_c (contents, '\n'); } - if (!g_file_set_contents (filename, contents->str, -1, NULL)) { + if (!g_file_set_contents (filename, contents->str, contents->len, NULL)) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, "Writing route6 file '%s' failed", filename); return FALSE; diff --git a/src/settings/plugins/ifcfg-rh/shvar.c b/src/settings/plugins/ifcfg-rh/shvar.c index 9fce5aa1..47ad5a23 100644 --- a/src/settings/plugins/ifcfg-rh/shvar.c +++ b/src/settings/plugins/ifcfg-rh/shvar.c @@ -905,6 +905,28 @@ svGetKeys (shvarFile *s) /*****************************************************************************/ +const char * +svFindFirstKeyWithPrefix (shvarFile *s, const char *key_prefix) +{ + const GList *current; + const shvarLine *l; + + g_return_val_if_fail (s, NULL); + g_return_val_if_fail (key_prefix, NULL); + + for (current = s->lineList; current; current = current->next) { + l = current->data; + if ( l->key + && l->line + && g_str_has_prefix (l->key, key_prefix)) + return l->key; + } + + return NULL; +} + +/*****************************************************************************/ + static const char * _svGetValue (shvarFile *s, const char *key, char **to_free) { diff --git a/src/settings/plugins/ifcfg-rh/shvar.h b/src/settings/plugins/ifcfg-rh/shvar.h index 9d8c2364..a13920a1 100644 --- a/src/settings/plugins/ifcfg-rh/shvar.h +++ b/src/settings/plugins/ifcfg-rh/shvar.h @@ -44,6 +44,8 @@ shvarFile *svCreateFile (const char *name); /* Open the file <name>, return shvarFile on success, NULL on failure */ shvarFile *svOpenFile (const char *name, GError **error); +const char *svFindFirstKeyWithPrefix (shvarFile *s, const char *key_prefix); + /* Get the value associated with the key, and leave the current pointer * pointing at the line containing the value. The char* returned MUST * be freed by the caller. diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1 b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1 new file mode 100644 index 00000000..ecb36c37 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1 @@ -0,0 +1,14 @@ +DNS1="192.0.2.1" +IPADDR="102.0.2.2" +GATEWAY="192.0.2.1" +NETMASK="255.254.0.0" +BOOTPROTO="static" +DEVICE="eth1" +ONBOOT="yes" +IPV6INIT="yes" + +#bogus +PREFIX1=25 +NETMASK0=255.255.0.0 + +#end diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1.cexpected new file mode 100644 index 00000000..5dfdce4d --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1.cexpected @@ -0,0 +1,23 @@ +DNS1=192.0.2.1 +IPADDR=102.0.2.2 +GATEWAY=192.0.2.1 +NETMASK=255.254.0.0 +BOOTPROTO="static" +DEVICE=eth1 +ONBOOT=yes +IPV6INIT=yes + +#bogus + +#end +TYPE=Ethernet +PROXY_METHOD=none +BROWSER_ONLY=no +PREFIX=15 +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6_AUTOCONF=yes +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no +NAME="System netmask-1" +UUID=${UUID} diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c index babb068d..496a164b 100644 --- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -399,6 +399,47 @@ _writer_new_connection_fail (NMConnection *connection, /*****************************************************************************/ +static void +test_read_netmask_1 (void) +{ + nmtst_auto_unlinkfile char *testfile = NULL; + gs_unref_object NMConnection *connection = NULL; + gs_free char *content = NULL; + NMSettingConnection *s_con; + NMSettingIPConfig *s_ip4; + NMIPAddress *ip4_addr; + const char *FILENAME = TEST_IFCFG_DIR "/network-scripts/ifcfg-netmask-1"; + + connection = _connection_from_file (FILENAME, NULL, TYPE_ETHERNET, NULL); + + s_con = nm_connection_get_setting_connection (connection); + g_assert (s_con); + g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "System netmask-1"); + + s_ip4 = nm_connection_get_setting_ip4_config (connection); + g_assert (s_ip4); + g_assert_cmpuint (nm_setting_ip_config_get_num_dns (s_ip4), ==, 1); + ip4_addr = nm_setting_ip_config_get_address (s_ip4, 0); + g_assert (ip4_addr); + g_assert_cmpstr (nm_ip_address_get_address (ip4_addr), ==, "102.0.2.2"); + g_assert_cmpint (nm_ip_address_get_prefix (ip4_addr), ==, 15); + + nmtst_assert_connection_verifies_without_normalization (connection); + + content = nmtst_file_get_contents (FILENAME); + + testfile = g_strdup (TEST_SCRATCH_DIR "/network-scripts/ifcfg-netmask-1.copy"); + + nmtst_file_set_contents (testfile, content); + + _writer_update_connection (connection, + TEST_SCRATCH_DIR "/network-scripts/", + testfile, + TEST_IFCFG_DIR "/network-scripts/ifcfg-netmask-1.cexpected"); +} + +/*****************************************************************************/ + static gboolean verify_cert_or_key (NMSetting8021x *s_compare, const char *file, @@ -4928,15 +4969,16 @@ test_write_wired_aliases (void) if (!g_strcmp0 (addrstr, ip[j])) break; } - g_assert (j < num_addresses); - - g_assert_cmpint (nm_ip_address_get_prefix (addr), ==, 24); - if (label[j]) - g_assert_cmpstr (g_variant_get_string (nm_ip_address_get_attribute (addr, "label"), NULL), ==, label[j]); - else - g_assert (nm_ip_address_get_attribute (addr, "label") == NULL); - - ip[j] = NULL; + if (j >= num_addresses) + g_assert_not_reached (); + else { + g_assert_cmpint (nm_ip_address_get_prefix (addr), ==, 24); + if (label[j]) + g_assert_cmpstr (g_variant_get_string (nm_ip_address_get_attribute (addr, "label"), NULL), ==, label[j]); + else + g_assert (nm_ip_address_get_attribute (addr, "label") == NULL); + ip[j] = NULL; + } } for (i = 0; i < num_addresses; i++) @@ -9348,6 +9390,8 @@ int main (int argc, char **argv) nmtst_add_test_func (TPATH "read-static", test_read_wired_static, TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-static", "System test-wired-static", GINT_TO_POINTER (TRUE)); nmtst_add_test_func (TPATH "read-static-bootproto", test_read_wired_static, TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-static-bootproto", "System test-wired-static-bootproto", GINT_TO_POINTER (FALSE)); + g_test_add_func (TPATH "read-netmask-1", test_read_netmask_1); + g_test_add_func (TPATH "read-dhcp", test_read_wired_dhcp); g_test_add_func (TPATH "read-dhcp-plus-ip", test_read_wired_dhcp_plus_ip); g_test_add_func (TPATH "read-shared-plus-ip", test_read_wired_shared_plus_ip); diff --git a/src/supplicant/nm-supplicant-interface.c b/src/supplicant/nm-supplicant-interface.c index 71f1f9aa..ab8a0670 100644 --- a/src/supplicant/nm-supplicant-interface.c +++ b/src/supplicant/nm-supplicant-interface.c @@ -228,15 +228,17 @@ bss_proxy_acquired_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_da GVariant *props = NULL; const char *object_path; BssData *bss_data; + gboolean success; - g_async_initable_init_finish (G_ASYNC_INITABLE (proxy), result, &error); - if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + success = g_async_initable_init_finish (G_ASYNC_INITABLE (proxy), result, &error); + if ( !success + && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) return; self = NM_SUPPLICANT_INTERFACE (user_data); priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - if (error) { + if (!success) { _LOGD ("failed to acquire BSS proxy: (%s)", error->message); g_hash_table_remove (priv->bss_proxies, g_dbus_proxy_get_object_path (proxy)); @@ -1120,7 +1122,7 @@ nm_supplicant_interface_disconnect (NMSupplicantInterface * self) /* Cancel all pending calls related to a prior connection attempt */ if (priv->assoc_data) { - gs_free GError *error = NULL; + gs_free_error GError *error = NULL; nm_utils_error_set_cancelled (&error, FALSE, "NMSupplicantInterface"); assoc_return (self, error, "abort due to disconnect"); @@ -1597,7 +1599,7 @@ dispose (GObject *object) NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); if (priv->assoc_data) { - gs_free GError *error = NULL; + gs_free_error GError *error = NULL; nm_utils_error_set_cancelled (&error, TRUE, "NMSupplicantInterface"); assoc_return (self, error, "cancelled due to dispose of supplicant interface"); diff --git a/src/supplicant/tests/test-supplicant-config.c b/src/supplicant/tests/test-supplicant-config.c index fd91e921..ef6f2c64 100644 --- a/src/supplicant/tests/test-supplicant-config.c +++ b/src/supplicant/tests/test-supplicant-config.c @@ -525,7 +525,7 @@ test_wifi_eap (void) nm_connection_add_setting (connection, NM_SETTING (s_8021x)); nm_setting_802_1x_add_eap_method (s_8021x, "tls"); nm_setting_802_1x_set_client_cert (s_8021x, TEST_CERT_DIR "/test-cert.p12", NM_SETTING_802_1X_CK_SCHEME_PATH, NULL, NULL); - nm_setting_802_1x_set_ca_cert (s_8021x, TEST_CERT_DIR "/test-ca-cert.pem", NM_SETTING_802_1X_CK_SCHEME_PATH, NULL, NULL); + g_assert (nm_setting_802_1x_set_ca_cert (s_8021x, TEST_CERT_DIR "/test-ca-cert.pem", NM_SETTING_802_1X_CK_SCHEME_PATH, NULL, NULL)); nm_setting_802_1x_set_private_key (s_8021x, TEST_CERT_DIR "/test-cert.p12", NULL, NM_SETTING_802_1X_CK_SCHEME_PATH, NULL, NULL); /* IP4 setting */ |