diff options
Diffstat (limited to 'src')
81 files changed, 995 insertions, 580 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index c460caff..8d29b191 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -335,6 +335,7 @@ libNetworkManager_la_SOURCES = \ dhcp-manager/nm-dhcp-client.c \ dhcp-manager/nm-dhcp-client.h \ dhcp-manager/nm-dhcp-client-logging.h \ + dhcp-manager/nm-dhcp-helper-api.h \ dhcp-manager/nm-dhcp-utils.c \ dhcp-manager/nm-dhcp-utils.h \ dhcp-manager/nm-dhcp-listener.c \ diff --git a/src/Makefile.in b/src/Makefile.in index 7f4cf252..d7a37db5 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -118,7 +118,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_options.m4 \ - $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ @@ -162,8 +162,8 @@ am__libNetworkManager_la_SOURCES_DIST = \ devices/nm-device-private.h dhcp-manager/nm-dhcp-client.c \ dhcp-manager/nm-dhcp-client.h \ dhcp-manager/nm-dhcp-client-logging.h \ - dhcp-manager/nm-dhcp-utils.c dhcp-manager/nm-dhcp-utils.h \ - dhcp-manager/nm-dhcp-listener.c \ + dhcp-manager/nm-dhcp-helper-api.h dhcp-manager/nm-dhcp-utils.c \ + dhcp-manager/nm-dhcp-utils.h dhcp-manager/nm-dhcp-listener.c \ dhcp-manager/nm-dhcp-listener.h dhcp-manager/nm-dhcp-manager.c \ dhcp-manager/nm-dhcp-manager.h dns-manager/nm-dns-dnsmasq.c \ dns-manager/nm-dns-dnsmasq.h dns-manager/nm-dns-unbound.c \ @@ -1085,8 +1085,8 @@ libNetworkManager_la_SOURCES = dhcp-manager/nm-dhcp-dhclient-utils.c \ devices/nm-device-private.h dhcp-manager/nm-dhcp-client.c \ dhcp-manager/nm-dhcp-client.h \ dhcp-manager/nm-dhcp-client-logging.h \ - dhcp-manager/nm-dhcp-utils.c dhcp-manager/nm-dhcp-utils.h \ - dhcp-manager/nm-dhcp-listener.c \ + dhcp-manager/nm-dhcp-helper-api.h dhcp-manager/nm-dhcp-utils.c \ + dhcp-manager/nm-dhcp-utils.h dhcp-manager/nm-dhcp-listener.c \ dhcp-manager/nm-dhcp-listener.h dhcp-manager/nm-dhcp-manager.c \ dhcp-manager/nm-dhcp-manager.h dns-manager/nm-dns-dnsmasq.c \ dns-manager/nm-dns-dnsmasq.h dns-manager/nm-dns-unbound.c \ diff --git a/src/NetworkManager.ver b/src/NetworkManager.ver index c91affcb..d5358e5c 100644 --- a/src/NetworkManager.ver +++ b/src/NetworkManager.ver @@ -5,6 +5,16 @@ global: _nm*; NM*; _NM*; + + /* The _IO_stdin_used symbol is used by the GNU libc to determine + which version of the I/O function should be used. Not + exporting it means that the "old" version is used, causing + crashes or other issues on some architectures. It should be + exported as an anonymous tag, but ld does not support mixing + anonymous version tags with other version tags. Fortunately + the GNU libc is able to cope with the symbol having the wrong + version tag. */ + _IO_stdin_used; local: *; }; diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c index 7eb6cf16..7cfe03f1 100644 --- a/src/NetworkManagerUtils.c +++ b/src/NetworkManagerUtils.c @@ -528,6 +528,39 @@ check_connection_mac_address (NMConnection *orig, } static gboolean +check_connection_infiniband_mac_address (NMConnection *orig, + NMConnection *candidate, + GHashTable *settings) +{ + GHashTable *props; + const char *orig_mac = NULL, *cand_mac = NULL; + NMSettingInfiniband *s_infiniband_orig, *s_infiniband_cand; + + props = check_property_in_hash (settings, + NM_SETTING_INFINIBAND_SETTING_NAME, + NM_SETTING_INFINIBAND_MAC_ADDRESS); + if (!props) + return TRUE; + + /* If one of the MAC addresses is NULL, we accept that connection */ + s_infiniband_orig = nm_connection_get_setting_infiniband (orig); + if (s_infiniband_orig) + orig_mac = nm_setting_infiniband_get_mac_address (s_infiniband_orig); + + s_infiniband_cand = nm_connection_get_setting_infiniband (candidate); + if (s_infiniband_cand) + cand_mac = nm_setting_infiniband_get_mac_address (s_infiniband_cand); + + if (!orig_mac || !cand_mac) { + remove_from_hash (settings, props, + NM_SETTING_INFINIBAND_SETTING_NAME, + NM_SETTING_INFINIBAND_MAC_ADDRESS); + return TRUE; + } + return FALSE; +} + +static gboolean check_connection_cloned_mac_address (NMConnection *orig, NMConnection *candidate, GHashTable *settings) @@ -640,6 +673,9 @@ check_possible_match (NMConnection *orig, if (!check_connection_mac_address (orig, candidate, settings)) return NULL; + if (!check_connection_infiniband_mac_address (orig, candidate, settings)) + return NULL; + if (!check_connection_cloned_mac_address (orig, candidate, settings)) return NULL; diff --git a/src/devices/Makefile.in b/src/devices/Makefile.in index 4791015d..b247b35b 100644 --- a/src/devices/Makefile.in +++ b/src/devices/Makefile.in @@ -92,7 +92,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_options.m4 \ - $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ diff --git a/src/devices/adsl/Makefile.in b/src/devices/adsl/Makefile.in index f3fbad4c..37015ab1 100644 --- a/src/devices/adsl/Makefile.in +++ b/src/devices/adsl/Makefile.in @@ -93,7 +93,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_options.m4 \ - $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ diff --git a/src/devices/bluetooth/Makefile.in b/src/devices/bluetooth/Makefile.in index c010f4c7..ce12d2d4 100644 --- a/src/devices/bluetooth/Makefile.in +++ b/src/devices/bluetooth/Makefile.in @@ -99,7 +99,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_options.m4 \ - $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c index 90d472da..b213a0cc 100644 --- a/src/devices/nm-device-ethernet.c +++ b/src/devices/nm-device-ethernet.c @@ -127,18 +127,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceEthernet, G_DEFINE_TYPE (NMDeviceEthernet, nm_device_ethernet, NM_TYPE_DEVICE) -#define NM_DEVICE_ETHERNET_GET_PRIVATE(self) \ - ({ \ - /* preserve the const-ness of self. Unfortunately, that - * way, @self cannot be a void pointer */ \ - typeof (self) _self = (self); \ - \ - /* Get compiler error if variable is of wrong type */ \ - _nm_unused const NMDeviceEthernet *_self2 = (_self); \ - \ - nm_assert (NM_IS_DEVICE_ETHERNET (_self)); \ - _self->_priv; \ - }) +#define NM_DEVICE_ETHERNET_GET_PRIVATE(self) _NM_GET_PRIVATE_PTR(self, NMDeviceEthernet, NM_IS_DEVICE_ETHERNET) /*****************************************************************************/ diff --git a/src/devices/nm-device-veth.c b/src/devices/nm-device-veth.c index cca86fbe..56923315 100644 --- a/src/devices/nm-device-veth.c +++ b/src/devices/nm-device-veth.c @@ -62,18 +62,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceVeth, G_DEFINE_TYPE (NMDeviceVeth, nm_device_veth, NM_TYPE_DEVICE_ETHERNET) -#define NM_DEVICE_VETH_GET_PRIVATE(self) \ - ({ \ - /* preserve the const-ness of self. Unfortunately, that - * way, @self cannot be a void pointer */ \ - typeof (self) _self = (self); \ - \ - /* Get compiler error if variable is of wrong type */ \ - _nm_unused const NMDeviceVeth *_self2 = (_self); \ - \ - nm_assert (NM_IS_DEVICE_VETH (_self)); \ - &_self->_priv; \ - }) +#define NM_DEVICE_VETH_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMDeviceVeth, NM_IS_DEVICE_VETH) /*****************************************************************************/ diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 199acc66..27d940c9 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -75,18 +75,7 @@ _LOG_DECLARE_SELF (NMDevice); G_DEFINE_ABSTRACT_TYPE (NMDevice, nm_device, NM_TYPE_EXPORTED_OBJECT) -#define NM_DEVICE_GET_PRIVATE(self) \ - ({ \ - /* preserve the const-ness of self. Unfortunately, that - * way, @self cannot be a void pointer */ \ - typeof (self) _self = (self); \ - \ - /* Get compiler error if variable is of wrong type */ \ - _nm_unused const NMDevice *_self2 = (_self); \ - \ - nm_assert (NM_IS_DEVICE (_self)); \ - _self->priv; \ - }) +#define NM_DEVICE_GET_PRIVATE(self) _NM_GET_PRIVATE_PTR(self, NMDevice, NM_IS_DEVICE) enum { STATE_CHANGED, @@ -1526,7 +1515,7 @@ is_unmanaged_external_down (NMDevice *self, gboolean consider_can) /* Manage externally-created software interfaces only when they are IFF_UP */ if ( priv->ifindex <= 0 || !priv->up - || !nm_platform_link_can_assume (NM_PLATFORM_GET, priv->ifindex)) + || !(priv->slaves || nm_platform_link_can_assume (NM_PLATFORM_GET, priv->ifindex))) return NM_UNMAN_FLAG_OP_SET_UNMANAGED; return NM_UNMAN_FLAG_OP_SET_MANAGED; @@ -2029,7 +2018,7 @@ link_type_compatible (NMDevice *self, return FALSE; } - device_type = self->priv->link_type; + device_type = self->_priv->link_type; if (device_type > NM_LINK_TYPE_UNKNOWN && device_type != link_type) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, "Needed link type 0x%x does not match the platform link type 0x%X", @@ -2526,6 +2515,7 @@ nm_device_unrealize (NMDevice *self, gboolean remove_resources, GError **error) NM_UNMANAGED_PARENT | NM_UNMANAGED_LOOPBACK | NM_UNMANAGED_USER_UDEV | + NM_UNMANAGED_USER_EXPLICIT | NM_UNMANAGED_EXTERNAL_DOWN | NM_UNMANAGED_IS_SLAVE, NM_UNMAN_FLAG_OP_FORGET); @@ -2627,6 +2617,7 @@ slave_state_changed (NMDevice *slave, { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); gboolean release = FALSE; + gboolean configure = TRUE; _LOGD (LOGD_DEVICE, "slave %s state change %d (%s) -> %d (%s)", nm_device_get_iface (slave), @@ -2649,8 +2640,12 @@ slave_state_changed (NMDevice *slave, release = TRUE; } + /* Don't touch the device if its state changed externally. */ + if (reason == NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED) + configure = FALSE; + if (release) { - nm_device_master_release_one_slave (self, slave, TRUE, reason); + nm_device_master_release_one_slave (self, slave, configure, reason); /* Bridge/bond/team interfaces are left up until manually deactivated */ if (priv->slaves == NULL && priv->state == NM_DEVICE_STATE_ACTIVATED) _LOGD (LOGD_DEVICE, "last slave removed; remaining activated"); @@ -3215,8 +3210,8 @@ device_has_config (NMDevice *self) if (nm_device_is_software (self) && nm_device_is_real (self)) return TRUE; - /* Slaves are also configured by definition */ - if (nm_platform_link_get_master (NM_PLATFORM_GET, priv->ifindex) > 0) + /* Master-slave relationship is also a configuration */ + if (priv->slaves || nm_platform_link_get_master (NM_PLATFORM_GET, priv->ifindex) > 0) return TRUE; return FALSE; @@ -5970,7 +5965,7 @@ dhcp6_start (NMDevice *self, gboolean wait_for_ll, NMDeviceStateReason *reason) } if (!dhcp6_start_with_link_ready (self, connection)) { - *reason = NM_DEVICE_STATE_REASON_DHCP_START_FAILED; + NM_SET_OUT (reason, NM_DEVICE_STATE_REASON_DHCP_START_FAILED); return FALSE; } @@ -7005,7 +7000,7 @@ nm_device_activate_schedule_stage3_ip_config_start (NMDevice *self) s_con = nm_connection_get_setting_connection (connection); if (!priv->fw_ready) { - if (nm_device_uses_assumed_connection (self)) + if (nm_device_uses_generated_assumed_connection (self)) priv->fw_ready = TRUE; else { if (!priv->fw_call) { @@ -7786,6 +7781,7 @@ nm_device_reactivate_ip4_config (NMDevice *self, NMSettingIPConfig *s_ip4_new) { NMDevicePrivate *priv; + const char *method_old, *method_new; g_return_if_fail (NM_IS_DEVICE (self)); priv = NM_DEVICE_GET_PRIVATE (self); @@ -7798,8 +7794,14 @@ nm_device_reactivate_ip4_config (NMDevice *self, s_ip4_new, nm_device_get_ip4_route_metric (self)); - if (strcmp (nm_setting_ip_config_get_method (s_ip4_new), - nm_setting_ip_config_get_method (s_ip4_old))) { + method_old = s_ip4_old ? + nm_setting_ip_config_get_method (s_ip4_old) : + NM_SETTING_IP4_CONFIG_METHOD_DISABLED; + method_new = s_ip4_new ? + nm_setting_ip_config_get_method (s_ip4_new) : + NM_SETTING_IP4_CONFIG_METHOD_DISABLED; + + if (!nm_streq0 (method_old, method_new)) { _cleanup_ip4_pre (self, CLEANUP_TYPE_DECONFIGURE); priv->ip4_state = IP_WAIT; if (!nm_device_activate_stage3_ip4_start (self)) @@ -7817,6 +7819,7 @@ nm_device_reactivate_ip6_config (NMDevice *self, NMSettingIPConfig *s_ip6_new) { NMDevicePrivate *priv; + const char *method_old, *method_new; g_return_if_fail (NM_IS_DEVICE (self)); priv = NM_DEVICE_GET_PRIVATE (self); @@ -7829,8 +7832,14 @@ nm_device_reactivate_ip6_config (NMDevice *self, s_ip6_new, nm_device_get_ip6_route_metric (self)); - if (strcmp (nm_setting_ip_config_get_method (s_ip6_new), - nm_setting_ip_config_get_method (s_ip6_old))) { + method_old = s_ip6_old ? + nm_setting_ip_config_get_method (s_ip6_old) : + NM_SETTING_IP6_CONFIG_METHOD_IGNORE; + method_new = s_ip6_new ? + nm_setting_ip_config_get_method (s_ip6_new) : + NM_SETTING_IP6_CONFIG_METHOD_IGNORE; + + if (!nm_streq0 (method_old, method_new)) { _cleanup_ip6_pre (self, CLEANUP_TYPE_DECONFIGURE); priv->ip6_state = IP_WAIT; if (!nm_device_activate_stage3_ip6_start (self)) @@ -10058,7 +10067,7 @@ nm_device_set_unmanaged_by_user_udev (NMDevice *self) int ifindex; gboolean platform_unmanaged = FALSE; - ifindex = self->priv->ifindex; + ifindex = self->_priv->ifindex; if ( ifindex <= 0 || !nm_platform_link_get_unmanaged (NM_PLATFORM_GET, ifindex, &platform_unmanaged)) @@ -10145,7 +10154,7 @@ nm_device_reapply_settings_immediately (NMDevice *self) if (g_strcmp0 ((zone = nm_setting_connection_get_zone (s_con_settings)), nm_setting_connection_get_zone (s_con_applied)) != 0) { - version_id = nm_active_connection_version_id_bump ((NMActiveConnection *) self->priv->act_request); + version_id = nm_active_connection_version_id_bump ((NMActiveConnection *) self->_priv->act_request); _LOGD (LOGD_DEVICE, "reapply setting: zone = %s%s%s (version-id %llu)", NM_PRINT_FMT_QUOTE_STRING (zone), (long long unsigned) version_id); g_object_set (G_OBJECT (s_con_applied), @@ -10157,7 +10166,7 @@ nm_device_reapply_settings_immediately (NMDevice *self) if ((metered = nm_setting_connection_get_metered (s_con_settings)) != nm_setting_connection_get_metered (s_con_applied)) { - version_id = nm_active_connection_version_id_bump ((NMActiveConnection *) self->priv->act_request); + version_id = nm_active_connection_version_id_bump ((NMActiveConnection *) self->_priv->act_request); _LOGD (LOGD_DEVICE, "reapply setting: metered = %d (version-id %llu)", (int) metered, (long long unsigned) version_id); g_object_set (G_OBJECT (s_con_applied), @@ -10181,8 +10190,8 @@ nm_device_update_firewall_zone (NMDevice *self) return; s_con = nm_connection_get_setting_connection (applied_connection); - if ( nm_device_get_state (self) == NM_DEVICE_STATE_ACTIVATED - && !nm_device_uses_assumed_connection (self)) { + if ( nm_device_get_state (self) == NM_DEVICE_STATE_ACTIVATED + && !nm_device_uses_generated_assumed_connection (self)) { nm_firewall_manager_add_or_change_zone (nm_firewall_manager_get (), nm_device_get_ip_iface (self), nm_setting_connection_get_zone (s_con), @@ -10336,22 +10345,22 @@ nm_device_check_connection_available (NMDevice *self, static gboolean available_connections_del_all (NMDevice *self) { - if (g_hash_table_size (self->priv->available_connections) == 0) + if (g_hash_table_size (self->_priv->available_connections) == 0) return FALSE; - g_hash_table_remove_all (self->priv->available_connections); + g_hash_table_remove_all (self->_priv->available_connections); return TRUE; } static gboolean available_connections_add (NMDevice *self, NMConnection *connection) { - return nm_g_hash_table_add (self->priv->available_connections, g_object_ref (connection)); + return nm_g_hash_table_add (self->_priv->available_connections, g_object_ref (connection)); } static gboolean available_connections_del (NMDevice *self, NMConnection *connection) { - return g_hash_table_remove (self->priv->available_connections, connection); + return g_hash_table_remove (self->_priv->available_connections, connection); } static gboolean @@ -10673,7 +10682,7 @@ _cleanup_generic_pre (NMDevice *self, CleanupType cleanup_type) connection = nm_device_get_applied_connection (self); if ( cleanup_type == CLEANUP_TYPE_DECONFIGURE && connection - && !nm_device_uses_assumed_connection (self)) { + && !nm_device_uses_generated_assumed_connection (self)) { nm_firewall_manager_remove_from_zone (nm_firewall_manager_get (), nm_device_get_ip_iface (self), NULL, @@ -11374,7 +11383,7 @@ _set_state_full (NMDevice *self, if ( applied_connection && priv->ifindex != priv->ip_ifindex - && !nm_device_uses_assumed_connection (self)) { + && !nm_device_uses_generated_assumed_connection (self)) { NMSettingConnection *s_con; const char *zone; @@ -11560,16 +11569,17 @@ nm_device_get_hw_address (NMDevice *self) return priv->hw_addr; } -void +gboolean nm_device_update_hw_address (NMDevice *self) { NMDevicePrivate *priv; const guint8 *hwaddr; gsize hwaddrlen = 0; + gboolean changed = FALSE; priv = NM_DEVICE_GET_PRIVATE (self); if (priv->ifindex <= 0) - return; + return FALSE; hwaddr = nm_platform_link_get_address (NM_PLATFORM_GET, priv->ifindex, &hwaddrlen); @@ -11596,6 +11606,7 @@ nm_device_update_hw_address (NMDevice *self) * update our inital hw-address as well. */ nm_device_update_initial_hw_address (self); } + changed = TRUE; } } else { /* Invalid or no hardware address */ @@ -11608,6 +11619,7 @@ nm_device_update_hw_address (NMDevice *self) "hw-addr: failed reading current MAC address"); } } + return changed; } void @@ -11767,6 +11779,15 @@ nm_device_hw_addr_is_explict (NMDevice *self) } static gboolean +_hw_addr_matches (NMDevice *self, const char *addr) +{ + const char *cur_addr; + + cur_addr = nm_device_get_hw_address (self); + return cur_addr && nm_utils_hwaddr_matches (cur_addr, -1, addr, -1); +} + +static gboolean _hw_addr_set (NMDevice *self, const char *addr, const char *operation, @@ -11775,7 +11796,6 @@ _hw_addr_set (NMDevice *self, NMDevicePrivate *priv; gboolean success = FALSE; NMPlatformError plerr; - const char *cur_addr; guint8 addr_bytes[NM_UTILS_HWADDR_LEN_MAX]; guint hw_addr_len; gboolean was_up; @@ -11786,11 +11806,9 @@ _hw_addr_set (NMDevice *self, priv = NM_DEVICE_GET_PRIVATE (self); - cur_addr = nm_device_get_hw_address (self); - /* Do nothing if current MAC is same */ - if (cur_addr && nm_utils_hwaddr_matches (cur_addr, -1, addr, -1)) { - _LOGT (LOGD_DEVICE, "set-hw-addr: no MAC address change needed (%s)", cur_addr); + if (_hw_addr_matches (self, addr)) { + _LOGT (LOGD_DEVICE, "set-hw-addr: no MAC address change needed (%s)", addr); return TRUE; } @@ -11814,15 +11832,59 @@ _hw_addr_set (NMDevice *self, if (success) { /* MAC address succesfully changed; update the current MAC to match */ nm_device_update_hw_address (self); - cur_addr = nm_device_get_hw_address (self); - if (cur_addr && nm_utils_hwaddr_matches (cur_addr, -1, addr, -1)) { + if (_hw_addr_matches (self, addr)) { _LOGI (LOGD_DEVICE, "set-hw-addr: %s MAC address to %s (%s)", operation, addr, detail); } else { - _LOGW (LOGD_DEVICE, - "set-hw-addr: new MAC address %s not successfully set to %s (%s)", + gint64 poll_end, now; + + _LOGD (LOGD_DEVICE, + "set-hw-addr: new MAC address %s not successfully %s (%s) (refresh link)", addr, operation, detail); - success = FALSE; + + /* The platform call indicated success, however the address is not + * as expected. That is either due to a driver issue (brcmfmac, bgo#770456, + * rh#1374023) or a race where externally the MAC address was reset. + * The race is rather unlikely. + * + * The alternative would be to postpone the activation in case the + * MAC address is not yet ready and poll without blocking. However, + * that is rather complicated and it is not expected that this case + * happens for regular drivers. + * Note that brcmfmac can block NetworkManager for 500 msec while + * taking down the device. Let's add annother 100 msec to that. + * + * wait/poll up to 100 msec until it changes. */ + + poll_end = nm_utils_get_monotonic_timestamp_us () + (100 * 1000); + for (;;) { + if (!nm_platform_link_refresh (NM_PLATFORM_GET, nm_device_get_ip_ifindex (self))) + goto handle_fail; + if (!nm_device_update_hw_address (self)) + goto handle_wait; + if (!_hw_addr_matches (self, addr)) + goto handle_fail; + + break; +handle_wait: + now = nm_utils_get_monotonic_timestamp_us (); + if (now < poll_end) { + g_usleep (NM_MIN (poll_end - now, 500)); + continue; + } +handle_fail: + success = FALSE; + break; + } + + if (success) { + _LOGI (LOGD_DEVICE, "set-hw-addr: %s MAC address to %s (%s)", + operation, addr, detail); + } else { + _LOGW (LOGD_DEVICE, + "set-hw-addr: new MAC address %s not successfully %s (%s)", + addr, operation, detail); + } } } else { _NMLOG (plerr == NM_PLATFORM_ERROR_NOT_FOUND ? LOGL_DEBUG : LOGL_WARN, @@ -12075,7 +12137,7 @@ nm_device_init (NMDevice *self) priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_DEVICE, NMDevicePrivate); - self->priv = priv; + self->_priv = priv; priv->type = NM_DEVICE_TYPE_UNKNOWN; priv->capabilities = NM_DEVICE_CAP_NM_SUPPORTED; @@ -12328,21 +12390,22 @@ set_property (GObject *object, guint prop_id, case PROP_IP4_ADDRESS: priv->ip4_address = g_value_get_uint (value); break; - case PROP_MANAGED: { - gboolean managed; - NMDeviceStateReason reason; + case PROP_MANAGED: + if (nm_device_is_real (self)) { + gboolean managed; + NMDeviceStateReason reason; - managed = g_value_get_boolean (value); - if (managed) - reason = NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED; - else - reason = NM_DEVICE_STATE_REASON_REMOVED; - nm_device_set_unmanaged_by_flags (self, - NM_UNMANAGED_USER_EXPLICIT, - !managed, - reason); + managed = g_value_get_boolean (value); + if (managed) + reason = NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED; + else + reason = NM_DEVICE_STATE_REASON_REMOVED; + nm_device_set_unmanaged_by_flags (self, + NM_UNMANAGED_USER_EXPLICIT, + !managed, + reason); + } break; - } case PROP_AUTOCONNECT: nm_device_set_autoconnect (self, g_value_get_boolean (value)); break; diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index 34d31cad..a757a37e 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -125,7 +125,7 @@ struct _NMDevice { NMExportedObject parent; /* private */ - struct _NMDevicePrivate *priv; + struct _NMDevicePrivate *_priv; }; /* The flags have an relaxing meaning, that means, specifying more flags, can make @@ -588,7 +588,7 @@ void nm_device_reactivate_ip6_config (NMDevice *device, NMSettingIPConfig *s_ip6_old, NMSettingIPConfig *s_ip6_new); -void nm_device_update_hw_address (NMDevice *self); +gboolean nm_device_update_hw_address (NMDevice *self); void nm_device_update_initial_hw_address (NMDevice *self); void nm_device_update_permanent_hw_address (NMDevice *self); void nm_device_update_dynamic_ip_setup (NMDevice *self); diff --git a/src/devices/team/Makefile.in b/src/devices/team/Makefile.in index 922ec593..f227a77a 100644 --- a/src/devices/team/Makefile.in +++ b/src/devices/team/Makefile.in @@ -95,7 +95,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_options.m4 \ - $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ diff --git a/src/devices/tests/Makefile.in b/src/devices/tests/Makefile.in index 7c25dc11..866fe0e1 100644 --- a/src/devices/tests/Makefile.in +++ b/src/devices/tests/Makefile.in @@ -95,7 +95,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_options.m4 \ - $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ diff --git a/src/devices/wifi/Makefile.in b/src/devices/wifi/Makefile.in index 134c4012..42246d5c 100644 --- a/src/devices/wifi/Makefile.in +++ b/src/devices/wifi/Makefile.in @@ -93,7 +93,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_options.m4 \ - $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index 49c380af..f97e6689 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -138,18 +138,7 @@ struct _NMDeviceWifiClass G_DEFINE_TYPE (NMDeviceWifi, nm_device_wifi, NM_TYPE_DEVICE) -#define NM_DEVICE_WIFI_GET_PRIVATE(self) \ - ({ \ - /* preserve the const-ness of self. Unfortunately, that - * way, @self cannot be a void pointer */ \ - typeof (self) _self = (self); \ - \ - /* Get compiler error if variable is of wrong type */ \ - _nm_unused const NMDeviceWifi *_self2 = (_self); \ - \ - nm_assert (NM_IS_DEVICE_WIFI (_self)); \ - &_self->_priv; \ - }) +#define NM_DEVICE_WIFI_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMDeviceWifi, NM_IS_DEVICE_WIFI) /*****************************************************************************/ diff --git a/src/devices/wifi/nm-wifi-ap.c b/src/devices/wifi/nm-wifi-ap.c index e1beb85b..2232f826 100644 --- a/src/devices/wifi/nm-wifi-ap.c +++ b/src/devices/wifi/nm-wifi-ap.c @@ -68,18 +68,7 @@ struct _NMAccessPointClass{ NMExportedObjectClass parent; }; -#define NM_AP_GET_PRIVATE(self) \ - ({ \ - /* preserve the const-ness of self. Unfortunately, that - * way, @self cannot be a void pointer */ \ - typeof (self) _self = (self); \ - \ - /* Get compiler error if variable is of wrong type */ \ - _nm_unused const NMAccessPoint *_self2 = (_self); \ - \ - nm_assert (NM_IS_AP (_self)); \ - &_self->_priv; \ - }) +#define NM_AP_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMAccessPoint, NM_IS_AP) G_DEFINE_TYPE (NMAccessPoint, nm_ap, NM_TYPE_EXPORTED_OBJECT) diff --git a/src/devices/wifi/tests/Makefile.in b/src/devices/wifi/tests/Makefile.in index 64113a21..676ae990 100644 --- a/src/devices/wifi/tests/Makefile.in +++ b/src/devices/wifi/tests/Makefile.in @@ -95,7 +95,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_options.m4 \ - $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ diff --git a/src/devices/wwan/Makefile.in b/src/devices/wwan/Makefile.in index 6d395567..22ba0f30 100644 --- a/src/devices/wwan/Makefile.in +++ b/src/devices/wwan/Makefile.in @@ -98,7 +98,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_options.m4 \ - $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ diff --git a/src/dhcp-manager/Makefile.am b/src/dhcp-manager/Makefile.am index b4590b4b..42954127 100644 --- a/src/dhcp-manager/Makefile.am +++ b/src/dhcp-manager/Makefile.am @@ -1,6 +1,9 @@ libexec_PROGRAMS = nm-dhcp-helper -nm_dhcp_helper_SOURCES = nm-dhcp-helper.c +nm_dhcp_helper_SOURCES = \ + nm-dhcp-helper.c \ + nm-dhcp-helper-api.h \ + $(NULL) nm_dhcp_helper_CPPFLAGS = \ $(GLIB_CFLAGS) \ diff --git a/src/dhcp-manager/Makefile.in b/src/dhcp-manager/Makefile.in index dcb45183..5309cde6 100644 --- a/src/dhcp-manager/Makefile.in +++ b/src/dhcp-manager/Makefile.in @@ -94,7 +94,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_options.m4 \ - $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ @@ -456,7 +456,11 @@ with_dhcpcd = @with_dhcpcd@ with_netconfig = @with_netconfig@ with_resolvconf = @with_resolvconf@ with_valgrind = @with_valgrind@ -nm_dhcp_helper_SOURCES = nm-dhcp-helper.c +nm_dhcp_helper_SOURCES = \ + nm-dhcp-helper.c \ + nm-dhcp-helper-api.h \ + $(NULL) + nm_dhcp_helper_CPPFLAGS = \ $(GLIB_CFLAGS) \ -I$(top_srcdir)/shared \ diff --git a/src/dhcp-manager/nm-dhcp-helper-api.h b/src/dhcp-manager/nm-dhcp-helper-api.h new file mode 100644 index 00000000..a3eb171d --- /dev/null +++ b/src/dhcp-manager/nm-dhcp-helper-api.h @@ -0,0 +1,36 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2016 Red Hat, Inc. + */ + +#ifndef __NM_DHCP_HELPER_API_H__ +#define __NM_DHCP_HELPER_API_H__ + +/******************************************************************************/ + +#define NM_DHCP_CLIENT_DBUS_IFACE "org.freedesktop.nm_dhcp_client" + +#define NM_DHCP_HELPER_SERVER_BUS_NAME "org.freedesktop.nm_dhcp_server" +#define NM_DHCP_HELPER_SERVER_OBJECT_PATH "/org/freedesktop/nm_dhcp_server" +#define NM_DHCP_HELPER_SERVER_INTERFACE_NAME "org.freedesktop.nm_dhcp_server" +#define NM_DHCP_HELPER_SERVER_METHOD_NOTIFY "Notify" + +/******************************************************************************/ + +#endif /* __NM_DHCP_HELPER_API_H__ */ diff --git a/src/dhcp-manager/nm-dhcp-helper.c b/src/dhcp-manager/nm-dhcp-helper.c index 7667084d..9c6f69b8 100644 --- a/src/dhcp-manager/nm-dhcp-helper.c +++ b/src/dhcp-manager/nm-dhcp-helper.c @@ -25,7 +25,42 @@ #include <string.h> #include <signal.h> -#define NM_DHCP_CLIENT_DBUS_IFACE "org.freedesktop.nm_dhcp_client" +#include "nm-utils/nm-vpn-plugin-macros.h" + +#include "nm-dhcp-helper-api.h" + +/*****************************************************************************/ + +#ifdef NM_MORE_LOGGING +#define _NMLOG_ENABLED(level) TRUE +#else +#define _NMLOG_ENABLED(level) ((level) <= LOG_ERR) +#endif + +#define _NMLOG(always_enabled, level, ...) \ + G_STMT_START { \ + if ((always_enabled) || _NMLOG_ENABLED (level)) { \ + GTimeVal _tv; \ + \ + g_get_current_time (&_tv); \ + g_print ("nm-dhcp-helper[%ld] %-7s [%ld.%04ld] " _NM_UTILS_MACRO_FIRST (__VA_ARGS__) "\n", \ + (long) getpid (), \ + nm_utils_syslog_to_str (level), \ + _tv.tv_sec, _tv.tv_usec / 100 \ + _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ + } \ + } G_STMT_END + +#define _LOGD(...) _NMLOG(TRUE, LOG_INFO, __VA_ARGS__) +#define _LOGI(...) _NMLOG(TRUE, LOG_NOTICE, __VA_ARGS__) +#define _LOGW(...) _NMLOG(TRUE, LOG_WARNING, __VA_ARGS__) +#define _LOGE(...) _NMLOG(TRUE, LOG_ERR, __VA_ARGS__) + +#define _LOGd(...) _NMLOG(FALSE, LOG_INFO, __VA_ARGS__) +#define _LOGi(...) _NMLOG(FALSE, LOG_NOTICE, __VA_ARGS__) +#define _LOGw(...) _NMLOG(FALSE, LOG_WARNING, __VA_ARGS__) + +/*****************************************************************************/ static const char * ignore[] = {"PATH", "SHLVL", "_", "PWD", "dhc_dbus", NULL}; @@ -70,30 +105,34 @@ build_signal_parameters (void) g_free (name); } - return g_variant_new ("(a{sv})", &builder); + return g_variant_ref_sink (g_variant_new ("(a{sv})", &builder)); } static void -fatal_error (void) +kill_pid (void) { - const char *pid_str = getenv ("pid"); - int pid = 0; + const char *pid_str; + pid_t pid = 0; + pid_str = getenv ("pid"); if (pid_str) pid = strtol (pid_str, NULL, 10); if (pid) { - g_printerr ("Fatal error occured, killing dhclient instance with pid %d.\n", pid); + _LOGI ("a fatal error occured, kill dhclient instance with pid %d\n", pid); kill (pid, SIGTERM); } - - exit (1); } int main (int argc, char *argv[]) { - GDBusConnection *connection; - GError *error = NULL; + gs_unref_object GDBusConnection *connection = NULL; + gs_free_error GError *error = NULL; + gs_unref_variant GVariant *parameters = NULL; + gs_unref_variant GVariant *result = NULL; + gboolean success = FALSE; + guint try_count = 0; + gint64 time_end; nm_g_type_init (); @@ -102,33 +141,81 @@ main (int argc, char *argv[]) NULL, NULL, &error); if (!connection) { g_dbus_error_strip_remote_error (error); - g_printerr ("Error: could not connect to NetworkManager D-Bus socket: %s\n", - error->message); - g_error_free (error); - fatal_error (); + _LOGE ("could not connect to NetworkManager D-Bus socket: %s", + error->message); + goto out; } - if (!g_dbus_connection_emit_signal (connection, - NULL, - "/", - NM_DHCP_CLIENT_DBUS_IFACE, - "Event", - build_signal_parameters (), - &error)) { - g_dbus_error_strip_remote_error (error); - g_printerr ("Error: Could not send DHCP Event signal: %s\n", error->message); - g_error_free (error); - fatal_error (); - } + parameters = build_signal_parameters (); + + time_end = g_get_monotonic_time () + (200 * 1000L); /* retry for at most 200 milliseconds */ + +do_notify: + try_count++; + result = g_dbus_connection_call_sync (connection, + NULL, + NM_DHCP_HELPER_SERVER_OBJECT_PATH, + NM_DHCP_HELPER_SERVER_INTERFACE_NAME, + NM_DHCP_HELPER_SERVER_METHOD_NOTIFY, + parameters, + NULL, + G_DBUS_CALL_FLAGS_NONE, + 1000, + NULL, + &error); + + if (!result) { + gs_free char *s_err = NULL; + + s_err = g_dbus_error_get_remote_error (error); + if (NM_IN_STRSET (s_err, "org.freedesktop.DBus.Error.UnknownMethod")) { + gint64 remaining_time = time_end - g_get_monotonic_time (); + + /* I am not sure that a race can actually happen, as we register the object + * on the server side during GDBusServer:new-connection signal. + * + * However, there was also a race for subscribing to an event, so let's just + * do some retry. */ + if (remaining_time > 0) { + _LOGi ("failure to call notify: %s (retry %u)", error->message, try_count); + g_usleep (NM_MIN (NM_CLAMP ((gint64) (100L * (1L << try_count)), 5000, 25000), remaining_time)); + g_clear_error (&error); + goto do_notify; + } + } + _LOGW ("failure to call notify: %s (try signal via Event)", error->message); + g_clear_error (&error); + + /* for backward compatibilty, try to emit the signal. There is no stable + * API between the dhcp-helper and NetworkManager. However, while upgrading + * the NetworkManager package, a newer helper might want to notify an + * older server, which still uses the "Event". */ + if (!g_dbus_connection_emit_signal (connection, + NULL, + "/", + NM_DHCP_CLIENT_DBUS_IFACE, + "Event", + parameters, + &error)) { + g_dbus_error_strip_remote_error (error); + _LOGE ("could not send DHCP Event signal: %s", error->message); + goto out; + } + /* We were able to send the asynchronous Event. Consider that a success. */ + success = TRUE; + } else + success = TRUE; if (!g_dbus_connection_flush_sync (connection, NULL, &error)) { g_dbus_error_strip_remote_error (error); - g_printerr ("Error: Could not flush D-Bus connection: %s\n", error->message); - g_error_free (error); - fatal_error (); + _LOGE ("could not flush D-Bus connection: %s", error->message); + success = FALSE; + goto out; } - g_object_unref (connection); - return 0; +out: + if (!success) + kill_pid (); + return success ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/src/dhcp-manager/nm-dhcp-listener.c b/src/dhcp-manager/nm-dhcp-listener.c index eadff3ec..0df41973 100644 --- a/src/dhcp-manager/nm-dhcp-listener.c +++ b/src/dhcp-manager/nm-dhcp-listener.c @@ -13,12 +13,14 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright 2014 Red Hat, Inc. + * Copyright 2014 - 2016 Red Hat, Inc. * */ #include "nm-default.h" +#include "nm-dhcp-listener.h" + #include <sys/socket.h> #include <sys/wait.h> #include <signal.h> @@ -27,25 +29,31 @@ #include <errno.h> #include <unistd.h> -#include "nm-dhcp-listener.h" +#include "nm-dhcp-helper-api.h" #include "nm-core-internal.h" #include "nm-bus-manager.h" #include "NetworkManagerUtils.h" -#define NM_DHCP_CLIENT_DBUS_IFACE "org.freedesktop.nm_dhcp_client" #define PRIV_SOCK_PATH NMRUNDIR "/private-dhcp" #define PRIV_SOCK_TAG "dhcp" +/*****************************************************************************/ + typedef struct { NMBusManager * dbus_mgr; gulong new_conn_id; gulong dis_conn_id; - GHashTable * signal_handlers; + GHashTable * connections; } NMDhcpListenerPrivate; -#define NM_DHCP_LISTENER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DHCP_LISTENER, NMDhcpListenerPrivate)) +struct _NMDhcpListener { + GObject parent; + NMDhcpListenerPrivate _priv; +}; -G_DEFINE_TYPE (NMDhcpListener, nm_dhcp_listener, G_TYPE_OBJECT) +struct _NMDhcpListenerClass { + GObjectClass parent_class; +}; enum { EVENT, @@ -53,7 +61,30 @@ enum { }; static guint signals[LAST_SIGNAL] = { 0 }; -/***************************************************/ +G_DEFINE_TYPE (NMDhcpListener, nm_dhcp_listener, G_TYPE_OBJECT) + +#define NM_DHCP_LISTENER_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMDhcpListener, NM_IS_DHCP_LISTENER) + +NM_DEFINE_SINGLETON_GETTER (NMDhcpListener, nm_dhcp_listener_get, NM_TYPE_DHCP_LISTENER); + +/*****************************************************************************/ + +#define _NMLOG_PREFIX_NAME "dhcp-listener" +#define _NMLOG_DOMAIN LOGD_DHCP +#define _NMLOG(level, ...) \ + G_STMT_START { \ + const NMDhcpListener *_self = (self); \ + char _prefix[64]; \ + \ + nm_log ((level), (_NMLOG_DOMAIN), \ + "%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + (_self != singleton_instance \ + ? nm_sprintf_buf (_prefix, "%s[%p]", _NMLOG_PREFIX_NAME, _self) \ + : _NMLOG_PREFIX_NAME )\ + _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } G_STMT_END + +/*****************************************************************************/ static char * get_option (GVariant *options, const char *key) @@ -88,13 +119,14 @@ get_option (GVariant *options, const char *key) } static void -handle_event (GDBusConnection *connection, - const char *sender_name, - const char *object_path, - const char *interface_name, - const char *signal_name, - GVariant *parameters, - gpointer user_data) +_method_call (GDBusConnection *connection, + const char *sender, + const char *object_path, + const char *interface_name, + const char *method_name, + GVariant *parameters, + GDBusMethodInvocation *invocation, + gpointer user_data) { NMDhcpListener *self = NM_DHCP_LISTENER (user_data); char *iface = NULL; @@ -104,27 +136,31 @@ handle_event (GDBusConnection *connection, gboolean handled = FALSE; GVariant *options; + if (!nm_streq0 (interface_name, NM_DHCP_HELPER_SERVER_INTERFACE_NAME)) + g_return_if_reached (); + if (!nm_streq0 (method_name, NM_DHCP_HELPER_SERVER_METHOD_NOTIFY)) + g_return_if_reached (); if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(a{sv})"))) - return; + g_return_if_reached (); g_variant_get (parameters, "(@a{sv})", &options); iface = get_option (options, "interface"); if (iface == NULL) { - nm_log_warn (LOGD_DHCP, "dhcp-event: didn't have associated interface."); + _LOGW ("dhcp-event: didn't have associated interface."); goto out; } pid_str = get_option (options, "pid"); pid = _nm_utils_ascii_str_to_int64 (pid_str, 10, 0, G_MAXINT32, -1); if (pid == -1) { - nm_log_warn (LOGD_DHCP, "dhcp-event: couldn't convert PID '%s' to an integer", pid_str ? pid_str : "(null)"); + _LOGW ("dhcp-event: couldn't convert PID '%s' to an integer", pid_str ? pid_str : "(null)"); goto out; } reason = get_option (options, "reason"); if (reason == NULL) { - nm_log_warn (LOGD_DHCP, "dhcp-event: (pid %d) DHCP event didn't have a reason", pid); + _LOGW ("dhcp-event: (pid %d) DHCP event didn't have a reason", pid); goto out; } @@ -132,9 +168,9 @@ handle_event (GDBusConnection *connection, if (!handled) { if (g_ascii_strcasecmp (reason, "RELEASE") == 0) { /* Ignore event when the dhcp client gets killed and we receive its last message */ - nm_log_dbg (LOGD_DHCP, "dhcp-event: (pid %d) unhandled RELEASE DHCP event for interface %s", pid, iface); + _LOGD ("dhcp-event: (pid %d) unhandled RELEASE DHCP event for interface %s", pid, iface); } else - nm_log_warn (LOGD_DHCP, "dhcp-event: (pid %d) unhandled DHCP event for interface %s", pid, iface); + _LOGW ("dhcp-event: (pid %d) unhandled DHCP event for interface %s", pid, iface); } out: @@ -142,6 +178,57 @@ out: g_free (pid_str); g_free (reason); g_variant_unref (options); + g_dbus_method_invocation_return_value (invocation, NULL); +} + +static guint +_dbus_connection_register_object (NMDhcpListener *self, + GDBusConnection *connection, + GError **error) +{ + static GDBusArgInfo arg_info_notify_in = { + .ref_count = -1, + .name = "data", + .signature = "a{sv}", + .annotations = NULL, + }; + static GDBusArgInfo *arg_infos_notify[] = { + &arg_info_notify_in, + NULL, + }; + static GDBusMethodInfo method_info_notify = { + .ref_count = -1, + .name = NM_DHCP_HELPER_SERVER_METHOD_NOTIFY, + .in_args = arg_infos_notify, + .out_args = NULL, + .annotations = NULL, + }; + static GDBusMethodInfo *method_infos[] = { + &method_info_notify, + NULL, + }; + static GDBusInterfaceInfo interface_info = { + .ref_count = -1, + .name = NM_DHCP_HELPER_SERVER_INTERFACE_NAME, + .methods = method_infos, + .signals = NULL, + .properties = NULL, + .annotations = NULL, + }; + + static GDBusInterfaceVTable interface_vtable = { + .method_call = _method_call, + .get_property = NULL, + .set_property = NULL, + }; + + return g_dbus_connection_register_object (connection, + NM_DHCP_HELPER_SERVER_OBJECT_PATH, + &interface_info, + &interface_vtable, + self, + NULL, + error); } static void @@ -151,17 +238,20 @@ new_connection_cb (NMBusManager *mgr, NMDhcpListener *self) { NMDhcpListenerPrivate *priv = NM_DHCP_LISTENER_GET_PRIVATE (self); - guint id; + guint registration_id; + GError *error = NULL; + + /* it is important to register the object during the new-connection signal, + * as this avoids races with the connecting object. */ + registration_id = _dbus_connection_register_object (self, connection, &error); + if (!registration_id) { + _LOGE ("failure to register %s for connection %p: %s", + NM_DHCP_HELPER_SERVER_OBJECT_PATH, connection, error->message); + g_error_free (error); + return; + } - id = g_dbus_connection_signal_subscribe (connection, - NULL, - NM_DHCP_CLIENT_DBUS_IFACE, - "Event", - NULL, - NULL, - G_DBUS_SIGNAL_FLAGS_NONE, - handle_event, self, NULL); - g_hash_table_insert (priv->signal_handlers, connection, GUINT_TO_POINTER (id)); + g_hash_table_insert (priv->connections, connection, GUINT_TO_POINTER (registration_id)); } static void @@ -172,24 +262,22 @@ dis_connection_cb (NMBusManager *mgr, NMDhcpListenerPrivate *priv = NM_DHCP_LISTENER_GET_PRIVATE (self); guint id; - id = GPOINTER_TO_UINT (g_hash_table_lookup (priv->signal_handlers, connection)); + id = GPOINTER_TO_UINT (g_hash_table_lookup (priv->connections, connection)); if (id) { - g_dbus_connection_signal_unsubscribe (connection, id); - g_hash_table_remove (priv->signal_handlers, connection); + g_dbus_connection_unregister_object (connection, id); + g_hash_table_remove (priv->connections, connection); } } /***************************************************/ -NM_DEFINE_SINGLETON_GETTER (NMDhcpListener, nm_dhcp_listener_get, NM_TYPE_DHCP_LISTENER); - static void nm_dhcp_listener_init (NMDhcpListener *self) { NMDhcpListenerPrivate *priv = NM_DHCP_LISTENER_GET_PRIVATE (self); - /* Maps GDBusConnection :: GDBusProxy */ - priv->signal_handlers = g_hash_table_new (NULL, NULL); + /* Maps GDBusConnection :: signal-id */ + priv->connections = g_hash_table_new (NULL, NULL); priv->dbus_mgr = nm_bus_manager_get (); @@ -208,13 +296,13 @@ nm_dhcp_listener_init (NMDhcpListener *self) static void dispose (GObject *object) { - NMDhcpListenerPrivate *priv = NM_DHCP_LISTENER_GET_PRIVATE (object); + NMDhcpListenerPrivate *priv = NM_DHCP_LISTENER_GET_PRIVATE ((NMDhcpListener *) object); nm_clear_g_signal_handler (priv->dbus_mgr, &priv->new_conn_id); nm_clear_g_signal_handler (priv->dbus_mgr, &priv->dis_conn_id); priv->dbus_mgr = NULL; - g_clear_pointer (&priv->signal_handlers, g_hash_table_destroy); + g_clear_pointer (&priv->connections, g_hash_table_destroy); G_OBJECT_CLASS (nm_dhcp_listener_parent_class)->dispose (object); } @@ -224,22 +312,18 @@ nm_dhcp_listener_class_init (NMDhcpListenerClass *listener_class) { GObjectClass *object_class = G_OBJECT_CLASS (listener_class); - g_type_class_add_private (listener_class, sizeof (NMDhcpListenerPrivate)); - - /* virtual methods */ object_class->dispose = dispose; - /* signals */ signals[EVENT] = - g_signal_new (NM_DHCP_LISTENER_EVENT, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, 0, - g_signal_accumulator_true_handled, - NULL, NULL, - G_TYPE_BOOLEAN, /* listeners return TRUE if handled */ - 4, - G_TYPE_STRING, /* iface */ - G_TYPE_INT, /* pid */ - G_TYPE_VARIANT, /* options */ - G_TYPE_STRING); /* reason */ + g_signal_new (NM_DHCP_LISTENER_EVENT, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, 0, + g_signal_accumulator_true_handled, + NULL, NULL, + G_TYPE_BOOLEAN, /* listeners return TRUE if handled */ + 4, + G_TYPE_STRING, /* iface */ + G_TYPE_INT, /* pid */ + G_TYPE_VARIANT, /* options */ + G_TYPE_STRING); /* reason */ } diff --git a/src/dhcp-manager/nm-dhcp-listener.h b/src/dhcp-manager/nm-dhcp-listener.h index ff31fe34..3018b97a 100644 --- a/src/dhcp-manager/nm-dhcp-listener.h +++ b/src/dhcp-manager/nm-dhcp-listener.h @@ -26,8 +26,8 @@ #define NM_DHCP_LISTENER_EVENT "event" -typedef GObject NMDhcpListener; -typedef GObjectClass NMDhcpListenerClass; +typedef struct _NMDhcpListener NMDhcpListener; +typedef struct _NMDhcpListenerClass NMDhcpListenerClass; GType nm_dhcp_listener_get_type (void); diff --git a/src/dhcp-manager/tests/Makefile.in b/src/dhcp-manager/tests/Makefile.in index 1ce288ba..3f5f1466 100644 --- a/src/dhcp-manager/tests/Makefile.in +++ b/src/dhcp-manager/tests/Makefile.in @@ -95,7 +95,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_options.m4 \ - $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ diff --git a/src/dns-manager/nm-dns-manager.c b/src/dns-manager/nm-dns-manager.c index 3efd5ac1..ce8f4d93 100644 --- a/src/dns-manager/nm-dns-manager.c +++ b/src/dns-manager/nm-dns-manager.c @@ -151,18 +151,7 @@ G_DEFINE_TYPE (NMDnsManager, nm_dns_manager, G_TYPE_OBJECT) NM_DEFINE_SINGLETON_INSTANCE (NMDnsManager); -#define NM_DNS_MANAGER_GET_PRIVATE(self) \ - ({ \ - /* preserve the const-ness of self. Unfortunately, that - * way, @self cannot be a void pointer */ \ - typeof (self) _self = (self); \ - \ - /* Get compiler error if variable is of wrong type */ \ - _nm_unused const NMDnsManager *_self2 = (_self); \ - \ - nm_assert (NM_IS_DNS_MANAGER (_self)); \ - &_self->_priv; \ - }) +#define NM_DNS_MANAGER_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMDnsManager, NM_IS_DNS_MANAGER) /*****************************************************************************/ diff --git a/src/dnsmasq-manager/tests/Makefile.in b/src/dnsmasq-manager/tests/Makefile.in index 70f1ba1d..8ba82f87 100644 --- a/src/dnsmasq-manager/tests/Makefile.in +++ b/src/dnsmasq-manager/tests/Makefile.in @@ -95,7 +95,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_options.m4 \ - $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ diff --git a/src/nm-auth-subject.c b/src/nm-auth-subject.c index eb496b28..54d35959 100644 --- a/src/nm-auth-subject.c +++ b/src/nm-auth-subject.c @@ -68,18 +68,7 @@ struct _NMAuthSubjectClass { G_DEFINE_TYPE (NMAuthSubject, nm_auth_subject, G_TYPE_OBJECT) -#define NM_AUTH_SUBJECT_GET_PRIVATE(self) \ - ({ \ - /* preserve the const-ness of self. Unfortunately, that - * way, @self cannot be a void pointer */ \ - typeof (self) _self = (self); \ - \ - /* Get compiler error if variable is of wrong type */ \ - _nm_unused const NMAuthSubject *_self2 = (_self); \ - \ - nm_assert (NM_IS_AUTH_SUBJECT (_self)); \ - &_self->_priv; \ - }) +#define NM_AUTH_SUBJECT_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMAuthSubject, NM_IS_AUTH_SUBJECT) /**************************************************************/ diff --git a/src/nm-bus-manager.c b/src/nm-bus-manager.c index 449de4e6..270792ef 100644 --- a/src/nm-bus-manager.c +++ b/src/nm-bus-manager.c @@ -221,7 +221,11 @@ private_server_new_connection (GDBusServer *server, _LOGD ("(%s) accepted connection %p on private socket", s->tag, conn); - /* Emit this for the manager */ + /* Emit this for the manager. + * + * It is essential to do this from the "new-connection" signal handler, as + * at that point no messages from the connection are yet processed + * (which avoids races with registering objects). */ g_signal_emit (s->manager, signals[PRIVATE_CONNECTION_NEW], s->detail, diff --git a/src/nm-checkpoint.c b/src/nm-checkpoint.c index cb1adc39..605e0700 100644 --- a/src/nm-checkpoint.c +++ b/src/nm-checkpoint.c @@ -70,7 +70,7 @@ typedef struct { struct _NMCheckpoint { NMExportedObject parent; - NMCheckpointPrivate priv; + NMCheckpointPrivate _priv; }; typedef struct { @@ -79,18 +79,7 @@ typedef struct { G_DEFINE_TYPE (NMCheckpoint, nm_checkpoint, NM_TYPE_EXPORTED_OBJECT) -#define NM_CHECKPOINT_GET_PRIVATE(self) \ - ({ \ - /* preserve the const-ness of self. Unfortunately, that - * way, @self cannot be a void pointer */ \ - typeof (self) _self = (self); \ - \ - /* Get compiler error if variable is of wrong type */ \ - _nm_unused const NMCheckpoint *_self2 = (_self); \ - \ - nm_assert (NM_IS_CHECKPOINT (_self)); \ - &_self->priv; \ - }) +#define NM_CHECKPOINT_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMCheckpoint, NM_IS_CHECKPOINT) NM_GOBJECT_PROPERTIES_DEFINE_BASE ( PROP_DEVICES, diff --git a/src/nm-enum-types.c b/src/nm-enum-types.c index 670502cf..50a0cfd5 100644 --- a/src/nm-enum-types.c +++ b/src/nm-enum-types.c @@ -18,6 +18,7 @@ #include "nm-device-factory.h" #include "nm-device-generic.h" #include "nm-dhcp-client.h" +#include "nm-dhcp-helper-api.h" #include "nm-dhcp-utils.h" #include "nm-dhcp-listener.h" #include "nm-dhcp-manager.h" diff --git a/src/nm-exported-object.c b/src/nm-exported-object.c index c4dbab87..32b5ec05 100644 --- a/src/nm-exported-object.c +++ b/src/nm-exported-object.c @@ -27,6 +27,10 @@ #include "nm-bus-manager.h" +#include "nm-device.h" +#include "nm-active-connection.h" +#include "nmdbus-device-statistics.h" + #if NM_MORE_ASSERTS >= 2 #define _ASSERT_NO_EARLY_EXPORT #endif @@ -38,14 +42,13 @@ G_DEFINE_ABSTRACT_TYPE (NMExportedObject, nm_exported_object, G_TYPE_DBUS_OBJECT typedef struct { GDBusInterfaceSkeleton *interface; guint property_changed_signal_id; + GHashTable *pending_notifies; } InterfaceData; typedef struct { NMBusManager *bus_mgr; char *path; - GHashTable *pending_notifies; - InterfaceData *interfaces; guint num_interfaces; @@ -73,11 +76,20 @@ G_DEFINE_QUARK (NMExportedObjectClassInfo, nm_exported_object_class_info) #define _NMLOG_DOMAIN LOGD_CORE #define _NMLOG(level, ...) \ - nm_log (level, _NMLOG_DOMAIN, \ + nm_log ((level), _NMLOG_DOMAIN, \ "%s[%p]: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ _NMLOG_PREFIX_NAME, (self) \ _NM_UTILS_MACRO_REST (__VA_ARGS__)) +#define _NMLOG2_PREFIX_NAME "properties-changed" +#define _NMLOG2_DOMAIN LOGD_DBUS_PROPS + +#define _NMLOG2(level, ...) \ + nm_log ((level), _NMLOG2_DOMAIN, \ + "%s[%p]: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ + _NMLOG2_PREFIX_NAME, (self) \ + _NM_UTILS_MACRO_REST (__VA_ARGS__)) + /*****************************************************************************/ /* "AddConnectionUnsaved" -> "handle-add-connection-unsaved" */ @@ -492,9 +504,17 @@ nm_exported_object_create_skeletons (NMExportedObject *self, g_dbus_object_skeleton_add_interface ((GDBusObjectSkeleton *) self, ifdata->interface); ifdata->property_changed_signal_id = g_signal_lookup ("properties-changed", G_OBJECT_TYPE (ifdata->interface)); + + ifdata->pending_notifies = g_hash_table_new_full (g_direct_hash, + g_direct_equal, + NULL, + (GDestroyNotify) g_variant_unref); } nm_assert (i == 0); + /* The list of interfaces priv->interfaces is to be sorted from parent-class to derived-class. + * On the other hand, if one class defines multiple interfaces, the interfaces are sorted in + * the order of calls to nm_exported_object_class_add_interface(). */ if (priv->num_interfaces > 0) { memcpy (&interfaces[num_interfaces], priv->interfaces, sizeof (InterfaceData) * priv->num_interfaces); g_slice_free1 (sizeof (InterfaceData) * priv->num_interfaces, priv->interfaces); @@ -542,6 +562,7 @@ nm_exported_object_destroy_skeletons (NMExportedObject *self) g_dbus_object_skeleton_remove_interface ((GDBusObjectSkeleton *) self, ifdata->interface); nm_exported_object_skeleton_release (ifdata->interface); + g_hash_table_destroy (ifdata->pending_notifies); } g_slice_free1 (sizeof (InterfaceData) * n, priv->interfaces); @@ -701,11 +722,7 @@ nm_exported_object_unexport (NMExportedObject *self) g_clear_pointer (&priv->path, g_free); - if (nm_clear_g_source (&priv->notify_idle_id)) { - /* We had a notification queued. Since we removed all interfaces, - * the notification is obsolete and must be cleaned up. */ - g_hash_table_remove_all (priv->pending_notifies); - } + nm_clear_g_source (&priv->notify_idle_id); } /*****************************************************************************/ @@ -784,70 +801,82 @@ static gboolean idle_emit_properties_changed (gpointer self) { NMExportedObjectPrivate *priv = NM_EXPORTED_OBJECT_GET_PRIVATE (self); - gs_unref_variant GVariant *variant = NULL; - InterfaceData *ifdata = NULL; - GHashTableIter hash_iter; - GVariantBuilder notifies; - guint i, n; - PendingNotifiesItem *values; + guint k; priv->notify_idle_id = 0; + for (k = 0; k < priv->num_interfaces; k++) { + InterfaceData *ifdata = &priv->interfaces[k]; + gs_unref_variant GVariant *variant = NULL; + PendingNotifiesItem *values; + GVariantBuilder notifies; + GHashTableIter hash_iter; + guint i, n; - n = g_hash_table_size (priv->pending_notifies); - g_return_val_if_fail (n > 0, FALSE); + n = g_hash_table_size (ifdata->pending_notifies); + if (n == 0) + continue; - values = g_alloca (sizeof (values[0]) * n); + nm_assert (ifdata->property_changed_signal_id); - i = 0; - g_hash_table_iter_init (&hash_iter, priv->pending_notifies); - while (g_hash_table_iter_next (&hash_iter, (gpointer) &values[i].property_name, (gpointer) &values[i].variant)) - i++; - nm_assert (i == n); + /* We use here alloca in a loop, something that is usually avoided. + * But the number of interfaces "priv->num_interfaces" is small (determined by + * the depth of the type inheritance) and the number of possible pending_notifies + * "n" is small (determined by the number of GObject properties). */ + values = g_alloca (sizeof (values[0]) * n); - g_qsort_with_data (values, n, sizeof (values[0]), _sort_pending_notifies, NULL); + i = 0; + g_hash_table_iter_init (&hash_iter, ifdata->pending_notifies); + while (g_hash_table_iter_next (&hash_iter, (gpointer) &values[i].property_name, (gpointer) &values[i].variant)) + i++; + nm_assert (i == n); - g_variant_builder_init (¬ifies, G_VARIANT_TYPE_VARDICT); - for (i = 0; i < n; i++) - g_variant_builder_add (¬ifies, "{sv}", values[i].property_name, values[i].variant); - variant = g_variant_ref_sink (g_variant_builder_end (¬ifies)); + g_qsort_with_data (values, n, sizeof (values[0]), _sort_pending_notifies, NULL); - g_hash_table_remove_all (priv->pending_notifies); + g_variant_builder_init (¬ifies, G_VARIANT_TYPE_VARDICT); + for (i = 0; i < n; i++) + g_variant_builder_add (¬ifies, "{sv}", values[i].property_name, values[i].variant); + variant = g_variant_ref_sink (g_variant_builder_end (¬ifies)); - for (i = 0; i < priv->num_interfaces; i++) { - if (priv->interfaces[i].property_changed_signal_id != 0) { - ifdata = &priv->interfaces[i]; - break; + + if (_LOG2D_ENABLED ()) { + gs_free char *notification = g_variant_print (variant, TRUE); + + _LOG2D ("type %s, iface %s: %s", + G_OBJECT_TYPE_NAME (self), G_OBJECT_TYPE_NAME (ifdata->interface), + notification); } - } - g_return_val_if_fail (ifdata, FALSE); - if (nm_logging_enabled (LOGL_DEBUG, LOGD_DBUS_PROPS)) { - gs_free char *notification = g_variant_print (variant, TRUE); + g_signal_emit (ifdata->interface, ifdata->property_changed_signal_id, 0, variant); - nm_log_dbg (LOGD_DBUS_PROPS, "PropertiesChanged %s %p: %s", - G_OBJECT_TYPE_NAME (self), self, notification); + g_hash_table_remove_all (ifdata->pending_notifies); } - g_signal_emit (ifdata->interface, ifdata->property_changed_signal_id, 0, variant); - return FALSE; + return G_SOURCE_REMOVE; } static void nm_exported_object_notify (GObject *object, GParamSpec *pspec) { - NMExportedObjectPrivate *priv = NM_EXPORTED_OBJECT_GET_PRIVATE (object); + NMExportedObject *self = (NMExportedObject *) object; + NMExportedObjectPrivate *priv = NM_EXPORTED_OBJECT_GET_PRIVATE (self); NMExportedObjectClassInfo *classinfo; GType type; const char *dbus_property_name = NULL; GValue value = G_VALUE_INIT; + GVariant *value_variant; + InterfaceData *ifdata = NULL; const GVariantType *vtype; guint i, j; + /* Hook to emit deprecated "PropertiesChanged" signal on NetworkManager interfaces. + * This is to preserve deprecated D-Bus API, nowadays we use instead + * the "PropertiesChanged" signal of "org.freedesktop.DBus.Properties". */ + if (priv->num_interfaces == 0) return; - for (type = G_OBJECT_TYPE (object); type; type = g_type_parent (type)) { + for (type = G_OBJECT_TYPE (self); type; type = g_type_parent (type)) { classinfo = g_type_get_qdata (type, nm_exported_object_class_info_quark ()); if (!classinfo) continue; @@ -857,16 +886,16 @@ nm_exported_object_notify (GObject *object, GParamSpec *pspec) break; } if (!dbus_property_name) { - nm_log_trace (LOGD_DBUS_PROPS, "ignoring notification for prop %s on type %s", - pspec->name, G_OBJECT_TYPE_NAME (object)); + _LOG2T ("ignoring notification for prop %s on type %s", + pspec->name, G_OBJECT_TYPE_NAME (self)); return; } for (i = 0; i < priv->num_interfaces; i++) { - GDBusInterfaceSkeleton *skel = priv->interfaces[i].interface; GDBusInterfaceInfo *iinfo; - iinfo = g_dbus_interface_skeleton_get_info (skel); + ifdata = &priv->interfaces[i]; + iinfo = g_dbus_interface_skeleton_get_info (ifdata->interface); for (j = 0; iinfo->properties[j]; j++) { if (nm_streq (iinfo->properties[j]->name, dbus_property_name)) { vtype = G_VARIANT_TYPE (iinfo->properties[j]->signature); @@ -878,17 +907,61 @@ nm_exported_object_notify (GObject *object, GParamSpec *pspec) vtype_found: g_value_init (&value, pspec->value_type); - g_object_get_property (G_OBJECT (object), pspec->name, &value); - - /* @dbus_property_name is inside classinfo and never freed, thus we don't clone it. - * Also, we do a pointer, not string comparison. */ - g_hash_table_insert (priv->pending_notifies, - (gpointer) dbus_property_name, - g_dbus_gvalue_to_gvariant (&value, vtype)); + g_object_get_property ((GObject *) self, pspec->name, &value); + value_variant = g_dbus_gvalue_to_gvariant (&value, vtype); g_value_unset (&value); + if ( ( NM_IS_DEVICE (self) + && !NMDBUS_IS_DEVICE_STATISTICS_SKELETON (ifdata->interface)) + || NM_IS_ACTIVE_CONNECTION (self)) { + /* This PropertiesChanged signal is nodaways deprecated in favor + * of "org.freedesktop.DBus.Properties"'s PropertiesChanged signal. + * This function solely exists to raise the NM version of PropertiesChanged. + * + * With types exported on D-Bus that are implemented as derived + * types in glib (NMDevice and NMActiveConnection), multiple types + * in the inheritance tree define a "PropertiesChanged" signal. + * + * In 1.0.0 and earlier, the signal was emitted once for every interface + * that had a "PropertiesChanged" signal. For example: + * - NMDeviceEthernet.HwAddress was emitted on "fdo.NM.Device.Ethernet" + * and "fdo.NM.Device.Veth" (if the device was of type NMDeviceVeth). + * - NMVpnConnection.VpnState was emitted on "fdo.NM.Connecion.Active" + * and "fdo.NM.VPN.Connection". + * + * NMDevice is special in that it didn't have a "PropertiesChanged" signal. + * Thus, a change to "NMDevice.StateReason" would be emitted on "fdo.NM.Device.Ethernet" + * and also on "fdo.NM.Device.Veth" (in case of a device of type NMDeviceVeth). + * + * The releases of 1.2.0 and 1.4.0 failed to realize above and broke this behavior. + * This special handling here is to bring back the 1.0.0 behavior. + * + * The Device.Statistics signal is special, because it was only added with 1.4.0 + * and didn't have above behavior. So let's save the overhead of emitting multiple + * deprecated signals for wrong interfaces. */ + for (i = 0, j = 0; i < priv->num_interfaces; i++) { + ifdata = &priv->interfaces[i]; + if ( ifdata->property_changed_signal_id + && !NMDBUS_IS_DEVICE_STATISTICS_SKELETON (ifdata->interface)) { + j++; + g_hash_table_insert (ifdata->pending_notifies, + (gpointer) dbus_property_name, + g_variant_ref (value_variant)); + } + } + nm_assert (j > 0); + g_variant_unref (value_variant); + } else if (ifdata->property_changed_signal_id) { + /* @dbus_property_name is inside classinfo and never freed, thus we don't clone it. + * Also, we do a pointer, not string comparison. */ + g_hash_table_insert (ifdata->pending_notifies, + (gpointer) dbus_property_name, + value_variant); + } else + nm_assert_not_reached (); + if (!priv->notify_idle_id) - priv->notify_idle_id = g_idle_add (idle_emit_properties_changed, object); + priv->notify_idle_id = g_idle_add (idle_emit_properties_changed, self); } /*****************************************************************************/ @@ -896,12 +969,6 @@ vtype_found: static void nm_exported_object_init (NMExportedObject *self) { - NMExportedObjectPrivate *priv = NM_EXPORTED_OBJECT_GET_PRIVATE (self); - - priv->pending_notifies = g_hash_table_new_full (g_direct_hash, - g_direct_equal, - NULL, - (GDestroyNotify) g_variant_unref); } static void @@ -937,7 +1004,6 @@ nm_exported_object_dispose (GObject *object) } else g_clear_pointer (&priv->path, g_free); - g_clear_pointer (&priv->pending_notifies, g_hash_table_destroy); nm_clear_g_source (&priv->notify_idle_id); G_OBJECT_CLASS (nm_exported_object_parent_class)->dispose (object); diff --git a/src/nm-iface-helper.c b/src/nm-iface-helper.c index 49672cf5..de035f1a 100644 --- a/src/nm-iface-helper.c +++ b/src/nm-iface-helper.c @@ -534,6 +534,8 @@ gboolean nm_config_get_configure_and_quit (gpointer unused); gconstpointer nm_bus_manager_get (void); void nm_bus_manager_register_object (gpointer unused, gpointer object); void nm_bus_manager_unregister_object (gpointer unused, gpointer object); +GType nm_device_get_type (void); +GType nm_active_connection_get_type (void); gconstpointer nm_config_get (void) @@ -569,3 +571,15 @@ nm_bus_manager_unregister_object (gpointer unused, gpointer object) { } +GType +nm_device_get_type (void) +{ + g_return_val_if_reached (0); +} + +GType +nm_active_connection_get_type (void) +{ + g_return_val_if_reached (0); +} + diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index 22d1d077..a4d43612 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -68,18 +68,7 @@ struct _NMIP4ConfigClass { G_DEFINE_TYPE (NMIP4Config, nm_ip4_config, NM_TYPE_EXPORTED_OBJECT) -#define NM_IP4_CONFIG_GET_PRIVATE(self) \ - ({ \ - /* preserve the const-ness of self. Unfortunately, that - * way, @self cannot be a void pointer */ \ - typeof (self) _self = (self); \ - \ - /* Get compiler error if variable is of wrong type */ \ - _nm_unused const NMIP4Config *_self2 = (_self); \ - \ - nm_assert (NM_IS_IP4_CONFIG (_self)); \ - &_self->_priv; \ - }) +#define NM_IP4_CONFIG_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMIP4Config, NM_IS_IP4_CONFIG) /* internal guint32 are assigned to gobject properties of type uint. Ensure, that uint is large enough */ G_STATIC_ASSERT (sizeof (uint) >= sizeof (guint32)); diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c index ac9e6cd1..8002d61a 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -61,18 +61,7 @@ struct _NMIP6ConfigClass { G_DEFINE_TYPE (NMIP6Config, nm_ip6_config, NM_TYPE_EXPORTED_OBJECT) -#define NM_IP6_CONFIG_GET_PRIVATE(self) \ - ({ \ - /* preserve the const-ness of self. Unfortunately, that - * way, @self cannot be a void pointer */ \ - typeof (self) _self = (self); \ - \ - /* Get compiler error if variable is of wrong type */ \ - _nm_unused const NMIP6Config *_self2 = (_self); \ - \ - nm_assert (NM_IS_IP6_CONFIG (_self)); \ - &_self->_priv; \ - }) +#define NM_IP6_CONFIG_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMIP6Config, NM_IS_IP6_CONFIG) NM_GOBJECT_PROPERTIES_DEFINE (NMIP6Config, PROP_IFINDEX, diff --git a/src/nm-logging.c b/src/nm-logging.c index 3db8d20c..6ecc1606 100644 --- a/src/nm-logging.c +++ b/src/nm-logging.c @@ -512,7 +512,7 @@ _nm_log_impl (const char *file, va_end (args); g_get_current_time (&tv); - nm_sprintf_buf (s_buf_timestamp, " [%ld.%04ld]", tv.tv_sec, (tv.tv_usec + 50) / 100); + nm_sprintf_buf (s_buf_timestamp, " [%ld.%04ld]", tv.tv_sec, tv.tv_usec / 100); switch (global.log_backend) { #if SYSTEMD_JOURNAL diff --git a/src/nm-manager.c b/src/nm-manager.c index 5794bb9a..836ab768 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -158,21 +158,10 @@ typedef struct { NMExportedObjectClass parent; } NMManagerClass; -#define NM_MANAGER_GET_PRIVATE(self) \ - ({ \ - /* preserve the const-ness of self. Unfortunately, that - * way, @self cannot be a void pointer */ \ - typeof (self) _self = (self); \ - \ - /* Get compiler error if variable is of wrong type */ \ - _nm_unused const NMManager *_self2 = (_self); \ - \ - nm_assert (NM_IS_MANAGER (_self)); \ - &_self->_priv; \ - }) - G_DEFINE_TYPE (NMManager, nm_manager, NM_TYPE_EXPORTED_OBJECT) +#define NM_MANAGER_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMManager, NM_IS_MANAGER) + enum { DEVICE_ADDED, INTERNAL_DEVICE_ADDED, @@ -1879,8 +1868,10 @@ device_realized (NMDevice *device, GParamSpec *pspec, NMManager *self) { + gboolean real = nm_device_is_real (device); + /* Emit D-Bus signals */ - g_signal_emit (self, signals[DEVICE_ADDED], 0, device); + g_signal_emit (self, signals[real ? DEVICE_ADDED : DEVICE_REMOVED], 0, device); _notify (self, PROP_DEVICES); } @@ -6056,7 +6047,8 @@ nm_manager_class_init (NMManagerClass *manager_class) NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_OBJECT); - /* D-Bus exported; emitted only for realized devices */ + /* D-Bus exported; emitted only for realized devices when a device + * becomes unrealized or removed */ signals[DEVICE_REMOVED] = g_signal_new (NM_MANAGER_DEVICE_REMOVED, G_OBJECT_CLASS_TYPE (object_class), diff --git a/src/platform/Makefile.in b/src/platform/Makefile.in index bf094348..be78d19f 100644 --- a/src/platform/Makefile.in +++ b/src/platform/Makefile.in @@ -92,7 +92,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_options.m4 \ - $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 98c4e461..070a83ea 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -4060,21 +4060,17 @@ out: return !!nmp_cache_lookup_obj (priv->cache, obj_id); } -static NMPlatformError -do_change_link (NMPlatform *platform, - int ifindex, - struct nl_msg *nlmsg) +static WaitForNlResponseResult +do_change_link_request (NMPlatform *platform, + int ifindex, + struct nl_msg *nlmsg) { nm_auto_pop_netns NMPNetns *netns = NULL; WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; int nle; - char s_buf[256]; - NMPlatformError result = NM_PLATFORM_ERROR_SUCCESS; - NMLogLevel log_level = LOGL_DEBUG; - const char *log_result = "failure", *log_detail = ""; if (!nm_platform_netns_push (platform, &netns)) - return NM_PLATFORM_ERROR_UNSPECIFIED; + return WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; retry: nle = _nl_send_auto_with_seq (platform, nlmsg, &seq_result, NULL); @@ -4082,7 +4078,7 @@ retry: _LOGE ("do-change-link[%d]: failure sending netlink request \"%s\" (%d)", ifindex, nl_geterror (nle), -nle); - return NM_PLATFORM_ERROR_UNSPECIFIED; + return WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; } /* always refetch the link after changing it. There seems to be issues @@ -4098,6 +4094,18 @@ retry: nlmsg_hdr (nlmsg)->nlmsg_type = RTM_SETLINK; goto retry; } + return seq_result; +} + +static NMPlatformError +do_change_link_result (NMPlatform *platform, + int ifindex, + WaitForNlResponseResult seq_result) +{ + char s_buf[256]; + NMPlatformError result = NM_PLATFORM_ERROR_SUCCESS; + NMLogLevel log_level = LOGL_DEBUG; + const char *log_result = "failure", *log_detail = ""; if (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK) { log_result = "success"; @@ -4123,6 +4131,17 @@ retry: return result; } +static NMPlatformError +do_change_link (NMPlatform *platform, + int ifindex, + struct nl_msg *nlmsg) +{ + WaitForNlResponseResult seq_result; + + seq_result = do_change_link_request (platform, ifindex, nlmsg); + return do_change_link_result (platform, ifindex, seq_result); +} + static gboolean link_add (NMPlatform *platform, const char *name, @@ -4430,6 +4449,8 @@ link_set_address (NMPlatform *platform, int ifindex, gconstpointer address, size { nm_auto_nlmsg struct nl_msg *nlmsg = NULL; gs_free char *mac = NULL; + WaitForNlResponseResult seq_result; + char s_buf[256]; if (!address || !length) g_return_val_if_reached (NM_PLATFORM_ERROR_BUG); @@ -4449,7 +4470,30 @@ link_set_address (NMPlatform *platform, int ifindex, gconstpointer address, size NLA_PUT (nlmsg, IFLA_ADDRESS, length, address); - return do_change_link (platform, ifindex, nlmsg); + seq_result = do_change_link_request (platform, ifindex, nlmsg); + + if (NM_IN_SET (-((int) seq_result), ENFILE)) { + const NMPObject *obj_cache; + + /* workaround ENFILE which may be wrongly returned (bgo #770456). + * If the MAC address is as expected, assume success? */ + + obj_cache = nmp_cache_lookup_link (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, ifindex); + if ( obj_cache + && obj_cache->link.addr.len == length + && memcmp (obj_cache->link.addr.data, address, length) == 0) { + _NMLOG (LOGL_DEBUG, + "do-change-link[%d]: %s changing link: %s%s", + ifindex, + "success", + wait_for_nl_response_to_string (seq_result, s_buf, sizeof (s_buf)), + " (assume success changing address)"); + return NM_PLATFORM_ERROR_SUCCESS; + } + } + + return do_change_link_result (platform, ifindex, seq_result); + nla_put_failure: g_return_val_if_reached (NM_PLATFORM_ERROR_UNSPECIFIED); } diff --git a/src/platform/tests/Makefile.in b/src/platform/tests/Makefile.in index 4922a3dc..3f452b0f 100644 --- a/src/platform/tests/Makefile.in +++ b/src/platform/tests/Makefile.in @@ -105,7 +105,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_options.m4 \ - $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c index 99873620..e242a71f 100644 --- a/src/platform/tests/test-link.c +++ b/src/platform/tests/test-link.c @@ -297,9 +297,9 @@ test_slave (int master, int type, SignalData *master_changed) switch (type) { case NM_LINK_TYPE_BRIDGE: if (nmtstp_is_sysfs_writable ()) { - g_assert (nm_platform_sysctl_slave_set_option (NM_PLATFORM_GET, ifindex, "priority", "789")); + g_assert (nm_platform_sysctl_slave_set_option (NM_PLATFORM_GET, ifindex, "priority", "614")); value = nm_platform_sysctl_slave_get_option (NM_PLATFORM_GET, ifindex, "priority"); - g_assert_cmpstr (value, ==, "789"); + g_assert_cmpstr (value, ==, "614"); g_free (value); } break; @@ -398,9 +398,9 @@ test_software (NMLinkType link_type, const char *link_typename) switch (link_type) { case NM_LINK_TYPE_BRIDGE: if (nmtstp_is_sysfs_writable ()) { - g_assert (nm_platform_sysctl_master_set_option (NM_PLATFORM_GET, ifindex, "forward_delay", "789")); + g_assert (nm_platform_sysctl_master_set_option (NM_PLATFORM_GET, ifindex, "forward_delay", "628")); value = nm_platform_sysctl_master_get_option (NM_PLATFORM_GET, ifindex, "forward_delay"); - g_assert_cmpstr (value, ==, "789"); + g_assert_cmpstr (value, ==, "628"); g_free (value); } break; diff --git a/src/ppp-manager/Makefile.in b/src/ppp-manager/Makefile.in index b8215aab..656bdd6c 100644 --- a/src/ppp-manager/Makefile.in +++ b/src/ppp-manager/Makefile.in @@ -93,7 +93,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_options.m4 \ - $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ diff --git a/src/rdisc/Makefile.in b/src/rdisc/Makefile.in index 68fed001..719ce8a2 100644 --- a/src/rdisc/Makefile.in +++ b/src/rdisc/Makefile.in @@ -92,7 +92,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_options.m4 \ - $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ diff --git a/src/rdisc/nm-lndp-rdisc.c b/src/rdisc/nm-lndp-rdisc.c index 12c2e30d..db2965b1 100644 --- a/src/rdisc/nm-lndp-rdisc.c +++ b/src/rdisc/nm-lndp-rdisc.c @@ -60,18 +60,7 @@ struct _NMLndpRDiscClass { G_DEFINE_TYPE (NMLndpRDisc, nm_lndp_rdisc, NM_TYPE_RDISC) -#define NM_LNDP_RDISC_GET_PRIVATE(self) \ - ({ \ - /* preserve the const-ness of self. Unfortunately, that - * way, @self cannot be a void pointer */ \ - typeof (self) _self = (self); \ - \ - /* Get compiler error if variable is of wrong type */ \ - _nm_unused const NMLndpRDisc *_self2 = (_self); \ - \ - nm_assert (NM_IS_LNDP_RDISC (_self)); \ - &_self->_priv; \ - }) +#define NM_LNDP_RDISC_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMLndpRDisc, NM_IS_LNDP_RDISC) /*****************************************************************************/ diff --git a/src/rdisc/nm-rdisc.c b/src/rdisc/nm-rdisc.c index cf993bc3..3bc69750 100644 --- a/src/rdisc/nm-rdisc.c +++ b/src/rdisc/nm-rdisc.c @@ -87,18 +87,7 @@ static guint signals[LAST_SIGNAL] = { 0 }; G_DEFINE_TYPE (NMRDisc, nm_rdisc, G_TYPE_OBJECT) -#define NM_RDISC_GET_PRIVATE(self) \ - ({ \ - /* preserve the const-ness of self. Unfortunately, that - * way, @self cannot be a void pointer */ \ - typeof (self) _self = (self); \ - \ - /* Get compiler error if variable is of wrong type */ \ - _nm_unused const NMRDisc *_self2 = (_self); \ - \ - nm_assert (NM_IS_RDISC (_self)); \ - _self->_priv; \ - }) +#define NM_RDISC_GET_PRIVATE(self) _NM_GET_PRIVATE_PTR(self, NMRDisc, NM_IS_RDISC) /*****************************************************************************/ diff --git a/src/rdisc/tests/Makefile.in b/src/rdisc/tests/Makefile.in index f160600e..3cbc48a0 100644 --- a/src/rdisc/tests/Makefile.in +++ b/src/rdisc/tests/Makefile.in @@ -95,7 +95,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_options.m4 \ - $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ diff --git a/src/settings/plugins/Makefile.in b/src/settings/plugins/Makefile.in index ba388a5f..dfe5a45f 100644 --- a/src/settings/plugins/Makefile.in +++ b/src/settings/plugins/Makefile.in @@ -96,7 +96,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_options.m4 \ - $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ diff --git a/src/settings/plugins/ibft/Makefile.in b/src/settings/plugins/ibft/Makefile.in index 9da764de..ea6a3a63 100644 --- a/src/settings/plugins/ibft/Makefile.in +++ b/src/settings/plugins/ibft/Makefile.in @@ -93,7 +93,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_options.m4 \ - $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ diff --git a/src/settings/plugins/ibft/tests/Makefile.in b/src/settings/plugins/ibft/tests/Makefile.in index f0c681ab..4de64380 100644 --- a/src/settings/plugins/ibft/tests/Makefile.in +++ b/src/settings/plugins/ibft/tests/Makefile.in @@ -95,7 +95,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_options.m4 \ - $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ diff --git a/src/settings/plugins/ifcfg-rh/Makefile.in b/src/settings/plugins/ifcfg-rh/Makefile.in index 3cd841c3..200289e5 100644 --- a/src/settings/plugins/ifcfg-rh/Makefile.in +++ b/src/settings/plugins/ifcfg-rh/Makefile.in @@ -94,7 +94,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_options.m4 \ - $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ diff --git a/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c b/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c index 82f20598..184e95b2 100644 --- a/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c +++ b/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c @@ -395,7 +395,9 @@ commit_changes (NMSettingsConnection *connection, */ filename = nm_settings_connection_get_filename (connection); if (filename) { - reread = connection_from_file (filename, NULL, NULL, NULL); + gs_free char *unhandled = NULL; + + reread = connection_from_file (filename, &unhandled, NULL, NULL); if (reread) { same = nm_connection_compare (NM_CONNECTION (connection), reread, diff --git a/src/settings/plugins/ifcfg-rh/reader.c b/src/settings/plugins/ifcfg-rh/reader.c index af5d2910..5a351cfa 100644 --- a/src/settings/plugins/ifcfg-rh/reader.c +++ b/src/settings/plugins/ifcfg-rh/reader.c @@ -1621,26 +1621,29 @@ check_if_bond_slave (shvarFile *ifcfg, */ } -static void +static gboolean check_if_team_slave (shvarFile *ifcfg, NMSettingConnection *s_con) { - char *value; + gs_free char *value = NULL; - value = svGetValue (ifcfg, "DEVICETYPE", FALSE); - if (!value) - return; - if (strcasecmp (value, TYPE_TEAM_PORT)) { - g_free (value); - return; - } - g_free (value); value = svGetValue (ifcfg, "TEAM_MASTER", FALSE); if (!value) - return; + return FALSE; g_object_set (s_con, NM_SETTING_CONNECTION_MASTER, value, NULL); g_object_set (s_con, NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_TEAM_SETTING_NAME, NULL); - g_free (value); + return TRUE; +} + +static void +check_if_slave (shvarFile *ifcfg, + NMSettingConnection *s_con) +{ + g_return_if_fail (NM_IS_SETTING_CONNECTION (s_con)); + + if (check_if_team_slave (ifcfg, s_con)) + return; + check_if_bond_slave (ifcfg, s_con); } typedef struct { @@ -3157,14 +3160,6 @@ make_wpa_setting (shvarFile *ifcfg, if (allow_rsn && svGetValueBoolean (ifcfg, "WPA_ALLOW_WPA2", TRUE)) nm_setting_wireless_security_add_proto (wsec, "rsn"); - /* If neither WPA_ALLOW_WPA or WPA_ALLOW_WPA2 were present, default - * to both WPA and RSN allowed. - */ - if (!allow_wpa && !allow_rsn && !ieee8021x) { - nm_setting_wireless_security_add_proto (wsec, "wpa"); - nm_setting_wireless_security_add_proto (wsec, "rsn"); - } - g_free (allow_wpa); g_free (allow_rsn); } @@ -3211,6 +3206,12 @@ make_wpa_setting (shvarFile *ifcfg, } g_free (value); + + value = svGetValue (ifcfg, "SECURITYMODE", FALSE); + if (NM_IN_STRSET (value, NULL, "open")) + g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, value, NULL); + + g_free (value); return (NMSetting *) wsec; error: @@ -3948,8 +3949,7 @@ wired_connection_from_ifcfg (const char *file, g_object_unref (connection); return NULL; } - check_if_bond_slave (ifcfg, NM_SETTING_CONNECTION (con_setting)); - check_if_team_slave (ifcfg, NM_SETTING_CONNECTION (con_setting)); + check_if_slave (ifcfg, (NMSettingConnection *) con_setting); nm_connection_add_setting (connection, con_setting); wired_setting = make_wired_setting (ifcfg, file, &s_8021x, error); @@ -4099,8 +4099,7 @@ infiniband_connection_from_ifcfg (const char *file, g_object_unref (connection); return NULL; } - check_if_bond_slave (ifcfg, NM_SETTING_CONNECTION (con_setting)); - check_if_team_slave (ifcfg, NM_SETTING_CONNECTION (con_setting)); + check_if_slave (ifcfg, (NMSettingConnection *) con_setting); nm_connection_add_setting (connection, con_setting); infiniband_setting = make_infiniband_setting (ifcfg, file, error); @@ -4237,6 +4236,7 @@ bond_connection_from_ifcfg (const char *file, static char * read_team_config (shvarFile *ifcfg, const char *key, GError **error) { + gs_free_error GError *local_error = NULL; char *value; size_t l; @@ -4257,6 +4257,12 @@ read_team_config (shvarFile *ifcfg, const char *key, GError **error) return NULL; } svUnescape (value); + + if (value && value[0] && !_nm_utils_check_valid_json (value, &local_error)) { + PARSE_WARNING ("ignoring invalid team configuration: %s", local_error->message); + g_clear_pointer (&value, g_free); + } + return value; } @@ -4599,8 +4605,6 @@ is_bond_device (const char *name, shvarFile *parsed) if (svGetValueBoolean (parsed, "BONDING_MASTER", FALSE)) return TRUE; - - /* XXX: Check for "bond[\d]+"? */ return FALSE; } @@ -4816,8 +4820,7 @@ vlan_connection_from_ifcfg (const char *file, g_object_unref (connection); return NULL; } - check_if_bond_slave (ifcfg, NM_SETTING_CONNECTION (con_setting)); - check_if_team_slave (ifcfg, NM_SETTING_CONNECTION (con_setting)); + check_if_slave (ifcfg, (NMSettingConnection *) con_setting); nm_connection_add_setting (connection, con_setting); vlan_setting = make_vlan_setting (ifcfg, file, error); @@ -4848,7 +4851,7 @@ create_unhandled_connection (const char *filename, shvarFile *ifcfg, NMSetting *s_con; char *value; - g_assert (out_spec != NULL); + nm_assert (out_spec && !*out_spec); connection = nm_simple_connection_new (); @@ -4963,8 +4966,7 @@ connection_from_file_full (const char *filename, const char *ifcfg_name = NULL; g_return_val_if_fail (filename != NULL, NULL); - if (out_unhandled) - g_return_val_if_fail (*out_unhandled == NULL, NULL); + g_return_val_if_fail (out_unhandled && !*out_unhandled, NULL); /* Non-NULL only for unit tests; normally use /etc/sysconfig/network */ if (!network_file) @@ -4982,8 +4984,6 @@ connection_from_file_full (const char *filename, return NULL; if (!svGetValueBoolean (parsed, "NM_CONTROLLED", TRUE)) { - g_assert (out_unhandled != NULL); - connection = create_unhandled_connection (filename, parsed, "unmanaged", out_unhandled); if (!connection) g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, @@ -5011,6 +5011,16 @@ connection_from_file_full (const char *filename, type = g_strdup (TYPE_ETHERNET); g_free (devtype); } + if (!type) { + gs_free char *t = NULL; + + /* Team and TeamPort types are also accepted by the mere + * presense of TEAM_CONFIG/TEAM_MASTER. They don't require + * DEVICETYPE. */ + t = svGetValue (parsed, "TEAM_CONFIG", FALSE); + if (t) + type = g_strdup (TYPE_TEAM); + } if (!type) type = svGetValue (parsed, "TYPE", FALSE); @@ -5136,8 +5146,6 @@ connection_from_file_full (const char *filename, else if (!strcasecmp (type, TYPE_BRIDGE)) connection = bridge_connection_from_ifcfg (filename, parsed, error); else { - g_assert (out_unhandled != NULL); - connection = create_unhandled_connection (filename, parsed, "unrecognized", out_unhandled); if (!connection) PARSE_WARNING ("connection type was unrecognized but device was not uniquely identified; device may be managed"); diff --git a/src/settings/plugins/ifcfg-rh/tests/Makefile.in b/src/settings/plugins/ifcfg-rh/tests/Makefile.in index ac21e19b..f2ce157b 100644 --- a/src/settings/plugins/ifcfg-rh/tests/Makefile.in +++ b/src/settings/plugins/ifcfg-rh/tests/Makefile.in @@ -97,7 +97,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_options.m4 \ - $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am index fc759e6d..de9c1ed7 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am @@ -132,8 +132,11 @@ EXTRA_DIST = \ ifcfg-test-dcb-pgpct-not-100 \ ifcfg-test-fcoe-fabric \ ifcfg-test-fcoe-vn2vn \ - ifcfg-test-team-master \ - ifcfg-test-team-port \ + ifcfg-test-team-master-1 \ + ifcfg-test-team-master-2 \ + ifcfg-test-team-master-invalid \ + ifcfg-test-team-port-1 \ + ifcfg-test-team-port-2 \ ifcfg-test-team-port-empty-config \ ifcfg-test-vlan-trailing-spaces \ ifcfg-test-dns-options \ diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in index 30cc7c05..583f0809 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in @@ -92,7 +92,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_options.m4 \ - $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ @@ -537,8 +537,11 @@ EXTRA_DIST = \ ifcfg-test-dcb-pgpct-not-100 \ ifcfg-test-fcoe-fabric \ ifcfg-test-fcoe-vn2vn \ - ifcfg-test-team-master \ - ifcfg-test-team-port \ + ifcfg-test-team-master-1 \ + ifcfg-test-team-master-2 \ + ifcfg-test-team-master-invalid \ + ifcfg-test-team-port-1 \ + ifcfg-test-team-port-2 \ ifcfg-test-team-port-empty-config \ ifcfg-test-vlan-trailing-spaces \ ifcfg-test-dns-options \ diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-1 index 7edc736a..7edc736a 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-1 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-2 b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-2 new file mode 100644 index 00000000..d01e37c5 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-2 @@ -0,0 +1,5 @@ +DEVICE=team0 +ONBOOT=no +BOOTPROTO=dhcp +TEAM_CONFIG="{ \"device\": \"team0\", \"link_watch\": { \"name\": \"ethtool\" } }" + diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-invalid b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-invalid new file mode 100644 index 00000000..4534882e --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-invalid @@ -0,0 +1,4 @@ +DEVICE=team0 +ONBOOT=no +BOOTPROTO=dhcp +TEAM_CONFIG="{ foobar }" diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-1 index 966bec67..966bec67 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-1 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-2 b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-2 new file mode 100644 index 00000000..992510ee --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-2 @@ -0,0 +1,4 @@ +TYPE=Ethernet +TEAM_PORT_CONFIG="{ \"p4p1\": { \"prio\": -10, \"sticky\": true } }" +DEVICE=p4p1 +TEAM_MASTER=team0 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 60938f6e..9ed48beb 100644 --- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -67,11 +67,14 @@ _connection_from_file (const char *filename, { NMConnection *connection; GError *error = NULL; + char *unhandled_fallback = NULL; g_assert (!out_unhandled || !*out_unhandled); - connection = connection_from_file_test (filename, network_file, test_type, out_unhandled, &error); + connection = connection_from_file_test (filename, network_file, test_type, + out_unhandled ?: &unhandled_fallback, &error); g_assert_no_error (error); + g_assert (!unhandled_fallback); if (out_unhandled && *out_unhandled) nmtst_assert_connection_verifies (connection); @@ -89,13 +92,12 @@ _connection_from_file_fail (const char *filename, NMConnection *connection; GError *local = NULL; char *unhandled = NULL; - char **p_unhandled = (nmtst_get_rand_int () % 2) ? &unhandled : NULL; - connection = connection_from_file_test (filename, network_file, test_type, p_unhandled, &local); + connection = connection_from_file_test (filename, network_file, test_type, &unhandled, &local); g_assert (!connection); g_assert (local); - g_assert (!p_unhandled || !*p_unhandled); + g_assert (!unhandled); g_propagate_error (error, local); } @@ -107,11 +109,14 @@ _writer_new_connection (NMConnection *connection, gboolean success; GError *error = NULL; char *filename = NULL; + gs_unref_object NMConnection *con_verified = NULL; g_assert (NM_IS_CONNECTION (connection)); g_assert (ifcfg_dir); - success = writer_new_connection (connection, + con_verified = nmtst_connection_duplicate_and_normalize (connection); + + success = writer_new_connection (con_verified, ifcfg_dir, &filename, &error); @@ -8425,15 +8430,15 @@ test_write_fcoe_mode (gconstpointer user_data) } static void -test_read_team_master (void) +test_read_team_master (gconstpointer user_data) { + const char *const PATH_NAME = user_data; NMConnection *connection; NMSettingConnection *s_con; NMSettingTeam *s_team; const char *expected_config = "{ \"device\": \"team0\", \"link_watch\": { \"name\": \"ethtool\" } }"; - connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-team-master", - NULL, TYPE_ETHERNET, NULL); + connection = _connection_from_file (PATH_NAME, NULL, TYPE_ETHERNET, NULL); g_assert_cmpstr (nm_connection_get_interface_name (connection), ==, "team0"); @@ -8449,6 +8454,31 @@ test_read_team_master (void) } static void +test_read_team_master_invalid (gconstpointer user_data) +{ + const char *const PATH_NAME = user_data; + NMConnection *connection; + NMSettingConnection *s_con; + NMSettingTeam *s_team; + + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*ignoring invalid team configuration*"); + connection = _connection_from_file (PATH_NAME, NULL, TYPE_ETHERNET, NULL); + g_test_assert_expected_messages (); + + g_assert_cmpstr (nm_connection_get_interface_name (connection), ==, "team0"); + + s_con = nm_connection_get_setting_connection (connection); + g_assert (s_con); + g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_TEAM_SETTING_NAME); + + s_team = nm_connection_get_setting_team (connection); + g_assert (s_team); + g_assert (nm_setting_team_get_config (s_team) == NULL); + + g_object_unref (connection); +} + +static void test_write_team_master (void) { NMConnection *connection, *reread; @@ -8541,15 +8571,15 @@ test_write_team_master (void) } static void -test_read_team_port (void) +test_read_team_port (gconstpointer user_data) { + const char *const PATH_NAME = user_data; NMConnection *connection; NMSettingConnection *s_con; NMSettingTeamPort *s_team_port; const char *expected_config = "{ \"p4p1\": { \"prio\": -10, \"sticky\": true } }"; - connection = _connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-team-port", - NULL, TYPE_ETHERNET, NULL); + connection = _connection_from_file (PATH_NAME, NULL, TYPE_ETHERNET, NULL); s_con = nm_connection_get_setting_connection (connection); g_assert (s_con); @@ -9043,9 +9073,12 @@ int main (int argc, char **argv) g_test_add_func (TPATH "bridge/write-component", test_write_bridge_component); g_test_add_func (TPATH "bridge/read-missing-stp", test_read_bridge_missing_stp); - g_test_add_func (TPATH "team/read-master", test_read_team_master); + g_test_add_data_func (TPATH "team/read-master-1", TEST_IFCFG_DIR"/network-scripts/ifcfg-test-team-master-1", test_read_team_master); + g_test_add_data_func (TPATH "team/read-master-2", TEST_IFCFG_DIR"/network-scripts/ifcfg-test-team-master-2", test_read_team_master); + g_test_add_data_func (TPATH "team/read-master-invalid", TEST_IFCFG_DIR"/network-scripts/ifcfg-test-team-master-invalid", test_read_team_master_invalid); g_test_add_func (TPATH "team/write-master", test_write_team_master); - g_test_add_func (TPATH "team/read-port", test_read_team_port); + g_test_add_data_func (TPATH "team/read-port-1", TEST_IFCFG_DIR"/network-scripts/ifcfg-test-team-port-1", test_read_team_port); + g_test_add_data_func (TPATH "team/read-port-2", TEST_IFCFG_DIR"/network-scripts/ifcfg-test-team-port-2", test_read_team_port); g_test_add_func (TPATH "team/write-port", test_write_team_port); g_test_add_func (TPATH "team/read-port-empty-config", test_read_team_port_empty_config); diff --git a/src/settings/plugins/ifcfg-rh/utils.c b/src/settings/plugins/ifcfg-rh/utils.c index b602a7d7..b9d52b7f 100644 --- a/src/settings/plugins/ifcfg-rh/utils.c +++ b/src/settings/plugins/ifcfg-rh/utils.c @@ -382,25 +382,6 @@ utils_has_complex_routes (const char *filename) return FALSE; } -gboolean -utils_ignore_ip_config (NMConnection *connection) -{ - NMSettingConnection *s_con; - - s_con = nm_connection_get_setting_connection (connection); - g_assert (s_con); - - /* bonding slaves have no IP configuration, and the system - * scripts just ignore it if it's there. - */ - if ( nm_setting_connection_is_slave_type (s_con, NM_SETTING_BOND_SETTING_NAME) - || nm_setting_connection_is_slave_type (s_con, NM_SETTING_BRIDGE_SETTING_NAME) - || nm_setting_connection_is_slave_type (s_con, NM_SETTING_TEAM_SETTING_NAME)) - return TRUE; - - return FALSE; -} - /* Find out if the 'alias' file name might be an alias file for 'ifcfg' file name, * or any alias when 'ifcfg' is NULL. Does not check that it's actually a valid * alias name; that happens in reader.c diff --git a/src/settings/plugins/ifcfg-rh/utils.h b/src/settings/plugins/ifcfg-rh/utils.h index b8b172e7..c105487a 100644 --- a/src/settings/plugins/ifcfg-rh/utils.h +++ b/src/settings/plugins/ifcfg-rh/utils.h @@ -54,8 +54,6 @@ shvarFile *utils_get_route6_ifcfg (const char *parent, gboolean should_create); gboolean utils_has_route_file_new_syntax (const char *filename); gboolean utils_has_complex_routes (const char *filename); -gboolean utils_ignore_ip_config (NMConnection *connection); - gboolean utils_is_ifcfg_alias_file (const char *alias, const char *ifcfg); char *utils_detect_ifcfg_path (const char *path, gboolean only_ifcfg); diff --git a/src/settings/plugins/ifcfg-rh/writer.c b/src/settings/plugins/ifcfg-rh/writer.c index 4817549e..dcc48f2a 100644 --- a/src/settings/plugins/ifcfg-rh/writer.c +++ b/src/settings/plugins/ifcfg-rh/writer.c @@ -2010,13 +2010,29 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) gint priority; int timeout; GString *searches; - gboolean success = FALSE; - gboolean fake_ip4 = FALSE; const char *method = NULL; s_ip4 = nm_connection_get_setting_ip4_config (connection); - if (s_ip4) - method = nm_setting_ip_config_get_method (s_ip4); + if (!s_ip4) { + /* slave-type: clear IPv4 settings. + * + * Some IPv4 setting related options are not cleared, + * for no strong reason. */ + svSetValue (ifcfg, "BOOTPROTO", NULL, FALSE); + + svSetValue (ifcfg, "IPADDR", NULL, FALSE); + svSetValue (ifcfg, "PREFIX", NULL, FALSE); + svSetValue (ifcfg, "NETMASK", NULL, FALSE); + svSetValue (ifcfg, "GATEWAY", NULL, FALSE); + + svSetValue (ifcfg, "IPADDR0", NULL, FALSE); + svSetValue (ifcfg, "PREFIX0", NULL, FALSE); + svSetValue (ifcfg, "NETMASK0", NULL, FALSE); + svSetValue (ifcfg, "GATEWAY0", NULL, FALSE); + return TRUE; + } + + method = nm_setting_ip_config_get_method (s_ip4); /* Missing IP4 setting is assumed to be DHCP */ if (!method) @@ -2057,12 +2073,6 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) return TRUE; } - /* Temporarily create fake IP4 setting if missing; method set to DHCP above */ - if (!s_ip4) { - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new (); - fake_ip4 = TRUE; - } - if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) svSetValue (ifcfg, "BOOTPROTO", "dhcp", FALSE); else if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) @@ -2237,7 +2247,7 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) if (!route_path) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, "Could not get route file path for '%s'", ifcfg->fileName); - goto out; + return FALSE; } if (utils_has_route_file_new_syntax (route_path)) { @@ -2248,7 +2258,7 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, "Could not create route file '%s'", route_path); g_free (route_path); - goto out; + return FALSE; } g_free (route_path); @@ -2299,14 +2309,14 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) } if (!svWriteFile (routefile, 0644, error)) { svCloseFile (routefile); - goto out; + return FALSE; } svCloseFile (routefile); } else { write_route_file_legacy (route_path, s_ip4, error); g_free (route_path); if (error && *error) - goto out; + return FALSE; } timeout = nm_setting_ip_config_get_dad_timeout (s_ip4); @@ -2325,13 +2335,7 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) else svSetValue (ifcfg, "IPV4_DNS_PRIORITY", NULL, FALSE); - success = TRUE; - -out: - if (fake_ip4) - g_object_unref (s_ip4); - - return success; + return TRUE; } static void @@ -2371,12 +2375,11 @@ write_ip4_aliases (NMConnection *connection, char *base_ifcfg_path) g_dir_close (dir); } - if (utils_ignore_ip_config (connection)) - return; - s_ip4 = nm_connection_get_setting_ip4_config (connection); - if (!s_ip4) + if (!s_ip4) { + /* slave-type: no alias files */ return; + } num = nm_setting_ip_config_get_num_addresses (s_ip4); for (i = 0; i < num; i++) { @@ -2495,16 +2498,19 @@ write_ip6_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) s_ip6 = nm_connection_get_setting_ip6_config (connection); if (!s_ip6) { - /* Treat missing IPv6 setting as a setting with method "auto" */ - svSetValue (ifcfg, "IPV6INIT", "yes", FALSE); - svSetValue (ifcfg, "IPV6_AUTOCONF", "yes", FALSE); + /* slave-type: clear IPv6 settings + * + * Some IPv6 setting related options are not cleared, + * for no strong reason. */ + svSetValue (ifcfg, "IPV6INIT", NULL, FALSE); + svSetValue (ifcfg, "IPV6_AUTOCONF", NULL, FALSE); svSetValue (ifcfg, "DHCPV6C", NULL, FALSE); - svSetValue (ifcfg, "IPV6_DEFROUTE", "yes", FALSE); - svSetValue (ifcfg, "IPV6_PEERDNS", "yes", FALSE); - svSetValue (ifcfg, "IPV6_PEERROUTES", "yes", FALSE); - svSetValue (ifcfg, "IPV6_FAILURE_FATAL", "no", FALSE); + svSetValue (ifcfg, "IPV6_DEFROUTE", NULL, FALSE); + svSetValue (ifcfg, "IPV6_PEERDNS", NULL, FALSE); + svSetValue (ifcfg, "IPV6_PEERROUTES", NULL, FALSE); + svSetValue (ifcfg, "IPV6_FAILURE_FATAL", NULL, FALSE); svSetValue (ifcfg, "IPV6_ROUTE_METRIC", NULL, FALSE); - svSetValue (ifcfg, "IPV6_ADDR_GEN_MODE", "stable-privacy", FALSE); + svSetValue (ifcfg, "IPV6_ADDR_GEN_MODE", NULL, FALSE); return TRUE; } @@ -2695,34 +2701,37 @@ write_res_options (NMConnection *connection, shvarFile *ifcfg, GError **error) NMSettingIPConfig *s_ip4; const char *method; int i, num_options; - GPtrArray *array; + gs_unref_ptrarray GPtrArray *array = NULL; GString *value; s_ip4 = nm_connection_get_setting_ip4_config (connection); - s_ip6 = nm_connection_get_setting_ip6_config (connection); + + if (!s_ip4) { + /* slave-type: clear res-options */ + svSetValue (ifcfg, "RES_OPTIONS", NULL, FALSE); + return TRUE; + } + array = g_ptr_array_new (); - if (s_ip4) { - method = nm_setting_ip_config_get_method (s_ip4); - if (g_strcmp0 (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) { - num_options = nm_setting_ip_config_get_num_dns_options (s_ip4); - for (i = 0; i < num_options; i++) - add_dns_option (array, nm_setting_ip_config_get_dns_option (s_ip4, i)); - } + method = nm_setting_ip_config_get_method (s_ip4); + if (g_strcmp0 (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) { + num_options = nm_setting_ip_config_get_num_dns_options (s_ip4); + for (i = 0; i < num_options; i++) + add_dns_option (array, nm_setting_ip_config_get_dns_option (s_ip4, i)); } - if (s_ip6) { - method = nm_setting_ip_config_get_method (s_ip6); - if (g_strcmp0 (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE)) { - num_options = nm_setting_ip_config_get_num_dns_options (s_ip6); - for (i = 0; i < num_options; i++) - add_dns_option (array, nm_setting_ip_config_get_dns_option (s_ip6, i)); - } + s_ip6 = nm_connection_get_setting_ip6_config (connection); + method = nm_setting_ip_config_get_method (s_ip6); + if (g_strcmp0 (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE)) { + num_options = nm_setting_ip_config_get_num_dns_options (s_ip6); + for (i = 0; i < num_options; i++) + add_dns_option (array, nm_setting_ip_config_get_dns_option (s_ip6, i)); } - if (array->len > 0 - || (s_ip4 && nm_setting_ip_config_has_dns_options (s_ip4)) - || (s_ip6 && nm_setting_ip_config_has_dns_options (s_ip6))) { + if ( array->len > 0 + || nm_setting_ip_config_has_dns_options (s_ip4) + || nm_setting_ip_config_has_dns_options (s_ip6)) { value = g_string_new (NULL); for (i = 0; i < array->len; i++) { if (i > 0) @@ -2734,7 +2743,6 @@ write_res_options (NMConnection *connection, shvarFile *ifcfg, GError **error) } else svSetValue (ifcfg, "RES_OPTIONS", NULL, FALSE); - g_ptr_array_unref (array); return TRUE; } @@ -2772,6 +2780,9 @@ write_connection (NMConnection *connection, gboolean no_8021x = FALSE; gboolean wired = FALSE; + nm_assert (NM_IS_CONNECTION (connection)); + nm_assert (nm_connection_verify (connection, NULL)); + if (!writer_can_write_connection (connection, error)) return FALSE; @@ -2876,20 +2887,18 @@ write_connection (NMConnection *connection, if (!write_dcb_setting (connection, ifcfg, error)) goto out; - if (!utils_ignore_ip_config (connection)) { - svSetValue (ifcfg, "DHCP_HOSTNAME", NULL, FALSE); - svSetValue (ifcfg, "DHCP_FQDN", NULL, FALSE); + svSetValue (ifcfg, "DHCP_HOSTNAME", NULL, FALSE); + svSetValue (ifcfg, "DHCP_FQDN", NULL, FALSE); - if (!write_ip4_setting (connection, ifcfg, error)) - goto out; - write_ip4_aliases (connection, ifcfg_name); + if (!write_ip4_setting (connection, ifcfg, error)) + goto out; + write_ip4_aliases (connection, ifcfg_name); - if (!write_ip6_setting (connection, ifcfg, error)) - goto out; + if (!write_ip6_setting (connection, ifcfg, error)) + goto out; - if (!write_res_options (connection, ifcfg, error)) - goto out; - } + if (!write_res_options (connection, ifcfg, error)) + goto out; write_connection_setting (s_con, ifcfg); diff --git a/src/settings/plugins/ifnet/Makefile.in b/src/settings/plugins/ifnet/Makefile.in index 44295ada..a3b12364 100644 --- a/src/settings/plugins/ifnet/Makefile.in +++ b/src/settings/plugins/ifnet/Makefile.in @@ -93,7 +93,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_options.m4 \ - $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ diff --git a/src/settings/plugins/ifnet/tests/Makefile.in b/src/settings/plugins/ifnet/tests/Makefile.in index 0aee0582..18f3c20c 100644 --- a/src/settings/plugins/ifnet/tests/Makefile.in +++ b/src/settings/plugins/ifnet/tests/Makefile.in @@ -95,7 +95,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_options.m4 \ - $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ diff --git a/src/settings/plugins/ifupdown/Makefile.in b/src/settings/plugins/ifupdown/Makefile.in index 4e1c657b..385a55d9 100644 --- a/src/settings/plugins/ifupdown/Makefile.in +++ b/src/settings/plugins/ifupdown/Makefile.in @@ -93,7 +93,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_options.m4 \ - $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ diff --git a/src/settings/plugins/ifupdown/interface_parser.c b/src/settings/plugins/ifupdown/interface_parser.c index 7ad902d4..764ba5c9 100644 --- a/src/settings/plugins/ifupdown/interface_parser.c +++ b/src/settings/plugins/ifupdown/interface_parser.c @@ -100,7 +100,7 @@ static char *join_values_with_spaces(char *dst, char **src) return(dst); } -static void _ifparser_source (const char *path, const char *en_dir, int quiet); +static void _ifparser_source (const char *path, const char *en_dir, int quiet, int dir); static void _recursive_ifparser (const char *eni_file, int quiet) @@ -189,9 +189,9 @@ _recursive_ifparser (const char *eni_file, int quiet) continue; } - /* There are five different stanzas: - * iface, mapping, auto, allow-* and source. - * Create a block for each of them except source. */ + /* There are six different stanzas: + * iface, mapping, auto, allow-*, source, and source-directory. + * Create a block for each of them except source and source-directory. */ /* iface stanza takes at least 3 parameters */ if (strcmp(token[0], "iface") == 0) { @@ -226,22 +226,28 @@ _recursive_ifparser (const char *eni_file, int quiet) add_block(token[0], token[i]); skip_to_block = 0; } - /* source stanza takes one or more filepaths as parameters */ - else if (strcmp(token[0], "source") == 0) { + /* source and source-directory stanzas take one or more paths as parameters */ + else if (strcmp (token[0], "source") == 0 || strcmp (token[0], "source-directory") == 0) { int i; char *en_dir; skip_to_block = 0; if (toknum == 1) { - if (!quiet) - nm_log_warn (LOGD_SETTINGS, "Invalid source line without parameters\n"); + if (!quiet) { + nm_log_warn (LOGD_SETTINGS, "Invalid %s line without parameters\n", + token[0]); + } continue; } en_dir = g_path_get_dirname (eni_file); - for (i = 1; i < toknum; ++i) - _ifparser_source (token[i], en_dir, quiet); + for (i = 1; i < toknum; ++i) { + if (strcmp (token[0], "source-directory") == 0) + _ifparser_source (token[i], en_dir, quiet, TRUE); + else + _ifparser_source (token[i], en_dir, quiet, FALSE); + } g_free (en_dir); } else { @@ -261,10 +267,13 @@ _recursive_ifparser (const char *eni_file, int quiet) } static void -_ifparser_source (const char *path, const char *en_dir, int quiet) +_ifparser_source (const char *path, const char *en_dir, int quiet, int dir) { char *abs_path; + const char *item; wordexp_t we; + GDir *source_dir; + GError *error = NULL; uint i; if (g_path_is_absolute (path)) @@ -280,8 +289,23 @@ _ifparser_source (const char *path, const char *en_dir, int quiet) if (!quiet) nm_log_warn (LOGD_SETTINGS, "word expansion for %s failed\n", abs_path); } else { - for (i = 0; i < we.we_wordc; i++) - _recursive_ifparser (we.we_wordv[i], quiet); + for (i = 0; i < we.we_wordc; i++) { + if (dir) { + source_dir = g_dir_open (we.we_wordv[i], 0, &error); + if (!source_dir) { + if (!quiet) { + nm_log_warn (LOGD_SETTINGS, "Failed to open directory %s: %s", + we.we_wordv[i], error->message); + } + g_clear_error (&error); + } else { + while ((item = g_dir_read_name (source_dir))) + _ifparser_source (item, we.we_wordv[i], quiet, FALSE); + g_dir_close (source_dir); + } + } else + _recursive_ifparser (we.we_wordv[i], quiet); + } wordfree (&we); } g_free (abs_path); diff --git a/src/settings/plugins/ifupdown/tests/Makefile.am b/src/settings/plugins/ifupdown/tests/Makefile.am index 1287a716..3d702375 100644 --- a/src/settings/plugins/ifupdown/tests/Makefile.am +++ b/src/settings/plugins/ifupdown/tests/Makefile.am @@ -35,4 +35,5 @@ EXTRA_DIST = \ test1 test2 test3 test4 test5 test6 test7 test8 test9 test11 test12 \ test13 test14 test15 test16 test17-wired-static-verify-ip4 \ test18-wired-static-verify-ip6 test19-wired-static-verify-ip4-plen \ - test20-source-stanza test20-source-stanza.eth0 test20-source-stanza.eth1 + test20-source-stanza test20-source-stanza.eth0 test20-source-stanza.eth1 \ + test21-source-dir-stanza test21-source-dir-stanza.d diff --git a/src/settings/plugins/ifupdown/tests/Makefile.in b/src/settings/plugins/ifupdown/tests/Makefile.in index b63f9a89..b3be79e1 100644 --- a/src/settings/plugins/ifupdown/tests/Makefile.in +++ b/src/settings/plugins/ifupdown/tests/Makefile.in @@ -95,7 +95,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_options.m4 \ - $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ @@ -688,7 +688,8 @@ EXTRA_DIST = \ test1 test2 test3 test4 test5 test6 test7 test8 test9 test11 test12 \ test13 test14 test15 test16 test17-wired-static-verify-ip4 \ test18-wired-static-verify-ip6 test19-wired-static-verify-ip4-plen \ - test20-source-stanza test20-source-stanza.eth0 test20-source-stanza.eth1 + test20-source-stanza test20-source-stanza.eth0 test20-source-stanza.eth1 \ + test21-source-dir-stanza test21-source-dir-stanza.d all: all-am diff --git a/src/settings/plugins/ifupdown/tests/test-ifupdown.c b/src/settings/plugins/ifupdown/tests/test-ifupdown.c index 7ce08aee..11b42c71 100644 --- a/src/settings/plugins/ifupdown/tests/test-ifupdown.c +++ b/src/settings/plugins/ifupdown/tests/test-ifupdown.c @@ -627,6 +627,27 @@ test20_source_stanza (const char *path) expected_free (e); } +static void +test21_source_dir_stanza (const char *path) +{ + Expected *e; + ExpectedBlock *b; + + e = expected_new (); + + b = expected_block_new ("auto", "eth0"); + expected_add_block (e, b); + b = expected_block_new ("iface", "eth0"); + expected_add_block (e, b); + expected_block_add_key (b, expected_key_new ("inet", "dhcp")); + + init_ifparser_with_file (path, "test21-source-dir-stanza"); + compare_expected_to_ifparser (e); + + ifparser_destroy (); + expected_free (e); +} + NMTST_DEFINE (); int @@ -675,6 +696,8 @@ main (int argc, char **argv) (GTestDataFunc) test19_read_static_ipv4_plen); g_test_add_data_func ("/ifupdate/source_stanza", TEST_ENI_DIR, (GTestDataFunc) test20_source_stanza); + g_test_add_data_func ("/ifupdate/source_dir_stanza", TEST_ENI_DIR, + (GTestDataFunc) test21_source_dir_stanza); return g_test_run (); } diff --git a/src/settings/plugins/ifupdown/tests/test21-source-dir-stanza b/src/settings/plugins/ifupdown/tests/test21-source-dir-stanza new file mode 100644 index 00000000..d0604ddc --- /dev/null +++ b/src/settings/plugins/ifupdown/tests/test21-source-dir-stanza @@ -0,0 +1 @@ +source-directory test21-source-dir-stanza.d diff --git a/src/settings/plugins/ifupdown/tests/test21-source-dir-stanza.d/test21-source-dir-stanza.eth0 b/src/settings/plugins/ifupdown/tests/test21-source-dir-stanza.d/test21-source-dir-stanza.eth0 new file mode 100644 index 00000000..81922cea --- /dev/null +++ b/src/settings/plugins/ifupdown/tests/test21-source-dir-stanza.d/test21-source-dir-stanza.eth0 @@ -0,0 +1,2 @@ +auto eth0 +iface eth0 inet dhcp diff --git a/src/settings/plugins/keyfile/Makefile.in b/src/settings/plugins/keyfile/Makefile.in index e6f4b4cf..085dfdd5 100644 --- a/src/settings/plugins/keyfile/Makefile.in +++ b/src/settings/plugins/keyfile/Makefile.in @@ -93,7 +93,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_options.m4 \ - $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ diff --git a/src/settings/plugins/keyfile/tests/Makefile.in b/src/settings/plugins/keyfile/tests/Makefile.in index e2e56d4e..ffa882b2 100644 --- a/src/settings/plugins/keyfile/tests/Makefile.in +++ b/src/settings/plugins/keyfile/tests/Makefile.in @@ -95,7 +95,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_options.m4 \ - $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Makefile.in b/src/settings/plugins/keyfile/tests/keyfiles/Makefile.in index 88e03515..cac6dcd0 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Makefile.in +++ b/src/settings/plugins/keyfile/tests/keyfiles/Makefile.in @@ -92,7 +92,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_options.m4 \ - $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ diff --git a/src/supplicant-manager/tests/Makefile.in b/src/supplicant-manager/tests/Makefile.in index bb5efff7..eb6b03ea 100644 --- a/src/supplicant-manager/tests/Makefile.in +++ b/src/supplicant-manager/tests/Makefile.in @@ -95,7 +95,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_options.m4 \ - $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ diff --git a/src/supplicant-manager/tests/certs/Makefile.in b/src/supplicant-manager/tests/certs/Makefile.in index a1be6bcb..3d348a38 100644 --- a/src/supplicant-manager/tests/certs/Makefile.in +++ b/src/supplicant-manager/tests/certs/Makefile.in @@ -92,7 +92,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_options.m4 \ - $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in index a4ca2212..a115170e 100644 --- a/src/tests/Makefile.in +++ b/src/tests/Makefile.in @@ -105,7 +105,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_options.m4 \ - $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ diff --git a/src/tests/config/Makefile.in b/src/tests/config/Makefile.in index 89c18941..738788cf 100644 --- a/src/tests/config/Makefile.in +++ b/src/tests/config/Makefile.in @@ -95,7 +95,7 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_options.m4 \ - $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/git-sha-record.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ diff --git a/src/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c index 92c5bd8f..69b45dcc 100644 --- a/src/vpn-manager/nm-vpn-connection.c +++ b/src/vpn-manager/nm-vpn-connection.c @@ -168,18 +168,7 @@ struct _NMVpnConnectionClass { G_DEFINE_TYPE (NMVpnConnection, nm_vpn_connection, NM_TYPE_ACTIVE_CONNECTION) -#define NM_VPN_CONNECTION_GET_PRIVATE(self) \ - ({ \ - /* preserve the const-ness of self. Unfortunately, that - * way, @self cannot be a void pointer */ \ - typeof (self) _self = (self); \ - \ - /* Get compiler error if variable is of wrong type */ \ - _nm_unused const NMVpnConnection *_self2 = (_self); \ - \ - nm_assert (NM_IS_VPN_CONNECTION (_self)); \ - &_self->_priv; \ - }) +#define NM_VPN_CONNECTION_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMVpnConnection, NM_IS_VPN_CONNECTION) /*****************************************************************************/ |