diff options
Diffstat (limited to 'src')
102 files changed, 3189 insertions, 2018 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index aa35eefb..48af5a06 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -305,8 +305,6 @@ libNetworkManager_la_SOURCES = \ dns-manager/nm-dns-manager.h \ dns-manager/nm-dns-plugin.c \ dns-manager/nm-dns-plugin.h \ - dns-manager/nm-dns-utils.c \ - dns-manager/nm-dns-utils.h \ \ dnsmasq-manager/nm-dnsmasq-manager.c \ dnsmasq-manager/nm-dnsmasq-manager.h \ @@ -438,6 +436,7 @@ libNetworkManager_la_SOURCES = \ nm-rfkill-manager.h \ nm-session-monitor.h \ nm-session-monitor.c \ + nm-sleep-monitor.c \ nm-sleep-monitor.h \ nm-types.h \ nm-core-utils.c \ @@ -446,13 +445,6 @@ libNetworkManager_la_SOURCES = \ NetworkManagerUtils.h -if SUSPEND_RESUME_UPOWER -libNetworkManager_la_SOURCES += nm-sleep-monitor-upower.c -else -# systemd/consolekit suspend/resume used whenever upower is not enabled -libNetworkManager_la_SOURCES += nm-sleep-monitor-systemd.c -endif - if WITH_WEXT libNetworkManager_la_SOURCES += \ platform/wifi/wifi-utils-wext.c \ diff --git a/src/Makefile.in b/src/Makefile.in index 51ded6bc..1047880d 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -110,15 +110,12 @@ host_triplet = @host@ @ENABLE_TESTS_TRUE@ libNetworkManager-base.la sbin_PROGRAMS = NetworkManager$(EXEEXT) -@SUSPEND_RESUME_UPOWER_TRUE@am__append_6 = nm-sleep-monitor-upower.c -# systemd/consolekit suspend/resume used whenever upower is not enabled -@SUSPEND_RESUME_UPOWER_FALSE@am__append_7 = nm-sleep-monitor-systemd.c -@WITH_WEXT_TRUE@am__append_8 = \ +@WITH_WEXT_TRUE@am__append_6 = \ @WITH_WEXT_TRUE@ platform/wifi/wifi-utils-wext.c \ @WITH_WEXT_TRUE@ platform/wifi/wifi-utils-wext.h -@WITH_LIBSOUP_TRUE@am__append_9 = $(LIBSOUP_LIBS) -@WITH_WEXT_TRUE@am__append_10 = \ +@WITH_LIBSOUP_TRUE@am__append_7 = $(LIBSOUP_LIBS) +@WITH_WEXT_TRUE@am__append_8 = \ @WITH_WEXT_TRUE@ platform/wifi/wifi-utils-wext.c \ @WITH_WEXT_TRUE@ platform/wifi/wifi-utils-wext.h @@ -197,8 +194,7 @@ am__libNetworkManager_la_SOURCES_DIST = devices/nm-device-bond.h \ dns-manager/nm-dns-dnsmasq.h dns-manager/nm-dns-unbound.c \ dns-manager/nm-dns-unbound.h dns-manager/nm-dns-manager.c \ dns-manager/nm-dns-manager.h dns-manager/nm-dns-plugin.c \ - dns-manager/nm-dns-plugin.h dns-manager/nm-dns-utils.c \ - dns-manager/nm-dns-utils.h \ + dns-manager/nm-dns-plugin.h \ dnsmasq-manager/nm-dnsmasq-manager.c \ dnsmasq-manager/nm-dnsmasq-manager.h \ dnsmasq-manager/nm-dnsmasq-utils.c \ @@ -262,26 +258,21 @@ am__libNetworkManager_la_SOURCES_DIST = devices/nm-device-bond.h \ nm-auth-subject.h nm-auth-utils.c nm-auth-utils.h nm-manager.c \ nm-manager.h nm-multi-index.c nm-multi-index.h nm-policy.c \ nm-policy.h nm-rfkill-manager.c nm-rfkill-manager.h \ - nm-session-monitor.h nm-session-monitor.c nm-sleep-monitor.h \ - nm-types.h nm-core-utils.c nm-core-utils.h \ + nm-session-monitor.h nm-session-monitor.c nm-sleep-monitor.c \ + nm-sleep-monitor.h nm-types.h nm-core-utils.c nm-core-utils.h \ NetworkManagerUtils.c NetworkManagerUtils.h \ - nm-sleep-monitor-upower.c nm-sleep-monitor-systemd.c \ platform/wifi/wifi-utils-wext.c \ platform/wifi/wifi-utils-wext.h am__objects_1 = -@SUSPEND_RESUME_UPOWER_TRUE@am__objects_2 = \ -@SUSPEND_RESUME_UPOWER_TRUE@ nm-sleep-monitor-upower.lo -@SUSPEND_RESUME_UPOWER_FALSE@am__objects_3 = \ -@SUSPEND_RESUME_UPOWER_FALSE@ nm-sleep-monitor-systemd.lo -@WITH_WEXT_TRUE@am__objects_4 = wifi-utils-wext.lo +@WITH_WEXT_TRUE@am__objects_2 = wifi-utils-wext.lo am_libNetworkManager_la_OBJECTS = $(am__objects_1) $(am__objects_1) \ nm-device.lo nm-lldp-listener.lo nm-arping-manager.lo \ nm-device-ethernet-utils.lo nm-device-factory.lo \ nm-device-generic.lo nm-dhcp-client.lo nm-dhcp-utils.lo \ nm-dhcp-listener.lo nm-dhcp-manager.lo nm-dns-dnsmasq.lo \ nm-dns-unbound.lo nm-dns-manager.lo nm-dns-plugin.lo \ - nm-dns-utils.lo nm-dnsmasq-manager.lo nm-dnsmasq-utils.lo \ - nmp-netns.lo nmp-object.lo nm-platform-utils.lo nm-platform.lo \ + nm-dnsmasq-manager.lo nm-dnsmasq-utils.lo nmp-netns.lo \ + nmp-object.lo nm-platform-utils.lo nm-platform.lo \ nm-linux-platform.lo nm-fake-platform.lo wifi-utils-nl80211.lo \ wifi-utils.lo nm-fake-rdisc.lo nm-lndp-rdisc.lo nm-rdisc.lo \ nm-ppp-manager.lo nm-agent-manager.lo nm-inotify-helper.lo \ @@ -300,8 +291,8 @@ am_libNetworkManager_la_OBJECTS = $(am__objects_1) $(am__objects_1) \ nm-ip6-config.lo nm-logging.lo nm-auth-manager.lo \ nm-auth-subject.lo nm-auth-utils.lo nm-manager.lo \ nm-multi-index.lo nm-policy.lo nm-rfkill-manager.lo \ - nm-session-monitor.lo nm-core-utils.lo NetworkManagerUtils.lo \ - $(am__objects_2) $(am__objects_3) $(am__objects_4) + nm-session-monitor.lo nm-sleep-monitor.lo nm-core-utils.lo \ + NetworkManagerUtils.lo $(am__objects_2) libNetworkManager_la_OBJECTS = $(am_libNetworkManager_la_OBJECTS) libnm_iface_helper_la_DEPENDENCIES = \ $(top_builddir)/libnm-core/libnm-core.la \ @@ -340,7 +331,7 @@ am_libnm_iface_helper_la_OBJECTS = nm-dhcp-client.lo nm-dhcp-utils.lo \ nm-lndp-rdisc.lo nm-rdisc.lo nm-route-manager.lo \ nm-exported-object.lo nm-ip4-config.lo nm-ip6-config.lo \ nm-enum-types.lo nm-logging.lo nm-multi-index.lo \ - nm-core-utils.lo NetworkManagerUtils.lo $(am__objects_4) + nm-core-utils.lo NetworkManagerUtils.lo $(am__objects_2) libnm_iface_helper_la_OBJECTS = $(am_libnm_iface_helper_la_OBJECTS) libsystemd_nm_la_DEPENDENCIES = $(am__DEPENDENCIES_1) am_libsystemd_nm_la_OBJECTS = libsystemd_nm_la-nm-sd.lo \ @@ -379,16 +370,16 @@ libsystemd_nm_la_OBJECTS = $(am_libsystemd_nm_la_OBJECTS) am__installdirs = "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(sbindir)" \ "$(DESTDIR)$(dbusservicedir)" PROGRAMS = $(libexec_PROGRAMS) $(sbin_PROGRAMS) -am__objects_5 = nm-device-bond.$(OBJEXT) nm-device-bridge.$(OBJEXT) \ +am__objects_3 = nm-device-bond.$(OBJEXT) nm-device-bridge.$(OBJEXT) \ nm-device-ethernet.$(OBJEXT) nm-device-infiniband.$(OBJEXT) \ nm-device-ip-tunnel.$(OBJEXT) nm-device-macvlan.$(OBJEXT) \ nm-device-tun.$(OBJEXT) nm-device-veth.$(OBJEXT) \ nm-device-vlan.$(OBJEXT) nm-device-vxlan.$(OBJEXT) -am__objects_6 = nm-dhcp-dhclient.$(OBJEXT) \ +am__objects_4 = nm-dhcp-dhclient.$(OBJEXT) \ nm-dhcp-dhclient-utils.$(OBJEXT) nm-dhcp-dhcpcd.$(OBJEXT) \ nm-dhcp-systemd.$(OBJEXT) -am_NetworkManager_OBJECTS = $(am__objects_5) $(am__objects_1) \ - $(am__objects_6) $(am__objects_1) main-utils.$(OBJEXT) \ +am_NetworkManager_OBJECTS = $(am__objects_3) $(am__objects_1) \ + $(am__objects_4) $(am__objects_1) main-utils.$(OBJEXT) \ main.$(OBJEXT) NetworkManager_OBJECTS = $(am_NetworkManager_OBJECTS) NetworkManager_DEPENDENCIES = libNetworkManager.la @@ -685,6 +676,7 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@ NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ @@ -1065,8 +1057,7 @@ libNetworkManager_la_SOURCES = $(nm_device_headers) \ dns-manager/nm-dns-dnsmasq.h dns-manager/nm-dns-unbound.c \ dns-manager/nm-dns-unbound.h dns-manager/nm-dns-manager.c \ dns-manager/nm-dns-manager.h dns-manager/nm-dns-plugin.c \ - dns-manager/nm-dns-plugin.h dns-manager/nm-dns-utils.c \ - dns-manager/nm-dns-utils.h \ + dns-manager/nm-dns-plugin.h \ dnsmasq-manager/nm-dnsmasq-manager.c \ dnsmasq-manager/nm-dnsmasq-manager.h \ dnsmasq-manager/nm-dnsmasq-utils.c \ @@ -1130,10 +1121,9 @@ libNetworkManager_la_SOURCES = $(nm_device_headers) \ nm-auth-subject.h nm-auth-utils.c nm-auth-utils.h nm-manager.c \ nm-manager.h nm-multi-index.c nm-multi-index.h nm-policy.c \ nm-policy.h nm-rfkill-manager.c nm-rfkill-manager.h \ - nm-session-monitor.h nm-session-monitor.c nm-sleep-monitor.h \ - nm-types.h nm-core-utils.c nm-core-utils.h \ - NetworkManagerUtils.c NetworkManagerUtils.h $(am__append_6) \ - $(am__append_7) $(am__append_8) + nm-session-monitor.h nm-session-monitor.c nm-sleep-monitor.c \ + nm-sleep-monitor.h nm-types.h nm-core-utils.c nm-core-utils.h \ + NetworkManagerUtils.c NetworkManagerUtils.h $(am__append_6) GLIB_GENERATED = nm-enum-types.h nm-enum-types.c GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM --fhead '\#include <nm-core-enum-types.h>\n' GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM @@ -1151,7 +1141,7 @@ libNetworkManager_la_LIBADD = \ $(top_builddir)/introspection/libnmdbus.la libsystemd-nm.la \ $(GLIB_LIBS) $(GUDEV_LIBS) $(LIBNL_LIBS) $(SYSTEMD_LOGIN_LIBS) \ $(SYSTEMD_JOURNAL_LIBS) $(LIBNDP_LIBS) $(LIBDL) $(LIBM) \ - $(SELINUX_LIBS) $(LIBAUDIT_LIBS) $(am__append_9) + $(SELINUX_LIBS) $(LIBAUDIT_LIBS) $(am__append_7) NetworkManager_LDFLAGS = \ -rdynamic \ -Wl,--version-script="$(srcdir)/NetworkManager.ver" @@ -1179,7 +1169,7 @@ libnm_iface_helper_la_SOURCES = dhcp-manager/nm-dhcp-client.c \ nm-ip6-config.c nm-ip6-config.h nm-enum-types.c \ nm-enum-types.h nm-logging.c nm-logging.h nm-multi-index.c \ nm-multi-index.h nm-core-utils.c nm-core-utils.h \ - NetworkManagerUtils.c NetworkManagerUtils.h $(am__append_10) + NetworkManagerUtils.c NetworkManagerUtils.h $(am__append_8) libnm_iface_helper_la_LIBADD = \ $(top_builddir)/libnm-core/libnm-core.la \ $(top_builddir)/introspection/libnmdbus.la \ @@ -1491,7 +1481,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-dns-manager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-dns-plugin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-dns-unbound.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-dns-utils.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-dnsmasq-manager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-dnsmasq-utils.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-enum-types.Plo@am__quote@ @@ -1522,8 +1511,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-settings-connection.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-settings-plugin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-settings.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-sleep-monitor-systemd.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-sleep-monitor-upower.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-sleep-monitor.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-supplicant-config.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-supplicant-interface.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-supplicant-manager.Plo@am__quote@ @@ -1673,13 +1661,6 @@ nm-dns-plugin.lo: dns-manager/nm-dns-plugin.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-dns-plugin.lo `test -f 'dns-manager/nm-dns-plugin.c' || echo '$(srcdir)/'`dns-manager/nm-dns-plugin.c -nm-dns-utils.lo: dns-manager/nm-dns-utils.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-dns-utils.lo -MD -MP -MF $(DEPDIR)/nm-dns-utils.Tpo -c -o nm-dns-utils.lo `test -f 'dns-manager/nm-dns-utils.c' || echo '$(srcdir)/'`dns-manager/nm-dns-utils.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-dns-utils.Tpo $(DEPDIR)/nm-dns-utils.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dns-manager/nm-dns-utils.c' object='nm-dns-utils.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-dns-utils.lo `test -f 'dns-manager/nm-dns-utils.c' || echo '$(srcdir)/'`dns-manager/nm-dns-utils.c - nm-dnsmasq-manager.lo: dnsmasq-manager/nm-dnsmasq-manager.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-dnsmasq-manager.lo -MD -MP -MF $(DEPDIR)/nm-dnsmasq-manager.Tpo -c -o nm-dnsmasq-manager.lo `test -f 'dnsmasq-manager/nm-dnsmasq-manager.c' || echo '$(srcdir)/'`dnsmasq-manager/nm-dnsmasq-manager.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-dnsmasq-manager.Tpo $(DEPDIR)/nm-dnsmasq-manager.Plo diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c index 09ed25c5..9894872b 100644 --- a/src/NetworkManagerUtils.c +++ b/src/NetworkManagerUtils.c @@ -23,6 +23,7 @@ #include "NetworkManagerUtils.h" +#include "nm-common-macros.h" #include "nm-utils.h" #include "nm-setting-connection.h" #include "nm-setting-ip4-config.h" diff --git a/src/devices/Makefile.in b/src/devices/Makefile.in index 4415d31b..d6848e53 100644 --- a/src/devices/Makefile.in +++ b/src/devices/Makefile.in @@ -324,6 +324,7 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@ NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ diff --git a/src/devices/adsl/Makefile.in b/src/devices/adsl/Makefile.in index c8549200..b6805537 100644 --- a/src/devices/adsl/Makefile.in +++ b/src/devices/adsl/Makefile.in @@ -351,6 +351,7 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@ NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ diff --git a/src/devices/bluetooth/Makefile.in b/src/devices/bluetooth/Makefile.in index 233ad9e8..d2b0b865 100644 --- a/src/devices/bluetooth/Makefile.in +++ b/src/devices/bluetooth/Makefile.in @@ -372,6 +372,7 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@ NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ diff --git a/src/devices/bluetooth/nm-bluez-device.c b/src/devices/bluetooth/nm-bluez-device.c index 5ee22f93..dcfa5eec 100644 --- a/src/devices/bluetooth/nm-bluez-device.c +++ b/src/devices/bluetooth/nm-bluez-device.c @@ -54,6 +54,8 @@ typedef struct { gboolean usable; NMBluetoothCapabilities connection_bt_type; + guint check_emit_usable_id; + char *adapter_address; char *address; char *name; @@ -257,14 +259,14 @@ pan_connection_check_create (NMBluezDevice *self) g_free (uuid); } -static void +static gboolean check_emit_usable (NMBluezDevice *self) { NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); gboolean new_usable; /* only expect the supported capabilities set. */ - g_assert ((priv->capabilities & ~(NM_BT_CAPABILITY_NAP | NM_BT_CAPABILITY_DUN)) == NM_BT_CAPABILITY_NONE ); + nm_assert ((priv->capabilities & ~(NM_BT_CAPABILITY_NAP | NM_BT_CAPABILITY_DUN)) == NM_BT_CAPABILITY_NONE ); new_usable = (priv->initialized && priv->capabilities && priv->name && ((priv->bluez_version == 4) || @@ -291,6 +293,17 @@ END: priv->usable = new_usable; g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_USABLE); } + + return G_SOURCE_REMOVE; +} + +static void +check_emit_usable_schedule (NMBluezDevice *self) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + + if (priv->check_emit_usable_id == 0) + priv->check_emit_usable_id = g_idle_add ((GSourceFunc) check_emit_usable, self); } /********************************************************************/ @@ -331,15 +344,26 @@ connection_compatible (NMBluezDevice *self, NMConnection *connection) return TRUE; } -static void -_internal_add_connection (NMBluezDevice *self, NMConnection *connection) +static gboolean +_internal_track_connection (NMBluezDevice *self, NMConnection *connection, gboolean tracked) { NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + gboolean was_tracked; + + was_tracked = !!g_slist_find (priv->connections, connection); + if (was_tracked == !!tracked) + return FALSE; - if (!g_slist_find (priv->connections, connection)) { + if (tracked) priv->connections = g_slist_prepend (priv->connections, g_object_ref (connection)); - check_emit_usable (self); + else { + priv->connections = g_slist_remove (priv->connections, connection); + if (priv->pan_connection == connection) + priv->pan_connection = NULL; + g_object_unref (connection); } + + return TRUE; } static void @@ -347,8 +371,10 @@ cp_connection_added (NMConnectionProvider *provider, NMConnection *connection, NMBluezDevice *self) { - if (connection_compatible (self, connection)) - _internal_add_connection (self, connection); + if (connection_compatible (self, connection)) { + if (_internal_track_connection (self, connection, TRUE)) + check_emit_usable (self); + } } static void @@ -356,15 +382,8 @@ cp_connection_removed (NMConnectionProvider *provider, NMConnection *connection, NMBluezDevice *self) { - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - - if (g_slist_find (priv->connections, connection)) { - priv->connections = g_slist_remove (priv->connections, connection); - if (priv->pan_connection == connection) - priv->pan_connection = NULL; - g_object_unref (connection); + if (_internal_track_connection (self, connection, FALSE)) check_emit_usable (self); - } } static void @@ -372,10 +391,9 @@ cp_connection_updated (NMConnectionProvider *provider, NMConnection *connection, NMBluezDevice *self) { - if (connection_compatible (self, connection)) - _internal_add_connection (self, connection); - else - cp_connection_removed (provider, connection, self); + if (_internal_track_connection (self, connection, + connection_compatible (self, connection))) + check_emit_usable_schedule (self); } static void @@ -383,10 +401,17 @@ load_connections (NMBluezDevice *self) { NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); const GSList *connections, *iter; + gboolean changed = FALSE; connections = nm_connection_provider_get_connections (priv->provider); - for (iter = connections; iter; iter = g_slist_next (iter)) - cp_connection_added (priv->provider, NM_CONNECTION (iter->data), self); + for (iter = connections; iter; iter = g_slist_next (iter)) { + NMConnection *connection = iter->data; + + if (connection_compatible (self, connection)) + changed |= _internal_track_connection (self, connection, TRUE); + } + if (changed) + check_emit_usable (self); } /***********************************************************/ @@ -1031,20 +1056,9 @@ nm_bluez_device_new (const char *path, if (adapter_address) set_adapter_address (self, adapter_address); - g_signal_connect (priv->provider, - NM_CP_SIGNAL_CONNECTION_ADDED, - G_CALLBACK (cp_connection_added), - self); - - g_signal_connect (priv->provider, - NM_CP_SIGNAL_CONNECTION_REMOVED, - G_CALLBACK (cp_connection_removed), - self); - - g_signal_connect (priv->provider, - NM_CP_SIGNAL_CONNECTION_UPDATED, - G_CALLBACK (cp_connection_updated), - self); + g_signal_connect (priv->provider, NM_CP_SIGNAL_CONNECTION_ADDED, G_CALLBACK (cp_connection_added), self); + g_signal_connect (priv->provider, NM_CP_SIGNAL_CONNECTION_REMOVED, G_CALLBACK (cp_connection_removed), self); + g_signal_connect (priv->provider, NM_CP_SIGNAL_CONNECTION_UPDATED, G_CALLBACK (cp_connection_updated), self); g_bus_get (G_BUS_TYPE_SYSTEM, NULL, @@ -1084,6 +1098,8 @@ dispose (GObject *object) NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); NMConnection *to_delete = NULL; + nm_clear_g_source (&priv->check_emit_usable_id); + if (priv->pan_connection) { /* Check whether we want to remove the created connection. If so, we take a reference * and delete it at the end of dispose(). */ diff --git a/src/devices/nm-device-bond.c b/src/devices/nm-device-bond.c index 6ae29b9c..9c98c8ea 100644 --- a/src/devices/nm-device-bond.c +++ b/src/devices/nm-device-bond.c @@ -316,7 +316,7 @@ apply_bonding_config (NMDevice *device) if (NM_IN_STRSET (mode, "active-backup", "balance-alb", "balance-tlb")) { value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_PRIMARY); set_bond_attr (device, "primary", value ? value : ""); - set_simple_option (device, "lp_internal", s_bond, NM_SETTING_BOND_OPTION_LP_INTERVAL); + set_simple_option (device, "lp_interval", s_bond, NM_SETTING_BOND_OPTION_LP_INTERVAL); } /* Clear ARP targets */ diff --git a/src/devices/nm-device-tun.c b/src/devices/nm-device-tun.c index eac2fb82..01cd8ea6 100644 --- a/src/devices/nm-device-tun.c +++ b/src/devices/nm-device-tun.c @@ -104,6 +104,12 @@ reload_tun_properties (NMDeviceTun *self) g_object_thaw_notify (object); } +static NMDeviceCapabilities +get_generic_capabilities (NMDevice *dev) +{ + return NM_DEVICE_CAP_IS_SOFTWARE; +} + static void link_changed (NMDevice *device, NMPlatformLink *info) { @@ -430,6 +436,7 @@ nm_device_tun_class_init (NMDeviceTunClass *klass) device_class->complete_connection = complete_connection; device_class->check_connection_compatible = check_connection_compatible; device_class->create_and_realize = create_and_realize; + device_class->get_generic_capabilities = get_generic_capabilities; device_class->realize_start_notify = realize_start_notify; device_class->unrealize_notify = unrealize_notify; device_class->update_connection = update_connection; diff --git a/src/devices/nm-device-vxlan.c b/src/devices/nm-device-vxlan.c index d308d47a..45f33bdd 100644 --- a/src/devices/nm-device-vxlan.c +++ b/src/devices/nm-device-vxlan.c @@ -136,6 +136,12 @@ update_properties (NMDevice *device) g_object_thaw_notify (object); } +static NMDeviceCapabilities +get_generic_capabilities (NMDevice *dev) +{ + return NM_DEVICE_CAP_IS_SOFTWARE; +} + static void link_changed (NMDevice *device, NMPlatformLink *info) { @@ -647,6 +653,7 @@ nm_device_vxlan_class_init (NMDeviceVxlanClass *klass) device_class->create_and_realize = create_and_realize; device_class->check_connection_compatible = check_connection_compatible; device_class->complete_connection = complete_connection; + device_class->get_generic_capabilities = get_generic_capabilities; device_class->update_connection = update_connection; device_class->act_stage1_prepare = act_stage1_prepare; device_class->ip4_config_pre_commit = ip4_config_pre_commit; diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 8472ff80..62259bc4 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -34,7 +34,7 @@ #include <netlink/route/addr.h> #include <linux/if_addr.h> -#include "nm-device.h" +#include "nm-common-macros.h" #include "nm-device-private.h" #include "NetworkManagerUtils.h" #include "nm-manager.h" @@ -387,6 +387,9 @@ static gboolean nm_device_set_ip6_config (NMDevice *self, gboolean commit, gboolean routes_full_sync, NMDeviceStateReason *reason); +static gboolean ip6_config_merge_and_apply (NMDevice *self, + gboolean commit, + NMDeviceStateReason *out_reason); static void nm_device_master_add_slave (NMDevice *self, NMDevice *slave, gboolean configure); static void nm_device_slave_notify_enslave (NMDevice *self, gboolean success); @@ -413,6 +416,7 @@ static NMActStageReturn dhcp4_start (NMDevice *self, NMConnection *connection, N static gboolean dhcp6_start (NMDevice *self, gboolean wait_for_ll, NMDeviceStateReason *reason); static void nm_device_start_ip_check (NMDevice *self); static void realize_start_setup (NMDevice *self, const NMPlatformLink *plink); +static void nm_device_set_mtu (NMDevice *self, guint32 mtu); /***********************************************************/ @@ -520,6 +524,34 @@ NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_reason_to_string, NMDeviceStateReason, /***********************************************************/ +static void +init_ip4_config_dns_priority (NMDevice *self, NMIP4Config *config) +{ + gs_free char *value = NULL; + gint priority; + + value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA, + "ipv4.dns-priority", + self); + priority = _nm_utils_ascii_str_to_int64 (value, 10, G_MININT, G_MAXINT, 0); + nm_ip4_config_set_dns_priority (config, priority ?: NM_DNS_PRIORITY_DEFAULT_NORMAL); +} + +static void +init_ip6_config_dns_priority (NMDevice *self, NMIP6Config *config) +{ + gs_free char *value = NULL; + gint priority; + + value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA, + "ipv6.dns-priority", + self); + priority = _nm_utils_ascii_str_to_int64 (value, 10, G_MININT, G_MAXINT, 0); + nm_ip6_config_set_dns_priority (config, priority ?: NM_DNS_PRIORITY_DEFAULT_NORMAL); +} + +/***********************************************************/ + gboolean nm_device_ipv6_sysctl_set (NMDevice *self, const char *property, const char *value) { @@ -1091,6 +1123,38 @@ find_slave_info (NMDevice *self, NMDevice *slave) return NULL; } +static void +apply_mtu_from_config (NMDevice *self) +{ + const char *method = NM_SETTING_IP4_CONFIG_METHOD_DISABLED; + NMSettingIPConfig *s_ip4; + NMSettingWired *s_wired; + guint32 mtu; + + /* Devices having an IPv4 configuration will set MTU during the commit + * stage, so it is an error to call this function if the IPv4 method is not + * 'disabled'. + */ + s_ip4 = (NMSettingIPConfig *) + nm_device_get_applied_setting (self, NM_TYPE_SETTING_IP4_CONFIG); + if (s_ip4) + method = nm_setting_ip_config_get_method (s_ip4); + g_return_if_fail (nm_streq (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)); + + s_wired = (NMSettingWired *) + nm_device_get_applied_setting (self, NM_TYPE_SETTING_WIRED); + + if (s_wired) { + mtu = nm_setting_wired_get_mtu (s_wired); + if (mtu) { + _LOGD (LOGD_DEVICE | LOGD_IP, + "setting MTU of device without IP4 config to %u", + mtu); + nm_device_set_mtu (self, mtu); + } + } +} + /** * nm_device_master_enslave_slave: * @self: the master device @@ -1148,6 +1212,11 @@ nm_device_master_enslave_slave (NMDevice *self, NMDevice *slave, NMConnection *c nm_device_activate_stage3_ip6_start (self); } + /* Since slave devices don't have their own IP configuration, + * set the MTU here. + */ + apply_mtu_from_config (slave); + return success; } @@ -1500,6 +1569,7 @@ device_link_changed (NMDevice *self) NMPlatformLink info; const NMPlatformLink *pllink; int ifindex; + gboolean was_up; priv->device_link_changed_id = 0; @@ -1572,6 +1642,7 @@ device_link_changed (NMDevice *self) if (ip_ifname_changed) nm_device_update_dynamic_ip_setup (self); + was_up = priv->up; priv->up = NM_FLAGS_HAS (info.n_ifi_flags, IFF_UP); if ( info.initialized @@ -1599,6 +1670,20 @@ device_link_changed (NMDevice *self) set_unmanaged_external_down (self, FALSE); device_recheck_slave_status (self, &info); + + if (priv->up && !was_up) { + /* the link was down and just came up. That happens for example, while changing MTU. + * We must restore IP configuration. */ + if (priv->ip4_state == IP_DONE) { + if (!ip4_config_merge_and_apply (self, NULL, TRUE, NULL)) + _LOGW (LOGD_IP4, "failed applying IP4 config after link comes up again"); + } + if (priv->ip6_state == IP_DONE) { + if (!ip6_config_merge_and_apply (self, TRUE, NULL)) + _LOGW (LOGD_IP6, "failed applying IP6 config after link comes up again"); + } + } + return G_SOURCE_REMOVE; } @@ -4287,6 +4372,7 @@ ip4_config_merge_and_apply (NMDevice *self, gboolean routes_full_sync; gboolean ignore_auto_routes = FALSE; gboolean ignore_auto_dns = FALSE; + gboolean auto_method = FALSE; /* Merge all the configs into the composite config */ if (config) { @@ -4302,10 +4388,15 @@ ip4_config_merge_and_apply (NMDevice *self, if (s_ip4) { ignore_auto_routes = nm_setting_ip_config_get_ignore_auto_routes (s_ip4); ignore_auto_dns = nm_setting_ip_config_get_ignore_auto_dns (s_ip4); + + if (nm_streq0 (nm_setting_ip_config_get_method (s_ip4), + NM_SETTING_IP4_CONFIG_METHOD_AUTO)) + auto_method = TRUE; } } composite = nm_ip4_config_new (nm_device_get_ip_ifindex (self)); + init_ip4_config_dns_priority (self, composite); if (commit) ensure_con_ip4_config (self); @@ -4357,10 +4448,12 @@ ip4_config_merge_and_apply (NMDevice *self, goto END_ADD_DEFAULT_ROUTE; } - if (nm_device_uses_generated_assumed_connection (self)) { - /* a generate-assumed-connection always detects the default route from platform */ + /* a generated-assumed connection detects the default route from the platform, + * but if the IP method is automatic we need to update the default route to + * maintain connectivity. + */ + if (nm_device_uses_generated_assumed_connection (self) && !auto_method) goto END_ADD_DEFAULT_ROUTE; - } /* At this point, we treat assumed and non-assumed connections alike. * For assumed connections we do that because we still manage RA and DHCP @@ -4946,7 +5039,8 @@ act_stage3_ip4_config_start (NMDevice *self, } else ret = NM_ACT_STAGE_RETURN_FAILURE; } else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0) { - /* Nothing to do... */ + apply_mtu_from_config (self); + /* Nothing else to do... */ ret = NM_ACT_STAGE_RETURN_STOP; } else _LOGW (LOGD_IP4, "unhandled IPv4 config method '%s'; will fail", method); @@ -5009,6 +5103,7 @@ ip6_config_merge_and_apply (NMDevice *self, gboolean routes_full_sync; gboolean ignore_auto_routes = FALSE; gboolean ignore_auto_dns = FALSE; + gboolean auto_method = FALSE; /* Apply ignore-auto-routes and ignore-auto-dns settings */ connection = nm_device_get_applied_connection (self); @@ -5018,14 +5113,21 @@ ip6_config_merge_and_apply (NMDevice *self, if (s_ip6) { ignore_auto_routes = nm_setting_ip_config_get_ignore_auto_routes (s_ip6); ignore_auto_dns = nm_setting_ip_config_get_ignore_auto_dns (s_ip6); + + if (NM_IN_STRSET (nm_setting_ip_config_get_method (s_ip6), + NM_SETTING_IP6_CONFIG_METHOD_AUTO, + NM_SETTING_IP6_CONFIG_METHOD_DHCP)) + auto_method = TRUE; } } /* If no config was passed in, create a new one */ composite = nm_ip6_config_new (nm_device_get_ip_ifindex (self)); + init_ip6_config_dns_priority (self, composite); if (commit) ensure_con_ip6_config (self); + g_assert (composite); /* Merge all the IP configs into the composite config */ @@ -5081,10 +5183,12 @@ ip6_config_merge_and_apply (NMDevice *self, goto END_ADD_DEFAULT_ROUTE; } - if (nm_device_uses_generated_assumed_connection (self)) { - /* a generate-assumed-connection always detects the default route from platform */ + /* a generated-assumed connection detects the default route from the platform, + * but if the IP method is automatic we need to update the default route to + * maintain connectivity. + */ + if (nm_device_uses_generated_assumed_connection (self) && !auto_method) goto END_ADD_DEFAULT_ROUTE; - } /* At this point, we treat assumed and non-assumed connections alike. * For assumed connections we do that because we still manage RA and DHCP @@ -7895,6 +7999,9 @@ nm_device_set_ip4_config (NMDevice *self, g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + _LOGD (LOGD_IP4, "ip4-config: update (commit=%d, routes-full-sync=%d, new-config=%p)", + commit, routes_full_sync, new_config); + priv = NM_DEVICE_GET_PRIVATE (self); ip_ifindex = nm_device_get_ip_ifindex (self); @@ -7928,7 +8035,7 @@ nm_device_set_ip4_config (NMDevice *self, * this causes a re-read and reset. This should only happen for relevant changes */ nm_ip4_config_replace (old_config, new_config, &has_changes); if (has_changes) { - _LOGD (LOGD_IP4, "update IP4Config instance (%s)", + _LOGD (LOGD_IP4, "ip4-config: update IP4Config instance (%s)", nm_exported_object_get_path (NM_EXPORTED_OBJECT (old_config))); } } else { @@ -7938,13 +8045,13 @@ nm_device_set_ip4_config (NMDevice *self, if (success && !nm_exported_object_is_exported (NM_EXPORTED_OBJECT (new_config))) nm_exported_object_export (NM_EXPORTED_OBJECT (new_config)); - _LOGD (LOGD_IP4, "set IP4Config instance (%s)", + _LOGD (LOGD_IP4, "ip4-config: set IP4Config instance (%s)", nm_exported_object_get_path (NM_EXPORTED_OBJECT (new_config))); } } else if (old_config) { has_changes = TRUE; priv->ip4_config = NULL; - _LOGD (LOGD_IP4, "clear IP4Config instance (%s)", + _LOGD (LOGD_IP4, "ip4-config: clear IP4Config instance (%s)", nm_exported_object_get_path (NM_EXPORTED_OBJECT (old_config))); /* Device config is invalid if combined config is invalid */ g_clear_object (&priv->dev_ip4_config); @@ -7963,23 +8070,16 @@ nm_device_set_ip4_config (NMDevice *self, nm_exported_object_clear_and_unexport (&old_config); if (nm_device_uses_generated_assumed_connection (self)) { - NMConnection *connection = nm_device_get_applied_connection (self); NMConnection *settings_connection = NM_CONNECTION (nm_device_get_settings_connection (self)); NMSetting *s_ip4; - g_object_freeze_notify (G_OBJECT (connection)); g_object_freeze_notify (G_OBJECT (settings_connection)); nm_connection_remove_setting (settings_connection, NM_TYPE_SETTING_IP4_CONFIG); s_ip4 = nm_ip4_config_create_setting (priv->ip4_config); nm_connection_add_setting (settings_connection, s_ip4); - nm_connection_remove_setting (connection, NM_TYPE_SETTING_IP4_CONFIG); - s_ip4 = nm_ip4_config_create_setting (priv->ip4_config); - nm_connection_add_setting (connection, s_ip4); - g_object_thaw_notify (G_OBJECT (settings_connection)); - g_object_thaw_notify (G_OBJECT (connection)); } nm_device_queue_recheck_assume (self); @@ -8070,6 +8170,9 @@ nm_device_set_ip6_config (NMDevice *self, g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + _LOGD (LOGD_IP6, "ip6-config: update (commit=%d, routes-full-sync=%d, new-config=%p)", + commit, routes_full_sync, new_config); + priv = NM_DEVICE_GET_PRIVATE (self); ip_ifindex = nm_device_get_ip_ifindex (self); @@ -8097,7 +8200,7 @@ nm_device_set_ip6_config (NMDevice *self, * this causes a re-read and reset. This should only happen for relevant changes */ nm_ip6_config_replace (old_config, new_config, &has_changes); if (has_changes) { - _LOGD (LOGD_IP6, "update IP6Config instance (%s)", + _LOGD (LOGD_IP6, "ip6-config: update IP6Config instance (%s)", nm_exported_object_get_path (NM_EXPORTED_OBJECT (old_config))); } } else { @@ -8107,13 +8210,13 @@ nm_device_set_ip6_config (NMDevice *self, if (success && !nm_exported_object_is_exported (NM_EXPORTED_OBJECT (new_config))) nm_exported_object_export (NM_EXPORTED_OBJECT (new_config)); - _LOGD (LOGD_IP6, "set IP6Config instance (%s)", + _LOGD (LOGD_IP6, "ip6-config: set IP6Config instance (%s)", nm_exported_object_get_path (NM_EXPORTED_OBJECT (new_config))); } } else if (old_config) { has_changes = TRUE; priv->ip6_config = NULL; - _LOGD (LOGD_IP6, "clear IP6Config instance (%s)", + _LOGD (LOGD_IP6, "ip6-config: clear IP6Config instance (%s)", nm_exported_object_get_path (NM_EXPORTED_OBJECT (old_config))); } @@ -8128,23 +8231,16 @@ nm_device_set_ip6_config (NMDevice *self, nm_exported_object_clear_and_unexport (&old_config); if (nm_device_uses_generated_assumed_connection (self)) { - NMConnection *connection = nm_device_get_applied_connection (self); NMConnection *settings_connection = NM_CONNECTION (nm_device_get_settings_connection (self)); NMSetting *s_ip6; - g_object_freeze_notify (G_OBJECT (connection)); g_object_freeze_notify (G_OBJECT (settings_connection)); nm_connection_remove_setting (settings_connection, NM_TYPE_SETTING_IP6_CONFIG); s_ip6 = nm_ip6_config_create_setting (priv->ip6_config); nm_connection_add_setting (settings_connection, s_ip6); - nm_connection_remove_setting (connection, NM_TYPE_SETTING_IP6_CONFIG); - s_ip6 = nm_ip6_config_create_setting (priv->ip6_config); - nm_connection_add_setting (connection, s_ip6); - g_object_thaw_notify (G_OBJECT (settings_connection)); - g_object_thaw_notify (G_OBJECT (connection)); } nm_device_queue_recheck_assume (self); @@ -8545,6 +8641,17 @@ nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware) nm_device_update_hw_address (self); _update_ip4_address (self); + + /* when the link comes up, we must restore IP configuration if necessary. */ + if (priv->ip4_state == IP_DONE) { + if (!ip4_config_merge_and_apply (self, NULL, TRUE, NULL)) + _LOGW (LOGD_IP4, "failed applying IP4 config after bringing link up"); + } + if (priv->ip6_state == IP_DONE) { + if (!ip6_config_merge_and_apply (self, TRUE, NULL)) + _LOGW (LOGD_IP6, "failed applying IP6 config after bringing link up"); + } + return TRUE; } @@ -8782,7 +8889,6 @@ update_ip4_config (NMDevice *self, gboolean initial) NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); int ifindex; gboolean capture_resolv_conf; - NMDnsManagerResolvConfMode resolv_conf_mode; /* If a commit is scheduled, this function would potentially interfere with * it changing IP configurations before they are applied. Postpone the @@ -8801,8 +8907,8 @@ update_ip4_config (NMDevice *self, gboolean initial) if (!ifindex) return; - resolv_conf_mode = nm_dns_manager_get_resolv_conf_mode (nm_dns_manager_get ()); - capture_resolv_conf = initial && (resolv_conf_mode == NM_DNS_MANAGER_RESOLV_CONF_EXPLICIT); + capture_resolv_conf = initial + && nm_dns_manager_get_resolv_conf_explicit (nm_dns_manager_get ()); /* IPv4 */ g_clear_object (&priv->ext_ip4_config); @@ -8873,7 +8979,6 @@ update_ip6_config (NMDevice *self, gboolean initial) NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); int ifindex; gboolean capture_resolv_conf; - NMDnsManagerResolvConfMode resolv_conf_mode; /* If a commit is scheduled, this function would potentially interfere with * it changing IP configurations before they are applied. Postpone the @@ -8892,8 +8997,8 @@ update_ip6_config (NMDevice *self, gboolean initial) if (!ifindex) return; - resolv_conf_mode = nm_dns_manager_get_resolv_conf_mode (nm_dns_manager_get ()); - capture_resolv_conf = initial && (resolv_conf_mode == NM_DNS_MANAGER_RESOLV_CONF_EXPLICIT); + capture_resolv_conf = initial + && nm_dns_manager_get_resolv_conf_explicit (nm_dns_manager_get ()); /* IPv6 */ g_clear_object (&priv->ext_ip6_config); @@ -8994,9 +9099,9 @@ queued_ip6_config_change (gpointer user_data) g_object_ref (self); update_ip6_config (self, FALSE); - if ( nm_platform_link_get (NM_PLATFORM_GET, priv->ifindex) - && priv->state < NM_DEVICE_STATE_DEACTIVATING) { - /* Handle DAD falures */ + if ( priv->state < NM_DEVICE_STATE_DEACTIVATING + && nm_platform_link_get (NM_PLATFORM_GET, priv->ifindex)) { + /* Handle DAD failures */ for (iter = priv->dad6_failed_addrs; iter; iter = g_slist_next (iter)) { NMPlatformIP6Address *addr = iter->data; @@ -9277,6 +9382,7 @@ nm_device_get_unmanaged_flags (NMDevice *self, NMUnmanagedFlags flag) * @allow_state_transition: if %FALSE, setting flags never triggers a device * state change. If %TRUE, the device can change state, if it is real and * switches from managed to unmanaged (or vice versa). + * @now: whether the state change should be immediate or delayed * @reason: the device state reason passed to nm_device_state_changed() if * the device becomes managed/unmanaged. This is only relevant if the * device switches state and if @allow_state_transition is %TRUE. @@ -9288,11 +9394,13 @@ _set_unmanaged_flags (NMDevice *self, NMUnmanagedFlags flags, NMUnmanFlagOp set_op, gboolean allow_state_transition, + gboolean now, NMDeviceStateReason reason) { NMDevicePrivate *priv; gboolean was_managed, transition_state; NMUnmanagedFlags old_flags, old_mask; + NMDeviceState new_state; const char *operation = NULL; char str1[512]; char str2[512]; @@ -9364,10 +9472,11 @@ _set_unmanaged_flags (NMDevice *self, #undef _FMT if (transition_state) { - if (was_managed) - nm_device_state_changed (self, NM_DEVICE_STATE_UNMANAGED, reason); + new_state = was_managed ? NM_DEVICE_STATE_UNMANAGED : NM_DEVICE_STATE_UNAVAILABLE; + if (now) + nm_device_state_changed (self, new_state, reason); else - nm_device_state_changed (self, NM_DEVICE_STATE_UNAVAILABLE, reason); + nm_device_queue_state (self, new_state, reason); } } @@ -9385,7 +9494,7 @@ nm_device_set_unmanaged_flags (NMDevice *self, NMUnmanagedFlags flags, NMUnmanFlagOp set_op) { - _set_unmanaged_flags (self, flags, set_op, FALSE, NM_DEVICE_STATE_REASON_NONE); + _set_unmanaged_flags (self, flags, set_op, FALSE, FALSE, NM_DEVICE_STATE_REASON_NONE); } /** @@ -9406,7 +9515,16 @@ nm_device_set_unmanaged_by_flags (NMDevice *self, NMUnmanFlagOp set_op, NMDeviceStateReason reason) { - _set_unmanaged_flags (self, flags, set_op, TRUE, reason); + _set_unmanaged_flags (self, flags, set_op, TRUE, TRUE, reason); +} + +void +nm_device_set_unmanaged_by_flags_queue (NMDevice *self, + NMUnmanagedFlags flags, + NMUnmanFlagOp set_op, + NMDeviceStateReason reason) +{ + _set_unmanaged_flags (self, flags, set_op, TRUE, FALSE, reason); } void @@ -9710,12 +9828,6 @@ nm_device_check_connection_available (NMDevice *self, return available; } -static void -available_connections_notify (NMDevice *self) -{ - _notify (self, PROP_AVAILABLE_CONNECTIONS); -} - static gboolean available_connections_del_all (NMDevice *self) { @@ -9815,7 +9927,7 @@ nm_device_recheck_available_connections (NMDevice *self) } if (changed) - available_connections_notify (self); + _notify (self, PROP_AVAILABLE_CONNECTIONS); available_connections_check_delete_unrealized (self); } @@ -9889,7 +10001,7 @@ cp_connection_added_or_updated (NMConnectionProvider *cp, NMConnection *connecti changed = available_connections_del (self, connection); if (changed) { - available_connections_notify (self); + _notify (self, PROP_AVAILABLE_CONNECTIONS); available_connections_check_delete_unrealized (self); } } @@ -9902,7 +10014,7 @@ cp_connection_removed (NMConnectionProvider *cp, NMConnection *connection, gpoin g_return_if_fail (NM_IS_DEVICE (self)); if (available_connections_del (self, connection)) { - available_connections_notify (self); + _notify (self, PROP_AVAILABLE_CONNECTIONS); available_connections_check_delete_unrealized (self); } } @@ -10524,7 +10636,7 @@ _set_state_full (NMDevice *self, if (state <= NM_DEVICE_STATE_UNAVAILABLE) { if (available_connections_del_all (self)) - available_connections_notify (self); + _notify (self, PROP_AVAILABLE_CONNECTIONS); if (old_state > NM_DEVICE_STATE_UNAVAILABLE) _clear_queued_act_request (priv); } diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index 9f689850..21804396 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -489,6 +489,10 @@ void nm_device_set_unmanaged_by_flags (NMDevice *device, NMUnmanagedFlags flags, NMUnmanFlagOp set_op, NMDeviceStateReason reason); +void nm_device_set_unmanaged_by_flags_queue (NMDevice *self, + NMUnmanagedFlags flags, + NMUnmanFlagOp set_op, + NMDeviceStateReason reason); void nm_device_set_unmanaged_by_user_config (NMDevice *self, const GSList *unmanaged_specs); void nm_device_set_unmanaged_by_user_udev (NMDevice *self); void nm_device_set_unmanaged_by_quitting (NMDevice *device); diff --git a/src/devices/nm-lldp-listener.c b/src/devices/nm-lldp-listener.c index 592059f5..9cc1d086 100644 --- a/src/devices/nm-lldp-listener.c +++ b/src/devices/nm-lldp-listener.c @@ -531,7 +531,7 @@ lldp_neighbor_new (sd_lldp_neighbor *neighbor_sd, GError **error) neigh->valid = TRUE; out: - return nm_unauto (&neigh); + return g_steal_pointer (&neigh); } static GVariant * @@ -694,7 +694,7 @@ process_lldp_neighbor (NMLldpListener *self, sd_lldp_neighbor *neighbor_sd, gboo LOG_NEIGH_ARG (neigh)); changed = TRUE; - g_hash_table_add (priv->lldp_neighbors, nm_unauto (&neigh)); + g_hash_table_add (priv->lldp_neighbors, g_steal_pointer (&neigh)); done: if (changed) diff --git a/src/devices/team/Makefile.in b/src/devices/team/Makefile.in index 115a7589..4ca3014f 100644 --- a/src/devices/team/Makefile.in +++ b/src/devices/team/Makefile.in @@ -355,6 +355,7 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@ NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ diff --git a/src/devices/team/nm-device-team.c b/src/devices/team/nm-device-team.c index 60842c18..b4b522d8 100644 --- a/src/devices/team/nm-device-team.c +++ b/src/devices/team/nm-device-team.c @@ -318,10 +318,18 @@ teamd_dbus_appeared (GDBusConnection *connection, 2000, NULL, NULL); - g_variant_get (ret, "(u)", &pid); - if (pid != priv->teamd_pid) - teamd_cleanup (device, FALSE); + if (ret) { + g_variant_get (ret, "(u)", &pid); + if (pid != priv->teamd_pid) + teamd_cleanup (device, FALSE); + } else { + _LOGW (LOGD_TEAM, "failed to determine D-Bus name owner"); + /* If we can't determine the bus name owner, don't kill our + * teamd instance. Hopefully another existing teamd just died and + * our instance will be able to grab the bus name. + */ + } } /* Grab a teamd control handle even if we aren't going to use it diff --git a/src/devices/tests/Makefile.in b/src/devices/tests/Makefile.in index 31cf0d38..b07e6dfd 100644 --- a/src/devices/tests/Makefile.in +++ b/src/devices/tests/Makefile.in @@ -527,6 +527,7 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@ NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ diff --git a/src/devices/wifi/Makefile.in b/src/devices/wifi/Makefile.in index a180a434..34aa4b97 100644 --- a/src/devices/wifi/Makefile.in +++ b/src/devices/wifi/Makefile.in @@ -394,6 +394,7 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@ NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index 95a89eab..82b12a11 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -26,6 +26,7 @@ #include <unistd.h> #include <errno.h> +#include "nm-common-macros.h" #include "nm-device.h" #include "nm-device-wifi.h" #include "nm-device-private.h" @@ -696,6 +697,7 @@ manf_defaults[] = { "WLAN", "ALICE-WLAN", "Speedport W 501V", + "TURBONETT", }; #define ARRAY_SIZE(a) (sizeof (a) / sizeof (a[0])) diff --git a/src/devices/wifi/tests/Makefile.in b/src/devices/wifi/tests/Makefile.in index be874cc3..956730f8 100644 --- a/src/devices/wifi/tests/Makefile.in +++ b/src/devices/wifi/tests/Makefile.in @@ -522,6 +522,7 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@ NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ diff --git a/src/devices/wwan/Makefile.in b/src/devices/wwan/Makefile.in index e7722414..89328665 100644 --- a/src/devices/wwan/Makefile.in +++ b/src/devices/wwan/Makefile.in @@ -363,6 +363,7 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@ NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ diff --git a/src/dhcp-manager/Makefile.in b/src/dhcp-manager/Makefile.in index 0f98c8c5..063489cb 100644 --- a/src/dhcp-manager/Makefile.in +++ b/src/dhcp-manager/Makefile.in @@ -317,6 +317,7 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@ NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ diff --git a/src/dhcp-manager/nm-dhcp-client.c b/src/dhcp-manager/nm-dhcp-client.c index 9f4cdf3e..c1025817 100644 --- a/src/dhcp-manager/nm-dhcp-client.c +++ b/src/dhcp-manager/nm-dhcp-client.c @@ -884,7 +884,9 @@ dispose (GObject *object) g_clear_pointer (&priv->iface, g_free); g_clear_pointer (&priv->hostname, g_free); + g_clear_pointer (&priv->fqdn, g_free); g_clear_pointer (&priv->uuid, g_free); + g_clear_pointer (&priv->client_id, g_bytes_unref); if (priv->hwaddr) { g_byte_array_free (priv->hwaddr, TRUE); diff --git a/src/dhcp-manager/nm-dhcp-dhclient-utils.c b/src/dhcp-manager/nm-dhcp-dhclient-utils.c index bf2df1e0..008f8af2 100644 --- a/src/dhcp-manager/nm-dhcp-dhclient-utils.c +++ b/src/dhcp-manager/nm-dhcp-dhclient-utils.c @@ -36,8 +36,9 @@ #define HOSTNAME4_TAG "send host-name" #define HOSTNAME4_FORMAT HOSTNAME4_TAG " \"%s\"; # added by NetworkManager" -#define FQDN_TAG "send fqdn.fqdn" -#define FQDN_FORMAT FQDN_TAG " \"%s\"; # added by NetworkManager" +#define FQDN_TAG_PREFIX "send fqdn." +#define FQDN_TAG FQDN_TAG_PREFIX "fqdn" +#define FQDN_FORMAT FQDN_TAG " \"%s\"; # added by NetworkManager" #define ALSOREQ_TAG "also request " @@ -205,13 +206,14 @@ nm_dhcp_dhclient_create_config (const char *interface, GBytes **out_new_client_id) { GString *new_contents; - GPtrArray *alsoreq; + GPtrArray *alsoreq, *fqdn_opts; int i; g_return_val_if_fail (!anycast_addr || nm_utils_hwaddr_valid (anycast_addr, ETH_ALEN), NULL); new_contents = g_string_new (_("# Created by NetworkManager\n")); alsoreq = g_ptr_array_sized_new (5); + fqdn_opts = g_ptr_array_sized_new (5); if (orig_contents) { char **lines, **line; @@ -244,6 +246,14 @@ nm_dhcp_dhclient_create_config (const char *interface, continue; } + /* To let user's FQDN options (except "fqdn.fqdn") override the + * default ones set by NM, add them later + */ + if (!strncmp (p, FQDN_TAG_PREFIX, NM_STRLEN (FQDN_TAG_PREFIX))) { + g_ptr_array_add (fqdn_opts, g_strdup (p + NM_STRLEN (FQDN_TAG_PREFIX))); + continue; + } + /* Ignore 'script' since we pass our own */ if (g_str_has_prefix (p, "script ")) continue; @@ -320,6 +330,16 @@ nm_dhcp_dhclient_create_config (const char *interface, } g_ptr_array_free (alsoreq, TRUE); + for (i = 0; i < fqdn_opts->len; i++) { + char *t = g_ptr_array_index (fqdn_opts, i); + + if (i == 0) + g_string_append_printf (new_contents, "\n# FQDN options from %s\n", orig_path); + g_string_append_printf (new_contents, FQDN_TAG_PREFIX "%s\n", t); + g_free (t); + } + g_ptr_array_free (fqdn_opts, TRUE); + g_string_append_c (new_contents, '\n'); if (anycast_addr) { diff --git a/src/dhcp-manager/nm-dhcp-dhclient.c b/src/dhcp-manager/nm-dhcp-dhclient.c index 4b6d301b..b35921ec 100644 --- a/src/dhcp-manager/nm-dhcp-dhclient.c +++ b/src/dhcp-manager/nm-dhcp-dhclient.c @@ -52,6 +52,7 @@ typedef struct { const char *def_leasefile; char *lease_file; char *pid_file; + NMDhcpListener *dhcp_listener; } NMDhcpDhclientPrivate; static const char * @@ -622,7 +623,8 @@ nm_dhcp_dhclient_init (NMDhcpDhclient *self) if (!priv->def_leasefile) priv->def_leasefile = SYSCONFDIR "/dhclient6.leases"; - g_signal_connect (nm_dhcp_listener_get (), + priv->dhcp_listener = g_object_ref (nm_dhcp_listener_get ()); + g_signal_connect (priv->dhcp_listener, NM_DHCP_LISTENER_EVENT, G_CALLBACK (nm_dhcp_client_handle_event), self); @@ -633,9 +635,12 @@ dispose (GObject *object) { NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE (object); - g_signal_handlers_disconnect_by_func (nm_dhcp_listener_get (), - G_CALLBACK (nm_dhcp_client_handle_event), - NM_DHCP_DHCLIENT (object)); + if (priv->dhcp_listener) { + g_signal_handlers_disconnect_by_func (priv->dhcp_listener, + G_CALLBACK (nm_dhcp_client_handle_event), + NM_DHCP_DHCLIENT (object)); + g_clear_object (&priv->dhcp_listener); + } g_free (priv->pid_file); g_free (priv->conf_file); diff --git a/src/dhcp-manager/nm-dhcp-dhcpcd.c b/src/dhcp-manager/nm-dhcp-dhcpcd.c index 8bbb6e4c..17ec993a 100644 --- a/src/dhcp-manager/nm-dhcp-dhcpcd.c +++ b/src/dhcp-manager/nm-dhcp-dhcpcd.c @@ -44,6 +44,7 @@ G_DEFINE_TYPE (NMDhcpDhcpcd, nm_dhcp_dhcpcd, NM_TYPE_DHCP_CLIENT) typedef struct { char *pid_file; + NMDhcpListener *dhcp_listener; } NMDhcpDhcpcdPrivate; static const char * @@ -191,7 +192,10 @@ stop (NMDhcpClient *client, gboolean release, const GByteArray *duid) static void nm_dhcp_dhcpcd_init (NMDhcpDhcpcd *self) { - g_signal_connect (nm_dhcp_listener_get (), + NMDhcpDhcpcdPrivate *priv = NM_DHCP_DHCPCD_GET_PRIVATE (self); + + priv->dhcp_listener = g_object_ref (nm_dhcp_listener_get ()); + g_signal_connect (priv->dhcp_listener, NM_DHCP_LISTENER_EVENT, G_CALLBACK (nm_dhcp_client_handle_event), self); @@ -202,9 +206,12 @@ dispose (GObject *object) { NMDhcpDhcpcdPrivate *priv = NM_DHCP_DHCPCD_GET_PRIVATE (object); - g_signal_handlers_disconnect_by_func (nm_dhcp_listener_get (), - G_CALLBACK (nm_dhcp_client_handle_event), - NM_DHCP_DHCPCD (object)); + if (priv->dhcp_listener) { + g_signal_handlers_disconnect_by_func (priv->dhcp_listener, + G_CALLBACK (nm_dhcp_client_handle_event), + NM_DHCP_DHCPCD (object)); + g_clear_object (&priv->dhcp_listener); + } g_free (priv->pid_file); diff --git a/src/dhcp-manager/tests/Makefile.in b/src/dhcp-manager/tests/Makefile.in index 1a072c73..2528b3c5 100644 --- a/src/dhcp-manager/tests/Makefile.in +++ b/src/dhcp-manager/tests/Makefile.in @@ -527,6 +527,7 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@ NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ diff --git a/src/dhcp-manager/tests/test-dhcp-dhclient.c b/src/dhcp-manager/tests/test-dhcp-dhclient.c index 0561d43c..046dd7e2 100644 --- a/src/dhcp-manager/tests/test-dhcp-dhclient.c +++ b/src/dhcp-manager/tests/test-dhcp-dhclient.c @@ -334,6 +334,46 @@ test_fqdn (void) NULL); } +static const char *fqdn_options_override_orig = \ + "\n" + "send fqdn.fqdn \"foobar.com\"\n" /* NM must ignore this ... */ + "send fqdn.encoded off;\n" /* ... and honor these */ + "send fqdn.server-update off;\n"; + +static const char *fqdn_options_override_expected = \ + "# Created by NetworkManager\n" + "# Merged from /path/to/dhclient.conf\n" + "\n" + "send fqdn.fqdn \"example2.com\"; # added by NetworkManager\n" + "send fqdn.encoded on;\n" + "send fqdn.server-update on;\n" + "\n" + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" + "option wpad code 252 = string;\n" + "\n" + "also request rfc3442-classless-static-routes;\n" + "also request ms-classless-static-routes;\n" + "also request static-routes;\n" + "also request wpad;\n" + "also request ntp-servers;\n" + "\n" + "# FQDN options from /path/to/dhclient.conf\n" + "send fqdn.encoded off;\n" + "send fqdn.server-update off;\n\n"; + +static void +test_fqdn_options_override (void) +{ + test_config (fqdn_options_override_orig, + fqdn_options_override_expected, + FALSE, NULL, + "example2.com", NULL, + NULL, + "eth0", + NULL); +} + /*******************************************/ static const char *override_hostname_orig = \ @@ -804,6 +844,7 @@ main (int argc, char **argv) g_test_add_func ("/dhcp/dhclient/existing-hex-client-id", test_existing_hex_client_id); g_test_add_func ("/dhcp/dhclient/existing-ascii-client-id", test_existing_ascii_client_id); g_test_add_func ("/dhcp/dhclient/fqdn", test_fqdn); + g_test_add_func ("/dhcp/dhclient/fqdn_options_override", test_fqdn_options_override); g_test_add_func ("/dhcp/dhclient/override_hostname", test_override_hostname); g_test_add_func ("/dhcp/dhclient/override_hostname6", test_override_hostname6); g_test_add_func ("/dhcp/dhclient/nonfqdn_hostname6", test_nonfqdn_hostname6); diff --git a/src/dns-manager/nm-dns-dnsmasq.c b/src/dns-manager/nm-dns-dnsmasq.c index 4cee1608..69b26068 100644 --- a/src/dns-manager/nm-dns-dnsmasq.c +++ b/src/dns-manager/nm-dns-dnsmasq.c @@ -26,12 +26,14 @@ #include <sys/wait.h> #include <arpa/inet.h> #include <sys/stat.h> +#include <linux/if.h> #include "nm-dns-dnsmasq.h" +#include "nm-core-internal.h" +#include "nm-platform.h" #include "nm-utils.h" #include "nm-ip4-config.h" #include "nm-ip6-config.h" -#include "nm-dns-utils.h" #include "nm-bus-manager.h" #include "NetworkManagerUtils.h" @@ -48,6 +50,7 @@ G_DEFINE_TYPE (NMDnsDnsmasq, nm_dns_dnsmasq, NM_TYPE_DNS_PLUGIN) typedef struct { GDBusProxy *dnsmasq; GCancellable *dnsmasq_cancellable; + GCancellable *update_cancellable; gboolean running; GVariant *set_server_ex_args; @@ -68,6 +71,70 @@ typedef struct { /*****************************************************************************/ +static char ** +get_ip4_rdns_domains (NMIP4Config *ip4) +{ + char **strv; + GPtrArray *domains = NULL; + int i; + + g_return_val_if_fail (ip4 != NULL, NULL); + + domains = g_ptr_array_sized_new (5); + + for (i = 0; i < nm_ip4_config_get_num_addresses (ip4); i++) { + const NMPlatformIP4Address *address = nm_ip4_config_get_address (ip4, i); + + nm_utils_get_reverse_dns_domains_ip4 (address->address, address->plen, domains); + } + + for (i = 0; i < nm_ip4_config_get_num_routes (ip4); i++) { + const NMPlatformIP4Route *route = nm_ip4_config_get_route (ip4, i); + + nm_utils_get_reverse_dns_domains_ip4 (route->network, route->plen, domains); + } + + /* Terminating NULL so we can use g_strfreev() to free it */ + g_ptr_array_add (domains, NULL); + + /* Free the array and return NULL if the only element was the ending NULL */ + strv = (char **) g_ptr_array_free (domains, (domains->len == 1)); + + return _nm_utils_strv_cleanup (strv, FALSE, FALSE, TRUE); +} + +static char ** +get_ip6_rdns_domains (NMIP6Config *ip6) +{ + char **strv; + GPtrArray *domains = NULL; + int i; + + g_return_val_if_fail (ip6 != NULL, NULL); + + domains = g_ptr_array_sized_new (5); + + for (i = 0; i < nm_ip6_config_get_num_addresses (ip6); i++) { + const NMPlatformIP6Address *address = nm_ip6_config_get_address (ip6, i); + + nm_utils_get_reverse_dns_domains_ip6 (&address->address, address->plen, domains); + } + + for (i = 0; i < nm_ip6_config_get_num_routes (ip6); i++) { + const NMPlatformIP6Route *route = nm_ip6_config_get_route (ip6, i); + + nm_utils_get_reverse_dns_domains_ip6 (&route->network, route->plen, domains); + } + + /* Terminating NULL so we can use g_strfreev() to free it */ + g_ptr_array_add (domains, NULL); + + /* Free the array and return NULL if the only element was the ending NULL */ + strv = (char **) g_ptr_array_free (domains, (domains->len == 1)); + + return _nm_utils_strv_cleanup (strv, FALSE, FALSE, TRUE); +} + static void add_dnsmasq_nameserver (NMDnsDnsmasq *self, GVariantBuilder *servers, @@ -89,13 +156,16 @@ add_dnsmasq_nameserver (NMDnsDnsmasq *self, } static gboolean -add_ip4_config (NMDnsDnsmasq *self, GVariantBuilder *servers, NMIP4Config *ip4, gboolean split) +add_ip4_config (NMDnsDnsmasq *self, GVariantBuilder *servers, NMIP4Config *ip4, + const char *iface, gboolean split) { - char buf[INET_ADDRSTRLEN]; + char buf[INET_ADDRSTRLEN + 1 + IFNAMSIZ]; + char buf2[INET_ADDRSTRLEN]; in_addr_t addr; int nnameservers, i_nameserver, n, i; gboolean added = FALSE; + g_return_val_if_fail (iface, FALSE); nnameservers = nm_ip4_config_get_num_nameservers (ip4); if (split) { @@ -106,7 +176,8 @@ add_ip4_config (NMDnsDnsmasq *self, GVariantBuilder *servers, NMIP4Config *ip4, for (i_nameserver = 0; i_nameserver < nnameservers; i_nameserver++) { addr = nm_ip4_config_get_nameserver (ip4, i_nameserver); - nm_utils_inet4_ntop (addr, buf); + g_snprintf (buf, sizeof (buf), "%s@%s", + nm_utils_inet4_ntop (addr, buf2), iface); /* searches are preferred over domains */ n = nm_ip4_config_get_num_searches (ip4); @@ -133,22 +204,22 @@ add_ip4_config (NMDnsDnsmasq *self, GVariantBuilder *servers, NMIP4Config *ip4, /* Ensure reverse-DNS works by directing queries for in-addr.arpa * domains to the split domain's nameserver. */ - domains = nm_dns_utils_get_ip4_rdns_domains (ip4); + domains = get_ip4_rdns_domains (ip4); if (domains) { for (iter = domains; iter && *iter; iter++) add_dnsmasq_nameserver (self, servers, buf, *iter); g_strfreev (domains); - added = TRUE; } } } - /* If no searches or domains, just add the namservers */ + /* If no searches or domains, just add the nameservers */ if (!added) { for (i = 0; i < nnameservers; i++) { addr = nm_ip4_config_get_nameserver (ip4, i); - add_dnsmasq_nameserver (self, servers, - nm_utils_inet4_ntop (addr, NULL), NULL); + g_snprintf (buf, sizeof (buf), "%s@%s", + nm_utils_inet4_ntop (addr, buf2), iface); + add_dnsmasq_nameserver (self, servers, buf, NULL); } } @@ -158,23 +229,22 @@ add_ip4_config (NMDnsDnsmasq *self, GVariantBuilder *servers, NMIP4Config *ip4, static char * ip6_addr_to_string (const struct in6_addr *addr, const char *iface) { - char *buf; + char buf[NM_UTILS_INET_ADDRSTRLEN]; - if (IN6_IS_ADDR_V4MAPPED (addr)) { - buf = g_malloc (INET_ADDRSTRLEN); + if (IN6_IS_ADDR_V4MAPPED (addr)) nm_utils_inet4_ntop (addr->s6_addr32[3], buf); - } else if (!iface || !iface[0] || !IN6_IS_ADDR_LINKLOCAL (addr)) { - buf = g_malloc (INET6_ADDRSTRLEN); + else nm_utils_inet6_ntop (addr, buf); - } else { - /* Need to scope the address with %<zone-id>. Before dnsmasq 2.58, - * only '@' was supported as delimiter. Since 2.58, '@' and '%' - * are supported. Due to a bug, since 2.73 only '%' works properly - * as "server" address. - */ - buf = g_strconcat (nm_utils_inet6_ntop (addr, NULL), "%", iface, NULL); - } - return buf; + + /* Need to scope link-local addresses with %<zone-id>. Before dnsmasq 2.58, + * only '@' was supported as delimiter. Since 2.58, '@' and '%' are + * supported. Due to a bug, since 2.73 only '%' works properly as "server" + * address. + */ + return g_strdup_printf ("%s%c%s", + buf, + IN6_IS_ADDR_LINKLOCAL (addr) ? '%' : '@', + iface); } static void @@ -202,20 +272,20 @@ add_global_config (NMDnsDnsmasq *self, GVariantBuilder *dnsmasq_servers, const N } static gboolean -add_ip6_config (NMDnsDnsmasq *self, GVariantBuilder *servers, NMIP6Config *ip6, gboolean split) +add_ip6_config (NMDnsDnsmasq *self, GVariantBuilder *servers, NMIP6Config *ip6, + const char *iface, gboolean split) { const struct in6_addr *addr; char *buf = NULL; int nnameservers, i_nameserver, n, i; gboolean added = FALSE; - const char *iface; + g_return_val_if_fail (iface, FALSE); nnameservers = nm_ip6_config_get_num_nameservers (ip6); - iface = g_object_get_data (G_OBJECT (ip6), IP_CONFIG_IFACE_TAG); - g_assert (iface); - if (split) { + char **domains, **iter; + if (nnameservers == 0) return FALSE; @@ -245,11 +315,21 @@ add_ip6_config (NMDnsDnsmasq *self, GVariantBuilder *servers, NMIP6Config *ip6, } } + /* Ensure reverse-DNS works by directing queries for ip6.arpa + * domains to the split domain's nameserver. + */ + domains = get_ip6_rdns_domains (ip6); + if (domains) { + for (iter = domains; iter && *iter; iter++) + add_dnsmasq_nameserver (self, servers, buf, *iter); + g_strfreev (domains); + } + g_free (buf); } } - /* If no searches or domains, just add the namservers */ + /* If no searches or domains, just add the nameservers */ if (!added) { for (i = 0; i < nnameservers; i++) { addr = nm_ip6_config_get_nameserver (ip6, i); @@ -264,19 +344,71 @@ add_ip6_config (NMDnsDnsmasq *self, GVariantBuilder *servers, NMIP6Config *ip6, return TRUE; } +static gboolean +add_ip_config_data (NMDnsDnsmasq *self, GVariantBuilder *servers, const NMDnsIPConfigData *data) +{ + if (NM_IS_IP4_CONFIG (data->config)) { + return add_ip4_config (self, + servers, + (NMIP4Config *) data->config, + data->iface, + data->type == NM_DNS_IP_CONFIG_TYPE_VPN); + } else if (NM_IS_IP6_CONFIG (data->config)) { + return add_ip6_config (self, + servers, + (NMIP6Config *) data->config, + data->iface, + data->type == NM_DNS_IP_CONFIG_TYPE_VPN); + } else + g_return_val_if_reached (FALSE); +} + static void -dnsmasq_update_done (GObject *source, GAsyncResult *res, gpointer user_data) +dnsmasq_clear_cache_done (GDBusProxy *proxy, GAsyncResult *res, gpointer user_data) { - NMDnsDnsmasq *self = NM_DNS_DNSMASQ (user_data); - NMDnsDnsmasqPrivate *priv = NM_DNS_DNSMASQ_GET_PRIVATE (self); + NMDnsDnsmasq *self; gs_free_error GError *error = NULL; gs_unref_variant GVariant *response = NULL; - response = g_dbus_proxy_call_finish (priv->dnsmasq, res, &error); + response = g_dbus_proxy_call_finish (proxy, res, &error); + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + return; + + self = NM_DNS_DNSMASQ (user_data); + if (!response) - _LOGW ("dnsmasq update failed: %s", error->message); + _LOGW ("dnsmasq cache clear failed: %s", error->message); else - _LOGD ("dnsmasq update successful"); + _LOGD ("dnsmasq update successful, cache cleared"); +} + +static void +dnsmasq_update_done (GDBusProxy *proxy, GAsyncResult *res, gpointer user_data) +{ + NMDnsDnsmasq *self; + NMDnsDnsmasqPrivate *priv; + gs_free_error GError *error = NULL; + gs_unref_variant GVariant *response = NULL; + + response = g_dbus_proxy_call_finish (proxy, res, &error); + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + return; + + self = NM_DNS_DNSMASQ (user_data); + priv = NM_DNS_DNSMASQ_GET_PRIVATE (self); + + if (!response) + _LOGW ("dnsmasq update failed: %s", error->message); + else { + g_dbus_proxy_call (priv->dnsmasq, + "ClearCache", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + priv->update_cancellable, + (GAsyncReadyCallback) dnsmasq_clear_cache_done, + self); + } } static void @@ -290,12 +422,15 @@ send_dnsmasq_update (NMDnsDnsmasq *self) if (priv->running) { _LOGD ("trying to update dnsmasq nameservers"); + nm_clear_g_cancellable (&priv->update_cancellable); + priv->update_cancellable = g_cancellable_new (); + g_dbus_proxy_call (priv->dnsmasq, "SetServersEx", priv->set_server_ex_args, G_DBUS_CALL_FLAGS_NONE, -1, - NULL, + priv->update_cancellable, (GAsyncReadyCallback) dnsmasq_update_done, self); g_clear_pointer (&priv->set_server_ex_args, g_variant_unref); @@ -373,11 +508,16 @@ start_dnsmasq (NMDnsDnsmasq *self) NMBusManager *dbus_mgr; GDBusConnection *connection; + if (priv->running) { + /* the dnsmasq process is running. Nothing to do. */ + return; + } - if ( priv->running - || priv->dnsmasq - || priv->dnsmasq_cancellable) + if (nm_dns_plugin_child_pid ((NMDnsPlugin *) self) > 0) { + /* if we already have a child process spawned, don't do + * it again. */ return; + } dm_binary = nm_utils_find_helper ("dnsmasq", DNSMASQ_PATH, NULL); if (!dm_binary) { @@ -409,6 +549,13 @@ start_dnsmasq (NMDnsDnsmasq *self) if (!pid) return; + if ( priv->dnsmasq + || priv->dnsmasq_cancellable) { + /* we already have a proxy or are about to create it. + * We are done. */ + return; + } + dbus_mgr = nm_bus_manager_get (); g_return_if_fail (dbus_mgr); @@ -429,15 +576,12 @@ start_dnsmasq (NMDnsDnsmasq *self) static gboolean update (NMDnsPlugin *plugin, - const GSList *vpn_configs, - const GSList *dev_configs, - const GSList *other_configs, + const NMDnsIPConfigData **configs, const NMGlobalDnsConfig *global_config, const char *hostname) { NMDnsDnsmasq *self = NM_DNS_DNSMASQ (plugin); NMDnsDnsmasqPrivate *priv = NM_DNS_DNSMASQ_GET_PRIVATE (self); - const GSList *iter; GVariantBuilder servers; start_dnsmasq (self); @@ -447,28 +591,9 @@ update (NMDnsPlugin *plugin, if (global_config) add_global_config (self, &servers, global_config); else { - /* Use split DNS for VPN configs */ - for (iter = vpn_configs; iter; iter = g_slist_next (iter)) { - if (NM_IS_IP4_CONFIG (iter->data)) - add_ip4_config (self, &servers, iter->data, TRUE); - else if (NM_IS_IP6_CONFIG (iter->data)) - add_ip6_config (self, &servers, iter->data, TRUE); - } - - /* Now add interface configs without split DNS */ - for (iter = dev_configs; iter; iter = g_slist_next (iter)) { - if (NM_IS_IP4_CONFIG (iter->data)) - add_ip4_config (self, &servers, iter->data, FALSE); - else if (NM_IS_IP6_CONFIG (iter->data)) - add_ip6_config (self, &servers, iter->data, FALSE); - } - - /* And any other random configs */ - for (iter = other_configs; iter; iter = g_slist_next (iter)) { - if (NM_IS_IP4_CONFIG (iter->data)) - add_ip4_config (self, &servers, iter->data, FALSE); - else if (NM_IS_IP6_CONFIG (iter->data)) - add_ip6_config (self, &servers, iter->data, FALSE); + while (*configs) { + add_ip_config_data (self, &servers, *configs); + configs++; } } @@ -482,39 +607,23 @@ update (NMDnsPlugin *plugin, /****************************************************************/ -static const char * -dm_exit_code_to_msg (int status) -{ - if (status == 1) - return "Configuration problem"; - else if (status == 2) - return "Network access problem (address in use; permissions; etc)"; - else if (status == 3) - return "Filesystem problem (missing file/directory; permissions; etc)"; - else if (status == 4) - return "Memory allocation failure"; - else if (status == 5) - return "Other problem"; - else if (status >= 11) - return "Lease-script 'init' process failure"; - return "Unknown error"; -} - static void child_quit (NMDnsPlugin *plugin, gint status) { NMDnsDnsmasq *self = NM_DNS_DNSMASQ (plugin); + NMDnsDnsmasqPrivate *priv = NM_DNS_DNSMASQ_GET_PRIVATE (self); gboolean failed = TRUE; int err; if (WIFEXITED (status)) { err = WEXITSTATUS (status); if (err) { - _LOGW ("dnsmasq exited with error: %s (%d)", - dm_exit_code_to_msg (err), - err); - } else + _LOGW ("dnsmasq exited with error: %s", + nm_utils_dnsmasq_status_to_string (err, NULL, 0)); + } else { + _LOGD ("dnsmasq exited normally"); failed = FALSE; + } } else if (WIFSTOPPED (status)) _LOGW ("dnsmasq stopped unexpectedly with signal %d", WSTOPSIG (status)); else if (WIFSIGNALED (status)) @@ -522,6 +631,8 @@ child_quit (NMDnsPlugin *plugin, gint status) else _LOGW ("dnsmasq died from an unknown cause"); + priv->running = FALSE; + if (failed) g_signal_emit_by_name (self, NM_DNS_PLUGIN_FAILED); } @@ -559,6 +670,7 @@ dispose (GObject *object) NMDnsDnsmasqPrivate *priv = NM_DNS_DNSMASQ_GET_PRIVATE (object); nm_clear_g_cancellable (&priv->dnsmasq_cancellable); + nm_clear_g_cancellable (&priv->update_cancellable); g_clear_object (&priv->dnsmasq); diff --git a/src/dns-manager/nm-dns-manager.c b/src/dns-manager/nm-dns-manager.c index b42af167..3efd5ac1 100644 --- a/src/dns-manager/nm-dns-manager.c +++ b/src/dns-manager/nm-dns-manager.c @@ -61,23 +61,13 @@ #define DOMAIN_IS_VALID(domain) (*(domain)) #endif -G_DEFINE_TYPE (NMDnsManager, nm_dns_manager, G_TYPE_OBJECT) - -#define NM_DNS_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ - NM_TYPE_DNS_MANAGER, \ - NMDnsManagerPrivate)) - #define HASH_LEN 20 -#ifdef RESOLVCONF_PATH -#define RESOLVCONF_SELECTED -#else +#ifndef RESOLVCONF_PATH #define RESOLVCONF_PATH "/sbin/resolvconf" #endif -#ifdef NETCONFIG_PATH -#define NETCONFIG_SELECTED -#else +#ifndef NETCONFIG_PATH #define NETCONFIG_PATH "/sbin/netconfig" #endif @@ -85,7 +75,19 @@ G_DEFINE_TYPE (NMDnsManager, nm_dns_manager, G_TYPE_OBJECT) #define PLUGIN_RATELIMIT_BURST 5 #define PLUGIN_RATELIMIT_DELAY 300 -NM_DEFINE_SINGLETON_INSTANCE (NMDnsManager); +enum { + CONFIG_CHANGED, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +typedef enum { + SR_SUCCESS, + SR_NOTFOUND, + SR_ERROR +} SpawnResult; /*********************************************************************************************/ @@ -112,22 +114,17 @@ NM_DEFINE_SINGLETON_INSTANCE (NMDnsManager); /*********************************************************************************************/ typedef struct { - NMIP4Config *ip4_vpn_config; - NMIP4Config *ip4_device_config; - NMIP6Config *ip6_vpn_config; - NMIP6Config *ip6_device_config; - GSList *configs; + GPtrArray *configs; + NMDnsIPConfigData *best_conf4, *best_conf6; + gboolean need_sort; + char *hostname; guint updates_queue; guint8 hash[HASH_LEN]; /* SHA1 hash of current DNS config */ guint8 prev_hash[HASH_LEN]; /* Hash when begin_updates() was called */ - NMDnsManagerResolvConfMode resolv_conf_mode; NMDnsManagerResolvConfManager rc_manager; - char *last_mode; - bool last_immutable:1; - bool mode_initialized:1; NMDnsPlugin *plugin; NMConfig *config; @@ -141,20 +138,33 @@ typedef struct { } plugin_ratelimit; } NMDnsManagerPrivate; -enum { - CONFIG_CHANGED, +struct _NMDnsManager { + GObject parent; + NMDnsManagerPrivate _priv; +}; - LAST_SIGNAL +struct _NMDnsManagerClass { + GObjectClass parent; }; -typedef enum { - SR_SUCCESS, - SR_NOTFOUND, - SR_ERROR -} SpawnResult; +G_DEFINE_TYPE (NMDnsManager, nm_dns_manager, G_TYPE_OBJECT) -static guint signals[LAST_SIGNAL] = { 0 }; +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; \ + }) + +/*****************************************************************************/ typedef struct { GPtrArray *nameservers; @@ -166,13 +176,88 @@ typedef struct { NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_rc_manager_to_string, NMDnsManagerResolvConfManager, NM_UTILS_LOOKUP_DEFAULT_WARN (NULL), - NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE, "none"), - NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE, "file"), - NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF, "resolvconf"), - NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG, "netconfig"), - NM_UTILS_LOOKUP_ITEM_IGNORE (_NM_DNS_MANAGER_RESOLV_CONF_MAN_INTERNAL_ONLY), + NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_MANAGER_RESOLV_CONF_MAN_UNKNOWN, "unknown"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED, "unmanaged"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_MANAGER_RESOLV_CONF_MAN_IMMUTABLE, "immutable"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_MANAGER_RESOLV_CONF_MAN_SYMLINK, "symlink"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE, "file"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF, "resolvconf"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG, "netconfig"), ); +NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_config_type_to_string, NMDnsIPConfigType, + NM_UTILS_LOOKUP_DEFAULT_WARN ("<unknown>"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_IP_CONFIG_TYPE_DEFAULT, "default"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE, "best"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_IP_CONFIG_TYPE_VPN, "vpn"), +); + +static NMDnsIPConfigData * +ip_config_data_new (gpointer config, NMDnsIPConfigType type, const char *iface) +{ + NMDnsIPConfigData *data; + + data = g_slice_new0 (NMDnsIPConfigData); + data->config = g_object_ref (config); + data->iface = g_strdup (iface); + data->type = type; + + return data; +} + +static void +ip_config_data_destroy (gpointer ptr) +{ + NMDnsIPConfigData *data = ptr; + + if (!data) + return; + + g_object_unref (data->config); + g_free (data->iface); + g_slice_free (NMDnsIPConfigData, data); +} + +static gint +ip_config_data_compare (const NMDnsIPConfigData *a, const NMDnsIPConfigData *b) +{ + gboolean a_v4, b_v4; + gint a_prio, b_prio; + + a_v4 = NM_IS_IP4_CONFIG (a->config); + b_v4 = NM_IS_IP4_CONFIG (b->config); + + a_prio = a_v4 ? + nm_ip4_config_get_dns_priority ((NMIP4Config *) a->config) : + nm_ip6_config_get_dns_priority ((NMIP6Config *) a->config); + + b_prio = b_v4 ? + nm_ip4_config_get_dns_priority ((NMIP4Config *) b->config) : + nm_ip6_config_get_dns_priority ((NMIP6Config *) b->config); + + /* Configurations with lower priority value first */ + if (a_prio < b_prio) + return -1; + else if (a_prio > b_prio) + return 1; + + /* Sort also according to type */ + if (a->type > b->type) + return -1; + else if (a->type < b->type) + return 1; + + return 0; +} + +static gint +ip_config_data_ptr_compare (gconstpointer a, gconstpointer b) +{ + const NMDnsIPConfigData *const *ptr_a = a, *const *ptr_b = b; + + return ip_config_data_compare (*ptr_a, *ptr_b); +} + static void add_string_item (GPtrArray *array, const char *str) { @@ -257,12 +342,9 @@ merge_one_ip4_config (NMResolvConfData *rc, NMIP4Config *src) } static void -merge_one_ip6_config (NMResolvConfData *rc, NMIP6Config *src) +merge_one_ip6_config (NMResolvConfData *rc, NMIP6Config *src, const char *iface) { guint32 num, num_domains, num_searches, i; - const char *iface; - - iface = g_object_get_data (G_OBJECT (src), IP_CONFIG_IFACE_TAG); num = nm_ip6_config_get_num_nameservers (src); for (i = 0; i < num; i++) { @@ -276,7 +358,7 @@ merge_one_ip6_config (NMResolvConfData *rc, NMIP6Config *src) nm_utils_inet4_ntop (addr->s6_addr32[3], buf); else { nm_utils_inet6_ntop (addr, buf); - if (iface && IN6_IS_ADDR_LINKLOCAL (addr)) { + if (IN6_IS_ADDR_LINKLOCAL (addr)) { g_strlcat (buf, "%", sizeof (buf)); g_strlcat (buf, iface, sizeof (buf)); } @@ -316,6 +398,19 @@ merge_one_ip6_config (NMResolvConfData *rc, NMIP6Config *src) } } +static void +merge_one_ip_config_data (NMDnsManager *self, + NMResolvConfData *rc, + NMDnsIPConfigData *data) +{ + if (NM_IS_IP4_CONFIG (data->config)) + merge_one_ip4_config (rc, (NMIP4Config *) data->config); + else if (NM_IS_IP6_CONFIG (data->config)) + merge_one_ip6_config (rc, (NMIP6Config *) data->config, data->iface); + else + g_return_if_reached (); +} + static GPid run_netconfig (NMDnsManager *self, GError **error, gint *stdin_fd) { @@ -470,12 +565,16 @@ write_resolv_conf_contents (FILE *f, const char *content, GError **error) { + int errsv; + if (fprintf (f, "%s", content) < 0) { + errsv = errno; g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED, "Could not write " _PATH_RESCONF ": %s", - g_strerror (errno)); + g_strerror (errsv)); + errno = errsv; return FALSE; } @@ -574,6 +673,9 @@ update_resolv_conf (NMDnsManager *self, gboolean success; gs_free char *content = NULL; SpawnResult write_file_result = SR_SUCCESS; + int errsv; + const char *rc_path = _PATH_RESCONF; + nm_auto_free char *rc_path_real = NULL; /* If we are not managing /etc/resolv.conf and it points to * MY_RESOLV_CONF, don't write the private DNS configuration to @@ -582,12 +684,12 @@ update_resolv_conf (NMDnsManager *self, * * This is the only situation, where we don't try to update our * internal resolv.conf file. */ - if (rc_manager == _NM_DNS_MANAGER_RESOLV_CONF_MAN_INTERNAL_ONLY) { + if (rc_manager == NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED) { gs_free char *path = g_file_read_link (_PATH_RESCONF, NULL); if (g_strcmp0 (path, MY_RESOLV_CONF) == 0) { - _LOGD ("not updating " MY_RESOLV_CONF - " since it points to " _PATH_RESCONF); + _LOGD ("update-resolv-conf: not updating " _PATH_RESCONF + " since it points to " MY_RESOLV_CONF); return SR_SUCCESS; } } @@ -595,29 +697,50 @@ update_resolv_conf (NMDnsManager *self, content = create_resolv_conf (searches, nameservers, options); if (rc_manager == NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE) { + GError *local = NULL; + + rc_path_real = realpath (rc_path, NULL); + if (rc_path_real) + rc_path = rc_path_real; + /* we first write to /etc/resolv.conf directly. If that fails, * we still continue to write to runstatedir but remember the * error. */ - if (!g_file_set_contents (_PATH_RESCONF, content, -1, error)) { + if (!g_file_set_contents (rc_path, content, -1, &local)) { + _LOGT ("update-resolv-conf: write to %s failed (rc-manager=%s, %s)", + rc_path, _rc_manager_to_string (rc_manager), local->message); write_file_result = SR_ERROR; + g_propagate_error (error, local); error = NULL; + } else { + _LOGT ("update-resolv-conf: write to %s succeeded (rc-manager=%s)", + rc_path, _rc_manager_to_string (rc_manager)); } } if ((f = fopen (MY_RESOLV_CONF_TMP, "w")) == NULL) { + errsv = errno; g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED, "Could not open %s: %s", MY_RESOLV_CONF_TMP, - g_strerror (errno)); + g_strerror (errsv)); + _LOGT ("update-resolv-conf: open temporary file %s failed (%s)", + MY_RESOLV_CONF_TMP, g_strerror (errsv)); return SR_ERROR; } success = write_resolv_conf_contents (f, content, error); + if (!success) { + errsv = errno; + _LOGT ("update-resolv-conf: write temporary file %s failed (%s)", + MY_RESOLV_CONF_TMP, g_strerror (errsv)); + } if (fclose (f) < 0) { if (success) { + errsv = errno; /* only set an error here if write_resolv_conf() was successful, * since its error is more important. */ @@ -626,39 +749,66 @@ update_resolv_conf (NMDnsManager *self, NM_MANAGER_ERROR_FAILED, "Could not close %s: %s", MY_RESOLV_CONF_TMP, - g_strerror (errno)); + g_strerror (errsv)); + _LOGT ("update-resolv-conf: close temporary file %s failed (%s)", + MY_RESOLV_CONF_TMP, g_strerror (errsv)); } return SR_ERROR; } else if (!success) return SR_ERROR; if (rename (MY_RESOLV_CONF_TMP, MY_RESOLV_CONF) < 0) { + errsv = errno; g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED, "Could not replace %s: %s", MY_RESOLV_CONF, g_strerror (errno)); + _LOGT ("update-resolv-conf: failed to rename temporary file %s to %s (%s)", + MY_RESOLV_CONF_TMP, MY_RESOLV_CONF, g_strerror (errsv)); return SR_ERROR; } - if (rc_manager == NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE) + if (rc_manager == NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE) { + _LOGT ("update-resolv-conf: write internal file %s succeeded (rc-manager=%s)", + rc_path, _rc_manager_to_string (rc_manager)); return write_file_result; + } - if (rc_manager != NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE) + if (rc_manager != NM_DNS_MANAGER_RESOLV_CONF_MAN_SYMLINK) { + _LOGT ("update-resolv-conf: write internal file %s succeeded", MY_RESOLV_CONF); return SR_SUCCESS; + } /* A symlink pointing to NM's own resolv.conf (MY_RESOLV_CONF) is always * overwritten to ensure that changes are indicated with inotify. Symlinks * pointing to any other file are never overwritten. */ - if (lstat (_PATH_RESCONF, &st) != -1) { + if (lstat (_PATH_RESCONF, &st) != 0) { + errsv = errno; + if (errsv != ENOENT) { + /* NM cannot read /etc/resolv.conf */ + _LOGT ("update-resolv-conf: write internal file %s succeeded but lstat(%s) failed (%s)", + MY_RESOLV_CONF, _PATH_RESCONF, g_strerror (errsv)); + g_set_error (error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_FAILED, + "Could not lstat %s: %s", + _PATH_RESCONF, + g_strerror (errsv)); + return SR_ERROR; + } + } else { if (S_ISLNK (st.st_mode)) { if (stat (_PATH_RESCONF, &st) != -1) { gs_free char *path = g_file_read_link (_PATH_RESCONF, NULL); - if (g_strcmp0 (path, MY_RESOLV_CONF) != 0) { + if (!path || !nm_streq (path, MY_RESOLV_CONF)) { /* It's not NM's symlink; do nothing */ + _LOGT ("update-resolv-conf: write internal file %s succeeded " + "but don't update %s as it points to %s", + MY_RESOLV_CONF, _PATH_RESCONF, path ?: ""); return SR_SUCCESS; } @@ -669,56 +819,64 @@ update_resolv_conf (NMDnsManager *self, * some other program is probably managing resolv.conf and * NM should not touch it. */ + _LOGT ("update-resolv-conf: write internal file %s succeeded " + "but don't update %s as the symlinks points somewhere else", + MY_RESOLV_CONF, _PATH_RESCONF); return SR_SUCCESS; } } - } else if (errno != ENOENT) { - /* NM cannot read /etc/resolv.conf */ - g_set_error (error, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_FAILED, - "Could not lstat %s: %s", - _PATH_RESCONF, - g_strerror (errno)); - return SR_ERROR; } /* By this point, either /etc/resolv.conf does not exist, is a regular * file, or is a symlink already owned by NM. In all cases /etc/resolv.conf * is replaced with a symlink pointing to NM's resolv.conf in /var/run/. */ - if (unlink (RESOLV_CONF_TMP) == -1 && errno != ENOENT) { + if ( unlink (RESOLV_CONF_TMP) != 0 + && ((errsv = errno) != ENOENT)) { g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED, "Could not unlink %s: %s", RESOLV_CONF_TMP, - g_strerror (errno)); + g_strerror (errsv)); + _LOGT ("update-resolv-conf: write internal file %s succeeded " + "but canot delete temporary file %s: %s", + MY_RESOLV_CONF, RESOLV_CONF_TMP, g_strerror (errsv)); return SR_ERROR; } if (symlink (MY_RESOLV_CONF, RESOLV_CONF_TMP) == -1) { + errsv = errno; g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED, "Could not create symlink %s pointing to %s: %s", RESOLV_CONF_TMP, MY_RESOLV_CONF, - g_strerror (errno)); + g_strerror (errsv)); + _LOGT ("update-resolv-conf: write internal file %s succeeded " + "but failed to symlink %s: %s", + MY_RESOLV_CONF, RESOLV_CONF_TMP, g_strerror (errsv)); return SR_ERROR; } if (rename (RESOLV_CONF_TMP, _PATH_RESCONF) == -1) { + errsv = errno; g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED, "Could not rename %s to %s: %s", RESOLV_CONF_TMP, _PATH_RESCONF, - g_strerror (errno)); + g_strerror (errsv)); + _LOGT ("update-resolv-conf: write internal file %s succeeded " + "but failed to rename temporary symlink %s to %s: %s", + MY_RESOLV_CONF, RESOLV_CONF_TMP, _PATH_RESCONF, g_strerror (errsv)); return SR_ERROR; } + _LOGT ("update-resolv-conf: write internal file %s succeeded and update symlink %s", + MY_RESOLV_CONF, _PATH_RESCONF); return SR_SUCCESS; } @@ -727,79 +885,29 @@ compute_hash (NMDnsManager *self, const NMGlobalDnsConfig *global, guint8 buffer { NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); GChecksum *sum; - GSList *iter; gsize len = HASH_LEN; + guint i; sum = g_checksum_new (G_CHECKSUM_SHA1); g_assert (len == g_checksum_type_get_length (G_CHECKSUM_SHA1)); if (global) nm_global_dns_config_update_checksum (global, sum); + else { + for (i = 0; i < priv->configs->len; i++) { + NMDnsIPConfigData *data = priv->configs->pdata[i]; - if (priv->ip4_vpn_config) - nm_ip4_config_hash (priv->ip4_vpn_config, sum, TRUE); - if (priv->ip4_device_config) - nm_ip4_config_hash (priv->ip4_device_config, sum, TRUE); - - if (priv->ip6_vpn_config) - nm_ip6_config_hash (priv->ip6_vpn_config, sum, TRUE); - if (priv->ip6_device_config) - nm_ip6_config_hash (priv->ip6_device_config, sum, TRUE); - - /* add any other configs we know about */ - for (iter = priv->configs; iter; iter = g_slist_next (iter)) { - if (NM_IN_SET (iter->data, priv->ip4_vpn_config, - priv->ip4_device_config, - priv->ip6_vpn_config, - priv->ip6_device_config)) - continue; - - if (NM_IS_IP4_CONFIG (iter->data)) - nm_ip4_config_hash (NM_IP4_CONFIG (iter->data), sum, TRUE); - else if (NM_IS_IP6_CONFIG (iter->data)) - nm_ip6_config_hash (NM_IP6_CONFIG (iter->data), sum, TRUE); + if (NM_IS_IP4_CONFIG (data->config)) + nm_ip4_config_hash ((NMIP4Config *) data->config, sum, TRUE); + else if (NM_IS_IP6_CONFIG (data->config)) + nm_ip6_config_hash ((NMIP6Config *) data->config, sum, TRUE); + } } g_checksum_get_digest (sum, buffer, &len); g_checksum_free (sum); } -static void -build_plugin_config_lists (NMDnsManager *self, - GSList **out_vpn_configs, - GSList **out_dev_configs, - GSList **out_other_configs) -{ - NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); - GSList *iter; - - g_return_if_fail (out_vpn_configs && !*out_vpn_configs); - g_return_if_fail (out_dev_configs && !*out_dev_configs); - g_return_if_fail (out_other_configs && !*out_other_configs); - - /* Build up config lists for plugins; we use the raw configs here, not the - * merged information that we write to resolv.conf so that the plugins can - * still use the domain information in each config to provide split DNS if - * they want to. - */ - if (priv->ip4_vpn_config) - *out_vpn_configs = g_slist_append (*out_vpn_configs, priv->ip4_vpn_config); - if (priv->ip6_vpn_config) - *out_vpn_configs = g_slist_append (*out_vpn_configs, priv->ip6_vpn_config); - if (priv->ip4_device_config) - *out_dev_configs = g_slist_append (*out_dev_configs, priv->ip4_device_config); - if (priv->ip6_device_config) - *out_dev_configs = g_slist_append (*out_dev_configs, priv->ip6_device_config); - - for (iter = priv->configs; iter; iter = g_slist_next (iter)) { - if (!NM_IN_SET (iter->data, priv->ip4_vpn_config, - priv->ip4_device_config, - priv->ip6_vpn_config, - priv->ip6_device_config)) - *out_other_configs = g_slist_append (*out_other_configs, iter->data); - } -} - static gboolean merge_global_dns_config (NMResolvConfData *rc, NMGlobalDnsConfig *global_conf) { @@ -832,6 +940,44 @@ merge_global_dns_config (NMResolvConfData *rc, NMGlobalDnsConfig *global_conf) return TRUE; } +static const char * +get_nameserver_list (void *config, GString **str) +{ + NMIP4Config *ip4; + NMIP6Config *ip6; + guint num, i; + + nm_assert (str); + + if (*str) + g_string_truncate (*str, 0); + else + *str = g_string_sized_new (64); + + if (NM_IS_IP4_CONFIG (config)) { + ip4 = (NMIP4Config *) config; + num = nm_ip4_config_get_num_nameservers (ip4); + for (i = 0; i < num; i++) { + g_string_append (*str, + nm_utils_inet4_ntop (nm_ip4_config_get_nameserver (ip4, i), + NULL)); + g_string_append_c (*str, ' '); + } + } else if (NM_IS_IP6_CONFIG (config)) { + ip6 = (NMIP6Config *) config; + num = nm_ip6_config_get_num_nameservers (ip6); + for (i = 0; i < num; i++) { + g_string_append (*str, + nm_utils_inet6_ntop (nm_ip6_config_get_nameserver (ip6, i), + NULL)); + g_string_append_c (*str, ' '); + } + } else + g_return_val_if_reached (NULL); + + return (*str)->str; +} + static gboolean update_dns (NMDnsManager *self, gboolean no_caching, @@ -839,7 +985,6 @@ update_dns (NMDnsManager *self, { NMDnsManagerPrivate *priv; NMResolvConfData rc; - GSList *iter; const char *nis_domain = NULL; char **searches = NULL; char **options = NULL; @@ -851,13 +996,16 @@ update_dns (NMDnsManager *self, SpawnResult result = SR_ERROR; NMConfigData *data; NMGlobalDnsConfig *global_config; + gs_free NMDnsIPConfigData **plugin_confs = NULL; + nm_auto_free_gstring GString *tmp_gstring = NULL; g_return_val_if_fail (!error || !*error, FALSE); priv = NM_DNS_MANAGER_GET_PRIVATE (self); nm_clear_g_source (&priv->plugin_ratelimit.timer); - if (priv->resolv_conf_mode == NM_DNS_MANAGER_RESOLV_CONF_UNMANAGED) { + if (NM_IN_SET (priv->rc_manager, NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED, + NM_DNS_MANAGER_RESOLV_CONF_MAN_IMMUTABLE)) { update = FALSE; _LOGD ("update-dns: not updating resolv.conf"); } else { @@ -868,6 +1016,11 @@ update_dns (NMDnsManager *self, data = nm_config_get_data (priv->config); global_config = nm_config_data_get_global_dns_config (data); + if (priv->need_sort) { + g_ptr_array_sort (priv->configs, ip_config_data_ptr_compare); + priv->need_sort = FALSE; + } + /* Update hash with config we're applying */ compute_hash (self, global_config, priv->hash); @@ -880,34 +1033,41 @@ update_dns (NMDnsManager *self, if (global_config) merge_global_dns_config (&rc, global_config); else { - if (priv->ip4_vpn_config) - merge_one_ip4_config (&rc, priv->ip4_vpn_config); - if (priv->ip4_device_config) - merge_one_ip4_config (&rc, priv->ip4_device_config); - - if (priv->ip6_vpn_config) - merge_one_ip6_config (&rc, priv->ip6_vpn_config); - if (priv->ip6_device_config) - merge_one_ip6_config (&rc, priv->ip6_device_config); - - for (iter = priv->configs; iter; iter = g_slist_next (iter)) { - if (NM_IN_SET (iter->data, priv->ip4_vpn_config, - priv->ip4_device_config, - priv->ip6_vpn_config, - priv->ip6_device_config)) - continue; + int prio, prev_prio = 0; + NMDnsIPConfigData *current; + gboolean skip = FALSE, v4; + + plugin_confs = g_new (NMDnsIPConfigData *, priv->configs->len + 1); + + for (i = 0; i < priv->configs->len; i++) { + current = priv->configs->pdata[i]; + v4 = NM_IS_IP4_CONFIG (current->config); + + prio = v4 ? + nm_ip4_config_get_dns_priority ((NMIP4Config *) current->config) : + nm_ip6_config_get_dns_priority ((NMIP6Config *) current->config); - if (NM_IS_IP4_CONFIG (iter->data)) { - NMIP4Config *config = NM_IP4_CONFIG (iter->data); + if (prev_prio < 0 && prio != prev_prio) { + skip = TRUE; + plugin_confs[i] = NULL; + } + + prev_prio = prio; - merge_one_ip4_config (&rc, config); - } else if (NM_IS_IP6_CONFIG (iter->data)) { - NMIP6Config *config = NM_IP6_CONFIG (iter->data); + _LOGT ("config: %8d %-7s v%c %-16s %s: %s", + prio, + _config_type_to_string (current->type), + v4 ? '4' : '6', + current->iface, + skip ? "<SKIP>" : "", + get_nameserver_list (current->config, &tmp_gstring)); - merge_one_ip6_config (&rc, config); - } else - g_assert_not_reached (); + if (!skip) { + merge_one_ip_config_data (self, &rc, current); + plugin_confs[i] = current; + } } + plugin_confs[i] = NULL; } /* If the hostname is a FQDN ("dcbw.example.com"), then add the domain part of it @@ -970,7 +1130,6 @@ update_dns (NMDnsManager *self, if (priv->plugin) { NMDnsPlugin *plugin = priv->plugin; const char *plugin_name = nm_dns_plugin_get_name (plugin); - GSList *vpn_configs = NULL, *dev_configs = NULL, *other_configs = NULL; if (nm_dns_plugin_is_caching (plugin)) { if (no_caching) { @@ -981,14 +1140,9 @@ update_dns (NMDnsManager *self, caching = TRUE; } - if (!global_config) - build_plugin_config_lists (self, &vpn_configs, &dev_configs, &other_configs); - _LOGD ("update-dns: updating plugin %s", plugin_name); if (!nm_dns_plugin_update (plugin, - vpn_configs, - dev_configs, - other_configs, + (const NMDnsIPConfigData **) plugin_confs, global_config, priv->hostname)) { _LOGW ("update-dns: plugin %s update failed", plugin_name); @@ -998,9 +1152,6 @@ update_dns (NMDnsManager *self, */ caching = FALSE; } - g_slist_free (vpn_configs); - g_slist_free (dev_configs); - g_slist_free (other_configs); skip: ; @@ -1019,7 +1170,7 @@ update_dns (NMDnsManager *self, if (update) { switch (priv->rc_manager) { - case NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE: + case NM_DNS_MANAGER_RESOLV_CONF_MAN_SYMLINK: case NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE: result = update_resolv_conf (self, searches, nameservers, options, error, priv->rc_manager); resolv_conf_updated = TRUE; @@ -1038,7 +1189,7 @@ update_dns (NMDnsManager *self, if (result == SR_NOTFOUND) { _LOGD ("update-dns: program not available, writing to resolv.conf"); g_clear_error (error); - result = update_resolv_conf (self, searches, nameservers, options, error, NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE); + result = update_resolv_conf (self, searches, nameservers, options, error, NM_DNS_MANAGER_RESOLV_CONF_MAN_SYMLINK); resolv_conf_updated = TRUE; } } @@ -1046,7 +1197,7 @@ update_dns (NMDnsManager *self, /* Unless we've already done it, update private resolv.conf in NMRUNDIR ignoring any errors */ if (!resolv_conf_updated) - update_resolv_conf (self, searches, nameservers, options, NULL, _NM_DNS_MANAGER_RESOLV_CONF_MAN_INTERNAL_ONLY); + update_resolv_conf (self, searches, nameservers, options, NULL, NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED); /* signal that resolv.conf was changed */ if (update && result == SR_SUCCESS) @@ -1124,150 +1275,148 @@ plugin_child_quit (NMDnsPlugin *plugin, int exit_status, gpointer user_data) plugin_child_quit_update_dns (self); } -gboolean -nm_dns_manager_add_ip4_config (NMDnsManager *self, - const char *iface, - NMIP4Config *config, - NMDnsIPConfigType cfg_type) +static void +ip_config_dns_priority_changed (gpointer config, + GParamSpec *pspec, + NMDnsManager *self) { - NMDnsManagerPrivate *priv; - GError *error = NULL; - - g_return_val_if_fail (self != NULL, FALSE); - g_return_val_if_fail (config != NULL, FALSE); - - priv = NM_DNS_MANAGER_GET_PRIVATE (self); - - g_object_set_data_full (G_OBJECT (config), IP_CONFIG_IFACE_TAG, g_strdup (iface), g_free); - - switch (cfg_type) { - case NM_DNS_IP_CONFIG_TYPE_VPN: - priv->ip4_vpn_config = config; - break; - case NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE: - priv->ip4_device_config = config; - break; - default: - break; - } + NM_DNS_MANAGER_GET_PRIVATE (self)->need_sort = TRUE; +} - /* Don't allow the same zone added twice */ - if (!g_slist_find (priv->configs, config)) - priv->configs = g_slist_append (priv->configs, g_object_ref (config)); +static void +forget_data (NMDnsManager *self, NMDnsIPConfigData *data) +{ + NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); - if (!priv->updates_queue && !update_dns (self, FALSE, &error)) { - _LOGW ("could not commit DNS changes: %s", error->message); - g_clear_error (&error); - } + if (data == priv->best_conf4) + priv->best_conf4 = NULL; + else if (data == priv->best_conf6) + priv->best_conf6 = NULL; - return TRUE; + g_signal_handlers_disconnect_by_func (data->config, ip_config_dns_priority_changed, self); } -gboolean -nm_dns_manager_remove_ip4_config (NMDnsManager *self, NMIP4Config *config) +static gboolean +nm_dns_manager_add_ip_config (NMDnsManager *self, + const char *iface, + gpointer config, + NMDnsIPConfigType cfg_type) { NMDnsManagerPrivate *priv; GError *error = NULL; + NMDnsIPConfigData *data; + gboolean v4 = NM_IS_IP4_CONFIG (config); + guint i; - g_return_val_if_fail (self != NULL, FALSE); - g_return_val_if_fail (config != NULL, FALSE); + g_return_val_if_fail (NM_IS_DNS_MANAGER (self), FALSE); + g_return_val_if_fail (config, FALSE); + g_return_val_if_fail (iface && iface[0], FALSE); priv = NM_DNS_MANAGER_GET_PRIVATE (self); - /* Can't remove it if it wasn't in the list to begin with */ - if (!g_slist_find (priv->configs, config)) - return FALSE; - - priv->configs = g_slist_remove (priv->configs, config); - - if (config == priv->ip4_vpn_config) - priv->ip4_vpn_config = NULL; - if (config == priv->ip4_device_config) - priv->ip4_device_config = NULL; + for (i = 0; i < priv->configs->len; i++) { + data = priv->configs->pdata[i]; + if (data->config == config) { + if ( nm_streq (data->iface, iface) + && data->type == cfg_type) + return FALSE; + else { + forget_data (self, data); + g_ptr_array_remove_index_fast (priv->configs, i); + break; + } + } + } - g_object_unref (config); + data = ip_config_data_new (config, cfg_type, iface); + g_ptr_array_add (priv->configs, data); + g_signal_connect (config, + v4 ? + "notify::" NM_IP4_CONFIG_DNS_PRIORITY : + "notify::" NM_IP6_CONFIG_DNS_PRIORITY, + (GCallback) ip_config_dns_priority_changed, self); + priv->need_sort = TRUE; + + if (cfg_type == NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE) { + /* Only one best-device per IP version is allowed */ + if (v4) { + if (priv->best_conf4) + priv->best_conf4->type = NM_DNS_IP_CONFIG_TYPE_DEFAULT; + priv->best_conf4 = data; + } else { + if (priv->best_conf6) + priv->best_conf6->type = NM_DNS_IP_CONFIG_TYPE_DEFAULT; + priv->best_conf6 = data; + } + } if (!priv->updates_queue && !update_dns (self, FALSE, &error)) { _LOGW ("could not commit DNS changes: %s", error->message); g_clear_error (&error); } - g_object_set_data (G_OBJECT (config), IP_CONFIG_IFACE_TAG, NULL); - return TRUE; } gboolean +nm_dns_manager_add_ip4_config (NMDnsManager *self, + const char *iface, + NMIP4Config *config, + NMDnsIPConfigType cfg_type) +{ + return nm_dns_manager_add_ip_config (self, iface, config, cfg_type); +} + +gboolean nm_dns_manager_add_ip6_config (NMDnsManager *self, const char *iface, NMIP6Config *config, NMDnsIPConfigType cfg_type) { + return nm_dns_manager_add_ip_config (self, iface, config, cfg_type); +} + +static gboolean +nm_dns_manager_remove_ip_config (NMDnsManager *self, gpointer config) +{ NMDnsManagerPrivate *priv; GError *error = NULL; + NMDnsIPConfigData *data; + guint i; - g_return_val_if_fail (self != NULL, FALSE); - g_return_val_if_fail (config != NULL, FALSE); + g_return_val_if_fail (NM_IS_DNS_MANAGER (self), FALSE); + g_return_val_if_fail (config, FALSE); priv = NM_DNS_MANAGER_GET_PRIVATE (self); - g_object_set_data_full (G_OBJECT (config), IP_CONFIG_IFACE_TAG, g_strdup (iface), g_free); + for (i = 0; i < priv->configs->len; i++) { + data = priv->configs->pdata[i]; - switch (cfg_type) { - case NM_DNS_IP_CONFIG_TYPE_VPN: - priv->ip6_vpn_config = config; - break; - case NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE: - priv->ip6_device_config = config; - break; - default: - break; - } + if (data->config == config) { + forget_data (self, data); + g_ptr_array_remove_index (priv->configs, i); - /* Don't allow the same zone added twice */ - if (!g_slist_find (priv->configs, config)) - priv->configs = g_slist_append (priv->configs, g_object_ref (config)); + if (!priv->updates_queue && !update_dns (self, FALSE, &error)) { + _LOGW ("could not commit DNS changes: %s", error->message); + g_clear_error (&error); + } - if (!priv->updates_queue && !update_dns (self, FALSE, &error)) { - _LOGW ("could not commit DNS changes: %s", error->message); - g_clear_error (&error); + return TRUE; + } } + return FALSE; +} - return TRUE; +gboolean +nm_dns_manager_remove_ip4_config (NMDnsManager *self, NMIP4Config *config) +{ + return nm_dns_manager_remove_ip_config (self, config); } gboolean nm_dns_manager_remove_ip6_config (NMDnsManager *self, NMIP6Config *config) { - NMDnsManagerPrivate *priv; - GError *error = NULL; - - g_return_val_if_fail (self != NULL, FALSE); - g_return_val_if_fail (config != NULL, FALSE); - - priv = NM_DNS_MANAGER_GET_PRIVATE (self); - - /* Can't remove it if it wasn't in the list to begin with */ - if (!g_slist_find (priv->configs, config)) - return FALSE; - - priv->configs = g_slist_remove (priv->configs, config); - - if (config == priv->ip6_vpn_config) - priv->ip6_vpn_config = NULL; - if (config == priv->ip6_device_config) - priv->ip6_device_config = NULL; - - g_object_unref (config); - - if (!priv->updates_queue && !update_dns (self, FALSE, &error)) { - _LOGW ("could not commit DNS changes: %s", error->message); - g_clear_error (&error); - } - - g_object_set_data (G_OBJECT (config), IP_CONFIG_IFACE_TAG, NULL); - - return TRUE; + return nm_dns_manager_remove_ip_config (self, config); } void @@ -1308,10 +1457,21 @@ nm_dns_manager_set_hostname (NMDnsManager *self, } } -NMDnsManagerResolvConfMode -nm_dns_manager_get_resolv_conf_mode (NMDnsManager *self) +gboolean +nm_dns_manager_get_resolv_conf_explicit (NMDnsManager *self) { - return NM_DNS_MANAGER_GET_PRIVATE (self)->resolv_conf_mode; + NMDnsManagerPrivate *priv; + + g_return_val_if_fail (NM_IS_DNS_MANAGER (self), FALSE); + + priv = NM_DNS_MANAGER_GET_PRIVATE (self); + + if ( NM_IN_SET (priv->rc_manager, NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED, + NM_DNS_MANAGER_RESOLV_CONF_MAN_IMMUTABLE) + || priv->plugin) + return FALSE; + + return TRUE; } void @@ -1344,6 +1504,11 @@ nm_dns_manager_end_updates (NMDnsManager *self, const char *func) priv = NM_DNS_MANAGER_GET_PRIVATE (self); g_return_if_fail (priv->updates_queue > 0); + if (priv->need_sort) { + g_ptr_array_sort (priv->configs, ip_config_data_ptr_compare); + priv->need_sort = FALSE; + } + compute_hash (self, nm_config_data_get_global_dns_config (nm_config_get_data (priv->config)), new); changed = (memcmp (new, priv->prev_hash, sizeof (new)) != 0) ? TRUE : FALSE; _LOGD ("(%s): DNS configuration %s", func, changed ? "changed" : "did not change"); @@ -1366,122 +1531,153 @@ nm_dns_manager_end_updates (NMDnsManager *self, const char *func) /******************************************************************/ -static bool -_get_resconf_immutable (int *immutable_cached) +static gboolean +_clear_plugin (NMDnsManager *self) +{ + NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); + + if (priv->plugin) { + g_signal_handlers_disconnect_by_func (priv->plugin, plugin_failed, self); + g_signal_handlers_disconnect_by_func (priv->plugin, plugin_child_quit, self); + nm_dns_plugin_stop (priv->plugin); + g_clear_object (&priv->plugin); + return TRUE; + } + priv->plugin_ratelimit.ts = 0; + nm_clear_g_source (&priv->plugin_ratelimit.timer); + return FALSE; +} + +static NMDnsManagerResolvConfManager +_check_resconf_immutable (NMDnsManagerResolvConfManager rc_manager) { + struct stat st; int fd, flags; - int immutable; + bool immutable = FALSE; + + switch (rc_manager) { + case NM_DNS_MANAGER_RESOLV_CONF_MAN_UNKNOWN: + case NM_DNS_MANAGER_RESOLV_CONF_MAN_IMMUTABLE: + nm_assert_not_reached (); + /* fall-through */ + case NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED: + return NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED; + default: + + if (lstat (_PATH_RESCONF, &st) != 0) + return rc_manager; + + if (S_ISLNK (st.st_mode)) { + /* only regular files and directories can have extended file attributes. */ + switch (rc_manager) { + case NM_DNS_MANAGER_RESOLV_CONF_MAN_SYMLINK: + /* we don't care whether the link-target is immutable. + * If the symlink points to another file, rc-manager=symlink anyway backs off. + * Otherwise, we would only check whether our internal resolv.conf is immutable. */ + return NM_DNS_MANAGER_RESOLV_CONF_MAN_SYMLINK; + case NM_DNS_MANAGER_RESOLV_CONF_MAN_UNKNOWN: + case NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED: + case NM_DNS_MANAGER_RESOLV_CONF_MAN_IMMUTABLE: + nm_assert_not_reached (); + /* fall-through */ + case NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE: + case NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF: + case NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG: + break; + } + } - immutable = *immutable_cached; - if (!NM_IN_SET (immutable, FALSE, TRUE)) { - immutable = FALSE; fd = open (_PATH_RESCONF, O_RDONLY); if (fd != -1) { if (ioctl (fd, FS_IOC_GETFLAGS, &flags) != -1) immutable = NM_FLAGS_HAS (flags, FS_IMMUTABLE_FL); close (fd); } - *immutable_cached = immutable; + return immutable ? NM_DNS_MANAGER_RESOLV_CONF_MAN_IMMUTABLE : rc_manager; } - return immutable; } NM_DEFINE_SINGLETON_GETTER (NMDnsManager, nm_dns_manager_get, NM_TYPE_DNS_MANAGER); static void -init_resolv_conf_mode (NMDnsManager *self) +init_resolv_conf_mode (NMDnsManager *self, gboolean force_reload_plugin) { NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); - const char *mode, *mode_unknown; - int immutable = -1; + NMDnsManagerResolvConfManager rc_manager; + const char *mode; + gboolean plugin_changed = FALSE; mode = nm_config_data_get_dns_mode (nm_config_get_data (priv->config)); - if ( priv->mode_initialized - && nm_streq0 (mode, priv->last_mode) - && ( nm_streq0 (mode, "none") - || priv->last_immutable == _get_resconf_immutable (&immutable))) { - /* we call init_resolv_conf_mode() on every SIGHUP to possibly reload - * when either "mode" or "immutable" changed. However, we don't want to - * re-create the plugin, when the paramters didn't actually change. So - * detect that we would recreate the same plugin and return early. */ - return; - } - - priv->mode_initialized = TRUE; - g_free (priv->last_mode); - priv->last_mode = g_strdup (mode); - priv->last_immutable = FALSE; - g_clear_object (&priv->plugin); - priv->resolv_conf_mode = NM_DNS_MANAGER_RESOLV_CONF_UNMANAGED; - - if (nm_streq0 (mode, "none")) { - _LOGI ("%s%s", "set resolv-conf-mode: ", "none"); - return; + if (nm_streq0 (mode, "none")) + rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED; + else { + const char *man; + + rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_UNKNOWN; + man = nm_config_data_get_rc_manager (nm_config_get_data (priv->config)); + +again: + if (!man) { + /* nop */ + } else if (NM_IN_STRSET (man, "symlink", "none")) + rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_SYMLINK; + else if (nm_streq (man, "file")) + rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE; + else if (nm_streq (man, "resolvconf")) + rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF; + else if (nm_streq (man, "netconfig")) + rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG; + else if (nm_streq (man, "unmanaged")) + rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED; + + if (rc_manager == NM_DNS_MANAGER_RESOLV_CONF_MAN_UNKNOWN) { + if (man) { + _LOGW ("init: unknown resolv.conf manager \"%s\", fallback to \"%s\"", + man, ""NM_CONFIG_DEFAULT_DNS_RC_MANAGER); + } + man = ""NM_CONFIG_DEFAULT_DNS_RC_MANAGER; + rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_SYMLINK; + goto again; + } } - priv->last_immutable = _get_resconf_immutable (&immutable); + rc_manager = _check_resconf_immutable (rc_manager); - if (NM_IN_STRSET (mode, "dnsmasq", "unbound")) { - if (!immutable) - priv->resolv_conf_mode = NM_DNS_MANAGER_RESOLV_CONF_PROXY; - if (nm_streq (mode, "dnsmasq")) + if (nm_streq0 (mode, "dnsmasq")) { + if (force_reload_plugin || !NM_IS_DNS_DNSMASQ (priv->plugin)) { + _clear_plugin (self); priv->plugin = nm_dns_dnsmasq_new (); - else + plugin_changed = TRUE; + } + } else if (nm_streq0 (mode, "unbound")) { + if (force_reload_plugin || !NM_IS_DNS_UNBOUND (priv->plugin)) { + _clear_plugin (self); priv->plugin = nm_dns_unbound_new (); + plugin_changed = TRUE; + } + } else { + if (!NM_IN_STRSET (mode, "none", "default")) { + if (mode) + _LOGW ("init: unknown dns mode '%s'", mode); + mode = "default"; + } + if (_clear_plugin (self)) + plugin_changed = TRUE; + } + if (plugin_changed && priv->plugin) { g_signal_connect (priv->plugin, NM_DNS_PLUGIN_FAILED, G_CALLBACK (plugin_failed), self); g_signal_connect (priv->plugin, NM_DNS_PLUGIN_CHILD_QUIT, G_CALLBACK (plugin_child_quit), self); - - _NMLOG (immutable ? LOGL_WARN : LOGL_INFO, - "%s%s%s%s%s%s", - "set resolv-conf-mode: ", - immutable ? "none" : mode, - ", plugin=\"", nm_dns_plugin_get_name (priv->plugin), "\"", - immutable ? ", resolv.conf immutable" : ""); - return; } - if (!immutable) - priv->resolv_conf_mode = NM_DNS_MANAGER_RESOLV_CONF_EXPLICIT; - - mode_unknown = mode && !nm_streq (mode, "default") ? mode : NULL; - _NMLOG (mode_unknown ? LOGL_WARN : LOGL_INFO, - "%s%s%s%s%s%s", - "set resolv-conf-mode: ", - immutable ? "none" : "default", - NM_PRINT_FMT_QUOTED (mode_unknown, " -- unknown configuration '", mode_unknown, "'", ""), - immutable ? ", resolv.conf immutable" : ""); -} - -static void -init_resolv_conf_manager (NMDnsManager *self) -{ - NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); - const char *man; - - man = nm_config_data_get_rc_manager (nm_config_get_data (priv->config)); - if (!g_strcmp0 (man, "none")) - priv->rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE; - else if (nm_streq0 (man, "file")) - priv->rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE; - else if (!g_strcmp0 (man, "resolvconf")) - priv->rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF; - else if (!g_strcmp0 (man, "netconfig")) - priv->rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG; - else { -#if defined(RESOLVCONF_SELECTED) - priv->rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF; -#elif defined(NETCONFIG_SELECTED) - priv->rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG; -#else - priv->rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE; -#endif - if (man) - _LOGW ("unknown resolv.conf manager '%s'", man); + if ( plugin_changed + || priv->rc_manager != rc_manager) { + priv->rc_manager = rc_manager; + _LOGI ("init: dns=%s, rc-manager=%s%s%s%s", + mode, _rc_manager_to_string (rc_manager), + NM_PRINT_FMT_QUOTED (priv->plugin, ", plugin=", nm_dns_plugin_get_name (priv->plugin), "", "")); } - - _LOGI ("using resolv.conf manager '%s'", _rc_manager_to_string (priv->rc_manager)); } static void @@ -1494,23 +1690,26 @@ config_changed_cb (NMConfig *config, GError *error = NULL; if (NM_FLAGS_ANY (changes, NM_CONFIG_CHANGE_DNS_MODE | - NM_CONFIG_CHANGE_SIGHUP)) { + NM_CONFIG_CHANGE_RC_MANAGER | + NM_CONFIG_CHANGE_CAUSE_SIGHUP | + NM_CONFIG_CHANGE_CAUSE_DNS_FULL)) { /* reload the resolv-conf mode also on SIGHUP (when DNS_MODE didn't change). * The reason is, that the configuration also depends on whether resolv.conf * is immutable, thus, without the configuration changing, we always want to * re-configure the mode. */ - init_resolv_conf_mode (self); + init_resolv_conf_mode (self, + NM_FLAGS_ANY (changes, NM_CONFIG_CHANGE_CAUSE_SIGHUP + | NM_CONFIG_CHANGE_CAUSE_DNS_FULL)); } - if (NM_FLAGS_HAS (changes, NM_CONFIG_CHANGE_RC_MANAGER)) - init_resolv_conf_manager (self); - - if (NM_FLAGS_ANY (changes, NM_CONFIG_CHANGE_SIGHUP | - NM_CONFIG_CHANGE_SIGUSR1 | + if (NM_FLAGS_ANY (changes, NM_CONFIG_CHANGE_CAUSE_SIGHUP | + NM_CONFIG_CHANGE_CAUSE_SIGUSR1 | + NM_CONFIG_CHANGE_CAUSE_DNS_RC | + NM_CONFIG_CHANGE_CAUSE_DNS_FULL | NM_CONFIG_CHANGE_DNS_MODE | NM_CONFIG_CHANGE_RC_MANAGER | NM_CONFIG_CHANGE_GLOBAL_DNS_CONFIG)) { - if (!update_dns (self, TRUE, &error)) { + if (!update_dns (self, FALSE, &error)) { _LOGW ("could not commit DNS changes: %s", error->message); g_clear_error (&error); } @@ -1525,16 +1724,16 @@ nm_dns_manager_init (NMDnsManager *self) _LOGT ("creating..."); priv->config = g_object_ref (nm_config_get ()); + priv->configs = g_ptr_array_new_full (8, ip_config_data_destroy); + /* Set the initial hash */ - compute_hash (self, nm_config_data_get_global_dns_config (nm_config_get_data (priv->config)), - NM_DNS_MANAGER_GET_PRIVATE (self)->hash); + compute_hash (self, NULL, NM_DNS_MANAGER_GET_PRIVATE (self)->hash); g_signal_connect (G_OBJECT (priv->config), NM_CONFIG_SIGNAL_CONFIG_CHANGED, G_CALLBACK (config_changed_cb), self); - init_resolv_conf_mode (self); - init_resolv_conf_manager (self); + init_resolv_conf_mode (self, TRUE); } static void @@ -1542,17 +1741,13 @@ dispose (GObject *object) { NMDnsManager *self = NM_DNS_MANAGER (object); NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); + NMDnsIPConfigData *data; GError *error = NULL; + guint i; _LOGT ("disposing"); - if (priv->plugin) { - g_signal_handlers_disconnect_by_func (priv->plugin, plugin_failed, self); - g_signal_handlers_disconnect_by_func (priv->plugin, plugin_child_quit, self); - g_clear_object (&priv->plugin); - } - - g_clear_pointer (&priv->last_mode, g_free); + _clear_plugin (self); /* If we're quitting, leave a valid resolv.conf in place, not one * pointing to 127.0.0.1 if any plugins were active. Thus update @@ -1570,8 +1765,16 @@ dispose (GObject *object) g_clear_object (&priv->config); } - g_slist_free_full (priv->configs, g_object_unref); - priv->configs = NULL; + if (priv->configs) { + for (i = 0; i < priv->configs->len; i++) { + data = priv->configs->pdata[i]; + forget_data (self, data); + } + g_ptr_array_free (priv->configs, TRUE); + priv->configs = NULL; + } + + nm_clear_g_source (&priv->plugin_ratelimit.timer); G_OBJECT_CLASS (nm_dns_manager_parent_class)->dispose (object); } @@ -1579,7 +1782,8 @@ dispose (GObject *object) static void finalize (GObject *object) { - NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (object); + NMDnsManager *self = NM_DNS_MANAGER (object); + NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); g_free (priv->hostname); @@ -1591,8 +1795,6 @@ nm_dns_manager_class_init (NMDnsManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - g_type_class_add_private (object_class, sizeof (NMDnsManagerPrivate)); - /* virtual methods */ object_class->dispose = dispose; object_class->finalize = finalize; @@ -1602,8 +1804,7 @@ nm_dns_manager_class_init (NMDnsManagerClass *klass) g_signal_new (NM_DNS_MANAGER_CONFIG_CHANGED, G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMDnsManagerClass, config_changed), - NULL, NULL, + 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } diff --git a/src/dns-manager/nm-dns-manager.h b/src/dns-manager/nm-dns-manager.h index f1293f7e..50f050e5 100644 --- a/src/dns-manager/nm-dns-manager.h +++ b/src/dns-manager/nm-dns-manager.h @@ -28,13 +28,24 @@ #include "nm-ip4-config.h" #include "nm-ip6-config.h" +G_BEGIN_DECLS + typedef enum { NM_DNS_IP_CONFIG_TYPE_DEFAULT = 0, NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE, NM_DNS_IP_CONFIG_TYPE_VPN } NMDnsIPConfigType; -G_BEGIN_DECLS +enum { + NM_DNS_PRIORITY_DEFAULT_NORMAL = 100, + NM_DNS_PRIORITY_DEFAULT_VPN = 50, +}; + +typedef struct { + gpointer config; + NMDnsIPConfigType type; + char *iface; +} NMDnsIPConfigData; #define NM_TYPE_DNS_MANAGER (nm_dns_manager_get_type ()) #define NM_DNS_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), NM_TYPE_DNS_MANAGER, NMDnsManager)) @@ -45,16 +56,8 @@ G_BEGIN_DECLS #define NM_DNS_MANAGER_CONFIG_CHANGED "config-changed" -typedef struct { - GObject parent; -} NMDnsManager; - -typedef struct { - GObjectClass parent; - - /* Signals */ - void (*config_changed) (NMDnsManager *mgr); -} NMDnsManagerClass; +typedef struct _NMDnsManager NMDnsManager; +typedef struct _NMDnsManagerClass NMDnsManagerClass; GType nm_dns_manager_get_type (void); @@ -84,32 +87,17 @@ void nm_dns_manager_set_hostname (NMDnsManager *self, const char *hostname); /** - * NMDnsManagerResolvConfMode: - * @NM_DNS_MANAGER_RESOLV_CONF_UNMANAGED: NM is not managing resolv.conf - * @NM_DNS_MANAGER_RESOLV_CONF_EXPLICIT: NM is managing resolv.conf by - * adding and removing "nameserver" lines corresponding to the currently - * active connections - * @NM_DNS_MANAGER_RESOLV_CONF_PROXY: NM is managing resolv.conf by - * pointing it to some other service (eg, dnsmasq) that knows the - * nameservers corresponding to the currently active connections. - * - * NMDnsManager's behavior toward /etc/resolv.conf. - */ -typedef enum { - NM_DNS_MANAGER_RESOLV_CONF_UNMANAGED, - NM_DNS_MANAGER_RESOLV_CONF_EXPLICIT, - NM_DNS_MANAGER_RESOLV_CONF_PROXY -} NMDnsManagerResolvConfMode; - -/** * NMDnsManagerResolvConfManager - * @_NM_DNS_MANAGER_RESOLV_CONF_MAN_INTERNAL_ONLY: dummy-manager - * to not write resolv.conf at all, only the internal file in - * NM's run state directory. - * @NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE: NM writes resolv.conf + * @NM_DNS_MANAGER_RESOLV_CONF_MAN_UNKNOWN: unspecified rc-manager. + * @NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED: do not touch /etc/resolv.conf + * (but still write the internal copy -- unless it is symlinked by + * /etc/resolv.conf) + * @NM_DNS_MANAGER_RESOLV_CONF_MAN_IMMUTABLE: similar to "unmanaged", + * but indicates that resolv.conf cannot be modified. + * @NM_DNS_MANAGER_RESOLV_CONF_MAN_SYMLINK: NM writes resolv.conf * by symlinking it to the run state directory. - * @NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE: Like NONE, but instead of symlinking - * resolv.conf, write it as a file. + * @NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE: Like SYMLINK, but instead of + * symlinking /etc/resolv.conf, write it as a file. * @NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF: NM is managing resolv.conf through resolvconf * @NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG: NM is managing resolv.conf @@ -118,14 +106,16 @@ typedef enum { * NMDnsManager's management of resolv.conf */ typedef enum { - _NM_DNS_MANAGER_RESOLV_CONF_MAN_INTERNAL_ONLY, - NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE, + NM_DNS_MANAGER_RESOLV_CONF_MAN_UNKNOWN, + NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED, + NM_DNS_MANAGER_RESOLV_CONF_MAN_IMMUTABLE, + NM_DNS_MANAGER_RESOLV_CONF_MAN_SYMLINK, NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE, NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF, NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG, } NMDnsManagerResolvConfManager; -NMDnsManagerResolvConfMode nm_dns_manager_get_resolv_conf_mode (NMDnsManager *self); +gboolean nm_dns_manager_get_resolv_conf_explicit (NMDnsManager *self); G_END_DECLS diff --git a/src/dns-manager/nm-dns-plugin.c b/src/dns-manager/nm-dns-plugin.c index d5cb8822..f065a1ce 100644 --- a/src/dns-manager/nm-dns-plugin.c +++ b/src/dns-manager/nm-dns-plugin.c @@ -74,18 +74,14 @@ static guint signals[LAST_SIGNAL] = { 0 }; gboolean nm_dns_plugin_update (NMDnsPlugin *self, - const GSList *vpn_configs, - const GSList *dev_configs, - const GSList *other_configs, + const NMDnsIPConfigData **configs, const NMGlobalDnsConfig *global_config, const char *hostname) { g_return_val_if_fail (NM_DNS_PLUGIN_GET_CLASS (self)->update != NULL, FALSE); return NM_DNS_PLUGIN_GET_CLASS (self)->update (self, - vpn_configs, - dev_configs, - other_configs, + configs, global_config, hostname); } @@ -182,6 +178,17 @@ watch_cb (GPid pid, gint status, gpointer user_data) } GPid +nm_dns_plugin_child_pid (NMDnsPlugin *self) +{ + NMDnsPluginPrivate *priv; + + g_return_val_if_fail (NM_IS_DNS_PLUGIN (self), 0); + + priv = NM_DNS_PLUGIN_GET_PRIVATE (self); + return priv->pid; +} + +GPid nm_dns_plugin_child_spawn (NMDnsPlugin *self, const char **argv, const char *pidfile, @@ -224,7 +231,7 @@ nm_dns_plugin_child_spawn (NMDnsPlugin *self, _LOGD ("%s started with pid %d", progname, pid); priv->watch_id = g_child_watch_add (pid, (GChildWatchFunc) watch_cb, self); priv->pid = pid; - priv->progname = nm_unauto (&progname); + priv->progname = g_steal_pointer (&progname); priv->pidfile = g_strdup (pidfile); return pid; @@ -247,6 +254,12 @@ nm_dns_plugin_child_kill (NMDnsPlugin *self) return TRUE; } +void +nm_dns_plugin_stop (NMDnsPlugin *self) +{ + nm_dns_plugin_child_kill (self); +} + /********************************************/ static void @@ -259,7 +272,7 @@ dispose (GObject *object) { NMDnsPlugin *self = NM_DNS_PLUGIN (object); - nm_dns_plugin_child_kill (self); + nm_dns_plugin_stop (self); G_OBJECT_CLASS (nm_dns_plugin_parent_class)->dispose (object); } diff --git a/src/dns-manager/nm-dns-plugin.h b/src/dns-manager/nm-dns-plugin.h index 7ecaa424..4c84b145 100644 --- a/src/dns-manager/nm-dns-plugin.h +++ b/src/dns-manager/nm-dns-plugin.h @@ -20,6 +20,7 @@ #define __NETWORKMANAGER_DNS_PLUGIN_H__ #include "nm-default.h" +#include "nm-dns-manager.h" #include "nm-config-data.h" @@ -33,8 +34,6 @@ #define NM_DNS_PLUGIN_FAILED "failed" #define NM_DNS_PLUGIN_CHILD_QUIT "child-quit" -#define IP_CONFIG_IFACE_TAG "dns-manager-iface" - typedef struct { GObject parent; } NMDnsPlugin; @@ -44,18 +43,13 @@ typedef struct { /* Methods */ - /* Called when DNS information is changed. 'vpn_configs' is a list of - * NMIP4Config or NMIP6Config objects from VPN connections, while - * 'dev_configs' is a list of NMPI4Config or NMIP6Config objects from - * active devices. 'other_configs' represent other IP configuration that - * may be in-use. 'global_config' is the optional global DNS - * configuration. Configs of the same IP version are sorted in priority - * order. + /* Called when DNS information is changed. 'configs' is an array + * of pointers to NMDnsIPConfigData sorted by priority. + * 'global_config' is the optional global DNS + * configuration. */ gboolean (*update) (NMDnsPlugin *self, - const GSList *vpn_configs, - const GSList *dev_configs, - const GSList *other_configs, + const NMDnsIPConfigData **configs, const NMGlobalDnsConfig *global_config, const char *hostname); @@ -92,12 +86,12 @@ gboolean nm_dns_plugin_is_caching (NMDnsPlugin *self); const char *nm_dns_plugin_get_name (NMDnsPlugin *self); gboolean nm_dns_plugin_update (NMDnsPlugin *self, - const GSList *vpn_configs, - const GSList *dev_configs, - const GSList *other_configs, + const NMDnsIPConfigData **configs, const NMGlobalDnsConfig *global_config, const char *hostname); +void nm_dns_plugin_stop (NMDnsPlugin *self); + /* For subclasses/plugins */ /* Spawn a child process and watch for it to quit. 'argv' is the NULL-terminated @@ -111,6 +105,8 @@ GPid nm_dns_plugin_child_spawn (NMDnsPlugin *self, const char *pidfile, const char *kill_match); +GPid nm_dns_plugin_child_pid (NMDnsPlugin *self); + gboolean nm_dns_plugin_child_kill (NMDnsPlugin *self); #endif /* __NETWORKMANAGER_DNS_PLUGIN_H__ */ diff --git a/src/dns-manager/nm-dns-unbound.c b/src/dns-manager/nm-dns-unbound.c index 4c1af103..66a287fd 100644 --- a/src/dns-manager/nm-dns-unbound.c +++ b/src/dns-manager/nm-dns-unbound.c @@ -28,9 +28,7 @@ G_DEFINE_TYPE (NMDnsUnbound, nm_dns_unbound, NM_TYPE_DNS_PLUGIN) static gboolean update (NMDnsPlugin *plugin, - const GSList *vpn_configs, - const GSList *dev_configs, - const GSList *other_configs, + const NMDnsIPConfigData **configs, const NMGlobalDnsConfig *global_config, const char *hostname) { diff --git a/src/dns-manager/nm-dns-utils.c b/src/dns-manager/nm-dns-utils.c deleted file mode 100644 index e920611a..00000000 --- a/src/dns-manager/nm-dns-utils.c +++ /dev/null @@ -1,105 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2010 Red Hat, Inc. - * - */ - -#include "nm-default.h" - -#include <arpa/inet.h> -#include <string.h> - -#include "nm-dns-utils.h" -#include "nm-platform.h" -#include "nm-utils.h" - -static void -add_ip4_to_rdns_array (guint32 ip, GPtrArray *domains) /* network byte order */ -{ - guint32 defprefix; - guchar *p; - char *str = NULL; - int i; - - defprefix = nm_utils_ip4_get_default_prefix (ip); - - /* Convert to host byte order, mask the host bits, and convert back */ - ip = ntohl (ip); - ip &= 0xFFFFFFFF << (32 - defprefix); - ip = htonl (ip); - p = (guchar *) &ip; - - if (defprefix == 8) - str = g_strdup_printf ("%u.in-addr.arpa", p[0] & 0xFF); - else if (defprefix == 16) - str = g_strdup_printf ("%u.%u.in-addr.arpa", p[1] & 0xFF, p[0] & 0xFF); - else if (defprefix == 24) - str = g_strdup_printf ("%u.%u.%u.in-addr.arpa", p[2] & 0xFF, p[1] & 0xFF, p[0] & 0xFF); - - if (!str) { - g_return_if_fail (str != NULL); - return; - } - - /* Suppress duplicates */ - for (i = 0; i < domains->len; i++) { - if (strcmp (str, g_ptr_array_index (domains, i)) == 0) - break; - } - - if (i == domains->len) - g_ptr_array_add (domains, str); - else - g_free (str); -} - -char ** -nm_dns_utils_get_ip4_rdns_domains (NMIP4Config *ip4) -{ - GPtrArray *domains = NULL; - int i; - - g_return_val_if_fail (ip4 != NULL, NULL); - - domains = g_ptr_array_sized_new (5); - - /* To calculate the reverse DNS domains for this IP4 config, we take - * all the IP addresses and routes in the config, calculate the network - * portion, and convert that to classful, and use the network bits for - * the final domain. FIXME: better handle classless routing, which might - * require us to add multiple domains for each actual network prefix to - * cover all the separate networks in that block. - */ - - for (i = 0; i < nm_ip4_config_get_num_addresses (ip4); i++) { - const NMPlatformIP4Address *address = nm_ip4_config_get_address (ip4, i); - - add_ip4_to_rdns_array (address->address, domains); - } - - for (i = 0; i < nm_ip4_config_get_num_routes (ip4); i++) { - const NMPlatformIP4Route *route = nm_ip4_config_get_route (ip4, i); - - add_ip4_to_rdns_array (route->network, domains); - } - - /* Terminating NULL so we can use g_strfreev() to free it */ - g_ptr_array_add (domains, NULL); - - /* Free the array and return NULL if the only element was the ending NULL */ - return (char **) g_ptr_array_free (domains, (domains->len == 1)); -} - diff --git a/src/dns-manager/nm-dns-utils.h b/src/dns-manager/nm-dns-utils.h deleted file mode 100644 index 75c6b060..00000000 --- a/src/dns-manager/nm-dns-utils.h +++ /dev/null @@ -1,28 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2010 Red Hat, Inc. - * - */ - -#ifndef __NETWORKMANAGER_DNS_UTILS_H__ -#define __NETWORKMANAGER_DNS_UTILS_H__ - -#include "nm-ip4-config.h" - -char **nm_dns_utils_get_ip4_rdns_domains (NMIP4Config *ip4); - -#endif /* NM_DNS_UTILS_H */ - diff --git a/src/dnsmasq-manager/nm-dnsmasq-manager.c b/src/dnsmasq-manager/nm-dnsmasq-manager.c index 764aba29..12395db6 100644 --- a/src/dnsmasq-manager/nm-dnsmasq-manager.c +++ b/src/dnsmasq-manager/nm-dnsmasq-manager.c @@ -165,36 +165,6 @@ nm_cmd_line_add_string (NMCmdLine *cmd, const char *str) /*******************************************/ static void -dm_exit_code (guint dm_exit_status) -{ - char *msg = "Unknown error"; - - switch (dm_exit_status) { - case 1: - msg = "Configuration problem"; - break; - case 2: - msg = "Network access problem (address in use; permissions; etc)"; - break; - case 3: - msg = "Filesystem problem (missing file/directory; permissions; etc)"; - break; - case 4: - msg = "Memory allocation failure"; - break; - case 5: - msg = "Other problem"; - break; - default: - if (dm_exit_status >= 11) - msg = "Lease-script 'init' process failure"; - break; - } - - _LOGW ("dnsmasq exited with error: %s (%d)", msg, dm_exit_status); -} - -static void dm_watch_cb (GPid pid, gint status, gpointer user_data) { NMDnsMasqManager *manager = NM_DNSMASQ_MANAGER (user_data); @@ -203,8 +173,10 @@ dm_watch_cb (GPid pid, gint status, gpointer user_data) if (WIFEXITED (status)) { err = WEXITSTATUS (status); - if (err != 0) - dm_exit_code (err); + if (err != 0) { + _LOGW ("dnsmasq exited with error: %s", + nm_utils_dnsmasq_status_to_string (err, NULL, 0)); + } } else if (WIFSTOPPED (status)) { _LOGW ("dnsmasq stopped unexpectedly with signal %d", WSTOPSIG (status)); } else if (WIFSIGNALED (status)) { diff --git a/src/dnsmasq-manager/tests/Makefile.in b/src/dnsmasq-manager/tests/Makefile.in index d6b57edb..38344a8b 100644 --- a/src/dnsmasq-manager/tests/Makefile.in +++ b/src/dnsmasq-manager/tests/Makefile.in @@ -521,6 +521,7 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@ NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ diff --git a/src/main.c b/src/main.c index 4616155d..e243baa8 100644 --- a/src/main.c +++ b/src/main.c @@ -188,14 +188,31 @@ _init_nm_debug (const char *debug) void nm_main_config_reload (int signal) { + NMConfigChangeFlags reload_flags; + + switch (signal) { + case SIGHUP: + reload_flags = NM_CONFIG_CHANGE_CAUSE_SIGHUP; + break; + case SIGUSR1: + reload_flags = NM_CONFIG_CHANGE_CAUSE_SIGUSR1; + break; + case SIGUSR2: + reload_flags = NM_CONFIG_CHANGE_CAUSE_SIGUSR2; + break; + default: + g_return_if_reached (); + } + nm_log_info (LOGD_CORE, "reload configuration (signal %s)...", strsignal (signal)); + /* The signal handler thread is only installed after * creating NMConfig instance, and on shut down we * no longer run the mainloop (to reach this point). * * Hence, a NMConfig singleton instance must always be * available. */ - nm_config_reload (nm_config_get (), signal); + nm_config_reload (nm_config_get (), reload_flags); } static void diff --git a/src/nm-active-connection.c b/src/nm-active-connection.c index e9076136..2b7847b2 100644 --- a/src/nm-active-connection.c +++ b/src/nm-active-connection.c @@ -21,6 +21,8 @@ #include "nm-default.h" #include "nm-active-connection.h" + +#include "nm-common-macros.h" #include "nm-dbus-interface.h" #include "nm-device.h" #include "nm-settings-connection.h" @@ -70,8 +72,7 @@ typedef struct { gpointer user_data2; } NMActiveConnectionPrivate; -enum { - PROP_0, +NM_GOBJECT_PROPERTIES_DEFINE (NMActiveConnection, PROP_CONNECTION, PROP_ID, PROP_UUID, @@ -93,9 +94,7 @@ enum { PROP_INT_SUBJECT, PROP_INT_MASTER, PROP_INT_MASTER_READY, - - LAST_PROP -}; +); enum { DEVICE_CHANGED, @@ -137,6 +136,45 @@ NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_state_to_string, NMActiveConnectionState, /****************************************************************/ +static void +_settings_connection_updated (NMSettingsConnection *connection, + gboolean by_user, + gpointer user_data) +{ + NMActiveConnection *self = user_data; + + /* we don't know which properties actually changed. Just to be sure, + * notify about all possible properties. After all, an update of a + * connection is a rare event. */ + + _notify (self, PROP_ID); + + /* it's a bit odd to update the TYPE of an active connection. But the alternative + * is unexpected too. */ + _notify (self, PROP_TYPE); + + /* currently, the UUID and the exported CONNECTION path cannot change. Later, we might + * want to support a re-link operation, which associates an active-connection with a different + * settings-connection. */ +} + +static void +_set_settings_connection (NMActiveConnection *self, NMSettingsConnection *connection) +{ + NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self); + + if (priv->settings_connection == connection) + return; + if (priv->settings_connection) { + g_signal_handlers_disconnect_by_func (priv->settings_connection, _settings_connection_updated, self); + g_clear_object (&priv->settings_connection); + } + if (connection) { + priv->settings_connection = g_object_ref (connection); + g_signal_connect (connection, NM_SETTINGS_CONNECTION_UPDATED_INTERNAL, (GCallback) _settings_connection_updated, self); + } +} + NMActiveConnectionState nm_active_connection_get_state (NMActiveConnection *self) { @@ -164,7 +202,7 @@ nm_active_connection_set_state (NMActiveConnection *self, old_state = priv->state; priv->state = new_state; priv->state_set = TRUE; - g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_STATE); + _notify (self, PROP_STATE); check_master_ready (self); @@ -186,10 +224,10 @@ nm_active_connection_set_state (NMActiveConnection *self, if ( new_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED || old_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) { - g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_IP4_CONFIG); - g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_DHCP4_CONFIG); - g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_IP6_CONFIG); - g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_DHCP6_CONFIG); + _notify (self, PROP_IP4_CONFIG); + _notify (self, PROP_DHCP4_CONFIG); + _notify (self, PROP_IP6_CONFIG); + _notify (self, PROP_DHCP6_CONFIG); } if (priv->state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) { @@ -198,7 +236,7 @@ nm_active_connection_set_state (NMActiveConnection *self, * which will be NULL due to conditions in get_property(). */ _device_cleanup (self); - g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_DEVICES); + _notify (self, PROP_DEVICES); } } @@ -276,7 +314,7 @@ nm_active_connection_set_settings_connection (NMActiveConnection *self, * For example, we'd have to cancel all pending seret requests. */ g_return_if_fail (!nm_exported_object_is_exported (NM_EXPORTED_OBJECT (self))); - priv->settings_connection = g_object_ref (connection); + _set_settings_connection (self, connection); priv->applied_connection = nm_simple_connection_new_clone (NM_CONNECTION (priv->settings_connection)); nm_connection_clear_secrets (priv->applied_connection); } @@ -339,7 +377,7 @@ nm_active_connection_set_specific_object (NMActiveConnection *self, g_free (priv->specific_object); priv->specific_object = g_strdup (specific_object); - g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT); + _notify (self, PROP_SPECIFIC_OBJECT); } void @@ -356,7 +394,7 @@ nm_active_connection_set_default (NMActiveConnection *self, gboolean is_default) return; priv->is_default = is_default; - g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_DEFAULT); + _notify (self, PROP_DEFAULT); } gboolean @@ -381,7 +419,7 @@ nm_active_connection_set_default6 (NMActiveConnection *self, gboolean is_default return; priv->is_default6 = is_default6; - g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_DEFAULT6); + _notify (self, PROP_DEFAULT6); } gboolean @@ -524,11 +562,11 @@ nm_active_connection_set_device (NMActiveConnection *self, NMDevice *device) g_warn_if_fail (priv->state > NM_ACTIVE_CONNECTION_STATE_UNKNOWN); priv->device = NULL; } - g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_INT_DEVICE); + _notify (self, PROP_INT_DEVICE); g_signal_emit (self, signals[DEVICE_CHANGED], 0, priv->device, old_device); - g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_DEVICES); + _notify (self, PROP_DEVICES); return TRUE; } @@ -589,13 +627,13 @@ check_master_ready (NMActiveConnection *self) if (signalling) { priv->master_ready = TRUE; - g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_INT_MASTER_READY); + _notify (self, PROP_INT_MASTER_READY); /* Also notify clients to recheck the exported 'master' property to * ensure that if the master connection was created without a device * that we notify clients when the master device is known. */ - g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_MASTER); + _notify (self, PROP_MASTER); } } @@ -921,7 +959,8 @@ static void set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { - NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (object); + NMActiveConnection *self = (NMActiveConnection *) object; + NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self); const char *tmp; NMSettingsConnection *con; @@ -930,20 +969,20 @@ set_property (GObject *object, guint prop_id, /* construct-only */ con = g_value_get_object (value); if (con) { - priv->settings_connection = g_object_ref (con); - priv->applied_connection = nm_simple_connection_new_clone (NM_CONNECTION (con)); + _set_settings_connection (self, con); + priv->applied_connection = nm_simple_connection_new_clone ((NMConnection *) priv->settings_connection); nm_connection_clear_secrets (priv->applied_connection); } break; case PROP_INT_DEVICE: /* construct-only */ - nm_active_connection_set_device (NM_ACTIVE_CONNECTION (object), g_value_get_object (value)); + nm_active_connection_set_device (self, g_value_get_object (value)); break; case PROP_INT_SUBJECT: priv->subject = g_value_dup_object (value); break; case PROP_INT_MASTER: - nm_active_connection_set_master (NM_ACTIVE_CONNECTION (object), g_value_get_object (value)); + nm_active_connection_set_master (self, g_value_get_object (value)); break; case PROP_SPECIFIC_OBJECT: tmp = g_value_get_string (value); @@ -1083,7 +1122,7 @@ dispose (GObject *object) g_free (priv->specific_object); priv->specific_object = NULL; - g_clear_object (&priv->settings_connection); + _set_settings_connection (self, NULL); g_clear_object (&priv->applied_connection); _device_cleanup (self); @@ -1120,171 +1159,153 @@ nm_active_connection_class_init (NMActiveConnectionClass *ac_class) object_class->dispose = dispose; /* D-Bus exported properties */ - g_object_class_install_property - (object_class, PROP_CONNECTION, - g_param_spec_string (NM_ACTIVE_CONNECTION_CONNECTION, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_ID, - g_param_spec_string (NM_ACTIVE_CONNECTION_ID, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_UUID, - g_param_spec_string (NM_ACTIVE_CONNECTION_UUID, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_TYPE, - g_param_spec_string (NM_ACTIVE_CONNECTION_TYPE, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_SPECIFIC_OBJECT, - g_param_spec_string (NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT, "", "", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_DEVICES, - g_param_spec_boxed (NM_ACTIVE_CONNECTION_DEVICES, "", "", - G_TYPE_STRV, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_STATE, - g_param_spec_uint (NM_ACTIVE_CONNECTION_STATE, "", "", - NM_ACTIVE_CONNECTION_STATE_UNKNOWN, - NM_ACTIVE_CONNECTION_STATE_DEACTIVATING, - NM_ACTIVE_CONNECTION_STATE_UNKNOWN, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_DEFAULT, - g_param_spec_boolean (NM_ACTIVE_CONNECTION_DEFAULT, "", "", - FALSE, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_IP4_CONFIG, - g_param_spec_string (NM_ACTIVE_CONNECTION_IP4_CONFIG, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_DHCP4_CONFIG, - g_param_spec_string (NM_ACTIVE_CONNECTION_DHCP4_CONFIG, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_DEFAULT6, - g_param_spec_boolean (NM_ACTIVE_CONNECTION_DEFAULT6, "", "", - FALSE, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_IP6_CONFIG, - g_param_spec_string (NM_ACTIVE_CONNECTION_IP6_CONFIG, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_DHCP6_CONFIG, - g_param_spec_string (NM_ACTIVE_CONNECTION_DHCP6_CONFIG, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_VPN, - g_param_spec_boolean (NM_ACTIVE_CONNECTION_VPN, "", "", - FALSE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_MASTER, - g_param_spec_string (NM_ACTIVE_CONNECTION_MASTER, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_CONNECTION] = + g_param_spec_string (NM_ACTIVE_CONNECTION_CONNECTION, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_ID] = + g_param_spec_string (NM_ACTIVE_CONNECTION_ID, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_UUID] = + g_param_spec_string (NM_ACTIVE_CONNECTION_UUID, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_TYPE] = + g_param_spec_string (NM_ACTIVE_CONNECTION_TYPE, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_SPECIFIC_OBJECT] = + g_param_spec_string (NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT, "", "", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_DEVICES] = + g_param_spec_boxed (NM_ACTIVE_CONNECTION_DEVICES, "", "", + G_TYPE_STRV, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_STATE] = + g_param_spec_uint (NM_ACTIVE_CONNECTION_STATE, "", "", + NM_ACTIVE_CONNECTION_STATE_UNKNOWN, + NM_ACTIVE_CONNECTION_STATE_DEACTIVATING, + NM_ACTIVE_CONNECTION_STATE_UNKNOWN, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_DEFAULT] = + g_param_spec_boolean (NM_ACTIVE_CONNECTION_DEFAULT, "", "", + FALSE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_IP4_CONFIG] = + g_param_spec_string (NM_ACTIVE_CONNECTION_IP4_CONFIG, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_DHCP4_CONFIG] = + g_param_spec_string (NM_ACTIVE_CONNECTION_DHCP4_CONFIG, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_DEFAULT6] = + g_param_spec_boolean (NM_ACTIVE_CONNECTION_DEFAULT6, "", "", + FALSE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_IP6_CONFIG] = + g_param_spec_string (NM_ACTIVE_CONNECTION_IP6_CONFIG, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_DHCP6_CONFIG] = + g_param_spec_string (NM_ACTIVE_CONNECTION_DHCP6_CONFIG, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_VPN] = + g_param_spec_boolean (NM_ACTIVE_CONNECTION_VPN, "", "", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_MASTER] = + g_param_spec_string (NM_ACTIVE_CONNECTION_MASTER, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); /* Internal properties */ - g_object_class_install_property - (object_class, PROP_INT_SETTINGS_CONNECTION, - g_param_spec_object (NM_ACTIVE_CONNECTION_INT_SETTINGS_CONNECTION, "", "", - NM_TYPE_SETTINGS_CONNECTION, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_INT_DEVICE, - g_param_spec_object (NM_ACTIVE_CONNECTION_INT_DEVICE, "", "", - NM_TYPE_DEVICE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_INT_SUBJECT, - g_param_spec_object (NM_ACTIVE_CONNECTION_INT_SUBJECT, "", "", - NM_TYPE_AUTH_SUBJECT, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_INT_MASTER, - g_param_spec_object (NM_ACTIVE_CONNECTION_INT_MASTER, "", "", - NM_TYPE_ACTIVE_CONNECTION, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_INT_MASTER_READY, - g_param_spec_boolean (NM_ACTIVE_CONNECTION_INT_MASTER_READY, "", "", - FALSE, G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_INT_SETTINGS_CONNECTION] = + g_param_spec_object (NM_ACTIVE_CONNECTION_INT_SETTINGS_CONNECTION, "", "", + NM_TYPE_SETTINGS_CONNECTION, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_INT_DEVICE] = + g_param_spec_object (NM_ACTIVE_CONNECTION_INT_DEVICE, "", "", + NM_TYPE_DEVICE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_INT_SUBJECT] = + g_param_spec_object (NM_ACTIVE_CONNECTION_INT_SUBJECT, "", "", + NM_TYPE_AUTH_SUBJECT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_INT_MASTER] = + g_param_spec_object (NM_ACTIVE_CONNECTION_INT_MASTER, "", "", + NM_TYPE_ACTIVE_CONNECTION, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_INT_MASTER_READY] = + g_param_spec_boolean (NM_ACTIVE_CONNECTION_INT_MASTER_READY, "", "", + FALSE, G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); signals[DEVICE_CHANGED] = - g_signal_new (NM_ACTIVE_CONNECTION_DEVICE_CHANGED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMActiveConnectionClass, device_changed), - NULL, NULL, NULL, - G_TYPE_NONE, 2, NM_TYPE_DEVICE, NM_TYPE_DEVICE); + g_signal_new (NM_ACTIVE_CONNECTION_DEVICE_CHANGED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMActiveConnectionClass, device_changed), + NULL, NULL, NULL, + G_TYPE_NONE, 2, NM_TYPE_DEVICE, NM_TYPE_DEVICE); signals[DEVICE_METERED_CHANGED] = - g_signal_new (NM_ACTIVE_CONNECTION_DEVICE_METERED_CHANGED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMActiveConnectionClass, device_metered_changed), - NULL, NULL, NULL, - G_TYPE_NONE, 1, G_TYPE_UINT); + g_signal_new (NM_ACTIVE_CONNECTION_DEVICE_METERED_CHANGED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMActiveConnectionClass, device_metered_changed), + NULL, NULL, NULL, + G_TYPE_NONE, 1, G_TYPE_UINT); signals[PARENT_ACTIVE] = - g_signal_new (NM_ACTIVE_CONNECTION_PARENT_ACTIVE, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMActiveConnectionClass, parent_active), - NULL, NULL, NULL, - G_TYPE_NONE, 1, NM_TYPE_ACTIVE_CONNECTION); + g_signal_new (NM_ACTIVE_CONNECTION_PARENT_ACTIVE, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMActiveConnectionClass, parent_active), + NULL, NULL, NULL, + G_TYPE_NONE, 1, NM_TYPE_ACTIVE_CONNECTION); nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (ac_class), NMDBUS_TYPE_ACTIVE_CONNECTION_SKELETON, diff --git a/src/nm-audit-manager.h b/src/nm-audit-manager.h index ed53be69..9aef417f 100644 --- a/src/nm-audit-manager.h +++ b/src/nm-audit-manager.h @@ -53,6 +53,7 @@ typedef struct { #define NM_AUDIT_OP_CONN_DEACTIVATE "connection-deactivate" #define NM_AUDIT_OP_CONN_CLEAR_SECRETS "connection-clear-secrets" +#define NM_AUDIT_OP_RELOAD "reload" #define NM_AUDIT_OP_SLEEP_CONTROL "sleep-control" #define NM_AUDIT_OP_NET_CONTROL "networking-control" #define NM_AUDIT_OP_RADIO_CONTROL "radio-control" diff --git a/src/nm-auth-utils.c b/src/nm-auth-utils.c index 928e88b0..e1761cab 100644 --- a/src/nm-auth-utils.c +++ b/src/nm-auth-utils.c @@ -20,10 +20,11 @@ #include "nm-default.h" +#include "nm-auth-utils.h" + #include <string.h> #include "nm-setting-connection.h" -#include "nm-auth-utils.h" #include "nm-auth-subject.h" #include "nm-auth-manager.h" #include "nm-session-monitor.h" diff --git a/src/nm-auth-utils.h b/src/nm-auth-utils.h index 6eb0fda0..89ed79cc 100644 --- a/src/nm-auth-utils.h +++ b/src/nm-auth-utils.h @@ -21,22 +21,7 @@ #ifndef __NETWORKMANAGER_MANAGER_AUTH_H__ #define __NETWORKMANAGER_MANAGER_AUTH_H__ -#include <nm-connection.h> -#include "nm-default.h" - -#define NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK "org.freedesktop.NetworkManager.enable-disable-network" -#define NM_AUTH_PERMISSION_SLEEP_WAKE "org.freedesktop.NetworkManager.sleep-wake" -#define NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI "org.freedesktop.NetworkManager.enable-disable-wifi" -#define NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN "org.freedesktop.NetworkManager.enable-disable-wwan" -#define NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX "org.freedesktop.NetworkManager.enable-disable-wimax" -#define NM_AUTH_PERMISSION_NETWORK_CONTROL "org.freedesktop.NetworkManager.network-control" -#define NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED "org.freedesktop.NetworkManager.wifi.share.protected" -#define NM_AUTH_PERMISSION_WIFI_SHARE_OPEN "org.freedesktop.NetworkManager.wifi.share.open" -#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM "org.freedesktop.NetworkManager.settings.modify.system" -#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN "org.freedesktop.NetworkManager.settings.modify.own" -#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME "org.freedesktop.NetworkManager.settings.modify.hostname" -#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS "org.freedesktop.NetworkManager.settings.modify.global-dns" - +#include "nm-connection.h" typedef struct NMAuthChain NMAuthChain; diff --git a/src/nm-config-data.c b/src/nm-config-data.c index 1702b551..28057b47 100644 --- a/src/nm-config-data.c +++ b/src/nm-config-data.c @@ -1201,6 +1201,8 @@ nm_config_data_diff (NMConfigData *old_data, NMConfigData *new_data) if (!global_dns_equal (priv_old->global_dns, priv_new->global_dns)) changes |= NM_CONFIG_CHANGE_GLOBAL_DNS_CONFIG; + nm_assert (!NM_FLAGS_ANY (changes, NM_CONFIG_CHANGE_CAUSES)); + return changes; } diff --git a/src/nm-config-data.h b/src/nm-config-data.h index 2decfdb4..e01ad6ea 100644 --- a/src/nm-config-data.h +++ b/src/nm-config-data.h @@ -21,11 +21,6 @@ #ifndef NM_CONFIG_DATA_H #define NM_CONFIG_DATA_H - -#include "nm-default.h" - -G_BEGIN_DECLS - #define NM_TYPE_CONFIG_DATA (nm_config_data_get_type ()) #define NM_CONFIG_DATA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_CONFIG_DATA, NMConfigData)) #define NM_CONFIG_DATA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_CONFIG_DATA, NMConfigDataClass)) @@ -44,7 +39,26 @@ G_BEGIN_DECLS #define NM_CONFIG_DATA_NO_AUTO_DEFAULT "no-auto-default" #define NM_CONFIG_DATA_DNS_MODE "dns" -typedef enum { /*<flags >*/ +/* The flags for Reload. Currently these are internal defines, + * only their numeric value matters and must be stable as + * they are public API! Also, the enum must fit in uint32. */ +enum { /*< skip >*/ + NM_MANAGER_RELOAD_FLAGS_NONE = 0, + + /* reload the configuration from disk */ + NM_MANAGER_RELOAD_FLAGS_CONF = (1LL << 0), + + /* write DNS configuration to resolv.conf */ + NM_MANAGER_RELOAD_FLAGS_DNS_RC = (1LL << 1), + + /* restart the DNS plugin (includes DNS_RC) */ + NM_MANAGER_RELOAD_FLAGS_DNS_FULL = (1LL << 2), + + _NM_MANAGER_RELOAD_FLAGS_ALL, + NM_MANAGER_RELOAD_FLAGS_ALL = ((_NM_MANAGER_RELOAD_FLAGS_ALL - 1) << 1) - 1, +}; + +typedef enum { /*< flags >*/ NM_CONFIG_GET_VALUE_NONE = 0, /* use g_key_file_get_value() instead of g_key_file_get_string(). */ @@ -64,22 +78,54 @@ typedef enum { /*<flags >*/ typedef enum { /*< flags >*/ NM_CONFIG_CHANGE_NONE = 0, - NM_CONFIG_CHANGE_SIGHUP = (1L << 0), - NM_CONFIG_CHANGE_SIGUSR1 = (1L << 1), - NM_CONFIG_CHANGE_SIGUSR2 = (1L << 2), - - NM_CONFIG_CHANGE_CONFIG_FILES = (1L << 3), - NM_CONFIG_CHANGE_VALUES = (1L << 4), - NM_CONFIG_CHANGE_VALUES_USER = (1L << 5), - NM_CONFIG_CHANGE_VALUES_INTERN = (1L << 6), - NM_CONFIG_CHANGE_CONNECTIVITY = (1L << 7), - NM_CONFIG_CHANGE_NO_AUTO_DEFAULT = (1L << 8), - NM_CONFIG_CHANGE_DNS_MODE = (1L << 9), - NM_CONFIG_CHANGE_RC_MANAGER = (1L << 10), - NM_CONFIG_CHANGE_GLOBAL_DNS_CONFIG = (1L << 11), - - _NM_CONFIG_CHANGE_LAST, - NM_CONFIG_CHANGE_ALL = ((_NM_CONFIG_CHANGE_LAST - 1) << 1) - 1, + /************************************************************************** + * The external cause which triggered the reload/configuration-change + *************************************************************************/ + + NM_CONFIG_CHANGE_CAUSE_SIGHUP = (1L << 0), + NM_CONFIG_CHANGE_CAUSE_SIGUSR1 = (1L << 1), + NM_CONFIG_CHANGE_CAUSE_SIGUSR2 = (1L << 2), + NM_CONFIG_CHANGE_CAUSE_NO_AUTO_DEFAULT = (1L << 3), + NM_CONFIG_CHANGE_CAUSE_SET_VALUES = (1L << 4), + NM_CONFIG_CHANGE_CAUSE_CONF = (1L << 5), + NM_CONFIG_CHANGE_CAUSE_DNS_RC = (1L << 6), + NM_CONFIG_CHANGE_CAUSE_DNS_FULL = (1L << 7), + + NM_CONFIG_CHANGE_CAUSES = ((1L << 8) - 1), + + /************************************************************************** + * Following flags describe which property of the configuration changed: + *************************************************************************/ + + /* main-file or config-description changed */ + NM_CONFIG_CHANGE_CONFIG_FILES = (1L << 10), + + + /* any configuration on disk changed */ + NM_CONFIG_CHANGE_VALUES = (1L << 11), + + /* any user configuration on disk changed (NetworkManager.conf) */ + NM_CONFIG_CHANGE_VALUES_USER = (1L << 12), + + /* any internal configuration on disk changed (NetworkManager-intern.conf) */ + NM_CONFIG_CHANGE_VALUES_INTERN = (1L << 13), + + + /* configuration regarding connectivity changed */ + NM_CONFIG_CHANGE_CONNECTIVITY = (1L << 14), + + /* configuration regarding no-auto-default changed */ + NM_CONFIG_CHANGE_NO_AUTO_DEFAULT = (1L << 15), + + /* configuration regarding dns-mode changed */ + NM_CONFIG_CHANGE_DNS_MODE = (1L << 16), + + /* configuration regarding rc-manager changed */ + NM_CONFIG_CHANGE_RC_MANAGER = (1L << 17), + + /* configuration regarding global dns-config changed */ + NM_CONFIG_CHANGE_GLOBAL_DNS_CONFIG = (1L << 18), + } NMConfigChangeFlags; struct _NMConfigData { @@ -164,7 +210,5 @@ GKeyFile *_nm_config_data_get_keyfile (const NMConfigData *self); GKeyFile *_nm_config_data_get_keyfile_user (const NMConfigData *self); GKeyFile *_nm_config_data_get_keyfile_intern (const NMConfigData *self); -G_END_DECLS - #endif /* NM_CONFIG_DATA_H */ diff --git a/src/nm-config.c b/src/nm-config.c index 8bca6870..247b9a89 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -21,10 +21,11 @@ #include "nm-default.h" +#include "nm-config.h" + #include <string.h> #include <stdio.h> -#include "nm-config.h" #include "nm-utils.h" #include "nm-device.h" #include "NetworkManagerUtils.h" @@ -109,7 +110,7 @@ G_DEFINE_TYPE_WITH_CODE (NMConfig, nm_config, G_TYPE_OBJECT, /************************************************************************/ -static void _set_config_data (NMConfig *self, NMConfigData *new_data, int signal); +static void _set_config_data (NMConfig *self, NMConfigData *new_data, NMConfigChangeFlags reload_flags); /************************************************************************/ @@ -393,7 +394,7 @@ nm_config_set_no_auto_default_for_device (NMConfig *self, NMDevice *device) /* unref no_auto_default_set here. Note that _set_config_data() probably invalidates the content of the array. */ g_ptr_array_unref (no_auto_default_new); - _set_config_data (self, new_data, 0); + _set_config_data (self, new_data, NM_CONFIG_CHANGE_CAUSE_NO_AUTO_DEFAULT); } /************************************************************************/ @@ -634,6 +635,7 @@ read_config (GKeyFile *keyfile, gboolean is_base_config, const char *dirname, co kf = nm_config_create_keyfile (); if (!g_key_file_load_from_file (kf, path, G_KEY_FILE_NONE, error)) { + g_prefix_error (error, "%s: ", path); g_key_file_free (kf); return FALSE; } @@ -646,7 +648,7 @@ read_config (GKeyFile *keyfile, gboolean is_base_config, const char *dirname, co /* the config-group is internal to every configuration snippets. It doesn't make sense * to merge the into the global configuration, and it doesn't make sense to preserve the * group beyond this point. */ - g_key_file_remove_group (keyfile, NM_CONFIG_KEYFILE_GROUP_CONFIG, NULL); + g_key_file_remove_group (kf, NM_CONFIG_KEYFILE_GROUP_CONFIG, NULL); /* Override the current settings with the new ones */ groups = g_key_file_get_groups (kf, &ngroups); @@ -815,8 +817,7 @@ read_base_config (GKeyFile *keyfile, } if (!g_error_matches (my_error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND)) { - nm_log_warn (LOGD_CORE, "Old default config file %s invalid: %s\n", - DEFAULT_CONFIG_MAIN_FILE_OLD, + nm_log_warn (LOGD_CORE, "Old default config file invalid: %s\n", my_error->message); } g_clear_error (&my_error); @@ -828,8 +829,7 @@ read_base_config (GKeyFile *keyfile, } if (!g_error_matches (my_error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND)) { - nm_log_warn (LOGD_CORE, "Default config file %s invalid: %s\n", - DEFAULT_CONFIG_MAIN_FILE, + nm_log_warn (LOGD_CORE, "Default config file invalid: %s\n", my_error->message); g_propagate_error (error, my_error); return FALSE; @@ -1640,7 +1640,7 @@ nm_config_set_values (NMConfig *self, nm_log_dbg (LOGD_CORE, "don't persistate internal configuration (no file set, use --intern-config?)"); } if (new_data) - _set_config_data (self, new_data, 0); + _set_config_data (self, new_data, NM_CONFIG_CHANGE_CAUSE_SET_VALUES); g_key_file_unref (keyfile_new); } @@ -1648,7 +1648,7 @@ nm_config_set_values (NMConfig *self, /************************************************************************/ void -nm_config_reload (NMConfig *self, int signal) +nm_config_reload (NMConfig *self, NMConfigChangeFlags reload_flags) { NMConfigPrivate *priv; GError *error = NULL; @@ -1660,11 +1660,16 @@ nm_config_reload (NMConfig *self, int signal) gboolean intern_config_needs_rewrite; g_return_if_fail (NM_IS_CONFIG (self)); + g_return_if_fail ( reload_flags + && !NM_FLAGS_ANY (reload_flags, ~NM_CONFIG_CHANGE_CAUSES) + && !NM_FLAGS_ANY (reload_flags, NM_CONFIG_CHANGE_CAUSE_NO_AUTO_DEFAULT + | NM_CONFIG_CHANGE_CAUSE_SET_VALUES)); priv = NM_CONFIG_GET_PRIVATE (self); - if (signal != SIGHUP) { - _set_config_data (self, NULL, signal); + if (!NM_FLAGS_ANY (reload_flags, NM_CONFIG_CHANGE_CAUSE_SIGHUP | NM_CONFIG_CHANGE_CAUSE_CONF)) { + /* unless SIGHUP is specified, we don't reload the configuration from disc. */ + _set_config_data (self, NULL, reload_flags); return; } @@ -1681,7 +1686,7 @@ nm_config_reload (NMConfig *self, int signal) if (!keyfile) { nm_log_err (LOGD_CORE, "Failed to reload the configuration: %s", error->message); g_clear_error (&error); - _set_config_data (self, NULL, signal); + _set_config_data (self, NULL, reload_flags); return; } @@ -1703,13 +1708,20 @@ nm_config_reload (NMConfig *self, int signal) if (keyfile_intern) g_key_file_unref (keyfile_intern); - _set_config_data (self, new_data, signal); + _set_config_data (self, new_data, reload_flags); } NM_UTILS_FLAGS2STR_DEFINE (nm_config_change_flags_to_string, NMConfigChangeFlags, - NM_UTILS_FLAGS2STR (NM_CONFIG_CHANGE_SIGHUP, "SIGHUP"), - NM_UTILS_FLAGS2STR (NM_CONFIG_CHANGE_SIGUSR1, "SIGUSR1"), - NM_UTILS_FLAGS2STR (NM_CONFIG_CHANGE_SIGUSR2, "SIGUSR2"), + + NM_UTILS_FLAGS2STR (NM_CONFIG_CHANGE_CAUSE_CONF, "CONF"), + NM_UTILS_FLAGS2STR (NM_CONFIG_CHANGE_CAUSE_DNS_RC, "DNS_RC"), + NM_UTILS_FLAGS2STR (NM_CONFIG_CHANGE_CAUSE_DNS_FULL, "DNS_FULL"), + NM_UTILS_FLAGS2STR (NM_CONFIG_CHANGE_CAUSE_SIGHUP, "SIGHUP"), + NM_UTILS_FLAGS2STR (NM_CONFIG_CHANGE_CAUSE_SIGUSR1, "SIGUSR1"), + NM_UTILS_FLAGS2STR (NM_CONFIG_CHANGE_CAUSE_SIGUSR2, "SIGUSR2"), + NM_UTILS_FLAGS2STR (NM_CONFIG_CHANGE_CAUSE_NO_AUTO_DEFAULT, "NO_AUTO_DEFAULT"), + NM_UTILS_FLAGS2STR (NM_CONFIG_CHANGE_CAUSE_SET_VALUES, "SET_VALUES"), + NM_UTILS_FLAGS2STR (NM_CONFIG_CHANGE_CONFIG_FILES, "config-files"), NM_UTILS_FLAGS2STR (NM_CONFIG_CHANGE_VALUES, "values"), NM_UTILS_FLAGS2STR (NM_CONFIG_CHANGE_VALUES_USER, "values-user"), @@ -1722,27 +1734,19 @@ NM_UTILS_FLAGS2STR_DEFINE (nm_config_change_flags_to_string, NMConfigChangeFlags ); static void -_set_config_data (NMConfig *self, NMConfigData *new_data, int signal) +_set_config_data (NMConfig *self, NMConfigData *new_data, NMConfigChangeFlags reload_flags) { NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (self); NMConfigData *old_data = priv->config_data; NMConfigChangeFlags changes, changes_diff; gboolean had_new_data = !!new_data; - switch (signal) { - case SIGHUP: - changes = NM_CONFIG_CHANGE_SIGHUP; - break; - case SIGUSR1: - changes = NM_CONFIG_CHANGE_SIGUSR1; - break; - case SIGUSR2: - changes = NM_CONFIG_CHANGE_SIGUSR2; - break; - default: - changes = NM_CONFIG_CHANGE_NONE; - break; - } + nm_assert (reload_flags); + nm_assert (!NM_FLAGS_ANY (reload_flags, ~NM_CONFIG_CHANGE_CAUSES)); + nm_assert ( NM_IN_SET (reload_flags, NM_CONFIG_CHANGE_CAUSE_NO_AUTO_DEFAULT, NM_CONFIG_CHANGE_CAUSE_SET_VALUES) + || !NM_FLAGS_ANY (reload_flags, NM_CONFIG_CHANGE_CAUSE_NO_AUTO_DEFAULT | NM_CONFIG_CHANGE_CAUSE_SET_VALUES)); + + changes = reload_flags; if (new_data) { changes_diff = nm_config_data_diff (old_data, new_data); @@ -1752,12 +1756,19 @@ _set_config_data (NMConfig *self, NMConfigData *new_data, int signal) changes |= changes_diff; } - if (changes == NM_CONFIG_CHANGE_NONE) + if ( NM_IN_SET (reload_flags, + NM_CONFIG_CHANGE_CAUSE_NO_AUTO_DEFAULT, + NM_CONFIG_CHANGE_CAUSE_SET_VALUES, + NM_CONFIG_CHANGE_CAUSE_CONF) + && !new_data) { + /* no relevant changes that should be propagated. Return silently. */ return; + } if (new_data) { - nm_log_info (LOGD_CORE, "config: update %s (%s)", nm_config_data_get_config_description (new_data), - nm_config_change_flags_to_string (changes, NULL, 0)); + nm_log_info (LOGD_CORE, "config: signal %s (%s)", + nm_config_change_flags_to_string (changes, NULL, 0), + nm_config_data_get_config_description (new_data)); nm_config_data_log (new_data, "CONFIG: ", " ", NULL); priv->config_data = new_data; } else if (had_new_data) diff --git a/src/nm-config.h b/src/nm-config.h index 8bbab2ac..9a153e48 100644 --- a/src/nm-config.h +++ b/src/nm-config.h @@ -22,12 +22,8 @@ #ifndef __NETWORKMANAGER_CONFIG_H__ #define __NETWORKMANAGER_CONFIG_H__ - -#include "nm-default.h" #include "nm-config-data.h" -G_BEGIN_DECLS - #define NM_TYPE_CONFIG (nm_config_get_type ()) #define NM_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_CONFIG, NMConfig)) #define NM_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_CONFIG, NMConfigClass)) @@ -129,7 +125,7 @@ void nm_config_set_no_auto_default_for_device (NMConfig *config, NMDevice *devi NMConfig *nm_config_new (const NMConfigCmdLineOptions *cli, char **atomic_section_prefixes, GError **error); NMConfig *nm_config_setup (const NMConfigCmdLineOptions *cli, char **atomic_section_prefixes, GError **error); -void nm_config_reload (NMConfig *config, int signal); +void nm_config_reload (NMConfig *config, NMConfigChangeFlags reload_flags); gint nm_config_parse_boolean (const char *str, gint default_value); @@ -159,7 +155,5 @@ gboolean nm_config_set_global_dns (NMConfig *self, NMGlobalDnsConfig *global_dns extern guint _nm_config_match_nm_version; extern char *_nm_config_match_env; -G_END_DECLS - #endif /* __NETWORKMANAGER_CONFIG_H__ */ diff --git a/src/nm-connection-provider.c b/src/nm-connection-provider.c index 2e258bd5..e04cab92 100644 --- a/src/nm-connection-provider.c +++ b/src/nm-connection-provider.c @@ -106,24 +106,21 @@ nm_connection_provider_default_init (NMConnectionProviderInterface *g_iface) g_signal_new (NM_CP_SIGNAL_CONNECTION_ADDED, iface_type, G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMConnectionProviderInterface, connection_added), - NULL, NULL, + 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT); g_signal_new (NM_CP_SIGNAL_CONNECTION_UPDATED, iface_type, G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMConnectionProviderInterface, connection_updated), - NULL, NULL, + 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT); g_signal_new (NM_CP_SIGNAL_CONNECTION_REMOVED, iface_type, G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMConnectionProviderInterface, connection_removed), - NULL, NULL, + 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT); } diff --git a/src/nm-connection-provider.h b/src/nm-connection-provider.h index 2485c56f..b31af05f 100644 --- a/src/nm-connection-provider.h +++ b/src/nm-connection-provider.h @@ -63,14 +63,6 @@ typedef struct { NMConnection * (*get_connection_by_uuid) (NMConnectionProvider *self, const char *uuid); - - /* Signals */ - void (*connection_added) (NMConnectionProvider *self, NMConnection *connection); - - void (*connection_updated) (NMConnectionProvider *self, NMConnection *connection); - - void (*connection_removed) (NMConnectionProvider *self, NMConnection *connection); - } NMConnectionProviderInterface; GType nm_connection_provider_get_type (void); diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c index ef44a139..e9365c0c 100644 --- a/src/nm-core-utils.c +++ b/src/nm-core-utils.c @@ -1145,6 +1145,40 @@ nm_utils_find_helper(const char *progname, const char *try_first, GError **error /******************************************************************************************/ +/** + * nm_utils_read_link_absolute: + * @link_file: file name of the symbolic link + * @error: error reason in case of failure + * + * Uses to g_file_read_link()/readlink() to read the symlink + * and returns the result as absolute path. + **/ +char * +nm_utils_read_link_absolute (const char *link_file, GError **error) +{ + char *ln, *dirname, *ln_abs; + + ln = g_file_read_link (link_file, error); + if (!ln) + return NULL; + if (g_path_is_absolute (ln)) + return ln; + + dirname = g_path_get_dirname (link_file); + if (!g_path_is_absolute (link_file)) { + gs_free char *dirname_rel = dirname; + gs_free char *current_dir = g_get_current_dir (); + + dirname = g_build_filename (current_dir, dirname_rel, NULL); + } + ln_abs = g_build_filename (dirname, ln, NULL); + g_free (dirname); + g_free (ln); + return ln_abs; +} + +/******************************************************************************************/ + #define MAC_TAG "mac:" #define INTERFACE_NAME_TAG "interface-name:" #define DEVICE_TYPE_TAG "type:" @@ -2612,7 +2646,7 @@ nm_utils_machine_id_read (void) if (contents[i] != '\0') return FALSE; - return nm_unauto (&contents); + return g_steal_pointer (&contents); } /*****************************************************************************/ @@ -3085,3 +3119,145 @@ nm_utils_lifetime_get (guint32 timestamp, return TRUE; } +const char * +nm_utils_dnsmasq_status_to_string (int status, char *dest, guint size) +{ + static char buffer[128]; + char *msg, *ret; + gs_free char *msg_free = NULL; + int len; + + if (status == 0) + msg = "Success"; + else if (status == 1) + msg = "Configuration problem"; + else if (status == 2) + msg = "Network access problem (address in use, permissions)"; + else if (status == 3) + msg = "Filesystem problem (missing file/directory, permissions)"; + else if (status == 4) + msg = "Memory allocation failure"; + else if (status == 5) + msg = "Other problem"; + else if (status >= 11) + msg = msg_free = g_strdup_printf ("Lease script failed with error %d", status - 10); + else + msg = "Unknown problem"; + + if (dest) { + ret = dest; + len = size; + } else { + ret = buffer; + len = sizeof (buffer); + } + + g_snprintf (ret, len, "%s (%d)", msg, status); + + return ret; +} + +/** + * nm_utils_get_reverse_dns_domains_ip4: + * @addr: IP address in network order + * @plen: prefix length + * @domains: array for results + * + * Creates reverse DNS domains for the given address and prefix length, and + * append them to @domains. + */ +void +nm_utils_get_reverse_dns_domains_ip4 (guint32 addr, guint8 plen, GPtrArray *domains) +{ + guint32 ip, ip2, mask; + guchar *p; + guint octets; + guint i; + gsize len0, len; + char *str, *s; + + g_return_if_fail (domains); + g_return_if_fail (plen <= 32); + + if (!plen) + return; + + octets = (plen - 1) / 8 + 1; + ip = ntohl (addr); + mask = 0xFFFFFFFF << (32 - plen); + ip &= mask; + ip2 = ip; + + len0 = NM_STRLEN ("in-addr.arpa") + (4 * octets) + 1; + while ((ip2 & mask) == ip) { + addr = htonl (ip2); + p = (guchar *) &addr; + + len = len0; + str = s = g_malloc (len); + for (i = octets; i > 0; i--) + nm_utils_strbuf_append (&s, &len, "%u.", p[i - 1] & 0xff); + nm_utils_strbuf_append_str (&s, &len, "in-addr.arpa"); + + g_ptr_array_add (domains, str); + + ip2 += 1 << ((32 - plen) & ~7); + } +} + +/** + * nm_utils_get_reverse_dns_domains_ip6: + * @addr: IPv6 address + * @plen: prefix length + * @domains: array for results + * + * Creates reverse DNS domains for the given address and prefix length, and + * append them to @domains. + */ +void +nm_utils_get_reverse_dns_domains_ip6 (const struct in6_addr *ip, guint8 plen, GPtrArray *domains) +{ + struct in6_addr addr; + guint nibbles, bits, entries; + int i, j; + gsize len0, len; + char *str, *s; + + g_return_if_fail (domains); + g_return_if_fail (plen <= 128); + + if (!plen) + return; + + memcpy (&addr, ip, sizeof (struct in6_addr)); + nm_utils_ip6_address_clear_host_address (&addr, &addr, plen); + + /* Number of nibbles to include in domains */ + nibbles = (plen - 1) / 4 + 1; + /* Prefix length in nibble */ + bits = plen - ((plen - 1) / 4 * 4); + /* Number of domains */ + entries = 1 << (4 - bits); + + len0 = NM_STRLEN ("ip6.arpa") + (2 * nibbles) + 1; + +#define N_SHIFT(x) ((x) % 2 ? 0 : 4) + + for (i = 0; i < entries; i++) { + len = len0; + str = s = g_malloc (len); + + for (j = nibbles - 1; j >= 0; j--) + nm_utils_strbuf_append (&s, + &len, + "%x.", + (addr.s6_addr[j / 2] >> N_SHIFT (j)) & 0xf); + nm_utils_strbuf_append_str (&s, &len, "ip6.arpa"); + + g_ptr_array_add (domains, str); + + addr.s6_addr[(nibbles - 1) / 2] += 1 << N_SHIFT (nibbles - 1); + } + +#undef N_SHIFT +} diff --git a/src/nm-core-utils.h b/src/nm-core-utils.h index ad0f995f..a1213d2a 100644 --- a/src/nm-core-utils.h +++ b/src/nm-core-utils.h @@ -134,6 +134,8 @@ const char *nm_utils_find_helper (const char *progname, const char *try_first, GError **error); +char *nm_utils_read_link_absolute (const char *link_file, GError **error); + typedef enum { NM_MATCH_SPEC_NO_MATCH = 0, NM_MATCH_SPEC_MATCH = 1, @@ -394,4 +396,9 @@ gboolean nm_utils_lifetime_get (guint32 timestamp, gboolean nm_utils_ip4_address_is_link_local (in_addr_t addr); +const char *nm_utils_dnsmasq_status_to_string (int status, char *dest, guint size); + +void nm_utils_get_reverse_dns_domains_ip4 (guint32 ip, guint8 plen, GPtrArray *domains); +void nm_utils_get_reverse_dns_domains_ip6 (const struct in6_addr *ip, guint8 plen, GPtrArray *domains); + #endif /* __NM_CORE_UTILS_H__ */ diff --git a/src/nm-default-route-manager.c b/src/nm-default-route-manager.c index 3ee634a7..6f72ee84 100644 --- a/src/nm-default-route-manager.c +++ b/src/nm-default-route-manager.c @@ -727,16 +727,8 @@ _ipx_update_default_route (const VTableIP *vtable, NMDefaultRouteManager *self, if (device) ip_ifindex = nm_device_get_ip_ifindex (device); - else { - ip_ifindex = nm_vpn_connection_get_ip_ifindex (vpn); - - if (ip_ifindex <= 0) { - NMDevice *parent = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (vpn)); - - if (parent) - ip_ifindex = nm_device_get_ip_ifindex (parent); - } - } + else + ip_ifindex = nm_vpn_connection_get_ip_ifindex (vpn, TRUE); entries = vtable->get_entries (priv); entry = _entry_find_by_source (entries, source, &entry_idx); @@ -818,7 +810,7 @@ _ipx_update_default_route (const VTableIP *vtable, NMDefaultRouteManager *self, } } } - if (nm_vpn_connection_get_ip_ifindex (vpn) > 0) + if (nm_vpn_connection_get_ip_ifindex (vpn, FALSE) > 0) synced = TRUE; else { /* a VPN connection without tunnel device cannot have a non-synced, missing default route. @@ -1149,7 +1141,7 @@ _ipx_get_best_config (const VTableIP *vtable, if (out_ac) *out_ac = NM_ACTIVE_CONNECTION (vpn); if (out_ip_iface) - *out_ip_iface = nm_vpn_connection_get_ip_iface (vpn); + *out_ip_iface = nm_vpn_connection_get_ip_iface (vpn, TRUE); } else { NMDevice *device = entry->source.device; NMActRequest *req; diff --git a/src/nm-enum-types.c b/src/nm-enum-types.c index b3c82c63..b2f91dca 100644 --- a/src/nm-enum-types.c +++ b/src/nm-enum-types.c @@ -35,7 +35,6 @@ #include "nm-dns-unbound.h" #include "nm-dns-manager.h" #include "nm-dns-plugin.h" -#include "nm-dns-utils.h" #include "nm-dnsmasq-manager.h" #include "nm-dnsmasq-utils.h" #include "nmp-netns.h" @@ -188,26 +187,6 @@ nm_dns_ip_config_type_get_type (void) return g_define_type_id__volatile; } GType -nm_dns_manager_resolv_conf_mode_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_DNS_MANAGER_RESOLV_CONF_UNMANAGED, "NM_DNS_MANAGER_RESOLV_CONF_UNMANAGED", "unmanaged" }, - { NM_DNS_MANAGER_RESOLV_CONF_EXPLICIT, "NM_DNS_MANAGER_RESOLV_CONF_EXPLICIT", "explicit" }, - { NM_DNS_MANAGER_RESOLV_CONF_PROXY, "NM_DNS_MANAGER_RESOLV_CONF_PROXY", "proxy" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMDnsManagerResolvConfMode"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType nm_dns_manager_resolv_conf_manager_get_type (void) { static volatile gsize g_define_type_id__volatile = 0; @@ -215,11 +194,13 @@ nm_dns_manager_resolv_conf_manager_get_type (void) if (g_once_init_enter (&g_define_type_id__volatile)) { static const GEnumValue values[] = { - { _NM_DNS_MANAGER_RESOLV_CONF_MAN_INTERNAL_ONLY, "_NM_DNS_MANAGER_RESOLV_CONF_MAN_INTERNAL_ONLY", "-nm-dns-manager-resolv-conf-man-internal-only" }, - { NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE, "NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE", "nm-dns-manager-resolv-conf-man-none" }, - { NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE, "NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE", "nm-dns-manager-resolv-conf-man-file" }, - { NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF, "NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF", "nm-dns-manager-resolv-conf-man-resolvconf" }, - { NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG, "NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG", "nm-dns-manager-resolv-conf-man-netconfig" }, + { NM_DNS_MANAGER_RESOLV_CONF_MAN_UNKNOWN, "NM_DNS_MANAGER_RESOLV_CONF_MAN_UNKNOWN", "unknown" }, + { NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED, "NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED", "unmanaged" }, + { NM_DNS_MANAGER_RESOLV_CONF_MAN_IMMUTABLE, "NM_DNS_MANAGER_RESOLV_CONF_MAN_IMMUTABLE", "immutable" }, + { NM_DNS_MANAGER_RESOLV_CONF_MAN_SYMLINK, "NM_DNS_MANAGER_RESOLV_CONF_MAN_SYMLINK", "symlink" }, + { NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE, "NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE", "file" }, + { NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF, "NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF", "resolvconf" }, + { NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG, "NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG", "netconfig" }, { 0, NULL, NULL } }; GType g_define_type_id = @@ -523,21 +504,25 @@ nm_config_change_flags_get_type (void) if (g_once_init_enter (&g_define_type_id__volatile)) { static const GFlagsValue values[] = { - { NM_CONFIG_CHANGE_NONE, "NM_CONFIG_CHANGE_NONE", "nm-config-change-none" }, - { NM_CONFIG_CHANGE_SIGHUP, "NM_CONFIG_CHANGE_SIGHUP", "nm-config-change-sighup" }, - { NM_CONFIG_CHANGE_SIGUSR1, "NM_CONFIG_CHANGE_SIGUSR1", "nm-config-change-sigusr1" }, - { NM_CONFIG_CHANGE_SIGUSR2, "NM_CONFIG_CHANGE_SIGUSR2", "nm-config-change-sigusr2" }, - { NM_CONFIG_CHANGE_CONFIG_FILES, "NM_CONFIG_CHANGE_CONFIG_FILES", "nm-config-change-config-files" }, - { NM_CONFIG_CHANGE_VALUES, "NM_CONFIG_CHANGE_VALUES", "nm-config-change-values" }, - { NM_CONFIG_CHANGE_VALUES_USER, "NM_CONFIG_CHANGE_VALUES_USER", "nm-config-change-values-user" }, - { NM_CONFIG_CHANGE_VALUES_INTERN, "NM_CONFIG_CHANGE_VALUES_INTERN", "nm-config-change-values-intern" }, - { NM_CONFIG_CHANGE_CONNECTIVITY, "NM_CONFIG_CHANGE_CONNECTIVITY", "nm-config-change-connectivity" }, - { NM_CONFIG_CHANGE_NO_AUTO_DEFAULT, "NM_CONFIG_CHANGE_NO_AUTO_DEFAULT", "nm-config-change-no-auto-default" }, - { NM_CONFIG_CHANGE_DNS_MODE, "NM_CONFIG_CHANGE_DNS_MODE", "nm-config-change-dns-mode" }, - { NM_CONFIG_CHANGE_RC_MANAGER, "NM_CONFIG_CHANGE_RC_MANAGER", "nm-config-change-rc-manager" }, - { NM_CONFIG_CHANGE_GLOBAL_DNS_CONFIG, "NM_CONFIG_CHANGE_GLOBAL_DNS_CONFIG", "nm-config-change-global-dns-config" }, - { _NM_CONFIG_CHANGE_LAST, "_NM_CONFIG_CHANGE_LAST", "-nm-config-change-last" }, - { NM_CONFIG_CHANGE_ALL, "NM_CONFIG_CHANGE_ALL", "nm-config-change-all" }, + { NM_CONFIG_CHANGE_NONE, "NM_CONFIG_CHANGE_NONE", "none" }, + { NM_CONFIG_CHANGE_CAUSE_SIGHUP, "NM_CONFIG_CHANGE_CAUSE_SIGHUP", "cause-sighup" }, + { NM_CONFIG_CHANGE_CAUSE_SIGUSR1, "NM_CONFIG_CHANGE_CAUSE_SIGUSR1", "cause-sigusr1" }, + { NM_CONFIG_CHANGE_CAUSE_SIGUSR2, "NM_CONFIG_CHANGE_CAUSE_SIGUSR2", "cause-sigusr2" }, + { NM_CONFIG_CHANGE_CAUSE_NO_AUTO_DEFAULT, "NM_CONFIG_CHANGE_CAUSE_NO_AUTO_DEFAULT", "cause-no-auto-default" }, + { NM_CONFIG_CHANGE_CAUSE_SET_VALUES, "NM_CONFIG_CHANGE_CAUSE_SET_VALUES", "cause-set-values" }, + { NM_CONFIG_CHANGE_CAUSE_CONF, "NM_CONFIG_CHANGE_CAUSE_CONF", "cause-conf" }, + { NM_CONFIG_CHANGE_CAUSE_DNS_RC, "NM_CONFIG_CHANGE_CAUSE_DNS_RC", "cause-dns-rc" }, + { NM_CONFIG_CHANGE_CAUSE_DNS_FULL, "NM_CONFIG_CHANGE_CAUSE_DNS_FULL", "cause-dns-full" }, + { NM_CONFIG_CHANGE_CAUSES, "NM_CONFIG_CHANGE_CAUSES", "causes" }, + { NM_CONFIG_CHANGE_CONFIG_FILES, "NM_CONFIG_CHANGE_CONFIG_FILES", "config-files" }, + { NM_CONFIG_CHANGE_VALUES, "NM_CONFIG_CHANGE_VALUES", "values" }, + { NM_CONFIG_CHANGE_VALUES_USER, "NM_CONFIG_CHANGE_VALUES_USER", "values-user" }, + { NM_CONFIG_CHANGE_VALUES_INTERN, "NM_CONFIG_CHANGE_VALUES_INTERN", "values-intern" }, + { NM_CONFIG_CHANGE_CONNECTIVITY, "NM_CONFIG_CHANGE_CONNECTIVITY", "connectivity" }, + { NM_CONFIG_CHANGE_NO_AUTO_DEFAULT, "NM_CONFIG_CHANGE_NO_AUTO_DEFAULT", "no-auto-default" }, + { NM_CONFIG_CHANGE_DNS_MODE, "NM_CONFIG_CHANGE_DNS_MODE", "dns-mode" }, + { NM_CONFIG_CHANGE_RC_MANAGER, "NM_CONFIG_CHANGE_RC_MANAGER", "rc-manager" }, + { NM_CONFIG_CHANGE_GLOBAL_DNS_CONFIG, "NM_CONFIG_CHANGE_GLOBAL_DNS_CONFIG", "global-dns-config" }, { 0, NULL, NULL } }; GType g_define_type_id = diff --git a/src/nm-enum-types.h b/src/nm-enum-types.h index 8fe52e19..36a9c270 100644 --- a/src/nm-enum-types.h +++ b/src/nm-enum-types.h @@ -18,8 +18,6 @@ GType nm_dhcp_state_get_type (void) G_GNUC_CONST; #define NM_TYPE_DHCP_STATE (nm_dhcp_state_get_type ()) GType nm_dns_ip_config_type_get_type (void) G_GNUC_CONST; #define NM_TYPE_DNS_IP_CONFIG_TYPE (nm_dns_ip_config_type_get_type ()) -GType nm_dns_manager_resolv_conf_mode_get_type (void) G_GNUC_CONST; -#define NM_TYPE_DNS_MANAGER_RESOLV_CONF_MODE (nm_dns_manager_resolv_conf_mode_get_type ()) GType nm_dns_manager_resolv_conf_manager_get_type (void) G_GNUC_CONST; #define NM_TYPE_DNS_MANAGER_RESOLV_CONF_MANAGER (nm_dns_manager_resolv_conf_manager_get_type ()) GType nm_dns_masq_status_get_type (void) G_GNUC_CONST; diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index 75caf7e3..0ae7d0d4 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -58,6 +58,7 @@ typedef struct _NMIP4ConfigPrivate { int ifindex; gint64 route_metric; gboolean metered; + gint dns_priority; } NMIP4ConfigPrivate; /* internal guint32 are assigned to gobject properties of type uint. Ensure, that uint is large enough */ @@ -76,6 +77,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMIP4Config, PROP_SEARCHES, PROP_DNS_OPTIONS, PROP_WINS_SERVERS, + PROP_DNS_PRIORITY, ); NMIP4Config * @@ -427,7 +429,7 @@ nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIPConfig *setting, gu { NMIP4ConfigPrivate *priv; guint naddresses, nroutes, nnameservers, nsearches; - int i; + int i, priority; if (!setting) return; @@ -526,6 +528,10 @@ nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIPConfig *setting, gu i++; } + priority = nm_setting_ip_config_get_dns_priority (setting); + if (priority) + nm_ip4_config_set_dns_priority (config, priority); + g_object_thaw_notify (G_OBJECT (config)); } @@ -635,6 +641,11 @@ nm_ip4_config_create_setting (const NMIP4Config *config) nm_setting_ip_config_add_dns_option (s_ip4, option); } + g_object_set (s_ip4, + NM_SETTING_IP_CONFIG_DNS_PRIORITY, + nm_ip4_config_get_dns_priority (config), + NULL); + return NM_SETTING (s_ip4); } @@ -725,6 +736,10 @@ nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src, NMIPConfigMergeFl nm_ip4_config_set_metered (dst, nm_ip4_config_get_metered (dst) || nm_ip4_config_get_metered (src)); + /* DNS priority */ + if (nm_ip4_config_get_dns_priority (src)) + nm_ip4_config_set_dns_priority (dst, nm_ip4_config_get_dns_priority (src)); + g_object_thaw_notify (G_OBJECT (dst)); } @@ -948,6 +963,10 @@ nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src) nm_ip4_config_del_wins (dst, idx); } + /* DNS priority */ + if (nm_ip4_config_get_dns_priority (src) == nm_ip4_config_get_dns_priority (dst)) + nm_ip4_config_set_dns_priority (dst, 0); + g_object_thaw_notify (G_OBJECT (dst)); } @@ -1188,6 +1207,12 @@ nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relev has_relevant_changes = TRUE; } + /* DNS priority */ + if (src_priv->dns_priority != dst_priv->dns_priority) { + nm_ip4_config_set_dns_priority (dst, src_priv->dns_priority); + has_minor_changes = TRUE; + } + /* mss */ if (src_priv->mss != dst_priv->mss) { nm_ip4_config_set_mss (dst, src_priv->mss); @@ -1311,6 +1336,7 @@ nm_ip4_config_dump (const NMIP4Config *config, const char *detail) for (i = 0; i < nm_ip4_config_get_num_dns_options (config); i++) g_message (" dnsopt: %s", nm_ip4_config_get_dns_option (config, i)); + g_message (" dnspri: %d", nm_ip4_config_get_dns_priority (config)); g_message (" mss: %"G_GUINT32_FORMAT, nm_ip4_config_get_mss (config)); g_message (" mtu: %"G_GUINT32_FORMAT, nm_ip4_config_get_mtu (config)); @@ -1901,6 +1927,27 @@ nm_ip4_config_get_dns_option (const NMIP4Config *config, guint i) /******************************************************************/ void +nm_ip4_config_set_dns_priority (NMIP4Config *config, gint priority) +{ + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + + if (priority != priv->dns_priority) { + priv->dns_priority = priority; + _notify (config, PROP_DNS_PRIORITY); + } +} + +gint +nm_ip4_config_get_dns_priority (const NMIP4Config *config) +{ + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + + return priv->dns_priority; +} + +/******************************************************************/ + +void nm_ip4_config_set_mss (NMIP4Config *config, guint32 mss) { NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); @@ -2151,7 +2198,6 @@ nm_ip4_config_hash (const NMIP4Config *config, GChecksum *sum, gboolean dns_only s = nm_ip4_config_get_dns_option (config, i); g_checksum_update (sum, (const guint8 *) s, strlen (s)); } - } /** @@ -2386,6 +2432,9 @@ get_property (GObject *object, guint prop_id, case PROP_DNS_OPTIONS: nm_utils_g_value_set_strv (value, priv->dns_options); break; + case PROP_DNS_PRIORITY: + g_value_set_int (value, priv->dns_priority); + break; case PROP_WINS_SERVERS: g_value_take_variant (value, g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32, @@ -2488,7 +2537,11 @@ nm_ip4_config_class_init (NMIP4ConfigClass *config_class) G_TYPE_STRV, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - + obj_properties[PROP_DNS_PRIORITY] = + g_param_spec_int (NM_IP4_CONFIG_DNS_PRIORITY, "", "", + G_MININT32, G_MAXINT32, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); obj_properties[PROP_WINS_SERVERS] = g_param_spec_variant (NM_IP4_CONFIG_WINS_SERVERS, "", "", G_VARIANT_TYPE ("au"), diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h index b1a57687..e88fb141 100644 --- a/src/nm-ip4-config.h +++ b/src/nm-ip4-config.h @@ -55,6 +55,7 @@ typedef struct { #define NM_IP4_CONFIG_DOMAINS "domains" #define NM_IP4_CONFIG_SEARCHES "searches" #define NM_IP4_CONFIG_DNS_OPTIONS "dns-options" +#define NM_IP4_CONFIG_DNS_PRIORITY "dns-priority" #define NM_IP4_CONFIG_WINS_SERVERS "wins-servers" /* deprecated */ @@ -137,6 +138,10 @@ void nm_ip4_config_del_dns_option (NMIP4Config *config, guint i); guint32 nm_ip4_config_get_num_dns_options (const NMIP4Config *config); const char * nm_ip4_config_get_dns_option (const NMIP4Config *config, guint i); +/* DNS priority */ +void nm_ip4_config_set_dns_priority (NMIP4Config *config, gint priority); +gint nm_ip4_config_get_dns_priority (const NMIP4Config *config); + /* MSS */ void nm_ip4_config_set_mss (NMIP4Config *config, guint32 mss); guint32 nm_ip4_config_get_mss (const NMIP4Config *config); diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c index 8e7bd22c..86447357 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -50,6 +50,7 @@ typedef struct _NMIP6ConfigPrivate { guint32 mss; int ifindex; gint64 route_metric; + gint dns_priority; } NMIP6ConfigPrivate; @@ -64,6 +65,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMIP6Config, PROP_DOMAINS, PROP_SEARCHES, PROP_DNS_OPTIONS, + PROP_DNS_PRIORITY, ); NMIP6Config * @@ -414,7 +416,7 @@ nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIPConfig *setting, gu NMIP6ConfigPrivate *priv; guint naddresses, nroutes, nnameservers, nsearches; const char *gateway_str; - int i; + int i, priority; if (!setting) return; @@ -508,6 +510,10 @@ nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIPConfig *setting, gu i++; } + priority = nm_setting_ip_config_get_dns_priority (setting); + if (priority) + nm_ip6_config_set_dns_priority (config, priority); + g_object_thaw_notify (G_OBJECT (config)); } @@ -624,6 +630,10 @@ nm_ip6_config_create_setting (const NMIP6Config *config) nm_setting_ip_config_add_dns_option (s_ip6, option); } + g_object_set (s_ip6, + NM_SETTING_IP_CONFIG_DNS_PRIORITY, + nm_ip6_config_get_dns_priority (config), + NULL); return NM_SETTING (s_ip6); } @@ -690,6 +700,10 @@ nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src, NMIPConfigMergeFl if (nm_ip6_config_get_mss (src)) nm_ip6_config_set_mss (dst, nm_ip6_config_get_mss (src)); + /* DNS priority */ + if (nm_ip6_config_get_dns_priority (src)) + nm_ip6_config_set_dns_priority (dst, nm_ip6_config_get_dns_priority (src)); + g_object_thaw_notify (G_OBJECT (dst)); } @@ -883,6 +897,10 @@ nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src) if (nm_ip6_config_get_mss (src) == nm_ip6_config_get_mss (dst)) nm_ip6_config_set_mss (dst, 0); + /* DNS priority */ + if (nm_ip6_config_get_dns_priority (src) == nm_ip6_config_get_dns_priority (dst)) + nm_ip6_config_set_dns_priority (dst, 0); + g_object_thaw_notify (G_OBJECT (dst)); } @@ -1129,6 +1147,12 @@ nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relev has_minor_changes = TRUE; } + /* DNS priority */ + if (src_priv->dns_priority != dst_priv->dns_priority) { + nm_ip6_config_set_dns_priority (dst, src_priv->dns_priority); + has_minor_changes = TRUE; + } + #if NM_MORE_ASSERTS /* config_equal does not compare *all* the fields, therefore, we might have has_minor_changes * regardless of config_equal. But config_equal must correspond to has_relevant_changes. */ @@ -1189,6 +1213,8 @@ nm_ip6_config_dump (const NMIP6Config *config, const char *detail) for (i = 0; i < nm_ip6_config_get_num_dns_options (config); i++) g_message (" dnsopt: %s", nm_ip6_config_get_dns_option (config, i)); + g_message (" dnspri: %d", nm_ip6_config_get_dns_priority (config)); + g_message (" mss: %"G_GUINT32_FORMAT, nm_ip6_config_get_mss (config)); g_message (" n-dflt: %d", nm_ip6_config_get_never_default (config)); } @@ -1761,6 +1787,27 @@ nm_ip6_config_get_dns_option (const NMIP6Config *config, guint i) /******************************************************************/ void +nm_ip6_config_set_dns_priority (NMIP6Config *config, gint priority) +{ + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + + if (priority != priv->dns_priority) { + priv->dns_priority = priority; + _notify (config, PROP_DNS_PRIORITY); + } +} + +gint +nm_ip6_config_get_dns_priority (const NMIP6Config *config) +{ + const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + + return priv->dns_priority; +} + +/******************************************************************/ + +void nm_ip6_config_set_mss (NMIP6Config *config, guint32 mss) { NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); @@ -1839,7 +1886,6 @@ nm_ip6_config_hash (const NMIP6Config *config, GChecksum *sum, gboolean dns_only s = nm_ip6_config_get_dns_option (config, i); g_checksum_update (sum, (const guint8 *) s, strlen (s)); } - } /** @@ -2079,6 +2125,9 @@ get_property (GObject *object, guint prop_id, case PROP_DNS_OPTIONS: nm_utils_g_value_set_strv (value, priv->dns_options); break; + case PROP_DNS_PRIORITY: + g_value_set_int (value, priv->dns_priority); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -2176,6 +2225,11 @@ nm_ip6_config_class_init (NMIP6ConfigClass *config_class) G_TYPE_STRV, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_DNS_PRIORITY] = + g_param_spec_int (NM_IP6_CONFIG_DNS_PRIORITY, "", "", + G_MININT32, G_MAXINT32, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h index 5e66d500..010b1396 100644 --- a/src/nm-ip6-config.h +++ b/src/nm-ip6-config.h @@ -57,6 +57,7 @@ typedef struct { #define NM_IP6_CONFIG_DOMAINS "domains" #define NM_IP6_CONFIG_SEARCHES "searches" #define NM_IP6_CONFIG_DNS_OPTIONS "dns-options" +#define NM_IP6_CONFIG_DNS_PRIORITY "dns-priority" /* deprecated */ #define NM_IP6_CONFIG_ADDRESSES "addresses" @@ -139,6 +140,10 @@ void nm_ip6_config_del_dns_option (NMIP6Config *config, guint i); guint32 nm_ip6_config_get_num_dns_options (const NMIP6Config *config); const char * nm_ip6_config_get_dns_option (const NMIP6Config *config, guint i); +/* DNS priority */ +void nm_ip6_config_set_dns_priority (NMIP6Config *config, gint priority); +gint nm_ip6_config_get_dns_priority (const NMIP6Config *config); + /* MSS */ void nm_ip6_config_set_mss (NMIP6Config *config, guint32 mss); guint32 nm_ip6_config_get_mss (const NMIP6Config *config); diff --git a/src/nm-manager.c b/src/nm-manager.c index e64c68af..8277f6b0 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -28,6 +28,7 @@ #include <unistd.h> #include "nm-manager.h" +#include "nm-common-macros.h" #include "nm-bus-manager.h" #include "nm-vpn-manager.h" #include "nm-device.h" @@ -68,8 +69,6 @@ static NMActiveConnection *_new_active_connection (NMManager *self, static void policy_activating_device_changed (GObject *object, GParamSpec *pspec, gpointer user_data); -static void rfkill_change (const char *desc, RfKillType rtype, gboolean enabled); - static gboolean find_master (NMManager *self, NMConnection *connection, NMDevice *device, @@ -80,8 +79,10 @@ static gboolean find_master (NMManager *self, static void nm_manager_update_state (NMManager *manager); -static void connection_changed (NMSettings *settings, NMConnection *connection, - NMManager *manager); +static void connection_changed (NMManager *self, NMConnection *connection); +static void device_sleep_cb (NMDevice *device, + GParamSpec *pspec, + NMManager *self); #define TAG_ACTIVE_CONNETION_ADD_AND_ACTIVATE "act-con-add-and-activate" @@ -132,6 +133,7 @@ typedef struct { NMSleepMonitor *sleep_monitor; GSList *auth_chains; + GHashTable *sleep_devices; /* Firmware dir monitor */ GFileMonitor *fw_monitor; @@ -457,6 +459,104 @@ _config_changed_cb (NMConfig *config, NMConfigData *config_data, NMConfigChangeF _notify (self, PROP_GLOBAL_DNS_CONFIGURATION); } +static void +_reload_auth_cb (NMAuthChain *chain, + GError *error, + GDBusMethodInvocation *context, + gpointer user_data) +{ + NMManager *self = NM_MANAGER (user_data); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + GError *ret_error = NULL; + NMAuthCallResult result; + guint32 flags; + NMAuthSubject *subject; + char s_buf[60]; + NMConfigChangeFlags reload_type = NM_CONFIG_CHANGE_NONE; + + g_assert (context); + + priv->auth_chains = g_slist_remove (priv->auth_chains, chain); + flags = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, "flags")); + + subject = nm_auth_chain_get_subject (chain); + + result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_RELOAD); + if (error) { + _LOGD (LOGD_CORE, "Reload request failed: %s", error->message); + ret_error = g_error_new (NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + "Reload request failed: %s", + error->message); + } else if (result != NM_AUTH_CALL_RESULT_YES) { + ret_error = g_error_new_literal (NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + "Not authorized to reload configuration"); + } else { + if (NM_FLAGS_ANY (flags, ~NM_MANAGER_RELOAD_FLAGS_ALL)) { + /* invalid flags */ + } else if (flags == 0) + reload_type = NM_CONFIG_CHANGE_CAUSE_SIGHUP; + else { + if (NM_FLAGS_HAS (flags, NM_MANAGER_RELOAD_FLAGS_CONF)) + reload_type |= NM_CONFIG_CHANGE_CAUSE_CONF; + if (NM_FLAGS_HAS (flags, NM_MANAGER_RELOAD_FLAGS_DNS_RC)) + reload_type |= NM_CONFIG_CHANGE_CAUSE_DNS_RC; + if (NM_FLAGS_HAS (flags, NM_MANAGER_RELOAD_FLAGS_DNS_FULL)) + reload_type |= NM_CONFIG_CHANGE_CAUSE_DNS_FULL; + } + + if (reload_type == NM_CONFIG_CHANGE_NONE) { + ret_error = g_error_new_literal (NM_MANAGER_ERROR, + NM_MANAGER_ERROR_INVALID_ARGUMENTS, + "Invalid flags for reload"); + } + } + + nm_audit_log_control_op (NM_AUDIT_OP_RELOAD, + nm_sprintf_buf (s_buf, "%u", flags), + ret_error == NULL, subject, + ret_error ? ret_error->message : NULL); + + if (ret_error) { + g_dbus_method_invocation_take_error (context, ret_error); + goto out; + } + + nm_config_reload (priv->config, reload_type); + g_dbus_method_invocation_return_value (context, NULL); + +out: + nm_auth_chain_unref (chain); +} + +static void +impl_manager_reload (NMManager *self, + GDBusMethodInvocation *context, + guint32 flags) +{ + NMManagerPrivate *priv; + NMAuthChain *chain; + GError *error = NULL; + + g_return_if_fail (NM_IS_MANAGER (self)); + + priv = NM_MANAGER_GET_PRIVATE (self); + + chain = nm_auth_chain_new_context (context, _reload_auth_cb, self); + if (!chain) { + error = g_error_new_literal (NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + "Unable to authenticate request"); + g_dbus_method_invocation_take_error (context, error); + return; + } + + priv->auth_chains = g_slist_append (priv->auth_chains, chain); + nm_auth_chain_set_data (chain, "flags", GUINT_TO_POINTER (flags), NULL); + nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_RELOAD, TRUE); +} + /************************************************************************/ static NMDevice * @@ -839,19 +939,29 @@ remove_device (NMManager *self, nm_device_get_iface (device), allow_unmanage, nm_device_get_managed (device, FALSE)); if (allow_unmanage && nm_device_get_managed (device, FALSE)) { - NMActRequest *req = nm_device_get_act_request (device); + unmanage = TRUE; - /* Leave activated interfaces up when quitting so their configuration - * can be taken over when NM restarts. This ensures connectivity while - * NM is stopped. Devices which do not support connection assumption - * cannot be left up. - */ - if (!quitting) /* Forced removal; device already gone */ - unmanage = TRUE; - else if (!nm_device_can_assume_active_connection (device)) - unmanage = TRUE; - else if (!req) - unmanage = TRUE; + if (!quitting) { + /* the device is already gone. Unmanage it. */ + } else { + /* Leave certain devices alone when quitting so their configuration + * can be taken over when NM restarts. This ensures connectivity while + * NM is stopped. + */ + if (nm_device_uses_assumed_connection (device)) { + /* An assume connection must be left alone */ + unmanage = FALSE; + } else if (!nm_device_get_act_request (device)) { + /* a device without any active connection is either UNAVAILABLE or DISCONNECTED + * state. Since we don't know whether the device was upped by NetworkManager, + * we must leave it up on exit. */ + unmanage = FALSE; + } else if (!nm_platform_link_can_assume (NM_PLATFORM_GET, nm_device_get_ifindex (device))) { + /* The device has no layer 3 configuration. Leave it up. */ + unmanage = FALSE; + } else if (nm_device_can_assume_active_connection (device)) + unmanage = FALSE; + } if (unmanage) { if (quitting) @@ -1162,7 +1272,7 @@ retry_connections_for_parent_device (NMManager *self, NMDevice *device) ifname = nm_manager_get_connection_iface (self, candidate, &parent, &error); if (ifname) { if (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, ifname)) - connection_changed (priv->settings, candidate, self); + connection_changed (self, candidate); } } } @@ -1171,34 +1281,40 @@ retry_connections_for_parent_device (NMManager *self, NMDevice *device) } static void -connection_changed (NMSettings *settings, - NMConnection *connection, - NMManager *manager) +connection_changed (NMManager *self, + NMConnection *connection) { NMDevice *device; if (!nm_connection_is_virtual (connection)) return; - device = system_create_virtual_device (manager, connection); + device = system_create_virtual_device (self, connection); if (!device) return; /* Maybe the device that was created was needed by some other * connection's device (parent of a VLAN). Let the connections * can use the newly created device as a parent know. */ - retry_connections_for_parent_device (manager, device); + retry_connections_for_parent_device (self, device); } static void -connection_removed (NMSettings *settings, - NMSettingsConnection *connection, - NMManager *manager) +connection_added_cb (NMSettings *settings, + NMConnection *connection, + NMManager *self) { - /* - * Do not delete existing virtual devices to keep connectivity up. - * Virtual devices are reused when NetworkManager is restarted. - */ + connection_changed (self, connection); +} + +static void +connection_updated_cb (NMSettings *settings, + NMConnection *connection, + gboolean by_user, + NMManager *self) +{ + if (by_user) + connection_changed (self, connection); } static void @@ -2777,13 +2893,13 @@ active_connection_parent_active (NMActiveConnection *active, /* We can now proceed to disconnected state so that activation proceeds. */ unmanaged_to_disconnected (device); } else { - nm_log_warn (LOGD_CORE, "Could not realize device '%s': %s", - nm_device_get_iface (device), error->message); + _LOGW (LOGD_CORE, "Could not realize device '%s': %s", + nm_device_get_iface (device), error->message); nm_active_connection_set_state (active, NM_ACTIVE_CONNECTION_STATE_DEACTIVATED); } } else { - nm_log_warn (LOGD_CORE, "The parent connection device '%s' depended on disappeared.", - nm_device_get_iface (device)); + _LOGW (LOGD_CORE, "The parent connection device '%s' depended on disappeared.", + nm_device_get_iface (device)); nm_active_connection_set_state (active, NM_ACTIVE_CONNECTION_STATE_DEACTIVATED); } } @@ -3268,7 +3384,7 @@ validate_activation_request (NMManager *self, NM_MANAGER_ERROR, NM_MANAGER_ERROR_CONNECTION_NOT_AVAILABLE, "Sharing IPv6 connections is not supported yet."); - return NULL; + goto error; } /* Check whether it's a VPN or not */ @@ -3849,6 +3965,98 @@ device_is_wake_on_lan (NMDevice *device) return nm_platform_link_get_wake_on_lan (NM_PLATFORM_GET, nm_device_get_ip_ifindex (device)); } +static gboolean +sleep_devices_add (NMManager *self, NMDevice *device, gboolean suspending) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + NMSleepMonitorInhibitorHandle *handle = NULL; + + if (g_hash_table_lookup_extended (priv->sleep_devices, device, NULL, (gpointer *) &handle)) { + if (suspending) { + /* if we are suspending, always insert a new handle in sleep_devices. + * Even if we had an old handle, it might be stale by now. */ + g_hash_table_insert (priv->sleep_devices, device, + nm_sleep_monitor_inhibit_take (priv->sleep_monitor)); + if (handle) + nm_sleep_monitor_inhibit_release (priv->sleep_monitor, handle); + } + return FALSE; + } + + g_hash_table_insert (priv->sleep_devices, + g_object_ref (device), + suspending + ? nm_sleep_monitor_inhibit_take (priv->sleep_monitor) + : NULL); + g_signal_connect (device, "notify::" NM_DEVICE_STATE, (GCallback) device_sleep_cb, self); + return TRUE; +} + +static gboolean +sleep_devices_remove (NMManager *self, NMDevice *device) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + NMSleepMonitorInhibitorHandle *handle; + + if (!g_hash_table_lookup_extended (priv->sleep_devices, device, NULL, (gpointer *) &handle)) + return FALSE; + + if (handle) + nm_sleep_monitor_inhibit_release (priv->sleep_monitor, handle); + + /* Remove device from hash */ + g_signal_handlers_disconnect_by_func (device, device_sleep_cb, self); + g_hash_table_remove (priv->sleep_devices, device); + g_object_unref (device); + return TRUE; +} + +static void +sleep_devices_clear (NMManager *self) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + NMDevice *device; + NMSleepMonitorInhibitorHandle *handle; + GHashTableIter iter; + + if (!priv->sleep_devices) + return; + + g_hash_table_iter_init (&iter, priv->sleep_devices); + while (g_hash_table_iter_next (&iter, (gpointer *) &device, (gpointer *) &handle)) { + g_signal_handlers_disconnect_by_func (device, device_sleep_cb, self); + if (handle) + nm_sleep_monitor_inhibit_release (priv->sleep_monitor, handle); + g_object_unref (device); + g_hash_table_iter_remove (&iter); + } +} + +static void +device_sleep_cb (NMDevice *device, + GParamSpec *pspec, + NMManager *self) +{ + switch (nm_device_get_state (device)) { + case NM_DEVICE_STATE_DISCONNECTED: + _LOGD (LOGD_SUSPEND, "sleep: unmanaging device %s", nm_device_get_ip_iface (device)); + nm_device_set_unmanaged_by_flags_queue (device, + NM_UNMANAGED_SLEEPING, + TRUE, + NM_DEVICE_STATE_REASON_SLEEPING); + break; + case NM_DEVICE_STATE_UNMANAGED: + _LOGD (LOGD_SUSPEND, "sleep: device %s is ready", nm_device_get_ip_iface (device)); + + if (!sleep_devices_remove (self, device)) + g_return_if_reached (); + + break; + default: + return; + } +} + static void do_sleep_wake (NMManager *self, gboolean sleeping_changed) { @@ -3872,15 +4080,28 @@ do_sleep_wake (NMManager *self, gboolean sleeping_changed) if (nm_device_is_software (device)) continue; /* Wake-on-LAN devices will be taken down post-suspend rather than pre- */ - if (suspending && device_is_wake_on_lan (device)) + if (suspending && device_is_wake_on_lan (device)) { + _LOGD (LOGD_SUSPEND, "sleep: device %s has wake-on-lan, skipping", + nm_device_get_ip_iface (device)); continue; + } + + if (nm_device_is_activating (device) || + nm_device_get_state (device) == NM_DEVICE_STATE_ACTIVATED) { + _LOGD (LOGD_SUSPEND, "sleep: wait disconnection of device %s", + nm_device_get_ip_iface (device)); - nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_SLEEPING, TRUE, NM_DEVICE_STATE_REASON_SLEEPING); + if (sleep_devices_add (self, device, suspending)) + nm_device_queue_state (device, NM_DEVICE_STATE_DEACTIVATING, NM_DEVICE_STATE_REASON_SLEEPING); + } else { + nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_SLEEPING, TRUE, NM_DEVICE_STATE_REASON_SLEEPING); + } } } else { _LOGI (LOGD_SUSPEND, "%s...", waking_from_suspend ? "waking up" : "re-enabling"); if (waking_from_suspend) { + sleep_devices_clear (self); /* Belatedly take down Wake-on-LAN devices; ideally we wouldn't have to do this * but for now it's the only way to make sure we re-check their connectivity. */ @@ -3941,7 +4162,11 @@ do_sleep_wake (NMManager *self, gboolean sleeping_changed) static void _internal_sleep (NMManager *self, gboolean do_sleep) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + NMManagerPrivate *priv; + + g_return_if_fail (NM_IS_MANAGER (self)); + + priv = NM_MANAGER_GET_PRIVATE (self); if (priv->sleeping == do_sleep) return; @@ -4054,17 +4279,12 @@ impl_manager_sleep (NMManager *self, } static void -sleeping_cb (NMSleepMonitor *monitor, gpointer user_data) +sleeping_cb (NMSleepMonitor *monitor, gboolean is_about_to_suspend, gpointer user_data) { - nm_log_dbg (LOGD_SUSPEND, "Received sleeping signal"); - _internal_sleep (NM_MANAGER (user_data), TRUE); -} + NMManager *self = user_data; -static void -resuming_cb (NMSleepMonitor *monitor, gpointer user_data) -{ - nm_log_dbg (LOGD_SUSPEND, "Received resuming signal"); - _internal_sleep (NM_MANAGER (user_data), FALSE); + _LOGD (LOGD_SUSPEND, "Received %s signal", is_about_to_suspend ? "sleeping" : "resuming"); + _internal_sleep (self, is_about_to_suspend); } static void @@ -4186,7 +4406,7 @@ done: /* Permissions */ static void -get_perm_add_result (NMAuthChain *chain, GVariantBuilder *results, const char *permission) +get_perm_add_result (NMManager *self, NMAuthChain *chain, GVariantBuilder *results, const char *permission) { NMAuthCallResult result; @@ -4198,7 +4418,7 @@ get_perm_add_result (NMAuthChain *chain, GVariantBuilder *results, const char *p else if (result == NM_AUTH_CALL_RESULT_AUTH) g_variant_builder_add (results, "{ss}", permission, "auth"); else { - nm_log_dbg (LOGD_CORE, "unknown auth chain result %d", result); + _LOGD (LOGD_CORE, "unknown auth chain result %d", result); } } @@ -4226,17 +4446,18 @@ get_permissions_done_cb (NMAuthChain *chain, } else { g_variant_builder_init (&results, G_VARIANT_TYPE ("a{ss}")); - get_perm_add_result (chain, &results, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK); - get_perm_add_result (chain, &results, NM_AUTH_PERMISSION_SLEEP_WAKE); - get_perm_add_result (chain, &results, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI); - get_perm_add_result (chain, &results, NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN); - get_perm_add_result (chain, &results, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX); - get_perm_add_result (chain, &results, NM_AUTH_PERMISSION_NETWORK_CONTROL); - get_perm_add_result (chain, &results, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED); - get_perm_add_result (chain, &results, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN); - get_perm_add_result (chain, &results, NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM); - get_perm_add_result (chain, &results, NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN); - get_perm_add_result (chain, &results, NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME); + get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK); + get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_SLEEP_WAKE); + get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI); + get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN); + get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX); + get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_NETWORK_CONTROL); + get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED); + get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN); + get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM); + get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN); + get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME); + get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_RELOAD); g_dbus_method_invocation_return_value (context, g_variant_new ("(a{ss})", &results)); @@ -4274,6 +4495,7 @@ impl_manager_get_permissions (NMManager *self, nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM, FALSE); nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN, FALSE); nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME, FALSE); + nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_RELOAD, FALSE); } static void @@ -4473,7 +4695,7 @@ nm_manager_start (NMManager *self, GError **error) _LOGD (LOGD_CORE, "creating virtual devices..."); connections = nm_settings_get_connections (priv->settings); for (iter = connections; iter; iter = iter->next) - connection_changed (priv->settings, NM_CONNECTION (iter->data), self); + connection_changed (self, NM_CONNECTION (iter->data)); g_slist_free (connections); priv->devices_inited = TRUE; @@ -4965,7 +5187,7 @@ struct rfkill_event { } __attribute__((packed)); static void -rfkill_change (const char *desc, RfKillType rtype, gboolean enabled) +rfkill_change (NMManager *self, const char *desc, RfKillType rtype, gboolean enabled) { int fd; struct rfkill_event event; @@ -4977,13 +5199,13 @@ rfkill_change (const char *desc, RfKillType rtype, gboolean enabled) fd = open ("/dev/rfkill", O_RDWR); if (fd < 0) { if (errno == EACCES) - nm_log_warn (LOGD_RFKILL, "(%s): failed to open killswitch device", desc); + _LOGW (LOGD_RFKILL, "(%s): failed to open killswitch device", desc); return; } if (fcntl (fd, F_SETFL, O_NONBLOCK) < 0) { - nm_log_warn (LOGD_RFKILL, "(%s): failed to set killswitch device for " - "non-blocking operation", desc); + _LOGW (LOGD_RFKILL, "(%s): failed to set killswitch device for " + "non-blocking operation", desc); close (fd); return; } @@ -5004,14 +5226,14 @@ rfkill_change (const char *desc, RfKillType rtype, gboolean enabled) len = write (fd, &event, sizeof (event)); if (len < 0) { - nm_log_warn (LOGD_RFKILL, "(%s): failed to change WiFi killswitch state: (%d) %s", - desc, errno, g_strerror (errno)); + _LOGW (LOGD_RFKILL, "(%s): failed to change WiFi killswitch state: (%d) %s", + desc, errno, g_strerror (errno)); } else if (len == sizeof (event)) { - nm_log_info (LOGD_RFKILL, "%s hardware radio set %s", - desc, enabled ? "enabled" : "disabled"); + _LOGI (LOGD_RFKILL, "%s hardware radio set %s", + desc, enabled ? "enabled" : "disabled"); } else { /* Failed to write full structure */ - nm_log_warn (LOGD_RFKILL, "(%s): failed to change WiFi killswitch state", desc); + _LOGW (LOGD_RFKILL, "(%s): failed to change WiFi killswitch state", desc); } close (fd); @@ -5064,7 +5286,7 @@ manager_radio_user_toggled (NMManager *self, if (new_enabled != old_enabled) { /* Try to change the kernel rfkill state */ if (rstate->rtype == RFKILL_TYPE_WLAN || rstate->rtype == RFKILL_TYPE_WWAN) - rfkill_change (rstate->desc, rstate->rtype, new_enabled); + rfkill_change (self, rstate->desc, rstate->rtype, new_enabled); manager_update_radio_enabled (self, rstate, new_enabled); } @@ -5167,11 +5389,14 @@ constructed (GObject *object) g_signal_connect (priv->settings, "notify::" NM_SETTINGS_HOSTNAME, G_CALLBACK (system_hostname_changed_cb), self); g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_ADDED, - G_CALLBACK (connection_changed), self); - g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_UPDATED_BY_USER, - G_CALLBACK (connection_changed), self); - g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_REMOVED, - G_CALLBACK (connection_removed), self); + G_CALLBACK (connection_added_cb), self); + g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_UPDATED, + G_CALLBACK (connection_updated_cb), self); + /* + * Do not delete existing virtual devices to keep connectivity up. + * Virtual devices are reused when NetworkManager is restarted. + * Hence, don't react on NM_SETTINGS_SIGNAL_CONNECTION_REMOVED. + */ priv->policy = nm_policy_new (self, priv->settings); g_signal_connect (priv->policy, "notify::" NM_POLICY_DEFAULT_IP4_DEVICE, @@ -5207,8 +5432,8 @@ constructed (GObject *object) * changes to the WirelessEnabled/WWANEnabled properties which toggle kernel * rfkill. */ - rfkill_change (priv->radio_states[RFKILL_TYPE_WLAN].desc, RFKILL_TYPE_WLAN, priv->radio_states[RFKILL_TYPE_WLAN].user_enabled); - rfkill_change (priv->radio_states[RFKILL_TYPE_WWAN].desc, RFKILL_TYPE_WWAN, priv->radio_states[RFKILL_TYPE_WWAN].user_enabled); + rfkill_change (self, priv->radio_states[RFKILL_TYPE_WLAN].desc, RFKILL_TYPE_WLAN, priv->radio_states[RFKILL_TYPE_WLAN].user_enabled); + rfkill_change (self, priv->radio_states[RFKILL_TYPE_WWAN].desc, RFKILL_TYPE_WWAN, priv->radio_states[RFKILL_TYPE_WWAN].user_enabled); } static void @@ -5249,11 +5474,9 @@ nm_manager_init (NMManager *self) self); /* sleep/wake handling */ - priv->sleep_monitor = g_object_ref (nm_sleep_monitor_get ()); + priv->sleep_monitor = nm_sleep_monitor_new (); g_signal_connect (priv->sleep_monitor, NM_SLEEP_MONITOR_SLEEPING, G_CALLBACK (sleeping_cb), self); - g_signal_connect (priv->sleep_monitor, NM_SLEEP_MONITOR_RESUMING, - G_CALLBACK (resuming_cb), self); /* Listen for authorization changes */ g_signal_connect (nm_auth_manager_get (), @@ -5284,6 +5507,7 @@ nm_manager_init (NMManager *self) priv->timestamp_update_id = g_timeout_add_seconds (300, (GSourceFunc) periodic_update_active_connection_timestamps, self); priv->metered = NM_METERED_UNKNOWN; + priv->sleep_devices = g_hash_table_new (g_direct_hash, g_direct_equal); } static gboolean @@ -5492,8 +5716,8 @@ dispose (GObject *object) g_signal_handlers_disconnect_by_func (priv->settings, settings_startup_complete_changed, manager); g_signal_handlers_disconnect_by_func (priv->settings, system_unmanaged_devices_changed_cb, manager); g_signal_handlers_disconnect_by_func (priv->settings, system_hostname_changed_cb, manager); - g_signal_handlers_disconnect_by_func (priv->settings, connection_changed, manager); - g_signal_handlers_disconnect_by_func (priv->settings, connection_removed, manager); + g_signal_handlers_disconnect_by_func (priv->settings, connection_added_cb, manager); + g_signal_handlers_disconnect_by_func (priv->settings, connection_updated_cb, manager); g_clear_object (&priv->settings); } @@ -5507,9 +5731,11 @@ dispose (GObject *object) } _set_prop_filter (manager, NULL); + sleep_devices_clear (manager); + g_clear_pointer (&priv->sleep_devices, g_hash_table_unref); + if (priv->sleep_monitor) { g_signal_handlers_disconnect_by_func (priv->sleep_monitor, sleeping_cb, manager); - g_signal_handlers_disconnect_by_func (priv->sleep_monitor, resuming_cb, manager); g_clear_object (&priv->sleep_monitor); } @@ -5786,6 +6012,7 @@ nm_manager_class_init (NMManagerClass *manager_class) nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (manager_class), NMDBUS_TYPE_MANAGER_SKELETON, + "Reload", impl_manager_reload, "GetDevices", impl_manager_get_devices, "GetAllDevices", impl_manager_get_all_devices, "GetDeviceByIpIface", impl_manager_get_device_by_ip_iface, diff --git a/src/nm-policy.c b/src/nm-policy.c index 07bcce89..9613ad82 100644 --- a/src/nm-policy.c +++ b/src/nm-policy.c @@ -83,6 +83,8 @@ struct _NMPolicyPrivate { guint reset_retries_id; /* idle handler for resetting the retries count */ + guint schedule_activate_all_id; /* idle handler for schedule_activate_all(). */ + char *orig_hostname; /* hostname at NM start time */ char *cur_hostname; /* hostname we want to assign */ gboolean hostname_changed; /* TRUE if NM ever set the hostname */ @@ -913,6 +915,7 @@ block_autoconnect_for_device (NMPolicy *self, NMDevice *device) NM_DEVICE_STATE_REASON_USER_REQUESTED); } } + g_slist_free (connections); } static void @@ -1015,8 +1018,6 @@ reset_connections_retries (gpointer user_data) return FALSE; } -static void schedule_activate_all (NMPolicy *self); - static void activate_slave_connections (NMPolicy *self, NMDevice *device) { @@ -1441,7 +1442,7 @@ vpn_connection_activated (NMPolicy *self, NMVpnConnection *vpn) nm_dns_manager_begin_updates (priv->dns_manager, __func__); - ip_iface = nm_vpn_connection_get_ip_iface (vpn); + ip_iface = nm_vpn_connection_get_ip_iface (vpn, TRUE); /* Add the VPN connection's IP configs from DNS */ @@ -1579,14 +1580,30 @@ active_connection_removed (NMManager *manager, /**************************************************************************/ -static void -schedule_activate_all (NMPolicy *self) +static gboolean +schedule_activate_all_cb (gpointer user_data) { + NMPolicy *self = user_data; NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); const GSList *iter; + priv->schedule_activate_all_id = 0; + for (iter = nm_manager_get_devices (priv->manager); iter; iter = g_slist_next (iter)) - schedule_activate_check (self, NM_DEVICE (iter->data)); + schedule_activate_check (self, iter->data); + + return G_SOURCE_REMOVE; +} + +static void +schedule_activate_all (NMPolicy *self) +{ + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); + + /* always restart the idle handler. That way, we settle + * all other events before restarting to activate them. */ + nm_clear_g_source (&priv->schedule_activate_all_id); + priv->schedule_activate_all_id = g_idle_add (schedule_activate_all_cb, self); } static void @@ -1648,39 +1665,34 @@ dns_config_changed (NMDnsManager *dns_manager, gpointer user_data) static void connection_updated (NMSettings *settings, - NMConnection *connection, + NMSettingsConnection *connection, + gboolean by_user, gpointer user_data) { NMPolicyPrivate *priv = user_data; NMPolicy *self = priv->self; - - schedule_activate_all (self); -} - -static void -connection_updated_by_user (NMSettings *settings, - NMSettingsConnection *connection, - gpointer user_data) -{ - NMPolicyPrivate *priv = user_data; const GSList *iter; NMDevice *device = NULL; - /* find device with given connection */ - for (iter = nm_manager_get_devices (priv->manager); iter; iter = g_slist_next (iter)) { - NMDevice *dev = NM_DEVICE (iter->data); + if (by_user) { + /* find device with given connection */ + for (iter = nm_manager_get_devices (priv->manager); iter; iter = g_slist_next (iter)) { + NMDevice *dev = NM_DEVICE (iter->data); - if (nm_device_get_settings_connection (dev) == connection) { - device = dev; - break; + if (nm_device_get_settings_connection (dev) == connection) { + device = dev; + break; + } } - } - if (device) - nm_device_reapply_settings_immediately (device); + if (device) + nm_device_reapply_settings_immediately (device); + + /* Reset auto retries back to default since connection was updated */ + nm_settings_connection_reset_autoconnect_retries (connection); + } - /* Reset auto retries back to default since connection was updated */ - nm_settings_connection_reset_autoconnect_retries (connection); + schedule_activate_all (self); } static void @@ -1876,7 +1888,6 @@ constructed (GObject *object) g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_ADDED, (GCallback) connection_added, priv); g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_UPDATED, (GCallback) connection_updated, priv); - g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_UPDATED_BY_USER, (GCallback) connection_updated_by_user, priv); g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_REMOVED, (GCallback) connection_removed, priv); g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_VISIBILITY_CHANGED, (GCallback) connection_visibility_changed, priv); g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_AGENT_REGISTERED, (GCallback) secret_agent_registered, priv); @@ -1941,6 +1952,7 @@ dispose (GObject *object) g_assert (connections == NULL); nm_clear_g_source (&priv->reset_retries_id); + nm_clear_g_source (&priv->schedule_activate_all_id); g_clear_pointer (&priv->orig_hostname, g_free); g_clear_pointer (&priv->cur_hostname, g_free); diff --git a/src/nm-sleep-monitor-systemd.c b/src/nm-sleep-monitor-systemd.c deleted file mode 100644 index 064a7035..00000000 --- a/src/nm-sleep-monitor-systemd.c +++ /dev/null @@ -1,258 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2012 Red Hat, Inc. - * Author: Matthias Clasen <mclasen@redhat.com> - */ - -#include "nm-default.h" - -#include <errno.h> -#include <string.h> -#include <sys/stat.h> -#include <gio/gunixfdlist.h> - -#include "nm-core-internal.h" -#include "NetworkManagerUtils.h" - -#include "nm-sleep-monitor.h" - -#if defined (SUSPEND_RESUME_SYSTEMD) == defined (SUSPEND_RESUME_CONSOLEKIT) -#error either define SUSPEND_RESUME_SYSTEMD or SUSPEND_RESUME_CONSOLEKIT -#endif - -#ifdef SUSPEND_RESUME_SYSTEMD - -#define SUSPEND_DBUS_NAME "org.freedesktop.login1" -#define SUSPEND_DBUS_PATH "/org/freedesktop/login1" -#define SUSPEND_DBUS_INTERFACE "org.freedesktop.login1.Manager" - -#else - -/* ConsoleKit2 has added the same suspend/resume DBUS API that Systemd - * uses. http://consolekit2.github.io/ConsoleKit2/#Manager.Inhibit - */ - -#define SUSPEND_DBUS_NAME "org.freedesktop.ConsoleKit" -#define SUSPEND_DBUS_PATH "/org/freedesktop/ConsoleKit/Manager" -#define SUSPEND_DBUS_INTERFACE "org.freedesktop.ConsoleKit.Manager" - -#endif - -struct _NMSleepMonitor { - GObject parent_instance; - - GDBusProxy *sd_proxy; - gint inhibit_fd; -}; - -struct _NMSleepMonitorClass { - GObjectClass parent_class; - - void (*sleeping) (NMSleepMonitor *monitor); - void (*resuming) (NMSleepMonitor *monitor); -}; - - -enum { - SLEEPING, - RESUMING, - LAST_SIGNAL, -}; -static guint signals[LAST_SIGNAL] = {0}; - -G_DEFINE_TYPE (NMSleepMonitor, nm_sleep_monitor, G_TYPE_OBJECT); - -/********************************************************************/ - -static gboolean -drop_inhibitor (NMSleepMonitor *self) -{ - if (self->inhibit_fd >= 0) { - nm_log_dbg (LOGD_SUSPEND, "Dropping systemd sleep inhibitor"); - close (self->inhibit_fd); - self->inhibit_fd = -1; - return TRUE; - } - return FALSE; -} - -static void -inhibit_done (GObject *source, - GAsyncResult *result, - gpointer user_data) -{ - GDBusProxy *sd_proxy = G_DBUS_PROXY (source); - NMSleepMonitor *self = user_data; - GError *error = NULL; - GVariant *res; - GUnixFDList *fd_list; - - res = g_dbus_proxy_call_with_unix_fd_list_finish (sd_proxy, &fd_list, result, &error); - if (!res) { - g_dbus_error_strip_remote_error (error); - nm_log_warn (LOGD_SUSPEND, "Inhibit failed: %s", error->message); - g_error_free (error); - } else { - if (!fd_list || g_unix_fd_list_get_length (fd_list) != 1) - nm_log_warn (LOGD_SUSPEND, "Didn't get a single fd back"); - - self->inhibit_fd = g_unix_fd_list_get (fd_list, 0, NULL); - - nm_log_dbg (LOGD_SUSPEND, "Inhibitor fd is %d", self->inhibit_fd); - g_object_unref (fd_list); - g_variant_unref (res); - } -} - -static void -take_inhibitor (NMSleepMonitor *self) -{ - g_assert (self->inhibit_fd == -1); - - nm_log_dbg (LOGD_SUSPEND, "Taking systemd sleep inhibitor"); - g_dbus_proxy_call_with_unix_fd_list (self->sd_proxy, - "Inhibit", - g_variant_new ("(ssss)", - "sleep", - "NetworkManager", - _("NetworkManager needs to turn off networks"), - "delay"), - 0, - G_MAXINT, - NULL, - NULL, - inhibit_done, - self); -} - -static void -prepare_for_sleep_cb (GDBusProxy *proxy, - gboolean is_about_to_suspend, - gpointer data) -{ - NMSleepMonitor *self = data; - - nm_log_dbg (LOGD_SUSPEND, "Received PrepareForSleep signal: %d", is_about_to_suspend); - - if (is_about_to_suspend) { - g_signal_emit (self, signals[SLEEPING], 0); - drop_inhibitor (self); - } else { - take_inhibitor (self); - g_signal_emit (self, signals[RESUMING], 0); - } -} - -static void -name_owner_cb (GObject *object, - GParamSpec *pspec, - gpointer user_data) -{ - GDBusProxy *proxy = G_DBUS_PROXY (object); - NMSleepMonitor *self = NM_SLEEP_MONITOR (user_data); - char *owner; - - g_assert (proxy == self->sd_proxy); - - owner = g_dbus_proxy_get_name_owner (proxy); - if (owner) - take_inhibitor (self); - else - drop_inhibitor (self); - g_free (owner); -} - -static void -on_proxy_acquired (GObject *object, - GAsyncResult *res, - NMSleepMonitor *self) -{ - GError *error = NULL; - char *owner; - - self->sd_proxy = g_dbus_proxy_new_for_bus_finish (res, &error); - if (!self->sd_proxy) { - nm_log_warn (LOGD_SUSPEND, "Failed to acquire logind proxy: %s", error->message); - g_clear_error (&error); - return; - } - - g_signal_connect (self->sd_proxy, "notify::g-name-owner", G_CALLBACK (name_owner_cb), self); - _nm_dbus_signal_connect (self->sd_proxy, "PrepareForSleep", G_VARIANT_TYPE ("(b)"), - G_CALLBACK (prepare_for_sleep_cb), self); - - owner = g_dbus_proxy_get_name_owner (self->sd_proxy); - if (owner) - take_inhibitor (self); - g_free (owner); -} - -static void -nm_sleep_monitor_init (NMSleepMonitor *self) -{ - self->inhibit_fd = -1; - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START | - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, - NULL, - SUSPEND_DBUS_NAME, SUSPEND_DBUS_PATH, SUSPEND_DBUS_INTERFACE, - NULL, - (GAsyncReadyCallback) on_proxy_acquired, self); -} - -static void -finalize (GObject *object) -{ - NMSleepMonitor *self = NM_SLEEP_MONITOR (object); - - drop_inhibitor (self); - if (self->sd_proxy) - g_object_unref (self->sd_proxy); - - if (G_OBJECT_CLASS (nm_sleep_monitor_parent_class)->finalize != NULL) - G_OBJECT_CLASS (nm_sleep_monitor_parent_class)->finalize (object); -} - -static void -nm_sleep_monitor_class_init (NMSleepMonitorClass *klass) -{ - GObjectClass *gobject_class; - - gobject_class = G_OBJECT_CLASS (klass); - - gobject_class->finalize = finalize; - - signals[SLEEPING] = g_signal_new (NM_SLEEP_MONITOR_SLEEPING, - NM_TYPE_SLEEP_MONITOR, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMSleepMonitorClass, sleeping), - NULL, /* accumulator */ - NULL, /* accumulator data */ - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - signals[RESUMING] = g_signal_new (NM_SLEEP_MONITOR_RESUMING, - NM_TYPE_SLEEP_MONITOR, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMSleepMonitorClass, resuming), - NULL, /* accumulator */ - NULL, /* accumulator data */ - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); -} - -NM_DEFINE_SINGLETON_GETTER (NMSleepMonitor, nm_sleep_monitor_get, NM_TYPE_SLEEP_MONITOR); - -/* ---------------------------------------------------------------------------------------------------- */ diff --git a/src/nm-sleep-monitor-upower.c b/src/nm-sleep-monitor-upower.c deleted file mode 100644 index 5f0ff245..00000000 --- a/src/nm-sleep-monitor-upower.c +++ /dev/null @@ -1,134 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2012 Red Hat, Inc. - * Author: Matthias Clasen <mclasen@redhat.com> - */ - -#include "nm-default.h" - -#include <errno.h> -#include <string.h> -#include <sys/stat.h> - -#include "nm-core-internal.h" - -#include "nm-sleep-monitor.h" - -#define UPOWER_DBUS_SERVICE "org.freedesktop.UPower" - -struct _NMSleepMonitor { - GObject parent_instance; - - GDBusProxy *upower_proxy; -}; - -struct _NMSleepMonitorClass { - GObjectClass parent_class; - - void (*sleeping) (NMSleepMonitor *monitor); - void (*resuming) (NMSleepMonitor *monitor); -}; - - -enum { - SLEEPING, - RESUMING, - LAST_SIGNAL, -}; -static guint signals[LAST_SIGNAL] = {0}; - -G_DEFINE_TYPE (NMSleepMonitor, nm_sleep_monitor, G_TYPE_OBJECT); - -/********************************************************************/ - -static void -upower_sleeping_cb (GDBusProxy *proxy, gpointer user_data) -{ - nm_log_dbg (LOGD_SUSPEND, "Received UPower sleeping signal"); - g_signal_emit (user_data, signals[SLEEPING], 0); -} - -static void -upower_resuming_cb (GDBusProxy *proxy, gpointer user_data) -{ - nm_log_dbg (LOGD_SUSPEND, "Received UPower resuming signal"); - g_signal_emit (user_data, signals[RESUMING], 0); -} - -static void -nm_sleep_monitor_init (NMSleepMonitor *self) -{ - GError *error = NULL; - - self->upower_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START | - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, - NULL, - UPOWER_DBUS_SERVICE, - "/org/freedesktop/UPower", - "org.freedesktop.UPower", - NULL, &error); - if (self->upower_proxy) { - _nm_dbus_signal_connect (self->upower_proxy, "Sleeping", NULL, - G_CALLBACK (upower_sleeping_cb), self); - _nm_dbus_signal_connect (self->upower_proxy, "Resuming", NULL, - G_CALLBACK (upower_resuming_cb), self); - } else { - nm_log_warn (LOGD_SUSPEND, "could not initialize UPower D-Bus proxy: %s", error->message); - g_error_free (error); - } -} - -static void -finalize (GObject *object) -{ - NMSleepMonitor *self = NM_SLEEP_MONITOR (object); - - g_clear_object (&self->upower_proxy); - - G_OBJECT_CLASS (nm_sleep_monitor_parent_class)->finalize (object); -} - -static void -nm_sleep_monitor_class_init (NMSleepMonitorClass *klass) -{ - GObjectClass *gobject_class; - - gobject_class = G_OBJECT_CLASS (klass); - - gobject_class->finalize = finalize; - - signals[SLEEPING] = g_signal_new (NM_SLEEP_MONITOR_SLEEPING, - NM_TYPE_SLEEP_MONITOR, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMSleepMonitorClass, sleeping), - NULL, /* accumulator */ - NULL, /* accumulator data */ - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - signals[RESUMING] = g_signal_new (NM_SLEEP_MONITOR_RESUMING, - NM_TYPE_SLEEP_MONITOR, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMSleepMonitorClass, resuming), - NULL, /* accumulator */ - NULL, /* accumulator data */ - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); -} - -NM_DEFINE_SINGLETON_GETTER (NMSleepMonitor, nm_sleep_monitor_get, NM_TYPE_SLEEP_MONITOR); - -/* ---------------------------------------------------------------------------------------------------- */ diff --git a/src/nm-sleep-monitor.c b/src/nm-sleep-monitor.c new file mode 100644 index 00000000..13ce1be0 --- /dev/null +++ b/src/nm-sleep-monitor.c @@ -0,0 +1,396 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * (C) Copyright 2012-2016 Red Hat, Inc. + * Author: Matthias Clasen <mclasen@redhat.com> + */ + +#include "nm-default.h" + +#include "nm-sleep-monitor.h" + +#include <errno.h> +#include <string.h> +#include <sys/stat.h> +#include <gio/gunixfdlist.h> + +#include "nm-core-internal.h" +#include "NetworkManagerUtils.h" + + +#if defined (SUSPEND_RESUME_UPOWER) + +#define SUSPEND_DBUS_NAME "org.freedesktop.UPower" +#define SUSPEND_DBUS_PATH "/org/freedesktop/UPower" +#define SUSPEND_DBUS_INTERFACE "org.freedesktop.UPower" +#define USE_UPOWER 1 +#define _NMLOG_PREFIX_NAME "sleep-monitor-up" + +#elif defined (SUSPEND_RESUME_SYSTEMD) + +#define SUSPEND_DBUS_NAME "org.freedesktop.login1" +#define SUSPEND_DBUS_PATH "/org/freedesktop/login1" +#define SUSPEND_DBUS_INTERFACE "org.freedesktop.login1.Manager" +#define USE_UPOWER 0 +#define _NMLOG_PREFIX_NAME "sleep-monitor-sd" + +#elif defined(SUSPEND_RESUME_CONSOLEKIT) + +/* ConsoleKit2 has added the same suspend/resume DBUS API that Systemd + * uses. http://consolekit2.github.io/ConsoleKit2/#Manager.Inhibit + */ + +#define SUSPEND_DBUS_NAME "org.freedesktop.ConsoleKit" +#define SUSPEND_DBUS_PATH "/org/freedesktop/ConsoleKit/Manager" +#define SUSPEND_DBUS_INTERFACE "org.freedesktop.ConsoleKit.Manager" +#define USE_UPOWER 0 +#define _NMLOG_PREFIX_NAME "sleep-monitor-ck" + +#else + +#error define one of SUSPEND_RESUME_SYSTEMD, SUSPEND_RESUME_CONSOLEKIT, or SUSPEND_RESUME_UPOWER + +#endif + +struct _NMSleepMonitor { + GObject parent_instance; + + GDBusProxy *proxy; + + /* used both during construction of proxy and during Inhibit call. */ + GCancellable *cancellable; + + gint inhibit_fd; + GSList *handles_active; + GSList *handles_stale; + + gulong sig_id_1; + gulong sig_id_2; +}; + +struct _NMSleepMonitorClass { + GObjectClass parent_class; +}; + +enum { + SLEEPING, + LAST_SIGNAL, +}; +static guint signals[LAST_SIGNAL] = {0}; + +G_DEFINE_TYPE (NMSleepMonitor, nm_sleep_monitor, G_TYPE_OBJECT); + +static void sleep_signal (NMSleepMonitor *self, gboolean is_about_to_suspend); + +/*****************************************************************************/ + +#define _NMLOG_DOMAIN LOGD_SUSPEND +#define _NMLOG(level, ...) \ + G_STMT_START { \ + nm_log ((level), _NMLOG_DOMAIN, \ + "%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ + _NMLOG_PREFIX_NAME \ + _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ + } G_STMT_END + +/*****************************************************************************/ + +#if USE_UPOWER + +static void +upower_sleeping_cb (GDBusProxy *proxy, gpointer user_data) +{ + sleep_signal (user_data, TRUE); +} + +static void +upower_resuming_cb (GDBusProxy *proxy, gpointer user_data) +{ + sleep_signal (user_data, FALSE); +} + +#else /* USE_UPOWER */ + +static void +drop_inhibitor (NMSleepMonitor *self, gboolean force) +{ + if (!force && self->handles_active) + return; + + if (self->inhibit_fd >= 0) { + _LOGD ("inhibit: dropping sleep inhibitor %d", self->inhibit_fd); + close (self->inhibit_fd); + self->inhibit_fd = -1; + } + + if (self->handles_active) { + self->handles_stale = g_slist_concat (self->handles_stale, self->handles_active); + self->handles_active = NULL; + } + + nm_clear_g_cancellable (&self->cancellable); +} + +static void +inhibit_done (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + GDBusProxy *proxy = G_DBUS_PROXY (source); + NMSleepMonitor *self = user_data; + gs_free_error GError *error = NULL; + gs_unref_variant GVariant *res = NULL; + gs_unref_object GUnixFDList *fd_list = NULL; + + res = g_dbus_proxy_call_with_unix_fd_list_finish (proxy, &fd_list, result, &error); + if (!res) { + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + g_clear_object (&self->cancellable); + _LOGW ("inhibit: failed (%s)", error->message); + } + return; + } + + g_clear_object (&self->cancellable); + + if (!fd_list || g_unix_fd_list_get_length (fd_list) != 1) { + _LOGW ("inhibit: didn't get a single fd back"); + return; + } + + self->inhibit_fd = g_unix_fd_list_get (fd_list, 0, NULL); + _LOGD ("inhibit: inhibitor fd is %d", self->inhibit_fd); +} + +static void +take_inhibitor (NMSleepMonitor *self) +{ + g_return_if_fail (NM_IS_SLEEP_MONITOR (self)); + g_return_if_fail (G_IS_DBUS_PROXY (self->proxy)); + + drop_inhibitor (self, TRUE); + + _LOGD ("inhibit: taking sleep inhibitor..."); + self->cancellable = g_cancellable_new (); + g_dbus_proxy_call_with_unix_fd_list (self->proxy, + "Inhibit", + g_variant_new ("(ssss)", + "sleep", + "NetworkManager", + "NetworkManager needs to turn off networks", + "delay"), + 0, + G_MAXINT, + NULL, + self->cancellable, + inhibit_done, + self); +} + +static void +prepare_for_sleep_cb (GDBusProxy *proxy, + gboolean is_about_to_suspend, + gpointer data) +{ + sleep_signal (data, is_about_to_suspend); +} + +static void +name_owner_cb (GObject *object, + GParamSpec *pspec, + gpointer user_data) +{ + GDBusProxy *proxy = G_DBUS_PROXY (object); + NMSleepMonitor *self = NM_SLEEP_MONITOR (user_data); + char *owner; + + g_assert (proxy == self->proxy); + + owner = g_dbus_proxy_get_name_owner (proxy); + if (owner) + take_inhibitor (self); + else + drop_inhibitor (self, TRUE); + g_free (owner); +} +#endif /* USE_UPOWER */ + +static void +sleep_signal (NMSleepMonitor *self, + gboolean is_about_to_suspend) +{ + g_return_if_fail (NM_IS_SLEEP_MONITOR (self)); + + _LOGD ("received %s signal", is_about_to_suspend ? "SLEEP" : "RESUME"); + +#if !USE_UPOWER + if (!is_about_to_suspend) + take_inhibitor (self); +#endif + + g_signal_emit (self, signals[SLEEPING], 0, is_about_to_suspend); + +#if !USE_UPOWER + if (is_about_to_suspend) + drop_inhibitor (self, FALSE); +#endif +} + +/** + * nm_sleep_monitor_inhibit_take: + * @self: the #NMSleepMonitor instance + * + * Prevent the release of inhibitor lock + * + * Returns: an inhibitor handle that must be returned via + * nm_sleep_monitor_inhibit_release(). + **/ +NMSleepMonitorInhibitorHandle * +nm_sleep_monitor_inhibit_take (NMSleepMonitor *self) +{ + g_return_val_if_fail (NM_IS_SLEEP_MONITOR (self), NULL); + + self->handles_active = g_slist_prepend (self->handles_active, NULL); + return (NMSleepMonitorInhibitorHandle *) self->handles_active; +} + +/** + * nm_sleep_monitor_inhibit_release: + * @self: the #NMSleepMonitor instance + * @handle: the #NMSleepMonitorInhibitorHandle inhibitor handle. + * + * Allow again the release of inhibitor lock + **/ +void +nm_sleep_monitor_inhibit_release (NMSleepMonitor *self, + NMSleepMonitorInhibitorHandle *handle) +{ + GSList *l; + + g_return_if_fail (NM_IS_SLEEP_MONITOR (self)); + g_return_if_fail (handle); + + l = (GSList *) handle; + + if (g_slist_position (self->handles_active, l) < 0) { + if (g_slist_position (self->handles_stale, l) < 0) + g_return_if_reached (); + self->handles_stale = g_slist_delete_link (self->handles_stale, l); + return; + } + + self->handles_active = g_slist_delete_link (self->handles_active, l); + +#if !USE_UPOWER + drop_inhibitor (self, FALSE); +#endif +} + +static void +on_proxy_acquired (GObject *object, + GAsyncResult *res, + NMSleepMonitor *self) +{ + GError *error = NULL; + GDBusProxy *proxy; + + proxy = g_dbus_proxy_new_for_bus_finish (res, &error); + if (!proxy) { + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + _LOGW ("failed to acquire D-Bus proxy: %s", error->message); + g_clear_error (&error); + return; + } + self->proxy = proxy; + g_clear_object (&self->cancellable); + +#if USE_UPOWER + self->sig_id_1 = _nm_dbus_signal_connect (self->proxy, "Sleeping", NULL, + G_CALLBACK (upower_sleeping_cb), self); + self->sig_id_2 = _nm_dbus_signal_connect (self->proxy, "Resuming", NULL, + G_CALLBACK (upower_resuming_cb), self); +#else + self->sig_id_1 = g_signal_connect (self->proxy, "notify::g-name-owner", + G_CALLBACK (name_owner_cb), self); + self->sig_id_2 = _nm_dbus_signal_connect (self->proxy, "PrepareForSleep", + G_VARIANT_TYPE ("(b)"), + G_CALLBACK (prepare_for_sleep_cb), self); + { + gs_free char *owner = NULL; + + owner = g_dbus_proxy_get_name_owner (self->proxy); + if (owner) + take_inhibitor (self); + } +#endif +} + +static void +nm_sleep_monitor_init (NMSleepMonitor *self) +{ + self->inhibit_fd = -1; + self->cancellable = g_cancellable_new (); + g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START | + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, + NULL, + SUSPEND_DBUS_NAME, SUSPEND_DBUS_PATH, SUSPEND_DBUS_INTERFACE, + self->cancellable, + (GAsyncReadyCallback) on_proxy_acquired, self); +} + +NMSleepMonitor * +nm_sleep_monitor_new (void) +{ + return g_object_new (NM_TYPE_SLEEP_MONITOR, NULL); +} + +static void +dispose (GObject *object) +{ + NMSleepMonitor *self = NM_SLEEP_MONITOR (object); + +#if !USE_UPOWER + drop_inhibitor (self, TRUE); +#endif + + nm_clear_g_cancellable (&self->cancellable); + + if (self->proxy) { + nm_clear_g_signal_handler (self->proxy, &self->sig_id_1); + nm_clear_g_signal_handler (self->proxy, &self->sig_id_2); + g_clear_object (&self->proxy); + } + + G_OBJECT_CLASS (nm_sleep_monitor_parent_class)->dispose (object); +} + +static void +nm_sleep_monitor_class_init (NMSleepMonitorClass *klass) +{ + GObjectClass *gobject_class; + + gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->dispose = dispose; + + signals[SLEEPING] = g_signal_new (NM_SLEEP_MONITOR_SLEEPING, + NM_TYPE_SLEEP_MONITOR, + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__BOOLEAN, + G_TYPE_NONE, 1, G_TYPE_BOOLEAN); +} + diff --git a/src/nm-sleep-monitor.h b/src/nm-sleep-monitor.h index 21e6b844..140f964f 100644 --- a/src/nm-sleep-monitor.h +++ b/src/nm-sleep-monitor.h @@ -13,16 +13,13 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * (C) Copyright 2012 Red Hat, Inc. + * (C) Copyright 2012-2016 Red Hat, Inc. * Author: Matthias Clasen <mclasen@redhat.com> */ #ifndef __NETWORKMANAGER_SLEEP_MONITOR_H__ #define __NETWORKMANAGER_SLEEP_MONITOR_H__ - -#include "nm-default.h" - G_BEGIN_DECLS #define NM_TYPE_SLEEP_MONITOR (nm_sleep_monitor_get_type ()) @@ -33,12 +30,17 @@ G_BEGIN_DECLS #define NM_IS_SLEEP_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), NM_TYPE_SLEEP_MONITOR)) #define NM_SLEEP_MONITOR_SLEEPING "sleeping" -#define NM_SLEEP_MONITOR_RESUMING "resuming" typedef struct _NMSleepMonitorClass NMSleepMonitorClass; GType nm_sleep_monitor_get_type (void) G_GNUC_CONST; -NMSleepMonitor *nm_sleep_monitor_get (void); +NMSleepMonitor *nm_sleep_monitor_new (void); + +typedef struct _NMSleepMonitorInhibitorHandle NMSleepMonitorInhibitorHandle; + +NMSleepMonitorInhibitorHandle *nm_sleep_monitor_inhibit_take (NMSleepMonitor *self); +void nm_sleep_monitor_inhibit_release (NMSleepMonitor *self, + NMSleepMonitorInhibitorHandle *handle); G_END_DECLS diff --git a/src/platform/Makefile.in b/src/platform/Makefile.in index 854c6712..a528da66 100644 --- a/src/platform/Makefile.in +++ b/src/platform/Makefile.in @@ -324,6 +324,7 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@ NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index c5045503..f6f7be80 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -1439,6 +1439,8 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr gboolean *completed_from_cache = cache ? &completed_from_cache_val : NULL; const NMPObject *link_cached = NULL; NMPObject *lnk_data = NULL; + gboolean address_complete_from_cache = TRUE; + gboolean lnk_data_complete_from_cache = TRUE; if (!nlmsg_valid_hdr (nlh, sizeof (*ifi))) return NULL; @@ -1503,6 +1505,7 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr memcpy (obj->link.addr.data, nla_data (tb[IFLA_ADDRESS]), l); obj->link.addr.len = l; } + address_complete_from_cache = FALSE; } if (tb[IFLA_AF_SPEC]) { @@ -1552,28 +1555,34 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr lnk_data = _parse_lnk_vxlan (nl_info_kind, nl_info_data); break; default: - goto lnk_data_handled; + lnk_data_complete_from_cache = FALSE; + break; } - /* We always try to look into the cache and reuse the object there. - * We do that, because we consider the lnk object as immutable and don't - * modify it after creating. Hence we can share it and reuse. - * - * Also, sometimes the info-data is missing for updates. In this case - * we want to keep the previously received lnk_data. */ - if (completed_from_cache) { + if ( completed_from_cache + && ( lnk_data_complete_from_cache + || address_complete_from_cache)) { _lookup_cached_link (cache, obj->link.ifindex, completed_from_cache, &link_cached); - if ( link_cached - && link_cached->link.type == obj->link.type - && link_cached->_link.netlink.lnk - && ( !lnk_data - || nmp_object_equal (lnk_data, link_cached->_link.netlink.lnk))) { - nmp_object_unref (lnk_data); - lnk_data = nmp_object_ref (link_cached->_link.netlink.lnk); + if (link_cached) { + if ( lnk_data_complete_from_cache + && link_cached->link.type == obj->link.type + && link_cached->_link.netlink.lnk + && ( !lnk_data + || nmp_object_equal (lnk_data, link_cached->_link.netlink.lnk))) { + /* We always try to look into the cache and reuse the object there. + * We do that, because we consider the lnk object as immutable and don't + * modify it after creating. Hence we can share it and reuse. + * + * Also, sometimes the info-data is missing for updates. In this case + * we want to keep the previously received lnk_data. */ + nmp_object_unref (lnk_data); + lnk_data = nmp_object_ref (link_cached->_link.netlink.lnk); + } + if (address_complete_from_cache) + obj->link.addr = link_cached->link.addr; } } -lnk_data_handled: obj->_link.netlink.lnk = lnk_data; obj->_link.netlink.is_in_netlink = TRUE; @@ -3283,9 +3292,14 @@ cache_pre_hook (NMPCache *cache, const NMPObject *old, const NMPObject *new, NMP if ( ops_type == NMP_CACHE_OPS_UPDATED && old && new /* <-- nonsensical, make coverity happy */ && old->_link.netlink.is_in_netlink - && NM_FLAGS_HAS (old->link.n_ifi_flags, IFF_LOWER_UP) && new->_link.netlink.is_in_netlink - && !NM_FLAGS_HAS (new->link.n_ifi_flags, IFF_LOWER_UP)) { + && ( ( NM_FLAGS_HAS (old->link.n_ifi_flags, IFF_UP) + && !NM_FLAGS_HAS (new->link.n_ifi_flags, IFF_UP)) + || ( NM_FLAGS_HAS (old->link.n_ifi_flags, IFF_LOWER_UP) + && !NM_FLAGS_HAS (new->link.n_ifi_flags, IFF_LOWER_UP)))) { + /* FIXME: I suspect that IFF_LOWER_UP must not be considered, and I + * think kernel does send RTM_DELROUTE events for IPv6 routes, so + * we might not need to refresh IPv6 routes. */ delayed_action_schedule (platform, DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES | DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES, @@ -5140,13 +5154,30 @@ static WifiData * wifi_get_wifi_data (NMPlatform *platform, int ifindex) { NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + const NMPlatformLink *pllink; WifiData *wifi_data; wifi_data = g_hash_table_lookup (priv->wifi_data, GINT_TO_POINTER (ifindex)); - if (!wifi_data) { - const NMPlatformLink *pllink; + pllink = nm_platform_link_get (platform, ifindex); - pllink = nm_platform_link_get (platform, ifindex); + /* @wifi_data contains an interface name which is used for WEXT queries. If + * the interface name changes we should at least replace the name in the + * existing structure; but probably a complete reinitialization is better + * because during the initial creation there can be race conditions while + * the interface is renamed by udev. + */ + if (wifi_data && pllink) { + if (!nm_streq (wifi_utils_get_iface (wifi_data), pllink->name)) { + _LOGD ("wifi: interface %s renamed to %s, dropping old data for ifindex %d", + wifi_utils_get_iface (wifi_data), + pllink->name, + ifindex); + g_hash_table_remove (priv->wifi_data, GINT_TO_POINTER (ifindex)); + wifi_data = NULL; + } + } + + if (!wifi_data) { if (pllink) { if (pllink->type == NM_LINK_TYPE_WIFI) wifi_data = wifi_utils_init (pllink->name, ifindex, TRUE); @@ -5778,6 +5809,13 @@ continue_reading: errno = 0; n = nl_recv (sk, &nla, &buf, &creds); + if (n <= 0) { + /* workaround libnl3 <= 3.2.15 returning danling pointers in case nl_recv() + * fails. Fixed by libnl3 69468517d0de1675d80f24661ff57a5dbac7275c. */ + buf = NULL; + creds = NULL; + } + switch (n) { case 0: /* Work around a libnl bug fixed in 3.2.22 (375a6294) */ diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index 658b709a..19724f1c 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -138,7 +138,7 @@ struct _NMPlatformLink { /* rtnl_link_get_arptype(), ifinfomsg.ifi_type. */ guint32 arptype; - /* rtnl_link_get_addr() */ + /* rtnl_link_get_addr(), IFLA_ADDRESS */ struct { guint8 data[20]; /* NM_UTILS_HWADDR_LEN_MAX */ guint8 len; diff --git a/src/platform/tests/Makefile.in b/src/platform/tests/Makefile.in index 60cd6d82..49f2fa09 100644 --- a/src/platform/tests/Makefile.in +++ b/src/platform/tests/Makefile.in @@ -621,6 +621,7 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@ NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ diff --git a/src/platform/wifi/wifi-utils.c b/src/platform/wifi/wifi-utils.c index 38e5a054..4f04041a 100644 --- a/src/platform/wifi/wifi-utils.c +++ b/src/platform/wifi/wifi-utils.c @@ -70,6 +70,22 @@ wifi_utils_init (const char *iface, int ifindex, gboolean check_scan) return ret; } +int +wifi_utils_get_ifindex (WifiData *data) +{ + g_return_val_if_fail (data != NULL, -1); + + return data->ifindex; +} + +const char * +wifi_utils_get_iface (WifiData *data) +{ + g_return_val_if_fail (data != NULL, NULL); + + return data->iface; +} + NMDeviceWifiCapabilities wifi_utils_get_caps (WifiData *data) { diff --git a/src/platform/wifi/wifi-utils.h b/src/platform/wifi/wifi-utils.h index 21dac9e9..9555bbee 100644 --- a/src/platform/wifi/wifi-utils.h +++ b/src/platform/wifi/wifi-utils.h @@ -33,6 +33,10 @@ gboolean wifi_utils_is_wifi (const char *iface, const char *sysfs_path); WifiData *wifi_utils_init (const char *iface, int ifindex, gboolean check_scan); +int wifi_utils_get_ifindex (WifiData *data); + +const char *wifi_utils_get_iface (WifiData *data); + void wifi_utils_deinit (WifiData *data); NMDeviceWifiCapabilities wifi_utils_get_caps (WifiData *data); diff --git a/src/ppp-manager/Makefile.in b/src/ppp-manager/Makefile.in index 9a3cff62..c80ae6bc 100644 --- a/src/ppp-manager/Makefile.in +++ b/src/ppp-manager/Makefile.in @@ -350,6 +350,7 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@ NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ diff --git a/src/rdisc/Makefile.in b/src/rdisc/Makefile.in index 0ab39873..ebf72fb7 100644 --- a/src/rdisc/Makefile.in +++ b/src/rdisc/Makefile.in @@ -324,6 +324,7 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@ NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ diff --git a/src/rdisc/tests/Makefile.in b/src/rdisc/tests/Makefile.in index 7d452119..895d7063 100644 --- a/src/rdisc/tests/Makefile.in +++ b/src/rdisc/tests/Makefile.in @@ -525,6 +525,7 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@ NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ diff --git a/src/settings/nm-agent-manager.c b/src/settings/nm-agent-manager.c index 48a7da7b..54ca2f55 100644 --- a/src/settings/nm-agent-manager.c +++ b/src/settings/nm-agent-manager.c @@ -20,11 +20,13 @@ #include "nm-default.h" +#include "nm-agent-manager.h" + #include <string.h> #include <pwd.h> +#include "nm-common-macros.h" #include "nm-dbus-interface.h" -#include "nm-agent-manager.h" #include "nm-secret-agent.h" #include "nm-auth-utils.h" #include "nm-setting-vpn.h" diff --git a/src/settings/nm-agent-manager.h b/src/settings/nm-agent-manager.h index 2f505537..8240a2b5 100644 --- a/src/settings/nm-agent-manager.h +++ b/src/settings/nm-agent-manager.h @@ -21,7 +21,7 @@ #ifndef __NETWORKMANAGER_AGENT_MANAGER_H__ #define __NETWORKMANAGER_AGENT_MANAGER_H__ -#include <nm-connection.h> +#include "nm-connection.h" #include "nm-exported-object.h" #include "nm-secret-agent.h" diff --git a/src/settings/nm-secret-agent.c b/src/settings/nm-secret-agent.c index bfa7b506..8bc88fd4 100644 --- a/src/settings/nm-secret-agent.c +++ b/src/settings/nm-secret-agent.c @@ -362,6 +362,9 @@ nm_secret_agent_get_secrets (NMSecretAgent *self, r = request_new (self, "GetSecrets", path, setting_name, callback, callback_data); r->is_get_secrets = TRUE; g_hash_table_add (priv->requests, r); + + /* Increase the timeout only for this call */ + g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (priv->proxy), 120000); nmdbus_secret_agent_call_get_secrets (priv->proxy, dict, path, @@ -370,6 +373,7 @@ nm_secret_agent_get_secrets (NMSecretAgent *self, flags, r->cancellable, get_callback, r); + g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (priv->proxy), -1); return r; } diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c index 6bed3fe5..5b3a3999 100644 --- a/src/settings/nm-settings-connection.c +++ b/src/settings/nm-settings-connection.c @@ -21,10 +21,12 @@ #include "nm-default.h" +#include "nm-settings-connection.h" + #include <string.h> +#include "nm-common-macros.h" #include "nm-dbus-interface.h" -#include "nm-settings-connection.h" #include "nm-session-monitor.h" #include "nm-auth-utils.h" #include "nm-auth-subject.h" @@ -70,19 +72,18 @@ G_DEFINE_TYPE_WITH_CODE (NMSettingsConnection, nm_settings_connection, NM_TYPE_E NM_TYPE_SETTINGS_CONNECTION, \ NMSettingsConnectionPrivate)) -enum { - PROP_0 = 0, +NM_GOBJECT_PROPERTIES_DEFINE (NMSettingsConnection, PROP_VISIBLE, PROP_UNSAVED, PROP_READY, PROP_FLAGS, PROP_FILENAME, -}; +); enum { UPDATED, REMOVED, - UPDATED_BY_USER, + UPDATED_INTERNAL, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; @@ -97,8 +98,6 @@ typedef struct { NMSettingsConnectionFlags flags; gboolean ready; - guint updated_idle_id; - GSList *pending_auths; /* List of pending authentication requests */ gboolean visible; /* Is this connection is visible by some session? */ @@ -133,6 +132,15 @@ typedef struct { /*******************************************************************/ +static void +_emit_updated (NMSettingsConnection *self, gboolean by_user) +{ + g_signal_emit (self, signals[UPDATED], 0); + g_signal_emit (self, signals[UPDATED_INTERNAL], 0, by_user); +} + +/*******************************************************************/ + gboolean nm_settings_connection_has_unmodified_applied_connection (NMSettingsConnection *self, NMConnection *applied_connection, @@ -292,7 +300,7 @@ set_visible (NMSettingsConnection *self, gboolean new_visible) if (new_visible == priv->visible) return; priv->visible = new_visible; - g_object_notify (G_OBJECT (self), NM_SETTINGS_CONNECTION_VISIBLE); + _notify (self, PROP_VISIBLE); } gboolean @@ -465,14 +473,6 @@ secrets_cleared_cb (NMSettingsConnection *self) priv->agent_secrets = NULL; } -static gboolean -emit_updated (NMSettingsConnection *self) -{ - NM_SETTINGS_CONNECTION_GET_PRIVATE (self)->updated_idle_id = 0; - g_signal_emit (self, signals[UPDATED], 0); - return FALSE; -} - static void set_unsaved (NMSettingsConnection *self, gboolean now_unsaved) { @@ -491,16 +491,10 @@ set_unsaved (NMSettingsConnection *self, gboolean now_unsaved) } static void -changed_cb (NMSettingsConnection *self, gpointer user_data) +connection_changed_cb (NMSettingsConnection *self, gpointer unused) { - gboolean update_unsaved = !!user_data; - - NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); - - if (update_unsaved) - set_unsaved (self, TRUE); - if (priv->updated_idle_id == 0) - priv->updated_idle_id = g_idle_add ((GSourceFunc) emit_updated, self); + set_unsaved (self, TRUE); + _emit_updated (self, FALSE); } /* Update the settings of this connection to match that of 'new_connection', @@ -543,7 +537,7 @@ nm_settings_connection_replace_settings (NMSettingsConnection *self, /* Disconnect the changed signal to ensure we don't set Unsaved when * it's not required. */ - g_signal_handlers_block_by_func (self, G_CALLBACK (changed_cb), GUINT_TO_POINTER (TRUE)); + g_signal_handlers_block_by_func (self, G_CALLBACK (connection_changed_cb), NULL); if (log_diff_name) nm_utils_log_connection_diff (new_connection, NM_CONNECTION (self), LOGL_DEBUG, LOGD_CORE, log_diff_name, "++ "); @@ -580,11 +574,12 @@ nm_settings_connection_replace_settings (NMSettingsConnection *self, /* Manually emit changed signal since we disconnected the handler, but * only update Unsaved if the caller wanted us to. */ - changed_cb (self, GUINT_TO_POINTER (update_unsaved)); + if (update_unsaved) + set_unsaved (self, TRUE); - g_signal_emit (self, signals[UPDATED_BY_USER], 0); + g_signal_handlers_unblock_by_func (self, G_CALLBACK (connection_changed_cb), NULL); - g_signal_handlers_unblock_by_func (self, G_CALLBACK (changed_cb), GUINT_TO_POINTER (TRUE)); + _emit_updated (self, TRUE); return success; } @@ -2099,9 +2094,9 @@ nm_settings_connection_set_flags_all (NMSettingsConnection *self, NMSettingsConn old_flags = priv->flags; if (old_flags != flags) { priv->flags = flags; - g_object_notify (G_OBJECT (self), NM_SETTINGS_CONNECTION_FLAGS); + _notify (self, PROP_FLAGS); if (NM_FLAGS_HAS (old_flags, NM_SETTINGS_CONNECTION_FLAGS_UNSAVED) != NM_FLAGS_HAS (flags, NM_SETTINGS_CONNECTION_FLAGS_UNSAVED)) - g_object_notify (G_OBJECT (self), NM_SETTINGS_CONNECTION_UNSAVED); + _notify (self, PROP_UNSAVED); } return old_flags; } @@ -2506,7 +2501,7 @@ nm_settings_connection_set_ready (NMSettingsConnection *self, ready = !!ready; if (priv->ready != ready) { priv->ready = ready; - g_object_notify (G_OBJECT (self), NM_SETTINGS_CONNECTION_READY); + _notify (self, PROP_READY); } } @@ -2527,7 +2522,7 @@ nm_settings_connection_set_filename (NMSettingsConnection *self, if (g_strcmp0 (filename, priv->filename) != 0) { g_free (priv->filename); priv->filename = g_strdup (filename); - g_object_notify (G_OBJECT (self), NM_SETTINGS_CONNECTION_FILENAME); + _notify (self, PROP_FILENAME); } } @@ -2582,7 +2577,7 @@ nm_settings_connection_init (NMSettingsConnection *self) priv->autoconnect_blocked_reason = NM_DEVICE_STATE_REASON_NONE; g_signal_connect (self, NM_CONNECTION_SECRETS_CLEARED, G_CALLBACK (secrets_cleared_cb), NULL); - g_signal_connect (self, NM_CONNECTION_CHANGED, G_CALLBACK (changed_cb), GUINT_TO_POINTER (TRUE)); + g_signal_connect (self, NM_CONNECTION_CHANGED, G_CALLBACK (connection_changed_cb), NULL); } static void @@ -2613,14 +2608,12 @@ dispose (GObject *object) } } - nm_clear_g_source (&priv->updated_idle_id); - /* Disconnect handlers. - * changed_cb() has to be disconnected *before* nm_connection_clear_secrets(), + * connection_changed_cb() has to be disconnected *before* nm_connection_clear_secrets(), * because nm_connection_clear_secrets() emits NM_CONNECTION_CHANGED signal. */ g_signal_handlers_disconnect_by_func (self, G_CALLBACK (secrets_cleared_cb), NULL); - g_signal_handlers_disconnect_by_func (self, G_CALLBACK (changed_cb), GUINT_TO_POINTER (TRUE)); + g_signal_handlers_disconnect_by_func (self, G_CALLBACK (connection_changed_cb), NULL); nm_connection_clear_secrets (NM_CONNECTION (self)); g_clear_object (&priv->system_secrets); @@ -2719,72 +2712,68 @@ nm_settings_connection_class_init (NMSettingsConnectionClass *class) class->supports_secrets = supports_secrets; /* Properties */ - g_object_class_install_property - (object_class, PROP_VISIBLE, - g_param_spec_boolean (NM_SETTINGS_CONNECTION_VISIBLE, "", "", - FALSE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_UNSAVED, - g_param_spec_boolean (NM_SETTINGS_CONNECTION_UNSAVED, "", "", - FALSE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_READY, - g_param_spec_boolean (NM_SETTINGS_CONNECTION_READY, "", "", - TRUE, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_FLAGS, + obj_properties[PROP_VISIBLE] = + g_param_spec_boolean (NM_SETTINGS_CONNECTION_VISIBLE, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_UNSAVED] = + g_param_spec_boolean (NM_SETTINGS_CONNECTION_UNSAVED, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_READY] = + g_param_spec_boolean (NM_SETTINGS_CONNECTION_READY, "", "", + TRUE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_FLAGS] = g_param_spec_uint (NM_SETTINGS_CONNECTION_FLAGS, "", "", NM_SETTINGS_CONNECTION_FLAGS_NONE, NM_SETTINGS_CONNECTION_FLAGS_ALL, NM_SETTINGS_CONNECTION_FLAGS_NONE, G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_FILENAME] = + g_param_spec_string (NM_SETTINGS_CONNECTION_FILENAME, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); - g_object_class_install_property - (object_class, PROP_FILENAME, - g_param_spec_string (NM_SETTINGS_CONNECTION_FILENAME, "", "", - NULL, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); /* Signals */ - /* Emitted when the connection is changed for any reason */ signals[UPDATED] = - g_signal_new (NM_SETTINGS_CONNECTION_UPDATED, - G_TYPE_FROM_CLASS (class), - G_SIGNAL_RUN_FIRST, - 0, - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - /* Emitted when connection is changed from D-Bus */ - signals[UPDATED_BY_USER] = - g_signal_new (NM_SETTINGS_CONNECTION_UPDATED_BY_USER, - G_TYPE_FROM_CLASS (class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - signals[REMOVED] = - g_signal_new (NM_SETTINGS_CONNECTION_REMOVED, - G_TYPE_FROM_CLASS (class), - G_SIGNAL_RUN_FIRST, - 0, - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); + g_signal_new (NM_SETTINGS_CONNECTION_UPDATED, + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + /* internal signal, with an argument (gboolean by_user). */ + signals[UPDATED_INTERNAL] = + g_signal_new (NM_SETTINGS_CONNECTION_UPDATED_INTERNAL, + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__BOOLEAN, + G_TYPE_NONE, 1, G_TYPE_BOOLEAN); + + signals[REMOVED] = + g_signal_new (NM_SETTINGS_CONNECTION_REMOVED, + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (class), NMDBUS_TYPE_SETTINGS_CONNECTION_SKELETON, diff --git a/src/settings/nm-settings-connection.h b/src/settings/nm-settings-connection.h index 5c12a8ac..c45505d9 100644 --- a/src/settings/nm-settings-connection.h +++ b/src/settings/nm-settings-connection.h @@ -43,8 +43,8 @@ G_BEGIN_DECLS #define NM_SETTINGS_CONNECTION_GET_SECRETS "get-secrets" #define NM_SETTINGS_CONNECTION_CANCEL_SECRETS "cancel-secrets" -/* Emitted when connection is changed by a user action */ -#define NM_SETTINGS_CONNECTION_UPDATED_BY_USER "updated-by-user" +/* Internal signals */ +#define NM_SETTINGS_CONNECTION_UPDATED_INTERNAL "updated-internal" /* Properties */ #define NM_SETTINGS_CONNECTION_VISIBLE "visible" diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c index 65148994..73c678a6 100644 --- a/src/settings/nm-settings.c +++ b/src/settings/nm-settings.c @@ -36,6 +36,7 @@ #include <selinux/selinux.h> #endif +#include "nm-common-macros.h" #include "nm-dbus-interface.h" #include "nm-connection.h" #include "nm-setting-8021x.h" @@ -157,7 +158,6 @@ typedef struct { struct { char *value; - char *file; GFileMonitor *monitor; GFileMonitor *dhcp_monitor; gulong monitor_id; @@ -171,7 +171,6 @@ typedef struct { enum { CONNECTION_ADDED, CONNECTION_UPDATED, - CONNECTION_UPDATED_BY_USER, CONNECTION_REMOVED, CONNECTION_VISIBILITY_CHANGED, AGENT_REGISTERED, @@ -181,16 +180,13 @@ enum { }; static guint signals[LAST_SIGNAL] = { 0 }; -enum { - PROP_0, +NM_GOBJECT_PROPERTIES_DEFINE (NMSettings, PROP_UNMANAGED_SPECS, PROP_HOSTNAME, PROP_CAN_MODIFY, PROP_CONNECTIONS, PROP_STARTUP_COMPLETE, - - LAST_PROP -}; +); static void check_startup_complete (NMSettings *self) @@ -209,7 +205,7 @@ check_startup_complete (NMSettings *self) } priv->startup_complete = TRUE; - g_object_notify (G_OBJECT (self), NM_SETTINGS_STARTUP_COMPLETE); + _notify (self, PROP_STARTUP_COMPLETE); } static void @@ -589,11 +585,11 @@ nm_settings_get_hostname (NMSettings *self) #endif #if defined(HOSTNAME_PERSIST_GENTOO) - hostname = read_hostname_gentoo (priv->hostname.file); + hostname = read_hostname_gentoo (HOSTNAME_FILE); #elif defined(HOSTNAME_PERSIST_SLACKWARE) - hostname = read_hostname_slackware (priv->hostname.file); + hostname = read_hostname_slackware (HOSTNAME_FILE); #else - if (g_file_get_contents (priv->hostname.file, &hostname, NULL, NULL)) + if (g_file_get_contents (HOSTNAME_FILE, &hostname, NULL, NULL)) g_strchomp (hostname); #endif @@ -652,7 +648,7 @@ unmanaged_specs_changed (NMSettingsPlugin *config, update_specs (self, &priv->unmanaged_specs, nm_settings_plugin_get_unmanaged_specs); - g_object_notify (G_OBJECT (self), NM_SETTINGS_UNMANAGED_SPECS); + _notify (self, PROP_UNMANAGED_SPECS); } static void @@ -883,27 +879,17 @@ next: } static void -connection_updated (NMSettingsConnection *connection, gpointer user_data) +connection_updated (NMSettingsConnection *connection, gboolean by_user, gpointer user_data) { - /* Re-emit for listeners like NMPolicy */ g_signal_emit (NM_SETTINGS (user_data), signals[CONNECTION_UPDATED], 0, - connection); + connection, + by_user); g_signal_emit_by_name (NM_SETTINGS (user_data), NM_CP_SIGNAL_CONNECTION_UPDATED, connection); } static void -connection_updated_by_user (NMSettingsConnection *connection, gpointer user_data) -{ - /* Re-emit for listeners like NMPolicy */ - g_signal_emit (NM_SETTINGS (user_data), - signals[CONNECTION_UPDATED_BY_USER], - 0, - connection); -} - -static void connection_visibility_changed (NMSettingsConnection *connection, GParamSpec *pspec, gpointer user_data) @@ -933,7 +919,6 @@ connection_removed (NMSettingsConnection *connection, gpointer user_data) g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (connection_removed), self); g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (connection_updated), self); - g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (connection_updated_by_user), self); g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (connection_visibility_changed), self); g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (connection_ready_changed), self); g_object_unref (self); @@ -946,7 +931,7 @@ connection_removed (NMSettingsConnection *connection, gpointer user_data) /* Re-emit for listeners like NMPolicy */ g_signal_emit_by_name (self, NM_CP_SIGNAL_CONNECTION_REMOVED, connection); - g_object_notify (G_OBJECT (self), NM_SETTINGS_CONNECTIONS); + _notify (self, PROP_CONNECTIONS); if (nm_exported_object_is_exported (NM_EXPORTED_OBJECT (connection))) nm_exported_object_unexport (NM_EXPORTED_OBJECT (connection)); @@ -1065,10 +1050,8 @@ claim_connection (NMSettings *self, NMSettingsConnection *connection) g_object_ref (self); g_signal_connect (connection, NM_SETTINGS_CONNECTION_REMOVED, G_CALLBACK (connection_removed), self); - g_signal_connect (connection, NM_SETTINGS_CONNECTION_UPDATED, + g_signal_connect (connection, NM_SETTINGS_CONNECTION_UPDATED_INTERNAL, G_CALLBACK (connection_updated), self); - g_signal_connect (connection, NM_SETTINGS_CONNECTION_UPDATED_BY_USER, - G_CALLBACK (connection_updated_by_user), self); g_signal_connect (connection, "notify::" NM_SETTINGS_CONNECTION_VISIBLE, G_CALLBACK (connection_visibility_changed), self); @@ -1096,7 +1079,7 @@ claim_connection (NMSettings *self, NMSettingsConnection *connection) /* Internal added signal */ g_signal_emit (self, signals[CONNECTION_ADDED], 0, connection); g_signal_emit_by_name (self, NM_CP_SIGNAL_CONNECTION_ADDED, connection); - g_object_notify (G_OBJECT (self), NM_SETTINGS_CONNECTIONS); + _notify (self, PROP_CONNECTIONS); /* Exported D-Bus signal */ g_signal_emit (self, signals[NEW_CONNECTION], 0, connection); @@ -1111,7 +1094,7 @@ claim_connection (NMSettings *self, NMSettingsConnection *connection) * not save to disk * @error: on return, a location to store any errors that may occur * - * Creates a new #NMSettingsConnection for the given source @connection. + * Creates a new #NMSettingsConnection for the given source @connection. * The returned object is owned by @self and the caller must reference * the object to continue using it. * @@ -1635,7 +1618,7 @@ write_hostname (NMSettingsPrivate *priv, const char *hostname) char *hostname_eol; gboolean ret; gs_free_error GError *error = NULL; - const char *file = priv->hostname.file; + const char *file = HOSTNAME_FILE; gs_free char *link_path = NULL; gs_unref_variant GVariant *var = NULL; struct stat file_stat; @@ -1664,7 +1647,7 @@ write_hostname (NMSettingsPrivate *priv, const char *hostname) */ if ( lstat (file, &file_stat) == 0 && S_ISLNK (file_stat.st_mode) - && (link_path = g_file_read_link (file, NULL))) + && (link_path = nm_utils_read_link_absolute (file, NULL))) file = link_path; #if HAVE_SELINUX @@ -1830,7 +1813,7 @@ hostname_maybe_changed (NMSettings *settings) NM_PRINT_FMT_QUOTED (new_hostname, "\"", new_hostname, "\"", "(none)")); g_free (priv->hostname.value); priv->hostname.value = new_hostname; - g_object_notify (G_OBJECT (settings), NM_SETTINGS_HOSTNAME); + _notify (settings, PROP_HOSTNAME); } else g_free (new_hostname); } @@ -1932,10 +1915,13 @@ default_wired_connection_removed_cb (NMSettingsConnection *connection, NMSetting } static void -default_wired_connection_updated_by_user_cb (NMSettingsConnection *connection, NMSettings *self) +default_wired_connection_updated_by_user_cb (NMSettingsConnection *connection, gboolean by_user, NMSettings *self) { NMDevice *device; + if (!by_user) + return; + /* The connection has been changed by the user, it should no longer be * considered a default wired connection, and should no longer affect * the no-auto-default configuration option. @@ -2010,7 +1996,7 @@ device_realized (NMDevice *device, GParamSpec *pspec, NMSettings *self) g_object_set_data (G_OBJECT (added), DEFAULT_WIRED_DEVICE_TAG, device); g_object_set_data (G_OBJECT (device), DEFAULT_WIRED_CONNECTION_TAG, added); - g_signal_connect (added, NM_SETTINGS_CONNECTION_UPDATED_BY_USER, + g_signal_connect (added, NM_SETTINGS_CONNECTION_UPDATED_INTERNAL, G_CALLBACK (default_wired_connection_updated_by_user_cb), self); g_signal_connect (added, NM_SETTINGS_CONNECTION_REMOVED, G_CALLBACK (default_wired_connection_removed_cb), self); @@ -2174,7 +2160,8 @@ hostnamed_properties_changed (GDBusProxy *proxy, char **invalidated_properties, gpointer user_data) { - NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (user_data); + NMSettings *self = user_data; + NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self); GVariant *v_hostname; const char *hostname; @@ -2191,7 +2178,7 @@ hostnamed_properties_changed (GDBusProxy *proxy, NM_PRINT_FMT_QUOTED (hostname, "\"", hostname, "\"", "(none)")); g_free (priv->hostname.value); priv->hostname.value = g_strdup (hostname); - g_object_notify (G_OBJECT (user_data), NM_SETTINGS_HOSTNAME); + _notify (self, PROP_HOSTNAME); nm_dispatcher_call (DISPATCHER_ACTION_HOSTNAME, NULL, NULL, NULL, NULL, NULL, NULL); } @@ -2205,11 +2192,10 @@ setup_hostname_file_monitors (NMSettings *self) GFileMonitor *monitor; GFile *file; - priv->hostname.file = HOSTNAME_FILE; priv->hostname.value = nm_settings_get_hostname (self); /* monitor changes to hostname file */ - file = g_file_new_for_path (priv->hostname.file); + file = g_file_new_for_path (HOSTNAME_FILE); monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, NULL); g_object_unref (file); if (monitor) { @@ -2296,7 +2282,7 @@ nm_settings_start (NMSettings *self, GError **error) setup_hostname_file_monitors (self); priv->started = TRUE; - g_object_notify (G_OBJECT (self), NM_SETTINGS_HOSTNAME); + _notify (self, PROP_HOSTNAME); return TRUE; } @@ -2447,96 +2433,86 @@ nm_settings_class_init (NMSettingsClass *class) /* properties */ - g_object_class_install_property - (object_class, PROP_UNMANAGED_SPECS, - g_param_spec_boxed (NM_SETTINGS_UNMANAGED_SPECS, "", "", - G_TYPE_STRV, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_HOSTNAME, - g_param_spec_string (NM_SETTINGS_HOSTNAME, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_CAN_MODIFY, - g_param_spec_boolean (NM_SETTINGS_CAN_MODIFY, "", "", - FALSE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_CONNECTIONS, - g_param_spec_boxed (NM_SETTINGS_CONNECTIONS, "", "", - G_TYPE_STRV, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_UNMANAGED_SPECS] = + g_param_spec_boxed (NM_SETTINGS_UNMANAGED_SPECS, "", "", + G_TYPE_STRV, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_HOSTNAME] = + g_param_spec_string (NM_SETTINGS_HOSTNAME, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_CAN_MODIFY] = + g_param_spec_boolean (NM_SETTINGS_CAN_MODIFY, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_CONNECTIONS] = + g_param_spec_boxed (NM_SETTINGS_CONNECTIONS, "", "", + G_TYPE_STRV, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_STARTUP_COMPLETE] = + g_param_spec_boolean (NM_SETTINGS_STARTUP_COMPLETE, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); /* signals */ - signals[CONNECTION_ADDED] = - g_signal_new (NM_SETTINGS_SIGNAL_CONNECTION_ADDED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMSettingsClass, connection_added), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, NM_TYPE_SETTINGS_CONNECTION); - - signals[CONNECTION_UPDATED] = - g_signal_new (NM_SETTINGS_SIGNAL_CONNECTION_UPDATED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMSettingsClass, connection_updated), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, NM_TYPE_SETTINGS_CONNECTION); - - signals[CONNECTION_UPDATED_BY_USER] = - g_signal_new (NM_SETTINGS_SIGNAL_CONNECTION_UPDATED_BY_USER, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, NM_TYPE_SETTINGS_CONNECTION); - - signals[CONNECTION_REMOVED] = - g_signal_new (NM_SETTINGS_SIGNAL_CONNECTION_REMOVED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMSettingsClass, connection_removed), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, NM_TYPE_SETTINGS_CONNECTION); - - signals[CONNECTION_VISIBILITY_CHANGED] = - g_signal_new (NM_SETTINGS_SIGNAL_CONNECTION_VISIBILITY_CHANGED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMSettingsClass, connection_visibility_changed), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, NM_TYPE_SETTINGS_CONNECTION); + signals[CONNECTION_ADDED] = + g_signal_new (NM_SETTINGS_SIGNAL_CONNECTION_ADDED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, NM_TYPE_SETTINGS_CONNECTION); + + signals[CONNECTION_UPDATED] = + g_signal_new (NM_SETTINGS_SIGNAL_CONNECTION_UPDATED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, + NULL, + G_TYPE_NONE, 2, NM_TYPE_SETTINGS_CONNECTION, G_TYPE_BOOLEAN); + + signals[CONNECTION_REMOVED] = + g_signal_new (NM_SETTINGS_SIGNAL_CONNECTION_REMOVED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, NM_TYPE_SETTINGS_CONNECTION); + + signals[CONNECTION_VISIBILITY_CHANGED] = + g_signal_new (NM_SETTINGS_SIGNAL_CONNECTION_VISIBILITY_CHANGED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, NM_TYPE_SETTINGS_CONNECTION); signals[AGENT_REGISTERED] = - g_signal_new (NM_SETTINGS_SIGNAL_AGENT_REGISTERED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMSettingsClass, agent_registered), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, NM_TYPE_SECRET_AGENT); - - - signals[NEW_CONNECTION] = - g_signal_new ("new-connection", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, 0, NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, NM_TYPE_SETTINGS_CONNECTION); + g_signal_new (NM_SETTINGS_SIGNAL_AGENT_REGISTERED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, NM_TYPE_SECRET_AGENT); + + + signals[NEW_CONNECTION] = + g_signal_new ("new-connection", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, 0, NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, NM_TYPE_SETTINGS_CONNECTION); nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (class), NMDBUS_TYPE_SETTINGS_SKELETON, diff --git a/src/settings/nm-settings.h b/src/settings/nm-settings.h index 051c2094..5d41e5bc 100644 --- a/src/settings/nm-settings.h +++ b/src/settings/nm-settings.h @@ -41,11 +41,10 @@ #define NM_SETTINGS_HOSTNAME "hostname" #define NM_SETTINGS_CAN_MODIFY "can-modify" #define NM_SETTINGS_CONNECTIONS "connections" -#define NM_SETTINGS_STARTUP_COMPLETE "connections" +#define NM_SETTINGS_STARTUP_COMPLETE "startup-complete" #define NM_SETTINGS_SIGNAL_CONNECTION_ADDED "connection-added" #define NM_SETTINGS_SIGNAL_CONNECTION_UPDATED "connection-updated" -#define NM_SETTINGS_SIGNAL_CONNECTION_UPDATED_BY_USER "connection-updated-by-user" #define NM_SETTINGS_SIGNAL_CONNECTION_REMOVED "connection-removed" #define NM_SETTINGS_SIGNAL_CONNECTION_VISIBILITY_CHANGED "connection-visibility-changed" #define NM_SETTINGS_SIGNAL_AGENT_REGISTERED "agent-registered" @@ -56,19 +55,6 @@ struct _NMSettings { typedef struct { NMExportedObjectClass parent_class; - - /* Signals */ - void (*properties_changed) (NMSettings *self, GHashTable *properties); - - void (*connection_added) (NMSettings *self, NMSettingsConnection *connection); - - void (*connection_updated) (NMSettings *self, NMSettingsConnection *connection); - - void (*connection_removed) (NMSettings *self, NMSettingsConnection *connection); - - void (*connection_visibility_changed) (NMSettings *self, NMSettingsConnection *connection); - - void (*agent_registered) (NMSettings *self, NMSecretAgent *agent); } NMSettingsClass; typedef void (*NMSettingsSetHostnameCb) (const char *name, gboolean result, gpointer user_data); diff --git a/src/settings/plugins/Makefile.in b/src/settings/plugins/Makefile.in index 643e0da7..e770ccde 100644 --- a/src/settings/plugins/Makefile.in +++ b/src/settings/plugins/Makefile.in @@ -328,6 +328,7 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@ NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ diff --git a/src/settings/plugins/ibft/Makefile.in b/src/settings/plugins/ibft/Makefile.in index 7142cf1d..fe124670 100644 --- a/src/settings/plugins/ibft/Makefile.in +++ b/src/settings/plugins/ibft/Makefile.in @@ -395,6 +395,7 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@ NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ diff --git a/src/settings/plugins/ibft/tests/Makefile.in b/src/settings/plugins/ibft/tests/Makefile.in index 1869b502..c3fef788 100644 --- a/src/settings/plugins/ibft/tests/Makefile.in +++ b/src/settings/plugins/ibft/tests/Makefile.in @@ -523,6 +523,7 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@ NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ diff --git a/src/settings/plugins/ifcfg-rh/Makefile.in b/src/settings/plugins/ifcfg-rh/Makefile.in index 54a2b805..a87ee94c 100644 --- a/src/settings/plugins/ifcfg-rh/Makefile.in +++ b/src/settings/plugins/ifcfg-rh/Makefile.in @@ -405,6 +405,7 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@ NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ diff --git a/src/settings/plugins/ifcfg-rh/plugin.c b/src/settings/plugins/ifcfg-rh/plugin.c index 1fb6b789..63184eb5 100644 --- a/src/settings/plugins/ifcfg-rh/plugin.c +++ b/src/settings/plugins/ifcfg-rh/plugin.c @@ -943,8 +943,8 @@ config_changed_cb (NMConfig *config, * On SIGHUP and SIGUSR1 try to re-connect to D-Bus. So in the unlikely * event that the D-Bus conneciton is broken, that allows for recovery * without need for restarting NetworkManager. */ - if ( NM_FLAGS_HAS (changes, NM_CONFIG_CHANGE_SIGHUP) - || NM_FLAGS_HAS (changes, NM_CONFIG_CHANGE_SIGUSR1)) { + if (NM_FLAGS_ANY (changes, NM_CONFIG_CHANGE_CAUSE_SIGHUP + | NM_CONFIG_CHANGE_CAUSE_SIGUSR1)) { if (!SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (self)->dbus.connection) _dbus_setup (self); } diff --git a/src/settings/plugins/ifcfg-rh/reader.c b/src/settings/plugins/ifcfg-rh/reader.c index 39e981f9..fe762db1 100644 --- a/src/settings/plugins/ifcfg-rh/reader.c +++ b/src/settings/plugins/ifcfg-rh/reader.c @@ -984,6 +984,8 @@ make_ip4_setting (shvarFile *ifcfg, goto done; (void) nm_setting_ip_config_add_address (s_ip4, addr); nm_ip_address_unref (addr); + if (never_default) + PARSE_WARNING ("GATEWAY will be ignored when DEFROUTE is disabled"); g_object_set (s_ip4, NM_SETTING_IP_CONFIG_GATEWAY, gateway, NULL); } return NM_SETTING (s_ip4); @@ -1082,6 +1084,9 @@ make_ip4_setting (shvarFile *ifcfg, } g_object_set (s_ip4, NM_SETTING_IP_CONFIG_GATEWAY, gateway, NULL); + if (gateway && never_default) + PARSE_WARNING ("GATEWAY will be ignored when DEFROUTE is disabled"); + /* DNS servers * Pick up just IPv4 addresses (IPv6 addresses are taken by make_ip6_setting()) */ diff --git a/src/settings/plugins/ifcfg-rh/tests/Makefile.in b/src/settings/plugins/ifcfg-rh/tests/Makefile.in index d822e2e1..4bc35da2 100644 --- a/src/settings/plugins/ifcfg-rh/tests/Makefile.in +++ b/src/settings/plugins/ifcfg-rh/tests/Makefile.in @@ -577,6 +577,7 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@ NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ 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 e98ea93c..74f3bf05 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in @@ -264,6 +264,7 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@ NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ diff --git a/src/settings/plugins/ifnet/Makefile.in b/src/settings/plugins/ifnet/Makefile.in index 4b496f54..9f99e957 100644 --- a/src/settings/plugins/ifnet/Makefile.in +++ b/src/settings/plugins/ifnet/Makefile.in @@ -396,6 +396,7 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@ NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ diff --git a/src/settings/plugins/ifnet/tests/Makefile.in b/src/settings/plugins/ifnet/tests/Makefile.in index 1a152870..4646a342 100644 --- a/src/settings/plugins/ifnet/tests/Makefile.in +++ b/src/settings/plugins/ifnet/tests/Makefile.in @@ -529,6 +529,7 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@ NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ diff --git a/src/settings/plugins/ifupdown/Makefile.in b/src/settings/plugins/ifupdown/Makefile.in index 1f8c7e1b..8b153c6d 100644 --- a/src/settings/plugins/ifupdown/Makefile.in +++ b/src/settings/plugins/ifupdown/Makefile.in @@ -395,6 +395,7 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@ NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ diff --git a/src/settings/plugins/ifupdown/tests/Makefile.in b/src/settings/plugins/ifupdown/tests/Makefile.in index 06e9b61e..f744e620 100644 --- a/src/settings/plugins/ifupdown/tests/Makefile.in +++ b/src/settings/plugins/ifupdown/tests/Makefile.in @@ -524,6 +524,7 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@ NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ diff --git a/src/settings/plugins/keyfile/Makefile.in b/src/settings/plugins/keyfile/Makefile.in index 65410336..bace6af4 100644 --- a/src/settings/plugins/keyfile/Makefile.in +++ b/src/settings/plugins/keyfile/Makefile.in @@ -364,6 +364,7 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@ NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ diff --git a/src/settings/plugins/keyfile/tests/Makefile.in b/src/settings/plugins/keyfile/tests/Makefile.in index eb7a99d2..89708a18 100644 --- a/src/settings/plugins/keyfile/tests/Makefile.in +++ b/src/settings/plugins/keyfile/tests/Makefile.in @@ -568,6 +568,7 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@ NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Makefile.in b/src/settings/plugins/keyfile/tests/keyfiles/Makefile.in index 56f0735f..8be2893c 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Makefile.in +++ b/src/settings/plugins/keyfile/tests/keyfiles/Makefile.in @@ -264,6 +264,7 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@ NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ diff --git a/src/supplicant-manager/tests/Makefile.in b/src/supplicant-manager/tests/Makefile.in index 5e521ae0..7c822d91 100644 --- a/src/supplicant-manager/tests/Makefile.in +++ b/src/supplicant-manager/tests/Makefile.in @@ -562,6 +562,7 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@ NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ diff --git a/src/supplicant-manager/tests/certs/Makefile.in b/src/supplicant-manager/tests/certs/Makefile.in index 7f29bb3c..819f36cc 100644 --- a/src/supplicant-manager/tests/certs/Makefile.in +++ b/src/supplicant-manager/tests/certs/Makefile.in @@ -264,6 +264,7 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@ NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in index a4a135c5..2296c2b0 100644 --- a/src/tests/Makefile.in +++ b/src/tests/Makefile.in @@ -632,6 +632,7 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@ NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ diff --git a/src/tests/config/Makefile.in b/src/tests/config/Makefile.in index 5a4bfbd1..7197ee1f 100644 --- a/src/tests/config/Makefile.in +++ b/src/tests/config/Makefile.in @@ -521,6 +521,7 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_DNS_RC_MANAGER = @NM_CONFIG_DEFAULT_DNS_RC_MANAGER@ NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ diff --git a/src/tests/config/test-config.c b/src/tests/config/test-config.c index d83ff4b5..b6d88edf 100644 --- a/src/tests/config/test-config.c +++ b/src/tests/config/test-config.c @@ -343,7 +343,7 @@ test_config_no_auto_default (void) g_assert (!nm_config_get_no_auto_default_for_device (config, dev3)); g_assert (nm_config_get_no_auto_default_for_device (config, dev4)); - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*config: update * (no-auto-default)*"); + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*config: signal NO_AUTO_DEFAULT,no-auto-default *"); nm_config_set_no_auto_default_for_device (config, dev3); g_test_assert_expected_messages (); @@ -511,9 +511,9 @@ _set_values_config_changed_cb (NMConfig *config, g_assert (config_changed_data); g_assert (config_changed_data->changes == NM_CONFIG_CHANGE_NONE); - if (changes == NM_CONFIG_CHANGE_SIGHUP) + if (changes == NM_CONFIG_CHANGE_CAUSE_SIGHUP) return; - changes &= ~NM_CONFIG_CHANGE_SIGHUP; + changes &= ~NM_CONFIG_CHANGE_CAUSE_SIGHUP; config_changed_data->changes = changes; @@ -556,11 +556,11 @@ _set_values_user (NMConfig *config, config_data_before = g_object_ref (nm_config_get_data (config)); if (expected_changes != NM_CONFIG_CHANGE_NONE) - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*config: update *"); + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*config: signal *"); else g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*config: signal SIGHUP (no changes from disk)*"); - nm_config_reload (config, SIGHUP); + nm_config_reload (config, NM_CONFIG_CHANGE_CAUSE_SIGHUP); g_test_assert_expected_messages (); @@ -600,7 +600,7 @@ _set_values_intern (NMConfig *config, &config_changed_data); if (expected_changes != NM_CONFIG_CHANGE_NONE) - g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*config: update *"); + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*config: signal *"); nm_config_set_values (config, keyfile_intern, TRUE, FALSE); @@ -649,14 +649,14 @@ static void _set_values_intern_internal_set (NMConfig *config, gboolean set_user, GKeyFile *keyfile, NMConfigChangeFlags *out_expected_changes) { g_key_file_set_string (keyfile, NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN"section1", "key", "internal-section"); - *out_expected_changes = NM_CONFIG_CHANGE_VALUES | NM_CONFIG_CHANGE_VALUES_INTERN; + *out_expected_changes = NM_CONFIG_CHANGE_CAUSE_SET_VALUES | NM_CONFIG_CHANGE_VALUES | NM_CONFIG_CHANGE_VALUES_INTERN; } static void _set_values_intern_internal_check (NMConfig *config, NMConfigData *config_data, gboolean is_change_event, NMConfigChangeFlags changes, NMConfigData *old_data) { if (is_change_event) - g_assert (changes == (NM_CONFIG_CHANGE_VALUES | NM_CONFIG_CHANGE_VALUES_INTERN)); + g_assert (changes == (NM_CONFIG_CHANGE_CAUSE_SET_VALUES | NM_CONFIG_CHANGE_VALUES | NM_CONFIG_CHANGE_VALUES_INTERN)); assert_config_value (config_data, NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN"section1", "key", "internal-section"); } @@ -690,14 +690,14 @@ _set_values_intern_atomic_section_1_set (NMConfig *config, gboolean set_user, GK g_key_file_set_string (keyfile, "atomic-prefix-1.section-a", "key3", "intern-value3"); g_key_file_set_string (keyfile, "non-atomic-prefix-1.section-a", "nap1-key1", "intern-value1"); g_key_file_set_string (keyfile, "non-atomic-prefix-1.section-a", "nap1-key3", "intern-value3"); - *out_expected_changes = NM_CONFIG_CHANGE_VALUES | NM_CONFIG_CHANGE_VALUES_INTERN; + *out_expected_changes = NM_CONFIG_CHANGE_CAUSE_SET_VALUES | NM_CONFIG_CHANGE_VALUES | NM_CONFIG_CHANGE_VALUES_INTERN; } static void _set_values_intern_atomic_section_1_check (NMConfig *config, NMConfigData *config_data, gboolean is_change_event, NMConfigChangeFlags changes, NMConfigData *old_data) { if (is_change_event) - g_assert (changes == (NM_CONFIG_CHANGE_VALUES | NM_CONFIG_CHANGE_VALUES_INTERN)); + g_assert (changes == (NM_CONFIG_CHANGE_CAUSE_SET_VALUES | NM_CONFIG_CHANGE_VALUES | NM_CONFIG_CHANGE_VALUES_INTERN)); assert_config_value (config_data, "atomic-prefix-1.section-a", "key1", "intern-value1"); assert_config_value (config_data, "atomic-prefix-1.section-a", "key2", NULL); assert_config_value (config_data, "atomic-prefix-1.section-a", "key3", "intern-value3"); @@ -744,14 +744,14 @@ _set_values_intern_atomic_section_2_set (NMConfig *config, gboolean set_user, GK g_key_file_set_string (keyfile, "non-atomic-prefix-1.section-a", "nap1-key3", "intern-value3"); g_key_file_set_string (keyfile, NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN"with-whitespace", "key1", " b c\\, d "); g_key_file_set_value (keyfile, NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN"with-whitespace", "key2", " b c\\, d "); - *out_expected_changes = NM_CONFIG_CHANGE_VALUES | NM_CONFIG_CHANGE_VALUES_INTERN; + *out_expected_changes = NM_CONFIG_CHANGE_CAUSE_SET_VALUES | NM_CONFIG_CHANGE_VALUES | NM_CONFIG_CHANGE_VALUES_INTERN; } static void _set_values_intern_atomic_section_2_check (NMConfig *config, NMConfigData *config_data, gboolean is_change_event, NMConfigChangeFlags changes, NMConfigData *old_data) { if (is_change_event) - g_assert (changes == (NM_CONFIG_CHANGE_VALUES | NM_CONFIG_CHANGE_VALUES_INTERN)); + g_assert (changes == (NM_CONFIG_CHANGE_CAUSE_SET_VALUES | NM_CONFIG_CHANGE_VALUES | NM_CONFIG_CHANGE_VALUES_INTERN)); g_assert (!nm_config_data_has_group (config_data, "atomic-prefix-1.section-a")); assert_config_value (config_data, "atomic-prefix-1.section-b", "key1", "user-value1"); assert_config_value (config_data, "non-atomic-prefix-1.section-a", "nap1-key1", NULL); @@ -862,17 +862,17 @@ test_config_signal (void) G_CALLBACK (_test_signal_config_changed_cb), &expected); - expected = NM_CONFIG_CHANGE_SIGUSR1; + expected = NM_CONFIG_CHANGE_CAUSE_SIGUSR1; g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*config: signal SIGUSR1"); - nm_config_reload (config, SIGUSR1); + nm_config_reload (config, expected); - expected = NM_CONFIG_CHANGE_SIGUSR2; + expected = NM_CONFIG_CHANGE_CAUSE_SIGUSR2; g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*config: signal SIGUSR2"); - nm_config_reload (config, SIGUSR2); + nm_config_reload (config, expected); - expected = NM_CONFIG_CHANGE_SIGHUP; + expected = NM_CONFIG_CHANGE_CAUSE_SIGHUP; g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*config: signal SIGHUP (no changes from disk)*"); - nm_config_reload (config, SIGHUP); + nm_config_reload (config, expected); /* test with subscribing two signals... @@ -883,9 +883,9 @@ test_config_signal (void) NM_CONFIG_SIGNAL_CONFIG_CHANGED, G_CALLBACK (_test_signal_config_changed_cb2), &expected); - expected = NM_CONFIG_CHANGE_SIGUSR2; + expected = NM_CONFIG_CHANGE_CAUSE_SIGUSR2; g_test_expect_message ("NetworkManager", G_LOG_LEVEL_INFO, "*config: signal SIGUSR2"); - nm_config_reload (config, SIGUSR2); + nm_config_reload (config, NM_CONFIG_CHANGE_CAUSE_SIGUSR2); g_signal_handlers_disconnect_by_func (config, _test_signal_config_changed_cb2, &expected); diff --git a/src/tests/test-general.c b/src/tests/test-general.c index a45357e8..f714deec 100644 --- a/src/tests/test-general.c +++ b/src/tests/test-general.c @@ -1361,6 +1361,124 @@ test_duplicate_decl_specifier (void) v_result[0] = TEST_MAX (v_const[0], nmtst_get_rand_int () % 5) + v2; } +static void +test_reverse_dns_ip4 (void) +{ + guint32 addr; + GPtrArray *domains = g_ptr_array_new_full (8, g_free); + + inet_pton (AF_INET, "7.2.3.0", &addr); + nm_utils_get_reverse_dns_domains_ip4 (addr, 27, domains); + g_assert_cmpuint (domains->len, ==, 32); + g_assert_cmpstr (domains->pdata[0], ==, "0.3.2.7.in-addr.arpa"); + g_assert_cmpstr (domains->pdata[31], ==, "31.3.2.7.in-addr.arpa"); + + g_ptr_array_set_size (domains, 0); + + inet_pton (AF_INET, "10.155.16.0", &addr); + nm_utils_get_reverse_dns_domains_ip4 (addr, 22, domains); + g_assert_cmpuint (domains->len, ==, 4); + g_assert_cmpstr (domains->pdata[0], ==, "16.155.10.in-addr.arpa"); + g_assert_cmpstr (domains->pdata[1], ==, "17.155.10.in-addr.arpa"); + g_assert_cmpstr (domains->pdata[2], ==, "18.155.10.in-addr.arpa"); + g_assert_cmpstr (domains->pdata[3], ==, "19.155.10.in-addr.arpa"); + + g_ptr_array_set_size (domains, 0); + + inet_pton (AF_INET, "4.5.6.7", &addr); + nm_utils_get_reverse_dns_domains_ip4 (addr, 32, domains); + g_assert_cmpuint (domains->len, ==, 1); + g_assert_cmpstr (domains->pdata[0], ==, "7.6.5.4.in-addr.arpa"); + + g_ptr_array_set_size (domains, 0); + + inet_pton (AF_INET, "4.5.6.7", &addr); + nm_utils_get_reverse_dns_domains_ip4 (addr, 8, domains); + g_assert_cmpuint (domains->len, ==, 1); + g_assert_cmpstr (domains->pdata[0], ==, "4.in-addr.arpa"); + + g_ptr_array_set_size (domains, 0); + + inet_pton (AF_INET, "4.180.6.7", &addr); + nm_utils_get_reverse_dns_domains_ip4 (addr, 9, domains); + g_assert_cmpuint (domains->len, ==, 128); + g_assert_cmpstr (domains->pdata[0], ==, "128.4.in-addr.arpa"); + g_assert_cmpstr (domains->pdata[1], ==, "129.4.in-addr.arpa"); + g_assert_cmpstr (domains->pdata[127], ==, "255.4.in-addr.arpa"); + + g_ptr_array_set_size (domains, 0); + + inet_pton (AF_INET, "172.16.0.0", &addr); + nm_utils_get_reverse_dns_domains_ip4 (addr, 12, domains); + g_assert_cmpuint (domains->len, ==, 16); + g_assert_cmpstr (domains->pdata[0], ==, "16.172.in-addr.arpa"); + g_assert_cmpstr (domains->pdata[1], ==, "17.172.in-addr.arpa"); + g_assert_cmpstr (domains->pdata[14], ==, "30.172.in-addr.arpa"); + g_assert_cmpstr (domains->pdata[15], ==, "31.172.in-addr.arpa"); + + g_ptr_array_set_size (domains, 0); + + inet_pton (AF_INET, "1.2.3.4", &addr); + nm_utils_get_reverse_dns_domains_ip4 (addr, 0, domains); + g_assert_cmpuint (domains->len, ==, 0); + + g_ptr_array_unref (domains); +} + +static void +test_reverse_dns_ip6 (void) +{ + struct in6_addr addr; + GPtrArray *domains = g_ptr_array_new_full (8, g_free); + + inet_pton (AF_INET6, "1234::56", &addr); + nm_utils_get_reverse_dns_domains_ip6 (&addr, 16, domains); + g_assert_cmpuint (domains->len, ==, 1); + g_assert_cmpstr (domains->pdata[0], ==, "4.3.2.1.ip6.arpa"); + + g_ptr_array_set_size (domains, 0); + + inet_pton (AF_INET6, "1234::56", &addr); + nm_utils_get_reverse_dns_domains_ip6 (&addr, 17, domains); + g_assert_cmpuint (domains->len, ==, 8); + g_assert_cmpstr (domains->pdata[0], ==, "0.4.3.2.1.ip6.arpa"); + g_assert_cmpstr (domains->pdata[1], ==, "1.4.3.2.1.ip6.arpa"); + g_assert_cmpstr (domains->pdata[7], ==, "7.4.3.2.1.ip6.arpa"); + + g_ptr_array_set_size (domains, 0); + + inet_pton (AF_INET6, "2001:db8::", &addr); + nm_utils_get_reverse_dns_domains_ip6 (&addr, 29, domains); + g_assert_cmpuint (domains->len, ==, 8); + g_assert_cmpstr (domains->pdata[0], ==, "8.b.d.0.1.0.0.2.ip6.arpa"); + g_assert_cmpstr (domains->pdata[1], ==, "9.b.d.0.1.0.0.2.ip6.arpa"); + g_assert_cmpstr (domains->pdata[7], ==, "f.b.d.0.1.0.0.2.ip6.arpa"); + + g_ptr_array_set_size (domains, 0); + + inet_pton (AF_INET6, "0123:4567:89ab:cdef::", &addr); + nm_utils_get_reverse_dns_domains_ip6 (&addr, 63, domains); + g_assert_cmpuint (domains->len, ==, 2); + g_assert_cmpstr (domains->pdata[0], ==, "e.e.d.c.b.a.9.8.7.6.5.4.3.2.1.0.ip6.arpa"); + g_assert_cmpstr (domains->pdata[1], ==, "f.e.d.c.b.a.9.8.7.6.5.4.3.2.1.0.ip6.arpa"); + + g_ptr_array_set_size (domains, 0); + + inet_pton (AF_INET6, "fec0:1234:5678:9ab0::", &addr); + nm_utils_get_reverse_dns_domains_ip6 (&addr, 61, domains); + g_assert_cmpuint (domains->len, ==, 8); + g_assert_cmpstr (domains->pdata[0], ==, "0.b.a.9.8.7.6.5.4.3.2.1.0.c.e.f.ip6.arpa"); + g_assert_cmpstr (domains->pdata[7], ==, "7.b.a.9.8.7.6.5.4.3.2.1.0.c.e.f.ip6.arpa"); + + g_ptr_array_set_size (domains, 0); + + inet_pton (AF_INET6, "0123:4567:89ab:cdee::", &addr); + nm_utils_get_reverse_dns_domains_ip6 (&addr, 0, domains); + g_assert_cmpuint (domains->len, ==, 0); + + g_ptr_array_unref (domains); +} + /*****************************************************************************/ NMTST_DEFINE (); @@ -1397,6 +1515,9 @@ main (int argc, char **argv) g_test_add_func ("/general/nm_match_spec_match_config", test_nm_match_spec_match_config); g_test_add_func ("/general/duplicate_decl_specifier", test_duplicate_decl_specifier); + g_test_add_func ("/general/reverse_dns/ip4", test_reverse_dns_ip4); + g_test_add_func ("/general/reverse_dns/ip6", test_reverse_dns_ip6); + return g_test_run (); } diff --git a/src/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c index a1cd0c32..cb8474aa 100644 --- a/src/vpn-manager/nm-vpn-connection.c +++ b/src/vpn-manager/nm-vpn-connection.c @@ -44,6 +44,7 @@ #include "nm-config.h" #include "nm-vpn-plugin-info.h" #include "nm-vpn-manager.h" +#include "nm-dns-manager.h" #include "nmdbus-vpn-connection.h" @@ -192,14 +193,14 @@ __LOG_create_prefix (char *buf, NMVpnConnection *self) "%s%s" /*con-uuid*/ "%s%s%s%s" /*con-id*/ ",%d" /*ifindex*/ - "%s%s%s%s" /*iface*/ + "%s%s%s" /*iface*/ "]", _NMLOG_PREFIX_NAME, self, con ? "," : "--", con ? (nm_connection_get_uuid (con) ?: "??") : "", con ? "," : "", NM_PRINT_FMT_QUOTED (id, "\"", id, "\"", con ? "??" : ""), priv->ip_ifindex, - priv->ip_iface ? ":" : "", NM_PRINT_FMT_QUOTED (priv->ip_iface, "(", priv->ip_iface, ")", "") + NM_PRINT_FMT_QUOTED (priv->ip_iface, ":(", priv->ip_iface, ")", "") ); return buf; @@ -909,7 +910,7 @@ print_vpn_config (NMVpnConnection *self) nm_utils_inet6_ntop (priv->ip6_external_gw, NULL)); } - _LOGI ("Data: Tunnel Device: %s", priv->ip_iface ? priv->ip_iface : "(none)"); + _LOGI ("Data: Tunnel Device: %s%s%s", NM_PRINT_FMT_QUOTE_STRING (priv->ip_iface)); if (priv->ip4_config) { _LOGI ("Data: IPv4 configuration:"); @@ -1022,12 +1023,11 @@ apply_parent_device_config (NMVpnConnection *self) ifindex = nm_device_get_ip_ifindex (parent_dev); if (priv->ip4_config) { vpn4_parent_config = nm_ip4_config_new (ifindex); - nm_ip4_config_merge (vpn4_parent_config, priv->ip4_config, NM_IP_CONFIG_MERGE_DEFAULT); - nm_ip4_config_unset_gateway (vpn4_parent_config); + nm_ip4_config_merge (vpn4_parent_config, priv->ip4_config, NM_IP_CONFIG_MERGE_NO_DNS); } if (priv->ip6_config) { vpn6_parent_config = nm_ip6_config_new (ifindex); - nm_ip6_config_merge (vpn6_parent_config, priv->ip6_config, NM_IP_CONFIG_MERGE_DEFAULT); + nm_ip6_config_merge (vpn6_parent_config, priv->ip6_config, NM_IP_CONFIG_MERGE_NO_DNS); nm_ip6_config_set_gateway (vpn6_parent_config, NULL); } } @@ -1079,7 +1079,8 @@ nm_vpn_connection_apply_config (NMVpnConnection *self) nm_default_route_manager_ip6_update_default_route (priv->default_route_manager, self); _LOGI ("VPN connection: (IP Config Get) complete"); - _set_vpn_state (self, STATE_PRE_UP, NM_VPN_CONNECTION_STATE_REASON_NONE, FALSE); + if (priv->vpn_state < STATE_PRE_UP) + _set_vpn_state (self, STATE_PRE_UP, NM_VPN_CONNECTION_STATE_REASON_NONE, FALSE); return TRUE; } @@ -1218,6 +1219,8 @@ process_generic_config (NMVpnConnection *self, GVariant *dict) } g_clear_pointer (&priv->ip_iface, g_free); + priv->ip_ifindex = 0; + if (g_variant_lookup (dict, NM_VPN_PLUGIN_CONFIG_TUNDEV, "&s", &str)) { /* Backwards compat with NM-openswan */ if (g_strcmp0 (str, "_none_") != 0) @@ -1228,7 +1231,13 @@ process_generic_config (NMVpnConnection *self, GVariant *dict) /* Grab the interface index for address/routing operations */ priv->ip_ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, priv->ip_iface); if (priv->ip_ifindex <= 0) { + nm_platform_process_events (NM_PLATFORM_GET); + priv->ip_ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, priv->ip_iface); + } + if (priv->ip_ifindex <= 0) { _LOGE ("failed to look up VPN interface index for \"%s\"", priv->ip_iface); + g_clear_pointer (&priv->ip_iface, g_free); + priv->ip_ifindex = 0; nm_vpn_connection_config_maybe_complete (self, FALSE); return FALSE; } @@ -1329,7 +1338,6 @@ nm_vpn_connection_ip4_config_get (NMVpnConnection *self, GVariant *dict) const char *str; GVariant *v; gboolean b; - int ifindex; g_return_if_fail (dict && g_variant_is_of_type (dict, G_VARIANT_TYPE_VARDICT)); @@ -1357,13 +1365,8 @@ nm_vpn_connection_ip4_config_get (NMVpnConnection *self, GVariant *dict) priv->has_ip6 = FALSE; } - if (priv->ip_ifindex > 0) { - ifindex = priv->ip_ifindex; - } else { - NMDevice *parent_dev = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (self)); - ifindex = nm_device_get_ip_ifindex (parent_dev); - } - config = nm_ip4_config_new (ifindex); + config = nm_ip4_config_new (nm_vpn_connection_get_ip_ifindex (self, TRUE)); + nm_ip4_config_set_dns_priority (config, NM_DNS_PRIORITY_DEFAULT_VPN); memset (&address, 0, sizeof (address)); address.plen = 24; @@ -1464,10 +1467,15 @@ nm_vpn_connection_ip4_config_get (NMVpnConnection *self, GVariant *dict) nm_connection_get_setting_ip4_config (_get_applied_connection (self)), route_metric); - nm_exported_object_clear_and_unexport (&priv->ip4_config); - priv->ip4_config = config; - nm_exported_object_export (NM_EXPORTED_OBJECT (config)); - g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_IP4_CONFIG); + if (priv->ip4_config) { + nm_ip4_config_replace (priv->ip4_config, config, NULL); + g_object_unref (config); + } else { + priv->ip4_config = config; + nm_exported_object_export (NM_EXPORTED_OBJECT (config)); + g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_IP4_CONFIG); + } + nm_vpn_connection_config_maybe_complete (self, TRUE); } @@ -1497,6 +1505,7 @@ nm_vpn_connection_ip6_config_get (NMVpnConnection *self, GVariant *dict) } config = nm_ip6_config_new (priv->ip_ifindex); + nm_ip6_config_set_dns_priority (config, NM_DNS_PRIORITY_DEFAULT_VPN); memset (&address, 0, sizeof (address)); address.plen = 128; @@ -1600,10 +1609,15 @@ next: nm_connection_get_setting_ip6_config (_get_applied_connection (self)), route_metric); - nm_exported_object_clear_and_unexport (&priv->ip6_config); - priv->ip6_config = config; - nm_exported_object_export (NM_EXPORTED_OBJECT (config)); - g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_IP6_CONFIG); + if (priv->ip6_config) { + nm_ip6_config_replace (priv->ip6_config, config, NULL); + g_object_unref (config); + } else { + priv->ip6_config = config; + nm_exported_object_export (NM_EXPORTED_OBJECT (config)); + g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_IP6_CONFIG); + } + nm_vpn_connection_config_maybe_complete (self, TRUE); } @@ -1916,9 +1930,6 @@ _daemon_exec_timeout (gpointer data) _LOGW ("Timed out waiting for the service to start"); priv->start_timeout = 0; nm_vpn_connection_disconnect (self, NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT, FALSE); - - g_object_unref (self); - return G_SOURCE_REMOVE; } @@ -2085,20 +2096,67 @@ nm_vpn_connection_get_ip6_config (NMVpnConnection *self) return NM_VPN_CONNECTION_GET_PRIVATE (self)->ip6_config; } +static int +_get_ip_iface_for_device (NMVpnConnection *self, const char **out_iface) +{ + NMDevice *parent_dev; + int ifindex; + const char *iface; + + nm_assert (NM_IS_VPN_CONNECTION (self)); + + /* the ifindex and the ifname in this case should come together. + * They either must be both set, or none. */ + + parent_dev = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (self)); + if (!parent_dev) + goto none; + ifindex = nm_device_get_ip_ifindex (parent_dev); + if (ifindex <= 0) + goto none; + iface = nm_device_get_ip_iface (parent_dev); + if (!iface) + goto none; + + NM_SET_OUT (out_iface, iface); + return ifindex; +none: + NM_SET_OUT (out_iface, NULL); + return 0; +} + const char * -nm_vpn_connection_get_ip_iface (NMVpnConnection *self) +nm_vpn_connection_get_ip_iface (NMVpnConnection *self, gboolean fallback_device) { + NMVpnConnectionPrivate *priv; + const char *iface; + g_return_val_if_fail (NM_IS_VPN_CONNECTION (self), NULL); - return NM_VPN_CONNECTION_GET_PRIVATE (self)->ip_iface; + priv = NM_VPN_CONNECTION_GET_PRIVATE (self); + + if (priv->ip_iface || !fallback_device) + return priv->ip_iface; + + _get_ip_iface_for_device (self, &iface); + return iface; } int -nm_vpn_connection_get_ip_ifindex (NMVpnConnection *self) +nm_vpn_connection_get_ip_ifindex (NMVpnConnection *self, gboolean fallback_device) { - g_return_val_if_fail (NM_IS_VPN_CONNECTION (self), -1); + NMVpnConnectionPrivate *priv; + + g_return_val_if_fail (NM_IS_VPN_CONNECTION (self), 0); + + priv = NM_VPN_CONNECTION_GET_PRIVATE (self); + + if (priv->ip_ifindex > 0) + return priv->ip_ifindex; + if (!fallback_device) + return 0; - return NM_VPN_CONNECTION_GET_PRIVATE (self)->ip_ifindex; + return _get_ip_iface_for_device (self, NULL); } guint32 diff --git a/src/vpn-manager/nm-vpn-connection.h b/src/vpn-manager/nm-vpn-connection.h index 19b0eb3f..68374329 100644 --- a/src/vpn-manager/nm-vpn-connection.h +++ b/src/vpn-manager/nm-vpn-connection.h @@ -91,8 +91,8 @@ void nm_vpn_connection_disconnect (NMVpnConnection *self, NMIP4Config * nm_vpn_connection_get_ip4_config (NMVpnConnection *self); NMIP6Config * nm_vpn_connection_get_ip6_config (NMVpnConnection *self); -const char * nm_vpn_connection_get_ip_iface (NMVpnConnection *self); -int nm_vpn_connection_get_ip_ifindex (NMVpnConnection *self); +const char * nm_vpn_connection_get_ip_iface (NMVpnConnection *self, gboolean fallback_device); +int nm_vpn_connection_get_ip_ifindex (NMVpnConnection *self, gboolean fallback_device); guint32 nm_vpn_connection_get_ip4_internal_gateway (NMVpnConnection *self); struct in6_addr * nm_vpn_connection_get_ip6_internal_gateway (NMVpnConnection *self); |