diff options
| author | Michael Biebl <biebl@debian.org> | 2016-08-26 02:18:32 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2016-08-26 02:18:32 +0200 |
| commit | 7514efc2f38c9ace4557d4e69d68e7d380389030 (patch) | |
| tree | 7fb00fda86cfcc2ca377f191633a7cfdbfea7ca3 /src/devices | |
| parent | d6201f5d8daada3d64a0a3e0038e14eebec683ce (diff) | |
Imported Upstream version 1.4.0 upstream/1.4.0
Diffstat (limited to 'src/devices')
79 files changed, 4131 insertions, 1718 deletions
diff --git a/src/devices/Makefile.in b/src/devices/Makefile.in index d6848e53..4791015d 100644 --- a/src/devices/Makefile.in +++ b/src/devices/Makefile.in @@ -89,8 +89,9 @@ build_triplet = @build@ host_triplet = @host@ subdir = src/devices ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \ - $(top_srcdir)/m4/compiler_warnings.m4 \ +am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ + $(top_srcdir)/m4/ax_lib_readline.m4 \ + $(top_srcdir)/m4/compiler_options.m4 \ $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ @@ -225,6 +226,7 @@ DHCLIENT_PATH = @DHCLIENT_PATH@ DHCPCD_PATH = @DHCPCD_PATH@ DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@ DLLTOOL = @DLLTOOL@ +DL_LIBS = @DL_LIBS@ DNSMASQ_PATH = @DNSMASQ_PATH@ DNSSEC_TRIGGER_SCRIPT = @DNSSEC_TRIGGER_SCRIPT@ DSYMUTIL = @DSYMUTIL@ @@ -281,13 +283,14 @@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ IPTABLES_PATH = @IPTABLES_PATH@ +JANSSON_CFLAGS = @JANSSON_CFLAGS@ +JANSSON_LIBS = @JANSSON_LIBS@ KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBAUDIT_CFLAGS = @LIBAUDIT_CFLAGS@ LIBAUDIT_LIBS = @LIBAUDIT_LIBS@ -LIBDL = @LIBDL@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ @@ -299,6 +302,8 @@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@ LIBSOUP_LIBS = @LIBSOUP_LIBS@ +LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ +LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTEAMDCTL_CFLAGS = @LIBTEAMDCTL_CFLAGS@ LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@ LIBTOOL = @LIBTOOL@ @@ -359,6 +364,8 @@ QT_CFLAGS = @QT_CFLAGS@ QT_LIBS = @QT_LIBS@ RANLIB = @RANLIB@ READLINE_LIBS = @READLINE_LIBS@ +SANITIZERS = @SANITIZERS@ +SANITIZER_ENV = @SANITIZER_ENV@ SED = @SED@ SELINUX_CFLAGS = @SELINUX_CFLAGS@ SELINUX_LIBS = @SELINUX_LIBS@ @@ -394,6 +401,7 @@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_RANLIB = @ac_ct_RANLIB@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ diff --git a/src/devices/adsl/Makefile.am b/src/devices/adsl/Makefile.am index 5f981740..9075021c 100644 --- a/src/devices/adsl/Makefile.am +++ b/src/devices/adsl/Makefile.am @@ -40,6 +40,7 @@ if ENABLE_TESTS check-local: $(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-device-plugin-adsl.so $(SYMBOL_VIS_FILE) + LD_BIND_NOW=1 LD_PRELOAD=$(builddir)/.libs/libnm-device-plugin-adsl.so $(top_builddir)/src/NetworkManager --version >/dev/null endif diff --git a/src/devices/adsl/Makefile.in b/src/devices/adsl/Makefile.in index b6805537..f3fbad4c 100644 --- a/src/devices/adsl/Makefile.in +++ b/src/devices/adsl/Makefile.in @@ -90,8 +90,9 @@ build_triplet = @build@ host_triplet = @host@ subdir = src/devices/adsl ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \ - $(top_srcdir)/m4/compiler_warnings.m4 \ +am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ + $(top_srcdir)/m4/ax_lib_readline.m4 \ + $(top_srcdir)/m4/compiler_options.m4 \ $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ @@ -252,6 +253,7 @@ DHCLIENT_PATH = @DHCLIENT_PATH@ DHCPCD_PATH = @DHCPCD_PATH@ DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@ DLLTOOL = @DLLTOOL@ +DL_LIBS = @DL_LIBS@ DNSMASQ_PATH = @DNSMASQ_PATH@ DNSSEC_TRIGGER_SCRIPT = @DNSSEC_TRIGGER_SCRIPT@ DSYMUTIL = @DSYMUTIL@ @@ -308,13 +310,14 @@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ IPTABLES_PATH = @IPTABLES_PATH@ +JANSSON_CFLAGS = @JANSSON_CFLAGS@ +JANSSON_LIBS = @JANSSON_LIBS@ KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBAUDIT_CFLAGS = @LIBAUDIT_CFLAGS@ LIBAUDIT_LIBS = @LIBAUDIT_LIBS@ -LIBDL = @LIBDL@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ @@ -326,6 +329,8 @@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@ LIBSOUP_LIBS = @LIBSOUP_LIBS@ +LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ +LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTEAMDCTL_CFLAGS = @LIBTEAMDCTL_CFLAGS@ LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@ LIBTOOL = @LIBTOOL@ @@ -386,6 +391,8 @@ QT_CFLAGS = @QT_CFLAGS@ QT_LIBS = @QT_LIBS@ RANLIB = @RANLIB@ READLINE_LIBS = @READLINE_LIBS@ +SANITIZERS = @SANITIZERS@ +SANITIZER_ENV = @SANITIZER_ENV@ SED = @SED@ SELINUX_CFLAGS = @SELINUX_CFLAGS@ SELINUX_LIBS = @SELINUX_LIBS@ @@ -421,6 +428,7 @@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_RANLIB = @ac_ct_RANLIB@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ @@ -838,6 +846,7 @@ include $(GLIB_MAKEFILE) @ENABLE_TESTS_TRUE@check-local: @ENABLE_TESTS_TRUE@ $(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-device-plugin-adsl.so $(SYMBOL_VIS_FILE) +@ENABLE_TESTS_TRUE@ LD_BIND_NOW=1 LD_PRELOAD=$(builddir)/.libs/libnm-device-plugin-adsl.so $(top_builddir)/src/NetworkManager --version >/dev/null # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/src/devices/adsl/nm-atm-manager.h b/src/devices/adsl/nm-atm-manager.h index fe0bc14c..bcbc6c77 100644 --- a/src/devices/adsl/nm-atm-manager.h +++ b/src/devices/adsl/nm-atm-manager.h @@ -22,10 +22,6 @@ #ifndef __NETWORKMANAGER_ATM_MANAGER_H__ #define __NETWORKMANAGER_ATM_MANAGER_H__ -#include "nm-default.h" - -G_BEGIN_DECLS - #define NM_TYPE_ATM_MANAGER (nm_atm_manager_get_type ()) #define NM_ATM_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_ATM_MANAGER, NMAtmManager)) diff --git a/src/devices/adsl/nm-device-adsl.h b/src/devices/adsl/nm-device-adsl.h index efcdaf69..cfde2b35 100644 --- a/src/devices/adsl/nm-device-adsl.h +++ b/src/devices/adsl/nm-device-adsl.h @@ -23,11 +23,8 @@ #define __NETWORKMANAGER_DEVICE_ADSL_H__ // Parent class -#include "nm-default.h" #include "nm-device.h" -G_BEGIN_DECLS - #define NM_TYPE_DEVICE_ADSL (nm_device_adsl_get_type ()) #define NM_DEVICE_ADSL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_ADSL, NMDeviceAdsl)) #define NM_DEVICE_ADSL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_ADSL, NMDeviceAdslClass)) @@ -52,6 +49,4 @@ NMDevice *nm_device_adsl_new (const char *udi, const char *driver, int atm_index); -G_END_DECLS - -#endif /* NM_DEVICE_ADSL_H */ +#endif /* NM_DEVICE_ADSL_H */ diff --git a/src/devices/bluetooth/Makefile.am b/src/devices/bluetooth/Makefile.am index 2ff9a572..8454702e 100644 --- a/src/devices/bluetooth/Makefile.am +++ b/src/devices/bluetooth/Makefile.am @@ -76,6 +76,7 @@ if ENABLE_TESTS check-local: $(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-device-plugin-bluetooth.so $(SYMBOL_VIS_FILE) + LD_BIND_NOW=1 LD_PRELOAD=$(builddir)/.libs/libnm-device-plugin-bluetooth.so $(top_builddir)/src/NetworkManager --version >/dev/null endif diff --git a/src/devices/bluetooth/Makefile.in b/src/devices/bluetooth/Makefile.in index d2b0b865..c010f4c7 100644 --- a/src/devices/bluetooth/Makefile.in +++ b/src/devices/bluetooth/Makefile.in @@ -96,8 +96,9 @@ host_triplet = @host@ @WITH_BLUEZ5_DUN_TRUE@am__append_3 = $(BLUEZ5_LIBS) subdir = src/devices/bluetooth ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \ - $(top_srcdir)/m4/compiler_warnings.m4 \ +am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ + $(top_srcdir)/m4/ax_lib_readline.m4 \ + $(top_srcdir)/m4/compiler_options.m4 \ $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ @@ -273,6 +274,7 @@ DHCLIENT_PATH = @DHCLIENT_PATH@ DHCPCD_PATH = @DHCPCD_PATH@ DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@ DLLTOOL = @DLLTOOL@ +DL_LIBS = @DL_LIBS@ DNSMASQ_PATH = @DNSMASQ_PATH@ DNSSEC_TRIGGER_SCRIPT = @DNSSEC_TRIGGER_SCRIPT@ DSYMUTIL = @DSYMUTIL@ @@ -329,13 +331,14 @@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ IPTABLES_PATH = @IPTABLES_PATH@ +JANSSON_CFLAGS = @JANSSON_CFLAGS@ +JANSSON_LIBS = @JANSSON_LIBS@ KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBAUDIT_CFLAGS = @LIBAUDIT_CFLAGS@ LIBAUDIT_LIBS = @LIBAUDIT_LIBS@ -LIBDL = @LIBDL@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ @@ -347,6 +350,8 @@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@ LIBSOUP_LIBS = @LIBSOUP_LIBS@ +LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ +LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTEAMDCTL_CFLAGS = @LIBTEAMDCTL_CFLAGS@ LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@ LIBTOOL = @LIBTOOL@ @@ -407,6 +412,8 @@ QT_CFLAGS = @QT_CFLAGS@ QT_LIBS = @QT_LIBS@ RANLIB = @RANLIB@ READLINE_LIBS = @READLINE_LIBS@ +SANITIZERS = @SANITIZERS@ +SANITIZER_ENV = @SANITIZER_ENV@ SED = @SED@ SELINUX_CFLAGS = @SELINUX_CFLAGS@ SELINUX_LIBS = @SELINUX_LIBS@ @@ -442,6 +449,7 @@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_RANLIB = @ac_ct_RANLIB@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ @@ -872,6 +880,7 @@ include $(GLIB_MAKEFILE) @ENABLE_TESTS_TRUE@check-local: @ENABLE_TESTS_TRUE@ $(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-device-plugin-bluetooth.so $(SYMBOL_VIS_FILE) +@ENABLE_TESTS_TRUE@ LD_BIND_NOW=1 LD_PRELOAD=$(builddir)/.libs/libnm-device-plugin-bluetooth.so $(top_builddir)/src/NetworkManager --version >/dev/null # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/src/devices/bluetooth/nm-bluez-device.c b/src/devices/bluetooth/nm-bluez-device.c index dcfa5eec..3463da6b 100644 --- a/src/devices/bluetooth/nm-bluez-device.c +++ b/src/devices/bluetooth/nm-bluez-device.c @@ -28,6 +28,7 @@ #include "nm-bt-error.h" #include "nm-bluez-common.h" #include "nm-bluez-device.h" +#include "nm-settings.h" #include "nm-settings-connection.h" #include "NetworkManagerUtils.h" @@ -67,7 +68,7 @@ typedef struct { NMBluez5DunContext *b5_dun_context; #endif - NMConnectionProvider *provider; + NMSettings *settings; GSList *connections; NMConnection *pan_connection; @@ -96,7 +97,7 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; -static void cp_connection_added (NMConnectionProvider *provider, +static void cp_connection_added (NMSettings *settings, NMConnection *connection, NMBluezDevice *self); static gboolean connection_compatible (NMBluezDevice *self, NMConnection *connection); @@ -233,9 +234,9 @@ pan_connection_check_create (NMBluezDevice *self) /* Adding a new connection raises a signal which eventually calls check_emit_usable (again) * which then already finds the suitable connection in priv->connections. This is confusing, * so block the signal. check_emit_usable will succeed after this function call returns. */ - g_signal_handlers_block_by_func (priv->provider, cp_connection_added, self); - added = nm_connection_provider_add_connection (priv->provider, connection, FALSE, &error); - g_signal_handlers_unblock_by_func (priv->provider, cp_connection_added, self); + g_signal_handlers_block_by_func (priv->settings, cp_connection_added, self); + added = NM_CONNECTION (nm_settings_add_connection (priv->settings, connection, FALSE, &error)); + g_signal_handlers_unblock_by_func (priv->settings, cp_connection_added, self); if (added) { g_assert (!g_slist_find (priv->connections, added)); @@ -367,7 +368,7 @@ _internal_track_connection (NMBluezDevice *self, NMConnection *connection, gbool } static void -cp_connection_added (NMConnectionProvider *provider, +cp_connection_added (NMSettings *settings, NMConnection *connection, NMBluezDevice *self) { @@ -378,7 +379,7 @@ cp_connection_added (NMConnectionProvider *provider, } static void -cp_connection_removed (NMConnectionProvider *provider, +cp_connection_removed (NMSettings *settings, NMConnection *connection, NMBluezDevice *self) { @@ -387,8 +388,9 @@ cp_connection_removed (NMConnectionProvider *provider, } static void -cp_connection_updated (NMConnectionProvider *provider, +cp_connection_updated (NMSettings *settings, NMConnection *connection, + gboolean by_user, NMBluezDevice *self) { if (_internal_track_connection (self, connection, @@ -400,12 +402,13 @@ static void load_connections (NMBluezDevice *self) { NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - const GSList *connections, *iter; + NMSettingsConnection *const*connections; + guint i; gboolean changed = FALSE; - connections = nm_connection_provider_get_connections (priv->provider); - for (iter = connections; iter; iter = g_slist_next (iter)) { - NMConnection *connection = iter->data; + connections = nm_settings_get_connections (priv->settings, NULL); + for (i = 0; connections[i]; i++) { + NMConnection *connection = (NMConnection *) connections[i]; if (connection_compatible (self, connection)) changed |= _internal_track_connection (self, connection, TRUE); @@ -1029,7 +1032,7 @@ on_bus_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) NMBluezDevice * nm_bluez_device_new (const char *path, const char *adapter_address, - NMConnectionProvider *provider, + NMSettings *settings, int bluez_version) { NMBluezDevice *self; @@ -1037,7 +1040,7 @@ nm_bluez_device_new (const char *path, const char *interface_name = NULL; g_return_val_if_fail (path != NULL, NULL); - g_return_val_if_fail (NM_IS_CONNECTION_PROVIDER (provider), NULL); + g_return_val_if_fail (NM_IS_SETTINGS (settings), NULL); g_return_val_if_fail (bluez_version == 4 || bluez_version == 5, NULL); self = (NMBluezDevice *) g_object_new (NM_TYPE_BLUEZ_DEVICE, @@ -1051,14 +1054,14 @@ nm_bluez_device_new (const char *path, priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); priv->bluez_version = bluez_version; - priv->provider = g_object_ref (provider); + priv->settings = g_object_ref (settings); g_return_val_if_fail (bluez_version == 5 || (bluez_version == 4 && adapter_address), NULL); 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->settings, NM_SETTINGS_SIGNAL_CONNECTION_ADDED, G_CALLBACK (cp_connection_added), self); + g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_REMOVED, G_CALLBACK (cp_connection_removed), self); + g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_UPDATED, G_CALLBACK (cp_connection_updated), self); g_bus_get (G_BUS_TYPE_SYSTEM, NULL, @@ -1116,10 +1119,10 @@ dispose (GObject *object) } #endif - if (priv->provider) { - g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_added, self); - g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_removed, self); - g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_updated, self); + if (priv->settings) { + g_signal_handlers_disconnect_by_func (priv->settings, cp_connection_added, self); + g_signal_handlers_disconnect_by_func (priv->settings, cp_connection_removed, self); + g_signal_handlers_disconnect_by_func (priv->settings, cp_connection_updated, self); } g_slist_free_full (priv->connections, g_object_unref); @@ -1137,7 +1140,7 @@ dispose (GObject *object) g_object_unref (to_delete); } - g_clear_object (&priv->provider); + g_clear_object (&priv->settings); } static void diff --git a/src/devices/bluetooth/nm-bluez-device.h b/src/devices/bluetooth/nm-bluez-device.h index c9560540..66a349e0 100644 --- a/src/devices/bluetooth/nm-bluez-device.h +++ b/src/devices/bluetooth/nm-bluez-device.h @@ -22,7 +22,6 @@ #define __NETWORKMANAGER_BLUEZ_DEVICE_H__ #include "nm-connection.h" -#include "nm-connection-provider.h" #define NM_TYPE_BLUEZ_DEVICE (nm_bluez_device_get_type ()) #define NM_BLUEZ_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BLUEZ_DEVICE, NMBluezDevice)) @@ -59,7 +58,7 @@ GType nm_bluez_device_get_type (void); NMBluezDevice *nm_bluez_device_new (const char *path, const char *adapter_address, - NMConnectionProvider *provider, + NMSettings *settings, int bluez_version); const char *nm_bluez_device_get_path (NMBluezDevice *self); diff --git a/src/devices/bluetooth/nm-bluez-manager.c b/src/devices/bluetooth/nm-bluez-manager.c index 766ecc0a..0d2e302c 100644 --- a/src/devices/bluetooth/nm-bluez-manager.c +++ b/src/devices/bluetooth/nm-bluez-manager.c @@ -20,19 +20,20 @@ #include "nm-default.h" +#include "nm-bluez-manager.h" + #include <signal.h> #include <string.h> #include <stdlib.h> #include <gmodule.h> -#include "nm-bluez-manager.h" #include "nm-device-factory.h" #include "nm-setting-bluetooth.h" +#include "nm-settings.h" #include "nm-bluez4-manager.h" #include "nm-bluez5-manager.h" #include "nm-bluez-device.h" #include "nm-bluez-common.h" -#include "nm-connection-provider.h" #include "nm-device-bt.h" #include "nm-core-internal.h" #include "nm-platform.h" @@ -51,7 +52,7 @@ typedef struct { int bluez_version; - NMConnectionProvider *provider; + NMSettings *settings; NMBluez4Manager *manager4; NMBluez5Manager *manager5; @@ -190,7 +191,7 @@ setup_bluez4 (NMBluezManager *self) g_return_if_fail (!priv->manager4 && !priv->manager5 && !priv->bluez_version); setup_version_number (self, 4); - priv->manager4 = manager = nm_bluez4_manager_new (priv->provider); + priv->manager4 = manager = nm_bluez4_manager_new (priv->settings); g_signal_connect (manager, NM_BLUEZ_MANAGER_BDADDR_ADDED, @@ -209,7 +210,7 @@ setup_bluez5 (NMBluezManager *self) g_return_if_fail (!priv->manager4 && !priv->manager5 && !priv->bluez_version); setup_version_number (self, 5); - priv->manager5 = manager = nm_bluez5_manager_new (priv->provider); + priv->manager5 = manager = nm_bluez5_manager_new (priv->settings); g_signal_connect (manager, NM_BLUEZ_MANAGER_BDADDR_ADDED, @@ -407,9 +408,9 @@ dispose (GObject *object) priv->bluez_version = 0; - g_clear_object (&priv->provider); - G_OBJECT_CLASS (nm_bluez_manager_parent_class)->dispose (object); + + g_clear_object (&priv->settings); } static void @@ -417,7 +418,7 @@ nm_bluez_manager_init (NMBluezManager *self) { NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - priv->provider = g_object_ref (nm_connection_provider_get ()); + priv->settings = g_object_ref (NM_SETTINGS_GET); } static NMDevice * diff --git a/src/devices/bluetooth/nm-bluez-manager.h b/src/devices/bluetooth/nm-bluez-manager.h index 1f5597d8..d23b33a7 100644 --- a/src/devices/bluetooth/nm-bluez-manager.h +++ b/src/devices/bluetooth/nm-bluez-manager.h @@ -22,10 +22,6 @@ #ifndef __NETWORKMANAGER_BLUEZ_MANAGER_H__ #define __NETWORKMANAGER_BLUEZ_MANAGER_H__ -#include "nm-default.h" - -G_BEGIN_DECLS - #define NM_TYPE_BLUEZ_MANAGER (nm_bluez_manager_get_type ()) #define NM_BLUEZ_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BLUEZ_MANAGER, NMBluezManager)) diff --git a/src/devices/bluetooth/nm-bluez4-adapter.c b/src/devices/bluetooth/nm-bluez4-adapter.c index 9d8fd210..2ef071a8 100644 --- a/src/devices/bluetooth/nm-bluez4-adapter.c +++ b/src/devices/bluetooth/nm-bluez4-adapter.c @@ -20,13 +20,15 @@ #include "nm-default.h" +#include "nm-bluez4-adapter.h" + #include <string.h> #include "nm-dbus-interface.h" -#include "nm-bluez4-adapter.h" #include "nm-bluez-device.h" #include "nm-bluez-common.h" #include "nm-core-internal.h" +#include "nm-settings.h" G_DEFINE_TYPE (NMBluez4Adapter, nm_bluez4_adapter, G_TYPE_OBJECT) @@ -41,7 +43,7 @@ typedef struct { GHashTable *devices; /* Cached for devices */ - NMConnectionProvider *provider; + NMSettings *settings; } NMBluez4AdapterPrivate; @@ -160,7 +162,7 @@ device_created (GDBusProxy *proxy, const char *path, gpointer user_data) NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); NMBluezDevice *device; - device = nm_bluez_device_new (path, priv->address, priv->provider, 4); + device = nm_bluez_device_new (path, priv->address, priv->settings, 4); g_signal_connect (device, "initialized", G_CALLBACK (device_initialized), self); g_signal_connect (device, "notify::usable", G_CALLBACK (device_usable), self); g_hash_table_insert (priv->devices, (gpointer) nm_bluez_device_get_path (device), device); @@ -234,17 +236,19 @@ query_properties (NMBluez4Adapter *self) /***********************************************************/ NMBluez4Adapter * -nm_bluez4_adapter_new (const char *path, NMConnectionProvider *provider) +nm_bluez4_adapter_new (const char *path, NMSettings *settings) { NMBluez4Adapter *self; NMBluez4AdapterPrivate *priv; + g_return_val_if_fail (NM_IS_SETTINGS (settings), NULL); + self = (NMBluez4Adapter *) g_object_new (NM_TYPE_BLUEZ4_ADAPTER, NM_BLUEZ4_ADAPTER_PATH, path, NULL); priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); - priv->provider = provider; + priv->settings = g_object_ref (settings); priv->proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, @@ -301,6 +305,8 @@ finalize (GObject *object) g_object_unref (priv->proxy); G_OBJECT_CLASS (nm_bluez4_adapter_parent_class)->finalize (object); + + g_object_unref (priv->settings); } static void diff --git a/src/devices/bluetooth/nm-bluez4-adapter.h b/src/devices/bluetooth/nm-bluez4-adapter.h index a8a2bfb4..ee61112f 100644 --- a/src/devices/bluetooth/nm-bluez4-adapter.h +++ b/src/devices/bluetooth/nm-bluez4-adapter.h @@ -21,10 +21,7 @@ #ifndef __NETWORKMANAGER_BLUEZ4_ADAPTER_H__ #define __NETWORKMANAGER_BLUEZ4_ADAPTER_H__ - -#include "nm-default.h" #include "nm-bluez-device.h" -#include "nm-connection-provider.h" #define NM_TYPE_BLUEZ4_ADAPTER (nm_bluez4_adapter_get_type ()) #define NM_BLUEZ4_ADAPTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BLUEZ4_ADAPTER, NMBluez4Adapter)) @@ -54,7 +51,7 @@ typedef struct { GType nm_bluez4_adapter_get_type (void); NMBluez4Adapter *nm_bluez4_adapter_new (const char *path, - NMConnectionProvider *provider); + NMSettings *settings); const char *nm_bluez4_adapter_get_path (NMBluez4Adapter *self); diff --git a/src/devices/bluetooth/nm-bluez4-manager.c b/src/devices/bluetooth/nm-bluez4-manager.c index 146612a8..36bc30e5 100644 --- a/src/devices/bluetooth/nm-bluez4-manager.c +++ b/src/devices/bluetooth/nm-bluez4-manager.c @@ -21,20 +21,22 @@ #include "nm-default.h" +#include "nm-bluez4-manager.h" + #include <signal.h> #include <string.h> #include <stdlib.h> -#include "nm-bluez-manager.h" -#include "nm-bluez4-manager.h" #include "nm-bluez4-adapter.h" +#include "nm-bluez-manager.h" #include "nm-bluez-common.h" #include "nm-core-internal.h" +#include "nm-settings.h" typedef struct { gulong name_owner_changed_id; - NMConnectionProvider *provider; + NMSettings *settings; GDBusProxy *proxy; @@ -155,7 +157,7 @@ default_adapter_changed (GDBusProxy *proxy, const char *path, NMBluez4Manager *s /* Add the new default adapter */ if (path) { - priv->adapter = nm_bluez4_adapter_new (path, priv->provider); + priv->adapter = nm_bluez4_adapter_new (path, priv->settings); g_signal_connect (priv->adapter, "initialized", G_CALLBACK (adapter_initialized), self); } } @@ -223,12 +225,14 @@ name_owner_changed_cb (GObject *object, /****************************************************************/ NMBluez4Manager * -nm_bluez4_manager_new (NMConnectionProvider *provider) +nm_bluez4_manager_new (NMSettings *settings) { NMBluez4Manager *instance; + g_return_val_if_fail (NM_IS_SETTINGS (settings), NULL); + instance = g_object_new (NM_TYPE_BLUEZ4_MANAGER, NULL); - NM_BLUEZ4_MANAGER_GET_PRIVATE (instance)->provider = provider; + NM_BLUEZ4_MANAGER_GET_PRIVATE (instance)->settings = g_object_ref (settings); return instance; } @@ -264,6 +268,8 @@ dispose (GObject *object) g_clear_object (&priv->adapter); G_OBJECT_CLASS (nm_bluez4_manager_parent_class)->dispose (object); + + g_clear_object (&priv->settings); } static void diff --git a/src/devices/bluetooth/nm-bluez4-manager.h b/src/devices/bluetooth/nm-bluez4-manager.h index f6bf7658..8afe6924 100644 --- a/src/devices/bluetooth/nm-bluez4-manager.h +++ b/src/devices/bluetooth/nm-bluez4-manager.h @@ -1,4 +1,3 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ /* NetworkManager -- Network link manager * * This program is free software; you can redistribute it and/or modify @@ -22,11 +21,6 @@ #ifndef __NETWORKMANAGER_BLUEZ4_MANAGER_H__ #define __NETWORKMANAGER_BLUEZ4_MANAGER_H__ -#include "nm-default.h" -#include "nm-connection-provider.h" - -G_BEGIN_DECLS - #define NM_TYPE_BLUEZ4_MANAGER (nm_bluez4_manager_get_type ()) #define NM_BLUEZ4_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BLUEZ4_MANAGER, NMBluez4Manager)) #define NM_BLUEZ4_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_BLUEZ4_MANAGER, NMBluez4ManagerClass)) @@ -51,7 +45,7 @@ typedef struct { GType nm_bluez4_manager_get_type (void); -NMBluez4Manager *nm_bluez4_manager_new (NMConnectionProvider *provider); +NMBluez4Manager *nm_bluez4_manager_new (NMSettings *settings); void nm_bluez4_manager_query_devices (NMBluez4Manager *manager); diff --git a/src/devices/bluetooth/nm-bluez5-dun.h b/src/devices/bluetooth/nm-bluez5-dun.h index c59cbb80..124c1a05 100644 --- a/src/devices/bluetooth/nm-bluez5-dun.h +++ b/src/devices/bluetooth/nm-bluez5-dun.h @@ -21,8 +21,6 @@ #ifndef _NM_BLUEZ5_UTILS_H_ #define _NM_BLUEZ5_UTILS_H_ -#include "nm-default.h" - typedef struct _NMBluez5DunContext NMBluez5DunContext; typedef void (*NMBluez5DunFunc) (NMBluez5DunContext *context, diff --git a/src/devices/bluetooth/nm-bluez5-manager.c b/src/devices/bluetooth/nm-bluez5-manager.c index 66d171bf..a014d0c1 100644 --- a/src/devices/bluetooth/nm-bluez5-manager.c +++ b/src/devices/bluetooth/nm-bluez5-manager.c @@ -22,19 +22,21 @@ #include "nm-default.h" +#include "nm-bluez5-manager.h" + #include <signal.h> #include <string.h> #include <stdlib.h> +#include "nm-core-internal.h" + #include "nm-bluez-manager.h" -#include "nm-bluez5-manager.h" #include "nm-bluez-device.h" #include "nm-bluez-common.h" - -#include "nm-core-internal.h" +#include "nm-settings.h" typedef struct { - NMConnectionProvider *provider; + NMSettings *settings; GDBusProxy *proxy; @@ -140,7 +142,7 @@ device_added (GDBusProxy *proxy, const gchar *path, NMBluez5Manager *self) NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); NMBluezDevice *device; - device = nm_bluez_device_new (path, NULL, priv->provider, 5); + device = nm_bluez_device_new (path, NULL, priv->settings, 5); g_signal_connect (device, "initialized", G_CALLBACK (device_initialized), self); g_signal_connect (device, "notify::usable", G_CALLBACK (device_usable), self); g_hash_table_insert (priv->devices, (gpointer) nm_bluez_device_get_path (device), device); @@ -180,7 +182,7 @@ object_manager_interfaces_removed (GDBusProxy *proxy, const char **ifaces, NMBluez5Manager *self) { - if (_nm_utils_string_in_list (BLUEZ5_DEVICE_INTERFACE, ifaces)) + if (ifaces && g_strv_contains (ifaces, BLUEZ5_DEVICE_INTERFACE)) device_removed (proxy, path, self); } @@ -309,12 +311,14 @@ bluez_cleanup (NMBluez5Manager *self, gboolean do_signal) /****************************************************************/ NMBluez5Manager * -nm_bluez5_manager_new (NMConnectionProvider *provider) +nm_bluez5_manager_new (NMSettings *settings) { NMBluez5Manager *instance = NULL; + g_return_val_if_fail (NM_IS_SETTINGS (settings), NULL); + instance = g_object_new (NM_TYPE_BLUEZ5_MANAGER, NULL); - NM_BLUEZ5_MANAGER_GET_PRIVATE (instance)->provider = provider; + NM_BLUEZ5_MANAGER_GET_PRIVATE (instance)->settings = g_object_ref (settings); return instance; } @@ -347,6 +351,8 @@ finalize (GObject *object) g_hash_table_destroy (priv->devices); G_OBJECT_CLASS (nm_bluez5_manager_parent_class)->finalize (object); + + g_object_unref (priv->settings); } static void diff --git a/src/devices/bluetooth/nm-bluez5-manager.h b/src/devices/bluetooth/nm-bluez5-manager.h index 1c531090..0e309d33 100644 --- a/src/devices/bluetooth/nm-bluez5-manager.h +++ b/src/devices/bluetooth/nm-bluez5-manager.h @@ -22,11 +22,6 @@ #ifndef __NETWORKMANAGER_BLUEZ5_MANAGER_H__ #define __NETWORKMANAGER_BLUEZ5_MANAGER_H__ -#include "nm-default.h" -#include "nm-connection-provider.h" - -G_BEGIN_DECLS - #define NM_TYPE_BLUEZ5_MANAGER (nm_bluez5_manager_get_type ()) #define NM_BLUEZ5_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BLUEZ5_MANAGER, NMBluez5Manager)) #define NM_BLUEZ5_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_BLUEZ5_MANAGER, NMBluez5ManagerClass)) @@ -51,7 +46,7 @@ typedef struct { GType nm_bluez5_manager_get_type (void); -NMBluez5Manager *nm_bluez5_manager_new (NMConnectionProvider *provider); +NMBluez5Manager *nm_bluez5_manager_new (NMSettings *settings); void nm_bluez5_manager_query_devices (NMBluez5Manager *manager); diff --git a/src/devices/bluetooth/nm-device-bt.c b/src/devices/bluetooth/nm-device-bt.c index eef4ed0a..67ae15bc 100644 --- a/src/devices/bluetooth/nm-device-bt.c +++ b/src/devices/bluetooth/nm-device-bt.c @@ -362,6 +362,7 @@ static void ppp_failed (NMModem *modem, NMDeviceStateReason reason, gpointer user_data) { NMDevice *device = NM_DEVICE (user_data); + NMDeviceBt *self = NM_DEVICE_BT (user_data); switch (nm_device_get_state (device)) { case NM_DEVICE_STATE_PREPARE: @@ -375,7 +376,18 @@ ppp_failed (NMModem *modem, NMDeviceStateReason reason, gpointer user_data) case NM_DEVICE_STATE_ACTIVATED: if (nm_device_activate_ip4_state_in_conf (device)) nm_device_activate_schedule_ip4_config_timeout (device); - else { + else if (nm_device_activate_ip6_state_in_conf (device)) + nm_device_activate_schedule_ip6_config_timeout (device); + else if (nm_device_activate_ip4_state_done (device)) { + nm_device_ip_method_failed (device, + AF_INET, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + } else if (nm_device_activate_ip6_state_done (device)) { + nm_device_ip_method_failed (device, + AF_INET6, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + } else { + _LOGW (LOGD_MB, "PPP failure in unexpected state %u", (guint) nm_device_get_state (device)); nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); @@ -502,8 +514,9 @@ modem_ip4_config_result (NMModem *modem, _LOGW (LOGD_MB | LOGD_IP4 | LOGD_BT, "retrieving IP4 configuration failed: %s", error->message); - - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + nm_device_ip_method_failed (device, + AF_INET, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); } else nm_device_activate_schedule_ip4_config_result (device, config); } @@ -989,7 +1002,7 @@ nm_device_bt_new (NMBluezDevice *bt_device, NM_DEVICE_UDI, udi, NM_DEVICE_IFACE, bdaddr, NM_DEVICE_DRIVER, "bluez", - NM_DEVICE_HW_ADDRESS, bdaddr, + NM_DEVICE_PERM_HW_ADDRESS, bdaddr, NM_DEVICE_BT_DEVICE, bt_device, NM_DEVICE_BT_NAME, name, NM_DEVICE_BT_CAPABILITIES, capabilities, diff --git a/src/devices/bluetooth/nm-device-bt.h b/src/devices/bluetooth/nm-device-bt.h index c565745f..c97cca01 100644 --- a/src/devices/bluetooth/nm-device-bt.h +++ b/src/devices/bluetooth/nm-device-bt.h @@ -25,8 +25,6 @@ #include "nm-bluez-device.h" #include "nm-modem.h" -G_BEGIN_DECLS - #define NM_TYPE_DEVICE_BT (nm_device_bt_get_type ()) #define NM_DEVICE_BT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_BT, NMDeviceBt)) #define NM_DEVICE_BT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_BT, NMDeviceBtClass)) @@ -63,6 +61,4 @@ gboolean nm_device_bt_modem_added (NMDeviceBt *device, NMModem *modem, const char *driver); -G_END_DECLS - #endif /* __NETWORKMANAGER_DEVICE_BT_H__ */ diff --git a/src/devices/nm-arping-manager.h b/src/devices/nm-arping-manager.h index 4a4f8d4b..78965a0d 100644 --- a/src/devices/nm-arping-manager.h +++ b/src/devices/nm-arping-manager.h @@ -19,8 +19,6 @@ #include <netinet/in.h> -G_BEGIN_DECLS - #define NM_TYPE_ARPING_MANAGER (nm_arping_manager_get_type ()) #define NM_ARPING_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_ARPING_MANAGER, NMArpingManager)) #define NM_ARPING_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_ARPING_MANAGER, NMArpingManagerClass)) @@ -48,6 +46,4 @@ gboolean nm_arping_manager_check_address (NMArpingManager *self, in_addr_t addre void nm_arping_manager_announce_addresses (NMArpingManager *self); void nm_arping_manager_reset (NMArpingManager *self); -G_END_DECLS - #endif /* __NM_ARPING_MANAGER__ */ diff --git a/src/devices/nm-device-bond.c b/src/devices/nm-device-bond.c index 9c98c8ea..3f17849b 100644 --- a/src/devices/nm-device-bond.c +++ b/src/devices/nm-device-bond.c @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright 2011 - 2012 Red Hat, Inc. + * Copyright 2011 - 2016 Red Hat, Inc. */ #include "nm-default.h" @@ -118,12 +118,15 @@ complete_connection (NMDevice *device, /******************************************************************/ static gboolean -set_bond_attr (NMDevice *device, const char *attr, const char *value) +set_bond_attr (NMDevice *device, NMBondMode mode, const char *attr, const char *value) { NMDeviceBond *self = NM_DEVICE_BOND (device); gboolean ret; int ifindex = nm_device_get_ifindex (device); + if (!_nm_setting_bond_option_supported (attr, mode)) + return FALSE; + ret = nm_platform_sysctl_master_set_option (NM_PLATFORM_GET, ifindex, attr, value); if (!ret) _LOGW (LOGD_HW, "failed to set bonding attribute '%s' to '%s'", attr, value); @@ -134,10 +137,10 @@ set_bond_attr (NMDevice *device, const char *attr, const char *value) static gboolean ignore_if_zero (const char *option, const char *value) { - if (strcmp (option, "arp_interval") && - strcmp (option, "miimon") && - strcmp (option, "downdelay") && - strcmp (option, "updelay")) + if (!NM_IN_STRSET (option, NM_SETTING_BOND_OPTION_ARP_INTERVAL, + NM_SETTING_BOND_OPTION_DOWNDELAY, + NM_SETTING_BOND_OPTION_MIIMON, + NM_SETTING_BOND_OPTION_UPDELAY)) return FALSE; return g_strcmp0 (value, "0") == 0 ? TRUE : FALSE; @@ -173,7 +176,7 @@ update_connection (NMDevice *device, NMConnection *connection) && !ignore_if_zero (*options, value) && !nm_streq0 (value, defvalue)) { /* Replace " " with "," for arp_ip_targets from the kernel */ - if (strcmp (*options, "arp_ip_target") == 0) { + if (strcmp (*options, NM_SETTING_BOND_OPTION_ARP_IP_TARGET) == 0) { for (p = value; *p; p++) { if (*p == ' ') *p = ','; @@ -201,6 +204,7 @@ master_update_slave_connection (NMDevice *self, static void set_arp_targets (NMDevice *device, + NMBondMode mode, const char *value, const char *delim, const char *prefix) @@ -214,7 +218,7 @@ set_arp_targets (NMDevice *device, for (iter = items; iter && *iter; iter++) { if (*iter[0]) { tmp = g_strdup_printf ("%s%s", prefix, *iter); - set_bond_attr (device, "arp_ip_target", tmp); + set_bond_attr (device, mode, NM_SETTING_BOND_OPTION_ARP_IP_TARGET, tmp); g_free (tmp); } } @@ -223,7 +227,7 @@ set_arp_targets (NMDevice *device, static void set_simple_option (NMDevice *device, - const char *attr, + NMBondMode mode, NMSettingBond *s_bond, const char *opt) { @@ -232,18 +236,20 @@ set_simple_option (NMDevice *device, value = nm_setting_bond_get_option_by_name (s_bond, opt); if (!value) value = nm_setting_bond_get_option_default (s_bond, opt); - set_bond_attr (device, attr, value); + set_bond_attr (device, mode, opt, value); } static NMActStageReturn apply_bonding_config (NMDevice *device) { + NMDeviceBond *self = NM_DEVICE_BOND (device); NMConnection *connection; NMSettingBond *s_bond; int ifindex = nm_device_get_ifindex (device); - const char *mode, *value; + const char *mode_str, *value; char *contents; gboolean set_arp_interval = TRUE; + NMBondMode mode; /* Option restrictions: * @@ -263,98 +269,90 @@ apply_bonding_config (NMDevice *device) s_bond = nm_connection_get_setting_bond (connection); g_assert (s_bond); - mode = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_MODE); - if (mode == NULL) - mode = "balance-rr"; + mode_str = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_MODE); + if (!mode_str) + mode_str = "balance-rr"; + + mode = _nm_setting_bond_mode_from_string (mode_str); + if (mode == NM_BOND_MODE_UNKNOWN) { + _LOGW (LOGD_BOND, "unknown bond mode '%s'", mode_str); + return NM_ACT_STAGE_RETURN_FAILURE; + } + + /* Set mode first, as some other options (e.g. arp_interval) are valid + * only for certain modes. + */ + + set_bond_attr (device, mode, NM_SETTING_BOND_OPTION_MODE, mode_str); value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_MIIMON); if (value && atoi (value)) { /* clear arp interval */ - set_bond_attr (device, "arp_interval", "0"); + set_bond_attr (device, mode, NM_SETTING_BOND_OPTION_ARP_INTERVAL, "0"); set_arp_interval = FALSE; - set_bond_attr (device, "miimon", value); - set_simple_option (device, "updelay", s_bond, NM_SETTING_BOND_OPTION_UPDELAY); - set_simple_option (device, "downdelay", s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY); + set_bond_attr (device, mode, NM_SETTING_BOND_OPTION_MIIMON, value); + set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_UPDELAY); + set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY); } else if (!value) { - /* If not given, and arp_interval is not given, default to 100 */ - long int val_int; - char *end; - + /* If not given, and arp_interval is not given or disabled, default to 100 */ value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_ARP_INTERVAL); - errno = 0; - val_int = strtol (value ? value : "0", &end, 10); - if (!value || (val_int == 0 && errno == 0 && *end == '\0')) - set_bond_attr (device, "miimon", "100"); + if (_nm_utils_ascii_str_to_int64 (value, 10, 0, G_MAXUINT32, 0) == 0) + set_bond_attr (device, mode, NM_SETTING_BOND_OPTION_MIIMON, "100"); } - /* The stuff after 'mode' requires the given mode or doesn't care */ - set_bond_attr (device, "mode", mode); - - /* arp_interval not compatible with ALB, TLB */ - if (NM_IN_STRSET (mode, "balance-alb", "balance-tlb")) - set_arp_interval = FALSE; - if (set_arp_interval) { - set_simple_option (device, "arp_interval", s_bond, NM_SETTING_BOND_OPTION_ARP_INTERVAL); - + set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_ARP_INTERVAL); /* Just let miimon get cleared automatically; even setting miimon to * 0 (disabled) clears arp_interval. */ } + /* ARP validate: value > 0 only valid in active-backup mode */ value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_ARP_VALIDATE); - /* arp_validate > 0 only valid in active-backup mode */ if ( value && !nm_streq (value, "0") && !nm_streq (value, "none") - && nm_streq (mode, "active-backup")) - set_bond_attr (device, "arp_validate", value); + && mode == NM_BOND_MODE_ACTIVEBACKUP) + set_bond_attr (device, mode, NM_SETTING_BOND_OPTION_ARP_VALIDATE, value); else - set_bond_attr (device, "arp_validate", "0"); - - 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_interval", s_bond, NM_SETTING_BOND_OPTION_LP_INTERVAL); - } + set_bond_attr (device, mode, NM_SETTING_BOND_OPTION_ARP_VALIDATE, "0"); - /* Clear ARP targets */ - contents = nm_platform_sysctl_master_get_option (NM_PLATFORM_GET, ifindex, "arp_ip_target"); - set_arp_targets (device, contents, " \n", "-"); - g_free (contents); + /* Primary */ + value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_PRIMARY); + set_bond_attr (device, mode, NM_SETTING_BOND_OPTION_PRIMARY, value ? value : ""); - /* Add new ARP targets */ + /* ARP targets: clear and initialize the list */ + contents = nm_platform_sysctl_master_get_option (NM_PLATFORM_GET, ifindex, + NM_SETTING_BOND_OPTION_ARP_IP_TARGET); + set_arp_targets (device, mode, contents, " \n", "-"); value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET); - set_arp_targets (device, value, ",", "+"); - - set_simple_option (device, "primary_reselect", s_bond, NM_SETTING_BOND_OPTION_PRIMARY_RESELECT); - set_simple_option (device, "fail_over_mac", s_bond, NM_SETTING_BOND_OPTION_FAIL_OVER_MAC); - set_simple_option (device, "use_carrier", s_bond, NM_SETTING_BOND_OPTION_USE_CARRIER); - set_simple_option (device, "ad_select", s_bond, NM_SETTING_BOND_OPTION_AD_SELECT); - set_simple_option (device, "xmit_hash_policy", s_bond, NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY); - set_simple_option (device, "resend_igmp", s_bond, NM_SETTING_BOND_OPTION_RESEND_IGMP); - set_simple_option (device, "active_slave", s_bond, NM_SETTING_BOND_OPTION_ACTIVE_SLAVE); - set_simple_option (device, "all_slaves_active", s_bond, NM_SETTING_BOND_OPTION_ALL_SLAVES_ACTIVE); - set_simple_option (device, "num_grat_arp", s_bond, NM_SETTING_BOND_OPTION_NUM_GRAT_ARP); - set_simple_option (device, "num_unsol_na", s_bond, NM_SETTING_BOND_OPTION_NUM_UNSOL_NA); - - if (nm_streq (mode, "802.3ad")) { - set_simple_option (device, "lacp_rate", s_bond, NM_SETTING_BOND_OPTION_LACP_RATE); - set_simple_option (device, "ad_actor_sys_prio", s_bond, NM_SETTING_BOND_OPTION_AD_ACTOR_SYS_PRIO); - set_simple_option (device, "ad_actor_system", s_bond, NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM); - set_simple_option (device, "ad_user_port_key", s_bond, NM_SETTING_BOND_OPTION_AD_USER_PORT_KEY); - set_simple_option (device, "min_links", s_bond, NM_SETTING_BOND_OPTION_MIN_LINKS); - } - - if (nm_streq (mode, "active-backup")) - set_simple_option (device, "arp_all_targets", s_bond, NM_SETTING_BOND_OPTION_ARP_ALL_TARGETS); - - if (nm_streq (mode, "balance-rr")) - set_simple_option (device, "packets_per_slave", s_bond, NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE); + set_arp_targets (device, mode, value, ",", "+"); + g_free (contents); - if (nm_streq (mode, "balance-tlb")) - set_simple_option (device, "tlb_dynamic_lb", s_bond, NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB); + /* AD actor system: don't set if empty */ + value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM); + if (value) + set_bond_attr (device, mode, NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM, value); + + set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_ACTIVE_SLAVE); + set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_AD_ACTOR_SYS_PRIO); + set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_AD_SELECT); + set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_AD_USER_PORT_KEY); + set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_ALL_SLAVES_ACTIVE); + set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_ARP_ALL_TARGETS); + set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_FAIL_OVER_MAC); + set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_LACP_RATE); + set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_LP_INTERVAL); + set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_NUM_GRAT_ARP); + set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_NUM_UNSOL_NA); + set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_MIN_LINKS); + set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE); + set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_PRIMARY_RESELECT); + set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_RESEND_IGMP); + set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB); + set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_USE_CARRIER); + set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY); return NM_ACT_STAGE_RETURN_SUCCESS; } diff --git a/src/devices/nm-device-bond.h b/src/devices/nm-device-bond.h index 9e86719e..02b6c8e5 100644 --- a/src/devices/nm-device-bond.h +++ b/src/devices/nm-device-bond.h @@ -23,8 +23,6 @@ #include "nm-device.h" -G_BEGIN_DECLS - #define NM_TYPE_DEVICE_BOND (nm_device_bond_get_type ()) #define NM_DEVICE_BOND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_BOND, NMDeviceBond)) #define NM_DEVICE_BOND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_BOND, NMDeviceBondClass)) @@ -37,6 +35,4 @@ typedef NMDeviceClass NMDeviceBondClass; GType nm_device_bond_get_type (void); -G_END_DECLS - -#endif /* NM_DEVICE_BOND_H */ +#endif /* NM_DEVICE_BOND_H */ diff --git a/src/devices/nm-device-bridge.h b/src/devices/nm-device-bridge.h index 46482675..05da9ed7 100644 --- a/src/devices/nm-device-bridge.h +++ b/src/devices/nm-device-bridge.h @@ -21,11 +21,8 @@ #ifndef __NETWORKMANAGER_DEVICE_BRIDGE_H__ #define __NETWORKMANAGER_DEVICE_BRIDGE_H__ -#include "nm-default.h" #include "nm-device.h" -G_BEGIN_DECLS - #define NM_TYPE_DEVICE_BRIDGE (nm_device_bridge_get_type ()) #define NM_DEVICE_BRIDGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_BRIDGE, NMDeviceBridge)) #define NM_DEVICE_BRIDGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_BRIDGE, NMDeviceBridgeClass)) @@ -38,6 +35,4 @@ typedef NMDeviceClass NMDeviceBridgeClass; GType nm_device_bridge_get_type (void); -G_END_DECLS - -#endif /* NM_DEVICE_BRIDGE_H */ +#endif /* __NETWORKMANAGER_DEVICE_BRIDGE_H__ */ diff --git a/src/devices/nm-device-ethernet-utils.c b/src/devices/nm-device-ethernet-utils.c index d034ddfc..298e6dff 100644 --- a/src/devices/nm-device-ethernet-utils.c +++ b/src/devices/nm-device-ethernet-utils.c @@ -25,30 +25,26 @@ #include "nm-device-ethernet-utils.h" char * -nm_device_ethernet_utils_get_default_wired_name (const GSList *connections) +nm_device_ethernet_utils_get_default_wired_name (NMConnection *const *connections) { - const GSList *iter; - char *cname = NULL; - int i = 0; + char *temp; + guint j; + int i; /* Find the next available unique connection name */ - while (!cname && (i++ < 10000)) { - char *temp; - gboolean found = FALSE; - + for (i = 1; i <= 10000; i++) { temp = g_strdup_printf (_("Wired connection %d"), i); - for (iter = connections; iter; iter = iter->next) { - if (g_strcmp0 (nm_connection_get_id (NM_CONNECTION (iter->data)), temp) == 0) { - found = TRUE; + for (j = 0; connections[j]; j++) { + if (nm_streq0 (nm_connection_get_id (connections[j]), temp)) { g_free (temp); - break; + goto next; } } - - if (found == FALSE) - cname = temp; + return temp; +next: + ; } - return cname; + return NULL; } diff --git a/src/devices/nm-device-ethernet-utils.h b/src/devices/nm-device-ethernet-utils.h index 31d645d8..197d0a9e 100644 --- a/src/devices/nm-device-ethernet-utils.h +++ b/src/devices/nm-device-ethernet-utils.h @@ -19,8 +19,6 @@ #ifndef __NETWORKMANAGER_DEVICE_ETHERNET_UTILS_H__ #define __NETWORKMANAGER_DEVICE_ETHERNET_UTILS_H__ -#include "nm-default.h" - -char *nm_device_ethernet_utils_get_default_wired_name (const GSList *connections); +char *nm_device_ethernet_utils_get_default_wired_name (NMConnection *const *connections); #endif /* NETWORKMANAGER_DEVICE_ETHERNET_UTILS_H */ diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c index d27f7dca..90d472da 100644 --- a/src/devices/nm-device-ethernet.c +++ b/src/devices/nm-device-ethernet.c @@ -21,6 +21,8 @@ #include "nm-default.h" +#include "nm-device-ethernet.h" + #include <netinet/in.h> #include <string.h> #include <stdlib.h> @@ -29,7 +31,6 @@ #include <gudev/gudev.h> -#include "nm-device-ethernet.h" #include "nm-device-private.h" #include "nm-activation-request.h" #include "NetworkManagerUtils.h" @@ -44,7 +45,7 @@ #include "nm-settings-connection.h" #include "nm-config.h" #include "nm-device-ethernet-utils.h" -#include "nm-connection-provider.h" +#include "nm-settings.h" #include "nm-device-factory.h" #include "nm-core-internal.h" #include "NetworkManagerUtils.h" @@ -54,15 +55,15 @@ #include "nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceEthernet); -G_DEFINE_TYPE (NMDeviceEthernet, nm_device_ethernet, NM_TYPE_DEVICE) - -#define NM_DEVICE_ETHERNET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_ETHERNET, NMDeviceEthernetPrivate)) +/*****************************************************************************/ #define WIRED_SECRETS_TRIES "wired-secrets-tries" #define PPPOE_RECONNECT_DELAY 7 #define PPPOE_ENCAP_OVERHEAD 8 /* 2 bytes for PPP, 6 for PPPoE */ +/*****************************************************************************/ + typedef struct Supplicant { NMSupplicantManager *mgr; NMSupplicantInterface *iface; @@ -90,7 +91,7 @@ typedef enum { DCB_WAIT_CARRIER_POSTCONFIG_UP, } DcbWait; -typedef struct { +typedef struct _NMDeviceEthernetPrivate { guint32 speed; Supplicant supplicant; @@ -117,15 +118,29 @@ typedef struct { gulong dcb_carrier_id; } NMDeviceEthernetPrivate; -enum { - PROP_0, - PROP_PERM_HW_ADDRESS, +NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceEthernet, PROP_SPEED, PROP_S390_SUBCHANNELS, +); - LAST_PROP -}; +/*****************************************************************************/ + +G_DEFINE_TYPE (NMDeviceEthernet, nm_device_ethernet, NM_TYPE_DEVICE) + +#define NM_DEVICE_ETHERNET_GET_PRIVATE(self) \ + ({ \ + /* preserve the const-ness of self. Unfortunately, that + * way, @self cannot be a void pointer */ \ + typeof (self) _self = (self); \ + \ + /* Get compiler error if variable is of wrong type */ \ + _nm_unused const NMDeviceEthernet *_self2 = (_self); \ + \ + nm_assert (NM_IS_DEVICE_ETHERNET (_self)); \ + _self->_priv; \ + }) +/*****************************************************************************/ static char * get_link_basename (const char *parent_path, const char *name, GError **error) @@ -147,21 +162,29 @@ static void _update_s390_subchannels (NMDeviceEthernet *self) { NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - GUdevDevice *dev; - GUdevDevice *parent = NULL; - const char *parent_path, *item, *driver; + gs_unref_object GUdevDevice *dev = NULL; + gs_unref_object GUdevDevice *parent = NULL; + const char *parent_path, *item; int ifindex; GDir *dir; GError *error = NULL; - ifindex = nm_device_get_ifindex (NM_DEVICE (self)); - dev = (GUdevDevice *) nm_platform_link_get_udev_device (NM_PLATFORM_GET, ifindex); + if (priv->subchannels) { + /* only read the subchannels once. For one, we don't expect them to change + * on multiple invocations. Second, we didn't implement proper reloading. + * Proper reloading might also be complicated, because the subchannels are + * used to match on devices based on a device-spec. Thus, it's not clear + * what it means to change afterwards. */ + return; + } + + ifindex = nm_device_get_ifindex ((NMDevice *) self); + dev = (GUdevDevice *) nm_g_object_ref (nm_platform_link_get_udev_device (NM_PLATFORM_GET, ifindex)); if (!dev) { - _LOGW (LOGD_DEVICE | LOGD_HW, "failed to find device %d '%s' with udev", - ifindex, nm_device_get_iface (NM_DEVICE (self)) ?: "(null)"); - goto out; + /* we only call _update_s390_subchannels() when platform claims the device to be initialized. + * Thus, we expect to successfully lookup a GUdevDevice. */ + g_return_if_reached (); } - g_object_ref (dev); /* Try for the "ccwgroup" parent */ parent = g_udev_device_get_parent_with_subsystem (dev, "ccwgroup", NULL); @@ -169,17 +192,17 @@ _update_s390_subchannels (NMDeviceEthernet *self) /* FIXME: whatever 'lcs' devices' subsystem is here... */ if (!parent) { /* Not an s390 device */ - goto out; + return; } } parent_path = g_udev_device_get_sysfs_path (parent); dir = g_dir_open (parent_path, 0, &error); if (!dir) { - _LOGW (LOGD_DEVICE | LOGD_HW, "failed to open directory '%s': %s", + _LOGW (LOGD_DEVICE | LOGD_HW, "update-s390: failed to open directory '%s': %s", parent_path, error->message); g_clear_error (&error); - goto out; + return; } while ((item = g_dir_read_name (dir))) { @@ -206,11 +229,11 @@ _update_s390_subchannels (NMDeviceEthernet *self) g_hash_table_insert (priv->s390_options, g_strdup (item), value); value = NULL; } else - _LOGW (LOGD_DEVICE | LOGD_HW, "error reading %s", path); + _LOGW (LOGD_DEVICE | LOGD_HW, "update-s390: error reading %s", path); } if (error) { - _LOGW (LOGD_DEVICE | LOGD_HW, "%s", error->message); + _LOGW (LOGD_DEVICE | LOGD_HW, "update-s390: failed reading sysfs for %s (%s)", item, error->message); g_clear_error (&error); } } @@ -235,42 +258,23 @@ _update_s390_subchannels (NMDeviceEthernet *self) priv->subchannels_dbus[2] = g_strdup (priv->subchan3); priv->subchannels_dbus[3] = NULL; - driver = nm_device_get_driver (NM_DEVICE (self)); - _LOGI (LOGD_DEVICE | LOGD_HW, "found s390 '%s' subchannels [%s]", - driver ? driver : "(unknown driver)", priv->subchannels); + _LOGI (LOGD_DEVICE | LOGD_HW, "update-s390: found s390 '%s' subchannels [%s]", + nm_device_get_driver ((NMDevice *) self) ?: "(unknown driver)", + priv->subchannels); -out: - if (parent) - g_object_unref (parent); - if (dev) - g_object_unref (dev); + _notify (self, PROP_S390_SUBCHANNELS); } -static GObject* -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) +static void +constructed (GObject *object) { - GObject *object; - - object = G_OBJECT_CLASS (nm_device_ethernet_parent_class)->constructor (type, - n_construct_params, - construct_params); - if (object) { -#ifndef G_DISABLE_ASSERT - int ifindex = nm_device_get_ifindex (NM_DEVICE (object)); - NMLinkType link_type = nm_platform_link_get_type (NM_PLATFORM_GET, ifindex); - - g_assert ( link_type == NM_LINK_TYPE_ETHERNET - || link_type == NM_LINK_TYPE_VETH - || link_type == NM_LINK_TYPE_NONE); -#endif - - /* s390 stuff */ - _update_s390_subchannels (NM_DEVICE_ETHERNET (object)); - } + const NMPlatformLink *pllink; + + G_OBJECT_CLASS (nm_device_ethernet_parent_class)->constructed (object); - return object; + pllink = nm_platform_link_get (NM_PLATFORM_GET, nm_device_get_ifindex ((NMDevice *) object)); + if (pllink && pllink->initialized) + _update_s390_subchannels ((NMDeviceEthernet *) object); } static void @@ -302,16 +306,12 @@ device_state_changed (NMDevice *device, static void nm_device_ethernet_init (NMDeviceEthernet *self) { - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - priv->s390_options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); -} + NMDeviceEthernetPrivate *priv; -static void -realize_start_notify (NMDevice *device, const NMPlatformLink *plink) -{ - NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->realize_start_notify (device, plink); + priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_DEVICE_ETHERNET, NMDeviceEthernetPrivate); + self->_priv = priv; - g_object_notify (G_OBJECT (device), NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS); + priv->s390_options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); } static NMDeviceCapabilities @@ -407,7 +407,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection) if (!match_subchans (self, s_wired, &try_mac)) return FALSE; - perm_hw_addr = nm_device_get_permanent_hw_address (device); + perm_hw_addr = nm_device_get_permanent_hw_address (device, TRUE); mac = nm_setting_wired_get_mac_address (s_wired); if (perm_hw_addr) { if (try_mac && mac && !nm_utils_hwaddr_matches (mac, -1, perm_hw_addr, -1)) @@ -812,21 +812,17 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) { NMDeviceEthernet *self = NM_DEVICE_ETHERNET (dev); NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - NMSettingWired *s_wired; - const char *cloned_mac; NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS; g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); ret = NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->act_stage1_prepare (dev, reason); if (ret == NM_ACT_STAGE_RETURN_SUCCESS) { - s_wired = (NMSettingWired *) nm_device_get_applied_setting (dev, NM_TYPE_SETTING_WIRED); - if (s_wired) { - /* Set device MAC address if the connection wants to change it */ - cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired); - nm_device_set_hw_addr (dev, cloned_mac, "set", LOGD_ETHER); - } + if (!nm_device_hw_addr_set_cloned (dev, nm_device_get_applied_connection (dev), FALSE)) + ret = NM_ACT_STAGE_RETURN_FAILURE; + } + if (ret == NM_ACT_STAGE_RETURN_SUCCESS) { /* If we're re-activating a PPPoE connection a short while after * a previous PPPoE connection was torn down, wait a bit to allow the * remote side to handle the disconnection. Otherwise the peer may @@ -946,7 +942,7 @@ pppoe_stage3_ip4_config_start (NMDeviceEthernet *self, NMDeviceStateReason *reas req = nm_device_get_act_request (NM_DEVICE (self)); g_assert (req); - s_pppoe = (NMSettingPppoe *) nm_device_get_applied_setting (self, NM_TYPE_SETTING_PPPOE); + s_pppoe = (NMSettingPppoe *) nm_device_get_applied_setting ((NMDevice *) self, NM_TYPE_SETTING_PPPOE); g_assert (s_pppoe); priv->ppp_manager = nm_ppp_manager_new (nm_device_get_iface (NM_DEVICE (self))); @@ -972,22 +968,6 @@ pppoe_stage3_ip4_config_start (NMDeviceEthernet *self, NMDeviceStateReason *reas /****************************************************************/ -static void -dcb_timeout_cleanup (NMDevice *device) -{ - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device); - - nm_clear_g_source (&priv->dcb_timeout_id); -} - -static void -dcb_carrier_cleanup (NMDevice *device) -{ - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device); - - nm_clear_g_signal_handler (device, &priv->dcb_carrier_id); -} - static void dcb_state (NMDevice *device, gboolean timeout); static gboolean @@ -1011,12 +991,12 @@ dcb_carrier_timeout (gpointer user_data) static gboolean dcb_configure (NMDevice *device) { - NMDeviceEthernet *self = NM_DEVICE_ETHERNET (device); - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device); + NMDeviceEthernet *self = (NMDeviceEthernet *) device; + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); NMSettingDcb *s_dcb; GError *error = NULL; - dcb_timeout_cleanup (device); + nm_clear_g_source (&priv->dcb_timeout_id); s_dcb = (NMSettingDcb *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_DCB); g_assert (s_dcb); @@ -1043,7 +1023,7 @@ dcb_enable (NMDevice *device) NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); GError *error = NULL; - dcb_timeout_cleanup (device); + nm_clear_g_source (&priv->dcb_timeout_id); if (!nm_dcb_enable (nm_device_get_iface (device), TRUE, &error)) { _LOGW (LOGD_DCB, "Activation: (ethernet) failed to enable DCB/FCoE: %s", error->message); @@ -1081,9 +1061,9 @@ dcb_state (NMDevice *device, gboolean timeout) case DCB_WAIT_CARRIER_PREENABLE_UP: if (timeout || carrier) { _LOGD (LOGD_DCB, "dcb_state() enabling DCB"); - dcb_timeout_cleanup (device); + nm_clear_g_source (&priv->dcb_timeout_id); if (!dcb_enable (device)) { - dcb_carrier_cleanup (device); + nm_clear_g_signal_handler (device, &priv->dcb_carrier_id); nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED); @@ -1091,7 +1071,7 @@ dcb_state (NMDevice *device, gboolean timeout) } break; case DCB_WAIT_CARRIER_PRECONFIG_DOWN: - dcb_timeout_cleanup (device); + nm_clear_g_source (&priv->dcb_timeout_id); priv->dcb_wait = DCB_WAIT_CARRIER_PRECONFIG_UP; if (!carrier) { @@ -1105,9 +1085,9 @@ dcb_state (NMDevice *device, gboolean timeout) case DCB_WAIT_CARRIER_PRECONFIG_UP: if (timeout || carrier) { _LOGD (LOGD_DCB, "dcb_state() preconfig up configuring DCB"); - dcb_timeout_cleanup (device); + nm_clear_g_source (&priv->dcb_timeout_id); if (!dcb_configure (device)) { - dcb_carrier_cleanup (device); + nm_clear_g_signal_handler (device, &priv->dcb_carrier_id); nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED); @@ -1115,7 +1095,7 @@ dcb_state (NMDevice *device, gboolean timeout) } break; case DCB_WAIT_CARRIER_POSTCONFIG_DOWN: - dcb_timeout_cleanup (device); + nm_clear_g_source (&priv->dcb_timeout_id); priv->dcb_wait = DCB_WAIT_CARRIER_POSTCONFIG_UP; if (!carrier) { @@ -1129,8 +1109,8 @@ dcb_state (NMDevice *device, gboolean timeout) case DCB_WAIT_CARRIER_POSTCONFIG_UP: if (timeout || carrier) { _LOGD (LOGD_DCB, "dcb_state() postconfig up starting IP"); - dcb_timeout_cleanup (device); - dcb_carrier_cleanup (device); + nm_clear_g_source (&priv->dcb_timeout_id); + nm_clear_g_signal_handler (device, &priv->dcb_carrier_id); priv->dcb_wait = DCB_WAIT_UNKNOWN; nm_device_activate_schedule_stage3_ip_config_start (device); } @@ -1200,7 +1180,7 @@ found: static NMActStageReturn act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) { - NMDeviceEthernet *self = NM_DEVICE_ETHERNET (device); + NMDeviceEthernet *self = (NMDeviceEthernet *) device; NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); NMSettingConnection *s_con; const char *connection_type; @@ -1213,8 +1193,8 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) NM_TYPE_SETTING_CONNECTION)); g_assert (s_con); - dcb_timeout_cleanup (device); - dcb_carrier_cleanup (device); + nm_clear_g_source (&priv->dcb_timeout_id); + nm_clear_g_signal_handler (device, &priv->dcb_carrier_id); /* 802.1x has to run before any IP configuration since the 802.1x auth * process opens the port up for normal traffic. @@ -1311,7 +1291,7 @@ ip4_config_pre_commit (NMDevice *device, NMIP4Config *config) guint32 mtu; /* MTU only set for plain ethernet */ - if (NM_DEVICE_ETHERNET_GET_PRIVATE (device)->ppp_manager) + if (NM_DEVICE_ETHERNET_GET_PRIVATE ((NMDeviceEthernet *) device)->ppp_manager) return; connection = nm_device_get_applied_connection (device); @@ -1348,8 +1328,8 @@ deactivate (NMDevice *device) supplicant_interface_release (self); priv->dcb_wait = DCB_WAIT_UNKNOWN; - dcb_timeout_cleanup (device); - dcb_carrier_cleanup (device); + nm_clear_g_source (&priv->dcb_timeout_id); + nm_clear_g_signal_handler (device, &priv->dcb_carrier_id); /* Tear down DCB/FCoE if it was enabled */ s_dcb = (NMSettingDcb *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_DCB); @@ -1363,11 +1343,7 @@ deactivate (NMDevice *device) /* Set last PPPoE connection time */ if (nm_device_get_applied_setting (device, NM_TYPE_SETTING_PPPOE)) - NM_DEVICE_ETHERNET_GET_PRIVATE (device)->last_pppoe_time = nm_utils_get_monotonic_timestamp_s (); - - /* Reset MAC address back to initial address */ - if (nm_device_get_initial_hw_address (device)) - nm_device_set_hw_addr (device, nm_device_get_initial_hw_address (device), "reset", LOGD_ETHER); + priv->last_pppoe_time = nm_utils_get_monotonic_timestamp_s (); } static gboolean @@ -1408,7 +1384,7 @@ complete_connection (NMDevice *device, nm_connection_add_setting (connection, NM_SETTING (s_wired)); } - perm_hw_addr = nm_device_get_permanent_hw_address (device); + perm_hw_addr = nm_device_get_permanent_hw_address (device, FALSE); if (perm_hw_addr) { setting_mac = nm_setting_wired_get_mac_address (s_wired); if (setting_mac) { @@ -1435,9 +1411,9 @@ static NMConnection * new_default_connection (NMDevice *self) { NMConnection *connection; - const GSList *connections; + NMSettingsConnection *const*connections; NMSetting *setting; - const char *hw_address; + const char *perm_hw_addr; gs_free char *defname = NULL; gs_free char *uuid = NULL; gs_free char *machine_id = NULL; @@ -1445,16 +1421,16 @@ new_default_connection (NMDevice *self) if (nm_config_get_no_auto_default_for_device (nm_config_get (), self)) return NULL; - hw_address = nm_device_get_hw_address (self); - if (!hw_address) + perm_hw_addr = nm_device_get_permanent_hw_address (self, TRUE); + if (!perm_hw_addr) return NULL; connection = nm_simple_connection_new (); setting = nm_setting_connection_new (); nm_connection_add_setting (connection, setting); - connections = nm_connection_provider_get_connections (nm_connection_provider_get ()); - defname = nm_device_ethernet_utils_get_default_wired_name (connections); + connections = nm_settings_get_connections (nm_device_get_settings (self), NULL); + defname = nm_device_ethernet_utils_get_default_wired_name ((NMConnection *const*) connections); if (!defname) return NULL; @@ -1465,7 +1441,7 @@ new_default_connection (NMDevice *self) uuid = _nm_utils_uuid_generate_from_strings ("default-wired", machine_id ?: "", defname, - hw_address, + perm_hw_addr, NULL); g_object_set (setting, @@ -1479,7 +1455,7 @@ new_default_connection (NMDevice *self) /* Lock the connection to the device */ setting = nm_setting_wired_new (); - g_object_set (setting, NM_SETTING_WIRED_MAC_ADDRESS, hw_address, NULL); + g_object_set (setting, NM_SETTING_WIRED_MAC_ADDRESS, perm_hw_addr, NULL); nm_connection_add_setting (connection, setting); return connection; @@ -1489,7 +1465,7 @@ static NMMatchSpecMatchType spec_match_list (NMDevice *device, const GSList *specs) { NMMatchSpecMatchType matched = NM_MATCH_SPEC_NO_MATCH, m; - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device); + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE ((NMDeviceEthernet *) device); if (priv->subchannels) matched = nm_match_spec_s390_subchannels (specs, priv->subchannels); @@ -1503,9 +1479,9 @@ spec_match_list (NMDevice *device, const GSList *specs) static void update_connection (NMDevice *device, NMConnection *connection) { - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device); + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE ((NMDeviceEthernet *) device); NMSettingWired *s_wired = nm_connection_get_setting_wired (connection); - const char *perm_hw_addr = nm_device_get_permanent_hw_address (device); + const char *perm_hw_addr = nm_device_get_permanent_hw_address (device, FALSE); const char *mac = nm_device_get_hw_address (device); const char *mac_prop = NM_SETTING_WIRED_MAC_ADDRESS; GHashTableIter iter; @@ -1562,7 +1538,7 @@ get_link_speed (NMDevice *device) return; priv->speed = speed; - g_object_notify (G_OBJECT (device), "speed"); + _notify (self, PROP_SPEED); _LOGD (LOGD_HW | LOGD_ETHER, "speed is now %d Mb/s", speed); } @@ -1579,37 +1555,9 @@ carrier_changed (NMDevice *device, gboolean carrier) static void link_changed (NMDevice *device, NMPlatformLink *info) { - NMDeviceEthernet *self = NM_DEVICE_ETHERNET (device); - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - static const guint8 zero_hwaddr[ETH_ALEN]; - const guint8 *hwaddr; - gsize hwaddrlen = 0; - NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->link_changed (device, info); - if (!priv->subchan1 && info->initialized) - _update_s390_subchannels (self); - - if (!nm_device_get_initial_hw_address (device)) { - hwaddr = nm_platform_link_get_address (NM_PLATFORM_GET, - nm_device_get_ifindex (self), - &hwaddrlen); - if (!nm_utils_hwaddr_matches (hwaddr, hwaddrlen, zero_hwaddr, ETH_ALEN)) { - _LOGD (LOGD_DEVICE, "device got a valid hw address"); - nm_device_update_hw_address (self); - nm_device_update_initial_hw_address (self); - if (nm_device_get_state (device) == NM_DEVICE_STATE_UNAVAILABLE) { - /* - * If the device is UNAVAILABLE, any previous try to - * bring it up probably has failed because of the - * invalid hardware address; try again. - */ - nm_device_bring_up (self, TRUE, NULL); - nm_device_queue_recheck_available (device, - NM_DEVICE_STATE_REASON_NONE, - NM_DEVICE_STATE_REASON_NONE); - } - } - } + if (info->initialized) + _update_s390_subchannels ((NMDeviceEthernet *) device); } static gboolean @@ -1631,8 +1579,8 @@ dispose (GObject *object) nm_clear_g_source (&priv->pppoe_wait_id); - dcb_timeout_cleanup (NM_DEVICE (self)); - dcb_carrier_cleanup (NM_DEVICE (self)); + nm_clear_g_source (&priv->dcb_timeout_id); + nm_clear_g_signal_handler (self, &priv->dcb_carrier_id); G_OBJECT_CLASS (nm_device_ethernet_parent_class)->dispose (object); } @@ -1663,9 +1611,6 @@ get_property (GObject *object, guint prop_id, NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); switch (prop_id) { - case PROP_PERM_HW_ADDRESS: - g_value_set_string (value, nm_device_get_permanent_hw_address (NM_DEVICE (object))); - break; case PROP_SPEED: g_value_set_uint (value, priv->speed); break; @@ -1700,14 +1645,13 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass) NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_WIRED_SETTING_NAME, NM_LINK_TYPE_ETHERNET) /* virtual methods */ - object_class->constructor = constructor; + object_class->constructed = constructed; object_class->dispose = dispose; object_class->finalize = finalize; object_class->get_property = get_property; object_class->set_property = set_property; parent_class->get_generic_capabilities = get_generic_capabilities; - parent_class->realize_start_notify = realize_start_notify; parent_class->check_connection_compatible = check_connection_compatible; parent_class->complete_connection = complete_connection; parent_class->new_default_connection = new_default_connection; @@ -1725,27 +1669,19 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass) parent_class->state_changed = device_state_changed; - /* properties */ - g_object_class_install_property - (object_class, PROP_PERM_HW_ADDRESS, - g_param_spec_string (NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_SPEED, - g_param_spec_uint (NM_DEVICE_ETHERNET_SPEED, "", "", - 0, G_MAXUINT32, 0, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_S390_SUBCHANNELS, - g_param_spec_boxed (NM_DEVICE_ETHERNET_S390_SUBCHANNELS, "", "", - G_TYPE_STRV, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_SPEED] = + g_param_spec_uint (NM_DEVICE_ETHERNET_SPEED, "", "", + 0, G_MAXUINT32, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_S390_SUBCHANNELS] = + g_param_spec_boxed (NM_DEVICE_ETHERNET_S390_SUBCHANNELS, "", "", + G_TYPE_STRV, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), NMDBUS_TYPE_DEVICE_ETHERNET_SKELETON, diff --git a/src/devices/nm-device-ethernet.h b/src/devices/nm-device-ethernet.h index 2d284822..3ce6f0ca 100644 --- a/src/devices/nm-device-ethernet.h +++ b/src/devices/nm-device-ethernet.h @@ -24,8 +24,6 @@ #include "nm-device.h" -G_BEGIN_DECLS - #define NM_TYPE_DEVICE_ETHERNET (nm_device_ethernet_get_type ()) #define NM_DEVICE_ETHERNET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_ETHERNET, NMDeviceEthernet)) #define NM_DEVICE_ETHERNET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_ETHERNET, NMDeviceEthernetClass)) @@ -33,15 +31,20 @@ G_BEGIN_DECLS #define NM_IS_DEVICE_ETHERNET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_ETHERNET)) #define NM_DEVICE_ETHERNET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_ETHERNET, NMDeviceEthernetClass)) -#define NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS "perm-hw-address" #define NM_DEVICE_ETHERNET_SPEED "speed" #define NM_DEVICE_ETHERNET_S390_SUBCHANNELS "s390-subchannels" -typedef NMDevice NMDeviceEthernet; -typedef NMDeviceClass NMDeviceEthernetClass; +struct _NMDeviceEthernetPrivate; -GType nm_device_ethernet_get_type (void); +typedef struct { + NMDevice parent; + struct _NMDeviceEthernetPrivate *_priv; +} NMDeviceEthernet; -G_END_DECLS +typedef struct { + NMDeviceClass parent_class; +} NMDeviceEthernetClass; + +GType nm_device_ethernet_get_type (void); -#endif /* NM_DEVICE_ETHERNET_H */ +#endif /* __NETWORKMANAGER_DEVICE_ETHERNET_H__ */ diff --git a/src/devices/nm-device-factory.h b/src/devices/nm-device-factory.h index ae78968a..4a62468c 100644 --- a/src/devices/nm-device-factory.h +++ b/src/devices/nm-device-factory.h @@ -92,10 +92,10 @@ typedef struct { * @connection: the #NMConnection to return the parent name for, if supported * * Given a connection, returns the a parent interface name, parent connection - * UUID, or parent device hardware address for @connection. + * UUID, or parent device permanent hardware address for @connection. * * Returns: the parent interface name, parent connection UUID, parent - * device hardware address, or %NULL + * device permenent hardware address, or %NULL */ const char * (*get_connection_parent) (NMDeviceFactory *factory, NMConnection *connection); diff --git a/src/devices/nm-device-generic.h b/src/devices/nm-device-generic.h index 9303a278..9a5ff091 100644 --- a/src/devices/nm-device-generic.h +++ b/src/devices/nm-device-generic.h @@ -23,8 +23,6 @@ #include "nm-device.h" -G_BEGIN_DECLS - #define NM_TYPE_DEVICE_GENERIC (nm_device_generic_get_type ()) #define NM_DEVICE_GENERIC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_GENERIC, NMDeviceGeneric)) #define NM_DEVICE_GENERIC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_GENERIC, NMDeviceGenericClass)) @@ -47,6 +45,4 @@ GType nm_device_generic_get_type (void); NMDevice *nm_device_generic_new (const NMPlatformLink *plink); -G_END_DECLS - -#endif /* NM_DEVICE_GENERIC_H */ +#endif /* __NETWORKMANAGER_DEVICE_GENERIC_H__ */ diff --git a/src/devices/nm-device-infiniband.c b/src/devices/nm-device-infiniband.c index ae9543e4..17f50ba2 100644 --- a/src/devices/nm-device-infiniband.c +++ b/src/devices/nm-device-infiniband.c @@ -147,10 +147,15 @@ check_connection_compatible (NMDevice *device, NMConnection *connection) if (nm_device_is_real (device)) { const char *mac; + const char *hw_addr; mac = nm_setting_infiniband_get_mac_address (s_infiniband); - if (mac && !nm_utils_hwaddr_matches (mac, -1, nm_device_get_hw_address (device), -1)) - return FALSE; + if (mac) { + hw_addr = nm_device_get_permanent_hw_address (device, TRUE); + if ( !hw_addr + || !nm_utils_hwaddr_matches (mac, -1, hw_addr, -1)) + return FALSE; + } } return TRUE; @@ -183,7 +188,7 @@ complete_connection (NMDevice *device, } setting_mac = nm_setting_infiniband_get_mac_address (s_infiniband); - hw_address = nm_device_get_hw_address (device); + hw_address = nm_device_get_permanent_hw_address (device, TRUE); if (setting_mac) { /* Make sure the setting MAC (if any) matches the device's MAC */ if (!nm_utils_hwaddr_matches (setting_mac, -1, hw_address, -1)) { @@ -209,7 +214,7 @@ static void update_connection (NMDevice *device, NMConnection *connection) { NMSettingInfiniband *s_infiniband = nm_connection_get_setting_infiniband (connection); - const char *mac = nm_device_get_hw_address (device); + const char *mac = nm_device_get_permanent_hw_address (device, TRUE); const char *transport_mode = "datagram"; int ifindex; diff --git a/src/devices/nm-device-infiniband.h b/src/devices/nm-device-infiniband.h index cac9a79d..a74d07a5 100644 --- a/src/devices/nm-device-infiniband.h +++ b/src/devices/nm-device-infiniband.h @@ -23,8 +23,6 @@ #include "nm-device.h" -G_BEGIN_DECLS - #define NM_TYPE_DEVICE_INFINIBAND (nm_device_infiniband_get_type ()) #define NM_DEVICE_INFINIBAND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_INFINIBAND, NMDeviceInfiniband)) #define NM_DEVICE_INFINIBAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_INFINIBAND, NMDeviceInfinibandClass)) @@ -37,6 +35,4 @@ typedef NMDeviceClass NMDeviceInfinibandClass; GType nm_device_infiniband_get_type (void); -G_END_DECLS - -#endif /* NM_DEVICE_INFINIBAND_H */ +#endif /* __NETWORKMANAGER_DEVICE_INFINIBAND_H__ */ diff --git a/src/devices/nm-device-ip-tunnel.c b/src/devices/nm-device-ip-tunnel.c index 089b1035..785010eb 100644 --- a/src/devices/nm-device-ip-tunnel.c +++ b/src/devices/nm-device-ip-tunnel.c @@ -20,19 +20,20 @@ #include "nm-default.h" +#include "nm-device-ip-tunnel.h" + #include <string.h> #include <netinet/in.h> #include <linux/if.h> #include <linux/ip.h> #include <linux/if_tunnel.h> -#include "nm-device-ip-tunnel.h" #include "nm-device-private.h" #include "nm-manager.h" #include "nm-platform.h" #include "nm-device-factory.h" #include "nm-core-internal.h" -#include "nm-connection-provider.h" +#include "nm-settings.h" #include "nm-activation-request.h" #include "nm-ip4-config.h" @@ -385,8 +386,8 @@ update_connection (NMDevice *device, NMConnection *connection) NMConnection *parent_connection; /* Don't change a parent specified by UUID if it's still valid */ - parent_connection = nm_connection_provider_get_connection_by_uuid (nm_connection_provider_get (), - setting_parent); + parent_connection = (NMConnection *) nm_settings_get_connection_by_uuid (nm_device_get_settings (device), + setting_parent); if (parent_connection && nm_device_check_connection_compatible (parent, parent_connection)) new_parent = NULL; } diff --git a/src/devices/nm-device-ip-tunnel.h b/src/devices/nm-device-ip-tunnel.h index 11cb5bce..94cc7375 100644 --- a/src/devices/nm-device-ip-tunnel.h +++ b/src/devices/nm-device-ip-tunnel.h @@ -24,8 +24,6 @@ #include "nm-core-types.h" #include "nm-device.h" -G_BEGIN_DECLS - #define NM_TYPE_DEVICE_IP_TUNNEL (nm_device_ip_tunnel_get_type ()) #define NM_DEVICE_IP_TUNNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_IP_TUNNEL, NMDeviceIPTunnel)) #define NM_DEVICE_IP_TUNNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_IP_TUNNEL, NMDeviceIPTunnelClass)) @@ -55,6 +53,4 @@ typedef struct { GType nm_device_ip_tunnel_get_type (void); -G_END_DECLS - -#endif /* NM_DEVICE_IP_TUNNEL_H */ +#endif /* __NETWORKMANAGER_DEVICE_IP_TUNNEL_H__ */ diff --git a/src/devices/nm-device-logging.h b/src/devices/nm-device-logging.h index 1be17073..fac92eac 100644 --- a/src/devices/nm-device-logging.h +++ b/src/devices/nm-device-logging.h @@ -21,7 +21,6 @@ #ifndef __NETWORKMANAGER_DEVICE_LOGGING_H__ #define __NETWORKMANAGER_DEVICE_LOGGING_H__ -#include "nm-default.h" #include "nm-device.h" #define _LOG_DECLARE_SELF(t) \ diff --git a/src/devices/nm-device-macvlan.c b/src/devices/nm-device-macvlan.c index c431fe89..2bfc65cb 100644 --- a/src/devices/nm-device-macvlan.c +++ b/src/devices/nm-device-macvlan.c @@ -20,11 +20,12 @@ #include "nm-default.h" +#include "nm-device-macvlan.h" + #include <string.h> -#include "nm-device-macvlan.h" #include "nm-device-private.h" -#include "nm-connection-provider.h" +#include "nm-settings.h" #include "nm-activation-request.h" #include "nm-manager.h" #include "nm-platform.h" @@ -372,9 +373,8 @@ match_hwaddr (NMDevice *device, NMConnection *connection, gboolean fail_if_no_hw if (!priv->parent) return !fail_if_no_hwaddr; - parent_mac = nm_device_get_hw_address (priv->parent); - - return nm_utils_hwaddr_matches (setting_mac, -1, parent_mac, -1); + parent_mac = nm_device_get_permanent_hw_address (priv->parent, FALSE); + return parent_mac && nm_utils_hwaddr_matches (setting_mac, -1, parent_mac, -1); } static gboolean @@ -488,7 +488,7 @@ update_connection (NMDevice *device, NMConnection *connection) NMConnection *parent_connection; /* Don't change a parent specified by UUID if it's still valid */ - parent_connection = nm_connection_provider_get_connection_by_uuid (nm_connection_provider_get (), setting_parent); + parent_connection = (NMConnection *) nm_settings_get_connection_by_uuid (nm_device_get_settings (device), setting_parent); if (parent_connection && nm_device_check_connection_compatible (priv->parent, parent_connection)) new_parent = NULL; } @@ -502,8 +502,6 @@ update_connection (NMDevice *device, NMConnection *connection) static NMActStageReturn act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) { - NMSettingWired *s_wired; - const char *cloned_mac; NMActStageReturn ret; g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); @@ -512,14 +510,9 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) if (ret != NM_ACT_STAGE_RETURN_SUCCESS) return ret; - s_wired = (NMSettingWired *) nm_device_get_applied_setting (dev, NM_TYPE_SETTING_WIRED); - if (s_wired) { - /* Set device MAC address if the connection wants to change it */ - cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired); - nm_device_set_hw_addr (dev, cloned_mac, "set", LOGD_HW); - } - - return TRUE; + if (!nm_device_hw_addr_set_cloned (dev, nm_device_get_applied_connection (dev), FALSE)) + return NM_ACT_STAGE_RETURN_FAILURE; + return NM_ACT_STAGE_RETURN_SUCCESS; } static void @@ -548,16 +541,6 @@ realize_start_notify (NMDevice *device, const NMPlatformLink *plink) update_properties (device); } -static void -deactivate (NMDevice *device) -{ - /* Reset MAC address back to initial address */ - if (nm_device_get_initial_hw_address (device)) { - nm_device_set_hw_addr (device, nm_device_get_initial_hw_address (device), - "reset", LOGD_DEVICE); - } -} - /******************************************************************/ static void @@ -638,7 +621,6 @@ nm_device_macvlan_class_init (NMDeviceMacvlanClass *klass) device_class->complete_connection = complete_connection; device_class->connection_type = NM_SETTING_MACVLAN_SETTING_NAME; device_class->create_and_realize = create_and_realize; - device_class->deactivate = deactivate; device_class->get_generic_capabilities = get_generic_capabilities; device_class->ip4_config_pre_commit = ip4_config_pre_commit; device_class->is_available = is_available; diff --git a/src/devices/nm-device-macvlan.h b/src/devices/nm-device-macvlan.h index 89f670bd..5756f696 100644 --- a/src/devices/nm-device-macvlan.h +++ b/src/devices/nm-device-macvlan.h @@ -23,8 +23,6 @@ #include "nm-device.h" -G_BEGIN_DECLS - #define NM_TYPE_DEVICE_MACVLAN (nm_device_macvlan_get_type ()) #define NM_DEVICE_MACVLAN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_MACVLAN, NMDeviceMacvlan)) #define NM_DEVICE_MACVLAN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_MACVLAN, NMDeviceMacvlanClass)) @@ -42,6 +40,4 @@ typedef NMDeviceClass NMDeviceMacvlanClass; GType nm_device_macvlan_get_type (void); -G_END_DECLS - -#endif /* NM_DEVICE_MACVLAN_H */ +#endif /* __NETWORKMANAGER_DEVICE_MACVLAN_H__ */ diff --git a/src/devices/nm-device-private.h b/src/devices/nm-device-private.h index 602c2c85..c85cb969 100644 --- a/src/devices/nm-device-private.h +++ b/src/devices/nm-device-private.h @@ -24,8 +24,6 @@ #include "nm-device.h" -#include "nm-default.h" - /* This file should only be used by subclasses of NMDevice */ enum NMActStageReturn { @@ -42,6 +40,8 @@ enum NMActStageReturn { #define NM_DEVICE_CAP_INTERNAL_MASK 0xc0000000 +NMSettings *nm_device_get_settings (NMDevice *self); + void nm_device_set_ip_iface (NMDevice *self, const char *iface); void nm_device_activate_schedule_stage3_ip_config_start (NMDevice *device); @@ -54,8 +54,9 @@ gboolean nm_device_bring_up (NMDevice *self, gboolean wait, gboolean *no_firmwar void nm_device_take_down (NMDevice *self, gboolean block); -gboolean nm_device_set_hw_addr (NMDevice *device, const char *addr, - const char *detail, guint64 hw_log_domain); +gboolean nm_device_hw_addr_set (NMDevice *device, const char *addr, const char *detail); +gboolean nm_device_hw_addr_set_cloned (NMDevice *device, NMConnection *connection, gboolean is_wifi); +gboolean nm_device_hw_addr_reset (NMDevice *device, const char *detail); void nm_device_set_firmware_missing (NMDevice *self, gboolean missing); @@ -70,9 +71,11 @@ void nm_device_activate_schedule_ip6_config_timeout (NMDevice *device); gboolean nm_device_activate_ip4_state_in_conf (NMDevice *device); gboolean nm_device_activate_ip4_state_in_wait (NMDevice *device); +gboolean nm_device_activate_ip4_state_done (NMDevice *device); gboolean nm_device_activate_ip6_state_in_conf (NMDevice *device); gboolean nm_device_activate_ip6_state_in_wait (NMDevice *device); +gboolean nm_device_activate_ip6_state_done (NMDevice *device); void nm_device_set_dhcp_timeout (NMDevice *device, guint32 timeout); void nm_device_set_dhcp_anycast_address (NMDevice *device, const char *addr); @@ -103,6 +106,10 @@ void nm_device_queue_recheck_available (NMDevice *device, void nm_device_set_wwan_ip4_config (NMDevice *device, NMIP4Config *config); void nm_device_set_wwan_ip6_config (NMDevice *device, NMIP6Config *config); +gboolean nm_device_hw_addr_is_explict (NMDevice *device); + +void nm_device_ip_method_failed (NMDevice *self, int family, NMDeviceStateReason reason); + gboolean nm_device_ipv6_sysctl_set (NMDevice *self, const char *property, const char *value); #define NM_DEVICE_CLASS_DECLARE_TYPES(klass, conn_type, ...) \ diff --git a/src/devices/nm-device-tun.c b/src/devices/nm-device-tun.c index 01cd8ea6..1f42d060 100644 --- a/src/devices/nm-device-tun.c +++ b/src/devices/nm-device-tun.c @@ -291,8 +291,6 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) { NMDeviceTun *self = NM_DEVICE_TUN (device); NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (self); - NMSettingWired *s_wired; - const char *cloned_mac; NMActStageReturn ret; g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); @@ -305,12 +303,8 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) if (g_strcmp0 (priv->mode, "tap")) return NM_ACT_STAGE_RETURN_SUCCESS; - s_wired = (NMSettingWired *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_WIRED); - if (s_wired) { - /* Set device MAC address if the connection wants to change it */ - cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired); - nm_device_set_hw_addr (device, cloned_mac, "set", LOGD_DEVICE); - } + if (!nm_device_hw_addr_set_cloned (device, nm_device_get_applied_connection (device), FALSE)) + return NM_ACT_STAGE_RETURN_FAILURE; return NM_ACT_STAGE_RETURN_SUCCESS; } diff --git a/src/devices/nm-device-tun.h b/src/devices/nm-device-tun.h index 32dcfd47..d62b0c37 100644 --- a/src/devices/nm-device-tun.h +++ b/src/devices/nm-device-tun.h @@ -23,8 +23,6 @@ #include "nm-device-generic.h" -G_BEGIN_DECLS - #define NM_TYPE_DEVICE_TUN (nm_device_tun_get_type ()) #define NM_DEVICE_TUN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_TUN, NMDeviceTun)) #define NM_DEVICE_TUN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_TUN, NMDeviceTunClass)) @@ -44,6 +42,4 @@ typedef NMDeviceClass NMDeviceTunClass; GType nm_device_tun_get_type (void); -G_END_DECLS - -#endif /* NM_DEVICE_TUN_H */ +#endif /* __NETWORKMANAGER_DEVICE_TUN_H__ */ diff --git a/src/devices/nm-device-veth.c b/src/devices/nm-device-veth.c index ff198a7d..cca86fbe 100644 --- a/src/devices/nm-device-veth.c +++ b/src/devices/nm-device-veth.c @@ -38,23 +38,44 @@ #include "nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceVeth); -G_DEFINE_TYPE (NMDeviceVeth, nm_device_veth, NM_TYPE_DEVICE_ETHERNET) - -#define NM_DEVICE_VETH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_VETH, NMDeviceVethPrivate)) +/*****************************************************************************/ typedef struct { NMDevice *peer; gboolean ever_had_peer; } NMDeviceVethPrivate; -enum { - PROP_0, - PROP_PEER, +struct _NMDeviceVeth { + NMDeviceEthernet parent; + NMDeviceVethPrivate _priv; +}; - LAST_PROP +struct _NMDeviceVethClass { + NMDeviceEthernetClass parent_class; }; -/**************************************************************/ +NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceVeth, + PROP_PEER, +); + +/*****************************************************************************/ + +G_DEFINE_TYPE (NMDeviceVeth, nm_device_veth, NM_TYPE_DEVICE_ETHERNET) + +#define NM_DEVICE_VETH_GET_PRIVATE(self) \ + ({ \ + /* preserve the const-ness of self. Unfortunately, that + * way, @self cannot be a void pointer */ \ + typeof (self) _self = (self); \ + \ + /* Get compiler error if variable is of wrong type */ \ + _nm_unused const NMDeviceVeth *_self2 = (_self); \ + \ + nm_assert (NM_IS_DEVICE_VETH (_self)); \ + &_self->_priv; \ + }) + +/*****************************************************************************/ static void set_peer (NMDeviceVeth *self, NMDevice *peer) @@ -66,7 +87,7 @@ set_peer (NMDeviceVeth *self, NMDevice *peer) priv->peer = peer; g_object_add_weak_pointer (G_OBJECT (peer), (gpointer *) &priv->peer); - g_object_notify (G_OBJECT (self), NM_DEVICE_VETH_PEER); + _notify (self, PROP_PEER); } } @@ -150,8 +171,6 @@ nm_device_veth_class_init (NMDeviceVethClass *klass) GObjectClass *object_class = G_OBJECT_CLASS (klass); NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); - g_type_class_add_private (klass, sizeof (NMDeviceVethPrivate)); - NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_VETH) object_class->get_property = get_property; @@ -159,13 +178,13 @@ nm_device_veth_class_init (NMDeviceVethClass *klass) device_class->can_unmanaged_external_down = can_unmanaged_external_down; - /* properties */ - g_object_class_install_property - (object_class, PROP_PEER, - g_param_spec_string (NM_DEVICE_VETH_PEER, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_PEER] = + g_param_spec_string (NM_DEVICE_VETH_PEER, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), NMDBUS_TYPE_DEVICE_VETH_SKELETON, diff --git a/src/devices/nm-device-veth.h b/src/devices/nm-device-veth.h index c7b8ec3a..53ccf925 100644 --- a/src/devices/nm-device-veth.h +++ b/src/devices/nm-device-veth.h @@ -23,8 +23,6 @@ #include "nm-device-ethernet.h" -G_BEGIN_DECLS - #define NM_TYPE_DEVICE_VETH (nm_device_veth_get_type ()) #define NM_DEVICE_VETH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_VETH, NMDeviceVeth)) #define NM_DEVICE_VETH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_VETH, NMDeviceVethClass)) @@ -34,11 +32,9 @@ G_BEGIN_DECLS #define NM_DEVICE_VETH_PEER "peer" -typedef NMDeviceEthernet NMDeviceVeth; -typedef NMDeviceEthernetClass NMDeviceVethClass; +typedef struct _NMDeviceVeth NMDeviceVeth; +typedef struct _NMDeviceVethClass NMDeviceVethClass; GType nm_device_veth_get_type (void); -G_END_DECLS - -#endif /* NM_DEVICE_VETH_H */ +#endif /* __NETWORKMANAGER_DEVICE_VETH_H__ */ diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c index eb6527de..16edc0d2 100644 --- a/src/devices/nm-device-vlan.c +++ b/src/devices/nm-device-vlan.c @@ -20,15 +20,16 @@ #include "nm-default.h" +#include "nm-device-vlan.h" + #include <sys/socket.h> -#include "nm-device-vlan.h" #include "nm-manager.h" #include "nm-utils.h" #include "NetworkManagerUtils.h" #include "nm-device-private.h" #include "nm-enum-types.h" -#include "nm-connection-provider.h" +#include "nm-settings.h" #include "nm-activation-request.h" #include "nm-ip4-config.h" #include "nm-platform.h" @@ -86,7 +87,6 @@ parent_hwaddr_maybe_changed (NMDevice *parent, { NMDeviceVlan *self = NM_DEVICE_VLAN (user_data); NMConnection *connection; - NMSettingWired *s_wired; const char *new_mac, *old_mac; NMSettingIPConfig *s_ip6; @@ -99,11 +99,8 @@ parent_hwaddr_maybe_changed (NMDevice *parent, return; /* Update the VLAN MAC only if configuration does not specify one */ - s_wired = nm_connection_get_setting_wired (connection); - if (s_wired) { - if (nm_setting_wired_get_cloned_mac_address (s_wired)) - return; - } + if (nm_device_hw_addr_is_explict (self)) + return; old_mac = nm_device_get_hw_address (self); new_mac = nm_device_get_hw_address (parent); @@ -113,7 +110,7 @@ parent_hwaddr_maybe_changed (NMDevice *parent, _LOGD (LOGD_VLAN, "parent hardware address changed to %s%s%s", NM_PRINT_FMT_QUOTE_STRING (new_mac)); if (new_mac) { - nm_device_set_hw_addr (self, new_mac, "set", LOGD_VLAN); + nm_device_hw_addr_set (self, new_mac, "vlan-parent"); /* When changing the hw address the interface is taken down, * removing the IPv6 configuration; reapply it. */ @@ -377,21 +374,25 @@ match_parent (NMDeviceVlan *self, const char *parent) static gboolean match_hwaddr (NMDevice *device, NMConnection *connection, gboolean fail_if_no_hwaddr) { - NMSettingWired *s_wired; - const char *setting_mac; - const char *device_mac; + NMDeviceVlanPrivate *priv; + NMSettingWired *s_wired; + const char *setting_mac; + const char *parent_mac; - s_wired = nm_connection_get_setting_wired (connection); - if (!s_wired) - return !fail_if_no_hwaddr; + s_wired = nm_connection_get_setting_wired (connection); + if (!s_wired) + return !fail_if_no_hwaddr; - setting_mac = nm_setting_wired_get_mac_address (s_wired); - if (!setting_mac) - return !fail_if_no_hwaddr; + setting_mac = nm_setting_wired_get_mac_address (s_wired); + if (!setting_mac) + return !fail_if_no_hwaddr; - device_mac = nm_device_get_hw_address (device); + priv = NM_DEVICE_VLAN_GET_PRIVATE (device); + if (!priv->parent) + return !fail_if_no_hwaddr; - return nm_utils_hwaddr_matches (setting_mac, -1, device_mac, -1); + parent_mac = nm_device_get_permanent_hw_address (priv->parent, FALSE); + return parent_mac && nm_utils_hwaddr_matches (setting_mac, -1, parent_mac, -1); } static gboolean @@ -515,7 +516,7 @@ update_connection (NMDevice *device, NMConnection *connection) NMConnection *parent_connection; /* Don't change a parent specified by UUID if it's still valid */ - parent_connection = nm_connection_provider_get_connection_by_uuid (nm_connection_provider_get (), setting_parent); + parent_connection = (NMConnection *) nm_settings_get_connection_by_uuid (nm_device_get_settings (device), setting_parent); if (parent_connection && nm_device_check_connection_compatible (priv->parent, parent_connection)) new_parent = NULL; } @@ -549,8 +550,6 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) { NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (dev); NMSettingVlan *s_vlan; - NMSettingWired *s_wired; - const char *cloned_mac; NMActStageReturn ret; g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); @@ -559,12 +558,8 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) if (ret != NM_ACT_STAGE_RETURN_SUCCESS) return ret; - s_wired = (NMSettingWired *) nm_device_get_applied_setting (dev, NM_TYPE_SETTING_WIRED); - if (s_wired) { - /* Set device MAC address if the connection wants to change it */ - cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired); - nm_device_set_hw_addr (dev, cloned_mac, "set", LOGD_VLAN); - } + if (!nm_device_hw_addr_set_cloned (dev, nm_device_get_applied_connection (dev), FALSE)) + return NM_ACT_STAGE_RETURN_FAILURE; /* Change MAC address to parent's one if needed */ if (priv->parent) @@ -618,14 +613,6 @@ ip4_config_pre_commit (NMDevice *device, NMIP4Config *config) } } -static void -deactivate (NMDevice *device) -{ - /* Reset MAC address back to initial address */ - if (nm_device_get_initial_hw_address (device)) - nm_device_set_hw_addr (device, nm_device_get_initial_hw_address (device), "reset", LOGD_VLAN); -} - /******************************************************************/ static void @@ -689,7 +676,6 @@ nm_device_vlan_class_init (NMDeviceVlanClass *klass) parent_class->bring_up = bring_up; parent_class->act_stage1_prepare = act_stage1_prepare; parent_class->ip4_config_pre_commit = ip4_config_pre_commit; - parent_class->deactivate = deactivate; parent_class->is_available = is_available; parent_class->notify_new_device_added = notify_new_device_added; diff --git a/src/devices/nm-device-vlan.h b/src/devices/nm-device-vlan.h index e31e171d..71ca8030 100644 --- a/src/devices/nm-device-vlan.h +++ b/src/devices/nm-device-vlan.h @@ -23,8 +23,6 @@ #include "nm-device.h" -G_BEGIN_DECLS - #define NM_TYPE_DEVICE_VLAN (nm_device_vlan_get_type ()) #define NM_DEVICE_VLAN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_VLAN, NMDeviceVlan)) #define NM_DEVICE_VLAN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_VLAN, NMDeviceVlanClass)) @@ -47,6 +45,4 @@ typedef NMDeviceClass NMDeviceVlanClass; GType nm_device_vlan_get_type (void); -G_END_DECLS - -#endif /* NM_DEVICE_VLAN_H */ +#endif /* __NETWORKMANAGER_DEVICE_VLAN_H__ */ diff --git a/src/devices/nm-device-vxlan.c b/src/devices/nm-device-vxlan.c index 45f33bdd..674c2a78 100644 --- a/src/devices/nm-device-vxlan.c +++ b/src/devices/nm-device-vxlan.c @@ -20,9 +20,10 @@ #include "nm-default.h" +#include "nm-device-vxlan.h" + #include <string.h> -#include "nm-device-vxlan.h" #include "nm-device-private.h" #include "nm-manager.h" #include "nm-platform.h" @@ -30,7 +31,7 @@ #include "nm-device-factory.h" #include "nm-setting-vxlan.h" #include "nm-setting-wired.h" -#include "nm-connection-provider.h" +#include "nm-settings.h" #include "nm-activation-request.h" #include "nm-ip4-config.h" @@ -417,8 +418,8 @@ update_connection (NMDevice *device, NMConnection *connection) NMConnection *parent_connection; /* Don't change a parent specified by UUID if it's still valid */ - parent_connection = nm_connection_provider_get_connection_by_uuid (nm_connection_provider_get (), - setting_parent); + parent_connection = (NMConnection *) nm_settings_get_connection_by_uuid (nm_device_get_settings (device), + setting_parent); if (parent_connection && nm_device_check_connection_compatible (parent, parent_connection)) new_parent = NULL; } @@ -510,8 +511,6 @@ update_connection (NMDevice *device, NMConnection *connection) static NMActStageReturn act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) { - NMSettingWired *s_wired; - const char *cloned_mac; NMActStageReturn ret; g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); @@ -520,12 +519,8 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) if (ret != NM_ACT_STAGE_RETURN_SUCCESS) return ret; - s_wired = (NMSettingWired *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_WIRED); - if (s_wired) { - /* Set device MAC address if the connection wants to change it */ - cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired); - nm_device_set_hw_addr (device, cloned_mac, "set", LOGD_DEVICE); - } + if (!nm_device_hw_addr_set_cloned (device, nm_device_get_applied_connection (device), FALSE)) + return NM_ACT_STAGE_RETURN_FAILURE; return NM_ACT_STAGE_RETURN_SUCCESS; } diff --git a/src/devices/nm-device-vxlan.h b/src/devices/nm-device-vxlan.h index 7de04a12..71204d3b 100644 --- a/src/devices/nm-device-vxlan.h +++ b/src/devices/nm-device-vxlan.h @@ -23,8 +23,6 @@ #include "nm-device-generic.h" -G_BEGIN_DECLS - #define NM_TYPE_DEVICE_VXLAN (nm_device_vxlan_get_type ()) #define NM_DEVICE_VXLAN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_VXLAN, NMDeviceVxlan)) #define NM_DEVICE_VXLAN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_VXLAN, NMDeviceVxlanClass)) @@ -54,6 +52,4 @@ typedef NMDeviceClass NMDeviceVxlanClass; GType nm_device_vxlan_get_type (void); -G_END_DECLS - -#endif /* NM_DEVICE_VXLAN_H */ +#endif /* __NETWORKMANAGER_DEVICE_VXLAN_H__ */ diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 62259bc4..199acc66 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -21,6 +21,8 @@ #include "nm-default.h" +#include "nm-device.h" + #include <netinet/in.h> #include <string.h> #include <unistd.h> @@ -52,7 +54,7 @@ #include "nm-firewall-manager.h" #include "nm-enum-types.h" #include "nm-settings-connection.h" -#include "nm-connection-provider.h" +#include "nm-settings.h" #include "nm-auth-utils.h" #include "nm-dispatcher.h" #include "nm-config.h" @@ -69,10 +71,22 @@ _LOG_DECLARE_SELF (NMDevice); #include "nmdbus-device.h" +#include "nmdbus-device-statistics.h" G_DEFINE_ABSTRACT_TYPE (NMDevice, nm_device, NM_TYPE_EXPORTED_OBJECT) -#define NM_DEVICE_GET_PRIVATE(o) ((o)->priv) +#define NM_DEVICE_GET_PRIVATE(self) \ + ({ \ + /* preserve the const-ness of self. Unfortunately, that + * way, @self cannot be a void pointer */ \ + typeof (self) _self = (self); \ + \ + /* Get compiler error if variable is of wrong type */ \ + _nm_unused const NMDevice *_self2 = (_self); \ + \ + nm_assert (NM_IS_DEVICE (_self)); \ + _self->priv; \ + }) enum { STATE_CHANGED, @@ -119,11 +133,15 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDevice, PROP_IS_MASTER, PROP_MASTER, PROP_HW_ADDRESS, + PROP_PERM_HW_ADDRESS, PROP_HAS_PENDING_ACTION, PROP_METERED, PROP_LLDP_NEIGHBORS, PROP_REAL, PROP_SLAVES, + PROP_REFRESH_RATE_MS, + PROP_TX_BYTES, + PROP_RX_BYTES, ); #define DEFAULT_AUTOCONNECT TRUE @@ -134,6 +152,9 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDevice, #define PENDING_ACTION_DHCP6 "dhcp6" #define PENDING_ACTION_AUTOCONF6 "autoconf6" +#define DHCP_RESTART_TIMEOUT 120 +#define DHCP_NUM_TRIES_MAX 3 + typedef void (*ActivationHandleFunc) (NMDevice *self); typedef struct { @@ -142,9 +163,9 @@ typedef struct { } ActivationHandleData; typedef enum { - CLEANUP_TYPE_DECONFIGURE, CLEANUP_TYPE_KEEP, CLEANUP_TYPE_REMOVED, + CLEANUP_TYPE_DECONFIGURE, } CleanupType; typedef enum { @@ -163,9 +184,9 @@ typedef struct { typedef struct { NMDevice *slave; - gboolean slave_is_enslaved; - gboolean configure; gulong watch_id; + bool slave_is_enslaved; + bool configure; } SlaveInfo; typedef struct { @@ -192,8 +213,15 @@ typedef struct { NMIP4Config **configs; } ArpingData; +typedef enum { + HW_ADDR_TYPE_UNSET = 0, + HW_ADDR_TYPE_PERMANENT, + HW_ADDR_TYPE_EXPLICIT, + HW_ADDR_TYPE_GENERATED, +} HwAddrType; + typedef struct _NMDevicePrivate { - gboolean in_state_changed; + bool in_state_changed; guint device_link_changed_id; guint device_ip_link_changed_id; @@ -209,7 +237,12 @@ typedef struct _NMDevicePrivate { char * udi; char * iface; /* may change, could be renamed by user */ int ifindex; - gboolean real; + + guint hw_addr_len; + guint8 /*HwAddrType*/ hw_addr_type; + + bool real; + char * ip_iface; int ip_ifindex; NMDeviceType type; @@ -221,19 +254,19 @@ typedef struct _NMDevicePrivate { char * driver_version; char * firmware_version; RfKillType rfkill_type; - gboolean firmware_missing; - gboolean nm_plugin_missing; + bool firmware_missing:1; + bool nm_plugin_missing:1; + bool hw_addr_perm_fake:1; /* whether the permanent HW address could not be read and is a fake */ GHashTable * available_connections; char * hw_addr; - guint hw_addr_len; - char * perm_hw_addr; - char * initial_hw_addr; + char * hw_addr_perm; + char * hw_addr_initial; char * physical_port_id; guint dev_id; NMUnmanagedFlags unmanaged_mask; NMUnmanagedFlags unmanaged_flags; - gboolean is_nm_owned; /* whether the device is a device owned and created by NM */ + bool is_nm_owned; /* whether the device is a device owned and created by NM */ DeleteOnDeactivateData *delete_on_deactivate_data; /* data for scheduled cleanup when deleting link (g_idle_add) */ GCancellable *deactivating_cancellable; @@ -241,7 +274,7 @@ typedef struct _NMDevicePrivate { guint32 ip4_address; NMActRequest * queued_act_request; - gboolean queued_act_request_is_waiting_for_carrier; + bool queued_act_request_is_waiting_for_carrier; NMActRequest * act_request; ActivationHandleData act_handle4; /* for layer2 and IPv4. */ ActivationHandleData act_handle6; @@ -261,11 +294,12 @@ typedef struct _NMDevicePrivate { guint link_connected_id; guint link_disconnected_id; guint carrier_defer_id; - gboolean carrier; + bool carrier; guint carrier_wait_id; - gboolean ignore_carrier; + bool ignore_carrier; + gulong ignore_carrier_id; guint32 mtu; - gboolean up; /* IFF_UP */ + bool up; /* IFF_UP */ /* Generic DHCP stuff */ guint32 dhcp_timeout; @@ -288,14 +322,17 @@ typedef struct _NMDevicePrivate { NMPlatformIP6Route v6; } default_route; - gboolean v4_commit_first_time; - gboolean v6_commit_first_time; + bool v4_commit_first_time; + bool v6_commit_first_time; /* DHCPv4 tracking */ - NMDhcpClient * dhcp4_client; - gulong dhcp4_state_sigid; - NMDhcp4Config * dhcp4_config; - guint dhcp4_restart_id; + struct { + NMDhcpClient * client; + gulong state_sigid; + NMDhcp4Config * config; + guint restart_id; + guint num_tries_left; + } dhcp4; PingInfo gw_ping; @@ -304,7 +341,7 @@ typedef struct _NMDevicePrivate { gulong dnsmasq_state_id; /* Firewall */ - gboolean fw_ready; + bool fw_ready; NMFirewallManagerCallId fw_call; /* IPv4LL stuff */ @@ -325,8 +362,9 @@ typedef struct _NMDevicePrivate { NMIP6Config * ext_ip6_config; /* Stuff added outside NM */ NMIP6Config * ext_ip6_config_captured; /* Configuration captured from platform. */ GSList * vpn6_configs; /* VPNs which use this device */ - gboolean nm_ipv6ll; /* TRUE if NM handles the device's IPv6LL address */ + bool nm_ipv6ll; /* TRUE if NM handles the device's IPv6LL address */ guint32 ip6_mtu; + NMIP6Config * dad6_ip6_config; NMRDisc * rdisc; gulong rdisc_changed_id; @@ -340,35 +378,47 @@ typedef struct _NMDevicePrivate { GHashTable * ip6_saved_properties; - NMDhcpClient * dhcp6_client; - NMRDiscDHCPLevel dhcp6_mode; - gulong dhcp6_state_sigid; - NMDhcp6Config * dhcp6_config; - /* IP6 config from DHCP */ - NMIP6Config * dhcp6_ip6_config; - /* Event ID of the current IP6 config from DHCP */ - char * dhcp6_event_id; - guint dhcp6_restart_id; + struct { + NMDhcpClient * client; + NMRDiscDHCPLevel mode; + gulong state_sigid; + NMDhcp6Config * config; + /* IP6 config from DHCP */ + NMIP6Config * ip6_config; + /* Event ID of the current IP6 config from DHCP */ + char * event_id; + guint restart_id; + guint num_tries_left; + } dhcp6; /* allow autoconnect feature */ - gboolean autoconnect; + bool autoconnect; /* master interface for bridge/bond/team slave */ NMDevice * master; - gboolean is_enslaved; - gboolean master_ready_handled; + bool is_enslaved; + bool master_ready_handled; gulong master_ready_id; /* slave management */ - gboolean is_master; + bool is_master; GSList * slaves; /* list of SlaveInfo */ NMMetered metered; - NMConnectionProvider *con_provider; + NMSettings *settings; + NMLldpListener *lldp_listener; guint check_delete_unrealized_id; + + struct { + guint timeout_id; + guint refresh_rate_ms; + guint64 tx_bytes; + guint64 rx_bytes; + } stats; + } NMDevicePrivate; static gboolean nm_device_set_ip4_config (NMDevice *self, @@ -417,6 +467,8 @@ static gboolean dhcp6_start (NMDevice *self, gboolean wait_for_ll, NMDeviceState 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); +static void dhcp_schedule_restart (NMDevice *self, int family, const char *reason); +static void _cancel_activation (NMDevice *self); /***********************************************************/ @@ -524,6 +576,12 @@ NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_reason_to_string, NMDeviceStateReason, /***********************************************************/ +NMSettings * +nm_device_get_settings (NMDevice *self) +{ + return NM_DEVICE_GET_PRIVATE (self)->settings; +} + static void init_ip4_config_dns_priority (NMDevice *self, NMIP4Config *config) { @@ -570,6 +628,41 @@ nm_device_has_capability (NMDevice *self, NMDeviceCapabilities caps) return NM_FLAGS_ANY (NM_DEVICE_GET_PRIVATE (self)->capabilities, caps); } +static void +_add_capabilities (NMDevice *self, NMDeviceCapabilities capabilities) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + if (!NM_FLAGS_ALL (priv->capabilities, capabilities)) { + priv->capabilities |= capabilities; + _notify (self, PROP_CAPABILITIES); + } +} + +/***********************************************************/ + +static const char * +_get_stable_id (NMConnection *connection, NMUtilsStableType *out_stable_type) +{ + NMSettingConnection *s_con; + const char *stable_id; + + nm_assert (NM_IS_CONNECTION (connection)); + nm_assert (out_stable_type); + + s_con = nm_connection_get_setting_connection (connection); + g_return_val_if_fail (s_con, NULL); + + stable_id = nm_setting_connection_get_stable_id (s_con); + if (!stable_id) { + *out_stable_type = NM_UTILS_STABLE_TYPE_UUID; + return nm_connection_get_uuid (connection); + } + + *out_stable_type = NM_UTILS_STABLE_TYPE_STABLE_ID; + return stable_id; +} + /***********************************************************/ const char * @@ -688,43 +781,175 @@ nm_device_set_ip_iface (NMDevice *self, const char *iface) g_free (old_ip_iface); } +/*****************************************************************************/ + +static void +_stats_update_counters (NMDevice *self, + guint64 tx_bytes, + guint64 rx_bytes) +{ + NMDevicePrivate *priv; + + priv = NM_DEVICE_GET_PRIVATE (self); + + if (priv->stats.tx_bytes != tx_bytes) { + priv->stats.tx_bytes = tx_bytes; + _notify (self, PROP_TX_BYTES); + } + if (priv->stats.rx_bytes != rx_bytes) { + priv->stats.rx_bytes = rx_bytes; + _notify (self, PROP_RX_BYTES); + } +} + +static void +_stats_update_counters_from_pllink (NMDevice *self, const NMPlatformLink *pllink) +{ + _stats_update_counters (self, pllink->tx_bytes, pllink->rx_bytes); +} + +static gboolean +_stats_timeout_cb (gpointer user_data) +{ + NMDevice *self = user_data; + int ifindex; + + ifindex = nm_device_get_ip_ifindex (self); + + _LOGT (LOGD_DEVICE, "stats: refresh %d", ifindex); + + if (ifindex > 0) + nm_platform_link_refresh (NM_PLATFORM_GET, ifindex); + + return G_SOURCE_CONTINUE; +} + +static guint +_stats_refresh_rate_real (guint refresh_rate_ms) +{ + const guint STATS_REFRESH_RATE_MS_MIN = 200; + + if (refresh_rate_ms == 0) + return 0; + + if (refresh_rate_ms < STATS_REFRESH_RATE_MS_MIN) { + /* you cannot set the refresh-rate arbitrarly small. E.g. + * setting to 1ms is just killing. Have a lowest number. */ + return STATS_REFRESH_RATE_MS_MIN; + } + + return refresh_rate_ms; +} + +static void +_stats_set_refresh_rate (NMDevice *self, guint refresh_rate_ms) +{ + NMDevicePrivate *priv; + int ifindex; + guint old_rate; + + priv = NM_DEVICE_GET_PRIVATE (self); + + if (priv->stats.refresh_rate_ms == refresh_rate_ms) + return; + + old_rate = priv->stats.refresh_rate_ms; + priv->stats.refresh_rate_ms = refresh_rate_ms; + _notify (self, PROP_REFRESH_RATE_MS); + + _LOGD (LOGD_DEVICE, "stats: set refresh to %u ms", priv->stats.refresh_rate_ms); + + if (!nm_device_is_real (self)) + return; + + refresh_rate_ms = _stats_refresh_rate_real (refresh_rate_ms); + if (_stats_refresh_rate_real (old_rate) == refresh_rate_ms) + return; + + nm_clear_g_source (&priv->stats.timeout_id); + + if (!refresh_rate_ms) + return; + + /* trigger an inital refresh of the data whenever the refresh-rate changes. + * As we process the result in an idle handler with device_link_changed(), + * we don't get the result right away. */ + ifindex = nm_device_get_ip_ifindex (self); + if (ifindex > 0) + nm_platform_link_refresh (NM_PLATFORM_GET, ifindex); + + priv->stats.timeout_id = g_timeout_add (refresh_rate_ms, _stats_timeout_cb, self); +} + +/*****************************************************************************/ + static gboolean get_ip_iface_identifier (NMDevice *self, NMUtilsIPv6IfaceId *out_iid) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMLinkType link_type; - const guint8 *hwaddr = NULL; - size_t hwaddr_len = 0; + const NMPlatformLink *pllink; int ifindex; gboolean success; /* If we get here, we *must* have a kernel netdev, which implies an ifindex */ ifindex = nm_device_get_ip_ifindex (self); - g_assert (ifindex); + g_return_val_if_fail (ifindex > 0, FALSE); - link_type = nm_platform_link_get_type (NM_PLATFORM_GET, ifindex); - g_return_val_if_fail (link_type > NM_LINK_TYPE_UNKNOWN, 0); + pllink = nm_platform_link_get (NM_PLATFORM_GET, ifindex); + if ( !pllink + || NM_IN_SET (pllink->type, NM_LINK_TYPE_NONE, NM_LINK_TYPE_UNKNOWN)) + return FALSE; - hwaddr = nm_platform_link_get_address (NM_PLATFORM_GET, ifindex, &hwaddr_len); - if (!hwaddr_len) + if (pllink->addr.len <= 0) return FALSE; + if (pllink->addr.len > NM_UTILS_HWADDR_LEN_MAX) + g_return_val_if_reached (FALSE); - success = nm_utils_get_ipv6_interface_identifier (link_type, - hwaddr, - hwaddr_len, + success = nm_utils_get_ipv6_interface_identifier (pllink->type, + pllink->addr.data, + pllink->addr.len, priv->dev_id, out_iid); if (!success) { _LOGW (LOGD_HW, "failed to generate interface identifier " - "for link type %u hwaddr_len %zu", link_type, hwaddr_len); + "for link type %u hwaddr_len %u", pllink->type, (unsigned) pllink->addr.len); } return success; } +/** + * nm_device_get_ip_iface_identifier: + * @self: an #NMDevice + * @iid: where to place the interface identifier + * @ignore_token: force creation of a non-tokenized address + * + * Return the interface's identifier for the EUI64 address generation mode. + * It's either a manually set token or and identifier generated in a + * hardware-specific way. + * + * Unless @ignore_token is set the token is preferred. That is the case + * for link-local addresses (to mimic kernel behavior). + * + * Returns: #TRUE if the @iid could be set + */ static gboolean -nm_device_get_ip_iface_identifier (NMDevice *self, NMUtilsIPv6IfaceId *iid) +nm_device_get_ip_iface_identifier (NMDevice *self, NMUtilsIPv6IfaceId *iid, gboolean ignore_token) { - return NM_DEVICE_GET_CLASS (self)->get_ip_iface_identifier (self, iid); + NMSettingIP6Config *s_ip6; + const char *token = NULL; + + g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + + if (!ignore_token) { + s_ip6 = (NMSettingIP6Config *) + nm_device_get_applied_setting (self, NM_TYPE_SETTING_IP6_CONFIG); + g_return_val_if_fail (s_ip6, FALSE); + token = nm_setting_ip6_config_get_token (s_ip6); + } + if (token) + return nm_utils_ipv6_interface_identifier_get_from_token (iid, token); + else + return NM_DEVICE_GET_CLASS (self)->get_ip_iface_identifier (self, iid); } const char * @@ -1029,7 +1254,11 @@ nm_device_get_settings_connection (NMDevice *self) NMConnection * nm_device_get_applied_connection (NMDevice *self) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMDevicePrivate *priv; + + g_return_val_if_fail (NM_IS_DEVICE (self), NULL); + + priv = NM_DEVICE_GET_PRIVATE (self); return priv->act_request ? nm_act_request_get_applied_connection (priv->act_request) : NULL; } @@ -1046,23 +1275,12 @@ nm_device_has_unmodified_applied_connection (NMDevice *self, NMSettingCompareFla } NMSetting * -nm_device_get_applied_setting (NMDevice *device, GType setting_type) +nm_device_get_applied_setting (NMDevice *self, GType setting_type) { - NMActRequest *req; - NMSetting *setting = NULL; - - g_return_val_if_fail (NM_IS_DEVICE (device), NULL); - - req = nm_device_get_act_request (device); - if (req) { - NMConnection *connection; - - connection = nm_act_request_get_applied_connection (req); - if (connection) - setting = nm_connection_get_setting (connection, setting_type); - } + NMConnection *connection; - return setting; + connection = nm_device_get_applied_connection (self); + return connection ? nm_connection_get_setting (connection, setting_type) : NULL; } RfKillType @@ -1355,7 +1573,7 @@ nm_device_update_dynamic_ip_setup (NMDevice *self) g_hash_table_remove_all (priv->ip6_saved_properties); - if (priv->dhcp4_client) { + if (priv->dhcp4.client) { if (!nm_device_dhcp4_renew (self, FALSE)) { nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, @@ -1363,7 +1581,7 @@ nm_device_update_dynamic_ip_setup (NMDevice *self) return; } } - if (priv->dhcp6_client) { + if (priv->dhcp6.client) { if (!nm_device_dhcp6_renew (self, FALSE)) { nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, @@ -1467,8 +1685,6 @@ link_disconnect_action_cb (gpointer user_data) priv->carrier_defer_id = 0; - _LOGI (LOGD_DEVICE, "link disconnected (calling deferred action)"); - NM_DEVICE_GET_CLASS (self)->carrier_changed (self, FALSE); return FALSE; @@ -1508,11 +1724,11 @@ nm_device_set_carrier (NMDevice *self, gboolean carrier) nm_device_remove_pending_action (self, "carrier wait", TRUE); _carrier_wait_check_queued_act_request (self); } - } else if (state <= NM_DEVICE_STATE_DISCONNECTED) { - _LOGI (LOGD_DEVICE, "link disconnected"); + } else if ( state <= NM_DEVICE_STATE_DISCONNECTED + && !priv->queued_act_request) { + _LOGD (LOGD_DEVICE, "link disconnected"); klass->carrier_changed (self, FALSE); } else { - _LOGI (LOGD_DEVICE, "link disconnected (deferring action for %d seconds)", LINK_DISCONNECT_DELAY); priv->carrier_defer_id = g_timeout_add_seconds (LINK_DISCONNECT_DELAY, link_disconnect_action_cb, self); _LOGD (LOGD_DEVICE, "link disconnected (deferring action for %d seconds) (id=%u)", @@ -1563,13 +1779,14 @@ device_link_changed (NMDevice *self) { NMDeviceClass *klass = NM_DEVICE_GET_CLASS (self); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMUtilsIPv6IfaceId token_iid; gboolean ip_ifname_changed = FALSE; const char *udi; NMPlatformLink info; const NMPlatformLink *pllink; int ifindex; gboolean was_up; + gboolean update_unmanaged_specs = FALSE; + gboolean got_hw_addr = FALSE, had_hw_addr; priv->device_link_changed_id = 0; @@ -1607,6 +1824,14 @@ device_link_changed (NMDevice *self) _notify (self, PROP_DRIVER); } + if (ifindex == nm_device_get_ip_ifindex (self)) + _stats_update_counters_from_pllink (self, &info); + + had_hw_addr = (priv->hw_addr != NULL); + nm_device_update_hw_address (self); + got_hw_addr = (!had_hw_addr && priv->hw_addr); + nm_device_update_permanent_hw_address (self); + if (info.name[0] && strcmp (priv->iface, info.name) != 0) { _LOGI (LOGD_DEVICE, "interface index %d renamed iface from '%s' to '%s'", priv->ifindex, priv->iface, info.name); @@ -1616,6 +1841,11 @@ device_link_changed (NMDevice *self) /* If the device has no explicit ip_iface, then changing iface changes ip_iface too. */ ip_ifname_changed = !priv->ip_iface; + if (nm_device_get_unmanaged_flags (self, NM_UNMANAGED_PLATFORM_INIT)) + nm_device_set_unmanaged_by_user_settings (self, nm_settings_get_unmanaged_specs (priv->settings)); + else + update_unmanaged_specs = TRUE; + _notify (self, PROP_IFACE); if (ip_ifname_changed) _notify (self, PROP_IP_IFACE); @@ -1629,10 +1859,11 @@ device_link_changed (NMDevice *self) nm_device_emit_recheck_auto_activate (self); } - if (priv->rdisc && nm_platform_link_get_ipv6_token (NM_PLATFORM_GET, priv->ifindex, &token_iid)) { - _LOGD (LOGD_DEVICE, "IPv6 tokenized identifier present on device %s", priv->iface); - if (nm_rdisc_set_iid (priv->rdisc, token_iid)) + if (priv->rdisc && info.inet6_token.id) { + if (nm_rdisc_set_iid (priv->rdisc, info.inet6_token)) { + _LOGD (LOGD_DEVICE, "IPv6 tokenized identifier present on device %s", priv->iface); nm_rdisc_start (priv->rdisc); + } } if (klass->link_changed) @@ -1651,18 +1882,23 @@ device_link_changed (NMDevice *self) nm_device_set_unmanaged_by_user_udev (self); + reason = NM_DEVICE_STATE_REASON_NOW_MANAGED; + /* If the device is a external-down candidated but no longer has external * down set, we must clear the platform-unmanaged flag with reason * "assumed". */ if ( nm_device_get_unmanaged_mask (self, NM_UNMANAGED_EXTERNAL_DOWN) && !nm_device_get_unmanaged_flags (self, NM_UNMANAGED_EXTERNAL_DOWN)) { - /* Ensure the assume check is queued before any queued state changes - * from the transition to UNAVAILABLE. - */ - nm_device_queue_recheck_assume (self); - reason = NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED; - } else - reason = NM_DEVICE_STATE_REASON_NOW_MANAGED; + /* actually, user-udev overwrites external-down. So we only assume the device, + * when it is a external-down candidate, which is not managed via udev. */ + if (!nm_device_get_unmanaged_mask (self, NM_UNMANAGED_USER_UDEV)) { + /* Ensure the assume check is queued before any queued state changes + * from the transition to UNAVAILABLE. + */ + nm_device_queue_recheck_assume (self); + reason = NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED; + } + } nm_device_set_unmanaged_by_flags (self, NM_UNMANAGED_PLATFORM_INIT, FALSE, reason); } @@ -1684,6 +1920,23 @@ device_link_changed (NMDevice *self) } } + if (update_unmanaged_specs) + nm_device_set_unmanaged_by_user_settings (self, nm_settings_get_unmanaged_specs (priv->settings)); + + if ( got_hw_addr + && !priv->up + && nm_device_get_state (self) == NM_DEVICE_STATE_UNAVAILABLE) { + /* + * If the device is UNAVAILABLE, any previous try to + * bring it up probably has failed because of the + * invalid hardware address; try again. + */ + nm_device_bring_up (self, TRUE, NULL); + nm_device_queue_recheck_available (self, + NM_DEVICE_STATE_REASON_NONE, + NM_DEVICE_STATE_REASON_NONE); + } + return G_SOURCE_REMOVE; } @@ -1702,6 +1955,8 @@ device_ip_link_changed (NMDevice *self) if (!pllink) return G_SOURCE_REMOVE; + _stats_update_counters_from_pllink (self, pllink); + if (pllink->name[0] && g_strcmp0 (priv->ip_iface, pllink->name)) { _LOGI (LOGD_DEVICE, "interface index %d renamed ip_iface (%d) from '%s' to '%s'", priv->ifindex, nm_device_get_ip_ifindex (self), @@ -1712,6 +1967,7 @@ device_ip_link_changed (NMDevice *self) _notify (self, PROP_IP_IFACE); nm_device_update_dynamic_ip_setup (self); } + return G_SOURCE_REMOVE; } @@ -1817,6 +2073,8 @@ nm_device_realize_start (NMDevice *self, gboolean *out_compatible, GError **error) { + NMPlatformLink plink_copy; + NM_SET_OUT (out_compatible, TRUE); if (plink) { @@ -1831,6 +2089,10 @@ nm_device_realize_start (NMDevice *self, return FALSE; } + if (plink) { + plink_copy = *plink; + plink = &plink_copy; + } realize_start_setup (self, plink); return TRUE; @@ -1962,6 +2224,9 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink) NMDevicePrivate *priv; NMDeviceClass *klass; static guint32 id = 0; + NMDeviceCapabilities capabilities = 0; + NMConfig *config; + guint real_rate; g_return_if_fail (NM_IS_DEVICE (self)); @@ -1985,6 +2250,7 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink) if (plink) { g_return_if_fail (link_type_compatible (self, plink->type, NULL, NULL)); update_device_from_platform_link (self, plink); + _stats_update_counters_from_pllink (self, plink); } if (priv->ifindex > 0) { @@ -1994,7 +2260,7 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink) priv->dev_id = nm_platform_link_get_dev_id (NM_PLATFORM_GET, priv->ifindex); if (nm_platform_link_is_software (NM_PLATFORM_GET, priv->ifindex)) - priv->capabilities |= NM_DEVICE_CAP_IS_SOFTWARE; + capabilities |= NM_DEVICE_CAP_IS_SOFTWARE; priv->mtu = nm_platform_link_get_mtu (NM_PLATFORM_GET, priv->ifindex); _notify (self, PROP_MTU); @@ -2014,7 +2280,9 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink) } if (klass->get_generic_capabilities) - priv->capabilities |= klass->get_generic_capabilities (self); + capabilities |= klass->get_generic_capabilities (self); + + _add_capabilities (self, capabilities); if (!priv->udi) { /* Use a placeholder UDI until we get a real one */ @@ -2028,17 +2296,19 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink) nm_device_update_hw_address (self); nm_device_update_initial_hw_address (self); + nm_device_update_permanent_hw_address (self); /* Note: initial hardware address must be read before calling get_ignore_carrier() */ - if (nm_device_has_capability (self, NM_DEVICE_CAP_CARRIER_DETECT)) { - NMConfig *config = nm_config_get (); - - priv->ignore_carrier = nm_config_data_get_ignore_carrier (nm_config_get_data (config), self); - g_signal_connect (G_OBJECT (config), - NM_CONFIG_SIGNAL_CONFIG_CHANGED, - G_CALLBACK (config_changed_update_ignore_carrier), - self); + config = nm_config_get (); + priv->ignore_carrier = nm_config_data_get_ignore_carrier (nm_config_get_data (config), self); + if (!priv->ignore_carrier_id) { + priv->ignore_carrier_id = g_signal_connect (config, + NM_CONFIG_SIGNAL_CONFIG_CHANGED, + G_CALLBACK (config_changed_update_ignore_carrier), + self); + } + if (nm_device_has_capability (self, NM_DEVICE_CAP_CARRIER_DETECT)) { check_carrier (self); _LOGD (LOGD_HW, "carrier is %s%s", @@ -2049,7 +2319,10 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink) priv->carrier = TRUE; } - _notify (self, PROP_CAPABILITIES); + nm_assert (!priv->stats.timeout_id); + real_rate = _stats_refresh_rate_real (priv->stats.refresh_rate_ms); + if (real_rate) + priv->stats.timeout_id = g_timeout_add (real_rate, _stats_timeout_cb, self); klass->realize_start_notify (self, plink); @@ -2214,6 +2487,7 @@ nm_device_unrealize (NMDevice *self, gboolean remove_resources, GError **error) _notify (self, PROP_UDI); } if (priv->hw_addr) { + priv->hw_addr_len = 0; g_clear_pointer (&priv->hw_addr, g_free); _notify (self, PROP_HW_ADDRESS); } @@ -2222,14 +2496,21 @@ nm_device_unrealize (NMDevice *self, gboolean remove_resources, GError **error) _notify (self, PROP_PHYSICAL_PORT_ID); } - g_clear_pointer (&priv->perm_hw_addr, g_free); - g_clear_pointer (&priv->initial_hw_addr, g_free); + nm_clear_g_source (&priv->stats.timeout_id); + _stats_update_counters (self, 0, 0); + + priv->hw_addr_type = HW_ADDR_TYPE_UNSET; + g_clear_pointer (&priv->hw_addr_perm, g_free); + _notify (self, PROP_PERM_HW_ADDRESS); + g_clear_pointer (&priv->hw_addr_initial, g_free); priv->capabilities = NM_DEVICE_CAP_NM_SUPPORTED; if (NM_DEVICE_GET_CLASS (self)->get_generic_capabilities) priv->capabilities |= NM_DEVICE_GET_CLASS (self)->get_generic_capabilities (self); _notify (self, PROP_CAPABILITIES); + nm_clear_g_signal_handler (nm_config_get (), &priv->ignore_carrier_id); + priv->real = FALSE; _notify (self, PROP_REAL); @@ -2660,6 +2941,8 @@ nm_device_slave_notify_release (NMDevice *self, NMDeviceStateReason reason) nm_connection_get_id (connection), master_status); + /* Cancel any pending activation sources */ + _cancel_activation (self); nm_device_queue_state (self, new_state, reason); } else _LOGI (LOGD_DEVICE, "released from master device %s", nm_device_get_iface (priv->master)); @@ -2999,6 +3282,7 @@ nm_device_generate_connection (NMDevice *self, NMDevice *master) gs_free char *uuid = NULL; const char *ip4_method, *ip6_method; GError *error = NULL; + const NMPlatformLink *pllink; /* If update_connection() is not implemented, just fail. */ if (!klass->update_connection) @@ -3045,6 +3329,15 @@ nm_device_generate_connection (NMDevice *self, NMDevice *master) s_ip6 = nm_ip6_config_create_setting (priv->ip6_config); nm_connection_add_setting (connection, s_ip6); + + pllink = nm_platform_link_get (NM_PLATFORM_GET, priv->ifindex); + if (pllink && pllink->inet6_token.id) { + _LOGD (LOGD_IP6, "IPv6 tokenized identifier present"); + g_object_set (s_ip6, + NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE, NM_IN6_ADDR_GEN_MODE_EUI64, + NM_SETTING_IP6_CONFIG_TOKEN, nm_utils_inet6_interface_identifier_to_token (pllink->inet6_token, NULL), + NULL); + } } klass->update_connection (self, connection); @@ -3202,7 +3495,7 @@ nm_device_check_slave_connection_compatible (NMDevice *self, NMConnection *slave static gboolean nm_device_can_assume_connections (NMDevice *self) { - return !!NM_DEVICE_GET_CLASS (self)->update_connection; + return !!NM_DEVICE_GET_CLASS (self)->update_connection; } /** @@ -3218,7 +3511,7 @@ nm_device_can_assume_connections (NMDevice *self) * if there is no active connection or the active connection cannot be * assumed. */ -gboolean +static gboolean nm_device_can_assume_active_connection (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); @@ -3255,16 +3548,55 @@ nm_device_can_assume_active_connection (NMDevice *self) return FALSE; method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG); - if (!_nm_utils_string_in_list (method, assumable_ip6_methods)) + if (!g_strv_contains (assumable_ip6_methods, method)) return FALSE; method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG); - if (!_nm_utils_string_in_list (method, assumable_ip4_methods)) + if (!g_strv_contains (assumable_ip4_methods, method)) + return FALSE; + + return TRUE; +} + +static gboolean +unmanaged_on_quit (NMDevice *self) +{ + /* 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 (self)) { + /* An assume connection must be left alone */ + return FALSE; + } + + if (!nm_device_get_act_request (self)) { + /* 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. + */ + return FALSE; + } + + if (!nm_platform_link_can_assume (NM_PLATFORM_GET, nm_device_get_ifindex (self))) { + /* The device has no layer 3 configuration. Leave it up. */ + return FALSE; + } + + if (nm_device_can_assume_active_connection (self)) return FALSE; return TRUE; } +gboolean +nm_device_unmanage_on_quit (NMDevice *self) +{ + g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + + return NM_DEVICE_GET_CLASS (self)->unmanaged_on_quit (self); +} + static gboolean nm_device_emit_recheck_assume (gpointer user_data) { @@ -3351,7 +3683,7 @@ dnsmasq_state_changed_cb (NMDnsMasqManager *manager, guint32 status, gpointer us switch (status) { case NM_DNSMASQ_STATUS_DEAD: - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SHARED_START_FAILED); + nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_SHARED_START_FAILED); break; default: break; @@ -3753,15 +4085,21 @@ nm_device_activate_schedule_stage2_device_config (NMDevice *self) if (!priv->master_ready_handled) { NMActiveConnection *active = NM_ACTIVE_CONNECTION (priv->act_request); + NMActiveConnection *master; + + master = nm_active_connection_get_master (active); - if (!nm_active_connection_get_master (active)) { + if (!master) { g_warn_if_fail (!priv->master_ready_id); priv->master_ready_handled = TRUE; } else { /* If the master connection is ready for slaves, attach ourselves */ if (nm_active_connection_get_master_ready (active)) master_ready (self, active); - else { + else if (nm_active_connection_get_state (master) >= NM_ACTIVE_CONNECTION_STATE_DEACTIVATING) { + _LOGD (LOGD_DEVICE, "master connection is deactivating"); + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED); + } else { _LOGD (LOGD_DEVICE, "waiting for master connection to become ready"); if (priv->master_ready_id == 0) { @@ -3815,6 +4153,26 @@ check_ip_failed (NMDevice *self, gboolean may_fail) NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); } +void +nm_device_ip_method_failed (NMDevice *self, int family, NMDeviceStateReason reason) +{ + NMDevicePrivate *priv; + + g_return_if_fail (NM_IS_DEVICE (self)); + g_return_if_fail (family == AF_INET || family == AF_INET6); + priv = NM_DEVICE_GET_PRIVATE (self); + + if (family == AF_INET) + priv->ip4_state = IP_FAIL; + else + priv->ip6_state = IP_FAIL; + + if (get_ip_config_may_fail (self, family)) + check_ip_failed (self, FALSE); + else + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); +} + /* * check_ip_done * @@ -4050,14 +4408,14 @@ ipv4ll_get_ip4_config (NMDevice *self, guint32 lla) memset (&address, 0, sizeof (address)); nm_platform_ip4_address_set_addr (&address, lla, 16); - address.source = NM_IP_CONFIG_SOURCE_IP4LL; + address.addr_source = NM_IP_CONFIG_SOURCE_IP4LL; nm_ip4_config_add_address (config, &address); /* Add a multicast route for link-local connections: destination= 224.0.0.0, netmask=240.0.0.0 */ memset (&route, 0, sizeof (route)); route.network = htonl (0xE0000000L); route.plen = 4; - route.source = NM_IP_CONFIG_SOURCE_IP4LL; + route.rt_source = NM_IP_CONFIG_SOURCE_IP4LL; route.metric = nm_device_get_ip4_route_metric (self); nm_ip4_config_add_route (config, &route); @@ -4094,23 +4452,20 @@ nm_device_handle_ipv4ll_event (sd_ipv4ll *ll, int event, void *data) r = sd_ipv4ll_get_address (ll, &address); if (r < 0) { _LOGE (LOGD_AUTOIP4, "invalid IPv4 link-local address received, error %d.", r); - priv->ip4_state = IP_FAIL; - check_ip_failed (self, FALSE); + nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED); return; } if ((address.s_addr & IPV4LL_NETMASK) != IPV4LL_NETWORK) { _LOGE (LOGD_AUTOIP4, "invalid address %08x received (not link-local).", address.s_addr); - priv->ip4_state = IP_FAIL; - check_ip_failed (self, FALSE); + nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_AUTOIP_ERROR); return; } config = ipv4ll_get_ip4_config (self, address.s_addr); if (config == NULL) { _LOGE (LOGD_AUTOIP4, "failed to get IPv4LL config"); - priv->ip4_state = IP_FAIL; - check_ip_failed (self, FALSE); + nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_AUTOIP_FAILED); return; } @@ -4120,8 +4475,7 @@ nm_device_handle_ipv4ll_event (sd_ipv4ll *ll, int event, void *data) } else if (priv->ip4_state == IP_DONE) { if (!ip4_config_merge_and_apply (self, config, TRUE, NULL)) { _LOGE (LOGD_AUTOIP4, "failed to update IP4 config for autoip change."); - priv->ip4_state = IP_FAIL; - check_ip_failed (self, FALSE); + nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_AUTOIP_FAILED); } } else g_assert_not_reached (); @@ -4130,8 +4484,7 @@ nm_device_handle_ipv4ll_event (sd_ipv4ll *ll, int event, void *data) break; default: _LOGW (LOGD_AUTOIP4, "IPv4LL address no longer valid after event %d.", event); - priv->ip4_state = IP_FAIL; - check_ip_failed (self, FALSE); + nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_AUTOIP_FAILED); } } @@ -4188,9 +4541,9 @@ ipv4ll_start (NMDevice *self, NMDeviceStateReason *reason) goto fail; } - r = sd_ipv4ll_set_index (priv->ipv4ll, ifindex); + r = sd_ipv4ll_set_ifindex (priv->ipv4ll, ifindex); if (r < 0) { - _LOGE (LOGD_AUTOIP4, "IPv4LL: set_index() failed with error %d", r); + _LOGE (LOGD_AUTOIP4, "IPv4LL: set_ifindex() failed with error %d", r); goto fail; } @@ -4325,23 +4678,23 @@ dhcp4_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - nm_clear_g_source (&priv->dhcp4_restart_id); + nm_clear_g_source (&priv->dhcp4.restart_id); - if (priv->dhcp4_client) { + if (priv->dhcp4.client) { /* Stop any ongoing DHCP transaction on this device */ - nm_clear_g_signal_handler (priv->dhcp4_client, &priv->dhcp4_state_sigid); + nm_clear_g_signal_handler (priv->dhcp4.client, &priv->dhcp4.state_sigid); nm_device_remove_pending_action (self, PENDING_ACTION_DHCP4, FALSE); if ( cleanup_type == CLEANUP_TYPE_DECONFIGURE || cleanup_type == CLEANUP_TYPE_REMOVED) - nm_dhcp_client_stop (priv->dhcp4_client, release); + nm_dhcp_client_stop (priv->dhcp4.client, release); - g_clear_object (&priv->dhcp4_client); + g_clear_object (&priv->dhcp4.client); } - if (priv->dhcp4_config) { - nm_exported_object_clear_and_unexport (&priv->dhcp4_config); + if (priv->dhcp4.config) { + nm_exported_object_clear_and_unexport (&priv->dhcp4.config); _notify (self, PROP_DHCP4_CONFIG); } } @@ -4495,7 +4848,7 @@ ip4_config_merge_and_apply (NMDevice *self, priv->default_route.v4_has = TRUE; memset (&priv->default_route.v4, 0, sizeof (priv->default_route.v4)); - priv->default_route.v4.source = NM_IP_CONFIG_SOURCE_USER; + priv->default_route.v4.rt_source = NM_IP_CONFIG_SOURCE_USER; priv->default_route.v4.gateway = gateway; priv->default_route.v4.metric = default_route_metric; priv->default_route.v4.mss = nm_ip4_config_get_mss (composite); @@ -4541,28 +4894,30 @@ END_ADD_DEFAULT_ROUTE: return success; } -static void +static gboolean dhcp4_lease_change (NMDevice *self, NMIP4Config *config) { NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; - g_return_if_fail (config != NULL); + g_return_val_if_fail (config != NULL, FALSE); if (!ip4_config_merge_and_apply (self, config, TRUE, &reason)) { _LOGW (LOGD_DHCP4, "failed to update IPv4 config for DHCP change."); - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); - } else { - /* Notify dispatcher scripts of new DHCP4 config */ - nm_dispatcher_call (DISPATCHER_ACTION_DHCP4_CHANGE, - nm_device_get_settings_connection (self), - nm_device_get_applied_connection (self), - self, - NULL, - NULL, - NULL); - - nm_device_remove_pending_action (self, PENDING_ACTION_DHCP4, FALSE); + return FALSE; } + + /* Notify dispatcher scripts of new DHCP4 config */ + nm_dispatcher_call (DISPATCHER_ACTION_DHCP4_CHANGE, + nm_device_get_settings_connection (self), + nm_device_get_applied_connection (self), + self, + NULL, + NULL, + NULL); + + nm_device_remove_pending_action (self, PENDING_ACTION_DHCP4, FALSE); + + return TRUE; } static gboolean @@ -4576,11 +4931,11 @@ dhcp4_restart_cb (gpointer user_data) g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); priv = NM_DEVICE_GET_PRIVATE (self); - priv->dhcp4_restart_id = 0; + priv->dhcp4.restart_id = 0; connection = nm_device_get_applied_connection (self); if (dhcp4_start (self, connection, &reason) == NM_ACT_STAGE_RETURN_FAILURE) - priv->dhcp4_restart_id = g_timeout_add_seconds (120, dhcp4_restart_cb, self); + dhcp_schedule_restart (self, AF_INET, NULL); return FALSE; } @@ -4590,6 +4945,9 @@ dhcp4_fail (NMDevice *self, gboolean timeout) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + _LOGD (LOGD_DHCP4, "DHCPv4 failed: timeout %d, num tries left %u", + timeout, priv->dhcp4.num_tries_left); + dhcp4_cleanup (self, CLEANUP_TYPE_DECONFIGURE, FALSE); /* Don't fail if there are static addresses configured on @@ -4598,8 +4956,7 @@ dhcp4_fail (NMDevice *self, gboolean timeout) if ( priv->ip4_state == IP_DONE && priv->con_ip4_config && nm_ip4_config_get_num_addresses (priv->con_ip4_config) > 0) { - _LOGI (LOGD_DHCP4, "Scheduling DHCPv4 restart because device has IP addresses"); - priv->dhcp4_restart_id = g_timeout_add_seconds (120, dhcp4_restart_cb, self); + dhcp_schedule_restart (self, AF_INET, "device has IP addresses"); return; } @@ -4608,16 +4965,23 @@ dhcp4_fail (NMDevice *self, gboolean timeout) * retry DHCP again. */ if (nm_device_uses_assumed_connection (self)) { - _LOGI (LOGD_DHCP4, "Scheduling DHCPv4 restart because the connection is assumed"); - priv->dhcp4_restart_id = g_timeout_add_seconds (120, dhcp4_restart_cb, self); + dhcp_schedule_restart (self, AF_INET, "connection is assumed"); return; } - if (timeout || (priv->ip4_state == IP_CONF)) + if ( priv->dhcp4.num_tries_left == DHCP_NUM_TRIES_MAX + && (timeout || (priv->ip4_state == IP_CONF))) nm_device_activate_schedule_ip4_config_timeout (self); - else if (priv->ip4_state == IP_DONE) - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED); - else + else if (priv->ip4_state == IP_DONE) { + /* Don't fail immediately when the lease expires but try to + * restart DHCP for a predefined number of times. + */ + if (priv->dhcp4.num_tries_left) { + priv->dhcp4.num_tries_left--; + dhcp_schedule_restart (self, AF_INET, "lease expired"); + } else + nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED); + } else g_warn_if_reached (); } @@ -4654,14 +5018,13 @@ dhcp4_state_changed (NMDhcpClient *client, case NM_DHCP_STATE_BOUND: if (!ip4_config) { _LOGW (LOGD_DHCP4, "failed to get IPv4 config in response to DHCP event."); - nm_device_state_changed (self, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + dhcp4_fail (self, FALSE); break; } - nm_dhcp4_config_set_options (priv->dhcp4_config, options); + nm_dhcp4_config_set_options (priv->dhcp4.config, options); _notify (self, PROP_DHCP4_CONFIG); + priv->dhcp4.num_tries_left = DHCP_NUM_TRIES_MAX; if (priv->ip4_state == IP_CONF) { connection = nm_device_get_applied_connection (self); @@ -4678,8 +5041,10 @@ dhcp4_state_changed (NMDhcpClient *client, ipv4_dad_start (self, configs, dhcp4_dad_cb); } else if (priv->ip4_state == IP_DONE) { - dhcp4_lease_change (self, ip4_config); - nm_device_update_metered (self); + if (dhcp4_lease_change (self, ip4_config)) + nm_device_update_metered (self); + else + dhcp4_fail (self, FALSE); } break; case NM_DHCP_STATE_TIMEOUT: @@ -4735,8 +5100,8 @@ dhcp4_start (NMDevice *self, s_ip4 = nm_connection_get_setting_ip4_config (connection); /* Clear old exported DHCP options */ - nm_exported_object_clear_and_unexport (&priv->dhcp4_config); - priv->dhcp4_config = nm_dhcp4_config_new (); + nm_exported_object_clear_and_unexport (&priv->dhcp4.config); + priv->dhcp4.config = nm_dhcp4_config_new (); hw_addr = nm_platform_link_get_address (NM_PLATFORM_GET, nm_device_get_ip_ifindex (self), &hw_addr_len); if (hw_addr_len) { @@ -4745,8 +5110,8 @@ dhcp4_start (NMDevice *self, } /* Begin DHCP on the interface */ - g_warn_if_fail (priv->dhcp4_client == NULL); - priv->dhcp4_client = nm_dhcp_manager_start_ip4 (nm_dhcp_manager_get (), + g_warn_if_fail (priv->dhcp4.client == NULL); + priv->dhcp4.client = nm_dhcp_manager_start_ip4 (nm_dhcp_manager_get (), nm_device_get_ip_iface (self), nm_device_get_ip_ifindex (self), tmp, @@ -4763,12 +5128,12 @@ dhcp4_start (NMDevice *self, if (tmp) g_byte_array_free (tmp, TRUE); - if (!priv->dhcp4_client) { + if (!priv->dhcp4.client) { *reason = NM_DEVICE_STATE_REASON_DHCP_START_FAILED; return NM_ACT_STAGE_RETURN_FAILURE; } - priv->dhcp4_state_sigid = g_signal_connect (priv->dhcp4_client, + priv->dhcp4.state_sigid = g_signal_connect (priv->dhcp4.client, NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED, G_CALLBACK (dhcp4_state_changed), self); @@ -4787,7 +5152,7 @@ nm_device_dhcp4_renew (NMDevice *self, gboolean release) NMDeviceStateReason reason; NMConnection *connection; - g_return_val_if_fail (priv->dhcp4_client != NULL, FALSE); + g_return_val_if_fail (priv->dhcp4.client != NULL, FALSE); _LOGI (LOGD_DHCP4, "DHCPv4 lease renewal requested"); @@ -4862,7 +5227,7 @@ shared4_new_config (NMDevice *self, NMConnection *connection, NMDeviceStateReaso } config = nm_ip4_config_new (nm_device_get_ip_ifindex (self)); - address.source = NM_IP_CONFIG_SOURCE_SHARED; + address.addr_source = NM_IP_CONFIG_SOURCE_SHARED; nm_ip4_config_add_address (config, &address); /* Remove the address lock when the object gets disposed */ @@ -4888,7 +5253,7 @@ connection_ip4_method_requires_carrier (NMConnection *connection, if (out_ip4_enabled) *out_ip4_enabled = !!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED); - return _nm_utils_string_in_list (method, ip4_carrier_methods); + return g_strv_contains (ip4_carrier_methods, method); } static gboolean @@ -4905,7 +5270,7 @@ connection_ip6_method_requires_carrier (NMConnection *connection, if (out_ip6_enabled) *out_ip6_enabled = !!strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE); - return _nm_utils_string_in_list (method, ip6_carrier_methods); + return g_strv_contains (ip6_carrier_methods, method); } static gboolean @@ -5013,6 +5378,7 @@ act_stage3_ip4_config_start (NMDevice *self, } method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG); + priv->dhcp4.num_tries_left = DHCP_NUM_TRIES_MAX; /* Start IPv4 addressing based on the method requested */ if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0) @@ -5056,25 +5422,25 @@ dhcp6_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - priv->dhcp6_mode = NM_RDISC_DHCP_LEVEL_NONE; - g_clear_object (&priv->dhcp6_ip6_config); - g_clear_pointer (&priv->dhcp6_event_id, g_free); - nm_clear_g_source (&priv->dhcp6_restart_id); + priv->dhcp6.mode = NM_RDISC_DHCP_LEVEL_NONE; + g_clear_object (&priv->dhcp6.ip6_config); + g_clear_pointer (&priv->dhcp6.event_id, g_free); + nm_clear_g_source (&priv->dhcp6.restart_id); - if (priv->dhcp6_client) { - nm_clear_g_signal_handler (priv->dhcp6_client, &priv->dhcp6_state_sigid); + if (priv->dhcp6.client) { + nm_clear_g_signal_handler (priv->dhcp6.client, &priv->dhcp6.state_sigid); if ( cleanup_type == CLEANUP_TYPE_DECONFIGURE || cleanup_type == CLEANUP_TYPE_REMOVED) - nm_dhcp_client_stop (priv->dhcp6_client, release); + nm_dhcp_client_stop (priv->dhcp6.client, release); - g_clear_object (&priv->dhcp6_client); + g_clear_object (&priv->dhcp6.client); } nm_device_remove_pending_action (self, PENDING_ACTION_DHCP6, FALSE); - if (priv->dhcp6_config) { - nm_exported_object_clear_and_unexport (&priv->dhcp6_config); + if (priv->dhcp6.config) { + nm_exported_object_clear_and_unexport (&priv->dhcp6.config); _notify (self, PROP_DHCP6_CONFIG); } } @@ -5104,6 +5470,7 @@ ip6_config_merge_and_apply (NMDevice *self, gboolean ignore_auto_routes = FALSE; gboolean ignore_auto_dns = FALSE; gboolean auto_method = FALSE; + const char *token = NULL; /* Apply ignore-auto-routes and ignore-auto-dns settings */ connection = nm_device_get_applied_connection (self); @@ -5111,9 +5478,14 @@ ip6_config_merge_and_apply (NMDevice *self, NMSettingIPConfig *s_ip6 = nm_connection_get_setting_ip6_config (connection); if (s_ip6) { + NMSettingIP6Config *ip6 = NM_SETTING_IP6_CONFIG (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_setting_ip6_config_get_addr_gen_mode (ip6) == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64) + token = nm_setting_ip6_config_get_token (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)) @@ -5136,8 +5508,8 @@ ip6_config_merge_and_apply (NMDevice *self, (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0)); } - if (priv->dhcp6_ip6_config) { - nm_ip6_config_merge (composite, priv->dhcp6_ip6_config, + if (priv->dhcp6.ip6_config) { + nm_ip6_config_merge (composite, priv->dhcp6.ip6_config, (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0)); } @@ -5230,7 +5602,7 @@ ip6_config_merge_and_apply (NMDevice *self, priv->default_route.v6_has = TRUE; memset (&priv->default_route.v6, 0, sizeof (priv->default_route.v6)); - priv->default_route.v6.source = NM_IP_CONFIG_SOURCE_USER; + priv->default_route.v6.rt_source = NM_IP_CONFIG_SOURCE_USER; priv->default_route.v6.gateway = *gateway; priv->default_route.v6.metric = nm_device_get_ip6_route_metric (self); priv->default_route.v6.mss = nm_ip6_config_get_mss (composite); @@ -5261,6 +5633,14 @@ END_ADD_DEFAULT_ROUTE: /* Allow setting MTU etc */ if (commit) { + NMUtilsIPv6IfaceId iid; + + if (token && nm_utils_ipv6_interface_identifier_get_from_token (&iid, token)) { + nm_platform_link_set_ipv6_token (NM_PLATFORM_GET, + nm_device_get_ip_ifindex (self), + iid); + } + if (NM_DEVICE_GET_CLASS (self)->ip6_config_pre_commit) NM_DEVICE_GET_CLASS (self)->ip6_config_pre_commit (self, composite); } @@ -5276,37 +5656,38 @@ END_ADD_DEFAULT_ROUTE: return success; } -static void +static gboolean dhcp6_lease_change (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMSettingsConnection *settings_connection; NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; - if (priv->dhcp6_ip6_config == NULL) { + if (priv->dhcp6.ip6_config == NULL) { _LOGW (LOGD_DHCP6, "failed to get DHCPv6 config for rebind"); - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED); - return; + return FALSE; } - g_assert (priv->dhcp6_client); /* sanity check */ + g_assert (priv->dhcp6.client); /* sanity check */ settings_connection = nm_device_get_settings_connection (self); g_assert (settings_connection); /* Apply the updated config */ - if (ip6_config_merge_and_apply (self, TRUE, &reason) == FALSE) { - _LOGW (LOGD_DHCP6, "failed to update IPv6 config in response to DHCP event."); - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); - } else { - /* Notify dispatcher scripts of new DHCPv6 config */ - nm_dispatcher_call (DISPATCHER_ACTION_DHCP6_CHANGE, - settings_connection, - nm_device_get_applied_connection (self), - self, NULL, NULL, NULL); - - nm_device_remove_pending_action (self, PENDING_ACTION_DHCP6, FALSE); + if (!ip6_config_merge_and_apply (self, TRUE, &reason)) { + _LOGW (LOGD_DHCP6, "failed to update IPv6 config in response to DHCP event"); + return FALSE; } + + /* Notify dispatcher scripts of new DHCPv6 config */ + nm_dispatcher_call (DISPATCHER_ACTION_DHCP6_CHANGE, + settings_connection, + nm_device_get_applied_connection (self), + self, NULL, NULL, NULL); + + nm_device_remove_pending_action (self, PENDING_ACTION_DHCP6, FALSE); + + return TRUE; } static gboolean @@ -5319,30 +5700,63 @@ dhcp6_restart_cb (gpointer user_data) g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); priv = NM_DEVICE_GET_PRIVATE (self); - priv->dhcp6_restart_id = 0; + priv->dhcp6.restart_id = 0; if (!dhcp6_start (self, FALSE, &reason)) - priv->dhcp6_restart_id = g_timeout_add_seconds (120, dhcp6_restart_cb, self); + dhcp_schedule_restart (self, AF_INET6, NULL); return FALSE; } static void +dhcp_schedule_restart (NMDevice *self, int family, const char *reason) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + gboolean inet4; + guint tries_left; + gs_free char *tries_str = NULL; + + g_return_if_fail (family == AF_INET || family == AF_INET6); + inet4 = family == AF_INET; + + tries_left = inet4 ? priv->dhcp4.num_tries_left : priv->dhcp6.num_tries_left; + if (tries_left != DHCP_NUM_TRIES_MAX) + tries_str = g_strdup_printf (", %u tries left", tries_left + 1); + + _LOGI (inet4 ? LOGD_DHCP4 : LOGD_DHCP6, + "scheduling DHCPv%c restart in %u seconds%s%s%s%s", + inet4 ? '4' : '6', + DHCP_RESTART_TIMEOUT, + tries_str ? tries_str : "", + NM_PRINT_FMT_QUOTED (reason, " (reason: ", reason, ")", "")); + + if (inet4) { + priv->dhcp4.restart_id = g_timeout_add_seconds (DHCP_RESTART_TIMEOUT, + dhcp4_restart_cb, self); + } else { + priv->dhcp6.restart_id = g_timeout_add_seconds (DHCP_RESTART_TIMEOUT, + dhcp6_restart_cb, self); + } +} + +static void dhcp6_fail (NMDevice *self, gboolean timeout) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + _LOGD (LOGD_DHCP6, "DHCPv6 failed: timeout %d, num tries left %u", + timeout, priv->dhcp6.num_tries_left); + dhcp6_cleanup (self, CLEANUP_TYPE_DECONFIGURE, FALSE); - if (priv->dhcp6_mode == NM_RDISC_DHCP_LEVEL_MANAGED) { + if (priv->dhcp6.mode == NM_RDISC_DHCP_LEVEL_MANAGED) { /* Don't fail if there are static addresses configured on * the device, instead retry after some time. */ if ( priv->ip6_state == IP_DONE && priv->con_ip6_config && nm_ip6_config_get_num_addresses (priv->con_ip6_config)) { - _LOGI (LOGD_DHCP6, "Scheduling DHCPv6 restart because device has IP addresses"); - priv->dhcp6_restart_id = g_timeout_add_seconds (120, dhcp6_restart_cb, self); + dhcp_schedule_restart (self, AF_INET6, "device has IP addresses"); return; } @@ -5351,16 +5765,23 @@ dhcp6_fail (NMDevice *self, gboolean timeout) * retry DHCP again. */ if (nm_device_uses_assumed_connection (self)) { - _LOGI (LOGD_DHCP6, "Scheduling DHCPv6 restart because the connection is assumed"); - priv->dhcp6_restart_id = g_timeout_add_seconds (120, dhcp6_restart_cb, self); + dhcp_schedule_restart (self, AF_INET6, "connection is assumed"); return; } - if (timeout || (priv->ip6_state == IP_CONF)) + if ( priv->dhcp6.num_tries_left == DHCP_NUM_TRIES_MAX + && (timeout || (priv->ip6_state == IP_CONF))) nm_device_activate_schedule_ip6_config_timeout (self); - else if (priv->ip6_state == IP_DONE) - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED); - else + else if (priv->ip6_state == IP_DONE) { + /* Don't fail immediately when the lease expires but try to + * restart DHCP for a predefined number of times. + */ + if (priv->dhcp6.num_tries_left) { + priv->dhcp6.num_tries_left--; + dhcp_schedule_restart (self, AF_INET6, "lease expired"); + } else + nm_device_ip_method_failed (self, AF_INET6, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED); + } else g_warn_if_reached (); } else { /* not a hard failure; just live with the RA info */ @@ -5374,7 +5795,7 @@ dhcp6_timeout (NMDevice *self, NMDhcpClient *client) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - if (priv->dhcp6_mode == NM_RDISC_DHCP_LEVEL_MANAGED) + if (priv->dhcp6.mode == NM_RDISC_DHCP_LEVEL_MANAGED) dhcp6_fail (self, TRUE); else { /* not a hard failure; just live with the RA info */ @@ -5409,32 +5830,34 @@ dhcp6_state_changed (NMDhcpClient *client, */ if ( ip6_config && event_id - && priv->dhcp6_event_id - && !strcmp (event_id, priv->dhcp6_event_id)) { + && priv->dhcp6.event_id + && !strcmp (event_id, priv->dhcp6.event_id)) { for (i = 0; i < nm_ip6_config_get_num_addresses (ip6_config); i++) { - nm_ip6_config_add_address (priv->dhcp6_ip6_config, + nm_ip6_config_add_address (priv->dhcp6.ip6_config, nm_ip6_config_get_address (ip6_config, i)); } } else { - g_clear_object (&priv->dhcp6_ip6_config); - g_clear_pointer (&priv->dhcp6_event_id, g_free); + g_clear_object (&priv->dhcp6.ip6_config); + g_clear_pointer (&priv->dhcp6.event_id, g_free); if (ip6_config) { - priv->dhcp6_ip6_config = g_object_ref (ip6_config); - priv->dhcp6_event_id = g_strdup (event_id); - nm_dhcp6_config_set_options (priv->dhcp6_config, options); + priv->dhcp6.ip6_config = g_object_ref (ip6_config); + priv->dhcp6.event_id = g_strdup (event_id); + nm_dhcp6_config_set_options (priv->dhcp6.config, options); _notify (self, PROP_DHCP6_CONFIG); } } + priv->dhcp6.num_tries_left = DHCP_NUM_TRIES_MAX; + if (priv->ip6_state == IP_CONF) { - if (priv->dhcp6_ip6_config == NULL) { - /* FIXME: Initial DHCP failed; should we fail IPv6 entirely then? */ - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_DHCP_FAILED); + if (priv->dhcp6.ip6_config == NULL) { + nm_device_ip_method_failed (self, AF_INET6, NM_DEVICE_STATE_REASON_DHCP_FAILED); break; } nm_device_activate_schedule_ip6_config_result (self); } else if (priv->ip6_state == IP_DONE) - dhcp6_lease_change (self); + if (!dhcp6_lease_change (self)) + dhcp6_fail (self, FALSE); break; case NM_DHCP_STATE_TIMEOUT: dhcp6_timeout (self, client); @@ -5449,7 +5872,7 @@ dhcp6_state_changed (NMDhcpClient *client, * may exit right after getting a response from the server. That's * normal. In that case we just ignore the exit. */ - if (priv->dhcp6_mode == NM_RDISC_DHCP_LEVEL_OTHERCONF) + if (priv->dhcp6.mode == NM_RDISC_DHCP_LEVEL_OTHERCONF) break; /* Otherwise, fall through */ case NM_DHCP_STATE_FAIL: @@ -5485,7 +5908,7 @@ dhcp6_start_with_link_ready (NMDevice *self, NMConnection *connection) g_return_val_if_fail (ll_addr, FALSE); - priv->dhcp6_client = nm_dhcp_manager_start_ip6 (nm_dhcp_manager_get (), + priv->dhcp6.client = nm_dhcp_manager_start_ip6 (nm_dhcp_manager_get (), nm_device_get_ip_iface (self), nm_device_get_ip_ifindex (self), tmp, @@ -5496,19 +5919,19 @@ dhcp6_start_with_link_ready (NMDevice *self, NMConnection *connection) nm_setting_ip_config_get_dhcp_hostname (s_ip6), priv->dhcp_timeout, priv->dhcp_anycast_address, - (priv->dhcp6_mode == NM_RDISC_DHCP_LEVEL_OTHERCONF) ? TRUE : FALSE, + (priv->dhcp6.mode == NM_RDISC_DHCP_LEVEL_OTHERCONF) ? TRUE : FALSE, nm_setting_ip6_config_get_ip6_privacy (NM_SETTING_IP6_CONFIG (s_ip6))); if (tmp) g_byte_array_free (tmp, TRUE); - if (priv->dhcp6_client) { - priv->dhcp6_state_sigid = g_signal_connect (priv->dhcp6_client, + if (priv->dhcp6.client) { + priv->dhcp6.state_sigid = g_signal_connect (priv->dhcp6.client, NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED, G_CALLBACK (dhcp6_state_changed), self); } - return !!priv->dhcp6_client; + return !!priv->dhcp6.client; } static gboolean @@ -5518,12 +5941,12 @@ dhcp6_start (NMDevice *self, gboolean wait_for_ll, NMDeviceStateReason *reason) NMConnection *connection; NMSettingIPConfig *s_ip6; - nm_exported_object_clear_and_unexport (&priv->dhcp6_config); - priv->dhcp6_config = nm_dhcp6_config_new (); + nm_exported_object_clear_and_unexport (&priv->dhcp6.config); + priv->dhcp6.config = nm_dhcp6_config_new (); - g_warn_if_fail (priv->dhcp6_ip6_config == NULL); - g_clear_object (&priv->dhcp6_ip6_config); - g_clear_pointer (&priv->dhcp6_event_id, g_free); + g_warn_if_fail (priv->dhcp6.ip6_config == NULL); + g_clear_object (&priv->dhcp6.ip6_config); + g_clear_pointer (&priv->dhcp6.event_id, g_free); connection = nm_device_get_applied_connection (self); g_assert (connection); @@ -5559,7 +5982,7 @@ nm_device_dhcp6_renew (NMDevice *self, gboolean release) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - g_return_val_if_fail (priv->dhcp6_client != NULL, FALSE); + g_return_val_if_fail (priv->dhcp6.client != NULL, FALSE); _LOGI (LOGD_DHCP6, "DHCPv6 lease renewal requested"); @@ -5668,11 +6091,17 @@ check_and_add_ipv6ll_addr (NMDevice *self) s_ip6 = NM_SETTING_IP6_CONFIG (nm_connection_get_setting_ip6_config (connection)); if (s_ip6 && nm_setting_ip6_config_get_addr_gen_mode (s_ip6) == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY) { - if (!nm_utils_ipv6_addr_set_stable_privacy (&lladdr, - nm_device_get_iface (self), - nm_connection_get_uuid (connection), - priv->linklocal6_dad_counter++, - &error)) { + NMUtilsStableType stable_type; + const char *stable_id; + + stable_id = _get_stable_id (connection, &stable_type); + if ( !stable_id + || !nm_utils_ipv6_addr_set_stable_privacy (stable_type, + &lladdr, + nm_device_get_iface (self), + stable_id, + priv->linklocal6_dad_counter++, + &error)) { _LOGW (LOGD_IP6, "linklocal6: failed to generate an address: %s", error->message); g_clear_error (&error); linklocal6_failed (self); @@ -5690,13 +6119,13 @@ check_and_add_ipv6ll_addr (NMDevice *self) return; } - if (!nm_device_get_ip_iface_identifier (self, &iid)) { + if (!nm_device_get_ip_iface_identifier (self, &iid, TRUE)) { _LOGW (LOGD_IP6, "linklocal6: failed to get interface identifier; IPv6 cannot continue"); return; } _LOGD (LOGD_IP6, "linklocal6: using EUI-64 identifier to generate IPv6LL address"); - nm_utils_ipv6_addr_set_interface_identfier (&lladdr, iid); + nm_utils_ipv6_addr_set_interface_identifier (&lladdr, iid); } _LOGD (LOGD_IP6, "linklocal6: adding IPv6LL address %s", nm_utils_inet6_ntop (&lladdr, NULL)); @@ -5799,8 +6228,9 @@ nm_device_ipv6_set_mtu (NMDevice *self, guint32 mtu) } static void -rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *self) +rdisc_config_changed (NMRDisc *rdisc, const NMRDiscData *rdata, guint changed_int, NMDevice *self) { + NMRDiscConfigMap changed = changed_int; NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); int i; int system_support; @@ -5830,11 +6260,9 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *self) if (changed & NM_RDISC_CONFIG_GATEWAYS) { /* Use the first gateway as ordered in router discovery cache. */ - if (rdisc->gateways->len) { - NMRDiscGateway *gateway = &g_array_index (rdisc->gateways, NMRDiscGateway, 0); - - nm_ip6_config_set_gateway (priv->ac_ip6_config, &gateway->address); - } else + if (rdata->gateways_n) + nm_ip6_config_set_gateway (priv->ac_ip6_config, &rdata->gateways[0].address); + else nm_ip6_config_set_gateway (priv->ac_ip6_config, NULL); } @@ -5847,8 +6275,8 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *self) * also counts static and temporary addresses when checking * max_addresses. **/ - for (i = 0; i < rdisc->addresses->len; i++) { - NMRDiscAddress *discovered_address = &g_array_index (rdisc->addresses, NMRDiscAddress, i); + for (i = 0; i < rdata->addresses_n; i++) { + const NMRDiscAddress *discovered_address = &rdata->addresses[i]; NMPlatformIP6Address address; memset (&address, 0, sizeof (address)); @@ -5859,7 +6287,7 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *self) address.preferred = discovered_address->preferred; if (address.preferred > address.lifetime) address.preferred = address.lifetime; - address.source = NM_IP_CONFIG_SOURCE_RDISC; + address.addr_source = NM_IP_CONFIG_SOURCE_RDISC; address.n_ifa_flags = ifa_flags; nm_ip6_config_add_address (priv->ac_ip6_config, &address); @@ -5870,25 +6298,17 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *self) /* Rebuild route list from router discovery cache. */ nm_ip6_config_reset_routes (priv->ac_ip6_config); - for (i = 0; i < rdisc->routes->len; i++) { - NMRDiscRoute *discovered_route = &g_array_index (rdisc->routes, NMRDiscRoute, i); - NMPlatformIP6Route route; - - /* Only accept non-default routes. The router has no idea what the - * local configuration or user preferences are, so sending routes - * with a prefix length of 0 is quite rude and thus ignored. - */ - if (discovered_route->plen > 0) { - memset (&route, 0, sizeof (route)); - route.network = discovered_route->network; - nm_assert (discovered_route->plen <= 128); - route.plen = discovered_route->plen; - route.gateway = discovered_route->gateway; - route.source = NM_IP_CONFIG_SOURCE_RDISC; - route.metric = nm_device_get_ip6_route_metric (self); - - nm_ip6_config_add_route (priv->ac_ip6_config, &route); - } + for (i = 0; i < rdata->routes_n; i++) { + const NMRDiscRoute *discovered_route = &rdata->routes[i]; + const NMPlatformIP6Route route = { + .network = discovered_route->network, + .plen = discovered_route->plen, + .gateway = discovered_route->gateway, + .rt_source = NM_IP_CONFIG_SOURCE_RDISC, + .metric = nm_device_get_ip6_route_metric (self), + }; + + nm_ip6_config_add_route (priv->ac_ip6_config, &route); } } @@ -5896,36 +6316,30 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *self) /* Rebuild DNS server list from router discovery cache. */ nm_ip6_config_reset_nameservers (priv->ac_ip6_config); - for (i = 0; i < rdisc->dns_servers->len; i++) { - NMRDiscDNSServer *discovered_server = &g_array_index (rdisc->dns_servers, NMRDiscDNSServer, i); - - nm_ip6_config_add_nameserver (priv->ac_ip6_config, &discovered_server->address); - } + for (i = 0; i < rdata->dns_servers_n; i++) + nm_ip6_config_add_nameserver (priv->ac_ip6_config, &rdata->dns_servers[i].address); } if (changed & NM_RDISC_CONFIG_DNS_DOMAINS) { /* Rebuild domain list from router discovery cache. */ nm_ip6_config_reset_domains (priv->ac_ip6_config); - for (i = 0; i < rdisc->dns_domains->len; i++) { - NMRDiscDNSDomain *discovered_domain = &g_array_index (rdisc->dns_domains, NMRDiscDNSDomain, i); - - nm_ip6_config_add_domain (priv->ac_ip6_config, discovered_domain->domain); - } + for (i = 0; i < rdata->dns_domains_n; i++) + nm_ip6_config_add_domain (priv->ac_ip6_config, rdata->dns_domains[i].domain); } if (changed & NM_RDISC_CONFIG_DHCP_LEVEL) { dhcp6_cleanup (self, CLEANUP_TYPE_DECONFIGURE, TRUE); - priv->dhcp6_mode = rdisc->dhcp_level; - if (priv->dhcp6_mode != NM_RDISC_DHCP_LEVEL_NONE) { + priv->dhcp6.mode = rdata->dhcp_level; + if (priv->dhcp6.mode != NM_RDISC_DHCP_LEVEL_NONE) { NMDeviceStateReason reason; _LOGD (LOGD_DEVICE | LOGD_DHCP6, "Activation: Stage 3 of 5 (IP Configure Start) starting DHCPv6" " as requested by IPv6 router..."); if (!dhcp6_start (self, FALSE, &reason)) { - if (priv->dhcp6_mode == NM_RDISC_DHCP_LEVEL_MANAGED) { + if (priv->dhcp6.mode == NM_RDISC_DHCP_LEVEL_MANAGED) { nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); return; } @@ -5934,10 +6348,10 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *self) } if (changed & NM_RDISC_CONFIG_HOP_LIMIT) - nm_platform_sysctl_set_ip6_hop_limit_safe (NM_PLATFORM_GET, nm_device_get_ip_iface (self), rdisc->hop_limit); + nm_platform_sysctl_set_ip6_hop_limit_safe (NM_PLATFORM_GET, nm_device_get_ip_iface (self), rdata->hop_limit); if (changed & NM_RDISC_CONFIG_MTU) - priv->ip6_mtu = rdisc->mtu; + priv->ip6_mtu = rdata->mtu; nm_device_activate_schedule_ip6_config_result (self); } @@ -5975,10 +6389,7 @@ addrconf6_start_with_link_ready (NMDevice *self) g_assert (priv->rdisc); - if (nm_platform_link_get_ipv6_token (NM_PLATFORM_GET, priv->ifindex, &iid)) { - _LOGD (LOGD_IP6, "addrconf6: IPv6 tokenized identifier present"); - nm_rdisc_set_iid (priv->rdisc, iid); - } else if (nm_device_get_ip_iface_identifier (self, &iid)) { + if (nm_device_get_ip_iface_identifier (self, &iid, FALSE)) { _LOGD (LOGD_IP6, "addrconf6: using the device EUI-64 identifier"); nm_rdisc_set_iid (priv->rdisc, iid); } else { @@ -6017,6 +6428,8 @@ addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr) NMActStageReturn ret; NMSettingIP6Config *s_ip6 = NULL; GError *error = NULL; + NMUtilsStableType stable_type; + const char *stable_id; connection = nm_device_get_applied_connection (self); g_assert (connection); @@ -6030,12 +6443,16 @@ addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr) s_ip6 = NM_SETTING_IP6_CONFIG (nm_connection_get_setting_ip6_config (connection)); g_assert (s_ip6); - priv->rdisc = nm_lndp_rdisc_new (NM_PLATFORM_GET, - nm_device_get_ip_ifindex (self), - nm_device_get_ip_iface (self), - nm_connection_get_uuid (connection), - nm_setting_ip6_config_get_addr_gen_mode (s_ip6), - &error); + stable_id = _get_stable_id (connection, &stable_type); + if (stable_id) { + priv->rdisc = nm_lndp_rdisc_new (NM_PLATFORM_GET, + nm_device_get_ip_ifindex (self), + nm_device_get_ip_iface (self), + stable_type, + stable_id, + nm_setting_ip6_config_get_addr_gen_mode (s_ip6), + &error); + } if (!priv->rdisc) { _LOGE (LOGD_IP6, "addrconf6: failed to start router discovery: %s", error->message); g_error_free (error); @@ -6147,11 +6564,18 @@ set_nm_ipv6ll (NMDevice *self, gboolean enable) priv->nm_ipv6ll = enable; if (ifindex > 0) { + NMPlatformError plerr; const char *detail = enable ? "enable" : "disable"; _LOGD (LOGD_IP6, "will %s userland IPv6LL", detail); - if (!nm_platform_link_set_user_ipv6ll_enabled (NM_PLATFORM_GET, ifindex, enable)) - _LOGW (LOGD_IP6, "failed to %s userspace IPv6LL address handling", detail); + plerr = nm_platform_link_set_user_ipv6ll_enabled (NM_PLATFORM_GET, ifindex, enable); + if (plerr != NM_PLATFORM_ERROR_SUCCESS) { + _NMLOG (plerr == NM_PLATFORM_ERROR_NOT_FOUND ? LOGL_DEBUG : LOGL_WARN, + LOGD_IP6, + "failed to %s userspace IPv6LL address handling (%s)", + detail, + nm_platform_error_to_string (plerr)); + } if (enable) { /* Bounce IPv6 to ensure the kernel stops IPv6LL address generation */ @@ -6286,7 +6710,8 @@ act_stage3_ip6_config_start (NMDevice *self, } } - priv->dhcp6_mode = NM_RDISC_DHCP_LEVEL_NONE; + priv->dhcp6.mode = NM_RDISC_DHCP_LEVEL_NONE; + priv->dhcp6.num_tries_left = DHCP_NUM_TRIES_MAX; method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG); @@ -6334,7 +6759,7 @@ act_stage3_ip6_config_start (NMDevice *self, } else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0) { ret = linklocal6_start (self); } else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP) == 0) { - priv->dhcp6_mode = NM_RDISC_DHCP_LEVEL_MANAGED; + priv->dhcp6.mode = NM_RDISC_DHCP_LEVEL_MANAGED; if (!dhcp6_start (self, TRUE, reason)) { /* IPv6 might be disabled; allow IPv4 to proceed */ ret = NM_ACT_STAGE_RETURN_STOP; @@ -6611,7 +7036,6 @@ act_stage4_ip4_config_timeout (NMDevice *self, NMDeviceStateReason *reason) return NM_ACT_STAGE_RETURN_SUCCESS; } - /* * nm_device_activate_stage4_ip4_config_timeout * @@ -6639,7 +7063,6 @@ activate_stage4_ip4_config_timeout (NMDevice *self) check_ip_failed (self, FALSE); } - /* * nm_device_activate_schedule_ip4_config_timeout * @@ -6659,7 +7082,6 @@ nm_device_activate_schedule_ip4_config_timeout (NMDevice *self) activation_source_schedule (self, activate_stage4_ip4_config_timeout, AF_INET); } - static NMActStageReturn act_stage4_ip6_config_timeout (NMDevice *self, NMDeviceStateReason *reason) { @@ -6671,7 +7093,6 @@ act_stage4_ip6_config_timeout (NMDevice *self, NMDeviceStateReason *reason) return NM_ACT_STAGE_RETURN_SUCCESS; } - /* * activate_stage4_ip6_config_timeout * @@ -6699,7 +7120,6 @@ activate_stage4_ip6_config_timeout (NMDevice *self) check_ip_failed (self, FALSE); } - /* * nm_device_activate_schedule_ip6_config_timeout * @@ -6747,19 +7167,12 @@ share_init (void) return TRUE; } -static void -add_share_rule (NMActRequest *req, const char *table, const char *fmt, ...) -{ - va_list args; - char *cmd; - - va_start (args, fmt); - cmd = g_strdup_vprintf (fmt, args); - va_end (args); - - nm_act_request_add_share_rule (req, table, cmd); - g_free (cmd); -} +#define add_share_rule(req, table, ...) \ + G_STMT_START { \ + char *_cmd = g_strdup_printf (__VA_ARGS__); \ + nm_act_request_add_share_rule (req, table, _cmd); \ + g_free (_cmd); \ + } G_STMT_END static gboolean start_sharing (NMDevice *self, NMIP4Config *config) @@ -6906,7 +7319,7 @@ activate_stage5_ip4_config_commit (NMDevice *self) /* NULL to use the existing priv->dev_ip4_config */ if (!ip4_config_merge_and_apply (self, NULL, TRUE, &reason)) { _LOGD (LOGD_DEVICE | LOGD_IP4, "Activation: Stage 5 of 5 (IPv4 Commit) failed"); - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); + nm_device_ip_method_failed (self, AF_INET, reason); return; } @@ -6924,7 +7337,7 @@ activate_stage5_ip4_config_commit (NMDevice *self) /* If IPv4 wasn't the first to complete, and DHCP was used, then ensure * dispatcher scripts get the DHCP lease information. */ - if ( priv->dhcp4_client + if ( priv->dhcp4.client && nm_device_activate_ip4_state_in_conf (self) && (nm_device_get_state (self) > NM_DEVICE_STATE_IP_CONFIG)) { /* Notify dispatcher scripts of new DHCP4 config */ @@ -6975,6 +7388,64 @@ nm_device_activate_ip4_state_in_wait (NMDevice *self) return NM_DEVICE_GET_PRIVATE (self)->ip4_state == IP_WAIT; } +gboolean +nm_device_activate_ip4_state_done (NMDevice *self) +{ + g_return_val_if_fail (self != NULL, FALSE); + return NM_DEVICE_GET_PRIVATE (self)->ip4_state == IP_DONE; +} + +/* + * Returns a NMIP6Config containing NM-configured addresses which + * have the tentative flag, or NULL if none is present. + */ +static NMIP6Config * +dad6_get_pending_addresses (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMIP6Config *confs[] = { priv->ac_ip6_config, + priv->dhcp6.ip6_config, + priv->con_ip6_config, + priv->wwan_ip6_config }; + const NMPlatformIP6Address *addr, *pl_addr; + NMIP6Config *dad6_config = NULL; + guint i, j, num; + int ifindex; + + ifindex = nm_device_get_ip_ifindex (self); + g_return_val_if_fail (ifindex > 0, NULL); + + /* We are interested only in addresses that we have explicitly configured, + * not in externally added ones. + */ + for (i = 0; i < G_N_ELEMENTS (confs); i++) { + if (confs[i]) { + num = nm_ip6_config_get_num_addresses (confs[i]); + for (j = 0; j < num; j++) { + addr = nm_ip6_config_get_address (confs[i], j); + pl_addr = nm_platform_ip6_address_get (NM_PLATFORM_GET, + ifindex, + addr->address, + addr->plen); + if ( pl_addr + && NM_FLAGS_HAS (pl_addr->n_ifa_flags, IFA_F_TENTATIVE) + && !NM_FLAGS_HAS (pl_addr->n_ifa_flags, IFA_F_DADFAILED) + && !NM_FLAGS_HAS (pl_addr->n_ifa_flags, IFA_F_OPTIMISTIC)) { + _LOGt (LOGD_DEVICE, "IPv6 DAD: pending address %s", + nm_platform_ip6_address_to_string (pl_addr, NULL, 0)); + + if (!dad6_config) + dad6_config = nm_ip6_config_new (ifindex); + + nm_ip6_config_add_address (dad6_config, pl_addr); + } + } + } + } + + return dad6_config; +} + static void activate_stage5_ip6_config_commit (NMDevice *self) { @@ -6998,9 +7469,9 @@ activate_stage5_ip6_config_commit (NMDevice *self) } if (ip6_config_merge_and_apply (self, TRUE, &reason)) { - if ( priv->dhcp6_mode != NM_RDISC_DHCP_LEVEL_NONE + if ( priv->dhcp6.mode != NM_RDISC_DHCP_LEVEL_NONE && priv->ip6_state == IP_CONF) { - if (priv->dhcp6_ip6_config) { + if (priv->dhcp6.ip6_config) { /* If IPv6 wasn't the first IP to complete, and DHCP was used, * then ensure dispatcher scripts get the DHCP lease information. */ @@ -7016,16 +7487,23 @@ activate_stage5_ip6_config_commit (NMDevice *self) return; } } - nm_device_remove_pending_action (self, PENDING_ACTION_DHCP6, FALSE); nm_device_remove_pending_action (self, PENDING_ACTION_AUTOCONF6, FALSE); - /* Enter the IP_CHECK state if this is the first method to complete */ - priv->ip6_state = IP_DONE; - check_ip_done (self); + /* Check if we have to wait for DAD */ + if (priv->ip6_state == IP_CONF && !priv->dad6_ip6_config) { + priv->dad6_ip6_config = dad6_get_pending_addresses (self); + if (priv->dad6_ip6_config) { + _LOGD (LOGD_DEVICE | LOGD_IP6, "IPv6 DAD: waiting termination"); + } else { + /* No tentative addresses, proceed right away */ + priv->ip6_state = IP_DONE; + check_ip_done (self); + } + } } else { _LOGW (LOGD_DEVICE | LOGD_IP6, "Activation: Stage 5 of 5 (IPv6 Commit) failed"); - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); + nm_device_ip_method_failed (self, AF_INET6, reason); } } @@ -7059,6 +7537,13 @@ nm_device_activate_ip6_state_in_wait (NMDevice *self) return NM_DEVICE_GET_PRIVATE (self)->ip6_state == IP_WAIT; } +gboolean +nm_device_activate_ip6_state_done (NMDevice *self) +{ + g_return_val_if_fail (self != NULL, FALSE); + return NM_DEVICE_GET_PRIVATE (self)->ip6_state == IP_DONE; +} + static void clear_act_request (NMDevice *self) { @@ -7223,6 +7708,7 @@ _cleanup_ip6_pre (NMDevice *self, CleanupType cleanup_type) if (nm_clear_g_source (&priv->queued_ip6_config_id)) _LOGD (LOGD_DEVICE, "clearing queued IP6 config change"); + g_clear_object (&priv->dad6_ip6_config); dhcp6_cleanup (self, cleanup_type, FALSE); linklocal6_cleanup (self); addrconf6_cleanup (self); @@ -7891,7 +8377,7 @@ nm_device_steal_connection (NMDevice *self, NMSettingsConnection *connection) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - _LOGW (LOGD_DEVICE, "disconnecting connection '%s' for new activation request.", + _LOGI (LOGD_DEVICE, "disconnecting connection '%s' for new activation request", nm_settings_connection_get_id (connection)); if ( priv->queued_act_request @@ -7970,7 +8456,7 @@ nm_device_get_dhcp4_config (NMDevice *self) { g_return_val_if_fail (NM_IS_DEVICE (self), NULL); - return NM_DEVICE_GET_PRIVATE (self)->dhcp4_config; + return NM_DEVICE_GET_PRIVATE (self)->dhcp4.config; } NMIP4Config * @@ -8287,7 +8773,7 @@ nm_device_get_dhcp6_config (NMDevice *self) { g_return_val_if_fail (NM_IS_DEVICE (self), NULL); - return NM_DEVICE_GET_PRIVATE (self)->dhcp6_config; + return NM_DEVICE_GET_PRIVATE (self)->dhcp6.config; } NMIP6Config * @@ -8595,6 +9081,7 @@ nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); gboolean device_is_up = FALSE; + NMDeviceCapabilities capabilities; g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); @@ -8605,6 +9092,10 @@ nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware) return FALSE; } + /* Store carrier immediately. */ + if (nm_device_has_capability (self, NM_DEVICE_CAP_CARRIER_DETECT)) + check_carrier (self); + device_is_up = nm_device_is_up (self); if (block && !device_is_up) { int ifindex = nm_device_get_ip_ifindex (self); @@ -8626,6 +9117,13 @@ nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware) return FALSE; } + /* some ethernet devices fail to report capabilities unless the device + * is up. Re-read the capabilities. */ + capabilities = 0; + if (NM_DEVICE_GET_CLASS (self)->get_generic_capabilities) + capabilities |= NM_DEVICE_GET_CLASS (self)->get_generic_capabilities (self); + _add_capabilities (self, capabilities); + /* Devices that support carrier detect must be IFF_UP to report carrier * changes; so after setting the device IFF_UP we must suppress startup * complete (via a pending action) until either the carrier turns on, or @@ -8669,10 +9167,6 @@ bring_up (NMDevice *self, gboolean *no_firmware) result = nm_platform_link_set_up (NM_PLATFORM_GET, ifindex, no_firmware); - /* Store carrier immediately. */ - if (result && nm_device_has_capability (self, NM_DEVICE_CAP_CARRIER_DETECT)) - check_carrier (self); - return result; } @@ -8808,7 +9302,7 @@ capture_lease_config (NMDevice *self, NMIP6Config **out_ip6_config) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - const GSList *connections, *citer; + NMSettingsConnection *const*connections; guint i; gboolean dhcp_used = FALSE; @@ -8841,9 +9335,9 @@ capture_lease_config (NMDevice *self, if (!dhcp_used) return; - connections = nm_connection_provider_get_connections (priv->con_provider); - for (citer = connections; citer; citer = citer->next) { - NMConnection *candidate = citer->data; + connections = nm_settings_get_connections (priv->settings, NULL); + for (i = 0; connections[i]; i++) { + NMConnection *candidate = (NMConnection *) connections[i]; const char *method; if (!nm_device_check_connection_compatible (self, candidate)) @@ -9016,8 +9510,8 @@ update_ip6_config (NMDevice *self, gboolean initial) nm_ip6_config_intersect (priv->con_ip6_config, priv->ext_ip6_config); if (priv->ac_ip6_config) nm_ip6_config_intersect (priv->ac_ip6_config, priv->ext_ip6_config); - if (priv->dhcp6_ip6_config) - nm_ip6_config_intersect (priv->dhcp6_ip6_config, priv->ext_ip6_config); + if (priv->dhcp6.ip6_config) + nm_ip6_config_intersect (priv->dhcp6.ip6_config, priv->ext_ip6_config); if (priv->wwan_ip6_config) nm_ip6_config_intersect (priv->wwan_ip6_config, priv->ext_ip6_config); g_slist_foreach (priv->vpn6_configs, _ip6_config_intersect, priv->ext_ip6_config); @@ -9029,8 +9523,8 @@ update_ip6_config (NMDevice *self, gboolean initial) nm_ip6_config_subtract (priv->ext_ip6_config, priv->con_ip6_config); if (priv->ac_ip6_config) nm_ip6_config_subtract (priv->ext_ip6_config, priv->ac_ip6_config); - if (priv->dhcp6_ip6_config) - nm_ip6_config_subtract (priv->ext_ip6_config, priv->dhcp6_ip6_config); + if (priv->dhcp6.ip6_config) + nm_ip6_config_subtract (priv->ext_ip6_config, priv->dhcp6.ip6_config); if (priv->wwan_ip6_config) nm_ip6_config_subtract (priv->ext_ip6_config, priv->wwan_ip6_config); g_slist_foreach (priv->vpn6_configs, _ip6_config_subtract, priv->ext_ip6_config); @@ -9070,9 +9564,7 @@ queued_ip4_config_change (gpointer user_data) return TRUE; priv->queued_ip4_config_id = 0; - g_object_ref (self); update_ip4_config (self, FALSE); - g_object_unref (self); set_unmanaged_external_down (self, TRUE); @@ -9096,16 +9588,15 @@ queued_ip6_config_change (gpointer user_data) return TRUE; priv->queued_ip6_config_id = 0; - g_object_ref (self); update_ip6_config (self, FALSE); - if ( priv->state < NM_DEVICE_STATE_DEACTIVATING + 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; - if (addr->source >= NM_IP_CONFIG_SOURCE_USER) + if (addr->addr_source >= NM_IP_CONFIG_SOURCE_USER) continue; _LOGI (LOGD_IP6, "ipv6: duplicate address check failed for the %s address", @@ -9132,7 +9623,18 @@ queued_ip6_config_change (gpointer user_data) g_slist_free_full (priv->dad6_failed_addrs, g_free); priv->dad6_failed_addrs = NULL; - g_object_unref (self); + /* Check if DAD is still pending */ + if ( priv->ip6_state == IP_CONF + && priv->dad6_ip6_config + && priv->ext_ip6_config_captured) { + if (!nm_ip6_config_has_any_dad_pending (priv->ext_ip6_config_captured, + priv->dad6_ip6_config)) { + _LOGD (LOGD_DEVICE | LOGD_IP6, "IPv6 DAD terminated"); + g_clear_object (&priv->dad6_ip6_config); + priv->ip6_state = IP_DONE; + check_ip_done (self); + } + } set_unmanaged_external_down (self, TRUE); @@ -9256,7 +9758,7 @@ _get_managed_by_flags(NMUnmanagedFlags flags, NMUnmanagedFlags mask, gboolean fo * Some flags are authoritative, meaning they always cause * the device to be unmanaged (e.g. @NM_UNMANAGED_PLATFORM_INIT). * - * OTOH, some flags can be overwritten. For example NM_UNMANAGED_USER_SETTINGS + * OTOH, some flags can be overwritten. For example NM_UNMANAGED_USER_UDEV * is ignored once NM_UNMANAGED_USER_EXPLICIT is set. The idea is that * the flag from the configuration has no effect once the user explicitly * touches the unmanaged flags. */ @@ -9290,6 +9792,9 @@ _get_managed_by_flags(NMUnmanagedFlags flags, NMUnmanagedFlags mask, gboolean fo /* configuration from udev or nm-config overwrites the by-default flag * which is based on the device type. */ flags &= ~NM_UNMANAGED_BY_DEFAULT; + + /* configuration from udev overwrites external-down */ + flags &= ~NM_UNMANAGED_EXTERNAL_DOWN; } if ( NM_FLAGS_HAS (mask, NM_UNMANAGED_IS_SLAVE) @@ -9528,7 +10033,7 @@ nm_device_set_unmanaged_by_flags_queue (NMDevice *self, } void -nm_device_set_unmanaged_by_user_config (NMDevice *self, const GSList *unmanaged_specs) +nm_device_set_unmanaged_by_user_settings (NMDevice *self, const GSList *unmanaged_specs) { NMDevicePrivate *priv; gboolean unmanaged; @@ -9880,50 +10385,45 @@ void nm_device_recheck_available_connections (NMDevice *self) { NMDevicePrivate *priv; - const GSList *connections, *iter; + NMSettingsConnection *const*connections; gboolean changed = FALSE; GHashTableIter h_iter; NMConnection *connection; + guint i; + gs_unref_hashtable GHashTable *prune_list = NULL; g_return_if_fail (NM_IS_DEVICE (self)); priv = NM_DEVICE_GET_PRIVATE(self); - if (priv->con_provider) { - gs_unref_hashtable GHashTable *prune_list = NULL; - - if (g_hash_table_size (priv->available_connections) > 0) { - prune_list = g_hash_table_new (g_direct_hash, g_direct_equal); - g_hash_table_iter_init (&h_iter, priv->available_connections); - while (g_hash_table_iter_next (&h_iter, (gpointer *) &connection, NULL)) - g_hash_table_add (prune_list, connection); - } - - connections = nm_connection_provider_get_connections (priv->con_provider); - for (iter = connections; iter; iter = g_slist_next (iter)) { - connection = NM_CONNECTION (iter->data); - - if (nm_device_check_connection_available (self, - connection, - NM_DEVICE_CHECK_CON_AVAILABLE_NONE, - NULL)) { - if (available_connections_add (self, connection)) - changed = TRUE; - if (prune_list) - g_hash_table_remove (prune_list, connection); - } + if (g_hash_table_size (priv->available_connections) > 0) { + prune_list = g_hash_table_new (g_direct_hash, g_direct_equal); + g_hash_table_iter_init (&h_iter, priv->available_connections); + while (g_hash_table_iter_next (&h_iter, (gpointer *) &connection, NULL)) + g_hash_table_add (prune_list, connection); + } + + connections = nm_settings_get_connections (priv->settings, NULL); + for (i = 0; connections[i]; i++) { + connection = (NMConnection *) connections[i]; + + if (nm_device_check_connection_available (self, + connection, + NM_DEVICE_CHECK_CON_AVAILABLE_NONE, + NULL)) { + if (available_connections_add (self, connection)) + changed = TRUE; + if (prune_list) + g_hash_table_remove (prune_list, connection); } + } - if (prune_list) { - g_hash_table_iter_init (&h_iter, prune_list); - while (g_hash_table_iter_next (&h_iter, (gpointer *) &connection, NULL)) { - if (available_connections_del (self, connection)) - changed = TRUE; - } + if (prune_list) { + g_hash_table_iter_init (&h_iter, prune_list); + while (g_hash_table_iter_next (&h_iter, (gpointer *) &connection, NULL)) { + if (available_connections_del (self, connection)) + changed = TRUE; } - } else { - if (available_connections_del_all (self)) - changed = TRUE; } if (changed) @@ -9984,10 +10484,9 @@ nm_device_get_best_connection (NMDevice *self, } static void -cp_connection_added_or_updated (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data) +cp_connection_added_or_updated (NMDevice *self, NMConnection *connection) { gboolean changed; - NMDevice *self = user_data; g_return_if_fail (NM_IS_DEVICE (self)); g_return_if_fail (NM_IS_SETTINGS_CONNECTION (connection)); @@ -10007,6 +10506,18 @@ cp_connection_added_or_updated (NMConnectionProvider *cp, NMConnection *connecti } static void +cp_connection_added (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data) +{ + cp_connection_added_or_updated (user_data, connection); +} + +static void +cp_connection_updated (NMConnectionProvider *cp, NMConnection *connection, gboolean by_user, gpointer user_data) +{ + cp_connection_added_or_updated (user_data, connection); +} + +static void cp_connection_removed (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data) { NMDevice *self = user_data; @@ -10213,6 +10724,7 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type) g_clear_object (&priv->ext_ip6_config_captured); g_clear_object (&priv->wwan_ip6_config); g_clear_object (&priv->ip6_config); + g_clear_object (&priv->dad6_ip6_config); g_slist_free_full (priv->vpn4_configs, g_object_unref); priv->vpn4_configs = NULL; @@ -10276,44 +10788,48 @@ nm_device_cleanup (NMDevice *self, NMDeviceStateReason reason, CleanupType clean if (NM_DEVICE_GET_CLASS (self)->deactivate) NM_DEVICE_GET_CLASS (self)->deactivate (self); - /* master: release slaves */ - nm_device_master_release_slaves (self); + if (cleanup_type != CLEANUP_TYPE_KEEP) { + /* master: release slaves */ + nm_device_master_release_slaves (self); - /* slave: mark no longer enslaved */ - if ( priv->master - && nm_platform_link_get_master (NM_PLATFORM_GET, priv->ifindex) <= 0) - nm_device_master_release_one_slave (priv->master, self, FALSE, NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); + /* slave: mark no longer enslaved */ + if ( priv->master + && nm_platform_link_get_master (NM_PLATFORM_GET, priv->ifindex) <= 0) + nm_device_master_release_one_slave (priv->master, self, FALSE, NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); - /* Take out any entries in the routing table and any IP address the device had. */ - ifindex = nm_device_get_ip_ifindex (self); - if (ifindex > 0) { - nm_route_manager_route_flush (nm_route_manager_get (), ifindex); - nm_platform_address_flush (NM_PLATFORM_GET, ifindex); + /* Take out any entries in the routing table and any IP address the device had. */ + ifindex = nm_device_get_ip_ifindex (self); + if (ifindex > 0) { + nm_route_manager_route_flush (nm_route_manager_get (), ifindex); + nm_platform_address_flush (NM_PLATFORM_GET, ifindex); + } } if (priv->lldp_listener) nm_lldp_listener_stop (priv->lldp_listener); nm_device_update_metered (self); + + /* during device cleanup, we want to reset the MAC address of the device + * to the initial state. + * + * We certainly want to do that when reaching the UNMANAGED state... */ + if (nm_device_get_state (self) <= NM_DEVICE_STATE_UNMANAGED) + nm_device_hw_addr_reset (self, "unmanage"); + else { + /* for other device states (UNAVAILABLE, DISCONNECTED), allow the + * device to overwrite the reset behavior, so that Wi-Fi can set + * a randomized MAC address used during scanning. */ + NM_DEVICE_GET_CLASS (self)->deactivate_reset_hw_addr (self); + } + _cleanup_generic_post (self, cleanup_type); } -static char * -bin2hexstr (const char *bytes, gsize len) +static void +deactivate_reset_hw_addr (NMDevice *self) { - GString *str; - int i; - - g_return_val_if_fail (bytes != NULL, NULL); - g_return_val_if_fail (len > 0, NULL); - - str = g_string_sized_new (len * 2 + 1); - for (i = 0; i < len; i++) { - if (str->len) - g_string_append_c (str, ':'); - g_string_append_printf (str, "%02x", (guint8) bytes[i]); - } - return g_string_free (str, FALSE); + nm_device_hw_addr_reset (self, "deactivate"); } static char * @@ -10329,7 +10845,7 @@ find_dhcp4_address (NMDevice *self) for (i = 0; i < n; i++) { const NMPlatformIP4Address *a = nm_ip4_config_get_address (priv->ip4_config, i); - if (a->source == NM_IP_CONFIG_SOURCE_DHCP) + if (a->addr_source == NM_IP_CONFIG_SOURCE_DHCP) return g_strdup (nm_utils_inet4_ntop (a->address, NULL)); } return NULL; @@ -10346,6 +10862,8 @@ nm_device_spawn_iface_helper (NMDevice *self) GPtrArray *argv; gs_free char *dhcp4_address = NULL; char *logging_backend; + NMUtilsStableType stable_type; + const char *stable_id; if (priv->state != NM_DEVICE_STATE_ACTIVATED) return; @@ -10364,6 +10882,12 @@ nm_device_spawn_iface_helper (NMDevice *self) g_ptr_array_add (argv, g_strdup ("--uuid")); g_ptr_array_add (argv, g_strdup (nm_connection_get_uuid (connection))); + stable_id = _get_stable_id (connection, &stable_type); + if (stable_id && stable_type != NM_UTILS_STABLE_TYPE_UUID) { + g_ptr_array_add (argv, g_strdup ("--stable-id")); + g_ptr_array_add (argv, g_strdup_printf ("%d %s", (int) stable_type, stable_id)); + } + logging_backend = nm_config_get_is_debug (nm_config_get ()) ? g_strdup ("debug") : nm_config_data_get_value (NM_CONFIG_GET_DATA_ORIG, @@ -10380,7 +10904,6 @@ nm_device_spawn_iface_helper (NMDevice *self) method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG); if (g_strcmp0 (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0) { NMSettingIPConfig *s_ip4; - char *hex_client_id; s_ip4 = nm_connection_get_setting_ip4_config (connection); g_assert (s_ip4); @@ -10393,25 +10916,26 @@ nm_device_spawn_iface_helper (NMDevice *self) if (nm_setting_ip_config_get_may_fail (s_ip4) == FALSE) g_ptr_array_add (argv, g_strdup ("--dhcp4-required")); - if (priv->dhcp4_client) { + if (priv->dhcp4.client) { const char *hostname, *fqdn; GBytes *client_id; - client_id = nm_dhcp_client_get_client_id (priv->dhcp4_client); + client_id = nm_dhcp_client_get_client_id (priv->dhcp4.client); if (client_id) { g_ptr_array_add (argv, g_strdup ("--dhcp4-clientid")); - hex_client_id = bin2hexstr (g_bytes_get_data (client_id, NULL), - g_bytes_get_size (client_id)); - g_ptr_array_add (argv, hex_client_id); + g_ptr_array_add (argv, + _nm_utils_bin2str (g_bytes_get_data (client_id, NULL), + g_bytes_get_size (client_id), + FALSE)); } - hostname = nm_dhcp_client_get_hostname (priv->dhcp4_client); + hostname = nm_dhcp_client_get_hostname (priv->dhcp4.client); if (hostname) { g_ptr_array_add (argv, g_strdup ("--dhcp4-hostname")); g_ptr_array_add (argv, g_strdup (hostname)); } - fqdn = nm_dhcp_client_get_fqdn (priv->dhcp4_client); + fqdn = nm_dhcp_client_get_fqdn (priv->dhcp4.client); if (fqdn) { g_ptr_array_add (argv, g_strdup ("--dhcp4-fqdn")); g_ptr_array_add (argv, g_strdup (fqdn)); @@ -10424,7 +10948,6 @@ nm_device_spawn_iface_helper (NMDevice *self) method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG); if (g_strcmp0 (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0) { NMSettingIPConfig *s_ip6; - char *hex_iid; NMUtilsIPv6IfaceId iid = NM_UTILS_IPV6_IFACE_ID_INIT; s_ip6 = nm_connection_get_setting_ip6_config (connection); @@ -10441,10 +10964,12 @@ nm_device_spawn_iface_helper (NMDevice *self) g_ptr_array_add (argv, g_strdup ("--slaac-tempaddr")); g_ptr_array_add (argv, g_strdup_printf ("%d", priv->rdisc_use_tempaddr)); - if (nm_device_get_ip_iface_identifier (self, &iid)) { + if (nm_device_get_ip_iface_identifier (self, &iid, FALSE)) { g_ptr_array_add (argv, g_strdup ("--iid")); - hex_iid = bin2hexstr ((const char *) iid.id_u8, sizeof (NMUtilsIPv6IfaceId)); - g_ptr_array_add (argv, hex_iid); + g_ptr_array_add (argv, + _nm_utils_bin2str (iid.id_u8, + sizeof (NMUtilsIPv6IfaceId), + FALSE)); } g_ptr_array_add (argv, g_strdup ("--addr-gen-mode")); @@ -10654,11 +11179,14 @@ _set_state_full (NMDevice *self, if (old_state > NM_DEVICE_STATE_UNMANAGED) { if (reason == NM_DEVICE_STATE_REASON_REMOVED) { nm_device_cleanup (self, reason, CLEANUP_TYPE_REMOVED); + } else if (reason == NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED) { + nm_device_cleanup (self, reason, CLEANUP_TYPE_KEEP); } else { /* Clean up if the device is now unmanaged but was activated */ if (nm_device_get_act_request (self)) nm_device_cleanup (self, reason, CLEANUP_TYPE_DECONFIGURE); nm_device_take_down (self, TRUE); + nm_device_hw_addr_reset (self, "unmanage"); set_nm_ipv6ll (self, FALSE); restore_ip6_properties (self); } @@ -10706,6 +11234,9 @@ _set_state_full (NMDevice *self, } } break; + case NM_DEVICE_STATE_PREPARE: + nm_device_update_initial_hw_address (self); + break; case NM_DEVICE_STATE_NEED_AUTH: if (old_state > NM_DEVICE_STATE_NEED_AUTH) { /* Clean up any half-done IP operations if the device's layer2 @@ -10726,7 +11257,7 @@ _set_state_full (NMDevice *self, _notify (self, PROP_STATE); _notify (self, PROP_STATE_REASON); - g_signal_emit_by_name (self, NM_DEVICE_STATE_CHANGED, state, old_state, reason); + g_signal_emit (self, signals[STATE_CHANGED], 0, state, old_state, reason); /* Post-process the event after internal notification */ @@ -10749,11 +11280,9 @@ _set_state_full (NMDevice *self, case NM_DEVICE_STATE_DEACTIVATING: _cancel_activation (self); - if (nm_device_has_capability (self, NM_DEVICE_CAP_CARRIER_DETECT)) { - /* We cache the ignore_carrier state to not react on config-reloads while the connection - * is active. But on deactivating, reset the ignore-carrier flag to the current state. */ - priv->ignore_carrier = nm_config_data_get_ignore_carrier (NM_CONFIG_GET_DATA, self); - } + /* We cache the ignore_carrier state to not react on config-reloads while the connection + * is active. But on deactivating, reset the ignore-carrier flag to the current state. */ + priv->ignore_carrier = nm_config_data_get_ignore_carrier (NM_CONFIG_GET_DATA, self); if (quitting) { nm_dispatcher_call_sync (DISPATCHER_ACTION_PRE_DOWN, @@ -11026,25 +11555,27 @@ nm_device_get_hw_address (NMDevice *self) g_return_val_if_fail (NM_IS_DEVICE (self), NULL); priv = NM_DEVICE_GET_PRIVATE (self); - return priv->hw_addr_len ? priv->hw_addr : NULL; + nm_assert ((!priv->hw_addr) ^ (priv->hw_addr_len > 0)); + + return priv->hw_addr; } void nm_device_update_hw_address (NMDevice *self) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - int ifindex = nm_device_get_ifindex (self); + NMDevicePrivate *priv; const guint8 *hwaddr; gsize hwaddrlen = 0; - static const guint8 zero_hwaddr[ETH_ALEN]; - if (ifindex <= 0) + priv = NM_DEVICE_GET_PRIVATE (self); + if (priv->ifindex <= 0) return; - hwaddr = nm_platform_link_get_address (NM_PLATFORM_GET, ifindex, &hwaddrlen); + hwaddr = nm_platform_link_get_address (NM_PLATFORM_GET, priv->ifindex, &hwaddrlen); if ( priv->type == NM_DEVICE_TYPE_ETHERNET - && nm_utils_hwaddr_matches (hwaddr, hwaddrlen, zero_hwaddr, sizeof (zero_hwaddr))) + && hwaddr + && nm_utils_hwaddr_matches (hwaddr, hwaddrlen, nm_ip_addr_zero.addr_eth, sizeof (nm_ip_addr_zero.addr_eth))) hwaddrlen = 0; if (hwaddrlen) { @@ -11053,17 +11584,28 @@ nm_device_update_hw_address (NMDevice *self) g_free (priv->hw_addr); priv->hw_addr = nm_utils_hwaddr_ntoa (hwaddr, hwaddrlen); - _LOGD (LOGD_HW | LOGD_DEVICE, "hardware address now %s", priv->hw_addr); + _LOGD (LOGD_HW | LOGD_DEVICE, "hw-addr: hardware address now %s", priv->hw_addr); _notify (self, PROP_HW_ADDRESS); + + if ( !priv->hw_addr_initial + || ( priv->hw_addr_type == HW_ADDR_TYPE_UNSET + && priv->state < NM_DEVICE_STATE_PREPARE + && !nm_device_is_activating (self))) { + /* when we get a hw_addr the first time or while the device + * is not activated (with no explict hw address set), always + * update our inital hw-address as well. */ + nm_device_update_initial_hw_address (self); + } } } else { /* Invalid or no hardware address */ if (priv->hw_addr_len != 0) { - g_clear_pointer (&priv->hw_addr, g_free); - priv->hw_addr_len = 0; _LOGD (LOGD_HW | LOGD_DEVICE, - "previous hardware address is no longer valid"); - _notify (self, PROP_HW_ADDRESS); + "hw-addr: failed reading current MAC address (stay with %s)", + priv->hw_addr); + } else { + _LOGD (LOGD_HW | LOGD_DEVICE, + "hw-addr: failed reading current MAC address"); } } } @@ -11073,84 +11615,365 @@ nm_device_update_initial_hw_address (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - if (priv->hw_addr_len) { - priv->initial_hw_addr = g_strdup (priv->hw_addr); - _LOGD (LOGD_DEVICE | LOGD_HW, "read initial MAC address %s", priv->initial_hw_addr); + if ( priv->hw_addr + && !nm_streq0 (priv->hw_addr_initial, priv->hw_addr)) { + if ( priv->hw_addr_initial + && priv->hw_addr_type != HW_ADDR_TYPE_UNSET) { + /* once we have the initial hw address set, we only allow + * update if the currenty type is "unset". */ + return; + } + g_free (priv->hw_addr_initial); + priv->hw_addr_initial = g_strdup (priv->hw_addr); + _LOGD (LOGD_DEVICE, "hw-addr: update initial MAC address %s", + priv->hw_addr_initial); + } +} - if (priv->ifindex > 0) { - guint8 buf[NM_UTILS_HWADDR_LEN_MAX]; - size_t len = 0; +void +nm_device_update_permanent_hw_address (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + guint8 buf[NM_UTILS_HWADDR_LEN_MAX]; + size_t len = 0; + gboolean success_read; - if (nm_platform_link_get_permanent_address (NM_PLATFORM_GET, priv->ifindex, buf, &len)) { - g_warn_if_fail (len == priv->hw_addr_len); - priv->perm_hw_addr = nm_utils_hwaddr_ntoa (buf, priv->hw_addr_len); - _LOGD (LOGD_DEVICE | LOGD_HW, "read permanent MAC address %s", - priv->perm_hw_addr); - } else { - /* Fall back to current address */ - _LOGD (LOGD_HW | LOGD_ETHER, "unable to read permanent MAC address"); - priv->perm_hw_addr = g_strdup (priv->hw_addr); + if (priv->hw_addr_perm) { + /* the permanent hardware address is only read once and not + * re-read later. + * + * Except during unrealize/realize cycles, where we clear the permanent + * hardware address during unrealization. */ + return; + } + + if (priv->ifindex <= 0) + return; + + if (!priv->hw_addr_len) { + nm_device_update_hw_address (self); + if (!priv->hw_addr_len) + return; + } + + success_read = nm_platform_link_get_permanent_address (NM_PLATFORM_GET, priv->ifindex, buf, &len); + if (!success_read || len != priv->hw_addr_len) { + /* Fall back to current address. We use the fake address and keep it + * until the device unrealizes. + * + * In some cases it might be necessary to know whether this is a "real" or + * a temporary address (fake). */ + _LOGD (LOGD_HW | LOGD_ETHER, "hw-addr: %s (use current: %s)", + success_read + ? "read HW addr length of permanent MAC address differs" + : "unable to read permanent MAC address", + priv->hw_addr); + priv->hw_addr_perm_fake = TRUE; + priv->hw_addr_perm = g_strdup (priv->hw_addr); + } else { + priv->hw_addr_perm_fake = FALSE; + priv->hw_addr_perm = nm_utils_hwaddr_ntoa (buf, len); + _LOGD (LOGD_DEVICE, "hw-addr: read permanent MAC address '%s'", + priv->hw_addr_perm); + } + _notify (self, PROP_PERM_HW_ADDRESS); +} + +static const char * +_get_cloned_mac_address_setting (NMDevice *self, NMConnection *connection, gboolean is_wifi, char **out_addr) +{ + NMSetting *setting; + const char *addr = NULL; + + nm_assert (out_addr && !*out_addr); + + setting = nm_connection_get_setting (connection, + is_wifi ? NM_TYPE_SETTING_WIRELESS : NM_TYPE_SETTING_WIRED); + if (setting) { + addr = is_wifi + ? nm_setting_wireless_get_cloned_mac_address ((NMSettingWireless *) setting) + : nm_setting_wired_get_cloned_mac_address ((NMSettingWired *) setting); + } + + if (!addr) { + gs_free char *a = NULL; + + a = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA, + is_wifi ? "wifi.cloned-mac-address" : "ethernet.cloned-mac-address", + self); + /* default is permanent. */ + addr = NM_CLONED_MAC_PERMANENT; + + if (!a) { + if (is_wifi) { + NMSettingMacRandomization v; + + /* for backward compatibility, read the deprecated wifi.mac-address-randomization setting. */ + a = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA, + "wifi." NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION, + self); + v = _nm_utils_ascii_str_to_int64 (a, 10, + NM_SETTING_MAC_RANDOMIZATION_DEFAULT, + NM_SETTING_MAC_RANDOMIZATION_ALWAYS, + NM_SETTING_MAC_RANDOMIZATION_DEFAULT); + if (v == NM_SETTING_MAC_RANDOMIZATION_ALWAYS) + addr = NM_CLONED_MAC_RANDOM; } - } + } else if ( NM_CLONED_MAC_IS_SPECIAL (a) + || nm_utils_hwaddr_valid (a, ETH_ALEN)) + addr = *out_addr = g_steal_pointer (&a); } + + return addr; +} + +static const char * +_get_generate_mac_address_mask_setting (NMDevice *self, NMConnection *connection, gboolean is_wifi, char **out_value) +{ + NMSetting *setting; + const char *value = NULL; + char *a; + + nm_assert (out_value && !*out_value); + + setting = nm_connection_get_setting (connection, + is_wifi ? NM_TYPE_SETTING_WIRELESS : NM_TYPE_SETTING_WIRED); + if (setting) { + value = is_wifi + ? nm_setting_wireless_get_generate_mac_address_mask ((NMSettingWireless *) setting) + : nm_setting_wired_get_generate_mac_address_mask ((NMSettingWired *) setting); + if (value) + return value; + } + + a = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA, + is_wifi ? "wifi.generate-mac-address-mask" : "ethernet.generate-mac-mac-address-mask", + self); + if (!a) + return NULL; + *out_value = a; + return a; } gboolean -nm_device_set_hw_addr (NMDevice *self, const char *addr, - const char *detail, guint64 hw_log_domain) +nm_device_hw_addr_is_explict (NMDevice *self) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMDevicePrivate *priv; + + g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + + priv = NM_DEVICE_GET_PRIVATE (self); + return !NM_IN_SET (priv->hw_addr_type, HW_ADDR_TYPE_PERMANENT, HW_ADDR_TYPE_UNSET); +} + +static gboolean +_hw_addr_set (NMDevice *self, + const char *addr, + const char *operation, + const char *detail) +{ + NMDevicePrivate *priv; gboolean success = FALSE; - const char *cur_addr = nm_device_get_hw_address (self); + NMPlatformError plerr; + const char *cur_addr; guint8 addr_bytes[NM_UTILS_HWADDR_LEN_MAX]; + guint hw_addr_len; + gboolean was_up; - /* Fall back to the permanent address */ - if (!addr) - addr = priv->perm_hw_addr; - if (!addr) - return FALSE; + nm_assert (NM_IS_DEVICE (self)); + nm_assert (addr); + nm_assert (operation); + + priv = NM_DEVICE_GET_PRIVATE (self); + + cur_addr = nm_device_get_hw_address (self); /* Do nothing if current MAC is same */ if (cur_addr && nm_utils_hwaddr_matches (cur_addr, -1, addr, -1)) { - _LOGD (LOGD_DEVICE | hw_log_domain, "no MAC address change needed"); + _LOGT (LOGD_DEVICE, "set-hw-addr: no MAC address change needed (%s)", cur_addr); return TRUE; } - if (!nm_utils_hwaddr_aton (addr, addr_bytes, priv->hw_addr_len)) { - _LOGW (LOGD_DEVICE | hw_log_domain, "invalid MAC address %s", addr); - return FALSE; - } - /* Can't change MAC address while device is up */ - nm_device_take_down (self, FALSE); + hw_addr_len = priv->hw_addr_len; + if (!hw_addr_len) + hw_addr_len = _nm_utils_hwaddr_length (addr); + if ( !hw_addr_len + || !nm_utils_hwaddr_aton (addr, addr_bytes, hw_addr_len)) + g_return_val_if_reached (FALSE); - success = nm_platform_link_set_address (NM_PLATFORM_GET, nm_device_get_ip_ifindex (self), addr_bytes, priv->hw_addr_len); + _LOGT (LOGD_DEVICE, "set-hw-addr: setting MAC address to '%s' (%s, %s)...", addr, operation, detail); + + was_up = nm_device_is_up (self); + if (was_up) { + /* Can't change MAC address while device is up */ + nm_device_take_down (self, FALSE); + } + + plerr = nm_platform_link_set_address (NM_PLATFORM_GET, nm_device_get_ip_ifindex (self), addr_bytes, hw_addr_len); + success = (plerr == NM_PLATFORM_ERROR_SUCCESS); if (success) { /* MAC address succesfully changed; update the current MAC to match */ nm_device_update_hw_address (self); cur_addr = nm_device_get_hw_address (self); if (cur_addr && nm_utils_hwaddr_matches (cur_addr, -1, addr, -1)) { - _LOGI (LOGD_DEVICE | hw_log_domain, "%s MAC address to %s", - detail, addr); + _LOGI (LOGD_DEVICE, "set-hw-addr: %s MAC address to %s (%s)", + operation, addr, detail); } else { - _LOGW (LOGD_DEVICE | hw_log_domain, - "new MAC address %s not successfully set", addr); + _LOGW (LOGD_DEVICE, + "set-hw-addr: new MAC address %s not successfully set to %s (%s)", + addr, operation, detail); success = FALSE; } } else { - _LOGW (LOGD_DEVICE | hw_log_domain, "failed to %s MAC address to %s", - detail, addr); + _NMLOG (plerr == NM_PLATFORM_ERROR_NOT_FOUND ? LOGL_DEBUG : LOGL_WARN, + LOGD_DEVICE, "set-hw-addr: failed to %s MAC address to %s (%s) (%s)", + operation, addr, detail, + nm_platform_error_to_string (plerr)); + } + + if (was_up) { + if (!nm_device_bring_up (self, TRUE, NULL)) + return FALSE; } - nm_device_bring_up (self, TRUE, NULL); return success; } +gboolean +nm_device_hw_addr_set (NMDevice *self, const char *addr, const char *detail) +{ + NMDevicePrivate *priv; + + g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + + priv = NM_DEVICE_GET_PRIVATE (self); + + if (!addr) + g_return_val_if_reached (FALSE); + + /* this is called by NMDeviceVlan to take the MAC address from the parent + * and by NMDeviceWifi to set a random MAC address during scanning. + * In this case, it's like setting it to PERMANENT. */ + priv->hw_addr_type = HW_ADDR_TYPE_PERMANENT; + + return _hw_addr_set (self, addr, "set", detail); +} + +gboolean +nm_device_hw_addr_set_cloned (NMDevice *self, NMConnection *connection, gboolean is_wifi) +{ + NMDevicePrivate *priv; + gs_free char *hw_addr_tmp = NULL; + gs_free char *hw_addr_generated = NULL; + gs_free char *generate_mac_address_mask_tmp = NULL; + const char *addr, *addr_setting; + + g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + + priv = NM_DEVICE_GET_PRIVATE (self); + + if (!connection) + g_return_val_if_reached (FALSE); + + addr = addr_setting = _get_cloned_mac_address_setting (self, connection, is_wifi, &hw_addr_tmp); + + if (nm_streq (addr, NM_CLONED_MAC_PRESERVE)) { + /* "preserve" means to reset the initial MAC address. */ + return nm_device_hw_addr_reset (self, addr_setting); + } + + if (nm_streq (addr, NM_CLONED_MAC_PERMANENT)) { + addr = nm_device_get_permanent_hw_address (self, TRUE); + if (!addr) + return FALSE; + priv->hw_addr_type = HW_ADDR_TYPE_PERMANENT; + } else if (NM_IN_STRSET (addr, NM_CLONED_MAC_RANDOM)) { + if (priv->hw_addr_type == HW_ADDR_TYPE_GENERATED) { + /* hm, we already use a generate MAC address. Most certainly, that is from the same + * activation request, so we should not create a new random address, instead keep + * the current. */ + return TRUE; + } + hw_addr_generated = nm_utils_hw_addr_gen_random_eth (nm_device_get_initial_hw_address (self), + _get_generate_mac_address_mask_setting (self, connection, is_wifi, &generate_mac_address_mask_tmp)); + if (!hw_addr_generated) { + _LOGW (LOGD_DEVICE, "set-hw-addr: failed to generate %s MAC address", "random"); + return FALSE; + } + priv->hw_addr_type = HW_ADDR_TYPE_GENERATED; + addr = hw_addr_generated; + } else if (NM_IN_STRSET (addr, NM_CLONED_MAC_STABLE)) { + NMUtilsStableType stable_type; + const char *stable_id; + + if (priv->hw_addr_type == HW_ADDR_TYPE_GENERATED) { + /* hm, we already use a generate MAC address. Most certainly, that is from the same + * activation request, so let's skip creating the stable address anew. */ + return TRUE; + } + + stable_id = _get_stable_id (connection, &stable_type); + if (stable_id) { + hw_addr_generated = nm_utils_hw_addr_gen_stable_eth (stable_type, stable_id, + nm_device_get_ip_iface (self), + nm_device_get_initial_hw_address (self), + _get_generate_mac_address_mask_setting (self, connection, is_wifi, &generate_mac_address_mask_tmp)); + } + if (!hw_addr_generated) { + _LOGW (LOGD_DEVICE, "set-hw-addr: failed to generate %s MAC address", "stable"); + return FALSE; + } + priv->hw_addr_type = HW_ADDR_TYPE_GENERATED; + addr = hw_addr_generated; + } else { + /* this must be a valid address. Otherwise, we shouldn't come here. */ + if (_nm_utils_hwaddr_length (addr) <= 0) { + g_return_val_if_reached (FALSE); + } + priv->hw_addr_type = HW_ADDR_TYPE_EXPLICIT; + } + + return _hw_addr_set (self, addr, "set-cloned", addr_setting); +} + +gboolean +nm_device_hw_addr_reset (NMDevice *self, const char *detail) +{ + NMDevicePrivate *priv; + const char *addr; + + g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + + priv = NM_DEVICE_GET_PRIVATE (self); + + if (priv->hw_addr_type == HW_ADDR_TYPE_UNSET) + return TRUE; + + priv->hw_addr_type = HW_ADDR_TYPE_UNSET; + addr = nm_device_get_initial_hw_address (self); + if (!addr) { + /* as hw_addr_type is not UNSET, we expect that we can get an + * initial address to which to reset. */ + g_return_val_if_reached (FALSE); + } + + return _hw_addr_set (self, addr, "reset", detail); +} + const char * -nm_device_get_permanent_hw_address (NMDevice *self) +nm_device_get_permanent_hw_address (NMDevice *self, gboolean fallback_fake) { + NMDevicePrivate *priv; + g_return_val_if_fail (NM_IS_DEVICE (self), NULL); - return NM_DEVICE_GET_PRIVATE (self)->perm_hw_addr; + priv = NM_DEVICE_GET_PRIVATE (self); + if (!priv->hw_addr_perm) + return NULL; + if ( priv->hw_addr_perm_fake + && !fallback_fake) + return NULL; + return priv->hw_addr_perm; } const char * @@ -11158,7 +11981,7 @@ nm_device_get_initial_hw_address (NMDevice *self) { g_return_val_if_fail (NM_IS_DEVICE (self), NULL); - return NM_DEVICE_GET_PRIVATE (self)->initial_hw_addr; + return NM_DEVICE_GET_PRIVATE (self)->hw_addr_initial; } /** @@ -11196,9 +12019,9 @@ nm_device_spec_match_list (NMDevice *self, const GSList *specs) static NMMatchSpecMatchType spec_match_list (NMDevice *self, const GSList *specs) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMMatchSpecMatchType matched = NM_MATCH_SPEC_NO_MATCH, m; const GSList *iter; + const char *hw_addr_perm; for (iter = specs; iter; iter = g_slist_next (iter)) { if (!strcmp ((const char *) iter->data, "*")) { @@ -11206,8 +12029,10 @@ spec_match_list (NMDevice *self, const GSList *specs) break; } } - if (priv->hw_addr_len && priv->hw_addr) { - m = nm_match_spec_hwaddr (specs, priv->hw_addr); + + hw_addr_perm = nm_device_get_permanent_hw_address (self, FALSE); + if (hw_addr_perm) { + m = nm_match_spec_hwaddr (specs, hw_addr_perm); matched = MAX (matched, m); } if (matched != NM_MATCH_SPEC_NEG_MATCH) { @@ -11290,7 +12115,8 @@ constructor (GType type, self = NM_DEVICE (object); priv = NM_DEVICE_GET_PRIVATE (self); - if (priv->iface) { + if ( priv->iface + && G_LIKELY (!nm_utils_get_testing ())) { pllink = nm_platform_link_get_by_ifname (NM_PLATFORM_GET, priv->iface); if (pllink && link_type_compatible (self, pllink->type, NULL, NULL)) { @@ -11299,6 +12125,17 @@ constructor (GType type, } } + if (priv->hw_addr_perm) { + priv->hw_addr_len = _nm_utils_hwaddr_length (priv->hw_addr_perm); + if (!priv->hw_addr_len) { + g_clear_pointer (&priv->hw_addr_perm, g_free); + g_return_val_if_reached (object); + } + + priv->hw_addr = g_strdup (priv->hw_addr_perm); + _LOGT (LOGD_DEVICE, "hw-addr: has permanent hw-address '%s'", priv->hw_addr_perm); + } + return object; } @@ -11309,33 +12146,31 @@ constructed (GObject *object) NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMPlatform *platform; - platform = nm_platform_get (); - if (NM_DEVICE_GET_CLASS (self)->get_generic_capabilities) priv->capabilities |= NM_DEVICE_GET_CLASS (self)->get_generic_capabilities (self); /* Watch for external IP config changes */ + platform = NM_PLATFORM_GET; g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, G_CALLBACK (device_ipx_changed), self); g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, G_CALLBACK (device_ipx_changed), self); g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, G_CALLBACK (device_ipx_changed), self); g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, G_CALLBACK (device_ipx_changed), self); g_signal_connect (platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, G_CALLBACK (link_changed_cb), self); - priv->con_provider = nm_connection_provider_get (); - g_assert (priv->con_provider); - g_signal_connect (priv->con_provider, - NM_CP_SIGNAL_CONNECTION_ADDED, - G_CALLBACK (cp_connection_added_or_updated), - self); + priv->settings = g_object_ref (NM_SETTINGS_GET); + g_assert (priv->settings); - g_signal_connect (priv->con_provider, - NM_CP_SIGNAL_CONNECTION_REMOVED, - G_CALLBACK (cp_connection_removed), + g_signal_connect (priv->settings, + NM_SETTINGS_SIGNAL_CONNECTION_ADDED, + G_CALLBACK (cp_connection_added), self); - - g_signal_connect (priv->con_provider, - NM_CP_SIGNAL_CONNECTION_UPDATED, - G_CALLBACK (cp_connection_added_or_updated), + g_signal_connect (priv->settings, + NM_SETTINGS_SIGNAL_CONNECTION_UPDATED, + G_CALLBACK (cp_connection_updated), + self); + g_signal_connect (priv->settings, + NM_SETTINGS_SIGNAL_CONNECTION_REMOVED, + G_CALLBACK (cp_connection_removed), self); G_OBJECT_CLASS (nm_device_parent_class)->constructed (object); @@ -11352,7 +12187,7 @@ dispose (GObject *object) _LOGD (LOGD_DEVICE, "disposing"); - platform = nm_platform_get (); + platform = NM_PLATFORM_GET; g_signal_handlers_disconnect_by_func (platform, G_CALLBACK (device_ipx_changed), self); g_signal_handlers_disconnect_by_func (platform, G_CALLBACK (link_changed_cb), self); @@ -11361,7 +12196,7 @@ dispose (GObject *object) arp_cleanup (self); - g_signal_handlers_disconnect_by_func (nm_config_get (), config_changed_update_ignore_carrier, self); + nm_clear_g_signal_handler (nm_config_get (), &priv->ignore_carrier_id); dispatcher_cleanup (self); @@ -11382,12 +12217,14 @@ dispose (GObject *object) nm_clear_g_source (&priv->check_delete_unrealized_id); + nm_clear_g_source (&priv->stats.timeout_id); + link_disconnect_action_cancel (self); - if (priv->con_provider) { - g_signal_handlers_disconnect_by_func (priv->con_provider, cp_connection_added_or_updated, self); - g_signal_handlers_disconnect_by_func (priv->con_provider, cp_connection_removed, self); - priv->con_provider = NULL; + if (priv->settings) { + g_signal_handlers_disconnect_by_func (priv->settings, cp_connection_added, self); + g_signal_handlers_disconnect_by_func (priv->settings, cp_connection_updated, self); + g_signal_handlers_disconnect_by_func (priv->settings, cp_connection_removed, self); } available_connections_del_all (self); @@ -11426,8 +12263,8 @@ finalize (GObject *object) _LOGD (LOGD_DEVICE, "finalize(): %s", G_OBJECT_TYPE_NAME (self)); g_free (priv->hw_addr); - g_free (priv->perm_hw_addr); - g_free (priv->initial_hw_addr); + g_free (priv->hw_addr_perm); + g_free (priv->hw_addr_initial); g_slist_free_full (priv->pending_actions, g_free); g_slist_free_full (priv->dad6_failed_addrs, g_free); g_clear_pointer (&priv->physical_port_id, g_free); @@ -11445,16 +12282,19 @@ finalize (GObject *object) g_hash_table_unref (priv->available_connections); G_OBJECT_CLASS (nm_device_parent_class)->finalize (object); + + /* for testing, NMDeviceTest does not invoke NMDevice::constructed, + * and thus @settings might be unset. */ + if (priv->settings) + g_object_unref (priv->settings); } static void set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { - NMDevice *self = NM_DEVICE (object); + NMDevice *self = (NMDevice *) object; NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - const char *hw_addr, *p; - guint count; switch (prop_id) { case PROP_UDI: @@ -11476,11 +12316,11 @@ set_property (GObject *object, guint prop_id, break; case PROP_DRIVER_VERSION: g_free (priv->driver_version); - priv->driver_version = g_strdup (g_value_get_string (value)); + priv->driver_version = g_value_dup_string (value); break; case PROP_FIRMWARE_VERSION: g_free (priv->firmware_version); - priv->firmware_version = g_strdup (g_value_get_string (value)); + priv->firmware_version = g_value_dup_string (value); break; case PROP_MTU: priv->mtu = g_value_get_uint (value); @@ -11532,32 +12372,12 @@ set_property (GObject *object, guint prop_id, case PROP_IS_MASTER: priv->is_master = g_value_get_boolean (value); break; - case PROP_HW_ADDRESS: + case PROP_PERM_HW_ADDRESS: /* construct only */ - p = hw_addr = g_value_get_string (value); - - /* Hardware address length is the number of ':' plus 1 */ - count = 1; - while (p && *p) { - if (*p++ == ':') - count++; - } - if (count < ETH_ALEN || count > NM_UTILS_HWADDR_LEN_MAX) { - if (hw_addr && *hw_addr) { - _LOGW (LOGD_DEVICE, "ignoring hardware address '%s' with unexpected length %d", - hw_addr, count); - } - break; - } - - priv->hw_addr_len = count; - g_free (priv->hw_addr); - if (nm_utils_hwaddr_valid (hw_addr, priv->hw_addr_len)) - priv->hw_addr = g_strdup (hw_addr); - else { - _LOGW (LOGD_DEVICE, "could not parse hw-address '%s'", hw_addr); - priv->hw_addr = NULL; - } + priv->hw_addr_perm = g_value_dup_string (value); + break; + case PROP_REFRESH_RATE_MS: + _stats_set_refresh_rate (self, g_value_get_uint (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -11617,13 +12437,13 @@ get_property (GObject *object, guint prop_id, nm_utils_g_value_set_object_path (value, ip_config_valid (priv->state) ? priv->ip4_config : NULL); break; case PROP_DHCP4_CONFIG: - nm_utils_g_value_set_object_path (value, ip_config_valid (priv->state) ? priv->dhcp4_config : NULL); + nm_utils_g_value_set_object_path (value, ip_config_valid (priv->state) ? priv->dhcp4.config : NULL); break; case PROP_IP6_CONFIG: nm_utils_g_value_set_object_path (value, ip_config_valid (priv->state) ? priv->ip6_config : NULL); break; case PROP_DHCP6_CONFIG: - nm_utils_g_value_set_object_path (value, ip_config_valid (priv->state) ? priv->dhcp6_config : NULL); + nm_utils_g_value_set_object_path (value, ip_config_valid (priv->state) ? priv->dhcp6.config : NULL); break; case PROP_STATE: g_value_set_uint (value, priv->state); @@ -11680,6 +12500,10 @@ get_property (GObject *object, guint prop_id, case PROP_HW_ADDRESS: g_value_set_string (value, priv->hw_addr); break; + case PROP_PERM_HW_ADDRESS: + /* this property is exposed on D-Bus for NMDeviceEthernet and NMDeviceWifi. */ + g_value_set_string (value, nm_device_get_permanent_hw_address (self, FALSE)); + break; case PROP_HAS_PENDING_ACTION: g_value_set_boolean (value, nm_device_has_pending_action (self)); break; @@ -11717,6 +12541,15 @@ get_property (GObject *object, guint prop_id, g_value_take_boxed (value, slave_list); break; } + case PROP_REFRESH_RATE_MS: + g_value_set_uint (value, priv->stats.refresh_rate_ms); + break; + case PROP_TX_BYTES: + g_value_set_uint64 (value, priv->stats.tx_bytes); + break; + case PROP_RX_BYTES: + g_value_set_uint64 (value, priv->stats.rx_bytes); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -11765,6 +12598,8 @@ nm_device_class_init (NMDeviceClass *klass) klass->take_down = take_down; klass->carrier_changed = carrier_changed; klass->get_ip_iface_identifier = get_ip_iface_identifier; + klass->unmanaged_on_quit = unmanaged_on_quit; + klass->deactivate_reset_hw_addr = deactivate_reset_hw_addr; /* Properties */ obj_properties[PROP_UDI] = @@ -11923,6 +12758,11 @@ nm_device_class_init (NMDeviceClass *klass) obj_properties[PROP_HW_ADDRESS] = g_param_spec_string (NM_DEVICE_HW_ADDRESS, "", "", NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_PERM_HW_ADDRESS] = + g_param_spec_string (NM_DEVICE_PERM_HW_ADDRESS, "", "", + NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); obj_properties[PROP_HAS_PENDING_ACTION] = @@ -11960,6 +12800,23 @@ nm_device_class_init (NMDeviceClass *klass) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + /* Statistics */ + obj_properties[PROP_REFRESH_RATE_MS] = + g_param_spec_uint (NM_DEVICE_STATISTICS_REFRESH_RATE_MS, "", "", + 0, UINT32_MAX, 0, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_TX_BYTES] = + g_param_spec_uint64 (NM_DEVICE_STATISTICS_TX_BYTES, "", "", + 0, UINT64_MAX, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_RX_BYTES] = + g_param_spec_uint64 (NM_DEVICE_STATISTICS_RX_BYTES, "", "", + 0, UINT64_MAX, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); /* Signals */ @@ -12030,4 +12887,8 @@ nm_device_class_init (NMDeviceClass *klass) "Disconnect", impl_device_disconnect, "Delete", impl_device_delete, NULL); + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_STATISTICS_SKELETON, + NULL); } diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index 21804396..34d31cad 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -26,7 +26,6 @@ #include "nm-exported-object.h" #include "nm-dbus-interface.h" -#include "nm-default.h" #include "nm-connection.h" #include "nm-rfkill-manager.h" #include "NetworkManagerUtils.h" @@ -58,6 +57,11 @@ #define NM_DEVICE_PHYSICAL_PORT_ID "physical-port-id" #define NM_DEVICE_MTU "mtu" #define NM_DEVICE_HW_ADDRESS "hw-address" + +/* "perm-hw-address" is exposed on D-Bus both for NMDeviceEthernet + * and NMDeviceWifi. */ +#define NM_DEVICE_PERM_HW_ADDRESS "perm-hw-address" + #define NM_DEVICE_METERED "metered" #define NM_DEVICE_LLDP_NEIGHBORS "lldp-neighbors" #define NM_DEVICE_REAL "real" @@ -84,7 +88,9 @@ #define NM_DEVICE_STATE_CHANGED "state-changed" #define NM_DEVICE_LINK_INITIALIZED "link-initialized" -G_BEGIN_DECLS +#define NM_DEVICE_STATISTICS_REFRESH_RATE_MS "refresh-rate-ms" +#define NM_DEVICE_STATISTICS_TX_BYTES "tx-bytes" +#define NM_DEVICE_STATISTICS_RX_BYTES "rx-bytes" #define NM_TYPE_DEVICE (nm_device_get_type ()) #define NM_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE, NMDevice)) @@ -275,6 +281,8 @@ typedef struct { GAsyncResult *res, GError **error); + void (* deactivate_reset_hw_addr) (NMDevice *self); + /* Sync deactivating (in the DISCONNECTED phase) */ void (* deactivate) (NMDevice *self); @@ -324,6 +332,8 @@ typedef struct { gboolean (* owns_iface) (NMDevice *self, const char *iface); NMConnection * (* new_default_connection) (NMDevice *self); + + gboolean (* unmanaged_on_quit) (NMDevice *self); } NMDeviceClass; typedef void (*NMDeviceAuthRequestFunc) (NMDevice *device, @@ -354,7 +364,8 @@ guint32 nm_device_get_ip4_route_metric (NMDevice *dev); guint32 nm_device_get_ip6_route_metric (NMDevice *dev); const char * nm_device_get_hw_address (NMDevice *dev); -const char * nm_device_get_permanent_hw_address (NMDevice *dev); +const char * nm_device_get_permanent_hw_address (NMDevice *dev, + gboolean fallback_fake); const char * nm_device_get_initial_hw_address (NMDevice *dev); NMDhcp4Config * nm_device_get_dhcp4_config (NMDevice *dev); @@ -412,7 +423,7 @@ gboolean nm_device_check_slave_connection_compatible (NMDevice *device, NMConnec gboolean nm_device_uses_assumed_connection (NMDevice *device); -gboolean nm_device_can_assume_active_connection (NMDevice *device); +gboolean nm_device_unmanage_on_quit (NMDevice *self); gboolean nm_device_spec_match_list (NMDevice *device, const GSList *specs); @@ -440,7 +451,10 @@ RfKillType nm_device_get_rfkill_type (NMDevice *device); * (e.g. via a D-Bus command) * @NM_UNMANAGED_USER_SETTINGS: %TRUE when unmanaged by user decision via * the settings plugin (for example keyfile.unmanaged-devices or ifcfg-rh's - * NM_CONTROLLED=no) + * NM_CONTROLLED=no). Although this is user-configuration (provided from + * the settings plugins, such as NM_CONTROLLED=no in ifcfg-rh), it cannot + * be overruled and is authorative. That is because users may depend on + * dropping a ifcfg-rh file to ensure the device is unmanaged. * @NM_UNMANAGED_BY_DEFAULT: %TRUE for certain device types where we unmanage * them by default * @NM_UNMANAGED_USER_UDEV: %TRUE when unmanaged by user decision (via UDev rule) @@ -493,7 +507,7 @@ 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_settings (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); @@ -576,8 +590,7 @@ void nm_device_reactivate_ip6_config (NMDevice *device, void nm_device_update_hw_address (NMDevice *self); void nm_device_update_initial_hw_address (NMDevice *self); +void nm_device_update_permanent_hw_address (NMDevice *self); void nm_device_update_dynamic_ip_setup (NMDevice *self); -G_END_DECLS - -#endif /* NM_DEVICE_H */ +#endif /* __NETWORKMANAGER_DEVICE_H__ */ diff --git a/src/devices/nm-lldp-listener.c b/src/devices/nm-lldp-listener.c index 9cc1d086..f4663405 100644 --- a/src/devices/nm-lldp-listener.c +++ b/src/devices/nm-lldp-listener.c @@ -725,13 +725,20 @@ nm_lldp_listener_start (NMLldpListener *self, int ifindex, GError **error) return FALSE; } - ret = sd_lldp_new (&priv->lldp_handle, ifindex); + ret = sd_lldp_new (&priv->lldp_handle); if (ret < 0) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, "initialization failed"); return FALSE; } + ret = sd_lldp_set_ifindex (priv->lldp_handle, ifindex); + if (ret < 0) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, + "failed setting ifindex"); + goto err; + } + ret = sd_lldp_set_callback (priv->lldp_handle, lldp_event_handler, self); if (ret < 0) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, diff --git a/src/devices/nm-lldp-listener.h b/src/devices/nm-lldp-listener.h index df02fd63..870ca8a5 100644 --- a/src/devices/nm-lldp-listener.h +++ b/src/devices/nm-lldp-listener.h @@ -21,8 +21,6 @@ #ifndef __NM_LLDP_LISTENER__ #define __NM_LLDP_LISTENER__ -G_BEGIN_DECLS - #define NM_TYPE_LLDP_LISTENER (nm_lldp_listener_get_type ()) #define NM_LLDP_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_LLDP_LISTENER, NMLldpListener)) #define NM_LLDP_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_LLDP_LISTENER, NMLldpListenerClass)) @@ -48,6 +46,4 @@ gboolean nm_lldp_listener_is_running (NMLldpListener *self); GVariant *nm_lldp_listener_get_neighbors (NMLldpListener *self); -G_END_DECLS - #endif /* __NM_LLDP_LISTENER__ */ diff --git a/src/devices/team/Makefile.am b/src/devices/team/Makefile.am index 3609ace4..db756b4c 100644 --- a/src/devices/team/Makefile.am +++ b/src/devices/team/Makefile.am @@ -49,6 +49,7 @@ if ENABLE_TESTS check-local: $(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-device-plugin-team.so $(SYMBOL_VIS_FILE) + LD_BIND_NOW=1 LD_PRELOAD=$(builddir)/.libs/libnm-device-plugin-team.so $(top_builddir)/src/NetworkManager --version >/dev/null endif diff --git a/src/devices/team/Makefile.in b/src/devices/team/Makefile.in index 4ca3014f..922ec593 100644 --- a/src/devices/team/Makefile.in +++ b/src/devices/team/Makefile.in @@ -92,8 +92,9 @@ host_triplet = @host@ @WITH_TEAMDCTL_TRUE@am__append_2 = $(LIBTEAMDCTL_LIBS) subdir = src/devices/team ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \ - $(top_srcdir)/m4/compiler_warnings.m4 \ +am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ + $(top_srcdir)/m4/ax_lib_readline.m4 \ + $(top_srcdir)/m4/compiler_options.m4 \ $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ @@ -256,6 +257,7 @@ DHCLIENT_PATH = @DHCLIENT_PATH@ DHCPCD_PATH = @DHCPCD_PATH@ DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@ DLLTOOL = @DLLTOOL@ +DL_LIBS = @DL_LIBS@ DNSMASQ_PATH = @DNSMASQ_PATH@ DNSSEC_TRIGGER_SCRIPT = @DNSSEC_TRIGGER_SCRIPT@ DSYMUTIL = @DSYMUTIL@ @@ -312,13 +314,14 @@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ IPTABLES_PATH = @IPTABLES_PATH@ +JANSSON_CFLAGS = @JANSSON_CFLAGS@ +JANSSON_LIBS = @JANSSON_LIBS@ KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBAUDIT_CFLAGS = @LIBAUDIT_CFLAGS@ LIBAUDIT_LIBS = @LIBAUDIT_LIBS@ -LIBDL = @LIBDL@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ @@ -330,6 +333,8 @@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@ LIBSOUP_LIBS = @LIBSOUP_LIBS@ +LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ +LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTEAMDCTL_CFLAGS = @LIBTEAMDCTL_CFLAGS@ LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@ LIBTOOL = @LIBTOOL@ @@ -390,6 +395,8 @@ QT_CFLAGS = @QT_CFLAGS@ QT_LIBS = @QT_LIBS@ RANLIB = @RANLIB@ READLINE_LIBS = @READLINE_LIBS@ +SANITIZERS = @SANITIZERS@ +SANITIZER_ENV = @SANITIZER_ENV@ SED = @SED@ SELINUX_CFLAGS = @SELINUX_CFLAGS@ SELINUX_LIBS = @SELINUX_LIBS@ @@ -425,6 +432,7 @@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_RANLIB = @ac_ct_RANLIB@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ @@ -835,6 +843,7 @@ include $(GLIB_MAKEFILE) @ENABLE_TESTS_TRUE@check-local: @ENABLE_TESTS_TRUE@ $(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-device-plugin-team.so $(SYMBOL_VIS_FILE) +@ENABLE_TESTS_TRUE@ LD_BIND_NOW=1 LD_PRELOAD=$(builddir)/.libs/libnm-device-plugin-team.so $(top_builddir)/src/NetworkManager --version >/dev/null # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/src/devices/team/nm-device-team.c b/src/devices/team/nm-device-team.c index b4b522d8..09eefe70 100644 --- a/src/devices/team/nm-device-team.c +++ b/src/devices/team/nm-device-team.c @@ -45,12 +45,18 @@ G_DEFINE_TYPE (NMDeviceTeam, nm_device_team, NM_TYPE_DEVICE) #define NM_DEVICE_TEAM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_TEAM, NMDeviceTeamPrivate)) +NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceTeam, + PROP_CONFIG, +); + typedef struct { struct teamdctl *tdc; GPid teamd_pid; guint teamd_process_watch; guint teamd_timeout; + guint teamd_read_timeout; guint teamd_dbus_watch; + char *config; } NMDeviceTeamPrivate; static gboolean teamd_start (NMDevice *device, NMSettingTeam *s_team); @@ -147,39 +153,74 @@ ensure_teamd_connection (NMDevice *device) return !!priv->tdc; } +static gboolean +teamd_read_config (NMDevice *device) +{ + NMDeviceTeam *self = NM_DEVICE_TEAM (device); + NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (self); + char *config = NULL; + int err; + + if (priv->tdc) { + err = teamdctl_config_actual_get_raw_direct (priv->tdc, &config); + if (err) + return FALSE; + } + + if (!nm_streq0 (config, priv->config)) { + g_free (priv->config); + priv->config = g_strdup (config); + _notify (self, PROP_CONFIG); + } + + return TRUE; +} + +static gboolean +teamd_read_timeout_cb (gpointer user_data) +{ + NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (user_data); + + teamd_read_config ((NMDevice *) user_data); + priv->teamd_read_timeout = 0; + + return G_SOURCE_REMOVE; +} + static void update_connection (NMDevice *device, NMConnection *connection) { NMDeviceTeam *self = NM_DEVICE_TEAM (device); NMSettingTeam *s_team = nm_connection_get_setting_team (connection); NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (self); + struct teamdctl *tdc = priv->tdc; if (!s_team) { s_team = (NMSettingTeam *) nm_setting_team_new (); nm_connection_add_setting (connection, (NMSetting *) s_team); } - g_object_set (G_OBJECT (s_team), NM_SETTING_TEAM_CONFIG, NULL, NULL); - if (priv->tdc) { - const char *config = NULL; - int err; + /* Read the configuration only if not already set */ + if (!priv->config && ensure_teamd_connection (device)) + teamd_read_config (device); - err = teamdctl_config_get_raw_direct (NM_DEVICE_TEAM_GET_PRIVATE (device)->tdc, - (char **)&config); - if (err == 0) - g_object_set (G_OBJECT (s_team), NM_SETTING_TEAM_CONFIG, config, NULL); - else - _LOGE (LOGD_TEAM, "failed to read teamd config (err=%d)", err); + /* Restore previous tdc state */ + if (priv->tdc && !tdc) { + teamdctl_disconnect (priv->tdc); + teamdctl_free (priv->tdc); + priv->tdc = NULL; } + + g_object_set (G_OBJECT (s_team), NM_SETTING_TEAM_CONFIG, priv->config, NULL); } /******************************************************************/ static gboolean master_update_slave_connection (NMDevice *self, - NMDevice *slave, - NMConnection *connection, - GError **error) + NMDevice *slave, + NMConnection *connection, + GError **error) { NMSettingTeamPort *s_port; char *port_config = NULL; @@ -249,6 +290,7 @@ teamd_cleanup (NMDevice *device, gboolean free_tdc) nm_clear_g_source (&priv->teamd_process_watch); nm_clear_g_source (&priv->teamd_timeout); + nm_clear_g_source (&priv->teamd_read_timeout); if (priv->teamd_pid > 0) { nm_utils_kill_child_async (priv->teamd_pid, SIGTERM, LOGD_TEAM, "teamd", 2000, NULL, NULL); @@ -279,6 +321,14 @@ teamd_timeout_cb (gpointer user_data) g_warn_if_fail (nm_device_is_activating (device)); nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED); + } else { + /* Read again the configuration after the timeout since it might + * have changed. + */ + if (!teamd_read_config (device)) { + _LOGW (LOGD_TEAM, "failed to read teamd configuration"); + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED); + } } return G_SOURCE_REMOVE; @@ -339,6 +389,8 @@ teamd_dbus_appeared (GDBusConnection *connection, success = ensure_teamd_connection (device); if (nm_device_get_state (device) == NM_DEVICE_STATE_PREPARE) { if (success) + success = teamd_read_config (device); + if (success) nm_device_activate_schedule_stage2_device_config (device); else if (!nm_device_uses_assumed_connection (device)) nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED); @@ -523,7 +575,7 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) * have a PID, then we must fail. */ cfg = teamdctl_config_get_raw (priv->tdc); - if (cfg && strcmp (cfg, nm_setting_team_get_config (s_team)) == 0) { + if (cfg && nm_streq0 (cfg, nm_setting_team_get_config (s_team))) { _LOGD (LOGD_TEAM, "using existing matching teamd config"); return NM_ACT_STAGE_RETURN_SUCCESS; } @@ -626,6 +678,11 @@ enslave_slave (NMDevice *device, if (!success) return FALSE; + nm_clear_g_source (&priv->teamd_read_timeout); + priv->teamd_read_timeout = g_timeout_add_seconds (5, + teamd_read_timeout_cb, + self); + _LOGI (LOGD_TEAM, "enslaved team port %s", slave_iface); } else _LOGI (LOGD_TEAM, "team port %s was enslaved", slave_iface); @@ -639,6 +696,7 @@ release_slave (NMDevice *device, gboolean configure) { NMDeviceTeam *self = NM_DEVICE_TEAM (device); + NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (device); gboolean success, no_firmware = FALSE; if (configure) { @@ -658,6 +716,11 @@ release_slave (NMDevice *device, if (!nm_device_bring_up (slave, TRUE, &no_firmware)) _LOGW (LOGD_TEAM, "released team port %s could not be brought up", nm_device_get_ip_iface (slave)); + + nm_clear_g_source (&priv->teamd_read_timeout); + priv->teamd_read_timeout = g_timeout_add_seconds (5, + teamd_read_timeout_cb, + self); } else _LOGI (LOGD_TEAM, "team port %s was released", nm_device_get_ip_iface (slave)); } @@ -701,6 +764,23 @@ nm_device_team_new (const char *iface) } static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMDeviceTeam *self = NM_DEVICE_TEAM (object); + NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (self); + + switch (prop_id) { + case PROP_CONFIG: + g_value_set_string (value, priv->config); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void nm_device_team_init (NMDeviceTeam * self) { } @@ -738,6 +818,7 @@ dispose (GObject *object) } teamd_cleanup (device, TRUE); + g_clear_pointer (&priv->config, g_free); G_OBJECT_CLASS (nm_device_team_parent_class)->dispose (object); } @@ -754,6 +835,7 @@ nm_device_team_class_init (NMDeviceTeamClass *klass) object_class->constructed = constructed; object_class->dispose = dispose; + object_class->get_property = get_property; parent_class->create_and_realize = create_and_realize; parent_class->get_generic_capabilities = get_generic_capabilities; @@ -770,6 +852,14 @@ nm_device_team_class_init (NMDeviceTeamClass *klass) parent_class->enslave_slave = enslave_slave; parent_class->release_slave = release_slave; + obj_properties[PROP_CONFIG] = + g_param_spec_string (NM_DEVICE_TEAM_CONFIG, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), NMDBUS_TYPE_DEVICE_TEAM_SKELETON, NULL); diff --git a/src/devices/team/nm-device-team.h b/src/devices/team/nm-device-team.h index 0e81afa7..43e8aab4 100644 --- a/src/devices/team/nm-device-team.h +++ b/src/devices/team/nm-device-team.h @@ -23,8 +23,6 @@ #include "nm-device.h" -G_BEGIN_DECLS - #define NM_TYPE_DEVICE_TEAM (nm_device_team_get_type ()) #define NM_DEVICE_TEAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_TEAM, NMDeviceTeam)) #define NM_DEVICE_TEAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_TEAM, NMDeviceTeamClass)) @@ -32,6 +30,9 @@ G_BEGIN_DECLS #define NM_IS_DEVICE_TEAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_TEAM)) #define NM_DEVICE_TEAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_TEAM, NMDeviceTeamClass)) +/* Properties */ +#define NM_DEVICE_TEAM_CONFIG "config" + typedef NMDevice NMDeviceTeam; typedef NMDeviceClass NMDeviceTeamClass; @@ -39,6 +40,4 @@ GType nm_device_team_get_type (void); NMDevice *nm_device_team_new (const char *iface); -G_END_DECLS - -#endif /* NM_DEVICE_TEAM_H */ +#endif /* __NETWORKMANAGER_DEVICE_TEAM_H__ */ diff --git a/src/devices/team/nm-team-factory.h b/src/devices/team/nm-team-factory.h index 9049478d..4155870c 100644 --- a/src/devices/team/nm-team-factory.h +++ b/src/devices/team/nm-team-factory.h @@ -21,8 +21,6 @@ #ifndef __NETWORKMANAGER_TEAM_FACTORY_H__ #define __NETWORKMANAGER_TEAM_FACTORY_H__ -#include "nm-default.h" - #define NM_TYPE_TEAM_FACTORY (nm_team_factory_get_type ()) #define NM_TEAM_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_TEAM_FACTORY, NMTeamFactory)) diff --git a/src/devices/tests/Makefile.in b/src/devices/tests/Makefile.in index b07e6dfd..7c25dc11 100644 --- a/src/devices/tests/Makefile.in +++ b/src/devices/tests/Makefile.in @@ -92,8 +92,9 @@ noinst_PROGRAMS = test-lldp$(EXEEXT) test-arping$(EXEEXT) TESTS = test-lldp$(EXEEXT) test-arping$(EXEEXT) subdir = src/devices/tests ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \ - $(top_srcdir)/m4/compiler_warnings.m4 \ +am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ + $(top_srcdir)/m4/ax_lib_readline.m4 \ + $(top_srcdir)/m4/compiler_options.m4 \ $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ @@ -428,6 +429,7 @@ DHCLIENT_PATH = @DHCLIENT_PATH@ DHCPCD_PATH = @DHCPCD_PATH@ DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@ DLLTOOL = @DLLTOOL@ +DL_LIBS = @DL_LIBS@ DNSMASQ_PATH = @DNSMASQ_PATH@ DNSSEC_TRIGGER_SCRIPT = @DNSSEC_TRIGGER_SCRIPT@ DSYMUTIL = @DSYMUTIL@ @@ -484,13 +486,14 @@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ IPTABLES_PATH = @IPTABLES_PATH@ +JANSSON_CFLAGS = @JANSSON_CFLAGS@ +JANSSON_LIBS = @JANSSON_LIBS@ KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBAUDIT_CFLAGS = @LIBAUDIT_CFLAGS@ LIBAUDIT_LIBS = @LIBAUDIT_LIBS@ -LIBDL = @LIBDL@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ @@ -502,6 +505,8 @@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@ LIBSOUP_LIBS = @LIBSOUP_LIBS@ +LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ +LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTEAMDCTL_CFLAGS = @LIBTEAMDCTL_CFLAGS@ LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@ LIBTOOL = @LIBTOOL@ @@ -562,6 +567,8 @@ QT_CFLAGS = @QT_CFLAGS@ QT_LIBS = @QT_LIBS@ RANLIB = @RANLIB@ READLINE_LIBS = @READLINE_LIBS@ +SANITIZERS = @SANITIZERS@ +SANITIZER_ENV = @SANITIZER_ENV@ SED = @SED@ SELINUX_CFLAGS = @SELINUX_CFLAGS@ SELINUX_LIBS = @SELINUX_LIBS@ @@ -597,6 +604,7 @@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_RANLIB = @ac_ct_RANLIB@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ diff --git a/src/devices/tests/test-lldp.c b/src/devices/tests/test-lldp.c index bff85e6c..ff6f42a9 100644 --- a/src/devices/tests/test-lldp.c +++ b/src/devices/tests/test-lldp.c @@ -33,7 +33,7 @@ #include "test-common.h" -#include "nm-test-utils.h" +#include "nm-test-utils-core.h" /*****************************************************************************/ diff --git a/src/devices/wifi/Makefile.am b/src/devices/wifi/Makefile.am index e35a84b4..add0a007 100644 --- a/src/devices/wifi/Makefile.am +++ b/src/devices/wifi/Makefile.am @@ -52,6 +52,7 @@ if ENABLE_TESTS check-local: $(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-device-plugin-wifi.so $(SYMBOL_VIS_FILE) + LD_BIND_NOW=1 LD_PRELOAD=$(builddir)/.libs/libnm-device-plugin-wifi.so $(top_builddir)/src/NetworkManager --version >/dev/null endif diff --git a/src/devices/wifi/Makefile.in b/src/devices/wifi/Makefile.in index 34aa4b97..134c4012 100644 --- a/src/devices/wifi/Makefile.in +++ b/src/devices/wifi/Makefile.in @@ -90,8 +90,9 @@ build_triplet = @build@ host_triplet = @host@ subdir = src/devices/wifi ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \ - $(top_srcdir)/m4/compiler_warnings.m4 \ +am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ + $(top_srcdir)/m4/ax_lib_readline.m4 \ + $(top_srcdir)/m4/compiler_options.m4 \ $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ @@ -295,6 +296,7 @@ DHCLIENT_PATH = @DHCLIENT_PATH@ DHCPCD_PATH = @DHCPCD_PATH@ DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@ DLLTOOL = @DLLTOOL@ +DL_LIBS = @DL_LIBS@ DNSMASQ_PATH = @DNSMASQ_PATH@ DNSSEC_TRIGGER_SCRIPT = @DNSSEC_TRIGGER_SCRIPT@ DSYMUTIL = @DSYMUTIL@ @@ -351,13 +353,14 @@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ IPTABLES_PATH = @IPTABLES_PATH@ +JANSSON_CFLAGS = @JANSSON_CFLAGS@ +JANSSON_LIBS = @JANSSON_LIBS@ KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBAUDIT_CFLAGS = @LIBAUDIT_CFLAGS@ LIBAUDIT_LIBS = @LIBAUDIT_LIBS@ -LIBDL = @LIBDL@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ @@ -369,6 +372,8 @@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@ LIBSOUP_LIBS = @LIBSOUP_LIBS@ +LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ +LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTEAMDCTL_CFLAGS = @LIBTEAMDCTL_CFLAGS@ LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@ LIBTOOL = @LIBTOOL@ @@ -429,6 +434,8 @@ QT_CFLAGS = @QT_CFLAGS@ QT_LIBS = @QT_LIBS@ RANLIB = @RANLIB@ READLINE_LIBS = @READLINE_LIBS@ +SANITIZERS = @SANITIZERS@ +SANITIZER_ENV = @SANITIZER_ENV@ SED = @SED@ SELINUX_CFLAGS = @SELINUX_CFLAGS@ SELINUX_LIBS = @SELINUX_LIBS@ @@ -464,6 +471,7 @@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_RANLIB = @ac_ct_RANLIB@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ @@ -967,6 +975,7 @@ include $(GLIB_MAKEFILE) @ENABLE_TESTS_TRUE@check-local: @ENABLE_TESTS_TRUE@ $(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-device-plugin-wifi.so $(SYMBOL_VIS_FILE) +@ENABLE_TESTS_TRUE@ LD_BIND_NOW=1 LD_PRELOAD=$(builddir)/.libs/libnm-device-plugin-wifi.so $(top_builddir)/src/NetworkManager --version >/dev/null # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/src/devices/wifi/nm-device-olpc-mesh.h b/src/devices/wifi/nm-device-olpc-mesh.h index 63895a88..135226d5 100644 --- a/src/devices/wifi/nm-device-olpc-mesh.h +++ b/src/devices/wifi/nm-device-olpc-mesh.h @@ -30,8 +30,6 @@ #include "nm-device.h" -G_BEGIN_DECLS - #define NM_TYPE_DEVICE_OLPC_MESH (nm_device_olpc_mesh_get_type ()) #define NM_DEVICE_OLPC_MESH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_OLPC_MESH, NMDeviceOlpcMesh)) #define NM_DEVICE_OLPC_MESH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_OLPC_MESH, NMDeviceOlpcMeshClass)) @@ -67,6 +65,4 @@ GType nm_device_olpc_mesh_get_type (void); NMDevice *nm_device_olpc_mesh_new (const char *iface); -G_END_DECLS - -#endif /* NM_DEVICE_OLPC_MESH_H */ +#endif /* __NETWORKMANAGER_DEVICE_OLPC_MESH_H__ */ diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index 82b12a11..49c380af 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -21,6 +21,8 @@ #include "nm-default.h" +#include "nm-device-wifi.h" + #include <netinet/in.h> #include <string.h> #include <unistd.h> @@ -28,7 +30,6 @@ #include "nm-common-macros.h" #include "nm-device.h" -#include "nm-device-wifi.h" #include "nm-device-private.h" #include "nm-utils.h" #include "NetworkManagerUtils.h" @@ -46,8 +47,8 @@ #include "nm-platform.h" #include "nm-auth-utils.h" #include "nm-settings-connection.h" +#include "nm-settings.h" #include "nm-enum-types.h" -#include "nm-connection-provider.h" #include "nm-core-internal.h" #include "nm-config.h" @@ -61,25 +62,20 @@ _LOG_DECLARE_SELF(NMDeviceWifi); #define SCAN_INTERVAL_STEP 20 #define SCAN_INTERVAL_MAX 120 -#define WIRELESS_SECRETS_TRIES "wireless-secrets-tries" +#define SCAN_RAND_MAC_ADDRESS_EXPIRE_MIN 5 -G_DEFINE_TYPE (NMDeviceWifi, nm_device_wifi, NM_TYPE_DEVICE) - -#define NM_DEVICE_WIFI_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_WIFI, NMDeviceWifiPrivate)) +#define WIRELESS_SECRETS_TRIES "wireless-secrets-tries" +/*****************************************************************************/ -enum { - PROP_0, - PROP_PERM_HW_ADDRESS, +NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceWifi, PROP_MODE, PROP_BITRATE, PROP_ACCESS_POINTS, PROP_ACTIVE_ACCESS_POINT, PROP_CAPABILITIES, PROP_SCANNING, - - LAST_PROP -}; +); enum { ACCESS_POINT_ADDED, @@ -91,26 +87,26 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; -struct _NMDeviceWifiPrivate { +typedef struct { gint8 invalid_strength_counter; GHashTable * aps; NMAccessPoint * current_ap; guint32 rate; - gboolean enabled; /* rfkilled or not */ + bool enabled:1; /* rfkilled or not */ + bool requested_scan:1; + bool ssid_found:1; gint32 last_scan; gint32 scheduled_scan_time; guint8 scan_interval; /* seconds */ guint pending_scan_id; guint ap_dump_id; - bool requested_scan; NMSupplicantManager *sup_mgr; NMSupplicantInterface *sup_iface; guint sup_timeout_id; /* supplicant association timeout */ - bool ssid_found; NM80211Mode mode; guint periodic_source_id; @@ -119,8 +115,44 @@ struct _NMDeviceWifiPrivate { guint reacquire_iface_id; NMDeviceWifiCapabilities capabilities; + + gint32 hw_addr_scan_expire; + char *hw_addr_scan; +} NMDeviceWifiPrivate; + +struct _NMDeviceWifi +{ + NMDevice parent; + NMDeviceWifiPrivate _priv; }; +struct _NMDeviceWifiClass +{ + NMDeviceClass parent; + + /* Signals */ + gboolean (*scanning_allowed) (NMDeviceWifi *device); +}; + +/*****************************************************************************/ + +G_DEFINE_TYPE (NMDeviceWifi, nm_device_wifi, NM_TYPE_DEVICE) + +#define NM_DEVICE_WIFI_GET_PRIVATE(self) \ + ({ \ + /* preserve the const-ness of self. Unfortunately, that + * way, @self cannot be a void pointer */ \ + typeof (self) _self = (self); \ + \ + /* Get compiler error if variable is of wrong type */ \ + _nm_unused const NMDeviceWifi *_self2 = (_self); \ + \ + nm_assert (NM_IS_DEVICE_WIFI (_self)); \ + &_self->_priv; \ + }) + +/*****************************************************************************/ + static gboolean check_scanning_allowed (NMDeviceWifi *self); static void schedule_scan (NMDeviceWifi *self, gboolean backoff); @@ -169,7 +201,9 @@ static void ap_add_remove (NMDeviceWifi *self, static void remove_supplicant_interface_error_handler (NMDeviceWifi *self); -/*****************************************************************/ +static void _hw_addr_set_scanning (NMDeviceWifi *self, gboolean do_reset); + +/*****************************************************************************/ static void constructed (GObject *object) @@ -187,6 +221,18 @@ constructed (GObject *object) } static gboolean +unmanaged_on_quit (NMDevice *self) +{ + /* Wi-Fi devices cannot be assumed and are always taken down. + * However, also when being disconnected, we scan and thus + * set the MAC address to a random value. + * + * We must restore the original MAC address when quitting, thus + * signal to unmanage the device. */ + return TRUE; +} + +static gboolean supplicant_interface_acquire (NMDeviceWifi *self) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); @@ -238,6 +284,24 @@ supplicant_interface_acquire (NMDeviceWifi *self) } static void +_requested_scan_set (NMDeviceWifi *self, gboolean value) +{ + NMDeviceWifiPrivate *priv; + + value = !!value; + + priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + if (priv->requested_scan == value) + return; + + priv->requested_scan = value; + if (value) + nm_device_add_pending_action ((NMDevice *) self, "scan", TRUE); + else + nm_device_remove_pending_action ((NMDevice *) self, "scan", TRUE); +} + +static void supplicant_interface_release (NMDeviceWifi *self) { NMDeviceWifiPrivate *priv; @@ -246,6 +310,8 @@ supplicant_interface_release (NMDeviceWifi *self) priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + _requested_scan_set (self, FALSE); + nm_clear_g_source (&priv->pending_scan_id); /* Reset the scan interval to be pretty frequent when disconnected */ @@ -340,7 +406,7 @@ set_current_ap (NMDeviceWifi *self, NMAccessPoint *new_ap, gboolean recheck_avai g_object_unref (old_ap); } - g_object_notify (G_OBJECT (self), NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT); + _notify (self, PROP_ACTIVE_ACCESS_POINT); } static void @@ -386,7 +452,7 @@ periodic_update (NMDeviceWifi *self) new_rate = nm_platform_wifi_get_rate (NM_PLATFORM_GET, ifindex); if (new_rate != priv->rate) { priv->rate = new_rate; - g_object_notify (G_OBJECT (self), NM_DEVICE_WIFI_BITRATE); + _notify (self, PROP_BITRATE); } } @@ -397,18 +463,10 @@ periodic_update_cb (gpointer user_data) return TRUE; } -static void -realize_start_notify (NMDevice *device, const NMPlatformLink *plink) -{ - NM_DEVICE_CLASS (nm_device_wifi_parent_class)->realize_start_notify (device, plink); - - g_object_notify (G_OBJECT (device), NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS); -} - static gboolean bring_up (NMDevice *device, gboolean *no_firmware) { - if (!NM_DEVICE_WIFI_GET_PRIVATE (device)->enabled) + if (!NM_DEVICE_WIFI_GET_PRIVATE ((NMDeviceWifi *) device)->enabled) return FALSE; return NM_DEVICE_CLASS (nm_device_wifi_parent_class)->bring_up (device, no_firmware); @@ -431,7 +489,7 @@ ap_add_remove (NMDeviceWifi *self, } g_signal_emit (self, signals[signum], 0, ap); - g_object_notify (G_OBJECT (self), NM_DEVICE_WIFI_ACCESS_POINTS); + _notify (self, PROP_ACCESS_POINTS); if (signum == ACCESS_POINT_REMOVED) { g_hash_table_remove (priv->aps, nm_exported_object_get_path ((NMExportedObject *) ap)); @@ -485,10 +543,6 @@ deactivate (NMDevice *device) /* Clear any critical protocol notification in the Wi-Fi stack */ nm_platform_wifi_indicate_addressing_running (NM_PLATFORM_GET, ifindex, FALSE); - /* Reset MAC address back to initial address */ - if (nm_device_get_initial_hw_address (device)) - nm_device_set_hw_addr (device, nm_device_get_initial_hw_address (device), "reset", LOGD_WIFI); - /* Ensure we're in infrastructure mode after deactivation; some devices * (usually older ones) don't scan well in adhoc mode. */ @@ -500,7 +554,7 @@ deactivate (NMDevice *device) if (priv->mode != NM_802_11_MODE_INFRA) { priv->mode = NM_802_11_MODE_INFRA; - g_object_notify (G_OBJECT (self), NM_DEVICE_WIFI_MODE); + _notify (self, PROP_MODE); } /* Ensure we trigger a scan after deactivating a Hotspot */ @@ -510,6 +564,12 @@ deactivate (NMDevice *device) } } +static void +deactivate_reset_hw_addr (NMDevice *device) +{ + _hw_addr_set_scanning ((NMDeviceWifi *) device, TRUE); +} + static gboolean is_adhoc_wpa (NMConnection *connection) { @@ -566,7 +626,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection) if (!s_wireless) return FALSE; - perm_hw_addr = nm_device_get_permanent_hw_address (device); + perm_hw_addr = nm_device_get_permanent_hw_address (device, FALSE); mac = nm_setting_wireless_get_mac_address (s_wireless); if (perm_hw_addr) { if (mac && !nm_utils_hwaddr_matches (mac, -1, perm_hw_addr, -1)) @@ -679,35 +739,31 @@ check_connection_available (NMDevice *device, return !!find_first_compatible_ap (NM_DEVICE_WIFI (device), connection, TRUE); } -/* - * List of manufacturer default SSIDs that are often unchanged by users. - * - * NOTE: this list should *not* contain networks that you would like to - * automatically roam to like "Starbucks" or "AT&T" or "T-Mobile HotSpot". - */ -static const char * -manf_defaults[] = { - "linksys", - "linksys-a", - "linksys-g", - "default", - "belkin54g", - "NETGEAR", - "o2DSL", - "WLAN", - "ALICE-WLAN", - "Speedport W 501V", - "TURBONETT", -}; - -#define ARRAY_SIZE(a) (sizeof (a) / sizeof (a[0])) - static gboolean is_manf_default_ssid (const GByteArray *ssid) { int i; - - for (i = 0; i < ARRAY_SIZE (manf_defaults); i++) { + /* + * List of manufacturer default SSIDs that are often unchanged by users. + * + * NOTE: this list should *not* contain networks that you would like to + * automatically roam to like "Starbucks" or "AT&T" or "T-Mobile HotSpot". + */ + static const char *manf_defaults[] = { + "linksys", + "linksys-a", + "linksys-g", + "default", + "belkin54g", + "NETGEAR", + "o2DSL", + "WLAN", + "ALICE-WLAN", + "Speedport W 501V", + "TURBONETT", + }; + + for (i = 0; i < G_N_ELEMENTS (manf_defaults); i++) { if (ssid->len == strlen (manf_defaults[i])) { if (memcmp (manf_defaults[i], ssid->data, ssid->len) == 0) return TRUE; @@ -862,7 +918,7 @@ complete_connection (NMDevice *device, if (hidden) g_object_set (s_wifi, NM_SETTING_WIRELESS_HIDDEN, TRUE, NULL); - perm_hw_addr = nm_device_get_permanent_hw_address (device); + perm_hw_addr = nm_device_get_permanent_hw_address (device, FALSE); if (perm_hw_addr) { setting_mac = nm_setting_wireless_get_mac_address (s_wifi); if (setting_mac) { @@ -1022,6 +1078,60 @@ impl_device_wifi_get_all_access_points (NMDeviceWifi *self, } static void +_hw_addr_set_scanning (NMDeviceWifi *self, gboolean do_reset) +{ + NMDevice *device = (NMDevice *) self; + NMDeviceWifiPrivate *priv; + guint32 now; + gboolean randomize; + + g_return_if_fail (NM_IS_DEVICE_WIFI (self)); + + if ( nm_device_is_activating (device) + || nm_device_get_state (device) == NM_DEVICE_STATE_ACTIVATED) + return; + + priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + + randomize = nm_config_data_get_device_config_boolean (NM_CONFIG_GET_DATA, + "wifi.scan-rand-mac-address", + device, + TRUE, TRUE); + + if (!randomize) { + g_clear_pointer (&priv->hw_addr_scan, g_free); + if (do_reset) + nm_device_hw_addr_reset (device, "scanning"); + return; + } + + now = nm_utils_get_monotonic_timestamp_s (); + + if ( !priv->hw_addr_scan + || now >= priv->hw_addr_scan_expire) { + gs_free char *generate_mac_address_mask = NULL; + + /* the random MAC address for scanning expires after a while. + * + * We don't bother with to update the MAC address exactly when + * it expires, instead on the next scan request, we will generate + * a new one.*/ + priv->hw_addr_scan_expire = now + (SCAN_RAND_MAC_ADDRESS_EXPIRE_MIN * 60); + + generate_mac_address_mask = nm_config_data_get_device_config (NM_CONFIG_GET_DATA, + "wifi.scan-generate-mac-address-mask", + device, + NULL); + + g_free (priv->hw_addr_scan); + priv->hw_addr_scan = nm_utils_hw_addr_gen_random_eth (nm_device_get_initial_hw_address (device), + generate_mac_address_mask); + } + + nm_device_hw_addr_set (device, priv->hw_addr_scan, "scanning"); +} + +static void request_scan_cb (NMDevice *device, GDBusMethodInvocation *context, NMAuthSubject *subject, @@ -1199,7 +1309,7 @@ check_scanning_allowed (NMDeviceWifi *self) } static gboolean -hidden_filter_func (NMConnectionProvider *provider, +hidden_filter_func (NMSettings *settings, NMConnection *connection, gpointer user_data) { @@ -1226,12 +1336,12 @@ build_hidden_probe_list (NMDeviceWifi *self) if (G_UNLIKELY (nullssid == NULL)) nullssid = g_byte_array_new (); - connections = nm_connection_provider_get_best_connections (nm_connection_provider_get (), - max_scan_ssids - 1, - NM_SETTING_WIRELESS_SETTING_NAME, - NULL, - hidden_filter_func, - NULL); + connections = nm_settings_get_best_connections (nm_device_get_settings ((NMDevice *) self), + max_scan_ssids - 1, + NM_SETTING_WIRELESS_SETTING_NAME, + NULL, + hidden_filter_func, + NULL); if (connections && connections->data) { ssids = g_ptr_array_new_full (max_scan_ssids - 1, (GDestroyNotify) g_byte_array_unref); g_ptr_array_add (ssids, g_byte_array_ref (nullssid)); /* Add wildcard SSID */ @@ -1330,11 +1440,12 @@ request_wireless_scan (NMDeviceWifi *self, GVariant *scan_options) _LOGD (LOGD_WIFI_SCAN, "no SSIDs to probe scan"); } + _hw_addr_set_scanning (self, FALSE); + if (nm_supplicant_interface_request_scan (priv->sup_iface, ssids)) { /* success */ backoff = TRUE; - priv->requested_scan = TRUE; - nm_device_add_pending_action (NM_DEVICE (self), "scan", TRUE); + _requested_scan_set (self, TRUE); } if (ssids) @@ -1349,10 +1460,11 @@ request_wireless_scan (NMDeviceWifi *self, GVariant *scan_options) static gboolean request_wireless_scan_periodic (gpointer user_data) { - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (user_data); + NMDeviceWifi *self = user_data; + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); priv->pending_scan_id = 0; - request_wireless_scan (user_data, NULL); + request_wireless_scan (self, NULL); return FALSE; } @@ -1416,10 +1528,7 @@ supplicant_iface_scan_done_cb (NMSupplicantInterface *iface, priv->last_scan = nm_utils_get_monotonic_timestamp_s (); schedule_scan (self, success); - if (priv->requested_scan) { - priv->requested_scan = FALSE; - nm_device_remove_pending_action (NM_DEVICE (self), "scan", TRUE); - } + _requested_scan_set (self, FALSE); } /**************************************************************************** @@ -1458,10 +1567,12 @@ schedule_ap_list_dump (NMDeviceWifi *self) } static void -try_fill_ssid_for_hidden_ap (NMAccessPoint *ap) +try_fill_ssid_for_hidden_ap (NMDeviceWifi *self, + NMAccessPoint *ap) { const char *bssid; - const GSList *connections, *iter; + NMSettingsConnection *const*connections; + guint i; g_return_if_fail (nm_ap_get_ssid (ap) == NULL); @@ -1470,9 +1581,9 @@ try_fill_ssid_for_hidden_ap (NMAccessPoint *ap) /* Look for this AP's BSSID in the seen-bssids list of a connection, * and if a match is found, copy over the SSID */ - connections = nm_connection_provider_get_connections (nm_connection_provider_get ()); - for (iter = connections; iter; iter = g_slist_next (iter)) { - NMConnection *connection = NM_CONNECTION (iter->data); + connections = nm_settings_get_connections (nm_device_get_settings ((NMDevice *) self), NULL); + for (i = 0; connections[i]; i++) { + NMConnection *connection = (NMConnection *) connections[i]; NMSettingWireless *s_wifi; s_wifi = nm_connection_get_setting_wireless (connection); @@ -1522,7 +1633,7 @@ supplicant_iface_new_bss_cb (NMSupplicantInterface *iface, ssid = nm_ap_get_ssid (ap); if (!ssid || nm_utils_is_empty_ssid (ssid->data, ssid->len)) { /* Try to fill the SSID from the AP database */ - try_fill_ssid_for_hidden_ap (ap); + try_fill_ssid_for_hidden_ap (self, ap); ssid = nm_ap_get_ssid (ap); if (ssid && (nm_utils_is_empty_ssid (ssid->data, ssid->len) == FALSE)) { @@ -1951,6 +2062,11 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface, else _LOGI (LOGD_DEVICE | LOGD_WIFI, "supplicant interface keeps failing, giving up"); break; + case NM_SUPPLICANT_INTERFACE_STATE_INACTIVE: + _requested_scan_set (self, FALSE); + nm_clear_g_source (&priv->pending_scan_id); + request_wireless_scan (self, NULL); + break; default: break; } @@ -1964,7 +2080,7 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface, /* Signal scanning state changes */ if ( new_state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING || old_state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING) - g_object_notify (G_OBJECT (self), "scanning"); + _notify (self, PROP_SCANNING); } static void @@ -2008,7 +2124,7 @@ supplicant_iface_notify_scanning_cb (NMSupplicantInterface *iface, scanning = nm_supplicant_interface_get_scanning (iface); _LOGD (LOGD_WIFI_SCAN, "now %s", scanning ? "scanning" : "idle"); - g_object_notify (G_OBJECT (self), "scanning"); + _notify (self, PROP_SCANNING); /* Run a quick update of current AP when coming out of a scan */ state = nm_device_get_state (NM_DEVICE (self)); @@ -2197,9 +2313,6 @@ build_supplicant_config (NMDeviceWifi *self, NMSupplicantConfig *config = NULL; NMSettingWireless *s_wireless; NMSettingWirelessSecurity *s_wireless_sec; - NMSupplicantFeature mac_randomization_support; - NMSettingMacRandomization mac_randomization_fallback; - gs_free char *svalue = NULL; g_return_val_if_fail (priv->sup_iface, NULL); @@ -2214,20 +2327,9 @@ build_supplicant_config (NMDeviceWifi *self, _LOGW (LOGD_WIFI, "Supplicant may not support AP mode; connection may time out."); } - mac_randomization_support = nm_supplicant_interface_get_mac_randomization_support (priv->sup_iface); - svalue = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA, - "wifi." NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION, - NM_DEVICE (self)); - mac_randomization_fallback = _nm_utils_ascii_str_to_int64 (svalue, 10, - NM_SETTING_MAC_RANDOMIZATION_DEFAULT, - NM_SETTING_MAC_RANDOMIZATION_ALWAYS, - NM_SETTING_MAC_RANDOMIZATION_DEFAULT); - if (!nm_supplicant_config_add_setting_wireless (config, s_wireless, fixed_freq, - mac_randomization_support, - mac_randomization_fallback, error)) { g_prefix_error (error, "802-11-wireless: "); goto error; @@ -2277,7 +2379,6 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) NMActRequest *req; NMConnection *connection; NMSettingWireless *s_wireless; - const char *cloned_mac; const char *mode; const char *ap_path; @@ -2305,7 +2406,7 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) /* Scanning not done in AP mode; clear the scan list */ remove_all_aps (self); } - g_object_notify (G_OBJECT (self), NM_DEVICE_WIFI_MODE); + _notify (self, PROP_MODE); /* The kernel doesn't support Ad-Hoc WPA connections well at this time, * and turns them into open networks. It's been this way since at least @@ -2317,9 +2418,12 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) return NM_ACT_STAGE_RETURN_FAILURE; } + /* forget the temporary MAC address used during scanning */ + g_clear_pointer (&priv->hw_addr_scan, g_free); + /* Set spoof MAC to the interface */ - cloned_mac = nm_setting_wireless_get_cloned_mac_address (s_wireless); - nm_device_set_hw_addr (device, cloned_mac, "set", LOGD_WIFI); + if (!nm_device_hw_addr_set_cloned (device, connection, TRUE)) + return NM_ACT_STAGE_RETURN_FAILURE; /* AP mode never uses a specific object or existing scanned AP */ if (priv->mode != NM_802_11_MODE_AP) { @@ -2859,6 +2963,8 @@ set_enabled (NMDevice *device, gboolean enabled) NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); NMDeviceState state; + enabled = !!enabled; + if (priv->enabled == enabled) return; @@ -2959,6 +3065,8 @@ finalize (GObject *object) g_hash_table_unref (priv->aps); + g_free (priv->hw_addr_scan); + G_OBJECT_CLASS (nm_device_wifi_parent_class)->finalize (object); } @@ -2973,9 +3081,6 @@ get_property (GObject *object, guint prop_id, GPtrArray *array; switch (prop_id) { - case PROP_PERM_HW_ADDRESS: - g_value_set_string (value, nm_device_get_permanent_hw_address (NM_DEVICE (device))); - break; case PROP_MODE: g_value_set_uint (value, priv->mode); break; @@ -3030,8 +3135,6 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass) GObjectClass *object_class = G_OBJECT_CLASS (klass); NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); - g_type_class_add_private (object_class, sizeof (NMDeviceWifiPrivate)); - NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_WIRELESS_SETTING_NAME, NM_LINK_TYPE_WIFI) object_class->constructed = constructed; @@ -3040,7 +3143,6 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass) object_class->dispose = dispose; object_class->finalize = finalize; - parent_class->realize_start_notify = realize_start_notify; parent_class->bring_up = bring_up; parent_class->can_auto_connect = can_auto_connect; parent_class->is_available = is_available; @@ -3057,90 +3159,81 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass) parent_class->act_stage4_ip4_config_timeout = act_stage4_ip4_config_timeout; parent_class->act_stage4_ip6_config_timeout = act_stage4_ip6_config_timeout; parent_class->deactivate = deactivate; + parent_class->deactivate_reset_hw_addr = deactivate_reset_hw_addr; + parent_class->unmanaged_on_quit = unmanaged_on_quit; parent_class->state_changed = device_state_changed; klass->scanning_allowed = scanning_allowed; /* Properties */ - g_object_class_install_property - (object_class, PROP_PERM_HW_ADDRESS, - g_param_spec_string (NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_MODE, - g_param_spec_uint (NM_DEVICE_WIFI_MODE, "", "", - NM_802_11_MODE_UNKNOWN, - NM_802_11_MODE_AP, - NM_802_11_MODE_INFRA, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_BITRATE, - g_param_spec_uint (NM_DEVICE_WIFI_BITRATE, "", "", - 0, G_MAXUINT32, 0, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_ACCESS_POINTS, - g_param_spec_boxed (NM_DEVICE_WIFI_ACCESS_POINTS, "", "", - G_TYPE_STRV, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_ACTIVE_ACCESS_POINT, - g_param_spec_string (NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_CAPABILITIES, - g_param_spec_uint (NM_DEVICE_WIFI_CAPABILITIES, "", "", - 0, G_MAXUINT32, NM_WIFI_DEVICE_CAP_NONE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_SCANNING, - g_param_spec_boolean (NM_DEVICE_WIFI_SCANNING, "", "", - FALSE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_MODE] = + g_param_spec_uint (NM_DEVICE_WIFI_MODE, "", "", + NM_802_11_MODE_UNKNOWN, + NM_802_11_MODE_AP, + NM_802_11_MODE_INFRA, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_BITRATE] = + g_param_spec_uint (NM_DEVICE_WIFI_BITRATE, "", "", + 0, G_MAXUINT32, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_ACCESS_POINTS] = + g_param_spec_boxed (NM_DEVICE_WIFI_ACCESS_POINTS, "", "", + G_TYPE_STRV, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_ACTIVE_ACCESS_POINT] = + g_param_spec_string (NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_CAPABILITIES] = + g_param_spec_uint (NM_DEVICE_WIFI_CAPABILITIES, "", "", + 0, G_MAXUINT32, NM_WIFI_DEVICE_CAP_NONE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_SCANNING] = + g_param_spec_boolean (NM_DEVICE_WIFI_SCANNING, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); /* Signals */ signals[ACCESS_POINT_ADDED] = - g_signal_new ("access-point-added", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMDeviceWifiClass, access_point_added), - NULL, NULL, NULL, - G_TYPE_NONE, 1, - NM_TYPE_AP); + g_signal_new ("access-point-added", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, NULL, + G_TYPE_NONE, 1, + NM_TYPE_AP); signals[ACCESS_POINT_REMOVED] = - g_signal_new ("access-point-removed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 1, - NM_TYPE_AP); + g_signal_new ("access-point-removed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, NULL, + G_TYPE_NONE, 1, + NM_TYPE_AP); signals[SCANNING_ALLOWED] = - g_signal_new ("scanning-allowed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMDeviceWifiClass, scanning_allowed), - scanning_allowed_accumulator, NULL, NULL, - G_TYPE_BOOLEAN, 0); + g_signal_new ("scanning-allowed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NMDeviceWifiClass, scanning_allowed), + scanning_allowed_accumulator, NULL, NULL, + G_TYPE_BOOLEAN, 0); nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), NMDBUS_TYPE_DEVICE_WIFI_SKELETON, diff --git a/src/devices/wifi/nm-device-wifi.h b/src/devices/wifi/nm-device-wifi.h index 7e0d06f5..ba9d60e2 100644 --- a/src/devices/wifi/nm-device-wifi.h +++ b/src/devices/wifi/nm-device-wifi.h @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2005 - 2010 Red Hat, Inc. + * Copyright (C) 2005 - 2016 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ @@ -25,18 +25,13 @@ #include "nm-device.h" #include "nm-wifi-ap.h" -struct NMAccessPointList; +#define NM_TYPE_DEVICE_WIFI (nm_device_wifi_get_type ()) +#define NM_DEVICE_WIFI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_WIFI, NMDeviceWifi)) +#define NM_DEVICE_WIFI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_WIFI, NMDeviceWifiClass)) +#define NM_IS_DEVICE_WIFI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_WIFI)) +#define NM_IS_DEVICE_WIFI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_WIFI)) +#define NM_DEVICE_WIFI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_WIFI, NMDeviceWifiClass)) -G_BEGIN_DECLS - -#define NM_TYPE_DEVICE_WIFI (nm_device_wifi_get_type ()) -#define NM_DEVICE_WIFI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_WIFI, NMDeviceWifi)) -#define NM_DEVICE_WIFI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_WIFI, NMDeviceWifiClass)) -#define NM_IS_DEVICE_WIFI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_WIFI)) -#define NM_IS_DEVICE_WIFI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_WIFI)) -#define NM_DEVICE_WIFI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_WIFI, NMDeviceWifiClass)) - -#define NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS "perm-hw-address" #define NM_DEVICE_WIFI_MODE "mode" #define NM_DEVICE_WIFI_BITRATE "bitrate" #define NM_DEVICE_WIFI_ACCESS_POINTS "access-points" @@ -44,37 +39,11 @@ G_BEGIN_DECLS #define NM_DEVICE_WIFI_CAPABILITIES "wireless-capabilities" #define NM_DEVICE_WIFI_SCANNING "scanning" -#ifndef NM_DEVICE_WIFI_DEFINED -#define NM_DEVICE_WIFI_DEFINED typedef struct _NMDeviceWifi NMDeviceWifi; -#endif - typedef struct _NMDeviceWifiClass NMDeviceWifiClass; -typedef struct _NMDeviceWifiPrivate NMDeviceWifiPrivate; - -struct _NMDeviceWifi -{ - NMDevice parent; - - /*< private >*/ - NMDeviceWifiPrivate *priv; -}; - -struct _NMDeviceWifiClass -{ - NMDeviceClass parent; - - /* Signals */ - void (*access_point_added) (NMDeviceWifi *device, NMAccessPoint *ap); - void (*access_point_removed) (NMDeviceWifi *device, NMAccessPoint *ap); - gboolean (*scanning_allowed) (NMDeviceWifi *device); -}; - GType nm_device_wifi_get_type (void); NMDevice * nm_device_wifi_new (const char *iface, NMDeviceWifiCapabilities capabilities); -G_END_DECLS - -#endif /* NM_DEVICE_WIFI_H */ +#endif /* __NETWORKMANAGER_DEVICE_WIFI_H__ */ diff --git a/src/devices/wifi/nm-wifi-ap.c b/src/devices/wifi/nm-wifi-ap.c index a0c25709..e1beb85b 100644 --- a/src/devices/wifi/nm-wifi-ap.c +++ b/src/devices/wifi/nm-wifi-ap.c @@ -42,29 +42,48 @@ typedef struct char *supplicant_path; /* D-Bus object path of this AP from wpa_supplicant */ /* Scanned or cached values */ - GByteArray * ssid; - char * address; - NM80211Mode mode; - guint8 strength; - guint32 freq; /* Frequency in MHz; ie 2412 (== 2.412 GHz) */ - guint32 max_bitrate;/* Maximum bitrate of the AP in Kbit/s (ie 54000 Kb/s == 54Mbit/s) */ + GByteArray * ssid; + char * address; + NM80211Mode mode; + guint8 strength; + guint32 freq; /* Frequency in MHz; ie 2412 (== 2.412 GHz) */ + guint32 max_bitrate; /* Maximum bitrate of the AP in Kbit/s (ie 54000 Kb/s == 54Mbit/s) */ NM80211ApFlags flags; /* General flags */ NM80211ApSecurityFlags wpa_flags; /* WPA-related flags */ NM80211ApSecurityFlags rsn_flags; /* RSN (WPA2) -related flags */ /* Non-scanned attributes */ - gboolean fake; /* Whether or not the AP is from a scan */ - gboolean hotspot; /* Whether the AP is a local device's hotspot network */ + bool fake; /* Whether or not the AP is from a scan */ + bool hotspot; /* Whether the AP is a local device's hotspot network */ gint32 last_seen; /* Timestamp when the AP was seen lastly (obtained via nm_utils_get_monotonic_timestamp_s()) */ } NMAccessPointPrivate; -#define NM_AP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_AP, NMAccessPointPrivate)) +struct _NMAccessPoint { + NMExportedObject parent; + NMAccessPointPrivate _priv; +}; + +struct _NMAccessPointClass{ + NMExportedObjectClass parent; +}; + +#define NM_AP_GET_PRIVATE(self) \ + ({ \ + /* preserve the const-ness of self. Unfortunately, that + * way, @self cannot be a void pointer */ \ + typeof (self) _self = (self); \ + \ + /* Get compiler error if variable is of wrong type */ \ + _nm_unused const NMAccessPoint *_self2 = (_self); \ + \ + nm_assert (NM_IS_AP (_self)); \ + &_self->_priv; \ + }) G_DEFINE_TYPE (NMAccessPoint, nm_ap, NM_TYPE_EXPORTED_OBJECT) -enum { - PROP_0, +NM_GOBJECT_PROPERTIES_DEFINE (NMAccessPoint, PROP_FLAGS, PROP_WPA_FLAGS, PROP_RSN_FLAGS, @@ -75,8 +94,7 @@ enum { PROP_MAX_BITRATE, PROP_STRENGTH, PROP_LAST_SEEN, - LAST_PROP -}; +); /*****************************************************************/ @@ -130,7 +148,7 @@ nm_ap_set_ssid (NMAccessPoint *ap, const guint8 *ssid, gsize len) g_byte_array_append (priv->ssid, ssid, len); } - g_object_notify (G_OBJECT (ap), NM_AP_SSID); + _notify (ap, PROP_SSID); } static void @@ -144,7 +162,7 @@ nm_ap_set_flags (NMAccessPoint *ap, NM80211ApFlags flags) if (priv->flags != flags) { priv->flags = flags; - g_object_notify (G_OBJECT (ap), NM_AP_FLAGS); + _notify (ap, PROP_FLAGS); } } @@ -158,7 +176,7 @@ nm_ap_set_wpa_flags (NMAccessPoint *ap, NM80211ApSecurityFlags flags) priv = NM_AP_GET_PRIVATE (ap); if (priv->wpa_flags != flags) { priv->wpa_flags = flags; - g_object_notify (G_OBJECT (ap), NM_AP_WPA_FLAGS); + _notify (ap, PROP_WPA_FLAGS); } } @@ -172,7 +190,7 @@ nm_ap_set_rsn_flags (NMAccessPoint *ap, NM80211ApSecurityFlags flags) priv = NM_AP_GET_PRIVATE (ap); if (priv->rsn_flags != flags) { priv->rsn_flags = flags; - g_object_notify (G_OBJECT (ap), NM_AP_RSN_FLAGS); + _notify (ap, PROP_RSN_FLAGS); } } @@ -198,7 +216,7 @@ nm_ap_set_address (NMAccessPoint *ap, const char *addr) if (!priv->address || !nm_utils_hwaddr_matches (addr, -1, priv->address, -1)) { g_free (priv->address); priv->address = g_strdup (addr); - g_object_notify (G_OBJECT (ap), NM_AP_HW_ADDRESS); + _notify (ap, PROP_HW_ADDRESS); } } @@ -223,7 +241,7 @@ nm_ap_set_mode (NMAccessPoint *ap, const NM80211Mode mode) if (priv->mode != mode) { priv->mode = mode; - g_object_notify (G_OBJECT (ap), NM_AP_MODE); + _notify (ap, PROP_MODE); } } @@ -254,7 +272,7 @@ nm_ap_set_strength (NMAccessPoint *ap, const gint8 strength) if (priv->strength != strength) { priv->strength = strength; - g_object_notify (G_OBJECT (ap), NM_AP_STRENGTH); + _notify (ap, PROP_STRENGTH); } } @@ -278,7 +296,7 @@ nm_ap_set_freq (NMAccessPoint *ap, if (priv->freq != freq) { priv->freq = freq; - g_object_notify (G_OBJECT (ap), NM_AP_FREQUENCY); + _notify (ap, PROP_FREQUENCY); } } @@ -302,7 +320,7 @@ nm_ap_set_max_bitrate (NMAccessPoint *ap, guint32 bitrate) if (priv->max_bitrate != bitrate) { priv->max_bitrate = bitrate; - g_object_notify (G_OBJECT (ap), NM_AP_MAX_BITRATE); + _notify (ap, PROP_MAX_BITRATE); } } @@ -333,7 +351,7 @@ nm_ap_set_last_seen (NMAccessPoint *ap, gint32 last_seen) if (priv->last_seen != last_seen) { priv->last_seen = last_seen; - g_object_notify (G_OBJECT (ap), NM_AP_LAST_SEEN); + _notify (ap, PROP_LAST_SEEN); } } @@ -347,18 +365,20 @@ security_from_vardict (GVariant *security) g_return_val_if_fail (g_variant_is_of_type (security, G_VARIANT_TYPE_VARDICT), NM_802_11_AP_SEC_NONE); - if (g_variant_lookup (security, "KeyMgmt", "^a&s", &array)) { - if (_nm_utils_string_in_list ("wpa-psk", array)) + if ( g_variant_lookup (security, "KeyMgmt", "^a&s", &array) + && array) { + if (g_strv_contains (array, "wpa-psk")) flags |= NM_802_11_AP_SEC_KEY_MGMT_PSK; - if (_nm_utils_string_in_list ("wpa-eap", array)) + if (g_strv_contains (array, "wpa-eap")) flags |= NM_802_11_AP_SEC_KEY_MGMT_802_1X; g_free (array); } - if (g_variant_lookup (security, "Pairwise", "^a&s", &array)) { - if (_nm_utils_string_in_list ("tkip", array)) + if ( g_variant_lookup (security, "Pairwise", "^a&s", &array) + && array) { + if (g_strv_contains (array, "tkip")) flags |= NM_802_11_AP_SEC_PAIR_TKIP; - if (_nm_utils_string_in_list ("ccmp", array)) + if (g_strv_contains (array, "ccmp")) flags |= NM_802_11_AP_SEC_PAIR_CCMP; g_free (array); } @@ -879,7 +899,7 @@ nm_ap_init (NMAccessPoint *ap) static void finalize (GObject *object) { - NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE (object); + NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE ((NMAccessPoint *) object); g_free (priv->supplicant_path); if (priv->ssid) @@ -891,16 +911,16 @@ finalize (GObject *object) static void set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) + const GValue *value, GParamSpec *pspec) { G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } static void get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) + GValue *value, GParamSpec *pspec) { - NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE (object); + NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE ((NMAccessPoint *) object); GVariant *ssid; switch (prop_id) { @@ -965,8 +985,6 @@ nm_ap_class_init (NMAccessPointClass *ap_class) | NM_802_11_AP_SEC_KEY_MGMT_PSK | NM_802_11_AP_SEC_KEY_MGMT_802_1X; - g_type_class_add_private (ap_class, sizeof (NMAccessPointPrivate)); - exported_object_class->export_path = NM_DBUS_PATH_ACCESS_POINT "/%u"; /* virtual methods */ @@ -975,72 +993,64 @@ nm_ap_class_init (NMAccessPointClass *ap_class) object_class->finalize = finalize; /* properties */ - g_object_class_install_property - (object_class, PROP_FLAGS, - g_param_spec_uint (NM_AP_FLAGS, "", "", - NM_802_11_AP_FLAGS_NONE, - NM_802_11_AP_FLAGS_PRIVACY, - NM_802_11_AP_FLAGS_NONE, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_WPA_FLAGS, - g_param_spec_uint (NM_AP_WPA_FLAGS, "", "", - NM_802_11_AP_SEC_NONE, - all_sec_flags, - NM_802_11_AP_SEC_NONE, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_RSN_FLAGS, - g_param_spec_uint (NM_AP_RSN_FLAGS, "", "", - NM_802_11_AP_SEC_NONE, - all_sec_flags, - NM_802_11_AP_SEC_NONE, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_SSID, - g_param_spec_variant (NM_AP_SSID, "", "", - G_VARIANT_TYPE ("ay"), - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_FREQUENCY, - g_param_spec_uint (NM_AP_FREQUENCY, "", "", - 0, 10000, 0, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_HW_ADDRESS, - g_param_spec_string (NM_AP_HW_ADDRESS, "", "", + obj_properties[PROP_FLAGS] = + g_param_spec_uint (NM_AP_FLAGS, "", "", + NM_802_11_AP_FLAGS_NONE, + NM_802_11_AP_FLAGS_PRIVACY, + NM_802_11_AP_FLAGS_NONE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_WPA_FLAGS] = + g_param_spec_uint (NM_AP_WPA_FLAGS, "", "", + NM_802_11_AP_SEC_NONE, + all_sec_flags, + NM_802_11_AP_SEC_NONE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_RSN_FLAGS] = + g_param_spec_uint (NM_AP_RSN_FLAGS, "", "", + NM_802_11_AP_SEC_NONE, + all_sec_flags, + NM_802_11_AP_SEC_NONE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_SSID] = + g_param_spec_variant (NM_AP_SSID, "", "", + G_VARIANT_TYPE ("ay"), NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_MODE, - g_param_spec_uint (NM_AP_MODE, "", "", - NM_802_11_MODE_ADHOC, NM_802_11_MODE_INFRA, NM_802_11_MODE_INFRA, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_MAX_BITRATE, - g_param_spec_uint (NM_AP_MAX_BITRATE, "", "", - 0, G_MAXUINT16, 0, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_STRENGTH, - g_param_spec_uchar (NM_AP_STRENGTH, "", "", - 0, G_MAXINT8, 0, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_LAST_SEEN, - g_param_spec_int (NM_AP_LAST_SEEN, "", "", - -1, G_MAXINT, -1, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_FREQUENCY] = + g_param_spec_uint (NM_AP_FREQUENCY, "", "", + 0, 10000, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_HW_ADDRESS] = + g_param_spec_string (NM_AP_HW_ADDRESS, "", "", + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_MODE] = + g_param_spec_uint (NM_AP_MODE, "", "", + NM_802_11_MODE_ADHOC, NM_802_11_MODE_INFRA, NM_802_11_MODE_INFRA, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_MAX_BITRATE] = + g_param_spec_uint (NM_AP_MAX_BITRATE, "", "", + 0, G_MAXUINT16, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_STRENGTH] = + g_param_spec_uchar (NM_AP_STRENGTH, "", "", + 0, G_MAXINT8, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_LAST_SEEN] = + g_param_spec_int (NM_AP_LAST_SEEN, "", "", + -1, G_MAXINT, -1, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (ap_class), NMDBUS_TYPE_ACCESS_POINT_SKELETON, diff --git a/src/devices/wifi/nm-wifi-ap.h b/src/devices/wifi/nm-wifi-ap.h index 84aff983..035d1b5e 100644 --- a/src/devices/wifi/nm-wifi-ap.h +++ b/src/devices/wifi/nm-wifi-ap.h @@ -44,14 +44,8 @@ #define NM_AP_STRENGTH "strength" #define NM_AP_LAST_SEEN "last-seen" -typedef struct { - NMExportedObject parent; -} NMAccessPoint; - -typedef struct { - NMExportedObjectClass parent; - -} NMAccessPointClass; +typedef struct _NMAccessPoint NMAccessPoint; +typedef struct _NMAccessPointClass NMAccessPointClass; GType nm_ap_get_type (void); diff --git a/src/devices/wifi/tests/Makefile.in b/src/devices/wifi/tests/Makefile.in index 956730f8..64113a21 100644 --- a/src/devices/wifi/tests/Makefile.in +++ b/src/devices/wifi/tests/Makefile.in @@ -92,8 +92,9 @@ noinst_PROGRAMS = test-wifi-ap-utils$(EXEEXT) TESTS = test-wifi-ap-utils$(EXEEXT) subdir = src/devices/wifi/tests ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \ - $(top_srcdir)/m4/compiler_warnings.m4 \ +am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ + $(top_srcdir)/m4/ax_lib_readline.m4 \ + $(top_srcdir)/m4/compiler_options.m4 \ $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ @@ -423,6 +424,7 @@ DHCLIENT_PATH = @DHCLIENT_PATH@ DHCPCD_PATH = @DHCPCD_PATH@ DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@ DLLTOOL = @DLLTOOL@ +DL_LIBS = @DL_LIBS@ DNSMASQ_PATH = @DNSMASQ_PATH@ DNSSEC_TRIGGER_SCRIPT = @DNSSEC_TRIGGER_SCRIPT@ DSYMUTIL = @DSYMUTIL@ @@ -479,13 +481,14 @@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ IPTABLES_PATH = @IPTABLES_PATH@ +JANSSON_CFLAGS = @JANSSON_CFLAGS@ +JANSSON_LIBS = @JANSSON_LIBS@ KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBAUDIT_CFLAGS = @LIBAUDIT_CFLAGS@ LIBAUDIT_LIBS = @LIBAUDIT_LIBS@ -LIBDL = @LIBDL@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ @@ -497,6 +500,8 @@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@ LIBSOUP_LIBS = @LIBSOUP_LIBS@ +LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ +LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTEAMDCTL_CFLAGS = @LIBTEAMDCTL_CFLAGS@ LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@ LIBTOOL = @LIBTOOL@ @@ -557,6 +562,8 @@ QT_CFLAGS = @QT_CFLAGS@ QT_LIBS = @QT_LIBS@ RANLIB = @RANLIB@ READLINE_LIBS = @READLINE_LIBS@ +SANITIZERS = @SANITIZERS@ +SANITIZER_ENV = @SANITIZER_ENV@ SED = @SED@ SELINUX_CFLAGS = @SELINUX_CFLAGS@ SELINUX_LIBS = @SELINUX_LIBS@ @@ -592,6 +599,7 @@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_RANLIB = @ac_ct_RANLIB@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ diff --git a/src/devices/wifi/tests/test-wifi-ap-utils.c b/src/devices/wifi/tests/test-wifi-ap-utils.c index 838368c4..dbe185b3 100644 --- a/src/devices/wifi/tests/test-wifi-ap-utils.c +++ b/src/devices/wifi/tests/test-wifi-ap-utils.c @@ -26,7 +26,7 @@ #include "nm-core-internal.h" -#include "nm-test-utils.h" +#include "nm-test-utils-core.h" #define DEBUG 1 diff --git a/src/devices/wwan/Makefile.am b/src/devices/wwan/Makefile.am index 1777eb36..0d061a79 100644 --- a/src/devices/wwan/Makefile.am +++ b/src/devices/wwan/Makefile.am @@ -16,6 +16,7 @@ AM_CPPFLAGS = \ -DG_LOG_DOMAIN=\""NetworkManager-wwan"\" \ -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_INSIDE_DAEMON \ $(GLIB_CFLAGS) \ + $(LIBSYSTEMD_CFLAGS) \ $(MM_GLIB_CFLAGS) BUILT_SOURCES = $(null) @@ -26,7 +27,7 @@ pkglib_LTLIBRARIES = libnm-wwan.la libnm-device-plugin-wwan.la GLIB_GENERATED = nm-modem-enum-types.h nm-modem-enum-types.c GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM -GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM +GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM --fhead '\#include "nm-default.h"\n' nm_modem_enum_types_sources = $(srcdir)/nm-modem.h BUILT_SOURCES += $(GLIB_GENERATED) @@ -41,6 +42,13 @@ libnm_wwan_la_SOURCES = \ \ $(GLIB_GENERATED) +if WITH_OFONO +libnm_wwan_la_SOURCES += \ + nm-modem-ofono.c \ + nm-modem-ofono.h \ + $(NULL) +endif + WWAN_SYMBOL_VIS_FILE=$(srcdir)/wwan-exports.ver libnm_wwan_la_LDFLAGS = \ @@ -49,6 +57,7 @@ libnm_wwan_la_LDFLAGS = \ libnm_wwan_la_LIBADD = \ $(top_builddir)/introspection/libnmdbus.la \ $(GLIB_LIBS) \ + $(LIBSYSTEMD_LIBS) \ $(MM_GLIB_LIBS) ########################################################### @@ -79,7 +88,9 @@ if ENABLE_TESTS check-local: $(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-device-plugin-wwan.so $(SYMBOL_VIS_FILE) + LD_BIND_NOW=1 LD_PRELOAD=$(builddir)/.libs/libnm-device-plugin-wwan.so $(top_builddir)/src/NetworkManager --version >/dev/null $(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-wwan.so $(WWAN_SYMBOL_VIS_FILE) + LD_BIND_NOW=1 LD_PRELOAD=$(builddir)/.libs/libnm-wwan.so $(top_builddir)/src/NetworkManager --version >/dev/null endif diff --git a/src/devices/wwan/Makefile.in b/src/devices/wwan/Makefile.in index 89328665..6d395567 100644 --- a/src/devices/wwan/Makefile.in +++ b/src/devices/wwan/Makefile.in @@ -88,10 +88,16 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ +@WITH_OFONO_TRUE@am__append_1 = \ +@WITH_OFONO_TRUE@ nm-modem-ofono.c \ +@WITH_OFONO_TRUE@ nm-modem-ofono.h \ +@WITH_OFONO_TRUE@ $(NULL) + subdir = src/devices/wwan ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \ - $(top_srcdir)/m4/compiler_warnings.m4 \ +am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \ + $(top_srcdir)/m4/ax_lib_readline.m4 \ + $(top_srcdir)/m4/compiler_options.m4 \ $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/gnome-code-coverage.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ @@ -157,10 +163,16 @@ libnm_device_plugin_wwan_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(LDFLAGS) -o $@ libnm_wwan_la_DEPENDENCIES = \ $(top_builddir)/introspection/libnmdbus.la \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am__libnm_wwan_la_SOURCES_DIST = nm-modem-broadband.c \ + nm-modem-broadband.h nm-modem-manager.c nm-modem-manager.h \ + nm-modem.c nm-modem.h nm-modem-enum-types.h \ + nm-modem-enum-types.c nm-modem-ofono.c nm-modem-ofono.h am__objects_1 = nm-modem-enum-types.lo +@WITH_OFONO_TRUE@am__objects_2 = nm-modem-ofono.lo am_libnm_wwan_la_OBJECTS = nm-modem-broadband.lo nm-modem-manager.lo \ - nm-modem.lo $(am__objects_1) + nm-modem.lo $(am__objects_1) $(am__objects_2) libnm_wwan_la_OBJECTS = $(am_libnm_wwan_la_OBJECTS) libnm_wwan_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ @@ -202,7 +214,7 @@ am__v_CCLD_1 = SOURCES = $(libnm_device_plugin_wwan_la_SOURCES) \ $(libnm_wwan_la_SOURCES) DIST_SOURCES = $(libnm_device_plugin_wwan_la_SOURCES) \ - $(libnm_wwan_la_SOURCES) + $(am__libnm_wwan_la_SOURCES_DIST) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ @@ -264,6 +276,7 @@ DHCLIENT_PATH = @DHCLIENT_PATH@ DHCPCD_PATH = @DHCPCD_PATH@ DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@ DLLTOOL = @DLLTOOL@ +DL_LIBS = @DL_LIBS@ DNSMASQ_PATH = @DNSMASQ_PATH@ DNSSEC_TRIGGER_SCRIPT = @DNSSEC_TRIGGER_SCRIPT@ DSYMUTIL = @DSYMUTIL@ @@ -320,13 +333,14 @@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ IPTABLES_PATH = @IPTABLES_PATH@ +JANSSON_CFLAGS = @JANSSON_CFLAGS@ +JANSSON_LIBS = @JANSSON_LIBS@ KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBAUDIT_CFLAGS = @LIBAUDIT_CFLAGS@ LIBAUDIT_LIBS = @LIBAUDIT_LIBS@ -LIBDL = @LIBDL@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ @@ -338,6 +352,8 @@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@ LIBSOUP_LIBS = @LIBSOUP_LIBS@ +LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ +LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTEAMDCTL_CFLAGS = @LIBTEAMDCTL_CFLAGS@ LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@ LIBTOOL = @LIBTOOL@ @@ -398,6 +414,8 @@ QT_CFLAGS = @QT_CFLAGS@ QT_LIBS = @QT_LIBS@ RANLIB = @RANLIB@ READLINE_LIBS = @READLINE_LIBS@ +SANITIZERS = @SANITIZERS@ +SANITIZER_ENV = @SANITIZER_ENV@ SED = @SED@ SELINUX_CFLAGS = @SELINUX_CFLAGS@ SELINUX_LIBS = @SELINUX_LIBS@ @@ -433,6 +451,7 @@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_RANLIB = @ac_ct_RANLIB@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ @@ -508,6 +527,7 @@ AM_CPPFLAGS = \ -DG_LOG_DOMAIN=\""NetworkManager-wwan"\" \ -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_INSIDE_DAEMON \ $(GLIB_CFLAGS) \ + $(LIBSYSTEMD_CFLAGS) \ $(MM_GLIB_CFLAGS) BUILT_SOURCES = $(null) $(GLIB_GENERATED) @@ -516,18 +536,11 @@ pkglib_LTLIBRARIES = libnm-wwan.la libnm-device-plugin-wwan.la ########################################################### GLIB_GENERATED = nm-modem-enum-types.h nm-modem-enum-types.c GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM -GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM +GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM --fhead '\#include "nm-default.h"\n' nm_modem_enum_types_sources = $(srcdir)/nm-modem.h -libnm_wwan_la_SOURCES = \ - nm-modem-broadband.c \ - nm-modem-broadband.h \ - nm-modem-manager.c \ - nm-modem-manager.h \ - nm-modem.c \ - nm-modem.h \ - \ - $(GLIB_GENERATED) - +libnm_wwan_la_SOURCES = nm-modem-broadband.c nm-modem-broadband.h \ + nm-modem-manager.c nm-modem-manager.h nm-modem.c nm-modem.h \ + $(GLIB_GENERATED) $(am__append_1) WWAN_SYMBOL_VIS_FILE = $(srcdir)/wwan-exports.ver libnm_wwan_la_LDFLAGS = \ -avoid-version \ @@ -536,6 +549,7 @@ libnm_wwan_la_LDFLAGS = \ libnm_wwan_la_LIBADD = \ $(top_builddir)/introspection/libnmdbus.la \ $(GLIB_LIBS) \ + $(LIBSYSTEMD_LIBS) \ $(MM_GLIB_LIBS) @@ -646,6 +660,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-modem-broadband.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-modem-enum-types.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-modem-manager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-modem-ofono.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-modem.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-wwan-factory.Plo@am__quote@ @@ -897,7 +912,9 @@ include $(GLIB_MAKEFILE) @ENABLE_TESTS_TRUE@check-local: @ENABLE_TESTS_TRUE@ $(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-device-plugin-wwan.so $(SYMBOL_VIS_FILE) +@ENABLE_TESTS_TRUE@ LD_BIND_NOW=1 LD_PRELOAD=$(builddir)/.libs/libnm-device-plugin-wwan.so $(top_builddir)/src/NetworkManager --version >/dev/null @ENABLE_TESTS_TRUE@ $(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-wwan.so $(WWAN_SYMBOL_VIS_FILE) +@ENABLE_TESTS_TRUE@ LD_BIND_NOW=1 LD_PRELOAD=$(builddir)/.libs/libnm-wwan.so $(top_builddir)/src/NetworkManager --version >/dev/null # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/src/devices/wwan/nm-device-modem.c b/src/devices/wwan/nm-device-modem.c index a8361c49..0f96dafb 100644 --- a/src/devices/wwan/nm-device-modem.c +++ b/src/devices/wwan/nm-device-modem.c @@ -60,6 +60,7 @@ static void ppp_failed (NMModem *modem, NMDeviceStateReason reason, gpointer user_data) { NMDevice *device = NM_DEVICE (user_data); + NMDeviceModem *self = NM_DEVICE_MODEM (user_data); switch (nm_device_get_state (device)) { case NM_DEVICE_STATE_PREPARE: @@ -73,7 +74,18 @@ ppp_failed (NMModem *modem, NMDeviceStateReason reason, gpointer user_data) case NM_DEVICE_STATE_ACTIVATED: if (nm_device_activate_ip4_state_in_conf (device)) nm_device_activate_schedule_ip4_config_timeout (device); - else { + else if (nm_device_activate_ip6_state_in_conf (device)) + nm_device_activate_schedule_ip6_config_timeout (device); + else if (nm_device_activate_ip4_state_done (device)) { + nm_device_ip_method_failed (device, + AF_INET, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + } else if (nm_device_activate_ip6_state_done (device)) { + nm_device_ip_method_failed (device, + AF_INET6, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + } else { + _LOGW (LOGD_MB, "PPP failure in unexpected state %u", (guint) nm_device_get_state (device)); nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); @@ -159,8 +171,9 @@ modem_ip4_config_result (NMModem *modem, if (error) { _LOGW (LOGD_MB | LOGD_IP4, "retrieving IPv4 configuration failed: %s", error->message); - - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + nm_device_ip_method_failed (device, + AF_INET, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); } else { nm_device_set_wwan_ip4_config (device, config); nm_device_activate_schedule_ip4_config_result (device, NULL); @@ -184,9 +197,11 @@ modem_ip6_config_result (NMModem *modem, g_return_if_fail (nm_device_activate_ip6_state_in_conf (device) == TRUE); if (error) { - _LOGW (LOGD_MB | LOGD_IP6, "retrieving IPv6 configuration failed: %s", error->message); - - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + _LOGW (LOGD_MB | LOGD_IP6, "retrieving IPv6 configuration failed: %s", + error->message); + nm_device_ip_method_failed (device, + AF_INET6, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); return; } @@ -201,7 +216,9 @@ modem_ip6_config_result (NMModem *modem, nm_device_activate_schedule_ip6_config_result (device); else { _LOGW (LOGD_MB | LOGD_IP6, "retrieving IPv6 configuration failed: SLAAC not requested and no addresses"); - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + nm_device_ip_method_failed (device, + AF_INET6, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); } return; } @@ -211,7 +228,7 @@ modem_ip6_config_result (NMModem *modem, g_assert (ignored == NULL); switch (ret) { case NM_ACT_STAGE_RETURN_FAILURE: - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason); + nm_device_ip_method_failed (device, AF_INET6, reason); break; case NM_ACT_STAGE_RETURN_STOP: /* all done */ diff --git a/src/devices/wwan/nm-modem-broadband.c b/src/devices/wwan/nm-modem-broadband.c index 1a6e6b25..727c8409 100644 --- a/src/devices/wwan/nm-modem-broadband.c +++ b/src/devices/wwan/nm-modem-broadband.c @@ -30,6 +30,8 @@ #include "nm-device-private.h" #include "nm-platform.h" +#define NM_MODEM_BROADBAND_MODEM "modem" + G_DEFINE_TYPE (NMModemBroadband, nm_modem_broadband, NM_TYPE_MODEM) typedef enum { @@ -89,8 +91,35 @@ enum { /*****************************************************************************/ +#define _NMLOG_DOMAIN LOGD_MB +#define _NMLOG_PREFIX_NAME "modem-broadband" +#define _NMLOG(level, ...) \ + G_STMT_START { \ + const NMLogLevel _level = (level); \ + \ + if (nm_logging_enabled (_level, (_NMLOG_DOMAIN))) { \ + NMModemBroadband *const __self = (self); \ + char __prefix_name[128]; \ + const char *__uid; \ + \ + _nm_log (_level, (_NMLOG_DOMAIN), 0, \ + "%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + _NMLOG_PREFIX_NAME, \ + (__self \ + ? ({ \ + ((__uid = nm_modem_get_uid ((NMModem *) __self)) \ + ? nm_sprintf_buf (__prefix_name, "[%s]", __uid) \ + : "(null)"); \ + }) \ + : "") \ + _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ + } G_STMT_END + +/*****************************************************************************/ + static NMDeviceStateReason -translate_mm_error (GError *error) +translate_mm_error (NMModemBroadband *self, GError *error) { NMDeviceStateReason reason; @@ -122,7 +151,7 @@ translate_mm_error (GError *error) reason = NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT; else { /* unable to map the ModemManager error to a NM_DEVICE_STATE_REASON */ - nm_log_dbg (LOGD_MB, "unmapped error detected: '%s'", error->message); + _LOGD ("unmapped error detected: '%s'", error->message); reason = NM_DEVICE_STATE_REASON_UNKNOWN; } @@ -288,7 +317,7 @@ connect_context_clear (NMModemBroadband *self) g_clear_error (&ctx->first_error); g_clear_pointer (&ctx->ip_types, (GDestroyNotify) g_array_unref); - g_clear_object (&ctx->cancellable); + nm_clear_g_cancellable (&ctx->cancellable); g_clear_object (&ctx->connection); g_clear_object (&ctx->connect_properties); g_clear_object (&ctx->self); @@ -360,8 +389,7 @@ connect_ready (MMModemSimple *simple_iface, if (ip4_method == NM_MODEM_IP_METHOD_UNKNOWN && ip6_method == NM_MODEM_IP_METHOD_UNKNOWN) { - nm_log_warn (LOGD_MB, "(%s): failed to connect modem: invalid bearer IP configuration", - nm_modem_get_uid (NM_MODEM (self))); + _LOGW ("failed to connect modem: invalid bearer IP configuration"); g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, NM_DEVICE_STATE_REASON_CONFIG_FAILED); connect_context_clear (self); return; @@ -389,7 +417,7 @@ send_pin_ready (MMSim *sim, GAsyncResult *result, NMModemBroadband *self) return; if (!self->priv->ctx || self->priv->ctx->step != CONNECT_STEP_UNLOCK) - return; + g_return_if_reached (); if (error) { if (g_error_matches (error, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_SIM_PIN) || @@ -397,7 +425,7 @@ send_pin_ready (MMSim *sim, GAsyncResult *result, NMModemBroadband *self) mm_modem_get_unlock_required (self->priv->modem_iface) == MM_MODEM_LOCK_SIM_PIN)) { ask_for_pin (self); } else { - g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, translate_mm_error (error)); + g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, translate_mm_error (self, error)); } return; } @@ -459,9 +487,8 @@ connect_context_step (NMModemBroadband *self) else if (MODEM_CAPS_3GPP2 (ctx->caps)) ctx->connect_properties = create_cdma_connect_properties (ctx->connection); else { - nm_log_warn (LOGD_MB, "(%s): Failed to connect '%s': not a mobile broadband modem", - nm_modem_get_uid (NM_MODEM (self)), - nm_connection_get_id (ctx->connection)); + _LOGW ("failed to connect '%s': not a mobile broadband modem", + nm_connection_get_id (ctx->connection)); g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED); connect_context_clear (self); @@ -472,10 +499,9 @@ connect_context_step (NMModemBroadband *self) /* Build up list of IP types that we need to use in the retries */ ctx->ip_types = nm_modem_get_connection_ip_type (NM_MODEM (self), ctx->connection, &error); if (!ctx->ip_types) { - nm_log_warn (LOGD_MB, "(%s): Failed to connect '%s': %s", - nm_modem_get_uid (NM_MODEM (self)), - nm_connection_get_id (ctx->connection), - error->message); + _LOGW ("failed to connect '%s': %s", + nm_connection_get_id (ctx->connection), + error->message); g_clear_error (&error); g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED); @@ -502,10 +528,9 @@ connect_context_step (NMModemBroadband *self) else g_assert_not_reached (); - nm_log_dbg (LOGD_MB, "(%s): launching connection with ip type '%s' (try %d)", - nm_modem_get_uid (NM_MODEM (self)), - nm_modem_ip_type_to_string (current), - ctx->ip_type_tries + 1); + _LOGD ("launching connection with ip type '%s' (try %d)", + nm_modem_ip_type_to_string (current), + ctx->ip_type_tries + 1); mm_modem_simple_connect (self->priv->simple_iface, ctx->connect_properties, @@ -528,10 +553,9 @@ connect_context_step (NMModemBroadband *self) NM_DEVICE_ERROR_INVALID_CONNECTION, "invalid bearer IP configuration"); - nm_log_warn (LOGD_MB, "(%s): failed to connect modem: %s", - nm_modem_get_uid (NM_MODEM (self)), - ctx->first_error->message); - g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, translate_mm_error (ctx->first_error)); + _LOGW ("failed to connect modem: %s", + ctx->first_error->message); + g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, translate_mm_error (self, ctx->first_error)); } connect_context_clear (self); @@ -550,8 +574,7 @@ act_stage1_prepare (NMModem *_self, if (!self->priv->simple_iface) { self->priv->simple_iface = mm_object_get_modem_simple (self->priv->modem_object); if (!self->priv->simple_iface) { - nm_log_warn (LOGD_MB, "(%s) cannot access the Simple mobile broadband modem interface", - nm_modem_get_uid (NM_MODEM (self))); + _LOGW ("cannot access the Simple mobile broadband modem interface"); *reason = NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED; return NM_ACT_STAGE_RETURN_FAILURE; } @@ -745,9 +768,8 @@ set_power_state_low_ready (MMModem *modem, if (!mm_modem_set_power_state_finish (modem, result, &error)) { /* Log but ignore errors; not all modems support low power state */ - nm_log_dbg (LOGD_MB, "(%s): failed to set modem low power state: %s", - nm_modem_get_uid (NM_MODEM (self)), - NM_G_ERROR_MSG (error)); + _LOGD ("failed to set modem low power state: %s", + NM_G_ERROR_MSG (error)); g_clear_error (&error); } @@ -770,9 +792,8 @@ modem_disable_ready (MMModem *modem_iface, (GAsyncReadyCallback) set_power_state_low_ready, g_object_ref (self)); } else { - nm_log_warn (LOGD_MB, "(%s): failed to disable modem: %s", - nm_modem_get_uid (NM_MODEM (self)), - NM_G_ERROR_MSG (error)); + _LOGW ("failed to disable modem: %s", + NM_G_ERROR_MSG (error)); nm_modem_set_prev_state (NM_MODEM (self), "disable failed"); g_clear_error (&error); } @@ -789,9 +810,8 @@ modem_enable_ready (MMModem *modem_iface, GError *error = NULL; if (!mm_modem_enable_finish (modem_iface, res, &error)) { - nm_log_warn (LOGD_MB, "(%s) failed to enable modem: %s", - nm_modem_get_uid (NM_MODEM (self)), - NM_G_ERROR_MSG (error)); + _LOGW ("failed to enable modem: %s", + NM_G_ERROR_MSG (error)); nm_modem_set_prev_state (NM_MODEM (self), "enable failed"); g_clear_error (&error); } @@ -854,8 +874,7 @@ static_stage3_ip4_done (NMModemBroadband *self) g_assert (self->priv->ipv4_config); g_assert (self->priv->bearer); - nm_log_info (LOGD_MB, "(%s): IPv4 static configuration:", - nm_modem_get_uid (NM_MODEM (self))); + _LOGI ("IPv4 static configuration:"); /* Fully fail if invalid IP address retrieved */ address_string = mm_bearer_ip_config_get_address (self->priv->ipv4_config); @@ -880,15 +899,15 @@ static_stage3_ip4_done (NMModemBroadband *self) address.address = address_network; address.peer_address = address_network; address.plen = mm_bearer_ip_config_get_prefix (self->priv->ipv4_config); - address.source = NM_IP_CONFIG_SOURCE_WWAN; + address.addr_source = NM_IP_CONFIG_SOURCE_WWAN; if (address.plen <= 32) nm_ip4_config_add_address (config, &address); - nm_log_info (LOGD_MB, " address %s/%d", address_string, address.plen); + _LOGI (" address %s/%d", address_string, address.plen); if (gw) { nm_ip4_config_set_gateway (config, gw); - nm_log_info (LOGD_MB, " gateway %s", gw_string); + _LOGI (" gateway %s", gw_string); } /* DNS servers */ @@ -897,7 +916,7 @@ static_stage3_ip4_done (NMModemBroadband *self) if ( ip4_string_to_num (dns[i], &address_network) && address_network > 0) { nm_ip4_config_add_nameserver (config, address_network); - nm_log_info (LOGD_MB, " DNS %s", dns[i]); + _LOGI (" DNS %s", dns[i]); } } @@ -964,8 +983,7 @@ stage3_ip6_done (NMModemBroadband *self) goto out; } - nm_log_info (LOGD_MB, "(%s): IPv6 base configuration:", - nm_modem_get_uid (NM_MODEM (self))); + _LOGI ("IPv6 base configuration:"); data_port = mm_bearer_get_interface (self->priv->bearer); g_assert (data_port); @@ -975,7 +993,7 @@ stage3_ip6_done (NMModemBroadband *self) if (address.plen <= 128) nm_ip6_config_add_address (config, &address); - nm_log_info (LOGD_MB, " address %s/%d", address_string, address.plen); + _LOGI (" address %s/%d", address_string, address.plen); address_string = mm_bearer_ip_config_get_gateway (self->priv->ipv6_config); if (address_string) { @@ -987,7 +1005,7 @@ stage3_ip6_done (NMModemBroadband *self) address_string); goto out; } - nm_log_info (LOGD_MB, " gateway %s", address_string); + _LOGI (" gateway %s", address_string); nm_ip6_config_set_gateway (config, &address.address); } else if (ip_method == NM_MODEM_IP_METHOD_STATIC) { /* Gateway required for the 'static' method */ @@ -1005,7 +1023,7 @@ stage3_ip6_done (NMModemBroadband *self) if (inet_pton (AF_INET6, dns[i], &addr)) { nm_ip6_config_add_nameserver (config, &addr); - nm_log_info (LOGD_MB, " DNS %s", dns[i]); + _LOGI (" DNS %s", dns[i]); } } @@ -1050,19 +1068,6 @@ disconnect_context_complete (DisconnectContext *ctx) } static gboolean -disconnect_context_complete_if_cancelled (DisconnectContext *ctx) -{ - GError *error = NULL; - - if (g_cancellable_set_error_if_cancelled (ctx->cancellable, &error)) { - g_simple_async_result_take_error (ctx->result, error); - disconnect_context_complete (ctx); - return TRUE; - } - return FALSE; -} - -static gboolean disconnect_finish (NMModem *self, GAsyncResult *res, GError **error) @@ -1079,9 +1084,10 @@ simple_disconnect_ready (MMModemSimple *modem_iface, if (!mm_modem_simple_disconnect_finish (modem_iface, res, &error)) { if (ctx->warn && !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN)) { - nm_log_warn (LOGD_MB, "(%s) failed to disconnect modem: %s", - nm_modem_get_uid (NM_MODEM (ctx->self)), - error->message); + NMModemBroadband *self = ctx->self; + + _LOGW ("failed to disconnect modem: %s", + error->message); } g_simple_async_result_take_error (ctx->result, error); } @@ -1098,9 +1104,11 @@ disconnect (NMModem *modem, { NMModemBroadband *self = NM_MODEM_BROADBAND (modem); DisconnectContext *ctx; + GError *error = NULL; connect_context_clear (self); ctx = g_slice_new (DisconnectContext); + ctx->cancellable = NULL; ctx->self = g_object_ref (self); ctx->result = g_simple_async_result_new (G_OBJECT (self), callback, @@ -1109,10 +1117,12 @@ disconnect (NMModem *modem, /* Don't bother warning on FAILED since the modem is already gone */ ctx->warn = warn; - /* Setup cancellable */ - ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL; - if (disconnect_context_complete_if_cancelled (ctx)) + /* Already cancelled? */ + if (g_cancellable_set_error_if_cancelled (cancellable, &error)) { + g_simple_async_result_take_error (ctx->result, error); + disconnect_context_complete (ctx); return; + } /* If no simple iface, we're done */ if (!ctx->self->priv->simple_iface) { @@ -1120,14 +1130,13 @@ disconnect (NMModem *modem, return; } - nm_log_dbg (LOGD_MB, "(%s): notifying ModemManager about the modem disconnection", - nm_modem_get_uid (NM_MODEM (ctx->self))); - mm_modem_simple_disconnect ( - ctx->self->priv->simple_iface, - NULL, /* bearer path; if NULL given ALL get disconnected */ - cancellable, - (GAsyncReadyCallback)simple_disconnect_ready, - ctx); + _LOGD ("notifying ModemManager about the modem disconnection"); + ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL; + mm_modem_simple_disconnect (ctx->self->priv->simple_iface, + NULL, /* bearer path; if NULL given ALL get disconnected */ + cancellable, + (GAsyncReadyCallback) simple_disconnect_ready, + ctx); } /*****************************************************************************/ @@ -1274,9 +1283,10 @@ get_sim_ready (MMModem *modem, if (self->priv->ctx && self->priv->ctx->step == CONNECT_STEP_WAIT_FOR_SIM) connect_context_step (self); } else { - nm_log_warn (LOGD_MB, "(%s): failed to retrieve SIM object: %s", - nm_modem_get_uid (NM_MODEM (self)), - NM_G_ERROR_MSG (error)); + _NMLOG (g_error_matches (error, MM_CORE_ERROR, MM_CORE_ERROR_NOT_FOUND) + ? LOGL_INFO : LOGL_WARN, + "failed to retrieve SIM object: %s", + NM_G_ERROR_MSG (error)); } g_clear_error (&error); g_object_unref (self); diff --git a/src/devices/wwan/nm-modem-broadband.h b/src/devices/wwan/nm-modem-broadband.h index a54e63a6..6607f7f5 100644 --- a/src/devices/wwan/nm-modem-broadband.h +++ b/src/devices/wwan/nm-modem-broadband.h @@ -23,8 +23,6 @@ #include "nm-modem.h" -G_BEGIN_DECLS - #define NM_TYPE_MODEM_BROADBAND (nm_modem_broadband_get_type ()) #define NM_MODEM_BROADBAND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_MODEM_BROADBAND, NMModemBroadband)) #define NM_MODEM_BROADBAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_MODEM_BROADBAND, NMModemBroadbandClass)) @@ -32,8 +30,6 @@ G_BEGIN_DECLS #define NM_IS_MODEM_BROADBAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_MODEM_BROADBAND)) #define NM_MODEM_BROADBAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_MODEM_BROADBAND, NMModemBroadbandClass)) -#define NM_MODEM_BROADBAND_MODEM "modem" - typedef struct _NMModemBroadband NMModemBroadband; typedef struct _NMModemBroadbandClass NMModemBroadbandClass; typedef struct _NMModemBroadbandPrivate NMModemBroadbandPrivate; @@ -51,6 +47,4 @@ GType nm_modem_broadband_get_type (void); NMModem *nm_modem_broadband_new (GObject *object, GError **error); -G_END_DECLS - #endif /* __NETWORKMANAGER_MODEM_BROADBAND_H__ */ diff --git a/src/devices/wwan/nm-modem-enum-types.c b/src/devices/wwan/nm-modem-enum-types.c index 2d02ede9..f999b084 100644 --- a/src/devices/wwan/nm-modem-enum-types.c +++ b/src/devices/wwan/nm-modem-enum-types.c @@ -6,6 +6,7 @@ #include "config.h" #include "nm-modem-enum-types.h" +#include "nm-default.h" #include "nm-modem.h" diff --git a/src/devices/wwan/nm-modem-manager.c b/src/devices/wwan/nm-modem-manager.c index e26321b0..964485fc 100644 --- a/src/devices/wwan/nm-modem-manager.c +++ b/src/devices/wwan/nm-modem-manager.c @@ -17,20 +17,30 @@ * * Copyright (C) 2009 - 2014 Red Hat, Inc. * Copyright (C) 2009 Novell, Inc. - * Copyright (C) 2009 Canonical Ltd. + * Copyright (C) 2009 - 2013 Canonical Ltd. */ #include "nm-default.h" -#include <string.h> +#include "nm-modem-manager.h" +#include <string.h> #include <libmm-glib.h> -#include "nm-modem-manager.h" +#if HAVE_LIBSYSTEMD +#include <systemd/sd-daemon.h> +#else +#define sd_booted() FALSE +#endif + #include "nm-dbus-compat.h" #include "nm-modem.h" #include "nm-modem-broadband.h" +#if WITH_OFONO +#include "nm-modem-ofono.h" +#endif + #define MODEM_POKE_INTERVAL 120 G_DEFINE_TYPE (NMModemManager, nm_modem_manager, G_TYPE_OBJECT) @@ -39,9 +49,13 @@ struct _NMModemManagerPrivate { GDBusConnection *dbus_connection; MMManager *modem_manager; guint mm_launch_id; - guint mm_name_owner_changed_id; - guint mm_object_added_id; - guint mm_object_removed_id; + gulong mm_name_owner_changed_id; + gulong mm_object_added_id; + gulong mm_object_removed_id; + +#if WITH_OFONO + GDBusProxy *ofono_proxy; +#endif /* Common */ GHashTable *modems; @@ -79,34 +93,14 @@ remove_one_modem (gpointer key, gpointer value, gpointer user_data) } static void -modem_manager_clear_signals (NMModemManager *self) +clear_modem_manager (NMModemManager *self) { if (!self->priv->modem_manager) return; - - if (self->priv->mm_name_owner_changed_id) { - if (g_signal_handler_is_connected (self->priv->modem_manager, - self->priv->mm_name_owner_changed_id)) - g_signal_handler_disconnect (self->priv->modem_manager, - self->priv->mm_name_owner_changed_id); - self->priv->mm_name_owner_changed_id = 0; - } - - if (self->priv->mm_object_added_id) { - if (g_signal_handler_is_connected (self->priv->modem_manager, - self->priv->mm_object_added_id)) - g_signal_handler_disconnect (self->priv->modem_manager, - self->priv->mm_object_added_id); - self->priv->mm_object_added_id = 0; - } - - if (self->priv->mm_object_removed_id) { - if (g_signal_handler_is_connected (self->priv->modem_manager, - self->priv->mm_object_removed_id)) - g_signal_handler_disconnect (self->priv->modem_manager, - self->priv->mm_object_removed_id); - self->priv->mm_object_removed_id = 0; - } + nm_clear_g_signal_handler (self->priv->modem_manager, &self->priv->mm_name_owner_changed_id); + nm_clear_g_signal_handler (self->priv->modem_manager, &self->priv->mm_object_added_id); + nm_clear_g_signal_handler (self->priv->modem_manager, &self->priv->mm_object_removed_id); + g_clear_object (&self->priv->modem_manager); } static void @@ -183,7 +177,7 @@ modem_manager_available (NMModemManager *self) static void schedule_modem_manager_relaunch (NMModemManager *self, guint n_seconds); -static void ensure_client (NMModemManager *self); +static void ensure_modem_manager (NMModemManager *self); static void modem_manager_name_owner_changed (MMManager *modem_manager, @@ -199,10 +193,9 @@ modem_manager_name_owner_changed (MMManager *modem_manager, if (!name_owner) { nm_log_info (LOGD_MB, "ModemManager disappeared from bus"); -#if !HAVE_SYSTEMD /* If not managed by systemd, schedule relaunch */ - schedule_modem_manager_relaunch (self, 0); -#endif + if (!sd_booted ()) + schedule_modem_manager_relaunch (self, 0); return; } @@ -214,16 +207,173 @@ modem_manager_name_owner_changed (MMManager *modem_manager, * nor 'object-removed' if it was created while there was no ModemManager in * the bus. This hack avoids this issue until we get a GIO with the fix * included... */ - modem_manager_clear_signals (self); - g_clear_object (&self->priv->modem_manager); - ensure_client (self); + clear_modem_manager (self); + ensure_modem_manager (self); /* Whenever GDBusObjectManagerClient is fixed, we can just do the following: * modem_manager_available (self); */ } -#if !HAVE_SYSTEMD +#if WITH_OFONO +static void +ofono_create_modem (NMModemManager *self, const char *path) +{ + NMModem *modem = NULL; + + /* Ensure duplicate modems aren't created. Because we're not using the + * ObjectManager interface there's a race during oFono startup where we + * receive ModemAdded signals before GetModems() returns, so some of the + * modems returned from GetModems() may already have been created. + */ + if (!g_hash_table_lookup (self->priv->modems, path)) { + modem = nm_modem_ofono_new (path); + if (modem) + handle_new_modem (self, modem); + else + nm_log_warn (LOGD_MB, "Failed to create oFono modem for %s", path); + } +} + +static void +ofono_signal_cb (GDBusProxy *proxy, + gchar *sender_name, + gchar *signal_name, + GVariant *parameters, + gpointer user_data) +{ + NMModemManager *self = NM_MODEM_MANAGER (user_data); + gchar *object_path; + NMModem *modem; + + if (g_strcmp0 (signal_name, "ModemAdded") == 0) { + g_variant_get (parameters, "(oa{sv})", &object_path, NULL); + nm_log_info (LOGD_MB, "oFono modem appeared: %s", object_path); + + ofono_create_modem (NM_MODEM_MANAGER (user_data), object_path); + g_free (object_path); + } else if (g_strcmp0 (signal_name, "ModemRemoved") == 0) { + g_variant_get (parameters, "(o)", &object_path); + nm_log_info (LOGD_MB, "oFono modem removed: %s", object_path); + + modem = (NMModem *) g_hash_table_lookup (self->priv->modems, object_path); + if (modem) { + nm_modem_emit_removed (modem); + g_hash_table_remove (self->priv->modems, object_path); + } else { + nm_log_warn (LOGD_MB, "could not remove modem %s, not found in table", + object_path); + } + g_free (object_path); + } +} + +static void +ofono_enumerate_devices_done (GDBusProxy *proxy, GAsyncResult *res, gpointer user_data) +{ + NMModemManager *manager = NM_MODEM_MANAGER (user_data); + gs_free_error GError *error = NULL; + GVariant *results; + GVariantIter *iter; + const char *path; + + results = g_dbus_proxy_call_finish (proxy, res, &error); + if (results) { + g_variant_get (results, "(a(oa{sv}))", &iter); + while (g_variant_iter_loop (iter, "(&oa{sv})", &path, NULL)) + ofono_create_modem (manager, path); + g_variant_iter_free (iter); + g_variant_unref (results); + } + + if (error) { + nm_log_warn (LOGD_MB, "failed to enumerate oFono devices: %s", + error->message); + } +} + +static void +ofono_check_name_owner (NMModemManager *self) +{ + gs_free char *name_owner = NULL; + + name_owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (self->priv->ofono_proxy)); + if (name_owner) { + nm_log_info (LOGD_MB, "oFono is now available"); + + g_dbus_proxy_call (self->priv->ofono_proxy, + "GetModems", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + (GAsyncReadyCallback) ofono_enumerate_devices_done, + g_object_ref (self)); + } else { + GHashTableIter iter; + NMModem *modem; + + nm_log_info (LOGD_MB, "oFono disappeared from bus"); + + /* Remove any oFono modems that might be left around */ + g_hash_table_iter_init (&iter, self->priv->modems); + while (g_hash_table_iter_next (&iter, NULL, (gpointer) &modem)) { + if (NM_IS_MODEM_OFONO (modem)) { + nm_modem_emit_removed (modem); + g_hash_table_iter_remove (&iter); + } + } + } +} + +static void +ofono_name_owner_changed (GDBusProxy *ofono_proxy, + GParamSpec *pspec, + NMModemManager *self) +{ + ofono_check_name_owner (self); +} + +static void +ofono_proxy_new_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) +{ + gs_unref_object NMModemManager *self = NM_MODEM_MANAGER (user_data); + gs_free_error GError *error = NULL; + + self->priv->ofono_proxy = g_dbus_proxy_new_finish (res, &error); + if (error) { + nm_log_warn (LOGD_MB, "error getting oFono bus proxy: %s", error->message); + return; + } + + g_signal_connect (self->priv->ofono_proxy, + "notify::g-name-owner", + G_CALLBACK (ofono_name_owner_changed), + self); + + g_signal_connect (self->priv->ofono_proxy, + "g-signal", + G_CALLBACK (ofono_signal_cb), + self); + + ofono_check_name_owner (self); +} + +static void +ensure_ofono_client (NMModemManager *self) +{ + g_assert (self->priv->dbus_connection); + g_dbus_proxy_new (self->priv->dbus_connection, + G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, + NULL, + OFONO_DBUS_SERVICE, + OFONO_DBUS_PATH, + OFONO_DBUS_INTERFACE, + NULL, + (GAsyncReadyCallback) ofono_proxy_new_cb, + g_object_ref (self)); +} +#endif static void modem_manager_poke_cb (GDBusConnection *connection, @@ -235,19 +385,18 @@ modem_manager_poke_cb (GDBusConnection *connection, result = g_dbus_connection_call_finish (connection, res, &error); if (error) { - /* Ignore common errors when MM is not installed and such */ - if ( !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN) - && !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SPAWN_EXEC_FAILED) - && !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SPAWN_FORK_FAILED) - && !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SPAWN_FAILED) - && !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_TIMEOUT) - && !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND)) { - nm_log_dbg (LOGD_MB, "error poking ModemManager: %s", error->message); + nm_log_warn (LOGD_MB, "error poking ModemManager: %s", + error ? error->message : ""); + + /* Don't reschedule poke is MM service doesn't exist. */ + if (!g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN) + && !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND)) { + + /* Setup timeout to relaunch */ + schedule_modem_manager_relaunch (self, MODEM_POKE_INTERVAL); } - g_error_free (error); - /* Setup timeout to relaunch */ - schedule_modem_manager_relaunch (self, MODEM_POKE_INTERVAL); + g_error_free (error); } else g_variant_unref (result); @@ -273,25 +422,21 @@ modem_manager_poke (NMModemManager *self) g_object_ref (self)); /* user_data */ } -#endif /* HAVE_SYSTEMD */ - static void modem_manager_check_name_owner (NMModemManager *self) { - gchar *name_owner; + gs_free gchar *name_owner = NULL; name_owner = g_dbus_object_manager_client_get_name_owner (G_DBUS_OBJECT_MANAGER_CLIENT (self->priv->modem_manager)); if (name_owner) { /* Available! */ modem_manager_available (self); - g_free (name_owner); return; } -#if !HAVE_SYSTEMD /* If the lifecycle is not managed by systemd, poke */ - modem_manager_poke (self); -#endif + if (!sd_booted ()) + modem_manager_poke (self); } static void @@ -303,7 +448,8 @@ manager_new_ready (GObject *source, GError *error = NULL; - g_assert (!self->priv->modem_manager); + g_return_if_fail (!self->priv->modem_manager); + self->priv->modem_manager = mm_manager_new_finish (res, &error); if (!self->priv->modem_manager) { /* We're not really supposed to get any error here. If we do get one, @@ -316,20 +462,20 @@ manager_new_ready (GObject *source, } else { /* Setup signals in the GDBusObjectManagerClient */ self->priv->mm_name_owner_changed_id = - g_signal_connect (self->priv->modem_manager, - "notify::name-owner", - G_CALLBACK (modem_manager_name_owner_changed), - self); + g_signal_connect (self->priv->modem_manager, + "notify::name-owner", + G_CALLBACK (modem_manager_name_owner_changed), + self); self->priv->mm_object_added_id = - g_signal_connect (self->priv->modem_manager, - "object-added", - G_CALLBACK (modem_object_added), - self); + g_signal_connect (self->priv->modem_manager, + "object-added", + G_CALLBACK (modem_object_added), + self); self->priv->mm_object_removed_id = - g_signal_connect (self->priv->modem_manager, - "object-removed", - G_CALLBACK (modem_object_removed), - self); + g_signal_connect (self->priv->modem_manager, + "object-removed", + G_CALLBACK (modem_object_removed), + self); modem_manager_check_name_owner (self); } @@ -339,7 +485,7 @@ manager_new_ready (GObject *source, } static void -ensure_client (NMModemManager *self) +ensure_modem_manager (NMModemManager *self) { g_assert (self->priv->dbus_connection); @@ -359,46 +505,12 @@ ensure_client (NMModemManager *self) modem_manager_check_name_owner (self); } -static void -bus_get_ready (GObject *source, - GAsyncResult *res, - NMModemManager *self) -{ - /* Note we always get an extra reference to self here */ - - GError *error = NULL; - - self->priv->dbus_connection = g_bus_get_finish (res, &error); - if (!self->priv->dbus_connection) { - nm_log_warn (LOGD_CORE, "error getting bus connection: %s", error->message); - g_error_free (error); - /* Setup timeout to relaunch */ - schedule_modem_manager_relaunch (self, MODEM_POKE_INTERVAL); - } else { - /* Got the bus, ensure client */ - ensure_client (self); - } - - /* Balance refcount */ - g_object_unref (self); -} - static gboolean -ensure_bus (NMModemManager *self) +mm_launch_cb (NMModemManager *self) { - /* Clear launch ID */ self->priv->mm_launch_id = 0; - - if (!self->priv->dbus_connection) - g_bus_get (G_BUS_TYPE_SYSTEM, - NULL, - (GAsyncReadyCallback)bus_get_ready, - g_object_ref (self)); - else - /* If bus is already available, ensure client */ - ensure_client (self); - - return FALSE; + ensure_modem_manager (self); + return G_SOURCE_REMOVE; } static void @@ -407,11 +519,31 @@ schedule_modem_manager_relaunch (NMModemManager *self, { /* No need to pass an extra reference to self; timeout/idle will be * cancelled if the object gets disposed. */ - if (n_seconds) - self->priv->mm_launch_id = g_timeout_add_seconds (n_seconds, (GSourceFunc)ensure_bus, self); + self->priv->mm_launch_id = g_timeout_add_seconds (n_seconds, (GSourceFunc)mm_launch_cb, self); else - self->priv->mm_launch_id = g_idle_add ((GSourceFunc)ensure_bus, self); + self->priv->mm_launch_id = g_idle_add ((GSourceFunc)mm_launch_cb, self); +} + +static void +bus_get_ready (GObject *source, + GAsyncResult *res, + gpointer user_data) +{ + gs_unref_object NMModemManager *self = NM_MODEM_MANAGER (user_data); + gs_free_error GError *error = NULL; + + self->priv->dbus_connection = g_bus_get_finish (res, &error); + if (!self->priv->dbus_connection) { + nm_log_warn (LOGD_MB, "error getting bus connection: %s", error->message); + return; + } + + /* Got the bus, ensure clients */ + ensure_modem_manager (self); +#if WITH_OFONO + ensure_ofono_client (self); +#endif } /************************************************************************/ @@ -423,7 +555,11 @@ nm_modem_manager_init (NMModemManager *self) self->priv->modems = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); - schedule_modem_manager_relaunch (self, 0); + // FIXME: this doesn't handle bus-daemon restart + g_bus_get (G_BUS_TYPE_SYSTEM, + NULL, + (GAsyncReadyCallback)bus_get_ready, + g_object_ref (self)); } static void @@ -433,8 +569,16 @@ dispose (GObject *object) nm_clear_g_source (&self->priv->mm_launch_id); - modem_manager_clear_signals (self); - g_clear_object (&self->priv->modem_manager); + clear_modem_manager (self); + +#if WITH_OFONO + if (self->priv->ofono_proxy) { + g_signal_handlers_disconnect_by_func (self->priv->ofono_proxy, ofono_name_owner_changed, self); + g_signal_handlers_disconnect_by_func (self->priv->ofono_proxy, ofono_signal_cb, self); + g_clear_object (&self->priv->ofono_proxy); + } +#endif + g_clear_object (&self->priv->dbus_connection); if (self->priv->modems) { diff --git a/src/devices/wwan/nm-modem-ofono.c b/src/devices/wwan/nm-modem-ofono.c new file mode 100644 index 00000000..86492d3d --- /dev/null +++ b/src/devices/wwan/nm-modem-ofono.c @@ -0,0 +1,1202 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * 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. + * + * Copyright (C) 2013 - 2016 Canonical Ltd. + */ + +#include "nm-default.h" + +#include "nm-modem-ofono.h" + +#include <string.h> + +#include "nm-core-internal.h" +#include "nm-device-private.h" +#include "nm-modem.h" +#include "nm-platform.h" + +G_DEFINE_TYPE (NMModemOfono, nm_modem_ofono, NM_TYPE_MODEM) + +#define NM_MODEM_OFONO_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MODEM_OFONO, NMModemOfonoPrivate)) + +#define VARIANT_IS_OF_TYPE_BOOLEAN(v) ((v) != NULL && ( g_variant_is_of_type ((v), G_VARIANT_TYPE_BOOLEAN) )) +#define VARIANT_IS_OF_TYPE_STRING(v) ((v) != NULL && ( g_variant_is_of_type ((v), G_VARIANT_TYPE_STRING) )) +#define VARIANT_IS_OF_TYPE_OBJECT_PATH(v) ((v) != NULL && ( g_variant_is_of_type ((v), G_VARIANT_TYPE_OBJECT_PATH) )) +#define VARIANT_IS_OF_TYPE_STRING_ARRAY(v) ((v) != NULL && ( g_variant_is_of_type ((v), G_VARIANT_TYPE_STRING_ARRAY) )) +#define VARIANT_IS_OF_TYPE_DICTIONARY(v) ((v) != NULL && ( g_variant_is_of_type ((v), G_VARIANT_TYPE_DICTIONARY) )) + +typedef struct { + GHashTable *connect_properties; + + GDBusProxy *modem_proxy; + GDBusProxy *connman_proxy; + GDBusProxy *context_proxy; + GDBusProxy *sim_proxy; + + GError *property_error; + + char *context_path; + char *imsi; + + gboolean modem_online; + gboolean gprs_attached; + + NMIP4Config *ip4_config; +} NMModemOfonoPrivate; + +/*****************************************************************************/ + +#define _NMLOG_DOMAIN LOGD_MB +#define _NMLOG_PREFIX_NAME "modem-ofono" +#define _NMLOG(level, ...) \ + G_STMT_START { \ + const NMLogLevel _level = (level); \ + \ + if (nm_logging_enabled (_level, (_NMLOG_DOMAIN))) { \ + NMModemOfono *const __self = (self); \ + char __prefix_name[128]; \ + const char *__uid; \ + \ + _nm_log (_level, (_NMLOG_DOMAIN), 0, \ + "%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + _NMLOG_PREFIX_NAME, \ + (__self \ + ? ({ \ + ((__uid = nm_modem_get_uid ((NMModem *) __self)) \ + ? nm_sprintf_buf (__prefix_name, "[%s]", __uid) \ + : "(null)"); \ + }) \ + : "") \ + _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ + } G_STMT_END + +/*****************************************************************************/ + +static gboolean +ip_string_to_network_address (const gchar *str, + guint32 *out) +{ + guint32 addr = 0; + gboolean success = FALSE; + + if (!str || inet_pton (AF_INET, str, &addr) != 1) + addr = 0; + else + success = TRUE; + + *out = (guint32)addr; + return success; +} + +static void +get_capabilities (NMModem *_self, + NMDeviceModemCapabilities *modem_caps, + NMDeviceModemCapabilities *current_caps) +{ + /* FIXME: auto-detect capabilities to allow LTE */ + *modem_caps = NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS; + *current_caps = NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS; +} + +static void +update_modem_state (NMModemOfono *self) +{ + NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE (self); + NMModemState state = nm_modem_get_state (NM_MODEM (self)); + NMModemState new_state = NM_MODEM_STATE_DISABLED; + const char *reason = NULL; + + _LOGI ("'Attached': %s 'Online': %s 'IMSI': %s", + priv->gprs_attached ? "true" : "false", + priv->modem_online ? "true" : "false", + priv->imsi); + + if (priv->modem_online == FALSE) { + reason = "modem 'Online=false'"; + } else if (priv->imsi == NULL && state != NM_MODEM_STATE_ENABLING) { + reason = "modem not ready"; + } else if (priv->gprs_attached == FALSE) { + new_state = NM_MODEM_STATE_SEARCHING; + reason = "modem searching"; + } else { + new_state = NM_MODEM_STATE_REGISTERED; + reason = "modem ready"; + } + + if (state != new_state) + nm_modem_set_state (NM_MODEM (self), new_state, reason); +} + +/* Disconnect */ +typedef struct { + NMModemOfono *self; + GSimpleAsyncResult *result; + GCancellable *cancellable; + gboolean warn; +} DisconnectContext; + +static void +disconnect_context_complete (DisconnectContext *ctx) +{ + g_simple_async_result_complete_in_idle (ctx->result); + if (ctx->cancellable) + g_object_unref (ctx->cancellable); + g_object_unref (ctx->result); + g_object_unref (ctx->self); + g_slice_free (DisconnectContext, ctx); +} + +static gboolean +disconnect_context_complete_if_cancelled (DisconnectContext *ctx) +{ + GError *error = NULL; + + if (g_cancellable_set_error_if_cancelled (ctx->cancellable, &error)) { + g_simple_async_result_take_error (ctx->result, error); + disconnect_context_complete (ctx); + return TRUE; + } + + return FALSE; +} + +static gboolean +disconnect_finish (NMModem *self, + GAsyncResult *result, + GError **error) +{ + return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error); +} + +static void +disconnect_done (GDBusProxy *proxy, + GAsyncResult *result, + gpointer user_data) +{ + DisconnectContext *ctx = (DisconnectContext*) user_data; + NMModemOfono *self = ctx->self; + GError *error = NULL; + + g_dbus_proxy_call_finish (proxy, result, &error); + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + _LOGD ("disconnect cancelled"); + return; + } + + if (error) { + if (ctx->warn) + _LOGW ("failed to disconnect modem: %s", error->message); + g_clear_error (&error); + } + + _LOGD ("modem disconnected"); + + update_modem_state (self); + disconnect_context_complete (ctx); +} + +static void +disconnect (NMModem *modem, + gboolean warn, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + NMModemOfono *self = NM_MODEM_OFONO (modem); + NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE (self); + DisconnectContext *ctx; + NMModemState state = nm_modem_get_state (NM_MODEM (self)); + + _LOGD ("warn: %s modem_state: %s", + warn ? "TRUE" : "FALSE", + nm_modem_state_to_string (state)); + + if (state != NM_MODEM_STATE_CONNECTED) + return; + + ctx = g_slice_new (DisconnectContext); + ctx->self = g_object_ref (self); + ctx->warn = warn; + + if (callback) { + ctx->result = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + disconnect); + } + /* Setup cancellable */ + ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL; + if (disconnect_context_complete_if_cancelled (ctx)) + return; + + nm_modem_set_state (NM_MODEM (self), + NM_MODEM_STATE_DISCONNECTING, + nm_modem_state_to_string (NM_MODEM_STATE_DISCONNECTING)); + + g_dbus_proxy_call (priv->context_proxy, + "SetProperty", + g_variant_new ("(sv)", + "Active", + g_variant_new ("b", warn)), + G_DBUS_CALL_FLAGS_NONE, + 20000, + NULL, + (GAsyncReadyCallback) disconnect_done, + ctx); +} + +static void +deactivate_cleanup (NMModem *_self, NMDevice *device) +{ + NMModemOfono *self = NM_MODEM_OFONO (_self); + NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE (self); + + /* TODO: cancel SimpleConnect() if any */ + + g_clear_object (&priv->ip4_config); + + /* Chain up parent's */ + NM_MODEM_CLASS (nm_modem_ofono_parent_class)->deactivate_cleanup (_self, device); +} + + +static gboolean +check_connection_compatible (NMModem *modem, + NMConnection *connection) +{ + NMModemOfono *self = NM_MODEM_OFONO (modem); + NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE (self); + NMSettingConnection *s_con; + NMSettingGsm *s_gsm; + const char *uuid; + const char *id; + + s_con = nm_connection_get_setting_connection (connection); + g_assert (s_con); + + uuid = nm_connection_get_uuid (connection); + id = nm_connection_get_id (connection); + + s_gsm = nm_connection_get_setting_gsm (connection); + if (!s_gsm) + return FALSE; + + if (!priv->imsi) { + _LOGW ("skipping %s/%s: no IMSI", uuid, id); + return FALSE; + } + + if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_GSM_SETTING_NAME)) { + _LOGD ("skipping %s/%s: not GSM", uuid, id); + return FALSE; + } + + if (!g_strrstr (id, "/context")) { + _LOGD ("skipping %s/%s: unexpected ID", uuid, id); + return FALSE; + } + + if (!g_strrstr (id, priv->imsi)) { + _LOGD ("skipping %s/%s: ID doesn't contain IMSI", uuid, id); + return FALSE; + } + + _LOGD ("%s/%s compatible with IMSI %s", uuid, id, priv->imsi); + return TRUE; +} + +static void +handle_sim_property (GDBusProxy *proxy, + const char *property, + GVariant *v, + gpointer user_data) +{ + NMModemOfono *self = NM_MODEM_OFONO (user_data); + NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE (self); + + if (g_strcmp0 (property, "SubscriberIdentity") == 0 && VARIANT_IS_OF_TYPE_STRING (v)) { + gsize length; + const char *value_str = g_variant_get_string (v, &length); + + _LOGD ("SubscriberIdentify found"); + + /* Check for empty DBus string value */ + if (length && + g_strcmp0 (value_str, "(null)") != 0 && + g_strcmp0 (value_str, priv->imsi) != 0) { + + if (priv->imsi != NULL) { + _LOGW ("SimManager:'SubscriberIdentity' changed: %s", priv->imsi); + g_free(priv->imsi); + } + + priv->imsi = g_strdup (value_str); + update_modem_state (self); + } + } +} + +static void +sim_property_changed (GDBusProxy *proxy, + const char *property, + GVariant *v, + gpointer user_data) +{ + GVariant *v_child = g_variant_get_child_value (v, 0); + + handle_sim_property (proxy, property, v_child, user_data); + g_variant_unref (v_child); +} + +static void +sim_get_properties_done (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) +{ + gs_unref_object NMModemOfono *self = NM_MODEM_OFONO (user_data); + GError *error = NULL; + GVariant *v_properties, *v_dict, *v; + GVariantIter i; + const char *property; + + v_properties = _nm_dbus_proxy_call_finish (proxy, + result, + G_VARIANT_TYPE ("(a{sv})"), + &error); + if (!v_properties) { + g_dbus_error_strip_remote_error (error); + _LOGW ("error getting sim properties: %s", error->message); + g_error_free (error); + return; + } + + _LOGD ("sim v_properties is type: %s", g_variant_get_type_string (v_properties)); + + v_dict = g_variant_get_child_value (v_properties, 0); + if (!v_dict) { + _LOGW ("error getting sim properties: no v_dict"); + return; + } + + _LOGD ("sim v_dict is type: %s", g_variant_get_type_string (v_dict)); + + /* + * TODO: + * 1) optimize by looking up properties ( Online, Interfaces ), instead + * of iterating + * + * 2) reduce code duplication between all of the get_properties_done + * functions in this class. + */ + + g_variant_iter_init (&i, v_dict); + while (g_variant_iter_next (&i, "{&sv}", &property, &v)) { + handle_sim_property (NULL, property, v, self); + g_variant_unref (v); + } + + g_variant_unref (v_dict); + g_variant_unref (v_properties); +} + +static void +handle_sim_iface (NMModemOfono *self, gboolean found) +{ + NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE (self); + + _LOGD ("SimManager interface %sfound", found ? "" : "not "); + + if (!found && priv->sim_proxy) { + _LOGI ("SimManager interface disappeared"); + g_signal_handlers_disconnect_by_data (priv->sim_proxy, NM_MODEM_OFONO (self)); + g_clear_object (&priv->sim_proxy); + g_clear_pointer (&priv->imsi, g_free); + update_modem_state (self); + } else if (found && !priv->sim_proxy) { + GError *error = NULL; + + _LOGI ("found new SimManager interface"); + + priv->sim_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES + | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, + NULL, /* GDBusInterfaceInfo */ + OFONO_DBUS_SERVICE, + nm_modem_get_path (NM_MODEM (self)), + OFONO_DBUS_INTERFACE_SIM_MANAGER, + NULL, /* GCancellable */ + &error); + if (priv->sim_proxy == NULL) { + _LOGW ("failed to create SimManager proxy: %s", error->message); + g_error_free (error); + return; + } + + /* Watch for custom ofono PropertyChanged signals */ + _nm_dbus_signal_connect (priv->sim_proxy, + "PropertyChanged", + G_VARIANT_TYPE ("(sv)"), + G_CALLBACK (sim_property_changed), + self); + + g_dbus_proxy_call (priv->sim_proxy, + "GetProperties", + NULL, + G_DBUS_CALL_FLAGS_NONE, + 20000, + NULL, + (GAsyncReadyCallback) sim_get_properties_done, + g_object_ref (self)); + } +} + +static void +handle_connman_property (GDBusProxy *proxy, + const char *property, + GVariant *v, + gpointer user_data) +{ + NMModemOfono *self = NM_MODEM_OFONO (user_data); + NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE (self); + + if (g_strcmp0 (property, "Attached") == 0 && VARIANT_IS_OF_TYPE_BOOLEAN (v)) { + gboolean attached = g_variant_get_boolean (v); + gboolean old_attached = priv->gprs_attached; + + _LOGD ("Attached: %s", attached ? "True" : "False"); + + if (priv->gprs_attached != attached) { + priv->gprs_attached = attached; + + _LOGI ("Attached %s -> %s", + old_attached ? "true" : "false", + attached ? "true" : "false"); + + update_modem_state (self); + } + } +} + +static void +connman_property_changed (GDBusProxy *proxy, + const char *property, + GVariant *v, + gpointer user_data) +{ + GVariant *v_child = g_variant_get_child_value (v, 0); + + handle_connman_property (proxy, property, v_child, user_data); + g_variant_unref (v_child); +} + +static void +connman_get_properties_done (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) +{ + gs_unref_object NMModemOfono *self = NM_MODEM_OFONO (user_data); + GError *error = NULL; + GVariant *v_properties, *v_dict, *v; + GVariantIter i; + const char *property; + + v_properties = _nm_dbus_proxy_call_finish (proxy, + result, + G_VARIANT_TYPE ("(a{sv})"), + &error); + if (!v_properties) { + g_dbus_error_strip_remote_error (error); + _LOGW ("error getting connman properties: %s", error->message); + g_error_free (error); + return; + } + + v_dict = g_variant_get_child_value (v_properties, 0); + + /* + * TODO: + * 1) optimize by looking up properties ( Online, Interfaces ), instead + * of iterating + * + * 2) reduce code duplication between all of the get_properties_done + * functions in this class. + */ + + g_variant_iter_init (&i, v_dict); + while (g_variant_iter_next (&i, "{&sv}", &property, &v)) { + handle_connman_property (NULL, property, v, self); + g_variant_unref (v); + } + + g_variant_unref (v_dict); + g_variant_unref (v_properties); +} + +static void +handle_connman_iface (NMModemOfono *self, gboolean found) +{ + NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE (self); + + _LOGD ("ConnectionManager interface %sfound", found ? "" : "not "); + + if (!found && priv->connman_proxy) { + _LOGI ("ConnectionManager interface disappeared"); + + g_signal_handlers_disconnect_by_data (priv->connman_proxy, NM_MODEM_OFONO (self)); + g_clear_object (&priv->connman_proxy); + + /* The connection manager proxy disappeared, we should + * consider the modem disabled. + */ + priv->gprs_attached = FALSE; + + update_modem_state (self); + } else if (found && !priv->connman_proxy) { + GError *error = NULL; + + _LOGI ("found new ConnectionManager interface"); + + priv->connman_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES + | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, + NULL, /* GDBusInterfaceInfo */ + OFONO_DBUS_SERVICE, + nm_modem_get_path (NM_MODEM (self)), + OFONO_DBUS_INTERFACE_CONNECTION_MANAGER, + NULL, /* GCancellable */ + &error); + if (priv->connman_proxy == NULL) { + _LOGW ("failed to create ConnectionManager proxy: %s", error->message); + g_error_free (error); + return; + } + + /* Watch for custom ofono PropertyChanged signals */ + _nm_dbus_signal_connect (priv->connman_proxy, + "PropertyChanged", + G_VARIANT_TYPE ("(sv)"), + G_CALLBACK (connman_property_changed), + self); + + g_dbus_proxy_call (priv->connman_proxy, + "GetProperties", + NULL, + G_DBUS_CALL_FLAGS_NONE, + 20000, + NULL, + (GAsyncReadyCallback) connman_get_properties_done, + g_object_ref (self)); + } +} + +static void +handle_modem_property (GDBusProxy *proxy, + const char *property, + GVariant *v, + gpointer user_data) +{ + NMModemOfono *self = NM_MODEM_OFONO (user_data); + NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE (self); + + if ((g_strcmp0 (property, "Online") == 0) && VARIANT_IS_OF_TYPE_BOOLEAN (v)) { + gboolean online = g_variant_get_boolean (v); + + _LOGD ("Online: %s", online ? "True" : "False"); + + if (online != priv->modem_online) { + priv->modem_online = online; + _LOGI ("modem is now %s", online ? "Online" : "Offline"); + update_modem_state (self); + } + + } else if ((g_strcmp0 (property, "Interfaces") == 0) && VARIANT_IS_OF_TYPE_STRING_ARRAY (v)) { + const char **array, **iter; + gboolean found_connman = FALSE; + gboolean found_sim = FALSE; + + _LOGD ("Interfaces found"); + + array = g_variant_get_strv (v, NULL); + if (array) { + for (iter = array; *iter; iter++) { + if (g_strcmp0 (OFONO_DBUS_INTERFACE_SIM_MANAGER, *iter) == 0) + found_sim = TRUE; + else if (g_strcmp0 (OFONO_DBUS_INTERFACE_CONNECTION_MANAGER, *iter) == 0) + found_connman = TRUE; + } + g_free (array); + } + + handle_sim_iface (self, found_sim); + handle_connman_iface (self, found_connman); + } +} + +static void +modem_property_changed (GDBusProxy *proxy, + const char *property, + GVariant *v, + gpointer user_data) +{ + GVariant *v_child = g_variant_get_child_value (v, 0); + + handle_modem_property (proxy, property, v_child, user_data); + g_variant_unref (v_child); +} + +static void +modem_get_properties_done (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) +{ + gs_unref_object NMModemOfono *self = NM_MODEM_OFONO (user_data); + GError *error = NULL; + GVariant *v_properties, *v_dict, *v; + GVariantIter i; + const char *property; + + v_properties = _nm_dbus_proxy_call_finish (proxy, + result, + G_VARIANT_TYPE ("(a{sv})"), + &error); + if (!v_properties) { + g_dbus_error_strip_remote_error (error); + _LOGW ("error getting modem properties: %s", error->message); + g_error_free (error); + return; + } + + v_dict = g_variant_get_child_value (v_properties, 0); + if (!v_dict) { + _LOGW ("error getting modem properties: no v_dict"); + return; + } + + /* + * TODO: + * 1) optimize by looking up properties ( Online, Interfaces ), instead + * of iterating + * + * 2) reduce code duplication between all of the get_properties_done + * functions in this class. + */ + + g_variant_iter_init (&i, v_dict); + while (g_variant_iter_next (&i, "{&sv}", &property, &v)) { + handle_modem_property (NULL, property, v, self); + g_variant_unref (v); + } + + g_variant_unref (v_dict); + g_variant_unref (v_properties); +} + +NMModem * +nm_modem_ofono_new (const char *path) +{ + gs_free char *basename = NULL; + + g_return_val_if_fail (path != NULL, NULL); + + nm_log_info (LOGD_MB, "ofono: creating new Ofono modem path %s", path); + + /* Use short modem name (not its object path) as the NM device name (which + * comes from NM_MODEM_UID)and the device ID. + */ + basename = g_path_get_basename (path); + + return (NMModem *) g_object_new (NM_TYPE_MODEM_OFONO, + NM_MODEM_PATH, path, + NM_MODEM_UID, basename, + NM_MODEM_DEVICE_ID, basename, + NM_MODEM_CONTROL_PORT, "ofono", /* mandatory */ + NM_MODEM_DRIVER, "ofono", + NM_MODEM_STATE, NM_MODEM_STATE_INITIALIZING, + NULL); +} + +static void +stage1_prepare_done (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) +{ + gs_unref_object NMModemOfono *self = NM_MODEM_OFONO (user_data); + NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE (self); + GError *error = NULL; + + g_clear_pointer (&priv->connect_properties, g_hash_table_destroy); + + g_dbus_proxy_call_finish (proxy, result, &error); + if (error) { + _LOGW ("connection failed: %s", error->message); + + g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, + NM_DEVICE_STATE_REASON_MODEM_BUSY); + /* + * FIXME: add code to check for InProgress so that the + * connection doesn't continue to try and activate, + * leading to the connection being disabled, and a 5m + * timeout... + */ + + g_clear_error (&error); + } +} + +static void +context_property_changed (GDBusProxy *proxy, + const char *property, + GVariant *v, + gpointer user_data) +{ + NMModemOfono *self = NM_MODEM_OFONO (user_data); + NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE (self); + NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; + NMPlatformIP4Address addr; + gboolean ret = FALSE; + GVariant *v_dict; + const gchar *s, *addr_s; + const gchar **array, **iter; + guint32 address_network, gateway_network; + guint prefix = 0; + + _LOGD ("PropertyChanged: %s", property); + + /* + * TODO: might be a good idea and re-factor this to mimic bluez-device, + * ie. have this function just check the key, and call a sub-func to + * handle the action. + */ + + if (g_strcmp0 (property, "Settings") != 0) + return; + + v_dict = g_variant_get_child_value (v, 0); + if (!v_dict) { + _LOGW ("error getting IPv4 Settings: no v_dict"); + goto out; + } + + _LOGI ("IPv4 static Settings:"); + + if (g_variant_lookup (v_dict, "Interface", "&s", &s)) { + if (s && strlen (s)) { + _LOGD ("Interface: %s", s); + g_object_set (self, + NM_MODEM_DATA_PORT, g_strdup (s), + NM_MODEM_IP4_METHOD, NM_MODEM_IP_METHOD_STATIC, + NULL); + } else { + _LOGW ("Settings 'Interface'; empty"); + goto out; + } + + } else { + _LOGW ("Settings 'Interface' missing"); + goto out; + } + + /* TODO: verify handling of ip4_config; check other places it's used... */ + g_clear_object (&priv->ip4_config); + + memset (&addr, 0, sizeof (addr)); + + /* + * TODO: + * + * NM 1.2 changed the NMIP4Config constructor to take an ifindex + * ( vs. void pre 1.2 ), to tie config instance to a specific + * platform interface. + * + * This doesn't work for ofono, as the devices are created + * dynamically ( eg. ril_0, ril_1 ) in NMModemManager. The + * device created doesn't really map directly to a platform + * link. The closest would be one of the devices owned by + * rild ( eg. ccmin0 ), which is passed to us above as + * 'Interface'. + * + * This needs discussion with upstream. + */ + priv->ip4_config = nm_ip4_config_new (0); + + /* TODO: simply if/else error logic! */ + + if (g_variant_lookup (v_dict, "Address", "&s", &addr_s)) { + _LOGD ("Address: %s", addr_s); + + if (ip_string_to_network_address (addr_s, &address_network)) { + addr.address = address_network; + addr.addr_source = NM_IP_CONFIG_SOURCE_WWAN; + } else { + _LOGW ("can't convert 'Address' %s to addr", s); + goto out; + } + + } else { + _LOGW ("Settings 'Address' missing"); + goto out; + } + + if (g_variant_lookup (v_dict, "Netmask", "&s", &s)) { + _LOGD ("Netmask: %s", s); + + if (s && ip_string_to_network_address (s, &address_network)) { + prefix = nm_utils_ip4_netmask_to_prefix (address_network); + if (prefix > 0) + addr.plen = prefix; + } else { + _LOGW ("invalid 'Netmask': %s", s); + goto out; + } + } else { + _LOGW ("Settings 'Netmask' missing"); + goto out; + } + + _LOGI ("Address: %s/%d", addr_s, prefix); + + nm_ip4_config_add_address (priv->ip4_config, &addr); + + if (g_variant_lookup (v_dict, "Gateway", "&s", &s)) { + if (s && ip_string_to_network_address (s, &gateway_network)) { + _LOGI ("Gateway: %s", s); + nm_ip4_config_set_gateway (priv->ip4_config, gateway_network); + } else { + _LOGW ("invalid 'Gateway': %s", s); + goto out; + } + nm_ip4_config_set_gateway (priv->ip4_config, gateway_network); + } else { + _LOGW ("Settings 'Gateway' missing"); + goto out; + } + + if (g_variant_lookup (v_dict, "DomainNameServers", "^a&s", &array)) { + if (array) { + for (iter = array; *iter; iter++) { + if (ip_string_to_network_address (*iter, &address_network) && address_network > 0) { + _LOGI ("DNS: %s", *iter); + nm_ip4_config_add_nameserver (priv->ip4_config, address_network); + } else { + _LOGW ("invalid NameServer: %s", *iter); + } + } + + if (iter == array) { + _LOGW ("Settings: 'DomainNameServers': none specified"); + g_free (array); + goto out; + } + g_free (array); + } + } else { + _LOGW ("Settings 'DomainNameServers' missing"); + goto out; + } + + if (g_variant_lookup (v_dict, "MessageProxy", "&s", &s)) { + _LOGI ("MessageProxy: %s", s); + if (s && ip_string_to_network_address (s, &address_network)) { + NMPlatformIP4Route mms_route; + + mms_route.network = address_network; + mms_route.plen = 32; + mms_route.gateway = gateway_network; + + mms_route.metric = 1; + + nm_ip4_config_add_route (priv->ip4_config, &mms_route); + } else { + _LOGW ("invalid MessageProxy: %s", s); + } + } + + ret = TRUE; + +out: + if (nm_modem_get_state (NM_MODEM (self)) != NM_MODEM_STATE_CONNECTED) { + _LOGI ("emitting PREPARE_RESULT: %s", ret ? "TRUE" : "FALSE"); + if (!ret) + reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE; + g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, ret, reason); + } else { + _LOGW ("MODEM_PPP_FAILED"); + g_signal_emit_by_name (self, NM_MODEM_PPP_FAILED, NM_DEVICE_STATE_REASON_PPP_FAILED); + } +} + +static NMActStageReturn +static_stage3_ip4_config_start (NMModem *_self, + NMActRequest *req, + NMDeviceStateReason *reason) +{ + NMModemOfono *self = NM_MODEM_OFONO (_self); + NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE (self); + NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; + GError *error = NULL; + + if (priv->ip4_config) { + _LOGD ("IP4 config is done; setting modem_state -> CONNECTED"); + g_signal_emit_by_name (self, NM_MODEM_IP4_CONFIG_RESULT, priv->ip4_config, error); + + /* Signal listener takes ownership of the IP4Config */ + priv->ip4_config = NULL; + + nm_modem_set_state (NM_MODEM (self), + NM_MODEM_STATE_CONNECTED, + nm_modem_state_to_string (NM_MODEM_STATE_CONNECTED)); + ret = NM_ACT_STAGE_RETURN_POSTPONE; + } + + return ret; +} + +static void +context_proxy_new_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) +{ + gs_unref_object NMModemOfono *self = NM_MODEM_OFONO (user_data); + NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE (self); + GError *error = NULL; + + priv->context_proxy = g_dbus_proxy_new_for_bus_finish (result, &error); + if (error) { + _LOGE ("failed to create ofono ConnectionContext DBus proxy: %s", error->message); + g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, + NM_DEVICE_STATE_REASON_MODEM_BUSY); + return; + } + + if (!priv->gprs_attached) { + g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, + NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER); + return; + } + + /* We have an old copy of the settings from a previous activation, + * clear it so that we can gate getting the IP config from oFono + * on whether or not we have already received them + */ + g_clear_object (&priv->ip4_config); + + /* Watch for custom ofono PropertyChanged signals */ + _nm_dbus_signal_connect (priv->context_proxy, + "PropertyChanged", + G_VARIANT_TYPE ("(sv)"), + G_CALLBACK (context_property_changed), + self); + + g_dbus_proxy_call (priv->context_proxy, + "SetProperty", + g_variant_new ("(sv)", + "Active", + g_variant_new ("b", TRUE)), + G_DBUS_CALL_FLAGS_NONE, + 20000, + NULL, + (GAsyncReadyCallback) stage1_prepare_done, + g_object_ref (self)); +} + +static void +do_context_activate (NMModemOfono *self) +{ + NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE (self); + + g_return_if_fail (NM_IS_MODEM_OFONO (self)); + + g_clear_object (&priv->context_proxy); + g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, + NULL, + OFONO_DBUS_SERVICE, + priv->context_path, + OFONO_DBUS_INTERFACE_CONNECTION_CONTEXT, + NULL, + (GAsyncReadyCallback) context_proxy_new_cb, + g_object_ref (self)); +} + +static GHashTable * +create_connect_properties (NMConnection *connection) +{ + NMSettingGsm *setting; + GHashTable *properties; + const char *str; + + setting = nm_connection_get_setting_gsm (connection); + properties = g_hash_table_new (g_str_hash, g_str_equal); + + str = nm_setting_gsm_get_apn (setting); + if (str) + g_hash_table_insert (properties, "AccessPointName", g_strdup (str)); + + str = nm_setting_gsm_get_username (setting); + if (str) + g_hash_table_insert (properties, "Username", g_strdup (str)); + + str = nm_setting_gsm_get_password (setting); + if (str) + g_hash_table_insert (properties, "Password", g_strdup (str)); + + return properties; +} + +static NMActStageReturn +act_stage1_prepare (NMModem *modem, + NMConnection *connection, + NMDeviceStateReason *reason) +{ + NMModemOfono *self = NM_MODEM_OFONO (modem); + NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE (self); + const char *context_id; + char **id = NULL; + + context_id = nm_connection_get_id (connection); + id = g_strsplit (context_id, "/", 0); + g_assert (id[2]); + + _LOGD ("trying %s %s", id[1], id[2]); + + g_free (priv->context_path); + priv->context_path = g_strdup_printf ("%s/%s", + nm_modem_get_path (modem), + id[2]); + g_strfreev (id); + + if (!priv->context_path) { + *reason = NM_DEVICE_STATE_REASON_GSM_APN_FAILED; + return NM_ACT_STAGE_RETURN_FAILURE; + } + + if (priv->connect_properties) + g_hash_table_destroy (priv->connect_properties); + + priv->connect_properties = create_connect_properties (connection); + + _LOGI ("activating context %s", priv->context_path); + + if (nm_modem_get_state (modem) == NM_MODEM_STATE_REGISTERED) { + do_context_activate (self); + } else { + _LOGW ("could not activate context: modem is not registered."); + *reason = NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER; + return NM_ACT_STAGE_RETURN_FAILURE; + } + + return NM_ACT_STAGE_RETURN_POSTPONE; +} + +static void +modem_proxy_new_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) +{ + gs_unref_object NMModemOfono *self = NM_MODEM_OFONO (user_data); + NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE (self); + GError *error = NULL; + + priv->modem_proxy = g_dbus_proxy_new_for_bus_finish (result, &error); + if (error) { + _LOGE ("failed to create ofono modem DBus proxy: %s", error->message); + return; + } + + /* Watch for custom ofono PropertyChanged signals */ + _nm_dbus_signal_connect (priv->modem_proxy, + "PropertyChanged", + G_VARIANT_TYPE ("(sv)"), + G_CALLBACK (modem_property_changed), + self); + + g_dbus_proxy_call (priv->modem_proxy, + "GetProperties", + NULL, + G_DBUS_CALL_FLAGS_NONE, + 20000, + NULL, + (GAsyncReadyCallback) modem_get_properties_done, + g_object_ref (self)); +} + +static void +nm_modem_ofono_init (NMModemOfono *self) +{ +} + +static void +constructed (GObject *object) +{ + NMModemOfono *self = NM_MODEM_OFONO (object); + + g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, + NULL, + OFONO_DBUS_SERVICE, + nm_modem_get_path (NM_MODEM (self)), + OFONO_DBUS_INTERFACE_MODEM, + NULL, + (GAsyncReadyCallback) modem_proxy_new_cb, + g_object_ref (self)); +} + +static void +dispose (GObject *object) +{ + NMModemOfono *self = NM_MODEM_OFONO (object); + NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE (self); + + if (priv->connect_properties) { + g_hash_table_destroy (priv->connect_properties); + priv->connect_properties = NULL; + } + + g_clear_object (&priv->ip4_config); + + if (priv->modem_proxy) { + g_signal_handlers_disconnect_by_data (priv->modem_proxy, NM_MODEM_OFONO (self)); + g_clear_object (&priv->modem_proxy); + } + + g_clear_object (&priv->connman_proxy); + g_clear_object (&priv->context_proxy); + + if (priv->sim_proxy) { + g_signal_handlers_disconnect_by_data (priv->sim_proxy, NM_MODEM_OFONO (self)); + g_clear_object (&priv->sim_proxy); + } + + g_free (priv->imsi); + priv->imsi = NULL; + + G_OBJECT_CLASS (nm_modem_ofono_parent_class)->dispose (object); +} + +static void +nm_modem_ofono_class_init (NMModemOfonoClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMModemClass *modem_class = NM_MODEM_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMModemOfonoPrivate)); + + /* Virtual methods */ + object_class->constructed = constructed; + object_class->dispose = dispose; + + modem_class->get_capabilities = get_capabilities; + modem_class->disconnect = disconnect; + modem_class->disconnect_finish = disconnect_finish; + modem_class->deactivate_cleanup = deactivate_cleanup; + modem_class->check_connection_compatible = check_connection_compatible; + + /* same as nm-modem-broadband */ + modem_class->act_stage1_prepare = act_stage1_prepare; + + /* same as nm-modem-broadband */ + modem_class->static_stage3_ip4_config_start = static_stage3_ip4_config_start; +} diff --git a/src/devices/wwan/nm-modem-ofono.h b/src/devices/wwan/nm-modem-ofono.h new file mode 100644 index 00000000..5965526d --- /dev/null +++ b/src/devices/wwan/nm-modem-ofono.h @@ -0,0 +1,53 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * 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. + * + * Copyright (C) 2013 - Canonical Ltd. + */ + +#ifndef NM_MODEM_OFONO_H +#define NM_MODEM_OFONO_H + +#include "nm-modem.h" + +#define NM_TYPE_MODEM_OFONO (nm_modem_ofono_get_type ()) +#define NM_MODEM_OFONO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_MODEM_OFONO, NMModemOfono)) +#define NM_IS_MODEM_OFONO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_MODEM_OFONO)) +#define NM_MODEM_OFONO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_MODEM_OFONO, NMModemOfonoClass)) +#define NM_IS_MODEM_OFONO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_MODEM_OFONO)) +#define NM_MODEM_OFONO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_MODEM_OFONO, NMModemOfonoClass)) + +#define OFONO_DBUS_SERVICE "org.ofono" +#define OFONO_DBUS_PATH "/" +#define OFONO_DBUS_INTERFACE "org.ofono.Manager" +#define OFONO_DBUS_INTERFACE_MODEM "org.ofono.Modem" +#define OFONO_DBUS_INTERFACE_CONNECTION_MANAGER "org.ofono.ConnectionManager" +#define OFONO_DBUS_INTERFACE_CONNECTION_CONTEXT "org.ofono.ConnectionContext" +#define OFONO_DBUS_INTERFACE_SIM_MANAGER "org.ofono.SimManager" + +typedef struct { + NMModem parent; +} NMModemOfono; + +typedef struct { + NMModemClass parent; +} NMModemOfonoClass; + +GType nm_modem_ofono_get_type (void); + +NMModem *nm_modem_ofono_new (const char *path); + +#endif /* NM_MODEM_OFONO_H */ diff --git a/src/devices/wwan/nm-modem.c b/src/devices/wwan/nm-modem.c index a6c77007..2e3d63bb 100644 --- a/src/devices/wwan/nm-modem.c +++ b/src/devices/wwan/nm-modem.c @@ -202,7 +202,9 @@ nm_modem_set_mm_enabled (NMModem *self, return; } - NM_MODEM_GET_CLASS (self)->set_mm_enabled (self, enabled); + /* Not all modem classes support set_mm_enabled */ + if (NM_MODEM_GET_CLASS (self)->set_mm_enabled) + NM_MODEM_GET_CLASS (self)->set_mm_enabled (self, enabled); /* Pre-empt the state change signal */ nm_modem_set_state (self, @@ -573,6 +575,8 @@ nm_modem_stage3_ip4_config_start (NMModem *self, const char *method; NMActStageReturn ret; + nm_log_dbg (LOGD_MB, "ip4_config_start"); + g_return_val_if_fail (NM_IS_MODEM (self), NM_ACT_STAGE_RETURN_FAILURE); g_return_val_if_fail (NM_IS_DEVICE (device), NM_ACT_STAGE_RETURN_FAILURE); g_return_val_if_fail (NM_IS_DEVICE_CLASS (device_class), NM_ACT_STAGE_RETURN_FAILURE); @@ -602,9 +606,11 @@ nm_modem_stage3_ip4_config_start (NMModem *self, ret = ppp_stage3_ip_config_start (self, req, reason); break; case NM_MODEM_IP_METHOD_STATIC: + nm_log_dbg (LOGD_MB, "MODEM_IP_METHOD_STATIC"); ret = NM_MODEM_GET_CLASS (self)->static_stage3_ip4_config_start (self, req, reason); break; case NM_MODEM_IP_METHOD_AUTO: + nm_log_dbg (LOGD_MB, "MODEM_IP_METHOD_AUTO"); ret = device_class->act_stage3_ip4_config_start (device, NULL, reason); break; default: diff --git a/src/devices/wwan/nm-modem.h b/src/devices/wwan/nm-modem.h index 60e5589b..8f797d44 100644 --- a/src/devices/wwan/nm-modem.h +++ b/src/devices/wwan/nm-modem.h @@ -22,12 +22,9 @@ #ifndef __NETWORKMANAGER_MODEM_H__ #define __NETWORKMANAGER_MODEM_H__ -#include "nm-default.h" #include "ppp-manager/nm-ppp-manager.h" #include "nm-device.h" -G_BEGIN_DECLS - #define NM_TYPE_MODEM (nm_modem_get_type ()) #define NM_MODEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_MODEM, NMModem)) #define NM_MODEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_MODEM, NMModemClass)) @@ -268,6 +265,4 @@ void nm_modem_emit_ip6_config_result (NMModem *self, const gchar *nm_modem_ip_type_to_string (NMModemIPType ip_type); -G_END_DECLS - #endif /* __NETWORKMANAGER_MODEM_H__ */ diff --git a/src/devices/wwan/nm-wwan-factory.c b/src/devices/wwan/nm-wwan-factory.c index 805aea69..507935fc 100644 --- a/src/devices/wwan/nm-wwan-factory.c +++ b/src/devices/wwan/nm-wwan-factory.c @@ -90,7 +90,7 @@ modem_added_cb (NMModemManager *manager, NM_DEVICE_FACTORY_DECLARE_TYPES ( - NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_WWAN_ETHERNET) + NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_WWAN_NET) NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_GSM_SETTING_NAME, NM_SETTING_CDMA_SETTING_NAME) ) @@ -102,7 +102,7 @@ create_device (NMDeviceFactory *factory, gboolean *out_ignore) { g_return_val_if_fail (plink, NULL); - g_return_val_if_fail (plink->type == NM_LINK_TYPE_WWAN_ETHERNET, NULL); + g_return_val_if_fail (plink->type == NM_LINK_TYPE_WWAN_NET, NULL); *out_ignore = TRUE; return NULL; } diff --git a/src/devices/wwan/nm-wwan-factory.h b/src/devices/wwan/nm-wwan-factory.h index 78031e60..61bdcb1e 100644 --- a/src/devices/wwan/nm-wwan-factory.h +++ b/src/devices/wwan/nm-wwan-factory.h @@ -21,8 +21,6 @@ #ifndef __NETWORKMANAGER_WWAN_FACTORY_H__ #define __NETWORKMANAGER_WWAN_FACTORY_H__ -#include "nm-default.h" - #define NM_TYPE_WWAN_FACTORY (nm_wwan_factory_get_type ()) #define NM_WWAN_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_WWAN_FACTORY, NMWwanFactory)) |