From e32839838e5ea74ba490cf912e20939afa0e4f40 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Sun, 12 Mar 2017 15:54:02 +0100 Subject: [PATCH] udev: drop libgudev in favor of libudev libgudev is just a wrapper around libudev. We can use libudev directly and drop the dependency for libgudev. --- .travis.yml | 2 +- Makefile.am | 59 +++-- configure.ac | 2 +- contrib/fedora/REQUIRED_PACKAGES | 1 - contrib/fedora/nm-live-vm/build.sh | 2 +- contrib/fedora/rpm/NetworkManager.spec | 1 - libnm-glib/nm-device.c | 69 +++-- libnm/nm-device.c | 76 +++--- shared/nm-utils/nm-udev-utils.c | 240 ++++++++++++++++++ shared/nm-utils/nm-udev-utils.h | 46 ++++ src/devices/adsl/nm-atm-manager.c | 81 +++--- src/devices/nm-device-ethernet.c | 19 +- src/nm-rfkill-manager.c | 133 +++++----- src/platform/nm-linux-platform.c | 139 +++++----- src/platform/nm-platform-utils.c | 19 +- src/platform/nm-platform-utils.h | 6 +- src/platform/nm-platform.c | 2 +- src/platform/nm-platform.h | 6 +- src/platform/nmp-object.c | 39 +-- src/platform/nmp-object.h | 24 +- src/platform/tests/test-nmp-object.c | 42 ++- .../plugins/ifupdown/nms-ifupdown-plugin.c | 90 ++++--- 22 files changed, 724 insertions(+), 374 deletions(-) create mode 100644 shared/nm-utils/nm-udev-utils.c create mode 100644 shared/nm-utils/nm-udev-utils.h diff --git a/.travis.yml b/.travis.yml index 798db66971..29cb445a9f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ before_install: - sudo apt-get update - sudo apt-get install autoconf libtool pkg-config intltool libdbus-glib-1-dev libdbus-1-dev libiw-dev libglib2.0-dev libnl-3-dev libnl-route-3-dev libnl-genl-3-dev ppp-dev libpolkit-gobject-1-dev libgnutls28-dev libgcrypt11-dev - uuid-dev libudev-dev libgudev-1.0-dev libgirepository1.0-dev gobject-introspection libsoup2.4-dev gtk-doc-tools + uuid-dev libudev-dev libgirepository1.0-dev gobject-introspection libsoup2.4-dev gtk-doc-tools libglib2.0-doc libreadline-dev libnewt-dev libnss3-dev iptables make python-software-properties python-gi python-dbus dbus dbus-x11 libjansson4 libjansson-dev - sudo dbus-uuidgen --ensure diff --git a/Makefile.am b/Makefile.am index 3561a02993..f0e6a3664c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -414,6 +414,7 @@ libnm_core_lib_h_pub_mkenums = \ libnm-core/nm-core-enum-types.h libnm_core_lib_h_priv = \ shared/nm-utils/nm-shared-utils.h \ + shared/nm-utils/nm-udev-utils.h \ shared/nm-setting-metadata.h \ libnm-core/crypto.h \ libnm-core/nm-connection-private.h \ @@ -426,6 +427,7 @@ libnm_core_lib_h_priv = \ libnm-core/nm-utils-private.h libnm_core_lib_c_real = \ shared/nm-utils/nm-shared-utils.c \ + shared/nm-utils/nm-udev-utils.c \ shared/nm-setting-metadata.c \ libnm-core/crypto.c \ libnm-core/nm-connection.c \ @@ -491,7 +493,8 @@ dflt_cppflags_libnm_core = \ -I$(srcdir)/libnm-core \ -I$(builddir)/libnm-core \ $(CODE_COVERAGE_CFLAGS) \ - $(GLIB_CFLAGS) + $(GLIB_CFLAGS) \ + $(LIBUDEV_CFLAGS) if WITH_JANSSON dflt_cppflags_libnm_core += $(JANSSON_CFLAGS) @@ -556,7 +559,8 @@ nodist_libnm_core_libnm_core_la_SOURCES = \ libnm_core_libnm_core_la_LIBADD = \ $(GLIB_LIBS) \ - $(UUID_LIBS) + $(UUID_LIBS) \ + $(LIBUDEV_LIBS) if WITH_JANSSON libnm_core_libnm_core_la_LIBADD += $(JANSSON_LIBS) @@ -810,7 +814,7 @@ libnm_libnm_la_CPPFLAGS = \ $(dflt_cppflags_libnm_core) \ -I$(srcdir)/libnm \ -I$(builddir)/libnm \ - $(GUDEV_CFLAGS) \ + $(LIBUDEV_CFLAGS) \ -DG_LOG_DOMAIN=\""libnm"\" \ -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_LIB \ -DNMRUNDIR=\"$(nmrundir)\" @@ -834,7 +838,7 @@ libnm_libnm_la_LIBADD = \ $(DL_LIBS) \ $(GLIB_LIBS) \ $(UUID_LIBS) \ - $(GUDEV_LIBS) + $(LIBUDEV_LIBS) libnm_libnm_la_LDFLAGS = \ -Wl,--version-script="$(srcdir)/libnm/libnm.ver" \ @@ -859,7 +863,7 @@ EXTRA_DIST += \ if HAVE_INTROSPECTION libnm/NM-1.0.gir: libnm/libnm.la libnm_NM_1_0_gir_INCLUDES = Gio-2.0 -libnm_NM_1_0_gir_PACKAGES = gio-2.0 gudev-1.0 +libnm_NM_1_0_gir_PACKAGES = gio-2.0 libnm_NM_1_0_gir_EXPORT_PACKAGES = libnm libnm_NM_1_0_gir_CFLAGS = $(libnm_libnm_la_CPPFLAGS) libnm_NM_1_0_gir_LIBS = libnm/libnm.la @@ -1031,7 +1035,7 @@ src_cppflags = \ -DDHCLIENT_PATH=\"$(DHCLIENT_PATH)\" \ -DDHCPCD_PATH=\"$(DHCPCD_PATH)\" \ \ - $(GUDEV_CFLAGS) \ + $(LIBUDEV_CFLAGS) \ $(LIBNL_CFLAGS) \ $(LIBNDP_CFLAGS) \ $(LIBPSL_CFLAGS) \ @@ -1288,6 +1292,7 @@ src_libNetworkManagerBase_la_LIBADD = \ introspection/libnmdbus.la \ $(GLIB_LIBS) \ $(SYSTEMD_JOURNAL_LIBS) \ + $(LIBUDEV_LIBS) \ $(NULL) ############################################################################### @@ -1463,7 +1468,7 @@ src_libNetworkManager_la_LIBADD = \ src/libNetworkManagerBase.la \ src/libsystemd-nm.la \ $(GLIB_LIBS) \ - $(GUDEV_LIBS) \ + $(LIBUDEV_LIBS) \ $(LIBNL_LIBS) \ $(SYSTEMD_LOGIN_LIBS) \ $(LIBNDP_LIBS) \ @@ -1502,7 +1507,7 @@ src_libNetworkManagerTest_la_LIBADD = \ src/libNetworkManager.la \ $(CODE_COVERAGE_LDFLAGS) \ $(GLIB_LIBS) \ - $(GUDEV_LIBS) \ + $(LIBUDEV_LIBS) \ $(LIBNL_LIBS) ############################################################################### @@ -1538,7 +1543,7 @@ src_nm_iface_helper_LDADD = \ src/libNetworkManagerBase.la \ src/libsystemd-nm.la \ $(GLIB_LIBS) \ - $(GUDEV_LIBS) \ + $(LIBUDEV_LIBS) \ $(LIBNL_LIBS) \ $(LIBNDP_LIBS) \ $(DL_LIBS) \ @@ -2131,7 +2136,7 @@ src_settings_plugins_ifupdown_cppflags = \ -DG_LOG_DOMAIN=\""NetworkManager"\" \ -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_INSIDE_DAEMON \ $(GLIB_CFLAGS) \ - $(GUDEV_CFLAGS) \ + $(LIBUDEV_CFLAGS) \ -DSYSCONFDIR=\"$(sysconfdir)\" @@ -2143,6 +2148,8 @@ src_settings_plugins_ifupdown_libnms_ifupdown_core_la_SOURCES = \ src_settings_plugins_ifupdown_libnms_ifupdown_core_la_CPPFLAGS = $(src_settings_plugins_ifupdown_cppflags) +src_settings_plugins_ifupdown_libnms_ifupdown_core_la_LIBADD = \ + $(LIBUDEV_LIBS) src_settings_plugins_ifupdown_libnm_settings_plugin_ifupdown_la_SOURCES = \ src/settings/plugins/ifupdown/nms-ifupdown-connection.c \ @@ -2157,7 +2164,8 @@ src_settings_plugins_ifupdown_libnm_settings_plugin_ifupdown_la_LDFLAGS = \ -Wl,--version-script="$(srcdir)/linker-script-settings.ver" src_settings_plugins_ifupdown_libnm_settings_plugin_ifupdown_la_LIBADD = \ - src/settings/plugins/ifupdown/libnms-ifupdown-core.la + src/settings/plugins/ifupdown/libnms-ifupdown-core.la \ + $(LIBUDEV_LIBS) check-local-symbols-settings-ifupdown: src/settings/plugins/ifupdown/libnm-settings-plugin-ifupdown.la $(call check_so_symbols,$(builddir)/src/settings/plugins/ifupdown/.libs/libnm-settings-plugin-ifupdown.so) @@ -2325,7 +2333,7 @@ src_devices_adsl_libnm_device_plugin_adsl_la_CPPFLAGS = \ -DG_LOG_DOMAIN=\""NetworkManager"\" \ -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_INSIDE_DAEMON \ $(GLIB_CFLAGS) \ - $(GUDEV_CFLAGS) + $(LIBUDEV_CFLAGS) src_devices_adsl_libnm_device_plugin_adsl_la_LDFLAGS = \ -module -avoid-version \ @@ -2333,7 +2341,7 @@ src_devices_adsl_libnm_device_plugin_adsl_la_LDFLAGS = \ src_devices_adsl_libnm_device_plugin_adsl_la_LIBADD = \ introspection/libnmdbus.la \ - $(GUDEV_LIBS) + $(LIBUDEV_LIBS) check-local-devices-adsl: src/devices/adsl/libnm-device-plugin-adsl.la $(srcdir)/tools/check-exports.sh $(builddir)/src/devices/adsl/.libs/libnm-device-plugin-adsl.so "$(srcdir)/linker-script-devices.ver" @@ -2464,8 +2472,7 @@ src_devices_bluetooth_libnm_device_plugin_bluetooth_la_LDFLAGS = \ src_devices_bluetooth_libnm_device_plugin_bluetooth_la_LIBADD = \ introspection/libnmdbus.la \ src/devices/wwan/libnm-wwan.la \ - $(GLIB_LIBS) \ - $(GUDEV_LIBS) + $(GLIB_LIBS) if WITH_BLUEZ5_DUN src_devices_bluetooth_libnm_device_plugin_bluetooth_la_CPPFLAGS += $(BLUEZ5_CFLAGS) @@ -2521,8 +2528,7 @@ src_devices_wifi_libnm_device_plugin_wifi_la_LDFLAGS = \ src_devices_wifi_libnm_device_plugin_wifi_la_LIBADD = \ introspection/libnmdbus.la \ - $(GLIB_LIBS) \ - $(GUDEV_LIBS) + $(GLIB_LIBS) check-local-devices-wifi: src/devices/wifi/libnm-device-plugin-wifi.la $(srcdir)/tools/check-exports.sh $(builddir)/src/devices/wifi/.libs/libnm-device-plugin-wifi.so "$(srcdir)/linker-script-devices.ver" @@ -2588,8 +2594,7 @@ src_devices_team_libnm_device_plugin_team_la_LIBADD = \ introspection/libnmdbus.la \ $(LIBTEAMDCTL_LIBS) \ $(JANSSON_LIBS) \ - $(GLIB_LIBS) \ - $(GUDEV_LIBS) + $(GLIB_LIBS) check-local-devices-team: src/devices/team/libnm-device-plugin-team.la $(srcdir)/tools/check-exports.sh $(builddir)/src/devices/team/.libs/libnm-device-plugin-team.so "$(srcdir)/linker-script-devices.ver" @@ -2622,7 +2627,7 @@ src_platform_tests_ldflags = \ src_platform_tests_libadd = \ src/libNetworkManagerTest.la \ $(GLIB_LIBS) \ - $(GUDEV_LIBS) \ + $(LIBUDEV_LIBS) \ $(LIBNL_LIBS) check_programs_norun += \ @@ -2843,7 +2848,7 @@ src_tests_test_route_manager_ldflags = \ src_tests_test_route_manager_ldadd = \ src/libNetworkManagerTest.la \ $(GLIB_LIBS) \ - $(GUDEV_LIBS) \ + $(LIBUDEV_LIBS) \ $(LIBNL_LIBS) src_tests_test_route_manager_fake_SOURCES = src/tests/test-route-manager.c @@ -3283,7 +3288,6 @@ clients_tui_nmtui_CPPFLAGS = \ -I$(srcdir)/clients/common \ $(GLIB_CFLAGS) \ $(NEWT_CFLAGS) \ - $(GUDEV_CFLAGS) \ -DG_LOG_DOMAIN=\""nmtui"\" \ -DLOCALEDIR=\""$(localedir)"\" \ $(NULL) @@ -3294,9 +3298,8 @@ clients_tui_nmtui_LDFLAGS = \ clients_tui_nmtui_LDADD = \ libnm/libnm.la \ clients/tui/newt/libnmt-newt.a \ - $(GUDEV_LIBS) \ - $(NEWT_LIBS) \ $(GLIB_LIBS) \ + $(NEWT_LIBS) \ $(NULL) nmtui_links = nmtui-edit nmtui-connect nmtui-hostname @@ -3743,6 +3746,7 @@ libnm_glib_lib_h_pub_real = \ libnm_glib_lib_h_pub_mkenums = \ libnm-glib/nm-glib-enum-types.h libnm_glib_lib_h_priv = \ + shared/nm-utils/nm-udev-utils.h \ libnm-glib/nm-object-private.h \ libnm-glib/nm-device-private.h \ libnm-glib/nm-types-private.h \ @@ -3769,6 +3773,7 @@ nodist_libnm_glib_libnmvpn_HEADERS = \ $(libnm_glib_vpn_h_mkenums) libnm_glib_lib_c_real = \ + shared/nm-utils/nm-udev-utils.c \ libnm-glib/nm-object.c \ libnm-glib/nm-dbus-helpers.c \ libnm-glib/nm-client.c \ @@ -3813,7 +3818,7 @@ nodist_libnm_glib_libnm_glib_la_SOURCES = \ libnm_glib_libnm_glib_la_CPPFLAGS = \ $(libnm_glib_cppflags) \ - $(GUDEV_CFLAGS) \ + $(LIBUDEV_CFLAGS) \ -DNMRUNDIR=\"$(nmrundir)\" libnm_glib_libnm_glib_la_LDFLAGS = \ @@ -3825,7 +3830,7 @@ libnm_glib_libnm_glib_la_LIBADD = \ libnm-glib/libdeprecated-nm-glib.la \ $(GLIB_LIBS) \ $(DBUS_LIBS) \ - $(GUDEV_LIBS) + $(LIBUDEV_LIBS) GLIB_GENERATED += \ @@ -3905,7 +3910,7 @@ EXTRA_DIST += \ if HAVE_INTROSPECTION libnm-glib/NMClient-1.0.gir: libnm-glib/libnm-glib.la $(builddir)/libnm-util/NetworkManager-1.0.gir libnm_glib_NMClient_1_0_gir_INCLUDES = Gio-2.0 DBusGLib-1.0 -libnm_glib_NMClient_1_0_gir_PACKAGES = gio-2.0 dbus-glib-1 gudev-1.0 +libnm_glib_NMClient_1_0_gir_PACKAGES = gio-2.0 dbus-glib-1 libnm_glib_NMClient_1_0_gir_EXPORT_PACKAGES = libnm-glib libnm-glib-vpn libnm_glib_NMClient_1_0_gir_CFLAGS = $(libnm_glib_cppflags) libnm_glib_NMClient_1_0_gir_LIBS = \ diff --git a/configure.ac b/configure.ac index ecfce546b9..4562fcc973 100644 --- a/configure.ac +++ b/configure.ac @@ -310,7 +310,7 @@ Configure with --without-libnm-glib if you do not need the legacy libraries])]) fi AM_CONDITIONAL(WITH_LEGACY_LIBRARIES, test "$with_libnm_glib" != "no") -PKG_CHECK_MODULES(GUDEV, gudev-1.0 >= 165) +PKG_CHECK_MODULES([LIBUDEV], [libudev >= 175]) GOBJECT_INTROSPECTION_CHECK([0.9.6]) diff --git a/contrib/fedora/REQUIRED_PACKAGES b/contrib/fedora/REQUIRED_PACKAGES index ce834a7f0f..f1bcfd457d 100644 --- a/contrib/fedora/REQUIRED_PACKAGES +++ b/contrib/fedora/REQUIRED_PACKAGES @@ -21,7 +21,6 @@ yum install \ gettext-devel \ dbus-devel \ dbus-glib-devel \ - libgudev1-devel \ libuuid-devel \ nss-devel \ ppp-devel \ diff --git a/contrib/fedora/nm-live-vm/build.sh b/contrib/fedora/nm-live-vm/build.sh index d63a0cb392..3033fbc321 100755 --- a/contrib/fedora/nm-live-vm/build.sh +++ b/contrib/fedora/nm-live-vm/build.sh @@ -33,7 +33,7 @@ ARCH=i386 ROOT="${ROOT:-"fedora-20-$ARCH"}" TREE="/var/lib/mock/$ROOT/root" PACKAGES="kernel passwd git autoconf automake libtool intltool gtk-doc libnl3-devel - dbus-glib-devel libgudev1-devel libuuid-devel nss-devel ppp-devel newt-devel libndp-devel + dbus-glib-devel libuuid-devel nss-devel ppp-devel newt-devel libndp-devel readline-devel gobject-introspection-devel pygobject3 diff --git a/contrib/fedora/rpm/NetworkManager.spec b/contrib/fedora/rpm/NetworkManager.spec index d4c75ac8ce..e6140f314e 100644 --- a/contrib/fedora/rpm/NetworkManager.spec +++ b/contrib/fedora/rpm/NetworkManager.spec @@ -129,7 +129,6 @@ BuildRequires: gtk-doc %endif BuildRequires: libudev-devel BuildRequires: libuuid-devel -BuildRequires: libgudev1-devel >= 143 BuildRequires: vala-tools BuildRequires: iptables BuildRequires: libxslt diff --git a/libnm-glib/nm-device.c b/libnm-glib/nm-device.c index 626c84a97d..81af5b6cff 100644 --- a/libnm-glib/nm-device.c +++ b/libnm-glib/nm-device.c @@ -22,9 +22,11 @@ #include "nm-default.h" #include -#include +#include #include "NetworkManager.h" + +#include "nm-utils/nm-udev-utils.h" #include "nm-device-ethernet.h" #include "nm-device-adsl.h" #include "nm-device-wifi.h" @@ -92,7 +94,7 @@ typedef struct { NMActiveConnection *active_connection; GPtrArray *available_connections; - GUdevClient *client; + NMUdevClient *udev_client; char *product, *short_product; char *vendor, *short_vendor; char *description, *bus_name; @@ -374,9 +376,10 @@ dispose (GObject *object) g_clear_object (&priv->dhcp4_config); g_clear_object (&priv->ip6_config); g_clear_object (&priv->dhcp6_config); - g_clear_object (&priv->client); g_clear_object (&priv->active_connection); + priv->udev_client = nm_udev_client_unref (priv->udev_client); + if (priv->available_connections) { int i; @@ -1501,13 +1504,13 @@ nm_device_get_available_connections (NMDevice *device) } static char * -get_decoded_property (GUdevDevice *device, const char *property) +get_decoded_property (struct udev_device *device, const char *property) { const char *orig, *p; char *unescaped, *n; guint len; - p = orig = g_udev_device_get_property (device, property); + p = orig = udev_device_get_property_value (device, property); if (!orig) return NULL; @@ -1530,13 +1533,13 @@ get_decoded_property (GUdevDevice *device, const char *property) static gboolean ensure_udev_client (NMDevice *device) { - static const char *const subsys[3] = { "net", "tty", NULL }; NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); - if (!priv->client) - priv->client = g_udev_client_new (subsys); - - return priv->client != NULL; + if (!priv->udev_client) { + priv->udev_client = nm_udev_client_new ((const char *[]) { "net", "tty", NULL }, + NULL, NULL); + } + return !!priv->udev_client; } static char * @@ -1545,7 +1548,7 @@ _get_udev_property (NMDevice *device, const char *db_prop) /* ID_XXX_FROM_DATABASE */ { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); - GUdevDevice *udev_device = NULL, *tmpdev, *olddev; + struct udev_device *udev_device, *tmpdev; const char *ifname; guint32 count = 0; char *enc_value = NULL, *db_value = NULL; @@ -1557,39 +1560,25 @@ _get_udev_property (NMDevice *device, if (!ifname) return NULL; - udev_device = g_udev_client_query_by_subsystem_and_name (priv->client, "net", ifname); - if (!udev_device) - udev_device = g_udev_client_query_by_subsystem_and_name (priv->client, "tty", ifname); - if (!udev_device) - return NULL; - + udev_device = udev_device_new_from_subsystem_sysname (nm_udev_client_get_udev (priv->udev_client), "net", ifname); + if (!udev_device) { + udev_device = udev_device_new_from_subsystem_sysname (nm_udev_client_get_udev (priv->udev_client), "tty", ifname); + if (!udev_device) + return NULL; + } /* Walk up the chain of the device and its parents a few steps to grab * vendor and device ID information off it. */ - - /* Ref the device again because we have to unref it each iteration, - * as g_udev_device_get_parent() returns a ref-ed object. - */ - tmpdev = g_object_ref (udev_device); + tmpdev = udev_device; while ((count++ < 3) && tmpdev && !enc_value) { if (!enc_value) enc_value = get_decoded_property (tmpdev, enc_prop); if (!db_value) - db_value = g_strdup (g_udev_device_get_property (tmpdev, db_prop)); + db_value = g_strdup (udev_device_get_property_value (tmpdev, db_prop)); - olddev = tmpdev; - tmpdev = g_udev_device_get_parent (tmpdev); - g_object_unref (olddev); + tmpdev = udev_device_get_parent (tmpdev); } - - /* Unref the last device if we found what we needed before running out - * of parents. - */ - if (tmpdev) - g_object_unref (tmpdev); - - /* Balance the initial g_udev_client_query_by_subsystem_and_name() */ - g_object_unref (udev_device); + udev_device_unref (udev_device); /* Prefer the encoded value which comes directly from the device * over the hwdata database value. @@ -1930,7 +1919,7 @@ static const char * get_bus_name (NMDevice *device) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); - GUdevDevice *udevice; + struct udev_device *udevice; const char *ifname, *bus; if (priv->bus_name) @@ -1943,13 +1932,13 @@ get_bus_name (NMDevice *device) if (!ifname) return NULL; - udevice = g_udev_client_query_by_subsystem_and_name (priv->client, "net", ifname); + udevice = udev_device_new_from_subsystem_sysname (nm_udev_client_get_udev (priv->udev_client), "net", ifname); if (!udevice) - udevice = g_udev_client_query_by_subsystem_and_name (priv->client, "tty", ifname); + udevice = udev_device_new_from_subsystem_sysname (nm_udev_client_get_udev (priv->udev_client), "tty", ifname); if (!udevice) return NULL; - bus = g_udev_device_get_property (udevice, "ID_BUS"); + bus = udev_device_get_property_value (udevice, "ID_BUS"); if (!g_strcmp0 (bus, "pci")) priv->bus_name = g_strdup (_("PCI")); else if (!g_strcmp0 (bus, "usb")) @@ -1960,7 +1949,7 @@ get_bus_name (NMDevice *device) */ priv->bus_name = g_strdup (""); } - g_object_unref (udevice); + udev_device_unref (udevice); out: if (*priv->bus_name) diff --git a/libnm/nm-device.c b/libnm/nm-device.c index 9420dfb132..3629a8471b 100644 --- a/libnm/nm-device.c +++ b/libnm/nm-device.c @@ -24,7 +24,7 @@ #include "nm-device.h" #include -#include +#include #include "nm-dbus-interface.h" #include "nm-active-connection.h" @@ -40,6 +40,7 @@ #include "nm-dbus-helpers.h" #include "nm-device-tun.h" #include "nm-setting-connection.h" +#include "nm-utils/nm-udev-utils.h" #include "introspection/org.freedesktop.NetworkManager.Device.h" @@ -79,7 +80,7 @@ typedef struct { NMActiveConnection *active_connection; GPtrArray *available_connections; - GUdevClient *client; + NMUdevClient *udev_client; char *product, *short_product; char *vendor, *short_vendor; char *description, *bus_name; @@ -292,9 +293,10 @@ dispose (GObject *object) g_clear_object (&priv->dhcp4_config); g_clear_object (&priv->ip6_config); g_clear_object (&priv->dhcp6_config); - g_clear_object (&priv->client); g_clear_object (&priv->active_connection); + priv->udev_client = nm_udev_client_unref (priv->udev_client); + g_clear_pointer (&priv->available_connections, g_ptr_array_unref); g_clear_pointer (&priv->lldp_neighbors, g_ptr_array_unref); @@ -1304,13 +1306,13 @@ hex2byte (const char *hex) } static char * -get_decoded_property (GUdevDevice *device, const char *property) +get_decoded_property (struct udev_device *device, const char *property) { const char *orig, *p; char *unescaped, *n; guint len; - p = orig = g_udev_device_get_property (device, property); + p = orig = udev_device_get_property_value (device, property); if (!orig) return NULL; @@ -1333,13 +1335,13 @@ get_decoded_property (GUdevDevice *device, const char *property) static gboolean ensure_udev_client (NMDevice *device) { - static const char *const subsys[3] = { "net", "tty", NULL }; NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); - if (!priv->client) - priv->client = g_udev_client_new (subsys); - - return priv->client != NULL; + if (!priv->udev_client) { + priv->udev_client = nm_udev_client_new ((const char *[]) { "net", "tty", NULL }, + NULL, NULL); + } + return !!priv->udev_client; } static char * @@ -1348,7 +1350,7 @@ _get_udev_property (NMDevice *device, const char *db_prop) /* ID_XXX_FROM_DATABASE */ { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); - GUdevDevice *udev_device = NULL, *tmpdev, *olddev; + struct udev_device *udev_device, *tmpdev; const char *ifname; guint32 count = 0; char *enc_value = NULL, *db_value = NULL; @@ -1360,39 +1362,25 @@ _get_udev_property (NMDevice *device, if (!ifname) return NULL; - udev_device = g_udev_client_query_by_subsystem_and_name (priv->client, "net", ifname); - if (!udev_device) - udev_device = g_udev_client_query_by_subsystem_and_name (priv->client, "tty", ifname); - if (!udev_device) - return NULL; - + udev_device = udev_device_new_from_subsystem_sysname (nm_udev_client_get_udev (priv->udev_client), "net", ifname); + if (!udev_device) { + udev_device = udev_device_new_from_subsystem_sysname (nm_udev_client_get_udev (priv->udev_client), "tty", ifname); + if (!udev_device) + return NULL; + } /* Walk up the chain of the device and its parents a few steps to grab * vendor and device ID information off it. */ - - /* Ref the device again because we have to unref it each iteration, - * as g_udev_device_get_parent() returns a ref-ed object. - */ - tmpdev = g_object_ref (udev_device); + tmpdev = udev_device; while ((count++ < 3) && tmpdev && !enc_value) { if (!enc_value) enc_value = get_decoded_property (tmpdev, enc_prop); if (!db_value) - db_value = g_strdup (g_udev_device_get_property (tmpdev, db_prop)); + db_value = g_strdup (udev_device_get_property_value (tmpdev, db_prop)); - olddev = tmpdev; - tmpdev = g_udev_device_get_parent (tmpdev); - g_object_unref (olddev); + tmpdev = udev_device_get_parent (tmpdev); } - - /* Unref the last device if we found what we needed before running out - * of parents. - */ - if (tmpdev) - g_object_unref (tmpdev); - - /* Balance the initial g_udev_client_query_by_subsystem_and_name() */ - g_object_unref (udev_device); + udev_device_unref (udev_device); /* Prefer the encoded value which comes directly from the device * over the hwdata database value. @@ -1740,7 +1728,7 @@ static const char * get_bus_name (NMDevice *device) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); - GUdevDevice *udevice; + struct udev_device *udevice; const char *ifname, *bus; if (priv->bus_name) @@ -1753,13 +1741,13 @@ get_bus_name (NMDevice *device) if (!ifname) return NULL; - udevice = g_udev_client_query_by_subsystem_and_name (priv->client, "net", ifname); - if (!udevice) - udevice = g_udev_client_query_by_subsystem_and_name (priv->client, "tty", ifname); - if (!udevice) - return NULL; - - bus = g_udev_device_get_property (udevice, "ID_BUS"); + udevice = udev_device_new_from_subsystem_sysname (nm_udev_client_get_udev (priv->udev_client), "net", ifname); + if (!udevice) { + udevice = udev_device_new_from_subsystem_sysname (nm_udev_client_get_udev (priv->udev_client), "tty", ifname); + if (!udevice) + return NULL; + } + bus = udev_device_get_property_value (udevice, "ID_BUS"); if (!g_strcmp0 (bus, "pci")) priv->bus_name = g_strdup (_("PCI")); else if (!g_strcmp0 (bus, "usb")) @@ -1770,7 +1758,7 @@ get_bus_name (NMDevice *device) */ priv->bus_name = g_strdup (""); } - g_object_unref (udevice); + udev_device_unref (udevice); out: if (*priv->bus_name) diff --git a/shared/nm-utils/nm-udev-utils.c b/shared/nm-utils/nm-udev-utils.c new file mode 100644 index 0000000000..22d98037c7 --- /dev/null +++ b/shared/nm-utils/nm-udev-utils.c @@ -0,0 +1,240 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* nm-udev-utils.c - udev utils functions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2017 Red Hat, Inc. + */ + +#include "nm-default.h" + +#include "nm-udev-utils.h" + +#include + +struct _NMPUdevClient { + char **subsystems; + GSource *watch_source; + struct udev *udev; + struct udev_monitor *monitor; + NMUdevClientEvent event_handler; + gpointer event_user_data; +}; + +/*****************************************************************************/ + +gboolean +nm_udev_utils_property_as_boolean (const char *uproperty) +{ + /* taken from g_udev_device_get_property_as_boolean() */ + + if (uproperty) { + if ( strcmp (uproperty, "1") == 0 + || g_ascii_strcasecmp (uproperty, "true") == 0) + return TRUE; + } + return FALSE; +} + +/*****************************************************************************/ + +static void +_subsystem_split (const char *subsystem_full, + const char **out_subsystem, + const char **out_devtype, + char **to_free) +{ + char *tmp, *s; + + nm_assert (subsystem_full); + nm_assert (out_subsystem); + nm_assert (out_devtype); + nm_assert (to_free); + + s = strstr (subsystem_full, "/"); + if (s) { + tmp = g_strdup (subsystem_full); + s = &tmp[s - subsystem_full]; + *s = '\0'; + *out_subsystem = tmp; + *out_devtype = &s[1]; + *to_free = tmp; + } else { + *out_subsystem = subsystem_full; + *out_devtype = NULL; + *to_free = NULL; + } +} + +static struct udev_enumerate * +nm_udev_utils_enumerate (struct udev *uclient, + const char *const*subsystems) +{ + struct udev_enumerate *enumerate; + guint n; + + enumerate = udev_enumerate_new (uclient); + + if (subsystems) { + for (n = 0; subsystems[n]; n++) { + const char *subsystem; + const char *devtype; + gs_free char *to_free; + + _subsystem_split (subsystems[n], &subsystem, &devtype, &to_free); + + udev_enumerate_add_match_subsystem (enumerate, subsystem); + + if (devtype != NULL) + udev_enumerate_add_match_property (enumerate, "DEVTYPE", devtype); + } + } + + return enumerate; +} + +struct udev * +nm_udev_client_get_udev (NMUdevClient *self) +{ + g_return_val_if_fail (self, NULL); + + return self->udev; +} + +struct udev_enumerate * +nm_udev_client_enumerate_new (NMUdevClient *self) +{ + g_return_val_if_fail (self, NULL); + + return nm_udev_utils_enumerate (self->udev, (const char *const*) self->subsystems); +} + +/*****************************************************************************/ + +static gboolean +monitor_event (GIOChannel *source, + GIOCondition condition, + gpointer user_data) +{ + NMUdevClient *self = user_data; + struct udev_device *udevice; + + if (!self->monitor) + goto out; + + if (!self->event_handler) + goto out; + + udevice = udev_monitor_receive_device (self->monitor); + if (udevice == NULL) + goto out; + + self->event_handler (self, + udevice, + self->event_user_data); + udev_device_unref (udevice); + +out: + return TRUE; +} + +/** + * nm_udev_client_new: + * @subsystems: the subsystems + * @event_handler: callback for events + * @event_user_data: user-data for @event_handler + * + * Basically, it is g_udev_client_new(), and most notably + * g_udev_client_constructed(). + * + * Returns: a new NMUdevClient instance. + */ +NMUdevClient * +nm_udev_client_new (const char *const*subsystems, + NMUdevClientEvent event_handler, + gpointer event_user_data) +{ + NMUdevClient *self; + GIOChannel *channel; + guint n; + + self = g_slice_new0 (NMUdevClient); + + self->event_handler = event_handler; + self->event_user_data = event_user_data; + self->subsystems = subsystems && subsystems[0] ? g_strdupv ((char **) subsystems) : NULL; + + self->udev = udev_new (); + if (!self->udev) + goto fail; + + /* connect to event source */ + self->monitor = udev_monitor_new_from_netlink (self->udev, "udev"); + if (!self->monitor) + goto fail; + + if (self->subsystems) { + /* install subsystem filters to only wake up for certain events */ + for (n = 0; self->subsystems[n]; n++) { + if (self->monitor) { + gs_free char *to_free; + const char *subsystem; + const char *devtype; + + _subsystem_split (self->subsystems[n], &subsystem, &devtype, &to_free); + udev_monitor_filter_add_match_subsystem_devtype (self->monitor, subsystem, devtype); + } + } + + /* listen to events, and buffer them */ + if (self->monitor) { + udev_monitor_enable_receiving (self->monitor); + channel = g_io_channel_unix_new (udev_monitor_get_fd (self->monitor)); + self->watch_source = g_io_create_watch (channel, G_IO_IN); + g_io_channel_unref (channel); + g_source_set_callback (self->watch_source, (GSourceFunc) monitor_event, self, NULL); + g_source_attach (self->watch_source, g_main_context_get_thread_default ()); + g_source_unref (self->watch_source); + } + } + + return self; + +fail: + return nm_udev_client_unref (self); +} + +NMUdevClient * +nm_udev_client_unref (NMUdevClient *self) +{ + if (!self) + return NULL; + + if (self->watch_source) { + g_source_destroy (self->watch_source); + self->watch_source = NULL; + } + + udev_monitor_unref (self->monitor); + self->monitor = NULL; + udev_unref (self->udev); + self->udev = NULL; + + g_strfreev (self->subsystems); + + g_slice_free (NMUdevClient, self); + + return NULL; +} diff --git a/shared/nm-utils/nm-udev-utils.h b/shared/nm-utils/nm-udev-utils.h new file mode 100644 index 0000000000..5f6e383f15 --- /dev/null +++ b/shared/nm-utils/nm-udev-utils.h @@ -0,0 +1,46 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* nm-udev-utils.h - udev utils functions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2017 Red Hat, Inc. + */ + +#ifndef __NM_UDEV_UTILS_H__ +#define __NM_UDEV_UTILS_H__ + +struct udev; +struct udev_device; +struct udev_enumerate; + +gboolean nm_udev_utils_property_as_boolean (const char *uproperty); + +typedef struct _NMPUdevClient NMUdevClient; + +typedef void (*NMUdevClientEvent) (NMUdevClient *udev_client, + struct udev_device *udevice, + gpointer event_user_data); + +NMUdevClient *nm_udev_client_new (const char *const*subsystems, + NMUdevClientEvent event_handler, + gpointer event_user_data); + +NMUdevClient *nm_udev_client_unref (NMUdevClient *self); + +struct udev *nm_udev_client_get_udev (NMUdevClient *self); + +struct udev_enumerate *nm_udev_client_enumerate_new (NMUdevClient *self); + +#endif /* __NM_UDEV_UTILS_H__ */ diff --git a/src/devices/adsl/nm-atm-manager.c b/src/devices/adsl/nm-atm-manager.c index b04e9fe717..32c4c386dc 100644 --- a/src/devices/adsl/nm-atm-manager.c +++ b/src/devices/adsl/nm-atm-manager.c @@ -21,13 +21,14 @@ #include "nm-default.h" #include -#include #include +#include #include "nm-setting-adsl.h" #include "nm-device-adsl.h" #include "devices/nm-device-factory.h" #include "platform/nm-platform.h" +#include "nm-utils/nm-udev-utils.h" /*****************************************************************************/ @@ -39,7 +40,7 @@ #define NM_ATM_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_ATM_MANAGER, NMAtmManagerClass)) typedef struct { - GUdevClient *client; + NMUdevClient *udev_client; GSList *devices; } NMAtmManagerPrivate; @@ -73,35 +74,34 @@ nm_device_factory_create (GError **error) /*****************************************************************************/ static gboolean -dev_get_attrs (GUdevDevice *udev_device, +dev_get_attrs (struct udev_device *udev_device, const char **out_path, char **out_driver) { - GUdevDevice *parent = NULL; + struct udev_device *parent = NULL; const char *driver, *path; g_return_val_if_fail (udev_device != NULL, FALSE); g_return_val_if_fail (out_path != NULL, FALSE); g_return_val_if_fail (out_driver != NULL, FALSE); - path = g_udev_device_get_sysfs_path (udev_device); + path = udev_device_get_syspath (udev_device); if (!path) { nm_log_warn (LOGD_PLATFORM, "couldn't determine device path; ignoring..."); return FALSE; } - driver = g_udev_device_get_driver (udev_device); + driver = udev_device_get_driver (udev_device); if (!driver) { /* Try the parent */ - parent = g_udev_device_get_parent (udev_device); + parent = udev_device_get_parent (udev_device); if (parent) - driver = g_udev_device_get_driver (parent); + driver = udev_device_get_driver (parent); } *out_path = path; *out_driver = g_strdup (driver); - g_clear_object (&parent); return TRUE; } @@ -115,7 +115,7 @@ device_destroyed (gpointer user_data, GObject *dead) } static void -adsl_add (NMAtmManager *self, GUdevDevice *udev_device) +adsl_add (NMAtmManager *self, struct udev_device *udev_device) { NMAtmManagerPrivate *priv = NM_ATM_MANAGER_GET_PRIVATE (self); const char *ifname, *sysfs_path = NULL; @@ -126,7 +126,7 @@ adsl_add (NMAtmManager *self, GUdevDevice *udev_device) g_return_if_fail (udev_device != NULL); - ifname = g_udev_device_get_name (udev_device); + ifname = udev_device_get_sysname (udev_device); if (!ifname) { nm_log_warn (LOGD_PLATFORM, "failed to get device's interface name"); return; @@ -165,10 +165,10 @@ adsl_add (NMAtmManager *self, GUdevDevice *udev_device) } static void -adsl_remove (NMAtmManager *self, GUdevDevice *udev_device) +adsl_remove (NMAtmManager *self, struct udev_device *udev_device) { NMAtmManagerPrivate *priv = NM_ATM_MANAGER_GET_PRIVATE (self); - const char *iface = g_udev_device_get_name (udev_device); + const char *iface = udev_device_get_sysname (udev_device); GSList *iter; nm_log_dbg (LOGD_PLATFORM, "(%s): removing ATM device", iface); @@ -194,42 +194,49 @@ start (NMDeviceFactory *factory) { NMAtmManager *self = NM_ATM_MANAGER (factory); NMAtmManagerPrivate *priv = NM_ATM_MANAGER_GET_PRIVATE (self); - GUdevEnumerator *enumerator; - GList *devices, *iter; + struct udev_enumerate *enumerate; + struct udev_list_entry *devices; - enumerator = g_udev_enumerator_new (priv->client); - g_udev_enumerator_add_match_subsystem (enumerator, "atm"); - g_udev_enumerator_add_match_is_initialized (enumerator); - devices = g_udev_enumerator_execute (enumerator); - for (iter = devices; iter; iter = g_list_next (iter)) { - adsl_add (self, G_UDEV_DEVICE (iter->data)); - g_object_unref (G_UDEV_DEVICE (iter->data)); + enumerate = nm_udev_client_enumerate_new (priv->udev_client); + udev_enumerate_add_match_is_initialized (enumerate); + udev_enumerate_scan_devices (enumerate); + devices = udev_enumerate_get_list_entry (enumerate); + for (; devices; devices = udev_list_entry_get_next (devices)) { + struct udev_device *udevice; + + udevice = udev_device_new_from_syspath (udev_enumerate_get_udev (enumerate), + udev_list_entry_get_name (devices)); + if (udevice) { + adsl_add (self, udevice); + udev_device_unref (udevice); + } } - g_list_free (devices); - g_object_unref (enumerator); + udev_enumerate_unref (enumerate); } static void -handle_uevent (GUdevClient *client, - const char *action, - GUdevDevice *device, +handle_uevent (NMUdevClient *client, + struct udev_device *device, gpointer user_data) { NMAtmManager *self = NM_ATM_MANAGER (user_data); const char *subsys; const char *ifindex; guint64 seqnum; + const char *action; + + action = udev_device_get_action (device); g_return_if_fail (action != NULL); /* A bit paranoid */ - subsys = g_udev_device_get_subsystem (device); + subsys = udev_device_get_subsystem (device); g_return_if_fail (!g_strcmp0 (subsys, "atm")); - ifindex = g_udev_device_get_property (device, "IFINDEX"); - seqnum = g_udev_device_get_seqnum (device); + ifindex = udev_device_get_property_value (device, "IFINDEX"); + seqnum = udev_device_get_seqnum (device); nm_log_dbg (LOGD_PLATFORM, "UDEV event: action '%s' subsys '%s' device '%s' (%s); seqnum=%" G_GUINT64_FORMAT, - action, subsys, g_udev_device_get_name (device), ifindex ? ifindex : "unknown", seqnum); + action, subsys, udev_device_get_sysname (device), ifindex ? ifindex : "unknown", seqnum); if (!strcmp (action, "add")) adsl_add (self, device); @@ -243,10 +250,9 @@ static void nm_atm_manager_init (NMAtmManager *self) { NMAtmManagerPrivate *priv = NM_ATM_MANAGER_GET_PRIVATE (self); - const char *subsys[] = { "atm", NULL }; - priv->client = g_udev_client_new (subsys); - g_signal_connect (priv->client, "uevent", G_CALLBACK (handle_uevent), self); + priv->udev_client = nm_udev_client_new ((const char *[]) {"atm", NULL }, + handle_uevent, self); } static void @@ -256,15 +262,12 @@ dispose (GObject *object) NMAtmManagerPrivate *priv = NM_ATM_MANAGER_GET_PRIVATE (self); GSList *iter; - if (priv->client) { - g_signal_handlers_disconnect_by_func (priv->client, handle_uevent, self); - g_clear_object (&priv->client); - } - for (iter = priv->devices; iter; iter = iter->next) g_object_weak_unref (G_OBJECT (iter->data), device_destroyed, self); g_clear_pointer (&priv->devices, g_slist_free); + priv->udev_client = nm_udev_client_unref (priv->udev_client); + G_OBJECT_CLASS (nm_atm_manager_parent_class)->dispose (object); } diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c index 9b39e2ad11..371738517a 100644 --- a/src/devices/nm-device-ethernet.c +++ b/src/devices/nm-device-ethernet.c @@ -29,7 +29,7 @@ #include #include -#include +#include #include "nm-device-private.h" #include "nm-act-request.h" @@ -155,8 +155,8 @@ static void _update_s390_subchannels (NMDeviceEthernet *self) { NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - gs_unref_object GUdevDevice *dev = NULL; - gs_unref_object GUdevDevice *parent = NULL; + struct udev_device *dev = NULL; + struct udev_device *parent = NULL; const char *parent_path, *item; int ifindex; GDir *dir; @@ -172,21 +172,20 @@ _update_s390_subchannels (NMDeviceEthernet *self) } ifindex = nm_device_get_ifindex ((NMDevice *) self); - dev = (GUdevDevice *) nm_g_object_ref (nm_platform_link_get_udev_device (NM_PLATFORM_GET, ifindex)); + dev = nm_platform_link_get_udev_device (NM_PLATFORM_GET, ifindex); if (!dev) return; /* Try for the "ccwgroup" parent */ - parent = g_udev_device_get_parent_with_subsystem (dev, "ccwgroup", NULL); + parent = udev_device_get_parent_with_subsystem_devtype (dev, "ccwgroup", NULL); if (!parent) { /* FIXME: whatever 'lcs' devices' subsystem is here... */ - if (!parent) { - /* Not an s390 device */ - return; - } + + /* Not an s390 device */ + return; } - parent_path = g_udev_device_get_sysfs_path (parent); + parent_path = udev_device_get_syspath (parent); dir = g_dir_open (parent_path, 0, &error); if (!dir) { _LOGW (LOGD_DEVICE | LOGD_PLATFORM, "update-s390: failed to open directory '%s': %s", diff --git a/src/nm-rfkill-manager.c b/src/nm-rfkill-manager.c index 09a32965cc..e655e67cc3 100644 --- a/src/nm-rfkill-manager.c +++ b/src/nm-rfkill-manager.c @@ -23,7 +23,9 @@ #include "nm-rfkill-manager.h" #include -#include +#include + +#include "nm-utils/nm-udev-utils.h" /*****************************************************************************/ @@ -35,7 +37,7 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; typedef struct { - GUdevClient *client; + NMUdevClient *udev_client; /* Authoritative rfkill state (RFKILL_* enum) */ RfKillState rfkill_states[RFKILL_TYPE_MAX]; @@ -101,32 +103,32 @@ rfkill_state_to_desc (RfKillState rstate) } static Killswitch * -killswitch_new (GUdevDevice *device, RfKillType rtype) +killswitch_new (struct udev_device *device, RfKillType rtype) { Killswitch *ks; - GUdevDevice *parent = NULL, *grandparent = NULL; + struct udev_device *parent = NULL, *grandparent = NULL; const char *driver, *subsys, *parent_subsys = NULL; ks = g_malloc0 (sizeof (Killswitch)); - ks->name = g_strdup (g_udev_device_get_name (device)); - ks->seqnum = g_udev_device_get_seqnum (device); - ks->path = g_strdup (g_udev_device_get_sysfs_path (device)); + ks->name = g_strdup (udev_device_get_sysname (device)); + ks->seqnum = udev_device_get_seqnum (device); + ks->path = g_strdup (udev_device_get_syspath (device)); ks->rtype = rtype; - driver = g_udev_device_get_property (device, "DRIVER"); - subsys = g_udev_device_get_subsystem (device); + driver = udev_device_get_property_value (device, "DRIVER"); + subsys = udev_device_get_subsystem (device); /* Check parent for various attributes */ - parent = g_udev_device_get_parent (device); + parent = udev_device_get_parent (device); if (parent) { - parent_subsys = g_udev_device_get_subsystem (parent); + parent_subsys = udev_device_get_subsystem (parent); if (!driver) - driver = g_udev_device_get_property (parent, "DRIVER"); + driver = udev_device_get_property_value (parent, "DRIVER"); if (!driver) { /* Sigh; try the grandparent */ - grandparent = g_udev_device_get_parent (parent); + grandparent = udev_device_get_parent (parent); if (grandparent) - driver = g_udev_device_get_property (grandparent, "DRIVER"); + driver = udev_device_get_property_value (grandparent, "DRIVER"); } } @@ -140,10 +142,6 @@ killswitch_new (GUdevDevice *device, RfKillType rtype) || g_strcmp0 (parent_subsys, "acpi") == 0) ks->platform = TRUE; - if (grandparent) - g_object_unref (grandparent); - if (parent) - g_object_unref (parent); return ks; } @@ -196,32 +194,34 @@ recheck_killswitches (NMRfkillManager *self) /* Poll the states of all killswitches */ for (iter = priv->killswitches; iter; iter = g_slist_next (iter)) { Killswitch *ks = iter->data; - GUdevDevice *device; + struct udev_device *device; RfKillState dev_state; int sysfs_state; - device = g_udev_client_query_by_subsystem_and_name (priv->client, "rfkill", ks->name); - if (device) { - sysfs_state = g_udev_device_get_property_as_int (device, "RFKILL_STATE"); - dev_state = sysfs_state_to_nm_state (sysfs_state); + device = udev_device_new_from_subsystem_sysname (nm_udev_client_get_udev (priv->udev_client), + "rfkill", ks->name); + if (!device) + continue; + sysfs_state = _nm_utils_ascii_str_to_int64 (udev_device_get_property_value (device, "RFKILL_STATE"), + 10, G_MININT, G_MAXINT, -1); + dev_state = sysfs_state_to_nm_state (sysfs_state); - nm_log_dbg (LOGD_RFKILL, "%s rfkill%s switch %s state now %d/%u", - rfkill_type_to_desc (ks->rtype), - ks->platform ? " platform" : "", - ks->name, - sysfs_state, - dev_state); + nm_log_dbg (LOGD_RFKILL, "%s rfkill%s switch %s state now %d/%u", + rfkill_type_to_desc (ks->rtype), + ks->platform ? " platform" : "", + ks->name, + sysfs_state, + dev_state); - if (ks->platform == FALSE) { - if (dev_state > poll_states[ks->rtype]) - poll_states[ks->rtype] = dev_state; - } else { - platform_checked[ks->rtype] = TRUE; - if (dev_state > platform_states[ks->rtype]) - platform_states[ks->rtype] = dev_state; - } - g_object_unref (device); + if (ks->platform == FALSE) { + if (dev_state > poll_states[ks->rtype]) + poll_states[ks->rtype] = dev_state; + } else { + platform_checked[ks->rtype] = TRUE; + if (dev_state > platform_states[ks->rtype]) + platform_states[ks->rtype] = dev_state; } + udev_device_unref (device); } /* Log and emit change signal for final rfkill states */ @@ -276,14 +276,14 @@ rfkill_type_to_enum (const char *str) } static void -add_one_killswitch (NMRfkillManager *self, GUdevDevice *device) +add_one_killswitch (NMRfkillManager *self, struct udev_device *device) { NMRfkillManagerPrivate *priv = NM_RFKILL_MANAGER_GET_PRIVATE (self); const char *str_type; RfKillType rtype; Killswitch *ks; - str_type = g_udev_device_get_property (device, "RFKILL_TYPE"); + str_type = udev_device_get_property_value (device, "RFKILL_TYPE"); rtype = rfkill_type_to_enum (str_type); if (rtype == RFKILL_TYPE_UNKNOWN) return; @@ -300,12 +300,12 @@ add_one_killswitch (NMRfkillManager *self, GUdevDevice *device) } static void -rfkill_add (NMRfkillManager *self, GUdevDevice *device) +rfkill_add (NMRfkillManager *self, struct udev_device *device) { const char *name; g_return_if_fail (device != NULL); - name = g_udev_device_get_name (device); + name = udev_device_get_sysname (device); g_return_if_fail (name != NULL); if (!killswitch_find_by_name (self, name)) @@ -314,14 +314,14 @@ rfkill_add (NMRfkillManager *self, GUdevDevice *device) static void rfkill_remove (NMRfkillManager *self, - GUdevDevice *device) + struct udev_device *device) { NMRfkillManagerPrivate *priv = NM_RFKILL_MANAGER_GET_PRIVATE (self); GSList *iter; const char *name; g_return_if_fail (device != NULL); - name = g_udev_device_get_name (device); + name = udev_device_get_sysname (device); g_return_if_fail (name != NULL); for (iter = priv->killswitches; iter; iter = g_slist_next (iter)) { @@ -337,22 +337,24 @@ rfkill_remove (NMRfkillManager *self, } static void -handle_uevent (GUdevClient *client, - const char *action, - GUdevDevice *device, +handle_uevent (NMUdevClient *client, + struct udev_device *device, gpointer user_data) { NMRfkillManager *self = NM_RFKILL_MANAGER (user_data); const char *subsys; + const char *action; + + action = udev_device_get_action (device); g_return_if_fail (action != NULL); /* A bit paranoid */ - subsys = g_udev_device_get_subsystem (device); + subsys = udev_device_get_subsystem (device); g_return_if_fail (!g_strcmp0 (subsys, "rfkill")); nm_log_dbg (LOGD_PLATFORM, "udev rfkill event: action '%s' device '%s'", - action, g_udev_device_get_name (device)); + action, udev_device_get_sysname (device)); if (!strcmp (action, "add")) rfkill_add (self, device); @@ -368,22 +370,31 @@ static void nm_rfkill_manager_init (NMRfkillManager *self) { NMRfkillManagerPrivate *priv = NM_RFKILL_MANAGER_GET_PRIVATE (self); - const char *subsys[] = { "rfkill", NULL }; - GList *switches, *iter; - guint32 i; + struct udev_enumerate *enumerate; + struct udev_list_entry *iter; + guint i; for (i = 0; i < RFKILL_TYPE_MAX; i++) priv->rfkill_states[i] = RFKILL_UNBLOCKED; - priv->client = g_udev_client_new (subsys); - g_signal_connect (priv->client, "uevent", G_CALLBACK (handle_uevent), self); + priv->udev_client = nm_udev_client_new ((const char *[]) { "rfkill", NULL }, + handle_uevent, self); - switches = g_udev_client_query_by_subsystem (priv->client, "rfkill"); - for (iter = switches; iter; iter = g_list_next (iter)) { - add_one_killswitch (self, G_UDEV_DEVICE (iter->data)); - g_object_unref (G_UDEV_DEVICE (iter->data)); + enumerate = nm_udev_client_enumerate_new (priv->udev_client); + udev_enumerate_scan_devices (enumerate); + iter = udev_enumerate_get_list_entry (enumerate); + for (; iter; iter = udev_list_entry_get_next (iter)) { + struct udev_device *udevice; + + udevice = udev_device_new_from_syspath (udev_enumerate_get_udev (enumerate), + udev_list_entry_get_name (iter)); + if (!udevice) + continue; + + add_one_killswitch (self, udevice); + udev_device_unref (udevice); } - g_list_free (switches); + udev_enumerate_unref (enumerate); recheck_killswitches (self); } @@ -400,13 +411,13 @@ dispose (GObject *object) NMRfkillManager *self = NM_RFKILL_MANAGER (object); NMRfkillManagerPrivate *priv = NM_RFKILL_MANAGER_GET_PRIVATE (self); - g_clear_object (&priv->client); - if (priv->killswitches) { g_slist_free_full (priv->killswitches, (GDestroyNotify) killswitch_destroy); priv->killswitches = NULL; } + priv->udev_client = nm_udev_client_unref (priv->udev_client); + G_OBJECT_CLASS (nm_rfkill_manager_parent_class)->dispose (object); } diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 6b91cf4c80..fdbcac3bfe 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include "nm-utils.h" #include "nm-core-internal.h" @@ -51,6 +51,7 @@ #include "wifi/wifi-utils.h" #include "wifi/wifi-utils-wext.h" #include "nm-utils/unaligned.h" +#include "nm-utils/nm-udev-utils.h" #define VLAN_FLAG_MVRP 0x8 @@ -2547,7 +2548,7 @@ typedef struct { gboolean sysctl_get_warned; GHashTable *sysctl_get_prev_values; - GUdevClient *udev_client; + NMUdevClient *udev_client; struct { /* which delayed actions are scheduled, as marked in @flags. @@ -4399,18 +4400,20 @@ link_get_unmanaged (NMPlatform *platform, int ifindex, gboolean *unmanaged) { NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); const NMPObject *link; - GUdevDevice *udev_device = NULL; + struct udev_device *udevice = NULL; + const char *uproperty; link = nmp_cache_lookup_link (priv->cache, ifindex); - if (link) - udev_device = link->_link.udev.device; + if (!link) + return FALSE; - if (udev_device && g_udev_device_get_property (udev_device, "NM_UNMANAGED")) { - *unmanaged = g_udev_device_get_property_as_boolean (udev_device, "NM_UNMANAGED"); - return TRUE; - } + udevice = link->_link.udev.device; + if (!udevice) + return FALSE; - return FALSE; + uproperty = udev_device_get_property_value (udevice, "NM_UNMANAGED"); + + return nm_udev_utils_property_as_boolean (uproperty); } static gboolean @@ -4510,10 +4513,10 @@ link_get_udi (NMPlatform *platform, int ifindex) || !obj->_link.netlink.is_in_netlink || !obj->_link.udev.device) return NULL; - return g_udev_device_get_sysfs_path (obj->_link.udev.device); + return udev_device_get_syspath (obj->_link.udev.device); } -static GObject * +static struct udev_device * link_get_udev_device (NMPlatform *platform, int ifindex) { const NMPObject *obj_cache; @@ -4524,7 +4527,7 @@ link_get_udev_device (NMPlatform *platform, int ifindex) * appears invisible via other platform functions. */ obj_cache = nmp_cache_lookup_link (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, ifindex); - return obj_cache ? (GObject *) obj_cache->_link.udev.device : NULL; + return obj_cache ? obj_cache->_link.udev.device : NULL; } static NMPlatformError @@ -6503,14 +6506,16 @@ after_read: /*****************************************************************************/ static void -cache_update_link_udev (NMPlatform *platform, int ifindex, GUdevDevice *udev_device) +cache_update_link_udev (NMPlatform *platform, + int ifindex, + struct udev_device *udevice) { NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); nm_auto_nmpobj NMPObject *obj_cache = NULL; gboolean was_visible; NMPCacheOpsType cache_op; - cache_op = nmp_cache_update_link_udev (priv->cache, ifindex, udev_device, &obj_cache, &was_visible, cache_pre_hook, platform); + cache_op = nmp_cache_update_link_udev (priv->cache, ifindex, udevice, &obj_cache, &was_visible, cache_pre_hook, platform); if (cache_op != NMP_CACHE_OPS_UNCHANGED) { nm_auto_pop_netns NMPNetns *netns = NULL; @@ -6523,55 +6528,58 @@ cache_update_link_udev (NMPlatform *platform, int ifindex, GUdevDevice *udev_dev static void udev_device_added (NMPlatform *platform, - GUdevDevice *udev_device) + struct udev_device *udevice) { const char *ifname; + const char *ifindex_s; int ifindex; - ifname = g_udev_device_get_name (udev_device); + ifname = udev_device_get_sysname (udevice); if (!ifname) { _LOGD ("udev-add: failed to get device's interface"); return; } - if (!g_udev_device_get_property (udev_device, "IFINDEX")) { + ifindex_s = udev_device_get_property_value (udevice, "IFINDEX"); + if (!ifindex_s) { _LOGW ("udev-add[%s]failed to get device's ifindex", ifname); return; } - ifindex = g_udev_device_get_property_as_int (udev_device, "IFINDEX"); + ifindex = _nm_utils_ascii_str_to_int64 (ifindex_s, 10, 1, G_MAXINT, 0); if (ifindex <= 0) { _LOGW ("udev-add[%s]: retrieved invalid IFINDEX=%d", ifname, ifindex); return; } - if (!g_udev_device_get_sysfs_path (udev_device)) { + if (!udev_device_get_syspath (udevice)) { _LOGD ("udev-add[%s,%d]: couldn't determine device path; ignoring...", ifname, ifindex); return; } _LOGT ("udev-add[%s,%d]: device added", ifname, ifindex); - cache_update_link_udev (platform, ifindex, udev_device); + cache_update_link_udev (platform, ifindex, udevice); } static gboolean -_udev_device_removed_match_link (const NMPObject *obj, gpointer udev_device) +_udev_device_removed_match_link (const NMPObject *obj, gpointer udevice) { - return obj->_link.udev.device == udev_device; + return obj->_link.udev.device == udevice; } static void udev_device_removed (NMPlatform *platform, - GUdevDevice *udev_device) + struct udev_device *udevice) { + const char *ifindex_s; int ifindex = 0; - if (g_udev_device_get_property (udev_device, "IFINDEX")) - ifindex = g_udev_device_get_property_as_int (udev_device, "IFINDEX"); - else { + ifindex_s = udev_device_get_property_value (udevice, "IFINDEX"); + ifindex = _nm_utils_ascii_str_to_int64 (ifindex_s, 10, 1, G_MAXINT, 0); + if (ifindex <= 0) { const NMPObject *obj; obj = nmp_cache_lookup_link_full (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, - 0, NULL, FALSE, NM_LINK_TYPE_NONE, _udev_device_removed_match_link, udev_device); + 0, NULL, FALSE, NM_LINK_TYPE_NONE, _udev_device_removed_match_link, udevice); if (obj) ifindex = obj->link.ifindex; } @@ -6584,9 +6592,8 @@ udev_device_removed (NMPlatform *platform, } static void -handle_udev_event (GUdevClient *client, - const char *action, - GUdevDevice *udev_device, +handle_udev_event (NMUdevClient *udev_client, + struct udev_device *udevice, gpointer user_data) { nm_auto_pop_netns NMPNetns *netns = NULL; @@ -6594,26 +6601,27 @@ handle_udev_event (GUdevClient *client, const char *subsys; const char *ifindex; guint64 seqnum; + const char *action; - g_return_if_fail (action != NULL); + action = udev_device_get_action (udevice); + g_return_if_fail (action); + + subsys = udev_device_get_subsystem (udevice); + g_return_if_fail (nm_streq0 (subsys, "net")); if (!nm_platform_netns_push (platform, &netns)) return; - /* A bit paranoid */ - subsys = g_udev_device_get_subsystem (udev_device); - g_return_if_fail (!g_strcmp0 (subsys, "net")); - - ifindex = g_udev_device_get_property (udev_device, "IFINDEX"); - seqnum = g_udev_device_get_seqnum (udev_device); + ifindex = udev_device_get_property_value (udevice, "IFINDEX"); + seqnum = udev_device_get_seqnum (udevice); _LOGD ("UDEV event: action '%s' subsys '%s' device '%s' (%s); seqnum=%" G_GUINT64_FORMAT, - action, subsys, g_udev_device_get_name (udev_device), + action, subsys, udev_device_get_sysname (udevice), ifindex ? ifindex : "unknown", seqnum); - if (!strcmp (action, "add") || !strcmp (action, "move")) - udev_device_added (platform, udev_device); - if (!strcmp (action, "remove")) - udev_device_removed (platform, udev_device); + if (NM_IN_STRSET (action, "add", "move")) + udev_device_added (platform, udevice); + else if (NM_IN_STRSET (action, "remove")) + udev_device_removed (platform, udevice); } /*****************************************************************************/ @@ -6634,8 +6642,10 @@ nm_linux_platform_init (NMLinuxPlatform *self) priv->delayed_action.list_wait_for_nl_response = g_array_new (FALSE, TRUE, sizeof (DelayedActionWaitForNlResponseData)); priv->wifi_data = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) wifi_utils_deinit); - if (use_udev) - priv->udev_client = g_udev_client_new ((const char *[]) { "net", NULL }); + if (use_udev) { + priv->udev_client = nm_udev_client_new ((const char *[]) { "net", NULL }, + handle_udev_event, self); + } } static void @@ -6718,24 +6728,30 @@ constructed (GObject *_object) /* Set up udev monitoring */ if (priv->udev_client) { - GUdevEnumerator *enumerator; - GList *devices, *iter; - - g_signal_connect (priv->udev_client, "uevent", G_CALLBACK (handle_udev_event), platform); + struct udev_enumerate *enumerator; + struct udev_list_entry *devices, *l; /* And read initial device list */ - enumerator = g_udev_enumerator_new (priv->udev_client); - g_udev_enumerator_add_match_subsystem (enumerator, "net"); + enumerator = nm_udev_client_enumerate_new (priv->udev_client); - g_udev_enumerator_add_match_is_initialized (enumerator); + udev_enumerate_add_match_is_initialized (enumerator); - devices = g_udev_enumerator_execute (enumerator); - for (iter = devices; iter; iter = g_list_next (iter)) { - udev_device_added (platform, G_UDEV_DEVICE (iter->data)); - g_object_unref (G_UDEV_DEVICE (iter->data)); + udev_enumerate_scan_devices (enumerator); + + devices = udev_enumerate_get_list_entry (enumerator); + for (l = devices; l; l = udev_list_entry_get_next (l)) { + struct udev_device *udevice; + + udevice = udev_device_new_from_syspath (udev_enumerate_get_udev (enumerator), + udev_list_entry_get_name (l)); + if (!udevice) + continue; + + udev_device_added (platform, udevice); + udev_device_unref (udevice); } - g_list_free (devices); - g_object_unref (enumerator); + + udev_enumerate_unref (enumerator); } } @@ -6755,11 +6771,6 @@ dispose (GObject *object) g_clear_pointer (&priv->prune_candidates, g_hash_table_unref); - if (priv->udev_client) { - g_signal_handlers_disconnect_by_func (priv->udev_client, G_CALLBACK (handle_udev_event), platform); - g_clear_object (&priv->udev_client); - } - G_OBJECT_CLASS (nm_linux_platform_parent_class)->dispose (object); } @@ -6785,6 +6796,8 @@ finalize (GObject *object) g_hash_table_destroy (priv->sysctl_get_prev_values); } + priv->udev_client = nm_udev_client_unref (priv->udev_client); + G_OBJECT_CLASS (nm_linux_platform_parent_class)->finalize (object); } diff --git a/src/platform/nm-platform-utils.c b/src/platform/nm-platform-utils.c index 80aa4445db..b664e8a9f1 100644 --- a/src/platform/nm-platform-utils.c +++ b/src/platform/nm-platform-utils.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "nm-utils.h" #include "nm-setting-wired.h" @@ -520,35 +521,33 @@ nmp_utils_mii_supports_carrier_detect (int ifindex) ******************************************************************/ const char * -nmp_utils_udev_get_driver (GUdevDevice *device) +nmp_utils_udev_get_driver (struct udev_device *udevice) { - GUdevDevice *parent = NULL, *grandparent = NULL; + struct udev_device *parent = NULL, *grandparent = NULL; const char *driver, *subsys; - driver = g_udev_device_get_driver (device); + driver = udev_device_get_driver (udevice); if (driver) goto out; /* Try the parent */ - parent = g_udev_device_get_parent (device); + parent = udev_device_get_parent (udevice); if (parent) { - driver = g_udev_device_get_driver (parent); + driver = udev_device_get_driver (parent); if (!driver) { /* Try the grandparent if it's an ibmebus device or if the * subsys is NULL which usually indicates some sort of * platform device like a 'gadget' net interface. */ - subsys = g_udev_device_get_subsystem (parent); + subsys = udev_device_get_subsystem (parent); if ( (g_strcmp0 (subsys, "ibmebus") == 0) || (subsys == NULL)) { - grandparent = g_udev_device_get_parent (parent); + grandparent = udev_device_get_parent (parent); if (grandparent) - driver = g_udev_device_get_driver (grandparent); + driver = udev_device_get_driver (grandparent); } } } - g_clear_object (&parent); - g_clear_object (&grandparent); out: /* Intern the string so we don't have to worry about memory diff --git a/src/platform/nm-platform-utils.h b/src/platform/nm-platform-utils.h index 699e80c698..ea25470e01 100644 --- a/src/platform/nm-platform-utils.h +++ b/src/platform/nm-platform-utils.h @@ -21,8 +21,6 @@ #ifndef __NM_PLATFORM_UTILS_H__ #define __NM_PLATFORM_UTILS_H__ -#include - #include "nm-platform.h" #include "nm-setting-wired.h" @@ -66,7 +64,9 @@ gboolean nmp_utils_ethtool_get_permanent_address (int ifindex, gboolean nmp_utils_mii_supports_carrier_detect (int ifindex); -const char *nmp_utils_udev_get_driver (GUdevDevice *device); +struct udev_device; + +const char *nmp_utils_udev_get_driver (struct udev_device *udevice); NMIPConfigSource nmp_utils_ip_config_source_from_rtprot (guint8 rtprot) _nm_const; guint8 nmp_utils_ip_config_source_coerce_to_rtprot (NMIPConfigSource source) _nm_const; diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index e711f642d6..38b8e0ec21 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -1000,7 +1000,7 @@ nm_platform_link_get_udi (NMPlatform *self, int ifindex) return NULL; } -GObject * +struct udev_device * nm_platform_link_get_udev_device (NMPlatform *self, int ifindex) { _CHECK_SELF (self, klass, FALSE); diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index a9d192f0dd..5eb46b42f2 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -49,6 +49,8 @@ /*****************************************************************************/ +struct udev_device; + /* workaround for older libnl version, that does not define these flags. */ #ifndef IFA_F_MANAGETEMPADDR #define IFA_F_MANAGETEMPADDR 0x100 @@ -562,7 +564,7 @@ typedef struct { gboolean (*link_set_noarp) (NMPlatform *, int ifindex); const char *(*link_get_udi) (NMPlatform *self, int ifindex); - GObject *(*link_get_udev_device) (NMPlatform *self, int ifindex); + struct udev_device *(*link_get_udev_device) (NMPlatform *self, int ifindex); NMPlatformError (*link_set_user_ipv6ll_enabled) (NMPlatform *, int ifindex, gboolean enabled); gboolean (*link_set_token) (NMPlatform *, int ifindex, NMUtilsIPv6IfaceId iid); @@ -814,7 +816,7 @@ gboolean nm_platform_link_set_noarp (NMPlatform *self, int ifindex); const char *nm_platform_link_get_udi (NMPlatform *self, int ifindex); -GObject *nm_platform_link_get_udev_device (NMPlatform *self, int ifindex); +struct udev_device *nm_platform_link_get_udev_device (NMPlatform *self, int ifindex); NMPlatformError nm_platform_link_set_user_ipv6ll_enabled (NMPlatform *self, int ifindex, gboolean enabled); gboolean nm_platform_link_set_ipv6_token (NMPlatform *self, int ifindex, NMUtilsIPv6IfaceId iid); diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c index a38a2eea87..2a7d3edd9e 100644 --- a/src/platform/nmp-object.c +++ b/src/platform/nmp-object.c @@ -24,6 +24,7 @@ #include #include +#include #include "nm-utils.h" @@ -125,14 +126,14 @@ _vlan_xgress_qos_mappings_cpy (guint *dst_n_map, /*****************************************************************************/ static const char * -_link_get_driver (GUdevDevice *udev_device, const char *kind, int ifindex) +_link_get_driver (struct udev_device *udevice, const char *kind, int ifindex) { const char *driver = NULL; nm_assert (kind == g_intern_string (kind)); - if (udev_device) { - driver = nmp_utils_udev_get_driver (udev_device); + if (udevice) { + driver = nmp_utils_udev_get_driver (udevice); if (driver) return driver; } @@ -242,7 +243,10 @@ nmp_object_unref (NMPObject *obj) static void _vt_cmd_obj_dispose_link (NMPObject *obj) { - g_clear_object (&obj->_link.udev.device); + if (obj->_link.udev.device) { + udev_device_unref (obj->_link.udev.device); + obj->_link.udev.device = NULL; + } nmp_object_unref (obj->_link.netlink.lnk); } @@ -619,8 +623,7 @@ _vt_cmd_obj_cmp_link (const NMPObject *obj1, const NMPObject *obj2) return 1; /* Only compare based on pointer values. That is ugly because it's not a - * stable sort order, but probably udev gives us always the same GUdevDevice - * instance. + * stable sort order. * * Have this check as very last. */ return (obj1->_link.udev.device < obj2->_link.udev.device) ? -1 : 1; @@ -687,15 +690,17 @@ _vt_cmd_obj_copy_link (NMPObject *dst, const NMPObject *src) { if (dst->_link.udev.device != src->_link.udev.device) { if (src->_link.udev.device) - g_object_ref (src->_link.udev.device); + udev_device_ref (src->_link.udev.device); if (dst->_link.udev.device) - g_object_unref (dst->_link.udev.device); + udev_device_unref (dst->_link.udev.device); + dst->_link.udev.device = src->_link.udev.device; } if (dst->_link.netlink.lnk != src->_link.netlink.lnk) { if (src->_link.netlink.lnk) nmp_object_ref (src->_link.netlink.lnk); if (dst->_link.netlink.lnk) nmp_object_unref (dst->_link.netlink.lnk); + dst->_link.netlink.lnk = src->_link.netlink.lnk; } dst->_link = src->_link; } @@ -1870,8 +1875,8 @@ nmp_cache_update_netlink (NMPCache *cache, NMPObject *obj, NMPObject **out_obj, _nmp_object_fixup_link_master_connected (obj, cache); /* Merge the netlink parts with what we have from udev. */ - g_clear_object (&obj->_link.udev.device); - obj->_link.udev.device = old->_link.udev.device ? g_object_ref (old->_link.udev.device) : NULL; + udev_device_unref (obj->_link.udev.device); + obj->_link.udev.device = old->_link.udev.device ? udev_device_ref (old->_link.udev.device) : NULL; _nmp_object_fixup_link_udev_fields (obj, cache->use_udev); } } else @@ -1896,7 +1901,7 @@ nmp_cache_update_netlink (NMPCache *cache, NMPObject *obj, NMPObject **out_obj, } NMPCacheOpsType -nmp_cache_update_link_udev (NMPCache *cache, int ifindex, GUdevDevice *udev_device, NMPObject **out_obj, gboolean *out_was_visible, NMPCachePreHook pre_hook, gpointer user_data) +nmp_cache_update_link_udev (NMPCache *cache, int ifindex, struct udev_device *udevice, NMPObject **out_obj, gboolean *out_was_visible, NMPCachePreHook pre_hook, gpointer user_data) { NMPObject *old; nm_auto_nmpobj NMPObject *obj = NULL; @@ -1909,12 +1914,12 @@ nmp_cache_update_link_udev (NMPCache *cache, int ifindex, GUdevDevice *udev_devi *out_was_visible = FALSE; if (!old) { - if (!udev_device) + if (!udevice) return NMP_CACHE_OPS_UNCHANGED; obj = nmp_object_new (NMP_OBJECT_TYPE_LINK, NULL); obj->link.ifindex = ifindex; - obj->_link.udev.device = g_object_ref (udev_device); + obj->_link.udev.device = udev_device_ref (udevice); _nmp_object_fixup_link_udev_fields (obj, cache->use_udev); @@ -1935,10 +1940,10 @@ nmp_cache_update_link_udev (NMPCache *cache, int ifindex, GUdevDevice *udev_devi if (out_was_visible) *out_was_visible = nmp_object_is_visible (old); - if (old->_link.udev.device == udev_device) + if (old->_link.udev.device == udevice) return NMP_CACHE_OPS_UNCHANGED; - if (!udev_device && !old->_link.netlink.is_in_netlink) { + if (!udevice && !old->_link.netlink.is_in_netlink) { /* the update would make @old invalid. Remove it. */ if (pre_hook) pre_hook (cache, old, NULL, NMP_CACHE_OPS_REMOVED, user_data); @@ -1948,8 +1953,8 @@ nmp_cache_update_link_udev (NMPCache *cache, int ifindex, GUdevDevice *udev_devi obj = nmp_object_clone (old, FALSE); - g_clear_object (&obj->_link.udev.device); - obj->_link.udev.device = udev_device ? g_object_ref (udev_device) : NULL; + udev_device_unref (obj->_link.udev.device); + obj->_link.udev.device = udevice ? udev_device_ref (udevice) : NULL; _nmp_object_fixup_link_udev_fields (obj, cache->use_udev); diff --git a/src/platform/nmp-object.h b/src/platform/nmp-object.h index 883fecf3a2..b69680f6bf 100644 --- a/src/platform/nmp-object.h +++ b/src/platform/nmp-object.h @@ -21,11 +21,11 @@ #ifndef __NMP_OBJECT_H__ #define __NMP_OBJECT_H__ -#include - #include "nm-platform.h" #include "nm-multi-index.h" +struct udev_device; + typedef enum { /*< skip >*/ NMP_OBJECT_TO_STRING_ID, NMP_OBJECT_TO_STRING_PUBLIC, @@ -186,7 +186,23 @@ typedef struct { } netlink; struct { - GUdevDevice *device; + /* note that "struct udev_device" references the library context + * "struct udev", but doesn't own it. + * + * Hence, the udev.device shall not be used after the library + * context is is destroyed. + * + * In case of NMPObjectLink instances that you obtained from the + * platform cache, that means that you shall no keep references + * to those instances that outlife the NMPlatform instance. + * + * In practice, the requirement is less strict and you'll be even + * fine if the platform instance (and the "struct udev" instance) + * are already destroyed while you still hold onto a reference to + * the NMPObjectLink instance. Just don't make use of udev functions + * that cause access to the udev library context. + */ + struct udev_device *device; } udev; } NMPObjectLink; @@ -442,7 +458,7 @@ void ASSERT_nmp_cache_is_consistent (const NMPCache *cache); NMPCacheOpsType nmp_cache_remove (NMPCache *cache, const NMPObject *obj, gboolean equals_by_ptr, NMPObject **out_obj, gboolean *out_was_visible, NMPCachePreHook pre_hook, gpointer user_data); NMPCacheOpsType nmp_cache_remove_netlink (NMPCache *cache, const NMPObject *obj, NMPObject **out_obj, gboolean *out_was_visible, NMPCachePreHook pre_hook, gpointer user_data); NMPCacheOpsType nmp_cache_update_netlink (NMPCache *cache, NMPObject *obj, NMPObject **out_obj, gboolean *out_was_visible, NMPCachePreHook pre_hook, gpointer user_data); -NMPCacheOpsType nmp_cache_update_link_udev (NMPCache *cache, int ifindex, GUdevDevice *udev_device, NMPObject **out_obj, gboolean *out_was_visible, NMPCachePreHook pre_hook, gpointer user_data); +NMPCacheOpsType nmp_cache_update_link_udev (NMPCache *cache, int ifindex, struct udev_device *udevice, NMPObject **out_obj, gboolean *out_was_visible, NMPCachePreHook pre_hook, gpointer user_data); NMPCacheOpsType nmp_cache_update_link_master_connected (NMPCache *cache, int ifindex, NMPObject **out_obj, gboolean *out_was_visible, NMPCachePreHook pre_hook, gpointer user_data); NMPCache *nmp_cache_new (gboolean use_udev); diff --git a/src/platform/tests/test-nmp-object.c b/src/platform/tests/test-nmp-object.c index f7b209dee2..42dfc572e6 100644 --- a/src/platform/tests/test-nmp-object.c +++ b/src/platform/tests/test-nmp-object.c @@ -20,7 +20,10 @@ #include "nm-default.h" +#include + #include "platform/nmp-object.h" +#include "nm-utils/nm-udev-utils.h" #include "nm-test-utils-core.h" @@ -159,7 +162,7 @@ _nmp_cache_update_netlink (NMPCache *cache, NMPObject *obj, NMPObject **out_obj, obj_old = nmp_cache_lookup_link (cache, obj->object.ifindex); if (obj_old && obj_old->_link.udev.device) - obj_clone->_link.udev.device = g_object_ref (obj_old->_link.udev.device); + obj_clone->_link.udev.device = udev_device_ref (obj_old->_link.udev.device); _nmp_object_fixup_link_udev_fields (obj_clone, nmp_cache_use_udev_get (cache)); g_assert (cache); @@ -219,8 +222,8 @@ test_cache_link (void) NMPObject objs1; gboolean was_visible; NMPCacheId cache_id_storage; - GUdevDevice *udev_device_2 = g_list_nth_data (global.udev_devices, 0); - GUdevDevice *udev_device_3 = g_list_nth_data (global.udev_devices, 0); + struct udev_device *udev_device_2 = g_list_nth_data (global.udev_devices, 0); + struct udev_device *udev_device_3 = g_list_nth_data (global.udev_devices, 0); NMPCacheOpsType ops_type; cache = nmp_cache_new (nmtst_get_rand_int () % 2); @@ -390,23 +393,40 @@ int main (int argc, char **argv) { int result; - gs_unref_object GUdevClient *udev_client = NULL; + NMUdevClient *udev_client; nmtst_init_assert_logging (&argc, &argv, "INFO", "DEFAULT"); - udev_client = g_udev_client_new ((const char *[]) { "net", NULL }); + udev_client = nm_udev_client_new ((const char *[]) { "net", NULL }, + NULL, NULL); { - gs_unref_object GUdevEnumerator *udev_enumerator = g_udev_enumerator_new (udev_client); + struct udev_enumerate *enumerator; + struct udev_list_entry *devices, *l; - g_udev_enumerator_add_match_subsystem (udev_enumerator, "net"); + enumerator = nm_udev_client_enumerate_new (udev_client); /* Demand that the device is initialized (udev rules ran, * device has a stable name now) in case udev is running * (not in a container). */ if (access ("/sys", W_OK) == 0) - g_udev_enumerator_add_match_is_initialized (udev_enumerator); + udev_enumerate_add_match_is_initialized (enumerator); - global.udev_devices = g_udev_enumerator_execute (udev_enumerator); + udev_enumerate_scan_devices (enumerator); + + devices = udev_enumerate_get_list_entry (enumerator); + for (l = devices; l != NULL; l = udev_list_entry_get_next (l)) { + struct udev_device *udevice; + + udevice = udev_device_new_from_syspath (udev_enumerate_get_udev (enumerator), + udev_list_entry_get_name (l)); + if (udevice == NULL) + continue; + + global.udev_devices = g_list_prepend (global.udev_devices, udevice); + } + global.udev_devices = g_list_reverse (global.udev_devices); + + udev_enumerate_unref (enumerator); } g_test_add_func ("/nmp-object/cache_link", test_cache_link); @@ -414,10 +434,12 @@ main (int argc, char **argv) result = g_test_run (); while (global.udev_devices) { - g_object_unref (global.udev_devices->data); + udev_device_unref (global.udev_devices->data); global.udev_devices = g_list_remove (global.udev_devices, global.udev_devices->data); } + nm_udev_client_unref (udev_client); + return result; } diff --git a/src/settings/plugins/ifupdown/nms-ifupdown-plugin.c b/src/settings/plugins/ifupdown/nms-ifupdown-plugin.c index 211e5d5736..189b6e69cb 100644 --- a/src/settings/plugins/ifupdown/nms-ifupdown-plugin.c +++ b/src/settings/plugins/ifupdown/nms-ifupdown-plugin.c @@ -28,8 +28,8 @@ #include #include -#include #include +#include #include "nm-setting-connection.h" #include "nm-dbus-interface.h" @@ -42,6 +42,7 @@ #include "nm-core-internal.h" #include "NetworkManagerUtils.h" #include "nm-config.h" +#include "nm-utils/nm-udev-utils.h" #include "nms-ifupdown-interface-parser.h" #include "nms-ifupdown-connection.h" @@ -62,7 +63,7 @@ /*****************************************************************************/ typedef struct { - GUdevClient *client; + NMUdevClient *udev_client; GHashTable *connections; /* /e/n/i block name :: NMIfupdownConnection */ @@ -103,21 +104,21 @@ NM_DEFINE_SINGLETON_GETTER (SettingsPluginIfupdown, settings_plugin_ifupdown_get static void bind_device_to_connection (SettingsPluginIfupdown *self, - GUdevDevice *device, + struct udev_device *device, NMIfupdownConnection *exported) { NMSettingWired *s_wired; NMSettingWireless *s_wifi; const char *iface, *address; - iface = g_udev_device_get_name (device); + iface = udev_device_get_sysname (device); if (!iface) { nm_log_warn (LOGD_SETTINGS, "failed to get ifname for device."); return; } - address = g_udev_device_get_sysfs_attr (device, "address"); - if (!address || !strlen (address)) { + address = udev_device_get_sysattr_value (device, "address"); + if (!address || !address[0]) { nm_log_warn (LOGD_SETTINGS, "failed to get MAC address for %s", iface); return; } @@ -142,14 +143,14 @@ bind_device_to_connection (SettingsPluginIfupdown *self, } static void -udev_device_added (SettingsPluginIfupdown *self, GUdevDevice *device) +udev_device_added (SettingsPluginIfupdown *self, struct udev_device *device) { SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE (self); const char *iface, *path; NMIfupdownConnection *exported; - iface = g_udev_device_get_name (device); - path = g_udev_device_get_sysfs_path (device); + iface = udev_device_get_sysname (device); + path = udev_device_get_syspath (device); if (!iface || !path) return; @@ -165,7 +166,7 @@ udev_device_added (SettingsPluginIfupdown *self, GUdevDevice *device) return; } - g_hash_table_insert (priv->kernel_ifaces, g_strdup (iface), g_object_ref (device)); + g_hash_table_insert (priv->kernel_ifaces, g_strdup (iface), udev_device_ref (device)); if (exported) bind_device_to_connection (self, device, exported); @@ -175,13 +176,13 @@ udev_device_added (SettingsPluginIfupdown *self, GUdevDevice *device) } static void -udev_device_removed (SettingsPluginIfupdown *self, GUdevDevice *device) +udev_device_removed (SettingsPluginIfupdown *self, struct udev_device *device) { SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE (self); const char *iface, *path; - iface = g_udev_device_get_name (device); - path = g_udev_device_get_sysfs_path (device); + iface = udev_device_get_sysname (device); + path = udev_device_get_syspath (device); if (!iface || !path) return; @@ -195,13 +196,13 @@ udev_device_removed (SettingsPluginIfupdown *self, GUdevDevice *device) } static void -udev_device_changed (SettingsPluginIfupdown *self, GUdevDevice *device) +udev_device_changed (SettingsPluginIfupdown *self, struct udev_device *device) { SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE (self); const char *iface, *path; - iface = g_udev_device_get_name (device); - path = g_udev_device_get_sysfs_path (device); + iface = udev_device_get_sysname (device); + path = udev_device_get_syspath (device); if (!iface || !path) return; @@ -215,20 +216,21 @@ udev_device_changed (SettingsPluginIfupdown *self, GUdevDevice *device) } static void -handle_uevent (GUdevClient *client, - const char *action, - GUdevDevice *device, +handle_uevent (NMUdevClient *client, + struct udev_device *device, gpointer user_data) { SettingsPluginIfupdown *self = SETTINGS_PLUGIN_IFUPDOWN (user_data); const char *subsys; + const char *action; + + action = udev_device_get_action (device); g_return_if_fail (action != NULL); /* A bit paranoid */ - subsys = g_udev_device_get_subsystem (device); - g_return_if_fail (subsys != NULL); - g_return_if_fail (strcmp (subsys, "net") == 0); + subsys = udev_device_get_subsystem (device); + g_return_if_fail (nm_streq0 (subsys, "net")); if (!strcmp (action, "add")) udev_device_added (self, device); @@ -271,7 +273,7 @@ get_unmanaged_specs (NMSettingsPlugin *config) SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE ((SettingsPluginIfupdown *) config); GSList *specs = NULL; GHashTableIter iter; - GUdevDevice *device; + struct udev_device *device; const char *iface; if (!ALWAYS_UNMANAGE && !priv->unmanage_well_known) @@ -284,7 +286,7 @@ get_unmanaged_specs (NMSettingsPlugin *config) while (g_hash_table_iter_next (&iter, (gpointer) &iface, (gpointer) &device)) { const char *address; - address = g_udev_device_get_sysfs_attr (device, "address"); + address = udev_device_get_sysattr_value (device, "address"); if (address) specs = g_slist_append (specs, g_strdup_printf ("mac:%s", address)); else @@ -317,6 +319,12 @@ get_property (GObject *object, guint prop_id, /*****************************************************************************/ +static void +_udev_device_unref (gpointer ptr) +{ + udev_device_unref (ptr); +} + static void init (NMSettingsPlugin *config) { @@ -324,11 +332,11 @@ init (NMSettingsPlugin *config) SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE (self); GHashTable *auto_ifaces; if_block *block = NULL; - GList *keys, *iter; + struct udev_enumerate *enumerate; + struct udev_list_entry *keys; GHashTableIter con_iter; const char *block_name; NMIfupdownConnection *connection; - const char *subsys[2] = { "net", NULL }; auto_ifaces = g_hash_table_new (g_str_hash, g_str_equal); @@ -336,18 +344,15 @@ init (NMSettingsPlugin *config) priv->connections = g_hash_table_new (g_str_hash, g_str_equal); if(!priv->kernel_ifaces) - priv->kernel_ifaces = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); + priv->kernel_ifaces = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, _udev_device_unref); if(!priv->eni_ifaces) priv->eni_ifaces = g_hash_table_new (g_str_hash, g_str_equal); nm_log_info (LOGD_SETTINGS, "init!"); - priv->client = g_udev_client_new (subsys); - if (!priv->client) { - nm_log_warn (LOGD_SETTINGS, " error initializing libgudev"); - } else - g_signal_connect (priv->client, "uevent", G_CALLBACK (handle_uevent), self); + priv->udev_client = nm_udev_client_new ((const char *[]) { "net", NULL }, + handle_uevent, self); /* Read in all the interfaces */ ifparser_init (ENI_INTERFACES_FILE, 0); @@ -445,12 +450,20 @@ init (NMSettingsPlugin *config) nm_log_info (LOGD_SETTINGS, "management mode: %s", priv->unmanage_well_known ? "unmanaged" : "managed"); /* Add well-known interfaces */ - keys = g_udev_client_query_by_subsystem (priv->client, "net"); - for (iter = keys; iter; iter = g_list_next (iter)) { - udev_device_added (self, G_UDEV_DEVICE (iter->data)); - g_object_unref (G_UDEV_DEVICE (iter->data)); + enumerate = nm_udev_client_enumerate_new (priv->udev_client); + udev_enumerate_scan_devices (enumerate); + keys = udev_enumerate_get_list_entry (enumerate); + for (; keys; keys = udev_list_entry_get_next (keys)) { + struct udev_device *udevice; + + udevice = udev_device_new_from_syspath (udev_enumerate_get_udev (enumerate), + udev_list_entry_get_name (keys)); + if (udevice) { + udev_device_added (self, udevice); + udev_device_unref (udevice); + } } - g_list_free (keys); + udev_enumerate_unref (enumerate); /* Now if we're running in managed mode, let NM know there are new connections */ if (!priv->unmanage_well_known) { @@ -483,7 +496,8 @@ dispose (GObject *object) g_clear_pointer (&priv->kernel_ifaces, g_hash_table_destroy); g_clear_pointer (&priv->eni_ifaces, g_hash_table_destroy); - g_clear_object (&priv->client); + + priv->udev_client = nm_udev_client_unref (priv->udev_client); G_OBJECT_CLASS (settings_plugin_ifupdown_parent_class)->dispose (object); }